X-Git-Url: http://git.videolan.org/?p=ffmpeg.git;a=blobdiff_plain;f=libavformat%2Fwv.c;h=49ca486a9328bddbebe9c8f7726d05dc60eb8dea;hp=71067350415b0ec7ad8a0787291cc6483dbb5eb5;hb=8bdab32f4ee402bbd7bf5a61b0ccbcc59569bfb0;hpb=8978fedaeefdff50ed4deefbfe822ad07f19f616 diff --git a/libavformat/wv.c b/libavformat/wv.c index 7106735041..49ca486a93 100644 --- a/libavformat/wv.c +++ b/libavformat/wv.c @@ -21,7 +21,9 @@ #include "libavutil/audioconvert.h" #include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" #include "avformat.h" +#include "internal.h" #include "apetag.h" #include "id3v1.h" @@ -109,6 +111,9 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, int appen size = wc->blksize; } wc->flags = AV_RL32(wc->extra + 4); + // blocks with zero samples don't contain actual audio information and should be ignored + if (!AV_RN32(wc->extra)) + return 0; //parse flags bpp = ((wc->flags & 3) + 1) << 3; chan = 1 + !(wc->flags & WV_MONO); @@ -198,19 +203,24 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, int appen return 0; } -static int wv_read_header(AVFormatContext *s, - AVFormatParameters *ap) +static int wv_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; WVContext *wc = s->priv_data; AVStream *st; wc->block_parsed = 0; - if(wv_read_block_header(s, pb, 0) < 0) - return -1; + for(;;){ + if(wv_read_block_header(s, pb, 0) < 0) + return -1; + if(!AV_RN32(wc->extra)) + avio_skip(pb, wc->blksize - 24); + else + break; + } /* now we are ready: build format streams */ - st = av_new_stream(s, 0); + st = avformat_new_stream(s, NULL); if (!st) return -1; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; @@ -219,14 +229,14 @@ static int wv_read_header(AVFormatContext *s, st->codec->channel_layout = wc->chmask; st->codec->sample_rate = wc->rate; st->codec->bits_per_coded_sample = wc->bpp; - av_set_pts_info(st, 64, 1, wc->rate); + avpriv_set_pts_info(st, 64, 1, wc->rate); st->start_time = 0; st->duration = wc->samples; if(s->pb->seekable) { int64_t cur = avio_tell(s->pb); ff_ape_parse_tag(s); - if(!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) + if(!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); avio_seek(s->pb, cur, SEEK_SET); } @@ -240,6 +250,8 @@ static int wv_read_packet(AVFormatContext *s, WVContext *wc = s->priv_data; int ret; int size, ver, off; + int64_t pos; + uint32_t block_samples; if (s->pb->eof_reached) return AVERROR(EIO); @@ -248,6 +260,7 @@ static int wv_read_packet(AVFormatContext *s, return -1; } + pos = wc->pos; off = wc->multichannel ? 4 : 0; if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE + off) < 0) return AVERROR(ENOMEM); @@ -304,7 +317,13 @@ static int wv_read_packet(AVFormatContext *s, pkt->stream_index = 0; wc->block_parsed = 1; pkt->pts = wc->soff; - av_add_index_entry(s->streams[0], wc->pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); + block_samples = AV_RN32(wc->extra); + if (block_samples > INT32_MAX) + av_log(s, AV_LOG_WARNING, "Too many samples in block: %"PRIu32"\n", block_samples); + else + pkt->duration = block_samples; + + av_add_index_entry(s->streams[0], pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); return 0; } @@ -318,7 +337,8 @@ static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int64_t pos, pts; /* if found, seek there */ - if (index >= 0){ + if (index >= 0 && + timestamp <= st->index_entries[st->nb_index_entries - 1].timestamp) { wc->block_parsed = 1; avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET); return 0; @@ -341,12 +361,11 @@ static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, } AVInputFormat ff_wv_demuxer = { - "wv", - NULL_IF_CONFIG_SMALL("WavPack"), - sizeof(WVContext), - wv_probe, - wv_read_header, - wv_read_packet, - NULL, - wv_read_seek, + .name = "wv", + .long_name = NULL_IF_CONFIG_SMALL("WavPack"), + .priv_data_size = sizeof(WVContext), + .read_probe = wv_probe, + .read_header = wv_read_header, + .read_packet = wv_read_packet, + .read_seek = wv_read_seek, };