Encapsulate VLC information needed for decoding blocks and macroblocks in
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 27 Feb 2010 12:32:31 +0000 (12:32 +0000)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 27 Feb 2010 12:32:31 +0000 (12:32 +0000)
Indeo 5 into single structure IVIHuffTab and factorize code using it.

Based on patch by Maxim (max_pole at German GMX)

Originally committed as revision 22092 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/indeo5.c
libavcodec/ivi_common.c
libavcodec/ivi_common.h

index 050ee2b..fa150f2 100644 (file)
@@ -67,10 +67,7 @@ typedef struct {
     uint8_t         frame_flags;
     uint16_t        checksum;        ///< frame checksum
 
-    int16_t         mb_huff_sel;     ///< MB huffman table selector
-    IVIHuffDesc     mb_huff_desc;    ///< MB table descriptor associated with the selector above
-    VLC             *mb_vlc;         ///< ptr to the vlc table for decoding macroblock data
-    VLC             mb_vlc_cust;     ///< custom macroblock vlc table
+    IVIHuffTab      mb_vlc;          ///< vlc table for decoding macroblock data
 
     uint16_t        gop_hdr_size;
     uint8_t         gop_flags;
@@ -305,9 +302,6 @@ static inline void skip_hdr_extension(GetBitContext *gb)
  */
 static int decode_pic_hdr(IVI5DecContext *ctx, AVCodecContext *avctx)
 {
-    int         result;
-    IVIHuffDesc new_huff;
-
     if (get_bits(&ctx->gb, 5) != 0x1F) {
         av_log(avctx, AV_LOG_ERROR, "Invalid picture start code!\n");
         return -1;
@@ -339,28 +333,8 @@ static int decode_pic_hdr(IVI5DecContext *ctx, AVCodecContext *avctx)
             skip_hdr_extension(&ctx->gb); /* XXX: untested */
 
         /* decode macroblock huffman codebook */
-        if (ctx->frame_flags & 0x40) {
-            ctx->mb_huff_sel = ff_ivi_dec_huff_desc(&ctx->gb, &new_huff);
-            if (ctx->mb_huff_sel != 7) {
-                ctx->mb_vlc = &ff_ivi_mb_vlc_tabs[ctx->mb_huff_sel];
-            } else {
-                if (ff_ivi_huff_desc_cmp(&new_huff, &ctx->mb_huff_desc)) {
-                    ff_ivi_huff_desc_copy(&ctx->mb_huff_desc, &new_huff);
-
-                    if (ctx->mb_vlc_cust.table)
-                        free_vlc(&ctx->mb_vlc_cust);
-                    result = ff_ivi_create_huff_from_desc(&ctx->mb_huff_desc,
-                                                          &ctx->mb_vlc_cust, 0);
-                    if (result) {
-                        av_log(avctx, AV_LOG_ERROR, "Error while initializing custom macroblock vlc table!\n");
-                        return -1;
-                    }
-                }
-                ctx->mb_vlc = &ctx->mb_vlc_cust;
-            }
-        } else {
-            ctx->mb_vlc = &ff_ivi_mb_vlc_tabs[7]; /* select the default macroblock huffman table */
-        }
+        if (ff_ivi_dec_huff_desc(&ctx->gb, ctx->frame_flags & 0x40, IVI_MB_HUFF, &ctx->mb_vlc, avctx))
+            return -1;
 
         skip_bits(&ctx->gb, 3); /* FIXME: unknown meaning! */
     }
@@ -382,9 +356,8 @@ static int decode_pic_hdr(IVI5DecContext *ctx, AVCodecContext *avctx)
 static int decode_band_hdr(IVI5DecContext *ctx, IVIBandDesc *band,
                            AVCodecContext *avctx)
 {
-    int         i, result;
+    int         i;
     uint8_t     band_flags;
-    IVIHuffDesc new_huff;
 
     band_flags = get_bits(&ctx->gb, 8);
 
@@ -419,28 +392,8 @@ static int decode_band_hdr(IVI5DecContext *ctx, IVIBandDesc *band,
     band->rvmap_sel = (band_flags & 0x40) ? get_bits(&ctx->gb, 3) : 8;
 
     /* decode block huffman codebook */
-    if (band_flags & 0x80) {
-        band->huff_sel = ff_ivi_dec_huff_desc(&ctx->gb, &new_huff);
-        if (band->huff_sel != 7) {
-            band->blk_vlc = &ff_ivi_blk_vlc_tabs[band->huff_sel];
-        } else {
-            if (ff_ivi_huff_desc_cmp(&new_huff, &band->huff_desc)) {
-                ff_ivi_huff_desc_copy(&band->huff_desc, &new_huff);
-
-                if (band->blk_vlc_cust.table)
-                    free_vlc(&band->blk_vlc_cust);
-                result = ff_ivi_create_huff_from_desc(&band->huff_desc,
-                                                      &band->blk_vlc_cust, 0);
-                if (result) {
-                    av_log(avctx, AV_LOG_ERROR, "Error while initializing custom block vlc table!\n");
-                    return -1;
-                }
-            }
-            band->blk_vlc = &band->blk_vlc_cust;
-        }
-    } else {
-        band->blk_vlc = &ff_ivi_blk_vlc_tabs[7]; /* select the default macroblock huffman table */
-    }
+    if (ff_ivi_dec_huff_desc(&ctx->gb, band_flags & 0x80, IVI_BLK_HUFF, &band->blk_vlc, avctx))
+        return -1;
 
     band->checksum_present = get_bits1(&ctx->gb);
     if (band->checksum_present)
@@ -504,7 +457,7 @@ static int decode_mb_info(IVI5DecContext *ctx, IVIBandDesc *band,
 
                 mb->q_delta = 0;
                 if (!band->plane && !band->band_num && (ctx->frame_flags & 8)) {
-                    mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc->table,
+                    mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table,
                                            IVI_VLC_BITS, 1);
                     mb->q_delta = IVI_TOSIGNED(mb->q_delta);
                 }
@@ -538,7 +491,7 @@ static int decode_mb_info(IVI5DecContext *ctx, IVIBandDesc *band,
                         if (ref_mb) mb->q_delta = ref_mb->q_delta;
                     } else if (mb->cbp || (!band->plane && !band->band_num &&
                                            (ctx->frame_flags & 8))) {
-                        mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc->table,
+                        mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table,
                                                IVI_VLC_BITS, 1);
                         mb->q_delta = IVI_TOSIGNED(mb->q_delta);
                     }
@@ -558,10 +511,10 @@ static int decode_mb_info(IVI5DecContext *ctx, IVIBandDesc *band,
                         }
                     } else {
                         /* decode motion vector deltas */
-                        mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc->table,
+                        mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table,
                                             IVI_VLC_BITS, 1);
                         mv_y += IVI_TOSIGNED(mv_delta);
-                        mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc->table,
+                        mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table,
                                             IVI_VLC_BITS, 1);
                         mv_x += IVI_TOSIGNED(mv_delta);
                         mb->mv_x = mv_x;
@@ -860,8 +813,8 @@ static av_cold int decode_close(AVCodecContext *avctx)
 
     ff_ivi_free_buffers(&ctx->planes[0]);
 
-    if (ctx->mb_vlc_cust.table)
-        free_vlc(&ctx->mb_vlc_cust);
+    if (ctx->mb_vlc.cust_tab.table)
+        free_vlc(&ctx->mb_vlc.cust_tab);
 
     if (ctx->frame.data[0])
         avctx->release_buffer(avctx, &ctx->frame);
index 0a58a68..ad08b44 100644 (file)
@@ -108,20 +108,48 @@ void ff_ivi_init_static_vlc(void)
     initialized_vlcs = 1;
 }
 
