Mercurial > libavformat.hg
changeset 5984:55c714a8fb00 libavformat
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
fields of common media header chunks (these can have different sizes depending
on the type of IFF file you read), better handle odd sizes (like RIFF, every
field is padded to word) and handle headerchunks after the BODY chunk.
Patch by Sebastian Vater <cdgs.basty googlemail com>.
author | rbultje |
---|---|
date | Tue, 27 Apr 2010 14:03:47 +0000 |
parents | cb7e1e218016 |
children | 35c3858d457f |
files | iff.c |
diffstat | 1 files changed, 23 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/iff.c Mon Apr 26 22:36:51 2010 +0000 +++ b/iff.c Tue Apr 27 14:03:47 2010 +0000 @@ -2,6 +2,7 @@ * IFF (.iff) file demuxer * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> * Copyright (c) 2010 Peter Ross <pross@xvid.org> + * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> * * This file is part of FFmpeg. * @@ -72,6 +73,7 @@ } bitmap_compression_type; typedef struct { + uint64_t body_pos; uint32_t body_size; uint32_t sent_bytes; uint32_t audio_frame_count; @@ -107,7 +109,6 @@ ByteIOContext *pb = s->pb; AVStream *st; uint32_t chunk_id, data_size; - int padding, done = 0; int compression = -1; char *buf; @@ -120,27 +121,34 @@ // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = get_le32(pb); - while(!done && !url_feof(pb)) { + while(!url_feof(pb)) { + uint64_t orig_pos; chunk_id = get_le32(pb); data_size = get_be32(pb); - padding = data_size & 1; + orig_pos = url_ftell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + + if (data_size < 14) + return AVERROR_INVALIDDATA; url_fskip(pb, 12); st->codec->sample_rate = get_be16(pb); + if (data_size >= 16) { url_fskip(pb, 1); compression = get_byte(pb); - url_fskip(pb, 4); + } break; case ID_BODY: + iff->body_pos = url_ftell(pb); iff->body_size = data_size; - done = 1; break; case ID_CHAN: + if (data_size < 4) + return AVERROR_INVALIDDATA; st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; break; @@ -155,16 +163,21 @@ case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + if (data_size <= 8) + return AVERROR_INVALIDDATA; st->codec->width = get_be16(pb); st->codec->height = get_be16(pb); url_fskip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = get_byte(pb); + if (data_size >= 11) { url_fskip(pb, 1); // masking compression = get_byte(pb); + } + if (data_size >= 16) { url_fskip(pb, 3); // paddding, transparent st->sample_aspect_ratio.num = get_byte(pb); st->sample_aspect_ratio.den = get_byte(pb); - url_fskip(pb, 4); // source page width, height + } break; case ID_ANNO: @@ -175,13 +188,13 @@ buf[data_size] = 0; av_metadata_set2(&s->metadata, "comment", buf, AV_METADATA_DONT_STRDUP_VAL); break; + } - default: - url_fseek(pb, data_size + padding, SEEK_CUR); - break; - } + url_fskip(pb, data_size - (url_ftell(pb) - orig_pos) + (data_size & 1)); } + url_fseek(pb, iff->body_pos, SEEK_SET); + switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: av_set_pts_info(st, 32, 1, st->codec->sample_rate);