[SCM] libav/experimental: oggdec: Seek to keyframes

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jun 30 17:04:10 UTC 2013


The following commit has been merged in the experimental branch:
commit d8b91fae1df740eae4e1fd65fda09fbe650d4c1a
Author: David Conrad <lessen42 at gmail.com>
Date:   Thu Mar 11 07:18:00 2010 +0000

    oggdec: Seek to keyframes
    
    Originally committed as revision 22463 to svn://svn.ffmpeg.org/ffmpeg/trunk

diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index ca88140..fda1eb2 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -531,9 +531,10 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
     struct ogg_stream *os;
     int idx = -1;
     int pstart, psize;
-    int64_t fpos;
+    int64_t fpos, pts, dts;
 
     //Get an ogg packet
+retry:
     do{
         if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
             return AVERROR(EIO);
@@ -542,13 +543,21 @@ ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
     ogg = s->priv_data;
     os = ogg->streams + idx;
 
+    // pflags might not be set until after this
+    pts = ogg_calc_pts(s, idx, &dts);
+
+    if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
+        goto retry;
+    os->keyframe_seek = 0;
+
     //Alloc a pkt
     if (av_new_packet (pkt, psize) < 0)
         return AVERROR(EIO);
     pkt->stream_index = idx;
     memcpy (pkt->data, os->buf + pstart, psize);
 
-    pkt->pts = ogg_calc_pts(s, idx, &pkt->dts);
+    pkt->pts = pts;
+    pkt->dts = dts;
     pkt->flags = os->pflags;
     pkt->duration = os->pduration;
     pkt->pos = fpos;
@@ -577,6 +586,7 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
                     int64_t pos_limit)
 {
     struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + stream_index;
     ByteIOContext *bc = s->pb;
     int64_t pts = AV_NOPTS_VALUE;
     int i;
@@ -586,6 +596,8 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
     while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
         if (i == stream_index) {
             pts = ogg_calc_pts(s, i, NULL);
+            if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
+                pts = AV_NOPTS_VALUE;
         }
         if (pts != AV_NOPTS_VALUE)
             break;
@@ -594,6 +606,24 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
     return pts;
 }
 
+static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
+{
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + stream_index;
+    int ret;
+
+    // Try seeking to a keyframe first. If this fails (very possible),
+    // av_seek_frame will fall back to ignoring keyframes
+    if (s->streams[stream_index]->codec->codec_type == CODEC_TYPE_VIDEO
+        && !(flags & AVSEEK_FLAG_ANY))
+        os->keyframe_seek = 1;
+
+    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
+    if (ret < 0)
+        os->keyframe_seek = 0;
+    return ret;
+}
+
 static int ogg_probe(AVProbeData *p)
 {
     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
@@ -612,7 +642,7 @@ AVInputFormat ogg_demuxer = {
     ogg_read_header,
     ogg_read_packet,
     ogg_read_close,
-    NULL,
+    ogg_read_seek,
     ogg_read_timestamp,
     .extensions = "ogg",
     .metadata_conv = ff_vorbiscomment_metadata_conv,
diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h
index 6a0ec59..8733d41 100644
--- a/libavformat/oggdec.h
+++ b/libavformat/oggdec.h
@@ -75,6 +75,7 @@ struct ogg_stream {
     uint8_t segments[255];
     int incomplete; ///< whether we're expecting a continuation in the next page
     int page_end;   ///< current packet is the last one completed in the page
+    int keyframe_seek;
     void *private;
 };
 

-- 
Libav/FFmpeg packaging



More information about the pkg-multimedia-commits mailing list