]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ivi_common.c
cinepak: use the AVFrame API properly.
[ffmpeg] / libavcodec / ivi_common.c
index d4eae9712610547cfe0182fe837414d2d04a29fb..8c5d7f32c338f32ff240c73309ab01aae98d2220 100644 (file)
 #include "ivi_common.h"
 #include "ivi_dsp.h"
 
-extern const IVIHuffDesc ff_ivi_mb_huff_desc[8];  ///< static macroblock huffman tables
-extern const IVIHuffDesc ff_ivi_blk_huff_desc[8]; ///< static block huffman tables
+/**
+ * These are 2x8 predefined Huffman codebooks for coding macroblock/block
+ * signals. They are specified using "huffman descriptors" in order to
+ * avoid huge static tables. The decoding tables will be generated at
+ * startup from these descriptors.
+ */
+/** static macroblock huffman tables */
+static const IVIHuffDesc ivi_mb_huff_desc[8] = {
+    {8,  {0, 4, 5, 4, 4, 4, 6, 6}},
+    {12, {0, 2, 2, 3, 3, 3, 3, 5, 3, 2, 2, 2}},
+    {12, {0, 2, 3, 4, 3, 3, 3, 3, 4, 3, 2, 2}},
+    {12, {0, 3, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2}},
+    {13, {0, 4, 4, 3, 3, 3, 3, 2, 3, 3, 2, 1, 1}},
+    {9,  {0, 4, 4, 4, 4, 3, 3, 3, 2}},
+    {10, {0, 4, 4, 4, 4, 3, 3, 2, 2, 2}},
+    {12, {0, 4, 4, 4, 3, 3, 2, 3, 2, 2, 2, 2}}
+};
+
+/** static block huffman tables */
+static const IVIHuffDesc ivi_blk_huff_desc[8] = {
+    {10, {1, 2, 3, 4, 4, 7, 5, 5, 4, 1}},
+    {11, {2, 3, 4, 4, 4, 7, 5, 4, 3, 3, 2}},
+    {12, {2, 4, 5, 5, 5, 5, 6, 4, 4, 3, 1, 1}},
+    {13, {3, 3, 4, 4, 5, 6, 6, 4, 4, 3, 2, 1, 1}},
+    {11, {3, 4, 4, 5, 5, 5, 6, 5, 4, 2, 2}},
+    {13, {3, 4, 5, 5, 5, 5, 6, 4, 3, 3, 2, 1, 1}},
+    {13, {3, 4, 5, 5, 5, 6, 5, 4, 3, 3, 2, 1, 1}},
+    {9,  {3, 4, 4, 5, 5, 5, 6, 5, 5}}
+};
 
 static VLC ivi_mb_vlc_tabs [8]; ///< static macroblock Huffman tables
 static VLC ivi_blk_vlc_tabs[8]; ///< static block Huffman tables
@@ -44,6 +71,26 @@ static VLC ivi_blk_vlc_tabs[8]; ///< static block Huffman tables
 typedef void (*ivi_mc_func) (int16_t *buf, const int16_t *ref_buf,
                              uint32_t pitch, int mc_type);
 
+static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc,
+                  int offs, int mv_x, int mv_y, int mc_type)
+{
+    int ref_offs = offs + mv_y * band->pitch + mv_x;
+    int buf_size = band->pitch * band->aheight;
+    int min_size = band->pitch * (band->blk_size - 1) + band->blk_size;
+    int ref_size = (mc_type > 1) * band->pitch + (mc_type & 1);
+
+    if (offs < 0 || ref_offs < 0 || !band->ref_buf)
+        return AVERROR_INVALIDDATA;
+    if (buf_size - min_size < offs)
+        return AVERROR_INVALIDDATA;
+    if (buf_size - min_size - ref_size < ref_offs)
+        return AVERROR_INVALIDDATA;
+
+    mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type);
+
+    return 0;
+}
+
 /**
  *  Reverse "nbits" bits of the value "val" and return the result
  *  in the least significant bits.
@@ -115,11 +162,11 @@ av_cold void ff_ivi_init_static_vlc(void)
     for (i = 0; i < 8; i++) {
         ivi_mb_vlc_tabs[i].table = table_data + i * 2 * 8192;
         ivi_mb_vlc_tabs[i].table_allocated = 8192;
-        ivi_create_huff_from_desc(&ff_ivi_mb_huff_desc[i],
+        ivi_create_huff_from_desc(&ivi_mb_huff_desc[i],
                                   &ivi_mb_vlc_tabs[i], 1);
         ivi_blk_vlc_tabs[i].table = table_data + (i * 2 + 1) * 8192;
         ivi_blk_vlc_tabs[i].table_allocated = 8192;
-        ivi_create_huff_from_desc(&ff_ivi_blk_huff_desc[i],
+        ivi_create_huff_from_desc(&ivi_blk_huff_desc[i],
                                   &ivi_blk_vlc_tabs[i], 1);
     }
     initialized_vlcs = 1;
@@ -224,6 +271,7 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes)
             av_freep(&planes[p].bands[b].tiles);
         }
         av_freep(&planes[p].bands);
+        planes[p].num_bands = 0;
     }
 }
 
@@ -236,6 +284,10 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg)
 
     ivi_free_buffers(planes);
 
+    if (cfg->pic_width < 1 || cfg->pic_height < 1 ||
+        cfg->luma_bands < 1 || cfg->chroma_bands < 1)
+        return AVERROR_INVALIDDATA;
+
     /* fill in the descriptor of the luminance plane */
     planes[0].width     = cfg->pic_width;
     planes[0].height    = cfg->pic_height;
