summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>2012-02-12 10:52:42 +0100
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>2012-02-12 18:56:06 +0100
commitff925491955036647c6de26c07070cc2afafda51 (patch)
tree9d9fac458b0057f8c052d66f853ee90a9993d2de /libavformat
parentb223035511d3431853c1e678d49e2630152c591a (diff)
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')
-rw-r--r--libavformat/oggenc.c15
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;