[FFmpeg-cvslog] r22463 - in trunk/libavformat: oggdec.c oggdec.h

conrad subversion
Thu Mar 11 08:18:01 CET 2010


Author: conrad
Date: Thu Mar 11 08:18:00 2010
New Revision: 22463

Log:
oggdec: Seek to keyframes

Modified:
   trunk/libavformat/oggdec.c
   trunk/libavformat/oggdec.h

Modified: trunk/libavformat/oggdec.c
==============================================================================
--- trunk/libavformat/oggdec.c	Thu Mar 11 08:17:56 2010	(r22462)
+++ trunk/libavformat/oggdec.c	Thu Mar 11 08:18:00 2010	(r22463)
@@ -531,9 +531,10 @@ ogg_read_packet (AVFormatContext * s, AV
     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, AV
     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,
                     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,
     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,
     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,

Modified: trunk/libavformat/oggdec.h
==============================================================================
--- trunk/libavformat/oggdec.h	Thu Mar 11 08:17:56 2010	(r22462)
+++ trunk/libavformat/oggdec.h	Thu Mar 11 08:18:00 2010	(r22463)
@@ -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;
 };
 



More information about the ffmpeg-cvslog mailing list