]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mss3.c
mpeg12dec: avoid signed overflow in bitrate calculation
[ffmpeg] / libavcodec / mss3.c
index 37d8aee4eccaf520f0d5e498fb509a34cfdc3a4c..6a9731b58b047ddd5a8e89ac936276e9eb1b2d5e 100644 (file)
@@ -26,6 +26,9 @@
 
 #include "avcodec.h"
 #include "bytestream.h"
+#include "internal.h"
+#include "mathops.h"
+#include "mss34dsp.h"
 
 #define HEADER_SIZE 27
 
@@ -88,7 +91,7 @@ typedef struct ImageBlockCoder {
 
 typedef struct DCTBlockCoder {
     int      *prev_dc;
-    int      prev_dc_stride;
+    ptrdiff_t prev_dc_stride;
     int      prev_dc_height;
     int      quality;
     uint16_t qmat[64];
@@ -105,7 +108,7 @@ typedef struct HaarBlockCoder {
 
 typedef struct MSS3Context {
     AVCodecContext   *avctx;
-    AVFrame          pic;
+    AVFrame          *pic;
 
     int              got_error;
     RangeCoder       coder;
@@ -119,39 +122,6 @@ typedef struct MSS3Context {
     int              hblock[16 * 16];
 } MSS3Context;
 
-static const uint8_t mss3_luma_quant[64] = {
-    16,  11,  10,  16,  24,  40,  51,  61,
-    12,  12,  14,  19,  26,  58,  60,  55,
-    14,  13,  16,  24,  40,  57,  69,  56,
-    14,  17,  22,  29,  51,  87,  80,  62,
-    18,  22,  37,  56,  68, 109, 103,  77,
-    24,  35,  55,  64,  81, 104, 113,  92,
-    49,  64,  78,  87, 103, 121, 120, 101,
-    72,  92,  95,  98, 112, 100, 103,  99
-};
-
-static const uint8_t mss3_chroma_quant[64] = {
-    17, 18, 24, 47, 99, 99, 99, 99,
-    18, 21, 26, 66, 99, 99, 99, 99,
-    24, 26, 56, 99, 99, 99, 99, 99,
-    47, 66, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99
-};
-
-const uint8_t zigzag_scan[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
-};
-
 
 static void model2_reset(Model2 *m)
 {
@@ -480,7 +450,7 @@ static int decode_coeff(RangeCoder *c, Model *m)
 }
 
 static void decode_fill_block(RangeCoder *c, FillBlockCoder *fc,
-                              uint8_t *dst, int stride, int block_size)
+                              uint8_t *dst, ptrdiff_t stride, int block_size)
 {
     int i;
 
@@ -491,7 +461,7 @@ static void decode_fill_block(RangeCoder *c, FillBlockCoder *fc,
 }
 
 static void decode_image_block(RangeCoder *c, ImageBlockCoder *ic,
-                               uint8_t *dst, int stride, int block_size)
+                               uint8_t *dst, ptrdiff_t stride, int block_size)
 {
     int i, j;
     int vec_size;
@@ -578,7 +548,7 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block,
         if (!sign)
             val = -val;
 
-        zz_pos = zigzag_scan[pos];
+        zz_pos = ff_zigzag_direct[pos];
         block[zz_pos] = val * bc->qmat[zz_pos];
         pos++;
     }
@@ -586,60 +556,8 @@ static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block,
     return pos == 64 ? 0 : -1;
 }
 
-#define DCT_TEMPLATE(blk, step, SOP, shift)                         \
-    const int t0 = -39409 * blk[7 * step] -  58980 * blk[1 * step]; \
-    const int t1 =  39410 * blk[1 * step] -  58980 * blk[7 * step]; \
-    const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \
-    const int t3 =  33410 * blk[3 * step] - 167963 * blk[5 * step]; \
-    const int t4 =          blk[3 * step] +          blk[7 * step]; \
-    const int t5 =          blk[1 * step] +          blk[5 * step]; \
-    const int t6 =  77062 * t4            +  51491 * t5;            \
-    const int t7 =  77062 * t5            -  51491 * t4;            \
-    const int t8 =  35470 * blk[2 * step] -  85623 * blk[6 * step]; \
-    const int t9 =  35470 * blk[6 * step] +  85623 * blk[2 * step]; \
-    const int tA = SOP(blk[0 * step] - blk[4 * step]);              \
-    const int tB = SOP(blk[0 * step] + blk[4 * step]);              \
-                                                                    \
-    blk[0 * step] = (  t1 + t6  + t9 + tB) >> shift;                \
-    blk[1 * step] = (  t3 + t7  + t8 + tA) >> shift;                \
-    blk[2 * step] = (  t2 + t6  - t8 + tA) >> shift;                \
-    blk[3 * step] = (  t0 + t7  - t9 + tB) >> shift;                \
-    blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift;                \
-    blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift;                \
-    blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift;                \
-    blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift;                \
-
-#define SOP_ROW(a) ((a) << 16) + 0x2000
-#define SOP_COL(a) ((a + 32) << 16)
-
-static void dct_put(uint8_t *dst, int stride, int *block)
-{
-    int i, j;
-    int *ptr;
-
-    ptr = block;
-    for (i = 0; i < 8; i++) {
-        DCT_TEMPLATE(ptr, 1, SOP_ROW, 13);
-        ptr += 8;
-    }
-
-    ptr = block;
-    for (i = 0; i < 8; i++) {
-        DCT_TEMPLATE(ptr, 8, SOP_COL, 22);
-        ptr++;
-    }
-
-    ptr = block;
-    for (j = 0; j < 8; j++) {
-        for (i = 0; i < 8; i++)
-            dst[i] = av_clip_uint8(ptr[i] + 128);
-        dst += stride;
-        ptr += 8;
-    }
-}
-
 static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc,
-                             uint8_t *dst, int stride, int block_size,
+                             uint8_t *dst, ptrdiff_t stride, int block_size,
                              int *block, int mb_x, int mb_y)
 {
     int i, j;
@@ -655,15 +573,15 @@ static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc,
                 c->got_error = 1;
                 return;
             }
-            dct_put(dst + i * 8, stride, block);
+            ff_mss34_dct_put(dst + i * 8, stride, block);
         }
         dst += 8 * stride;
     }
 }
 
 static void decode_haar_block(RangeCoder *c, HaarBlockCoder *hc,
-                              uint8_t *dst, int stride, int block_size,
-                              int *block)
+                              uint8_t *dst, ptrdiff_t stride,
+                              int block_size, int *block)
 {
     const int hsize = block_size >> 1;
     int A, B, C, D, t1, t2, t3, t4;
@@ -702,14 +620,6 @@ static void decode_haar_block(RangeCoder *c, HaarBlockCoder *hc,
     }
 }
 
