Merge commit '5c54fc6195e52c329b88cf5a56d18628f0ee0029' into release/1.1
* commit '5c54fc6195e52c329b88cf5a56d18628f0ee0029': Prepare for 9.8 RELEASE update Changelog smacker: check frame size validity smacker: pad the extradata allocation smacker: check the return value of smacker_decode_tree smacker: fix an off by one in huff.length computation 4xm: do not overread the prestream buffer 4xm: validate the buffer size before parsing it 4xm: reject frames not compatible with the declared version 4xm: drop pointless assert 4xm: forward errors from decode_p_block 4xm: fold last_picture lazy allocation in decode_p_frame 4xm: do not overread while parsing header 4xm: refactor fourxm_read_header 4xm: K&R formatting cosmetics 4xm: use the correct logging context Conflicts: Changelog RELEASE libavcodec/4xm.c libavcodec/smacker.c libavformat/4xm.c libavformat/smacker.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
21
Changelog
21
Changelog
@@ -2,6 +2,27 @@ Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
|
||||
Most of the following fixes resulted from test samples that the Google
|
||||
Security Team has kindly made available to us:
|
||||
|
||||
- 4xm: fix several programming errors to avoid crashes, etc.
|
||||
- apetag: use int64_t for filesize
|
||||
- jpegls: Fix invalid writes to memory
|
||||
- ljpeg: use the correct number of components in YUV
|
||||
- mjpeg: Validate sampling factors
|
||||
- mjpegdec: properly report unsupported disabled features
|
||||
- mjpegdec: validate parameters in mjpeg_decode_scan_progressive_ac
|
||||
- mpegvideo: allocate sufficiently large scratch buffer for interlaced vid
|
||||
- pixdesc: mark gray8 as pseudopal
|
||||
- smacker: fix several programming errors to avoid crashes, etc.
|
||||
- tiff: do not overread the source buffer
|
||||
- vmd: drop incomplete chunks and spurious samples
|
||||
- vmdav: convert to bytestream2 to avoid invalid reads and writes
|
||||
- wavpack: check packet size early
|
||||
- wavpack: use bytestream2 in wavpack_decode_block
|
||||
- wavpack: validate samples size parsed in wavpack_decode_block
|
||||
|
||||
- aac: check the maximum number of channels to avoid invalid writes
|
||||
- indeo3: fix off by one in MV validity check
|
||||
- id3v2: check for end of file while unescaping tags to avoid invalid
|
||||
|
||||
116
libavcodec/4xm.c
116
libavcodec/4xm.c
@@ -328,11 +328,11 @@ static inline void mcdc(uint16_t *dst, const uint16_t *src, int log2w,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
av_assert2(0);
|
||||
av_assert0(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src,
|
||||
static int decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src,
|
||||
int log2w, int log2h, int stride)
|
||||
{
|
||||
const int index = size2index[log2h][log2w];
|
||||
@@ -342,57 +342,64 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src,
|
||||
BLOCK_TYPE_VLC_BITS, 1);
|
||||
uint16_t *start = (uint16_t *)f->last_picture.data[0];
|
||||
uint16_t *end = start + stride * (f->avctx->height - h + 1) - (1 << log2w);
|
||||
int ret;
|
||||
|
||||
av_assert2(code >= 0 && code <= 6);
|
||||
av_assert0(code >= 0 && code <= 6 && log2w >= 0);
|
||||
|
||||
if (code == 0) {
|
||||
if (bytestream2_get_bytes_left(&f->g) < 1) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
src += f->mv[bytestream2_get_byteu(&f->g)];
|
||||
if (start > src || src > end) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
mcdc(dst, src, log2w, h, stride, 1, 0);
|
||||
} else if (code == 1) {
|
||||
log2h--;
|
||||
decode_p_block(f, dst, src, log2w, log2h, stride);
|
||||
decode_p_block(f, dst + (stride << log2h),
|
||||
src + (stride << log2h), log2w, log2h, stride);
|
||||
if ((ret = decode_p_block(f, dst, src, log2w, log2h, stride)) < 0)
|
||||
return ret;
|
||||
if ((ret = decode_p_block(f, dst + (stride << log2h),
|
||||
src + (stride << log2h),
|
||||
log2w, log2h, stride)) < 0)
|
||||
return ret;
|
||||
} else if (code == 2) {
|
||||
log2w--;
|
||||
decode_p_block(f, dst , src, log2w, log2h, stride);
|
||||
decode_p_block(f, dst + (1 << log2w),
|
||||
src + (1 << log2w), log2w, log2h, stride);
|
||||
if ((ret = decode_p_block(f, dst , src, log2w, log2h, stride)) < 0)
|
||||
return ret;
|
||||
if ((ret = decode_p_block(f, dst + (1 << log2w),
|
||||
src + (1 << log2w),
|
||||
log2w, log2h, stride)) < 0)
|
||||
return ret;
|
||||
} else if (code == 3 && f->version < 2) {
|
||||
mcdc(dst, src, log2w, h, stride, 1, 0);
|
||||
} else if (code == 4) {
|
||||
if (bytestream2_get_bytes_left(&f->g) < 1) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
src += f->mv[bytestream2_get_byteu(&f->g)];
|
||||
if (start > src || src > end) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (bytestream2_get_bytes_left(&f->g2) < 2){
|
||||
av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
mcdc(dst, src, log2w, h, stride, 1, bytestream2_get_le16u(&f->g2));
|
||||
} else if (code == 5) {
|
||||
if (bytestream2_get_bytes_left(&f->g2) < 2) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
mcdc(dst, src, log2w, h, stride, 0, bytestream2_get_le16u(&f->g2));
|
||||
} else if (code == 6) {
|
||||
if (bytestream2_get_bytes_left(&f->g2) < 4) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
|
||||
return;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (log2w) {
|
||||
dst[0] = bytestream2_get_le16u(&f->g2);
|
||||
@@ -402,6 +409,7 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src,
|
||||
dst[stride] = bytestream2_get_le16u(&f->g2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)
|
||||
@@ -414,8 +422,20 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)
|
||||
const int stride = f->current_picture.linesize[0] >> 1;
|
||||
unsigned int bitstream_size, bytestream_size, wordstream_size, extra,
|
||||
bytestream_offset, wordstream_offset;
|
||||
int ret;
|
||||
|
||||
if (!f->last_picture.data[0]) {
|
||||
if ((ret = ff_get_buffer(f->avctx, &f->last_picture)) < 0) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return ret;
|
||||
}
|
||||
for (y=0; y<f->avctx->height; y++)
|
||||
memset(f->last_picture.data[0] + y*f->last_picture.linesize[0], 0, 2*f->avctx->width);
|
||||
}
|
||||
|
||||
if (f->version > 1) {
|
||||
if (length < 20)
|
||||
return AVERROR_INVALIDDATA;
|
||||
extra = 20;
|
||||
if (length < extra)
|
||||
return -1;
|
||||
@@ -459,7 +479,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)
|
||||
|
||||
for (y = 0; y < height; y += 8) {
|
||||
for (x = 0; x < width; x += 8)
|
||||
decode_p_block(f, dst + x, src + x, 3, 3, stride);
|
||||
if ((ret = decode_p_block(f, dst + x, src + x, 3, 3, stride)) < 0)
|
||||
return ret;
|
||||
src += 8 * stride;
|
||||
dst += 8 * stride;
|
||||
}
|
||||
@@ -579,7 +600,8 @@ static int decode_i_mb(FourXContext *f)
|
||||
}
|
||||
|
||||
static const uint8_t *read_huffman_tables(FourXContext *f,
|
||||
const uint8_t * const buf, int buf_size)
|
||||
const uint8_t * const buf,
|
||||
int buf_size)
|
||||
{
|
||||
int frequency[512] = { 0 };
|
||||
uint8_t flag[512];
|
||||
@@ -598,8 +620,11 @@ static const uint8_t *read_huffman_tables(FourXContext *f,
|
||||
for (;;) {
|
||||
int i;
|
||||
|
||||
if (start <= end && ptr_end - ptr < end - start + 1 + 1)
|
||||
if (ptr_end - ptr < FFMAX(end - start + 1, 0) + 1) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "invalid data in read_huffman_tables\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = start; i <= end; i++)
|
||||
frequency[i] = *ptr++;
|
||||
start = *ptr++;
|
||||
@@ -701,9 +726,9 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length)
|
||||
color[1] = bytestream2_get_le16u(&g3);
|
||||
|
||||
if (color[0] & 0x8000)
|
||||
av_log(NULL, AV_LOG_ERROR, "unk bit 1\n");
|
||||
av_log(f->avctx, AV_LOG_ERROR, "unk bit 1\n");
|
||||
if (color[1] & 0x8000)
|
||||
av_log(NULL, AV_LOG_ERROR, "unk bit 2\n");
|
||||
av_log(f->avctx, AV_LOG_ERROR, "unk bit 2\n");
|
||||
|
||||
color[2] = mix(color[0], color[1]);
|
||||
color[3] = mix(color[1], color[0]);
|
||||
@@ -748,7 +773,7 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length)
|
||||
return -1;
|
||||
}
|
||||
|
||||
prestream = read_huffman_tables(f, prestream, buf + length - prestream);
|
||||
prestream = read_huffman_tables(f, prestream, prestream_size);
|
||||
if (!prestream) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "Error reading Huffman tables.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
@@ -795,30 +820,38 @@ static int decode_frame(AVCodecContext *avctx, void *data,
|
||||
AVFrame *p, temp;
|
||||
int i, frame_4cc, frame_size;
|
||||
|
||||
if (buf_size < 12)
|
||||
if (buf_size < 20)
|
||||
return AVERROR_INVALIDDATA;
|
||||
frame_4cc = AV_RL32(buf);
|
||||
if (buf_size != AV_RL32(buf + 4) + 8 || buf_size < 20)
|
||||
|
||||
av_assert0(avctx->width % 16 == 0 && avctx->height % 16 == 0);
|
||||
|
||||
if (buf_size < AV_RL32(buf + 4) + 8) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n",
|
||||
buf_size, AV_RL32(buf + 4));
|
||||
|
||||
if (frame_4cc == AV_RL32("cfrm")) {
|
||||
int free_index = -1;
|
||||
const int data_size = buf_size - 20;
|
||||
const int id = AV_RL32(buf + 12);
|
||||
const int whole_size = AV_RL32(buf + 16);
|
||||
CFrameBuffer *cfrm;
|
||||
|
||||
if (data_size < 0 || whole_size < 0) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
frame_4cc = AV_RL32(buf);
|
||||
|
||||
if (frame_4cc == AV_RL32("cfrm")) {
|
||||
int free_index = -1;
|
||||
int id, whole_size;
|
||||
const int data_size = buf_size - 20;
|
||||
CFrameBuffer *cfrm;
|
||||
|
||||
if (f->version <= 1) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "cfrm in version %d\n", f->version);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
id = AV_RL32(buf + 12);
|
||||
whole_size = AV_RL32(buf + 16);
|
||||
|
||||
if (data_size < 0 || whole_size < 0) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
for (i = 0; i < CFRAME_BUFFER_COUNT; i++)
|
||||
if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number)
|
||||
av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n",
|
||||
@@ -859,6 +892,9 @@ static int decode_frame(AVCodecContext *avctx, void *data,
|
||||
av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %d\n",
|
||||
id, avctx->frame_number);
|
||||
|
||||
if (f->version <= 1)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
cfrm->size = cfrm->id = 0;
|
||||
frame_4cc = AV_RL32("pfrm");
|
||||
} else
|
||||
@@ -897,16 +933,6 @@ static int decode_frame(AVCodecContext *avctx, void *data,
|
||||
return -1;
|
||||
}
|
||||
} else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) {
|
||||
if (!f->last_picture.data[0]) {
|
||||
f->last_picture.reference = 3;
|
||||
if (ff_get_buffer(avctx, &f->last_picture) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
for (i=0; i<avctx->height; i++)
|
||||
memset(f->last_picture.data[0] + i*f->last_picture.linesize[0], 0, 2*avctx->width);
|
||||
}
|
||||
|
||||
p->pict_type = AV_PICTURE_TYPE_P;
|
||||
if (decode_p_frame(f, buf, frame_size) < 0) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n");
|
||||
|
||||
@@ -257,7 +257,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int
|
||||
ctx.recode2 = tmp2.values;
|
||||
ctx.last = last;
|
||||
|
||||
huff.length = ((size + 3) >> 2) + 3;
|
||||
huff.length = ((size + 3) >> 2) + 4;
|
||||
huff.maxlength = 0;
|
||||
huff.current = 0;
|
||||
huff.values = av_mallocz(huff.length * sizeof(int));
|
||||
@@ -661,9 +661,16 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data,
|
||||
h[i].lengths = av_mallocz(256 * sizeof(int));
|
||||
h[i].values = av_mallocz(256 * sizeof(int));
|
||||
skip_bits1(&gb);
|
||||
res = smacker_decode_tree(&gb, &h[i], 0, 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (smacker_decode_tree(&gb, &h[i], 0, 0) < 0) {
|
||||
for (; i >= 0; i--) {
|
||||
if (vlc[i].table)
|
||||
ff_free_vlc(&vlc[i]);
|
||||
av_free(h[i].bits);
|
||||
av_free(h[i].lengths);
|
||||
av_free(h[i].values);
|
||||
}
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
skip_bits1(&gb);
|
||||
if(h[i].current > 1) {
|
||||
res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length,
|
||||
|
||||
@@ -72,8 +72,6 @@ typedef struct AudioTrack {
|
||||
} AudioTrack;
|
||||
|
||||
typedef struct FourxmDemuxContext {
|
||||
int width;
|
||||
int height;
|
||||
int video_stream_index;
|
||||
int track_count;
|
||||
AudioTrack *tracks;
|
||||
@@ -91,6 +89,108 @@ static int fourxm_probe(AVProbeData *p)
|
||||
return AVPROBE_SCORE_MAX;
|
||||
}
|
||||
|
||||
static int parse_vtrk(AVFormatContext *s,
|
||||
FourxmDemuxContext *fourxm, uint8_t *buf, int size,
|
||||
int left)
|
||||
{
|
||||
AVStream *st;
|
||||
/* check that there is enough data */
|
||||
if (size != vtrk_SIZE || left < size + 8) {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* allocate a new AVStream */
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
avpriv_set_pts_info(st, 60, 1, fourxm->fps);
|
||||
|
||||
fourxm->video_stream_index = st->index;
|
||||
|
||||
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
st->codec->codec_id = AV_CODEC_ID_4XM;
|
||||
st->codec->extradata_size = 4;
|
||||
st->codec->extradata = av_malloc(4);
|
||||
AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
|
||||
st->codec->width = AV_RL32(buf + 36);
|
||||
st->codec->height = AV_RL32(buf + 40);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int parse_strk(AVFormatContext *s,
|
||||
FourxmDemuxContext *fourxm, uint8_t *buf, int size,
|
||||
int left)
|
||||
{
|
||||
AVStream *st;
|
||||
int track;
|
||||
/* check that there is enough data */
|
||||
if (size != strk_SIZE || left < size + 8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
track = AV_RL32(buf + 8);
|
||||
if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
|
||||
av_log(s, AV_LOG_ERROR, "current_track too large\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (track + 1 > fourxm->track_count) {
|
||||
fourxm->tracks = av_realloc_f(fourxm->tracks, track + 1, sizeof(AudioTrack));
|
||||
if (!fourxm->tracks)
|
||||
return AVERROR(ENOMEM);
|
||||
memset(&fourxm->tracks[fourxm->track_count], 0,
|
||||
sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
|
||||
fourxm->track_count = track + 1;
|
||||
}
|
||||
fourxm->tracks[track].adpcm = AV_RL32(buf + 12);
|
||||
fourxm->tracks[track].channels = AV_RL32(buf + 36);
|
||||
fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
|
||||
fourxm->tracks[track].bits = AV_RL32(buf + 44);
|
||||
fourxm->tracks[track].audio_pts = 0;
|
||||
|
||||
if (fourxm->tracks[track].channels <= 0 ||
|
||||
fourxm->tracks[track].sample_rate <= 0 ||
|
||||
fourxm->tracks[track].bits < 0) {
|
||||
av_log(s, AV_LOG_ERROR, "audio header invalid\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) {
|
||||
av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* allocate a new AVStream */
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
st->id = track;
|
||||
avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
|
||||
|
||||
fourxm->tracks[track].stream_index = st->index;
|
||||
|
||||
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
st->codec->codec_tag = 0;
|
||||
st->codec->channels = fourxm->tracks[track].channels;
|
||||
st->codec->sample_rate = fourxm->tracks[track].sample_rate;
|
||||
st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
|
||||
st->codec->bit_rate = st->codec->channels *
|
||||
st->codec->sample_rate *
|
||||
st->codec->bits_per_coded_sample;
|
||||
st->codec->block_align = st->codec->channels *
|
||||
st->codec->bits_per_coded_sample;
|
||||
|
||||
if (fourxm->tracks[track].adpcm){
|
||||
st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
|
||||
} else if (st->codec->bits_per_coded_sample == 8) {
|
||||
st->codec->codec_id = AV_CODEC_ID_PCM_U8;
|
||||
} else
|
||||
st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fourxm_read_header(AVFormatContext *s)
|
||||
{
|
||||
AVIOContext *pb = s->pb;
|
||||
@@ -100,7 +200,6 @@ static int fourxm_read_header(AVFormatContext *s)
|
||||
FourxmDemuxContext *fourxm = s->priv_data;
|
||||
unsigned char *header;
|
||||
int i, ret;
|
||||
AVStream *st;
|
||||
|
||||
fourxm->track_count = 0;
|
||||
fourxm->tracks = NULL;
|
||||
@@ -119,7 +218,7 @@ static int fourxm_read_header(AVFormatContext *s)
|
||||
header = av_malloc(header_size);
|
||||
if (!header)
|
||||
return AVERROR(ENOMEM);
|
||||
if (avio_read(pb, header, header_size) != header_size){
|
||||
if (avio_read(pb, header, header_size) != header_size) {
|
||||
av_free(header);
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
@@ -134,116 +233,31 @@ static int fourxm_read_header(AVFormatContext *s)
|
||||
}
|
||||
|
||||
if (fourcc_tag == std__TAG) {
|
||||
if (header_size < i + 16) {
|
||||
if (header_size - i < 16) {
|
||||
av_log(s, AV_LOG_ERROR, "std TAG truncated\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
fourxm->fps = av_int2float(AV_RL32(&header[i + 12]));
|
||||
} else if (fourcc_tag == vtrk_TAG) {
|
||||
/* check that there is enough data */
|
||||
if (size != vtrk_SIZE) {
|
||||
ret= AVERROR_INVALIDDATA;
|
||||
if ((ret = parse_vtrk(s, fourxm, header + i, size,
|
||||
header_size - i)) < 0)
|
||||
goto fail;
|
||||
}
|
||||
fourxm->width = AV_RL32(&header[i + 36]);
|
||||
fourxm->height = AV_RL32(&header[i + 40]);
|
||||
|
||||
/* allocate a new AVStream */
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st){
|
||||
ret= AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
avpriv_set_pts_info(st, 60, 1, fourxm->fps);
|
||||
|
||||
fourxm->video_stream_index = st->index;
|
||||
|
||||
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
st->codec->codec_id = AV_CODEC_ID_4XM;
|
||||
st->codec->extradata_size = 4;
|
||||
st->codec->extradata = av_malloc(4);
|
||||
AV_WL32(st->codec->extradata, AV_RL32(&header[i + 16]));
|
||||
st->codec->width = fourxm->width;
|
||||
st->codec->height = fourxm->height;
|
||||
|
||||
i += 8 + size;
|
||||
} else if (fourcc_tag == strk_TAG) {
|
||||
int current_track;
|
||||
/* check that there is enough data */
|
||||
if (size != strk_SIZE) {
|
||||
ret= AVERROR_INVALIDDATA;
|
||||
if ((ret = parse_strk(s, fourxm, header + i, size,
|
||||
header_size - i)) < 0)
|
||||
goto fail;
|
||||
}
|
||||
current_track = AV_RL32(&header[i + 8]);
|
||||
if((unsigned)current_track >= UINT_MAX / sizeof(AudioTrack) - 1){
|
||||
av_log(s, AV_LOG_ERROR, "current_track too large\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
if (current_track + 1 > fourxm->track_count) {
|
||||
fourxm->tracks = av_realloc_f(fourxm->tracks,
|
||||
sizeof(AudioTrack),
|
||||
current_track + 1);
|
||||
if (!fourxm->tracks) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
memset(&fourxm->tracks[fourxm->track_count], 0,
|
||||
sizeof(AudioTrack) * (current_track + 1 - fourxm->track_count));
|
||||
fourxm->track_count = current_track + 1;
|
||||
}
|
||||
fourxm->tracks[current_track].adpcm = AV_RL32(&header[i + 12]);
|
||||
fourxm->tracks[current_track].channels = AV_RL32(&header[i + 36]);
|
||||
fourxm->tracks[current_track].sample_rate = AV_RL32(&header[i + 40]);
|
||||
fourxm->tracks[current_track].bits = AV_RL32(&header[i + 44]);
|
||||
fourxm->tracks[current_track].audio_pts = 0;
|
||||
if( fourxm->tracks[current_track].channels <= 0
|
||||
|| fourxm->tracks[current_track].sample_rate <= 0
|
||||
|| fourxm->tracks[current_track].bits < 0){
|
||||
av_log(s, AV_LOG_ERROR, "audio header invalid\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
if(!fourxm->tracks[current_track].adpcm && fourxm->tracks[current_track].bits<8){
|
||||
av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
i += 8 + size;
|
||||
|
||||
/* allocate a new AVStream */
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st){
|
||||
ret= AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
st->id = current_track;
|
||||
avpriv_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate);
|
||||
|
||||
fourxm->tracks[current_track].stream_index = st->index;
|
||||
|
||||
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
st->codec->codec_tag = 0;
|
||||
st->codec->channels = fourxm->tracks[current_track].channels;
|
||||
st->codec->sample_rate = fourxm->tracks[current_track].sample_rate;
|
||||
st->codec->bits_per_coded_sample = fourxm->tracks[current_track].bits;
|
||||
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
|
||||
st->codec->bits_per_coded_sample;
|
||||
st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
|
||||
if (fourxm->tracks[current_track].adpcm){
|
||||
st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
|
||||
}else if (st->codec->bits_per_coded_sample == 8){
|
||||
st->codec->codec_id = AV_CODEC_ID_PCM_U8;
|
||||
}else
|
||||
st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip over the LIST-MOVI chunk (which is where the stream should be */
|
||||
GET_LIST_HEADER();
|
||||
if (fourcc_tag != MOVI_TAG){
|
||||
ret= AVERROR_INVALIDDATA;
|
||||
if (fourcc_tag != MOVI_TAG) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -272,7 +286,6 @@ static int fourxm_read_packet(AVFormatContext *s,
|
||||
int audio_frame_count;
|
||||
|
||||
while (!packet_read) {
|
||||
|
||||
if ((ret = avio_read(s->pb, header, 8)) < 0)
|
||||
return ret;
|
||||
fourcc_tag = AV_RL32(&header[0]);
|
||||
@@ -280,10 +293,9 @@ static int fourxm_read_packet(AVFormatContext *s,
|
||||
if (url_feof(pb))
|
||||
return AVERROR(EIO);
|
||||
switch (fourcc_tag) {
|
||||
|
||||
case LIST_TAG:
|
||||
/* this is a good time to bump the video pts */
|
||||
fourxm->video_pts ++;
|
||||
fourxm->video_pts++;
|
||||
|
||||
/* skip the LIST-* tag and move on to the next fourcc */
|
||||
avio_rl32(pb);
|
||||
@@ -305,20 +317,21 @@ static int fourxm_read_packet(AVFormatContext *s,
|
||||
memcpy(pkt->data, header, 8);
|
||||
ret = avio_read(s->pb, &pkt->data[8], size);
|
||||
|
||||
if (ret < 0){
|
||||
if (ret < 0) {
|
||||
av_free_packet(pkt);
|
||||
}else
|
||||
} else
|
||||
packet_read = 1;
|
||||
break;
|
||||
|
||||
case snd__TAG:
|
||||
track_number = avio_rl32(pb);
|
||||
avio_skip(pb, 4);
|
||||
size-=8;
|
||||
size -= 8;
|
||||
|
||||
if (track_number < fourxm->track_count && fourxm->tracks[track_number].channels>0) {
|
||||
ret= av_get_packet(s->pb, pkt, size);
|
||||
if(ret<0)
|
||||
if (track_number < fourxm->track_count &&
|
||||
fourxm->tracks[track_number].channels > 0) {
|
||||
ret = av_get_packet(s->pb, pkt, size);
|
||||
if (ret < 0)
|
||||
return AVERROR(EIO);
|
||||
pkt->stream_index =
|
||||
fourxm->tracks[track_number].stream_index;
|
||||
@@ -328,17 +341,14 @@ static int fourxm_read_packet(AVFormatContext *s,
|
||||
/* pts accounting */
|
||||
audio_frame_count = size;
|
||||
if (fourxm->tracks[track_number].adpcm)
|
||||
audio_frame_count -=
|
||||
2 * (fourxm->tracks[track_number].channels);
|
||||
audio_frame_count /=
|
||||
fourxm->tracks[track_number].channels;
|
||||
if (fourxm->tracks[track_number].adpcm){
|
||||
audio_frame_count -= 2 * (fourxm->tracks[track_number].channels);
|
||||
audio_frame_count /= fourxm->tracks[track_number].channels;
|
||||
if (fourxm->tracks[track_number].adpcm) {
|
||||
audio_frame_count *= 2;
|
||||
}else
|
||||
} else
|
||||
audio_frame_count /=
|
||||
(fourxm->tracks[track_number].bits / 8);
|
||||
fourxm->tracks[track_number].audio_pts += audio_frame_count;
|
||||
|
||||
} else {
|
||||
avio_skip(pb, size);
|
||||
}
|
||||
|
||||
@@ -210,7 +210,8 @@ static int smacker_read_header(AVFormatContext *s)
|
||||
|
||||
|
||||
/* load trees to extradata, they will be unpacked by decoder */
|
||||
st->codec->extradata = av_malloc(smk->treesize + 16 + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
st->codec->extradata = av_mallocz(smk->treesize + 16 +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
st->codec->extradata_size = smk->treesize + 16;
|
||||
if(!st->codec->extradata){
|
||||
av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16);
|
||||
@@ -305,12 +306,14 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
/* if audio chunks are present, put them to stack and retrieve later */
|
||||
for(i = 0; i < 7; i++) {
|
||||
if(flags & 1) {
|
||||
unsigned int size;
|
||||
uint32_t size;
|
||||
uint8_t *tmpbuf;
|
||||
|
||||
size = avio_rl32(s->pb) - 4;
|
||||
if(size + 4L > frame_size)
|
||||
if (!size || size + 4L > frame_size) {
|
||||
av_log(s, AV_LOG_ERROR, "Invalid audio part size\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
frame_size -= size;
|
||||
frame_size -= 4;
|
||||
smk->curstream++;
|
||||
|
||||
Reference in New Issue
Block a user