aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/mpegts.c
diff options
context:
space:
mode:
authorIvan Schreter <schreter@gmx.net>2009-08-22 16:07:50 +0000
committerIvan Schreter <schreter@gmx.net>2009-08-22 16:07:50 +0000
commita8dd8dc6e9a419758006dc212fb590991e927030 (patch)
treee46ba067ee68aa0ad88e78d7f62ba9c9aae81072 /libavformat/mpegts.c
parent101036adb9ad143c1da8db41c2dd89eaf6d32deb (diff)
downloadffmpeg-a8dd8dc6e9a419758006dc212fb590991e927030.tar.gz
Use generic multi-stream key frame finding routine to implement read_seek2 and map
read_seek to read_seek2. Originally committed as revision 19681 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r--libavformat/mpegts.c81
1 files changed, 68 insertions, 13 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 6c0c314f42..e3bdc6b658 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -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,29 +1522,81 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
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;
- pos= url_ftell(s->pb);
+ backup = ff_store_parser_state(s);
- for(;;) {
- url_fseek(s->pb, pos, SEEK_SET);
- if (get_buffer(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
+ // detect direction of seeking for search purposes
+ flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ? AVSEEK_FLAG_BACKWARD : 0;
+
+ 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;
+ }
+
+ 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;
+ }
}
- url_fseek(s->pb, pos, SEEK_SET);
+ /* 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;
+ }
+
+ ff_free_parser_state(s, backup);
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;
+}
+
/**************************************************************/
/* parsing functions - called from other demuxers such as RTP */
@@ -1608,6 +1661,7 @@ AVInputFormat mpegts_demuxer = {
read_seek,
mpegts_get_pcr,
.flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,
+ .read_seek2 = read_seek2,
};
AVInputFormat mpegtsraw_demuxer = {
@@ -1621,4 +1675,5 @@ AVInputFormat mpegtsraw_demuxer = {
read_seek,
mpegts_get_pcr,
.flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,
+ .read_seek2 = read_seek2,
};