changeset 5079:6cba3ca983b5

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)
author melanson
date Fri, 15 Mar 2002 05:08:07 +0000
parents 18c5dc6db592
children f333b10ec34f
files roqav.c
diffstat 1 files changed, 104 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/roqav.c	Fri Mar 15 03:49:17 2002 +0000
+++ b/roqav.c	Fri Mar 15 05:08:07 2002 +0000
@@ -162,26 +162,24 @@
   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 @@
   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];
+  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];
+  // 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 @@
   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 @@
     return; \
   }
 
-
 void roq_decode_video(void *context, unsigned char *encoded,
   int encoded_size, mp_image_t *mpi)
 {
@@ -294,12 +276,11 @@
   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 @@
   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 @@
 
   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 @@
       info->v2[i].y1 = encoded[stream_ptr++];
       info->v2[i].y2 = encoded[stream_ptr++];
       info->v2[i].y3 = encoded[stream_ptr++];
+      info->v2[i].u = encoded[stream_ptr++];
       info->v2[i].v = encoded[stream_ptr++];
-      info->v2[i].u = encoded[stream_ptr++];
       prep_v2(&info->v2[i]);
     }
 
@@ -401,31 +381,30 @@
 
   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 @@
 
           // 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 @@
                 u_stride,
                 v_stride
               );
-
               break;
 
             // 8x8 block is painted with an 8x8 block from the last frame
@@ -471,17 +451,15 @@
               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 @@
                 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 @@
 
                 // 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 @@
                       u_stride,
                       v_stride
                     );
-
                     break;
 
                   // 4x4 block is motion compensated from the previous frame
@@ -601,22 +590,18 @@
                     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 @@
                       u_stride,
                       v_stride
                     );
-                  
                     break;
 
                   // 4x4 block is copied directly from v4 vector table
@@ -657,19 +641,13 @@
 
                   // 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 @@
 
                       // 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 @@
   }
 
   // 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",