changeset 5140:9c846d0a6803 libavformat

Use generic multi-stream key frame finding routine to implement read_seek2 and map read_seek to read_seek2.
author schreter
date Sat, 22 Aug 2009 16:07:50 +0000
parents 9b2d2f4aa042
children 8a649e932c1e
files mpegts.c
diffstat 1 files changed, 69 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/mpegts.c	Sat Aug 22 16:05:43 2009 +0000
+++ b/mpegts.c	Sat Aug 22 16:07:50 2009 +0000
@@ -28,6 +28,7 @@
 #include "avformat.h"
 #include "mpegts.h"
 #include "internal.h"
+#include "seek.h"
 
 /* 1.0 second at 24Mbit/s */
 #define MAX_SCAN_PACKETS 32000
@@ -1521,27 +1522,79 @@
     return timestamp;
 }
 
-static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
-    MpegTSContext *ts = s->priv_data;
-    uint8_t buf[TS_PACKET_SIZE];
+static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags);
+
+static int read_seek2(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t target_ts, int64_t max_ts, int flags)
+{
     int64_t pos;
 
-    if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
-        return -1;
+    int64_t ts_ret, ts_adj;
+    int stream_index_gen_search;
+    AVStream *st;
+    AVParserState *backup;
+
+    backup = ff_store_parser_state(s);
+
+    // detect direction of seeking for search purposes
+    flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ? AVSEEK_FLAG_BACKWARD : 0;
 
-    pos= url_ftell(s->pb);
+    if (flags & AVSEEK_FLAG_BYTE) {
+        /* use position directly, we will search starting from it */
+        pos = target_ts;
+    } else {
+        /* search for some position with good timestamp match */
+        if(stream_index < 0){
+            stream_index_gen_search = av_find_default_stream_index(s);
+            if (stream_index_gen_search < 0) {
+                ff_restore_parser_state(s, backup);
+                return -1;
+            }
 
-    for(;;) {
-        url_fseek(s->pb, pos, SEEK_SET);
-        if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+            st = s->streams[stream_index_gen_search];
+            /* timestamp for default must be expressed in AV_TIME_BASE units */
+            ts_adj = av_rescale(target_ts, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
+        } else {
+            ts_adj = target_ts;
+            stream_index_gen_search = stream_index;
+        }
+        pos = av_gen_search(s, stream_index_gen_search, ts_adj,
+                            0, INT64_MAX, -1,
+                            AV_NOPTS_VALUE,
+                            AV_NOPTS_VALUE,
+                            flags, &ts_ret, mpegts_get_pcr);
+        if (pos < 0) {
+            ff_restore_parser_state(s, backup);
             return -1;
-//        pid = AV_RB16(buf + 1) & 0x1fff;
-        if(buf[1] & 0x40) break;
-        pos += ts->raw_packet_size;
+        }
+    }
+
+    /* search for actual matching keyframe/starting position for all streams */
+    if (ff_gen_syncpoint_search(s, stream_index, pos, min_ts, target_ts, max_ts, flags) < 0) {
+        ff_restore_parser_state(s, backup);
+        return -1;
     }
-    url_fseek(s->pb, pos, SEEK_SET);
+
+    ff_free_parser_state(s, backup);
+    return 0;
+}
 
-    return 0;
+static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
+{
+    int ret;
+    if (flags & AVSEEK_FLAG_BACKWARD) {
+        ret = read_seek2(s, stream_index, INT64_MIN, target_ts, target_ts, flags & ~AVSEEK_FLAG_BACKWARD);
+        if (ret < 0) {
+            // for compatibility reasons, seek to best-fitting timestamp
+            ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags & ~AVSEEK_FLAG_BACKWARD);
+        }
+    } else {
+        ret = read_seek2(s, stream_index, target_ts, target_ts, INT64_MAX, flags);
+        if (ret < 0) {
+            // for compatibility reasons, seek to best-fitting timestamp
+            ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags);
+        }
+    }
+    return ret;
 }
 
 /**************************************************************/
@@ -1608,6 +1661,7 @@
     read_seek,
     mpegts_get_pcr,
     .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,
+    .read_seek2 = read_seek2,
 };
 
 AVInputFormat mpegtsraw_demuxer = {
@@ -1621,4 +1675,5 @@
     read_seek,
     mpegts_get_pcr,
     .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,
+    .read_seek2 = read_seek2,
 };