Browse code

Implement librtmp seek support.

Implement flv_read_seek(), add a missing check on stream_index
and fix timestamp rounding in rtmp_read_seek().

Also add the flv_read_seek2() function, which is not enabled but is
useful as reference.
To actually implement flv_read_seek2() correctly, there would need to
be some corresponding av_url_read_fseek2() function to propagate the
timestamps down to the ByteIOContext and URLContext.

Patch by Howard Chu <hyc <at> highlandsun.com>.

See the thread:
Subject: [FFmpeg-devel] RTMP seek support
Date: 2010-03-28 23:35:02 GMT

Originally committed as revision 22904 to svn://svn.ffmpeg.org/ffmpeg/trunk

Howard Chu authored on 2010/04/19 04:09:25
Showing 2 changed files
... ...
@@ -449,6 +449,39 @@ leave:
449 449
     return ret;
450 450
 }
451 451
 
452
+static int flv_read_seek(AVFormatContext *s, int stream_index,
453
+    int64_t ts, int flags)
454
+{
455
+    return av_url_read_fseek(s->pb, stream_index, ts, flags);
456
+}
457
+
458
+#if 0 /* don't know enough to implement this */
459
+static int flv_read_seek2(AVFormatContext *s, int stream_index,
460
+    int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
461
+{
462
+    int ret = AVERROR(ENOSYS);
463
+
464
+    if (ts - min_ts > (uint64_t)(max_ts - ts)) flags |= AVSEEK_FLAG_BACKWARD;
465
+
466
+    if (url_is_streamed(s->pb)) {
467
+        if (stream_index < 0) {
468
+            stream_index = av_find_default_stream_index(s);
469
+            if (stream_index < 0)
470
+                return -1;
471
+
472
+            /* timestamp for default must be expressed in AV_TIME_BASE units */
473
+            ts = av_rescale_rnd(ts, 1000, AV_TIME_BASE,
474
+                flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
475
+        }
476
+        ret = av_url_read_fseek(s->pb, stream_index, ts, flags);
477
+    }
478
+
479
+    if (ret == AVERROR(ENOSYS))
480
+        ret = av_seek_frame(s, stream_index, ts, flags);
481
+    return ret;
482
+}
483
+#endif
484
+
452 485
 AVInputFormat flv_demuxer = {
453 486
     "flv",
454 487
     NULL_IF_CONFIG_SMALL("FLV format"),
... ...
@@ -456,6 +489,10 @@ AVInputFormat flv_demuxer = {
456 456
     flv_probe,
457 457
     flv_read_header,
458 458
     flv_read_packet,
459
+    .read_seek = flv_read_seek,
460
+#if 0
461
+    .read_seek2 = flv_read_seek2,
462
+#endif
459 463
     .extensions = "flv",
460 464
     .value = CODEC_ID_FLV1,
461 465
 };
... ...
@@ -144,7 +144,10 @@ static int64_t rtmp_read_seek(URLContext *s, int stream_index,
144 144
         return AVERROR(ENOSYS);
145 145
 
146 146
     /* seeks are in milliseconds */
147
-    timestamp = av_rescale(timestamp, AV_TIME_BASE, 1000);
147
+    if (stream_index < 0)
148
+        timestamp = av_rescale_rnd(timestamp, 1000, AV_TIME_BASE,
149
+            flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
150
+
148 151
     if (!RTMP_SendSeek(r, timestamp))
149 152
         return -1;
150 153
     return timestamp;