@@ -318,6 +370,8 @@ static int ivi_init_tiles(IVIBandDesc *band, IVITile *ref_tile,
 
             tile->ref_mbs = 0;
             if (p || b) {
+                if (tile->num_MBs != ref_tile->num_MBs)
+                    return AVERROR_INVALIDDATA;
                 tile->ref_mbs = ref_tile->mbs;
                 ref_tile++;
             }
@@ -393,6 +447,24 @@ static int ivi_dec_tile_data_size(GetBitContext *gb)
     return len;
 }
 
+static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs,
+                            int blk_size)
+{
+    int buf_size = band->pitch * band->aheight - buf_offs;
+    int min_size = (blk_size - 1) * band->pitch + blk_size;
+
+    if (!band->dc_transform)
+        return 0;
+
+
+    if (min_size > buf_size)
+        return AVERROR_INVALIDDATA;
+
+    band->dc_transform(prev_dc, band->buf + buf_offs,
+                       band->pitch, blk_size);
+
+    return 0;
+}
 
 static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
                                    ivi_mc_func mc, int mv_x, int mv_y,
@@ -410,6 +482,12 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
     int num_coeffs = blk_size * blk_size;
     int col_mask   = blk_size - 1;
     int scan_pos   = -1;
+    int min_size   = band->pitch * (band->transform_size - 1) +
+                     band->transform_size;
+    int buf_size   = band->pitch * band->aheight - offs;
+
+    if (min_size > buf_size)
+        return AVERROR_INVALIDDATA;
 
     if (!band->scan) {
         av_log(avctx, AV_LOG_ERROR, "Scan pattern is not set.\n");
@@ -444,7 +522,7 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
 
         /* de-zigzag and dequantize */
         scan_pos += run;
-        if (scan_pos >= num_coeffs)
+        if (scan_pos >= num_coeffs || scan_pos < 0)
             break;
         pos = band->scan[scan_pos];
 
@@ -459,7 +537,7 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
         col_flags[pos & col_mask] |= !!val;
     }
 
-    if (scan_pos >= num_coeffs && sym != rvmap->eob_sym)
+    if (scan_pos < 0 || scan_pos >= num_coeffs && sym != rvmap->eob_sym)
         return AVERROR_INVALIDDATA; /* corrupt block data */
 
     /* undoing DC coeff prediction for intra-blocks */
@@ -475,9 +553,7 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
 
     /* apply motion compensation */
     if (!is_intra)
-        mc(band->buf + offs,
-           band->ref_buf + offs + mv_y * band->pitch + mv_x,
-           band->pitch, mc_type);
+        return ivi_mc(band, mc, offs, mv_x, mv_y, mc_type);
 
     return 0;
 }
@@ -576,13 +652,15 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
                 /* for intra blocks apply the dc slant transform */
                 /* for inter - perform the motion compensation without delta */
                 if (is_intra) {
-                    if (band->dc_transform)
-                        band->dc_transform(&prev_dc, band->buf + buf_offs,
-                                           band->pitch, blk_size);
-                } else
-                    mc_no_delta_func(band->buf + buf_offs,
-                                     band->ref_buf + buf_offs + mv_y * band->pitch + mv_x,
-                                     band->pitch, mc_type);
+                    ret = ivi_dc_transform(band, &prev_dc, buf_offs, blk_size);
+                    if (ret < 0)
+                        return ret;
+                } else {
+                    ret = ivi_mc(band, mc_no_delta_func, buf_offs,
+                                 mv_x, mv_y, mc_type);
+                    if (ret < 0)
+                        return ret;
+                }
             }
 
             cbp >>= 1;
