[FFmpeg-soc] [soc]: r4389 - seek_api/mpeg.c

spyfeng subversion at mplayerhq.hu
Sun Jun 7 20:19:38 CEST 2009


Author: spyfeng
Date: Sun Jun  7 20:19:38 2009
New Revision: 4389

Log:
add new functions for seeking, still undertest.

Modified:
   seek_api/mpeg.c

Modified: seek_api/mpeg.c
==============================================================================
--- seek_api/mpeg.c	Sat Jun  6 11:30:26 2009	(r4388)
+++ seek_api/mpeg.c	Sun Jun  7 20:19:38 2009	(r4389)
@@ -391,7 +391,7 @@ static int mpegps_read_pes_header(AVForm
             if(startcode == s->streams[i]->id &&
                !url_is_streamed(s->pb) /* index useless on streams anyway */) {
                 ff_reduce_index(s, i);
-                av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
+                av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVFMT_GENERIC_INDEX /* FIXME keyframe? */);
             }
         }
     }
@@ -597,6 +597,116 @@ static int64_t mpegps_read_dts(AVFormatC
     return dts;
 }
 
+/* 0 for sucess and -1 for error */
+static int find_keyframe(AVFormatContext *s, int64_t *ret_pos, int64_t *pts, int64_t target_ts, int flags)
+{
+    AVPacket pkt1, *pkt = &pkt1;
+    int64_t pre_pts, pre_pos, size;
+
+    for (;;) {
+        if (av_read_frame(s, pkt) < 0)
+            return -1;
+
+        size = pkt->size;
+        av_free_packet(pkt);
+        if (!(pkt->flags & PKT_FLAG_KEY))
+            continue;
+
+        *ret_pos += size;
+        *pts = pkt->pts;
+
+        if (*pts < target_ts) {
+            pre_pts = *pts;
+            pre_pos = *ret_pos;
+        } else
+            break;
+    }
+
+    if (flags & AVSEEK_FLAG_BACKWARD) {
+        *ret_pos = pre_pts;
+        *pts = pre_pos;
+    }
+    return 0;
+}
+
+static int mpegps_read_seek1(struct AVFormatContext *s, int stream_index,
+                            int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
+{
+    AVStream* st;
+    int index;
+    int64_t pos, av_uninit(pos_min), av_uninit(pos_max), pos_limit;
+    int64_t ts_min, ts_max, ret_ts, pts;
+
+    if (min_ts > ts || max_ts < ts)
+        return -1;
+
+    if (stream_index < 0) {
+        stream_index= av_find_default_stream_index(s);
+        if(stream_index < 0)
+            return -1;
+        st = s->streams[stream_index];
+        ts = av_rescale(ts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
+    } else
+        st = s->streams[stream_index];
+
+    if (ts < 0) {
+        pts = ts = 0;
+        url_fseek(s->pb, 0, SEEK_SET);
+        goto sucess;
+    }
+
+    if (st->discard >= AVDISCARD_ALL) {
+        av_log(s, AV_LOG_ERROR, "Not active stream!\n");
+        return -1;
+    }
+
+    if (st->index_entries) {
+        AVIndexEntry *e;
+        index = av_index_search_timestamp(st, ts, flags | AVSEEK_FLAG_BACKWARD);
+
+        if (index >= 0) {
+            e = &st->index_entries[index];
+            pos = e->pos;
+            pts = e->timestamp;
+            url_fseek(s->pb, pos, SEEK_SET);
+            av_log(s, AV_LOG_DEBUG, "the seek pos = %"PRId64", pts  = %"PRId64", targe timestamp = %"PRId64"\n", pos, pts, ts);
+
+            if (e->timestamp == ts) { // find the target timestamp
+                goto sucess;
+            } else { // seek around to get the keyframe, then seek there
+                if (find_keyframe(s, &pos,&pts,ts, flags) == 0) {
+                    url_fseek(s->pb, pos, SEEK_SET);
+                    goto sucess;
+                } else {
+                    av_update_cur_dts(s, st, pts);
+                    return -1;
+                }
+            }
+        }
+     }
+    // search the scr use binary search
+    ts_max=
+    ts_min= AV_NOPTS_VALUE;
+    pos_limit= -1;
+    pos= av_gen_search(s, stream_index, ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags | AVSEEK_FLAG_BACKWARD, &ret_ts, mpegps_read_dts);
+    av_log(s, AV_LOG_DEBUG, "the seek pos = %"PRId64", ret_ts  = %"PRId64"\n", pos, ret_ts);
+    if(pos<0)
+        return -1;
+
+    url_fseek(s->pb, pos, SEEK_SET);
+    if (find_keyframe(s, &pos, &ret_ts, ts, flags) == 0) {
+        url_fseek(s->pb, pos, SEEK_SET);
+        pts =  ret_ts;
+        goto sucess;
+    } else {
+        av_update_cur_dts(s, st, ret_ts);
+        return -1;
+    }
+sucess:
+    av_update_cur_dts(s, st, pts);
+    return 0;
+}
+
 static int mpegps_read_seek(struct AVFormatContext *s, int stream_index,
                             int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
 {
@@ -683,5 +793,5 @@ AVInputFormat mpegps_demuxer = {
     NULL, //mpegps_read_seek,
     mpegps_read_dts,
     .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,
-    .read_seek2 = mpegps_read_seek,
+    .read_seek2 = mpegps_read_seek1,
 };


More information about the FFmpeg-soc mailing list