-static void gen_quant_mat(uint16_t *qmat, const uint8_t *ref, float scale)
-{
-    int i;
-
-    for (i = 0; i < 64; i++)
-        qmat[i] = (uint16_t)(ref[i] * scale + 50.0) / 100;
-}
-
 static void reset_coders(MSS3Context *ctx, int quality)
 {
     int i, j;
@@ -726,15 +636,8 @@ static void reset_coders(MSS3Context *ctx, int quality)
         for (j = 0; j < 125; j++)
             model_reset(&ctx->image_coder[i].vq_model[j]);
         if (ctx->dct_coder[i].quality != quality) {
-            float scale;
             ctx->dct_coder[i].quality = quality;
-            if (quality > 50)
-                scale = 200.0f - 2 * quality;
-            else
-                scale = 5000.0f / quality;
-            gen_quant_mat(ctx->dct_coder[i].qmat,
-                          i ? mss3_chroma_quant : mss3_luma_quant,
-                          scale);
+            ff_mss34_gen_quant_mat(ctx->dct_coder[i].qmat, quality, !i);
         }
         memset(ctx->dct_coder[i].prev_dc, 0,
                sizeof(*ctx->dct_coder[i].prev_dc) *
@@ -772,7 +675,7 @@ static av_cold void init_coders(MSS3Context *ctx)
     }
 }
 