@@ -607,7 +685,7 @@ static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band,
                                   IVITile *tile, int32_t mv_scale)
 {
     int             x, y, need_mc, mbn, blk, num_blocks, mv_x, mv_y, mc_type;
-    int             offs, mb_offset, row_offset;
+    int             offs, mb_offset, row_offset, ret;
     IVIMbInfo       *mb, *ref_mb;
     const int16_t   *src;
     int16_t         *dst;
@@ -685,9 +763,10 @@ static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band,
             for (blk = 0; blk < num_blocks; blk++) {
                 /* adjust block position in the buffer according with its number */
                 offs = mb->buf_offs + band->blk_size * ((blk & 1) + !!(blk & 2) * band->pitch);
-                mc_no_delta_func(band->buf + offs,
-                                 band->ref_buf + offs + mv_y * band->pitch + mv_x,
-                                 band->pitch, mc_type);
+                ret = ivi_mc(band, mc_no_delta_func, offs,
+                             mv_x, mv_y, mc_type);
+                if (ret < 0)
+                    return ret;
             }
         }
     } else {
@@ -891,6 +970,11 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         return AVERROR_PATCHWELCOME;
     }
 
+    if (!ctx->planes[0].bands) {
+        av_log(avctx, AV_LOG_ERROR, "Color planes not initialized yet\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     ctx->switch_buffers(ctx);
 
     //{ START_TIMER;
@@ -906,6 +990,14 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                 }
             }
         }
+    } else {
+        if (ctx->is_scalable)
+            return AVERROR_INVALIDDATA;
+
+        for (p = 0; p < 3; p++) {
+            if (!ctx->planes[p].bands[0].buf)
+                return AVERROR_INVALIDDATA;
+        }
     }
 
     //STOP_TIMER("decode_planes"); }
@@ -923,7 +1015,10 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             av_log(avctx, AV_LOG_ERROR, "Buffer contains IP frames!\n");
     }
 
-    avcodec_set_dimensions(avctx, ctx->planes[0].width, ctx->planes[0].height);
+    result = ff_set_dimensions(avctx, ctx->planes[0].width, ctx->planes[0].height);
+    if (result < 0)
+        return result;
+
     if ((result = ff_get_buffer(avctx, frame, 0)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return result;
@@ -979,35 +1074,6 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx)
 }
 
 
-/**
- * These are 2x8 predefined Huffman codebooks for coding macroblock/block
- * signals. They are specified using "huffman descriptors" in order to
- * avoid huge static tables. The decoding tables will be generated at
- * startup from these descriptors.
- */
-const IVIHuffDesc ff_ivi_mb_huff_desc[8] = {
-    {8,  {0, 4, 5, 4, 4, 4, 6, 6}},
-    {12, {0, 2, 2, 3, 3, 3, 3, 5, 3, 2, 2, 2}},
-    {12, {0, 2, 3, 4, 3, 3, 3, 3, 4, 3, 2, 2}},
-    {12, {0, 3, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2}},
-    {13, {0, 4, 4, 3, 3, 3, 3, 2, 3, 3, 2, 1, 1}},
-    {9,  {0, 4, 4, 4, 4, 3, 3, 3, 2}},
-    {10, {0, 4, 4, 4, 4, 3, 3, 2, 2, 2}},
-    {12, {0, 4, 4, 4, 3, 3, 2, 3, 2, 2, 2, 2}}
-};
-
-const IVIHuffDesc ff_ivi_blk_huff_desc[8] = {
-    {10, {1, 2, 3, 4, 4, 7, 5, 5, 4, 1}},
-    {11, {2, 3, 4, 4, 4, 7, 5, 4, 3, 3, 2}},
-    {12, {2, 4, 5, 5, 5, 5, 6, 4, 4, 3, 1, 1}},
-    {13, {3, 3, 4, 4, 5, 6, 6, 4, 4, 3, 2, 1, 1}},
-    {11, {3, 4, 4, 5, 5, 5, 6, 5, 4, 2, 2}},
-    {13, {3, 4, 5, 5, 5, 5, 6, 4, 3, 3, 2, 1, 1}},
-    {13, {3, 4, 5, 5, 5, 6, 5, 4, 3, 3, 2, 1, 1}},
-    {9,  {3, 4, 4, 5, 5, 5, 6, 5, 5}}
-};
-
-
 /**
  *  Scan patterns shared between indeo4 and indeo5
  */