[FFmpeg-cvslog] Fix Theora-in-ogg keyframe handling.
Reimar Döffinger
git at videolan.org
Sun Feb 12 18:57:06 CET 2012
ffmpeg | branch: master | Reimar Döffinger <Reimar.Doeffinger at gmx.de> | Sun Feb 12 10:52:42 2012 +0100| [ff925491955036647c6de26c07070cc2afafda51] | committer: Reimar Döffinger
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 at gmx.de>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ff925491955036647c6de26c07070cc2afafda51
---
libavformat/oggenc.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index ac6eb87..315b8da 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;
More information about the ffmpeg-cvslog
mailing list