X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fape.c;h=4d13e4836c3b5155aadb10f2cf60560ed5441c28;hb=e30b3e59a4f3004337cb1623b2aac988ce52b93f;hp=d7c1447b018b9439fe9e084bb1503ba92bfa8d70;hpb=b0a4e5f9e765dc601a62f87cf3510ac381c3c4c6;p=ffmpeg diff --git a/libavformat/ape.c b/libavformat/ape.c index d7c1447b018..4d13e4836c3 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -24,10 +24,9 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "internal.h" #include "apetag.h" -#define ENABLE_DEBUG 0 - /* The earliest and latest file formats supported by this library */ #define APE_MIN_VERSION 3950 #define APE_MAX_VERSION 3990 @@ -96,7 +95,7 @@ static int ape_probe(AVProbeData * p) static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) { -#if ENABLE_DEBUG +#ifdef DEBUG int i; av_log(s, AV_LOG_DEBUG, "Descriptor Block:\n\n"); @@ -131,9 +130,11 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) } else { for (i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t); i++) { if (i < ape_ctx->totalframes - 1) { - av_log(s, AV_LOG_DEBUG, "%8d %d (%d bytes)\n", i, ape_ctx->seektable[i], ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]); + av_log(s, AV_LOG_DEBUG, "%8d %"PRIu32" (%"PRIu32" bytes)\n", + i, ape_ctx->seektable[i], + ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]); } else { - av_log(s, AV_LOG_DEBUG, "%8d %d\n", i, ape_ctx->seektable[i]); + av_log(s, AV_LOG_DEBUG, "%8d %"PRIu32"\n", i, ape_ctx->seektable[i]); } } } @@ -151,15 +152,15 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) #endif } -static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) +static int ape_read_header(AVFormatContext * s) { AVIOContext *pb = s->pb; APEContext *ape = s->priv_data; AVStream *st; uint32_t tag; int i; - int total_blocks; - int64_t pts; + int total_blocks, final_size = 0; + int64_t pts, file_size; /* Skip any leading junk such as id3v2 tags */ ape->junklength = avio_tell(pb); @@ -171,7 +172,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->fileversion = avio_rl16(pb); if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) { - av_log(s, AV_LOG_ERROR, "Unsupported file version - %"PRId16".%02"PRId16"\n", + av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10); return -1; } @@ -255,7 +256,8 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) return -1; } if (ape->seektablelength && (ape->seektablelength / sizeof(*ape->seektable)) < ape->totalframes) { - av_log(s, AV_LOG_ERROR, "Number of seek entries is less than number of frames: %ld vs. %"PRIu32"\n", + av_log(s, AV_LOG_ERROR, + "Number of seek entries is less than number of frames: %zu vs. %"PRIu32"\n", ape->seektablelength / sizeof(*ape->seektable), ape->totalframes); return AVERROR_INVALIDDATA; } @@ -272,6 +274,8 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) if (ape->seektablelength > 0) { ape->seektable = av_malloc(ape->seektablelength); + if (!ape->seektable) + return AVERROR(ENOMEM); for (i = 0; i < ape->seektablelength / sizeof(uint32_t); i++) ape->seektable[i] = avio_rl32(pb); } @@ -285,8 +289,17 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos; ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3; } - ape->frames[ape->totalframes - 1].size = ape->finalframeblocks * 4; ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks; + /* calculate final packet size from total file size, if available */ + file_size = avio_size(pb); + if (file_size > 0) { + final_size = file_size - ape->frames[ape->totalframes - 1].pos - + ape->wavtaillength; + final_size -= final_size & 3; + } + if (file_size <= 0 || final_size <= 0) + final_size = ape->finalframeblocks * 8; + ape->frames[ape->totalframes - 1].size = final_size; for (i = 0; i < ape->totalframes; i++) { if(ape->frames[i].skip){ @@ -310,7 +323,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) ape->compressiontype); /* now we are ready: build format streams */ - st = av_new_stream(s, 0); + st = avformat_new_stream(s, NULL); if (!st) return -1; @@ -327,7 +340,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) st->nb_frames = ape->totalframes; st->start_time = 0; st->duration = total_blocks / MAC_SUBFRAME_SIZE; - av_set_pts_info(st, 64, MAC_SUBFRAME_SIZE, ape->samplerate); + avpriv_set_pts_info(st, 64, MAC_SUBFRAME_SIZE, ape->samplerate); st->codec->extradata = av_malloc(APE_EXTRADATA_SIZE); st->codec->extradata_size = APE_EXTRADATA_SIZE; @@ -353,11 +366,12 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) uint32_t extra_size = 8; if (s->pb->eof_reached) - return AVERROR(EIO); - if (ape->currentframe > ape->totalframes) - return AVERROR(EIO); + return AVERROR_EOF; + if (ape->currentframe >= ape->totalframes) + return AVERROR_EOF; - avio_seek (s->pb, ape->frames[ape->currentframe].pos, SEEK_SET); + if (avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET) < 0) + return AVERROR(EIO); /* Calculate how many blocks there are in this frame */ if (ape->currentframe == (ape->totalframes - 1)) @@ -365,6 +379,14 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) else nblocks = ape->blocksperframe; + if (ape->frames[ape->currentframe].size <= 0 || + ape->frames[ape->currentframe].size > INT_MAX - extra_size) { + av_log(s, AV_LOG_ERROR, "invalid packet size: %d\n", + ape->frames[ape->currentframe].size); + ape->currentframe++; + return AVERROR(EIO); + } + if (av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size) < 0) return AVERROR(ENOMEM); @@ -402,18 +424,20 @@ static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp if (index < 0) return -1; + if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0) + return -1; ape->currentframe = index; return 0; } AVInputFormat ff_ape_demuxer = { - "ape", - NULL_IF_CONFIG_SMALL("Monkey's Audio"), - sizeof(APEContext), - ape_probe, - ape_read_header, - ape_read_packet, - ape_read_close, - ape_read_seek, + .name = "ape", + .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), + .priv_data_size = sizeof(APEContext), + .read_probe = ape_probe, + .read_header = ape_read_header, + .read_packet = ape_read_packet, + .read_close = ape_read_close, + .read_seek = ape_read_seek, .extensions = "ape,apl,mac" };