diff options
author | Peter Ross <pross@xvid.org> | 2014-08-29 16:42:04 +1000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-08-29 14:00:58 +0200 |
commit | 9b8eedd736ea443c4829baaca1ede4e146ebc024 (patch) | |
tree | 12ddb81865d934da2f9be52126a1bfd003206bc1 /libavformat/wtvdec.c | |
parent | 72732f2dddabae1d943ce617e0a27e32d13416fb (diff) | |
download | ffmpeg-9b8eedd736ea443c4829baaca1ede4e146ebc024.tar.gz |
avformat/wtvdec: seek over broken chunks
Fixes ticket #3898
Signed-off-by: Peter Ross <pross@xvid.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/wtvdec.c')
-rw-r--r-- | libavformat/wtvdec.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index c70057ce27..4cb3295464 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -751,6 +751,26 @@ enum { }; /** + * Try to seek over a broken chunk + * @return <0 on error + */ +static int recover(WtvContext *wtv, uint64_t broken_pos) +{ + AVIOContext *pb = wtv->pb; + int i; + for (i = 0; i < wtv->nb_index_entries; i++) { + if (wtv->index_entries[i].pos > broken_pos) { + int ret = avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET); + if (ret < 0) + return ret; + wtv->pts = wtv->index_entries[i].timestamp; + return 0; + } + } + return AVERROR(EIO); +} + +/** * Parse WTV chunks * @param mode SEEK_TO_DATA or SEEK_TO_PTS * @param seekts timestamp @@ -767,8 +787,13 @@ static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_p ff_get_guid(pb, &g); len = avio_rl32(pb); - if (len < 32) - break; + if (len < 32) { + int ret; + av_log(s, AV_LOG_WARNING, "encountered broken chunk\n"); + if ((ret = recover(wtv, avio_tell(pb) - 20)) < 0) + return ret; + continue; + } sid = avio_rl32(pb) & 0x7FFF; avio_skip(pb, 8); consumed = 32; |