[Mesa-dev] [PATCH] vl/mpeg12: implement inverse scan/quantization steps

Ilia Mirkin imirkin at alum.mit.edu
Sun Jun 23 09:59:26 PDT 2013


Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---

These changes make MPEG2 I-frames generate the correct macroblock data (as
compared to mplayer via xvmc). Other MPEG2 frames are still misparsed, and
MPEG1 I-frames have some errors (but largely match up).

 src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c | 84 ++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 11 deletions(-)

diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
index b0fb1bb..cd3647d 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
@@ -520,6 +520,30 @@ static const unsigned quant_scale[2][32] = {
     28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }
 };
 
+/* Inverses of Figures 7-2 and 7-3 */
+static const uint8_t scans[2][64] = {
+   {
+       0, 1, 8,16, 9, 2, 3,10,
+      17,24,32,25,18,11, 4, 5,
+      12,19,26,33,40,48,41,34,
+      27,20,13, 6, 7,14,21,28,
+      35,42,49,56,57,50,43,36,
+      29,22,15,23,30,37,44,51,
+      58,59,52,45,38,31,39,46,
+      53,60,61,54,47,55,62,63
+   },
+   {
+       0, 8,16,24, 1, 9, 2,10,
+      17,25,32,40,48,56,57,49,
+      41,33,26,18, 3,11, 4,12,
+      19,27,34,42,50,58,35,43,
+      51,59,20,28, 5,13, 6,14,
+      21,29,36,44,52,60,37,45,
+      53,61,22,30, 7,15,23,31,
+      38,46,54,62,39,47,55,63
+   }
+};
+
 static struct vl_vlc_entry tbl_B1[1 << 11];
 static struct vl_vlc_entry tbl_B2[1 << 2];
 static struct vl_vlc_entry tbl_B3[1 << 6];
@@ -706,6 +730,13 @@ reset_predictor(struct vl_mpg12_bs *bs) {
    bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0;
 }
 
+static INLINE int16_t
+sign(int16_t val)
+{
+   if (!val) return 0;
+   return (val < 0) ? -1 : 1;
+}
+
 static INLINE void
 decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
 {
@@ -717,8 +748,11 @@ decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
    bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA;
    const struct dct_coeff *table = intra ? bs->intra_dct_tbl : tbl_B14_AC;
    const struct dct_coeff *entry;
-   int i, cbp, blk = 0;
+   int i, j, cbp, blk = 0;
    short *dst = mb->blocks;
+   const uint8_t *scan = &scans[bs->desc->alternate_scan][0];
+   const uint8_t *quant_matrix = intra ? bs->desc->intra_matrix : bs->desc->non_intra_matrix;
+   int sums[6] = {0};
 
    vl_vlc_fillbits(&bs->vlc);
    mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9);
@@ -757,8 +791,9 @@ entry:
                bs->pred_dc[cc] += dct_diff;
             }
 
-            dst[0] = bs->pred_dc[cc];
             i = 0;
+            j = scan[i];
+            dst[j] = bs->pred_dc[cc];
 
          } else {
             entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17);
@@ -771,32 +806,59 @@ entry:
          i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
          if (i > 64)
             break;
+         j = scan[i];
 
-         dst[i] = vl_vlc_get_simsbf(&bs->vlc, 8);
-         if (dst[i] == -128)
-            dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8) - 256;
-         else if (dst[i] == 0)
-            dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8);
-
-         dst[i] *= scale;
+         dst[j] = vl_vlc_get_simsbf(&bs->vlc, 8);
+         if (dst[j] == -128)
+            dst[j] = vl_vlc_get_uimsbf(&bs->vlc, 8) - 256;
+         else if (dst[j] == 0)
+            dst[j] = vl_vlc_get_uimsbf(&bs->vlc, 8);
       } else if (entry->run == dct_Escape) {
          i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
          if (i > 64)
             break;
 
-         dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale;
+         j = scan[i];
+         dst[j] = vl_vlc_get_simsbf(&bs->vlc, 12);
 
       } else {
          i += entry->run;
          if (i > 64)
             break;
 
-         dst[i] = entry->level * scale;
+         j = scan[i];
+         dst[j] = entry->level;
+      }
+
+      if (intra && !j) {
+         dst[j] = dst[j] << (3 - bs->desc->intra_dc_precision);
+      } else {
+         dst[j] = (2 * dst[j] + (intra ? 0 : sign(dst[j]))) * quant_matrix[j] * scale / 32;
+         if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1 && dst[j])
+            dst[j] = (dst[j] - 1) | 1;
       }
+      if (dst[j] > 2047)
+         dst[j] = 2047;
+      else if (dst[j] < -2048)
+         dst[j] = -2048;
+
+      sums[blk] += dst[j];
 
       vl_vlc_fillbits(&bs->vlc);
       entry = table + vl_vlc_peekbits(&bs->vlc, 17);
    }
+
+   if (bs->decoder->profile != PIPE_VIDEO_PROFILE_MPEG1) {
+      dst = mb->blocks;
+      for (i = 0; i < blk; i++, dst += 64) {
+         if ((sums[i] & 1) == 0) {
+            if (dst[63] & 1)
+               dst[63] -= 1;
+            else
+               dst[63] += 1;
+         }
+      }
+   }
 }
 
 static INLINE void
-- 
1.8.1.5



More information about the mesa-dev mailing list