diff options
author | Ivan Schreter <schreter@gmx.net> | 2009-08-22 16:07:50 +0000 |
---|---|---|
committer | Ivan Schreter <schreter@gmx.net> | 2009-08-22 16:07:50 +0000 |
commit | a8dd8dc6e9a419758006dc212fb590991e927030 (patch) | |
tree | e46ba067ee68aa0ad88e78d7f62ba9c9aae81072 /libavformat | |
parent | 101036adb9ad143c1da8db41c2dd89eaf6d32deb (diff) | |
download | ffmpeg-streaming-a8dd8dc6e9a419758006dc212fb590991e927030.zip ffmpeg-streaming-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')
-rw-r--r-- | libavformat/mpegts.c | 81 |
1 files changed, 68 insertions, 13 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 6c0c314..e3bdc6b 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, }; |