diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-02-24 14:58:17 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-02-26 02:06:10 +0100 |
commit | 111d79aa8886ed979c15ba43918d3208937c93f1 (patch) | |
tree | 9659494e426d7b857ebd5679ca6b77ca0ced2141 /libavformat/dss.c | |
parent | 626904b77797cf541bf95204a8939e9c8efe95f0 (diff) | |
download | ffmpeg-111d79aa8886ed979c15ba43918d3208937c93f1.tar.gz |
avformat/dss: implement seeking
This assumes CBR (which is true for all samples i have)
Previous version reviewed by: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/dss.c')
-rw-r--r-- | libavformat/dss.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/libavformat/dss.c b/libavformat/dss.c index ae5b24cf60..ead0ee00dc 100644 --- a/libavformat/dss.c +++ b/libavformat/dss.c @@ -256,6 +256,11 @@ static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt) dss_sp_byte_swap(ctx, pkt->data, ctx->dss_sp_buf); + if (ctx->dss_sp_swap_byte < 0) { + ret = AVERROR(EAGAIN); + goto error_eof; + } + if (pkt->data[0] == 0xff) return AVERROR_INVALIDDATA; @@ -340,6 +345,45 @@ static int dss_read_close(AVFormatContext *s) return 0; } +static int dss_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + DSSDemuxContext *ctx = s->priv_data; + int64_t ret, seekto; + uint8_t header[DSS_AUDIO_BLOCK_HEADER_SIZE]; + int offset; + + if (ctx->audio_codec == DSS_ACODEC_DSS_SP) + seekto = timestamp / 264 * 41 / 506 * 512; + else + seekto = timestamp / 240 * ctx->packet_size / 506 * 512; + + if (seekto < 0) + seekto = 0; + + seekto += DSS_HEADER_SIZE; + + ret = avio_seek(s->pb, seekto, SEEK_SET); + if (ret < 0) + return ret; + + avio_read(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); + ctx->swap = !!(header[0] & 0x80); + offset = 2*header[1] + 2*ctx->swap; + if (offset < DSS_AUDIO_BLOCK_HEADER_SIZE) + return AVERROR_INVALIDDATA; + if (offset == DSS_AUDIO_BLOCK_HEADER_SIZE) { + ctx->counter = 0; + offset = avio_skip(s->pb, -DSS_AUDIO_BLOCK_HEADER_SIZE); + } else { + ctx->counter = DSS_BLOCK_SIZE - offset; + offset = avio_skip(s->pb, offset - DSS_AUDIO_BLOCK_HEADER_SIZE); + } + ctx->dss_sp_swap_byte = -1; + return 0; +} + + AVInputFormat ff_dss_demuxer = { .name = "dss", .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard (DSS)"), @@ -348,5 +392,6 @@ AVInputFormat ff_dss_demuxer = { .read_header = dss_read_header, .read_packet = dss_read_packet, .read_close = dss_read_close, + .read_seek = dss_read_seek, .extensions = "dss" }; |