X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavformat%2Faacdec.c;h=00ca2319cae8e88f900fd09871c1bbd9190276d1;hb=4e7e30bbe0fbe54d44cadc398d4071905d3063e8;hp=685458b9114d03864fb6d962227d1debcb747dff;hpb=c2631dfd0a0a12050cc1765fd41702c5e93abee5;p=ffmpeg diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 685458b9114..00ca2319cae 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" @@ -30,7 +31,7 @@ #define ADTS_HEADER_SIZE 7 -static int adts_aac_probe(AVProbeData *p) +static int adts_aac_probe(const AVProbeData *p) { int max_frames = 0, first_frames = 0; int fsize, frames; @@ -79,10 +80,31 @@ static int adts_aac_probe(AVProbeData *p) return 0; } +static int adts_aac_resync(AVFormatContext *s) +{ + uint16_t state; + + // skip data until an ADTS frame is found + state = avio_r8(s->pb); + while (!avio_feof(s->pb) && avio_tell(s->pb) < s->probesize) { + state = (state << 8) | avio_r8(s->pb); + if ((state >> 4) != 0xFFF) + continue; + avio_seek(s->pb, -2, SEEK_CUR); + break; + } + if (s->pb->eof_reached) + return AVERROR_EOF; + if ((state >> 4) != 0xFFF) + return AVERROR_INVALIDDATA; + + return 0; +} + static int adts_aac_read_header(AVFormatContext *s) { AVStream *st; - uint16_t state; + int ret; st = avformat_new_stream(s, NULL); if (!st) @@ -100,17 +122,9 @@ static int adts_aac_read_header(AVFormatContext *s) avio_seek(s->pb, cur, SEEK_SET); } - // skip data until the first ADTS frame is found - state = avio_r8(s->pb); - while (!avio_feof(s->pb) && avio_tell(s->pb) < s->probesize) { - state = (state << 8) | avio_r8(s->pb); - if ((state >> 4) != 0xFFF) - continue; - avio_seek(s->pb, -2, SEEK_CUR); - break; - } - if ((state >> 4) != 0xFFF) - return AVERROR_INVALIDDATA; + ret = adts_aac_resync(s); + if (ret < 0) + return ret; // LCM of all possible ADTS sample rates avpriv_set_pts_info(st, 64, 1, 28224000); @@ -154,17 +168,8 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, fsize; - // Parse all the ID3 headers between frames - while (1) { - ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); - if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { - if ((ret = handle_id3(s, pkt)) >= 0) { - continue; - } - } - break; - } - +retry: + ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); if (ret < 0) return ret; @@ -174,8 +179,24 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) } if ((AV_RB16(pkt->data) >> 4) != 0xfff) { - av_packet_unref(pkt); - return AVERROR_INVALIDDATA; + // Parse all the ID3 headers between frames + int append = ID3v2_HEADER_SIZE - ADTS_HEADER_SIZE; + + av_assert2(append > 0); + ret = av_append_packet(s->pb, pkt, append); + if (ret != append) { + av_packet_unref(pkt); + return AVERROR(EIO); + } + if (!ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + av_packet_unref(pkt); + ret = adts_aac_resync(s); + } else + ret = handle_id3(s, pkt); + if (ret < 0) + return ret; + + goto retry; } fsize = (AV_RB32(pkt->data + 3) >> 13) & 0x1FFF;