-int ff_ivi_dec_huff_desc(GetBitContext *gb, IVIHuffDesc *desc)
+int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab,
+                         IVIHuffTab *huff_tab, AVCodecContext *avctx)
 {
-    int tab_sel, i;
+    int         i, result;
+    IVIHuffDesc new_huff;
 
-    tab_sel = get_bits(gb, 3);
-    if (tab_sel == 7) {
-        /* custom huffman table (explicitly encoded) */
-        desc->num_rows = get_bits(gb, 4);
-
-        for (i = 0; i < desc->num_rows; i++)
-            desc->xbits[i] = get_bits(gb, 4);
+    if (!desc_coded) {
+        /* select default table */
+        huff_tab->tab = (which_tab) ? &ff_ivi_blk_vlc_tabs[7]
+            : &ff_ivi_mb_vlc_tabs [7];
+    } else {
+        huff_tab->tab_sel = get_bits(gb, 3);
+        if (huff_tab->tab_sel == 7) {
+            /* custom huffman table (explicitly encoded) */
+            new_huff.num_rows = get_bits(gb, 4);
+
+            for (i = 0; i < new_huff.num_rows; i++)
+                new_huff.xbits[i] = get_bits(gb, 4);
+
+            /* Have we got the same custom table? Rebuild if not. */
+            if (ff_ivi_huff_desc_cmp(&new_huff, &huff_tab->cust_desc)) {
+                ff_ivi_huff_desc_copy(&huff_tab->cust_desc, &new_huff);
+
+                if (huff_tab->cust_tab.table)
+                    free_vlc(&huff_tab->cust_tab);
+                result = ff_ivi_create_huff_from_desc(&huff_tab->cust_desc,
+                        &huff_tab->cust_tab, 0);
+                if (result) {
+                    av_log(avctx, AV_LOG_ERROR,
+                           "Error while initializing custom vlc table!\n");
+                    return -1;
+                }
+            }
+            huff_tab->tab = &huff_tab->cust_tab;
+        } else {
+            /* select one of predefined tables */
+            huff_tab->tab = (which_tab) ? &ff_ivi_blk_vlc_tabs[huff_tab->tab_sel]
+                : &ff_ivi_mb_vlc_tabs [huff_tab->tab_sel];
+        }
     }
 
-    return tab_sel;
+    return 0;
 }
 
 int ff_ivi_huff_desc_cmp(const IVIHuffDesc *desc1, const IVIHuffDesc *desc2)
@@ -191,7 +219,7 @@ int av_cold ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg)
                     return AVERROR(ENOMEM);
             }
 
