You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
avcodec/svq3: Factor out decoding extradata
Reduces indentation and avoids an extra variable for whether a sequence header has been found. It also fixes potential undefined behaviour: NULL + 0 is undefined and happens when no extradata is available. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@@ -1114,71 +1114,22 @@ static void init_dequant4_coeff_table(SVQ3Context *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
static av_cold int svq3_decode_extradata(AVCodecContext *avctx, SVQ3Context *s,
|
||||||
|
int seqh_offset)
|
||||||
{
|
{
|
||||||
SVQ3Context *s = avctx->priv_data;
|
const uint8_t *extradata = avctx->extradata + seqh_offset;
|
||||||
int m, x, y;
|
unsigned int size = AV_RB32(extradata + 4);
|
||||||
unsigned char *extradata;
|
GetBitContext gb;
|
||||||
unsigned char *extradata_end;
|
|
||||||
unsigned int size;
|
|
||||||
int marker_found = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
s->cur_pic = &s->frames[0];
|
if (size > avctx->extradata_size - seqh_offset - 8)
|
||||||
s->last_pic = &s->frames[1];
|
|
||||||
s->next_pic = &s->frames[2];
|
|
||||||
|
|
||||||
s->cur_pic->f = av_frame_alloc();
|
|
||||||
s->last_pic->f = av_frame_alloc();
|
|
||||||
s->next_pic->f = av_frame_alloc();
|
|
||||||
if (!s->cur_pic->f || !s->last_pic->f || !s->next_pic->f)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
|
|
||||||
ff_h264dsp_init(&s->h264dsp, 8, 1);
|
|
||||||
ff_h264_pred_init(&s->hpc, AV_CODEC_ID_SVQ3, 8, 1);
|
|
||||||
ff_videodsp_init(&s->vdsp, 8);
|
|
||||||
|
|
||||||
|
|
||||||
avctx->bits_per_raw_sample = 8;
|
|
||||||
|
|
||||||
ff_hpeldsp_init(&s->hdsp, avctx->flags);
|
|
||||||
ff_tpeldsp_init(&s->tdsp);
|
|
||||||
|
|
||||||
avctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
|
||||||
avctx->color_range = AVCOL_RANGE_JPEG;
|
|
||||||
|
|
||||||
s->avctx = avctx;
|
|
||||||
s->halfpel_flag = 1;
|
|
||||||
s->thirdpel_flag = 1;
|
|
||||||
s->has_watermark = 0;
|
|
||||||
|
|
||||||
/* prowl for the "SEQH" marker in the extradata */
|
|
||||||
extradata = (unsigned char *)avctx->extradata;
|
|
||||||
extradata_end = avctx->extradata + avctx->extradata_size;
|
|
||||||
if (extradata) {
|
|
||||||
for (m = 0; m + 8 < avctx->extradata_size; m++) {
|
|
||||||
if (!memcmp(extradata, "SEQH", 4)) {
|
|
||||||
marker_found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
extradata++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if a match was found, parse the extra data */
|
|
||||||
if (marker_found) {
|
|
||||||
GetBitContext gb;
|
|
||||||
int frame_size_code;
|
|
||||||
int unk0, unk1, unk2, unk3, unk4;
|
|
||||||
int w,h;
|
|
||||||
|
|
||||||
size = AV_RB32(&extradata[4]);
|
|
||||||
if (size > extradata_end - extradata - 8)
|
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
init_get_bits(&gb, extradata + 8, size * 8);
|
extradata += 8;
|
||||||
|
init_get_bits(&gb, extradata, size * 8);
|
||||||
|
|
||||||
/* 'frame size code' and optional 'width, height' */
|
/* 'frame size code' and optional 'width, height' */
|
||||||
frame_size_code = get_bits(&gb, 3);
|
int frame_size_code = get_bits(&gb, 3);
|
||||||
|
int w, h;
|
||||||
switch (frame_size_code) {
|
switch (frame_size_code) {
|
||||||
case 0:
|
case 0:
|
||||||
w = 160;
|
w = 160;
|
||||||
@@ -1221,15 +1172,16 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
|||||||
s->thirdpel_flag = get_bits1(&gb);
|
s->thirdpel_flag = get_bits1(&gb);
|
||||||
|
|
||||||
/* unknown fields */
|
/* unknown fields */
|
||||||
unk0 = get_bits1(&gb);
|
int unk0 = get_bits1(&gb);
|
||||||
unk1 = get_bits1(&gb);
|
int unk1 = get_bits1(&gb);
|
||||||
unk2 = get_bits1(&gb);
|
int unk2 = get_bits1(&gb);
|
||||||
unk3 = get_bits1(&gb);
|
int unk3 = get_bits1(&gb);
|
||||||
|
|
||||||
s->low_delay = get_bits1(&gb);
|
s->low_delay = get_bits1(&gb);
|
||||||
|
avctx->has_b_frames = !s->low_delay;
|
||||||
|
|
||||||
/* unknown field */
|
/* unknown field */
|
||||||
unk4 = get_bits1(&gb);
|
int unk4 = get_bits1(&gb);
|
||||||
|
|
||||||
av_log(avctx, AV_LOG_DEBUG, "Unknown fields %d %d %d %d %d\n",
|
av_log(avctx, AV_LOG_DEBUG, "Unknown fields %d %d %d %d %d\n",
|
||||||
unk0, unk1, unk2, unk3, unk4);
|
unk0, unk1, unk2, unk3, unk4);
|
||||||
@@ -1238,8 +1190,10 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
s->has_watermark = get_bits1(&gb);
|
s->has_watermark = get_bits1(&gb);
|
||||||
avctx->has_b_frames = !s->low_delay;
|
|
||||||
if (s->has_watermark) {
|
if (!s->has_watermark)
|
||||||
|
return 0;
|
||||||
|
|
||||||
#if CONFIG_ZLIB
|
#if CONFIG_ZLIB
|
||||||
unsigned watermark_width = get_interleaved_ue_golomb(&gb);
|
unsigned watermark_width = get_interleaved_ue_golomb(&gb);
|
||||||
unsigned watermark_height = get_interleaved_ue_golomb(&gb);
|
unsigned watermark_height = get_interleaved_ue_golomb(&gb);
|
||||||
@@ -1250,23 +1204,23 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
|||||||
unsigned long buf_len = watermark_width *
|
unsigned long buf_len = watermark_width *
|
||||||
watermark_height * 4;
|
watermark_height * 4;
|
||||||
int offset = get_bits_count(&gb) + 7 >> 3;
|
int offset = get_bits_count(&gb) + 7 >> 3;
|
||||||
uint8_t *buf;
|
|
||||||
|
|
||||||
if (watermark_height <= 0 ||
|
if (watermark_height <= 0 ||
|
||||||
get_bits_left(&gb) <= 0 ||
|
get_bits_left(&gb) <= 0 ||
|
||||||
(uint64_t)watermark_width * 4 > UINT_MAX / watermark_height)
|
(uint64_t)watermark_width * 4 > UINT_MAX / watermark_height)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
buf = av_malloc(buf_len);
|
|
||||||
if (!buf)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
|
|
||||||
av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n",
|
av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n",
|
||||||
watermark_width, watermark_height);
|
watermark_width, watermark_height);
|
||||||
av_log(avctx, AV_LOG_DEBUG,
|
av_log(avctx, AV_LOG_DEBUG,
|
||||||
"u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n",
|
"u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n",
|
||||||
u1, u2, u3, u4, offset);
|
u1, u2, u3, u4, offset);
|
||||||
if (uncompress(buf, &buf_len, extradata + 8 + offset,
|
|
||||||
|
uint8_t *buf = av_malloc(buf_len);
|
||||||
|
if (!buf)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
if (uncompress(buf, &buf_len, extradata + offset,
|
||||||
size - offset) != Z_OK) {
|
size - offset) != Z_OK) {
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
"could not uncompress watermark logo\n");
|
"could not uncompress watermark logo\n");
|
||||||
@@ -1279,11 +1233,62 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
|||||||
av_log(avctx, AV_LOG_DEBUG,
|
av_log(avctx, AV_LOG_DEBUG,
|
||||||
"watermark key %#"PRIx32"\n", s->watermark_key);
|
"watermark key %#"PRIx32"\n", s->watermark_key);
|
||||||
av_free(buf);
|
av_free(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
#else
|
#else
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
"this svq3 file contains watermark which need zlib support compiled in\n");
|
"this svq3 file contains watermark which need zlib support compiled in\n");
|
||||||
return AVERROR(ENOSYS);
|
return AVERROR(ENOSYS);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static av_cold int svq3_decode_init(AVCodecContext *avctx)
|
||||||
|
{
|
||||||
|
SVQ3Context *s = avctx->priv_data;
|
||||||
|
int m, x, y;
|
||||||
|
unsigned char *extradata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
s->cur_pic = &s->frames[0];
|
||||||
|
s->last_pic = &s->frames[1];
|
||||||
|
s->next_pic = &s->frames[2];
|
||||||
|
|
||||||
|
s->cur_pic->f = av_frame_alloc();
|
||||||
|
s->last_pic->f = av_frame_alloc();
|
||||||
|
s->next_pic->f = av_frame_alloc();
|
||||||
|
if (!s->cur_pic->f || !s->last_pic->f || !s->next_pic->f)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
ff_h264dsp_init(&s->h264dsp, 8, 1);
|
||||||
|
ff_h264_pred_init(&s->hpc, AV_CODEC_ID_SVQ3, 8, 1);
|
||||||
|
ff_videodsp_init(&s->vdsp, 8);
|
||||||
|
|
||||||
|
|
||||||
|
avctx->bits_per_raw_sample = 8;
|
||||||
|
|
||||||
|
ff_hpeldsp_init(&s->hdsp, avctx->flags);
|
||||||
|
ff_tpeldsp_init(&s->tdsp);
|
||||||
|
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||||
|
avctx->color_range = AVCOL_RANGE_JPEG;
|
||||||
|
|
||||||
|
s->avctx = avctx;
|
||||||
|
s->halfpel_flag = 1;
|
||||||
|
s->thirdpel_flag = 1;
|
||||||
|
s->has_watermark = 0;
|
||||||
|
|
||||||
|
/* prowl for the "SEQH" marker in the extradata */
|
||||||
|
extradata = (unsigned char *)avctx->extradata;
|
||||||
|
if (extradata) {
|
||||||
|
for (m = 0; m + 8 < avctx->extradata_size; m++) {
|
||||||
|
if (!memcmp(extradata, "SEQH", 4)) {
|
||||||
|
/* if a match was found, parse the extra data */
|
||||||
|
ret = svq3_decode_extradata(avctx, s, m);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extradata++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user