-static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
+static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                              AVPacket *avpkt)
 {
     const uint8_t *buf = avpkt->data;
@@ -828,18 +731,16 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
         return buf_size;
     c->got_error = 0;
 
-    c->pic.reference    = 3;
-    c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
-                          FF_BUFFER_HINTS_REUSABLE;
-    if ((ret = avctx->reget_buffer(avctx, &c->pic)) < 0) {
+    if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
         return ret;
     }
-    c->pic.key_frame = keyframe;
-    c->pic.pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
+    c->pic->key_frame = keyframe;
+    c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
     if (!bytestream2_get_bytes_left(&gb)) {
-        *data_size = sizeof(AVFrame);
-        *(AVFrame*)data = c->pic;
+        if ((ret = av_frame_ref(data, c->pic)) < 0)
+            return ret;
+        *got_frame      = 1;
 
         return buf_size;
     }
@@ -850,9 +751,9 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
 
     mb_width  = dec_width  >> 4;
     mb_height = dec_height >> 4;
-    dst[0] = c->pic.data[0] + dec_x     +  dec_y      * c->pic.linesize[0];
-    dst[1] = c->pic.data[1] + dec_x / 2 + (dec_y / 2) * c->pic.linesize[1];
-    dst[2] = c->pic.data[2] + dec_x / 2 + (dec_y / 2) * c->pic.linesize[2];
+    dst[0] = c->pic->data[0] + dec_x     +  dec_y      * c->pic->linesize[0];
+    dst[1] = c->pic->data[1] + dec_x / 2 + (dec_y / 2) * c->pic->linesize[1];
+    dst[2] = c->pic->data[2] + dec_x / 2 + (dec_y / 2) * c->pic->linesize[2];
     for (y = 0; y < mb_height; y++) {
         for (x = 0; x < mb_width; x++) {
             for (i = 0; i < 3; i++) {
@@ -863,23 +764,23 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                 case FILL_BLOCK:
                     decode_fill_block(acoder, c->fill_coder + i,
                                       dst[i] + x * blk_size,
-                                      c->pic.linesize[i], blk_size);
+                                      c->pic->linesize[i], blk_size);
                     break;
                 case IMAGE_BLOCK:
                     decode_image_block(acoder, c->image_coder + i,
                                        dst[i] + x * blk_size,
-                                       c->pic.linesize[i], blk_size);
+                                       c->pic->linesize[i], blk_size);
                     break;
                 case DCT_BLOCK:
                     decode_dct_block(acoder, c->dct_coder + i,
                                      dst[i] + x * blk_size,
-                                     c->pic.linesize[i], blk_size,
+                                     c->pic->linesize[i], blk_size,
                                      c->dctblock, x, y);
                     break;
                 case HAAR_BLOCK:
                     decode_haar_block(acoder, c->haar_coder + i,
                                       dst[i] + x * blk_size,
-                                      c->pic.linesize[i], blk_size,
+                                      c->pic->linesize[i], blk_size,
                                       c->hblock);
                     break;
                 }
@@ -891,17 +792,31 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                 }
             }
         }
-        dst[0] += c->pic.linesize[0] * 16;
-        dst[1] += c->pic.linesize[1] * 8;
-        dst[2] += c->pic.linesize[2] * 8;
+        dst[0] += c->pic->linesize[0] * 16;
+        dst[1] += c->pic->linesize[1] * 8;
+        dst[2] += c->pic->linesize[2] * 8;
     }
 
-    *data_size = sizeof(AVFrame);
-    *(AVFrame*)data = c->pic;
+    if ((ret = av_frame_ref(data, c->pic)) < 0)
+        return ret;
+
+    *got_frame      = 1;
 
     return buf_size;
 }
 
+static av_cold int mss3_decode_end(AVCodecContext *avctx)
+{
+    MSS3Context * const c = avctx->priv_data;
+    int i;
+
+    av_frame_free(&c->pic);
+    for (i = 0; i < 3; i++)
+        av_freep(&c->dct_coder[i].prev_dc);
+
+    return 0;
+}
+
 static av_cold int mss3_decode_init(AVCodecContext *avctx)
 {
     MSS3Context * const c = avctx->priv_data;
@@ -933,35 +848,27 @@ static av_cold int mss3_decode_init(AVCodecContext *avctx)
         }
     }
 
-    avctx->pix_fmt     = PIX_FMT_YUV420P;
-    avctx->coded_frame = &c->pic;
-
-    init_coders(c);
-
-    return 0;
-}
+    c->pic = av_frame_alloc();
+    if (!c->pic) {
+        mss3_decode_end(avctx);
+        return AVERROR(ENOMEM);
+    }
 
-static av_cold int mss3_decode_end(AVCodecContext *avctx)
-{
-    MSS3Context * const c = avctx->priv_data;
-    int i;
+    avctx->pix_fmt     = AV_PIX_FMT_YUV420P;
 
-    if (c->pic.data[0])
-        avctx->release_buffer(avctx, &c->pic);
-    for (i = 0; i < 3; i++)
-        av_freep(&c->dct_coder[i].prev_dc);
+    init_coders(c);
 
     return 0;
 }
 
 AVCodec ff_msa1_decoder = {
     .name           = "msa1",
+    .long_name      = NULL_IF_CONFIG_SMALL("MS ATC Screen"),
     .type           = AVMEDIA_TYPE_VIDEO,
-    .id             = CODEC_ID_MSA1,
+    .id             = AV_CODEC_ID_MSA1,
     .priv_data_size = sizeof(MSS3Context),
     .init           = mss3_decode_init,
     .close          = mss3_decode_end,
     .decode         = mss3_decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
-    .long_name      = NULL_IF_CONFIG_SMALL("MS ATC Screen"),
+    .capabilities   = AV_CODEC_CAP_DR1,
 };