diff options
author | Reimar Döffinger <Reimar.Doeffinger@gmx.de> | 2012-02-12 10:52:42 +0100 |
---|---|---|
committer | Reimar Döffinger <Reimar.Doeffinger@gmx.de> | 2012-02-12 18:56:06 +0100 |
commit | ff925491955036647c6de26c07070cc2afafda51 (patch) | |
tree | 9d9fac458b0057f8c052d66f853ee90a9993d2de /libavformat/oggenc.c | |
parent | b223035511d3431853c1e678d49e2630152c591a (diff) | |
download | ffmpeg-ff925491955036647c6de26c07070cc2afafda51.tar.gz |
Fix Theora-in-ogg keyframe handling.
To make seeking work correctly, we must write a new granule for
each keyframe.
Unfortunately we currently have no regression tests due to no
included Theora encoder.
A test based on -vcodec copy from a Theora FATE sample should
probably be added.
Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
Diffstat (limited to 'libavformat/oggenc.c')
-rw-r--r-- | libavformat/oggenc.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index ac6eb8737d..315b8da049 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -131,6 +131,11 @@ static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) return 0; } +static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule) +{ + return oggstream->kfgshift && !(granule & ((1<<oggstream->kfgshift)-1)); +} + static int64_t ogg_granule_to_timestamp(OGGStreamContext *oggstream, int64_t granule) { if (oggstream->kfgshift) @@ -199,9 +204,15 @@ static int ogg_buffer_data(AVFormatContext *s, AVStream *st, int i, segments, len, flush = 0; // Handles VFR by flushing page because this frame needs to have a timestamp + // For theora, keyframes also need to have a timestamp to correctly mark + // them as such, otherwise seeking will not work correctly at the very + // least with old libogg versions. + // Do not try to flush empty packets though, that will create broken files. if (st->codec->codec_id == CODEC_ID_THEORA && - ogg_granule_to_timestamp(oggstream, granule) > - ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1) { + oggstream->page.size && + (ogg_granule_to_timestamp(oggstream, granule) > + ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1 || + ogg_key_granule(oggstream, granule))) { if (oggstream->page.granule != -1) ogg_buffer_page(s, oggstream); flush = 1; |