summaryrefslogtreecommitdiff
path: root/libavcodec/cavsdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/cavsdec.c')
-rw-r--r--libavcodec/cavsdec.c148
1 files changed, 104 insertions, 44 deletions
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index a455a34bd0..70ac6f8a42 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -2,20 +2,20 @@
* Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
* Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.de>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -25,6 +25,7 @@
* @author Stefan Gehrer <stefan.gehrer@gmx.de>
*/
+#include "libavutil/avassert.h"
#include "avcodec.h"
#include "get_bits.h"
#include "golomb.h"
@@ -50,13 +51,6 @@ static const uint8_t cbp_tab[64][2] = {
static const uint8_t scan3x3[4] = { 4, 5, 7, 8 };
-static const uint8_t cavs_chroma_qp[64] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 44, 44,
- 45, 45, 46, 46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51
-};
-
static const uint8_t dequant_shift[64] = {
14, 14, 14, 14, 14, 14, 14, 14,
13, 13, 13, 13, 13, 13, 13, 13,
@@ -508,11 +502,15 @@ static inline void mv_pred_sym(AVSContext *h, cavs_vector *src,
/** kth-order exponential golomb code */
static inline int get_ue_code(GetBitContext *gb, int order)
{
+ unsigned ret = get_ue_golomb(gb);
+ if (ret >= ((1U<<31)>>order)) {
+ av_log(NULL, AV_LOG_ERROR, "get_ue_code: value too larger\n");
+ return AVERROR_INVALIDDATA;
+ }
if (order) {
- int ret = get_ue_golomb(gb) << order;
- return ret + get_bits(gb, order);
+ return (ret<<order) + get_bits(gb, order);
}
- return get_ue_golomb(gb);
+ return ret;
}
static inline int dequant(AVSContext *h, int16_t *level_buf, uint8_t *run_buf,
@@ -549,29 +547,37 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb,
const struct dec_2dvlc *r, int esc_golomb_order,
int qp, uint8_t *dst, int stride)
{
- int i, level_code, esc_code, level, run, mask, ret;
+ int i, esc_code, level, mask, ret;
+ unsigned int level_code, run;
int16_t level_buf[65];
uint8_t run_buf[65];
int16_t *block = h->block;
- for (i = 0;i < 65; i++) {
+ for (i = 0; i < 65; i++) {
level_code = get_ue_code(gb, r->golomb_order);
if (level_code >= ESCAPE_CODE) {
run = ((level_code - ESCAPE_CODE) >> 1) + 1;
+ if(run > 64) {
+ av_log(h->avctx, AV_LOG_ERROR, "run %d is too large\n", run);
+ return AVERROR_INVALIDDATA;
+ }
esc_code = get_ue_code(gb, esc_golomb_order);
+ if (esc_code < 0 || esc_code > 32767) {
+ av_log(h->avctx, AV_LOG_ERROR, "esc_code invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
+
level = esc_code + (run > r->max_run ? 1 : r->level_add[run]);
while (level > r->inc_limit)
r++;
mask = -(level_code & 1);
level = (level ^ mask) - mask;
- } else if (level_code >= 0) {
+ } else {
level = r->rltab[level_code][0];
if (!level) //end of block signal
break;
run = r->rltab[level_code][1];
r += r->rltab[level_code][2];
- } else {
- break;
}
level_buf[i] = level;
run_buf[i] = run;
@@ -589,10 +595,10 @@ static inline void decode_residual_chroma(AVSContext *h)
{
if (h->cbp & (1 << 4))
decode_residual_block(h, &h->gb, chroma_dec, 0,
- cavs_chroma_qp[h->qp], h->cu, h->c_stride);
+ ff_cavs_chroma_qp[h->qp], h->cu, h->c_stride);
if (h->cbp & (1 << 5))
decode_residual_block(h, &h->gb, chroma_dec, 0,
- cavs_chroma_qp[h->qp], h->cv, h->c_stride);
+ ff_cavs_chroma_qp[h->qp], h->cv, h->c_stride);
}
static inline int decode_residual_inter(AVSContext *h)
@@ -601,7 +607,7 @@ static inline int decode_residual_inter(AVSContext *h)
/* get coded block pattern */
int cbp = get_ue_golomb(&h->gb);
- if (cbp > 63 || cbp < 0) {
+ if (cbp > 63U) {
av_log(h->avctx, AV_LOG_ERROR, "illegal inter cbp %d\n", cbp);
return AVERROR_INVALIDDATA;
}
@@ -672,7 +678,7 @@ static int decode_mb_i(AVSContext *h, int cbp_code)
/* get coded block pattern */
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I)
cbp_code = get_ue_golomb(gb);
- if (cbp_code > 63 || cbp_code < 0) {
+ if (cbp_code > 63U) {
av_log(h->avctx, AV_LOG_ERROR, "illegal intra cbp\n");
return AVERROR_INVALIDDATA;
}
@@ -759,7 +765,7 @@ static void decode_mb_p(AVSContext *h, enum cavs_mb mb_type)
h->col_type_base[h->mbidx] = mb_type;
}
-static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
+static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
{
int block;
enum cavs_sub_mb sub_type[4];
@@ -796,6 +802,8 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0);
break;
case B_8X8:
+#define TMP_UNUSED_INX 7
+ flags = 0;
for (block = 0; block < 4; block++)
sub_type[block] = get_bits(&h->gb, 2);
for (block = 0; block < 4; block++) {
@@ -803,11 +811,30 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
case B_SUB_DIRECT:
if (!h->col_type_base[h->mbidx]) {
/* intra MB at co-location, do in-plane prediction */
- ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3,
- MV_PRED_BSKIP, BLK_8X8, 1);
- ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS,
- mv_scan[block] - 3 + MV_BWD_OFFS,
- MV_PRED_BSKIP, BLK_8X8, 0);
+ if(flags==0) {
+ // if col-MB is a Intra MB, current Block size is 16x16.
+ // AVS standard section 9.9.1
+ if(block>0){
+ h->mv[TMP_UNUSED_INX ] = h->mv[MV_FWD_X0 ];
+ h->mv[TMP_UNUSED_INX + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS];
+ }
+ ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2,
+ MV_PRED_BSKIP, BLK_8X8, 1);
+ ff_cavs_mv(h, MV_FWD_X0+MV_BWD_OFFS,
+ MV_FWD_C2+MV_BWD_OFFS,
+ MV_PRED_BSKIP, BLK_8X8, 0);
+ if(block>0) {
+ flags = mv_scan[block];
+ h->mv[flags ] = h->mv[MV_FWD_X0 ];
+ h->mv[flags + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS];
+ h->mv[MV_FWD_X0 ] = h->mv[TMP_UNUSED_INX ];
+ h->mv[MV_FWD_X0 + MV_BWD_OFFS] = h->mv[TMP_UNUSED_INX + MV_BWD_OFFS];
+ } else
+ flags = MV_FWD_X0;
+ } else {
+ h->mv[mv_scan[block] ] = h->mv[flags ];
+ h->mv[mv_scan[block] + MV_BWD_OFFS] = h->mv[flags + MV_BWD_OFFS];
+ }
} else
mv_pred_direct(h, &h->mv[mv_scan[block]],
&h->col_mv[h->mbidx * 4 + block]);
@@ -823,6 +850,7 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
break;
}
}
+#undef TMP_UNUSED_INX
for (block = 0; block < 4; block++) {
if (sub_type[block] == B_SUB_BWD)
ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS,
@@ -831,7 +859,11 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
}
break;
default:
- assert((mb_type > B_SYM_16X16) && (mb_type < B_8X8));
+ if (mb_type <= B_SYM_16X16) {
+ av_log(h->avctx, AV_LOG_ERROR, "Invalid mb_type %d in B frame\n", mb_type);
+ return AVERROR_INVALIDDATA;
+ }
+ av_assert2(mb_type < B_8X8);
flags = ff_cavs_partition_flags[mb_type];
if (mb_type & 1) { /* 16x8 macroblock types */
if (flags & FWD0)
@@ -866,6 +898,8 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
if (mb_type != B_SKIP)
decode_residual_inter(h);
ff_cavs_filter(h, mb_type);
+
+ return 0;
}
/*****************************************************************************
@@ -878,12 +912,18 @@ static inline int decode_slice_header(AVSContext *h, GetBitContext *gb)
{
if (h->stc > 0xAF)
av_log(h->avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc);
+
+ if (h->stc >= h->mb_height) {
+ av_log(h->avctx, AV_LOG_ERROR, "stc 0x%02x is too large\n", h->stc);
+ return AVERROR_INVALIDDATA;
+ }
+
h->mby = h->stc;
h->mbidx = h->mby * h->mb_width;
/* mark top macroblocks as unavailable */
h->flags &= ~(B_AVAIL | C_AVAIL);
- if ((h->mby == 0) && (!h->qp_fixed)) {
+ if (!h->pic_qp_fixed) {
h->qp_fixed = get_bits1(gb);
h->qp = get_bits(gb, 6);
}
@@ -976,16 +1016,17 @@ static int decode_pic(AVSContext *h)
return AVERROR(ENOMEM);
}
- ff_cavs_init_pic(h);
+ if ((ret = ff_cavs_init_pic(h)) < 0)
+ return ret;
h->cur.poc = get_bits(&h->gb, 8) * 2;
/* get temporal distances and MV scaling factors */
if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) {
- h->dist[0] = (h->cur.poc - h->DPB[0].poc + 512) % 512;
+ h->dist[0] = (h->cur.poc - h->DPB[0].poc) & 511;
} else {
- h->dist[0] = (h->DPB[0].poc - h->cur.poc + 512) % 512;
+ h->dist[0] = (h->DPB[0].poc - h->cur.poc) & 511;
}
- h->dist[1] = (h->cur.poc - h->DPB[1].poc + 512) % 512;
+ h->dist[1] = (h->cur.poc - h->DPB[1].poc) & 511;
h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0;
h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0;
if (h->cur.f->pict_type == AV_PICTURE_TYPE_B) {
@@ -1005,6 +1046,7 @@ static int decode_pic(AVSContext *h)
skip_bits1(&h->gb); //advanced_pred_mode_disable
skip_bits1(&h->gb); //top_field_first
skip_bits1(&h->gb); //repeat_first_field
+ h->pic_qp_fixed =
h->qp_fixed = get_bits1(&h->gb);
h->qp = get_bits(&h->gb, 6);
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
@@ -1080,6 +1122,7 @@ static int decode_seq_header(AVSContext *h)
{
int frame_rate_code;
int width, height;
+ int ret;
h->profile = get_bits(&h->gb, 8);
h->level = get_bits(&h->gb, 8);
@@ -1092,24 +1135,36 @@ static int decode_seq_header(AVSContext *h)
"Width/height changing in CAVS");
return AVERROR_PATCHWELCOME;
}
- h->width = width;
- h->height = height;
-
+ if (width <= 0 || height <= 0) {
+ av_log(h->avctx, AV_LOG_ERROR, "Dimensions invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
skip_bits(&h->gb, 2); //chroma format
skip_bits(&h->gb, 3); //sample_precision
h->aspect_ratio = get_bits(&h->gb, 4);
frame_rate_code = get_bits(&h->gb, 4);
+ if (frame_rate_code == 0 || frame_rate_code > 13) {
+ av_log(h->avctx, AV_LOG_WARNING,
+ "frame_rate_code %d is invalid\n", frame_rate_code);
+ frame_rate_code = 1;
+ }
+
skip_bits(&h->gb, 18); //bit_rate_lower
skip_bits1(&h->gb); //marker_bit
skip_bits(&h->gb, 12); //bit_rate_upper
h->low_delay = get_bits1(&h->gb);
+
+ ret = ff_set_dimensions(h->avctx, width, height);
+ if (ret < 0)
+ return ret;
+
+ h->width = width;
+ h->height = height;
h->mb_width = (h->width + 15) >> 4;
h->mb_height = (h->height + 15) >> 4;
h->avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_code];
- h->avctx->width = h->width;
- h->avctx->height = h->height;
if (!h->top_qp)
- ff_cavs_init_top_lines(h);
+ return ff_cavs_init_top_lines(h);
return 0;
}
@@ -1138,12 +1193,17 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
return 0;
}
+ h->stc = 0;
+
buf_ptr = buf;
buf_end = buf + buf_size;
for(;;) {
buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &stc);
- if ((stc & 0xFFFFFE00) || buf_ptr == buf_end)
+ if ((stc & 0xFFFFFE00) || buf_ptr == buf_end) {
+ if (!h->stc)
+ av_log(h->avctx, AV_LOG_WARNING, "no frame decoded\n");
return FFMAX(0, buf_ptr - buf);
+ }
input_size = (buf_end - buf_ptr) * 8;
switch (stc) {
case CAVS_START_CODE:
@@ -1166,8 +1226,8 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
break;
*got_frame = 1;
if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) {
- if (h->DPB[1].f->data[0]) {
- if ((ret = av_frame_ref(data, h->DPB[1].f)) < 0)
+ if (h->DPB[!h->low_delay].f->data[0]) {
+ if ((ret = av_frame_ref(data, h->DPB[!h->low_delay].f)) < 0)
return ret;
} else {
*got_frame = 0;