diff options
-rw-r--r-- | roqav.c | 227 |
1 files changed, 104 insertions, 123 deletions
@@ -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", |