X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fwv.c;h=ed1eefeea0f8eb62c3949c65784c6a938995cc99;hb=263a93ecff7268d803d8704e50460e5876e828e1;hp=93c3399f0dc1bc1570de5caa6a4fdf5241c6cae5;hpb=730581f3b4f55413368693f0c077c8177d070102;p=ffmpeg diff --git a/libavformat/wv.c b/libavformat/wv.c index 93c3399f0dc..ed1eefeea0f 100644 --- a/libavformat/wv.c +++ b/libavformat/wv.c @@ -2,18 +2,20 @@ * WavPack demuxer * Copyright (c) 2006 Konstantin Shishkov. * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -48,8 +50,10 @@ static const int wv_rates[16] = { typedef struct{ uint32_t blksize, flags; int rate, chan, bpp; + uint32_t samples, soff; int block_parsed; uint8_t extra[WV_EXTRA_SIZE]; + int64_t pos; }WVContext; static int wv_probe(AVProbeData *p) @@ -71,6 +75,7 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) int size; int rate, bpp, chan; + wc->pos = url_ftell(pb); tag = get_le32(pb); if (tag != MKTAG('w', 'v', 'p', 'k')) return -1; @@ -87,10 +92,10 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) } get_byte(pb); // track no get_byte(pb); // track sub index - get_le32(pb); // total samples in file - get_le32(pb); // offset in samples of current block + wc->samples = get_le32(pb); // total samples in file + wc->soff = get_le32(pb); // offset in samples of current block get_buffer(pb, wc->extra, WV_EXTRA_SIZE); - wc->flags = LE_32(wc->extra + 4); + wc->flags = AV_RL32(wc->extra + 4); //parse flags if(wc->flags & WV_FLOAT){ av_log(ctx, AV_LOG_ERROR, "Floating point data is not supported\n"); @@ -116,15 +121,15 @@ static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) if(!wc->chan) wc->chan = chan; if(!wc->rate) wc->rate = rate; - if(bpp != wc->bpp){ + if(wc->flags && bpp != wc->bpp){ av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp); return -1; } - if(chan != wc->chan){ + if(wc->flags && chan != wc->chan){ av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan); return -1; } - if(rate != wc->rate){ + if(wc->flags && rate != wc->rate){ av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate); return -1; } @@ -153,6 +158,8 @@ static int wv_read_header(AVFormatContext *s, st->codec->sample_rate = wc->rate; st->codec->bits_per_sample = wc->bpp; av_set_pts_info(st, 64, 1, wc->rate); + s->start_time = 0; + s->duration = (int64_t)wc->samples * AV_TIME_BASE / st->codec->sample_rate; return 0; } @@ -160,21 +167,15 @@ static int wv_read_packet(AVFormatContext *s, AVPacket *pkt) { WVContext *wc = s->priv_data; - int ret, samples; + int ret; if (url_feof(&s->pb)) - return -EIO; + return AVERROR(EIO); if(wc->block_parsed){ if(wv_read_block_header(s, &s->pb) < 0) return -1; } - samples = LE_32(wc->extra); - /* should not happen but who knows */ - if(samples * 2 * wc->chan > AVCODEC_MAX_AUDIO_FRAME_SIZE){ - av_log(s, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n"); - return -EIO; - } if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE) < 0) return AVERROR_NOMEM; memcpy(pkt->data, wc->extra, WV_EXTRA_SIZE); @@ -186,7 +187,8 @@ static int wv_read_packet(AVFormatContext *s, pkt->stream_index = 0; wc->block_parsed = 1; pkt->size = ret + WV_EXTRA_SIZE; - + pkt->pts = wc->soff; + av_add_index_entry(s->streams[0], wc->pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); return 0; } @@ -195,6 +197,38 @@ static int wv_read_close(AVFormatContext *s) return 0; } +static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + AVStream *st = s->streams[stream_index]; + WVContext *wc = s->priv_data; + AVPacket pkt1, *pkt = &pkt1; + int ret; + int index = av_index_search_timestamp(st, timestamp, flags); + int64_t pos, pts; + + /* if found, seek there */ + if (index >= 0){ + wc->block_parsed = 1; + url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET); + return 0; + } + /* if timestamp is out of bounds, return error */ + if(timestamp < 0 || timestamp >= s->duration) + return -1; + + pos = url_ftell(&s->pb); + do{ + ret = av_read_frame(s, pkt); + if (ret < 0){ + url_fseek(&s->pb, pos, SEEK_SET); + return -1; + } + pts = pkt->pts; + av_free_packet(pkt); + }while(pts < timestamp); + return 0; +} + AVInputFormat wv_demuxer = { "wv", "WavPack", @@ -203,5 +237,5 @@ AVInputFormat wv_demuxer = { wv_read_header, wv_read_packet, wv_read_close, - pcm_read_seek, + wv_read_seek, };