mirror of
https://github.com/mpv-player/mpv
synced 2025-02-26 18:32:08 +00:00
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
This commit is contained in:
parent
a240aa0c7e
commit
fee8789cea
227
roqav.c
227
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 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
*(unsigned short*)v_plane = *(unsigned short*)prev_v_plane;
|
||||
v_plane += v_stride;
|
||||
*(unsigned short*)v_plane = *(unsigned short*)prev_v_plane;
|
||||
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];
|
||||
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];
|
||||
|
||||
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];
|
||||
// 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,27 +473,43 @@ 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;
|
||||
@ -525,36 +519,30 @@ printf ("parsing quad vq\n");
|
||||
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",
|
||||
|
Loading…
Reference in New Issue
Block a user