-            planes[p].bands[0].huff_desc.num_rows = 0; /* reset custom vlc */
+            planes[p].bands[0].blk_vlc.cust_desc.num_rows = 0; /* reset custom vlc */
         }
     }
 
@@ -208,8 +236,8 @@ void av_cold ff_ivi_free_buffers(IVIPlaneDesc *planes)
             av_freep(&planes[p].bands[b].bufs[1]);
             av_freep(&planes[p].bands[b].bufs[2]);
 
-            if (planes[p].bands[b].blk_vlc_cust.table)
-                free_vlc(&planes[p].bands[b].blk_vlc_cust);
+            if (planes[p].bands[b].blk_vlc.cust_tab.table)
+                free_vlc(&planes[p].bands[b].blk_vlc.cust_tab);
             for (t = 0; t < planes[p].bands[b].num_tiles; t++)
                 av_freep(&planes[p].bands[b].tiles[t].mbs);
             av_freep(&planes[p].bands[b].tiles);
@@ -358,14 +386,14 @@ int ff_ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile)
                 memset(col_flags, 0, sizeof(col_flags));      /* zero column flags */
 
                 while (scan_pos <= num_coeffs) {
-                    sym = get_vlc2(gb, band->blk_vlc->table, IVI_VLC_BITS, 1);
+                    sym = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);
                     if (sym == rvmap->eob_sym)
                         break; /* End of block */
 
                     if (sym == rvmap->esc_sym) { /* Escape - run/val explicitly coded using 3 vlc codes */
-                        run = get_vlc2(gb, band->blk_vlc->table, IVI_VLC_BITS, 1) + 1;
-                        lo  = get_vlc2(gb, band->blk_vlc->table, IVI_VLC_BITS, 1);
-                        hi  = get_vlc2(gb, band->blk_vlc->table, IVI_VLC_BITS, 1);
+                        run = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1) + 1;
+                        lo  = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);
+                        hi  = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);
                         val = IVI_TOSIGNED((hi << 6) | lo); /* merge them and convert into signed val */
                     } else {
                         run = rvmap->runtab[sym];
index 95ab506..ef0a0f4 100644 (file)
@@ -45,6 +45,24 @@ typedef struct {
     uint8_t     xbits[16];
 } IVIHuffDesc;
 
+/**
+ *  macroblock/block huffman table descriptor
+ */
+typedef struct {
+    int32_t     tab_sel;    /// index of one of the predefined tables
+                            /// or "7" for custom one
+    VLC         *tab;       /// pointer to the table associated with tab_sel
+
+    //! the following are used only when tab_sel == 7
+    IVIHuffDesc cust_desc;  /// custom Huffman codebook descriptor
+    VLC         cust_tab;   /// vlc table for custom codebook
+} IVIHuffTab;
+
+enum {
+    IVI_MB_HUFF   = 0,      /// Huffman table is used for coding macroblocks
+    IVI_BLK_HUFF  = 1       /// Huffman table is used for coding blocks
+};
+
 extern VLC ff_ivi_mb_vlc_tabs [8]; ///< static macroblock Huffman tables
 extern VLC ff_ivi_blk_vlc_tabs[8]; ///< static block Huffman tables
 
@@ -118,10 +136,7 @@ typedef struct {
     int             glob_quant;     ///< quant base for this band
     const uint8_t   *scan;          ///< ptr to the scan pattern
 
-    int             huff_sel;       ///< huffman table for this band
-    IVIHuffDesc     huff_desc;      ///< table descriptor associated with the selector above
-    VLC             *blk_vlc;       ///< ptr to the vlc table for decoding block data
-    VLC             blk_vlc_cust;   ///< custom block vlc table
+    IVIHuffTab      blk_vlc;        ///< vlc table for decoding block data
 
     uint16_t        *dequant_intra; ///< ptr to dequant tables for intra blocks
     uint16_t        *dequant_inter; ///< ptr dequant tables for inter blocks
@@ -208,14 +223,18 @@ int  ff_ivi_create_huff_from_desc(const IVIHuffDesc *cb, VLC *vlc, int flag);
 void ff_ivi_init_static_vlc(void);
 
 /**
- *  Decodes a huffman codebook descriptor from the bitstream.
+ *  Decodes a huffman codebook descriptor from the bitstream
+ *  and selects specified huffman table.
  *
- *  @param gb   [in,out] the GetBit context
- *  @param desc [out] ptr to descriptor to be filled with data
- *  @return     selector indicating huffman table:
- *              (0...6 - predefined, 7 - custom one supplied with the bitstream)
+ *  @param gb           [in,out] the GetBit context
+ *  @param desc_coded   [in] flag signalling if table descriptor was coded
+ *  @param which_tab    [in] codebook purpose (IVI_MB_HUFF or IVI_BLK_HUFF)
+ *  @param huff_tab     [out] pointer to the descriptor of the selected table
+ *  @param avctx        [in] AVCodecContext pointer
+ *  @return             zero on success, negative value otherwise
  */
-int  ff_ivi_dec_huff_desc(GetBitContext *gb, IVIHuffDesc *desc);
+int  ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab,
+                          IVIHuffTab *huff_tab, AVCodecContext *avctx);
 
 /**
  *  Compares two huffman codebook descriptors.