summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormelanson <melanson@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-15 05:08:07 +0000
committermelanson <melanson@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-15 05:08:07 +0000
commitfee8789cea9482dd0b97c55779abc52e1b045a8d (patch)
tree19b29a81f56f36c2145813001f23a94f7155b1a2
parenta240aa0c7ecc27beb7ddc32abe2caf514f080bf9 (diff)
downloadmpv-fee8789cea9482dd0b97c55779abc52e1b045a8d.tar.bz2
mpv-fee8789cea9482dd0b97c55779abc52e1b045a8d.tar.xz
RoQ video decoder is much closer to being categorized as "working" (there
are still a few lingering bugs, but picture is starting to look right) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5080 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--roqav.c227
1 files changed, 104 insertions, 123 deletions
diff --git a/roqav.c b/roqav.c
index 635bd920d2..59a00af39d 100644
--- a/roqav.c
+++ b/roqav.c
@@ -162,26 +162,24 @@ inline void copy_4x4_block(
unsigned int u_stride,
unsigned int v_stride)
{
- // copy over the luminance components
- *(unsigned int *)y_plane = *(unsigned int *)prev_y_plane;
- y_plane += y_stride;
- prev_y_plane += y_stride;
- *(unsigned int *)y_plane = *(unsigned int *)prev_y_plane;
- y_plane += y_stride;
- prev_y_plane += y_stride;
- *(unsigned int *)y_plane = *(unsigned int *)prev_y_plane;
- y_plane += y_stride;
- prev_y_plane += y_stride;
- *(unsigned int *)y_plane = *(unsigned int *)prev_y_plane;
+ int i;
- // copy the chrominance values
- *(unsigned short*)u_plane = *(unsigned short*)prev_u_plane;
- u_plane += u_stride;
- *(unsigned short*)u_plane = *(unsigned short*)prev_u_plane;
+ // copy over the luminance components (4 rows, 2 uints each)
+ for (i = 0; i < 4; i++)
+ {
+ *(unsigned int *)y_plane = *(unsigned int *)prev_y_plane;
+ y_plane += y_stride;
+ prev_y_plane += y_stride;
+ }
- *(unsigned short*)v_plane = *(unsigned short*)prev_v_plane;
- v_plane += v_stride;
- *(unsigned short*)v_plane = *(unsigned short*)prev_v_plane;
+ // copy the chrominance values
+ for (i = 0; i < 2; i++)
+ {
+ *(unsigned short*)u_plane = *(unsigned short*)prev_u_plane;
+ u_plane += u_stride;
+ *(unsigned short*)v_plane = *(unsigned short*)prev_v_plane;
+ v_plane += v_stride;
+ }
}
// This function copies the 8x8 block from the prev_*_planes to the
@@ -197,41 +195,25 @@ inline void copy_8x8_block(
unsigned int u_stride,
unsigned int v_stride)
{
- // copy over the luminance components
- ((unsigned int *)y_plane)[0] = ((unsigned int *)prev_y_plane)[0];
- ((unsigned int *)y_plane)[1] = ((unsigned int *)prev_y_plane)[1];
-
- y_plane += y_stride;
- prev_y_plane += y_stride;
- ((unsigned int *)y_plane)[0] = ((unsigned int *)prev_y_plane)[0];
- ((unsigned int *)y_plane)[1] = ((unsigned int *)prev_y_plane)[1];
-
- y_plane += y_stride;
- prev_y_plane += y_stride;
- ((unsigned int *)y_plane)[0] = ((unsigned int *)prev_y_plane)[0];
- ((unsigned int *)y_plane)[1] = ((unsigned int *)prev_y_plane)[1];
+ int i;
- y_plane += y_stride;
- prev_y_plane += y_stride;
- ((unsigned int *)y_plane)[0] = ((unsigned int *)prev_y_plane)[0];
- ((unsigned int *)y_plane)[1] = ((unsigned int *)prev_y_plane)[1];
+ // copy over the luminance components (8 rows, 2 uints each)
+ for (i = 0; i < 8; i++)
+ {
+ ((unsigned int *)y_plane)[0] = ((unsigned int *)prev_y_plane)[0];
+ ((unsigned int *)y_plane)[1] = ((unsigned int *)prev_y_plane)[1];
+ y_plane += y_stride;
+ prev_y_plane += y_stride;
+ }
// copy the chrominance values
- *(unsigned int*)u_plane = *(unsigned int*)prev_u_plane;
- u_plane += u_stride;
- *(unsigned int*)u_plane = *(unsigned int*)prev_u_plane;
- u_plane += u_stride;
- *(unsigned int*)u_plane = *(unsigned int*)prev_u_plane;
- u_plane += u_stride;
- *(unsigned int*)u_plane = *(unsigned int*)prev_u_plane;
-
- *(unsigned int*)v_plane = *(unsigned int*)prev_v_plane;
- v_plane += v_stride;
- *(unsigned int*)v_plane = *(unsigned int*)prev_v_plane;
- v_plane += v_stride;
- *(unsigned int*)v_plane = *(unsigned int*)prev_v_plane;
- v_plane += v_stride;
- *(unsigned int*)v_plane = *(unsigned int*)prev_v_plane;
+ for (i = 0; i < 4; i++)
+ {
+ *(unsigned int*)u_plane = *(unsigned int*)prev_u_plane;
+ u_plane += u_stride;
+ *(unsigned int*)v_plane = *(unsigned int*)prev_v_plane;
+ v_plane += v_stride;
+ }
}
// This function creates storage space for the vector codebooks.
@@ -245,29 +227,30 @@ void *roq_decode_video_init(void)
return info;
}
+#define EMPTY_ROQ_CODEWORD 0xFFFF0000
+
#define FETCH_NEXT_CODE() \
- if (current_roq_codeword == 0xFFFF0000) \
+ if (current_roq_codeword == EMPTY_ROQ_CODEWORD) \
{ \
if (stream_ptr + 2 > encoded_size) \
{ \
mp_msg(MSGT_DECVIDEO, MSGL_WARN, \
- "RoQ video: stream pointer just went out of bounds\n"); \
+ "RoQ video: stream pointer just went out of bounds (1)\n"); \
return; \
} \
current_roq_codeword = (0x0000FFFF) | \
- (encoded[stream_ptr++] << 16) | \
- (encoded[stream_ptr++] << 24); \
+ (encoded[stream_ptr + 0] << 16) | \
+ (encoded[stream_ptr + 1] << 24); \
+ stream_ptr += 2; \
} \
roq_code = ((current_roq_codeword >> 30) & 0x03); \
current_roq_codeword <<= 2;
-//printf (" %d\n", roq_code);
-
#define FETCH_NEXT_ARGUMENT() \
if (stream_ptr + 1 > encoded_size) \
{ \
mp_msg(MSGT_DECVIDEO, MSGL_WARN, \
- "RoQ video: stream pointer just went out of bounds\n"); \
+ "RoQ video: stream pointer just went out of bounds (2)\n"); \
return; \
} \
argument = encoded[stream_ptr++];
@@ -280,7 +263,6 @@ void *roq_decode_video_init(void)
return; \
}
-
void roq_decode_video(void *context, unsigned char *encoded,
int encoded_size, mp_image_t *mpi)
{
@@ -294,12 +276,11 @@ void roq_decode_video(void *context, unsigned char *encoded,
int v2_ia, v2_ib, v2_ic, v2_id;
int roq_code;
- unsigned int current_roq_codeword = 0xFFFF0000;
+ unsigned int current_roq_codeword = EMPTY_ROQ_CODEWORD;
unsigned char argument = 0;
int mean_motion_x;
int mean_motion_y;
- int dx_y, dy_y; // for calculating the motion vector
- int dx_c, dy_c; // motion vector for chrominance components
+ int mx, my; // for calculating the motion vector
int mblock_x = 0;
int mblock_y = 0;
@@ -320,9 +301,7 @@ void roq_decode_video(void *context, unsigned char *encoded,
roq_v4_codebook v4;
roq_v2_codebook v2;
-
-static int counter = 0;
-//printf ("frame %d\n", counter++);
+int debugger = 0;
// make sure the encoded chunk is of minimal acceptable length
@@ -343,16 +322,17 @@ static int counter = 0;
if (LE_16(&encoded[stream_ptr]) == RoQ_QUAD_CODEBOOK)
{
+if (debugger)
printf ("parsing codebook\n");
stream_ptr += 2;
chunk_length = LE_32(&encoded[stream_ptr]);
stream_ptr += 4;
v4_count = encoded[stream_ptr++];
- if (v4_count == 0)
- v4_count = 256;
v2_count = encoded[stream_ptr++];
if (v2_count == 0)
v2_count = 256;
+ if ((v4_count == 0) && (v2_count * 6 < chunk_length))
+ v4_count = 256;
// make sure the lengths agree with each other
if (((v2_count * 6) + (v4_count * 4)) != chunk_length)
@@ -375,8 +355,8 @@ printf ("parsing codebook\n");
info->v2[i].y1 = encoded[stream_ptr++];
info->v2[i].y2 = encoded[stream_ptr++];
info->v2[i].y3 = encoded[stream_ptr++];
- info->v2[i].v = encoded[stream_ptr++];
info->v2[i].u = encoded[stream_ptr++];
+ info->v2[i].v = encoded[stream_ptr++];
prep_v2(&info->v2[i]);
}
@@ -401,31 +381,30 @@ printf ("parsing codebook\n");
if (LE_16(&encoded[stream_ptr]) == RoQ_QUAD_VQ)
{
+if (debugger)
printf ("parsing quad vq\n");
stream_ptr += 2;
chunk_length = LE_32(&encoded[stream_ptr]);
stream_ptr += 4;
mean_motion_y = encoded[stream_ptr++];
mean_motion_x = encoded[stream_ptr++];
+if (debugger){
+for (i = 0; i < 16; i++)
+ printf (" %02X", encoded[stream_ptr + i]);
+printf("\n");}
// iterate through the 16x16 macroblocks
for (mblock_y = 0; mblock_y < mpi->height; mblock_y += 16)
{
for (mblock_x = 0; mblock_x < mpi->width; mblock_x += 16)
{
- quad8_x = mblock_x;
- quad8_y = mblock_y;
-
// iterate through the 4 quadrants of the macroblock
for (i = 0; i < 4; i++)
{
- if (quad8_x & 8)
- {
- quad8_x -= 8;
- quad8_y += 8;
- }
- else
- quad8_x += 8;
+ quad8_x = mblock_x;
+ quad8_y = mblock_y;
+ if (i & 0x01) quad8_x += 8;
+ if (i & 0x02) quad8_y += 8;
// set up the planes
y_plane = mpi->planes[0] + quad8_y * y_stride + quad8_x;
@@ -434,6 +413,8 @@ printf ("parsing quad vq\n");
// decide how to handle this 8x8 quad
FETCH_NEXT_CODE();
+if (debugger)
+printf (" (%d, %d), %d\n", quad8_x, quad8_y, roq_code);
switch(roq_code)
{
// 8x8 block is painted with the same block as the last frame
@@ -459,7 +440,6 @@ printf ("parsing quad vq\n");
u_stride,
v_stride
);
-
break;
// 8x8 block is painted with an 8x8 block from the last frame
@@ -471,17 +451,15 @@ printf ("parsing quad vq\n");
FETCH_NEXT_ARGUMENT(); // argument contains motion vectors
// figure out the motion vectors
- dx_y = quad8_x + 8 - (argument >> 4) - mean_motion_x;
- dy_y = quad8_y + 8 - (argument & 0x0F) - mean_motion_y;
- dx_c = (quad8_x + 8) / 2 - (argument >> 4) - mean_motion_x / 2;
- dy_c = (quad8_y + 8) / 2 - (argument & 0x0F) - mean_motion_y / 2;
+ mx = quad8_x + 8 - (argument >> 4) - mean_motion_x;
+ my = quad8_y + 8 - (argument & 0x0F) - mean_motion_y;
prev_y_plane = info->prev_frame->planes[0] +
- dy_y * y_stride + dx_y;
+ my * y_stride + mx;
prev_u_plane = info->prev_frame->planes[1] +
- dy_c * u_stride + dx_c;
+ (my / 2) * u_stride + (mx + 1) / 2;
prev_v_plane = info->prev_frame->planes[2] +
- dy_c * v_stride + dx_c;
+ (my / 2) * v_stride + (mx + 1) / 2;
// sanity check before rendering
copy_8x8_block(
@@ -495,66 +473,76 @@ printf ("parsing quad vq\n");
u_stride,
v_stride
);
-
break;
// 8x8 block is painted with a doublesized 4x4 vector
case 2:
FETCH_NEXT_ARGUMENT();
v4 = info->v4[argument];
+if (debugger)
+printf (" vector: %d, %08X %08X %08X %08X %08X %08X\n", argument,
+ v4.v4d_y_rows_12_l, v4.v4d_y_rows_12_r,
+ v4.v4d_y_rows_34_l, v4.v4d_y_rows_34_r,
+ v4.v4d_u_rows_12, v4.v4d_u_rows_34);
// sanity check before rendering
// take care of the 8 luminance rows
((unsigned int*)y_plane)[0] = v4.v4d_y_rows_12_l;
((unsigned int*)y_plane)[1] = v4.v4d_y_rows_12_r;
+ y_plane += y_stride;
+ ((unsigned int*)y_plane)[0] = v4.v4d_y_rows_12_l;
+ ((unsigned int*)y_plane)[1] = v4.v4d_y_rows_12_r;
y_plane += y_stride;
((unsigned int*)y_plane)[0] = v4.v4d_y_rows_34_l;
((unsigned int*)y_plane)[1] = v4.v4d_y_rows_34_r;
+ y_plane += y_stride;
+ ((unsigned int*)y_plane)[0] = v4.v4d_y_rows_34_l;
+ ((unsigned int*)y_plane)[1] = v4.v4d_y_rows_34_r;
y_plane += y_stride;
((unsigned int*)y_plane)[0] = v4.v4d_y_rows_56_l;
((unsigned int*)y_plane)[1] = v4.v4d_y_rows_56_r;
+ y_plane += y_stride;
+ ((unsigned int*)y_plane)[0] = v4.v4d_y_rows_56_l;
+ ((unsigned int*)y_plane)[1] = v4.v4d_y_rows_56_r;
y_plane += y_stride;
((unsigned int*)y_plane)[0] = v4.v4d_y_rows_78_l;
((unsigned int*)y_plane)[1] = v4.v4d_y_rows_78_r;
+ y_plane += y_stride;
+ ((unsigned int*)y_plane)[0] = v4.v4d_y_rows_78_l;
+ ((unsigned int*)y_plane)[1] = v4.v4d_y_rows_78_r;
// then the 4 U & V chrominance rows
*(unsigned int*)u_plane = v4.v4d_u_rows_12;
u_plane += u_stride;
*(unsigned int*)u_plane = v4.v4d_u_rows_12;
u_plane += u_stride;
- *(unsigned int*)u_plane = v4.v4d_u_rows_12;
+ *(unsigned int*)u_plane = v4.v4d_u_rows_34;
u_plane += u_stride;
- *(unsigned int*)u_plane = v4.v4d_u_rows_12;
+ *(unsigned int*)u_plane = v4.v4d_u_rows_34;
*(unsigned int*)v_plane = v4.v4d_v_rows_12;
v_plane += v_stride;
*(unsigned int*)v_plane = v4.v4d_v_rows_12;
v_plane += v_stride;
- *(unsigned int*)v_plane = v4.v4d_v_rows_12;
+ *(unsigned int*)v_plane = v4.v4d_v_rows_34;
v_plane += v_stride;
- *(unsigned int*)v_plane = v4.v4d_v_rows_12;
+ *(unsigned int*)v_plane = v4.v4d_v_rows_34;
break;
// 8x8 block is broken down into 4 4x4 blocks and painted using
// 4 different codes.
case 3:
- quad4_x = quad8_x;
- quad4_y = quad8_y;
-
// iterate through 4 4x4 blocks
for (j = 0; j < 4; j++)
{
- if (quad4_x & 4)
- {
- quad4_x -= 4;
- quad4_y += 4;
- }
- else
- quad4_x += 4;
+ quad4_x = quad8_x;
+ quad4_y = quad8_y;
+ if (j & 0x01) quad4_x += 4;
+ if (j & 0x02) quad4_y += 4;
// set up the planes
y_plane = mpi->planes[0] + quad4_y * y_stride + quad4_x;
@@ -565,6 +553,8 @@ printf ("parsing quad vq\n");
// decide how to handle this 4x4 quad
FETCH_NEXT_CODE();
+if (debugger)
+printf (" (%d, %d), %d\n", quad4_x, quad4_y, roq_code);
switch(roq_code)
{
// 4x4 block is the same as in the previous frame
@@ -591,7 +581,6 @@ printf ("parsing quad vq\n");
u_stride,
v_stride
);
-
break;
// 4x4 block is motion compensated from the previous frame
@@ -601,22 +590,18 @@ printf ("parsing quad vq\n");
FETCH_NEXT_ARGUMENT(); // argument contains motion vectors
// figure out the motion vectors
- dx_y = quad4_x + 4 - (argument >> 4) - mean_motion_x;
- dy_y = quad4_y + 4 - (argument & 0x0F) - mean_motion_y;
- dx_c = (quad4_x + 4) / 2 - (argument >> 4) -
- mean_motion_x / 2;
- dy_c = (quad4_y + 4) / 2 - (argument & 0x0F) -
- mean_motion_y / 2;
+ mx = quad4_x + 8 - (argument >> 4) - mean_motion_x;
+ my = quad4_y + 8 - (argument & 0x0F) - mean_motion_y;
prev_y_plane = info->prev_frame->planes[0] +
- dy_y * y_stride + dx_y;
+ my * y_stride + mx;
prev_u_plane = info->prev_frame->planes[1] +
- dy_c * u_stride + dx_c;
+ (my / 2) * u_stride + (mx + 1) / 2;
prev_v_plane = info->prev_frame->planes[2] +
- dy_c * v_stride + dx_c;
+ (my / 2) * u_stride + (mx + 1) / 2;
// sanity check before rendering
- copy_8x8_block(
+ copy_4x4_block(
y_plane,
u_plane,
v_plane,
@@ -627,7 +612,6 @@ printf ("parsing quad vq\n");
u_stride,
v_stride
);
-
break;
// 4x4 block is copied directly from v4 vector table
@@ -657,19 +641,13 @@ printf ("parsing quad vq\n");
// 4x4 block is built from 4 2x2 vectors
case 3:
- quad2_x = quad4_x;
- quad2_y = quad4_y;
-
// iterate through 4 2x2 blocks
for (k = 0; k < 4; k++)
{
- if (quad2_x & 2)
- {
- quad2_x -= 2;
- quad2_y += 2;
- }
- else
- quad2_x += 2;
+ quad2_x = quad4_x;
+ quad2_y = quad4_y;
+ if (k & 0x01) quad2_x += 2;
+ if (k & 0x02) quad2_y += 2;
// set up the planes
y_plane = mpi->planes[0] + quad2_y * y_stride + quad2_x;
@@ -680,6 +658,8 @@ printf ("parsing quad vq\n");
// fetch the next index into the v2 vector table
FETCH_NEXT_ARGUMENT();
+if (debugger)
+printf (" (%d, %d), %d\n", quad2_x, quad2_y, argument);
v2 = info->v2[argument];
// copy the luminance components
@@ -703,7 +683,8 @@ printf ("parsing quad vq\n");
}
// one last sanity check on the way out
- if (stream_ptr < encoded_size)
+ // (apparently, it's not unusual to have 2 bytes left over after decode)
+ if (stream_ptr < encoded_size - 2)
{
mp_msg(MSGT_DECVIDEO, MSGL_WARN,
"RoQ video: completed frame decode with bytes left over (%d < %d)\n",