[FFmpeg-cvslog] Detect theora keyframes by content in Ogg demuxer.

Reimar Döffinger git at videolan.org
Mon Feb 6 22:09:19 CET 2012


ffmpeg | branch: master | Reimar Döffinger <Reimar.Doeffinger at gmx.de> | Mon Feb  6 22:03:25 2012 +0100| [787528b4a614898c52551dbedcb1f7ea1e5fe5ad] | committer: Reimar Döffinger

Detect theora keyframes by content in Ogg demuxer.

A lot of files do not mark keyframes correctly via
granule, so detect keyframe or not based on data
and complain if it mismatches.

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=787528b4a614898c52551dbedcb1f7ea1e5fe5ad
---

 libavformat/oggdec.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index ab71b39..e32ab69 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -576,6 +576,18 @@ static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
     return pts;
 }
 
+static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
+{
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + idx;
+    if (psize && s->streams[idx]->codec->codec_id == CODEC_ID_THEORA) {
+        if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
+            av_log(s, AV_LOG_WARNING, "Broken file, keyframes not correctly marked.\n");
+            os->pflags ^= AV_PKT_FLAG_KEY;
+        }
+    }
+}
+
 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     struct ogg *ogg;
@@ -597,6 +609,7 @@ retry:
 
     // pflags might not be set until after this
     pts = ogg_calc_pts(s, idx, &dts);
+    ogg_validate_keyframe(s, idx, pstart, psize);
 
     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
         goto retry;
@@ -639,13 +652,15 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
     int64_t pts = AV_NOPTS_VALUE;
     int64_t keypos = -1;
     int i = -1;
+    int pstart, psize;
     avio_seek(bc, *pos_arg, SEEK_SET);
     ogg_reset(ogg);
 
-    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
+    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
         if (i == stream_index) {
             struct ogg_stream *os = ogg->streams + stream_index;
             pts = ogg_calc_pts(s, i, NULL);
+            ogg_validate_keyframe(s, i, pstart, psize);
             if (os->pflags & AV_PKT_FLAG_KEY) {
                 keypos = *pos_arg;
             } else if (os->keyframe_seek) {



More information about the ffmpeg-cvslog mailing list