Commit 3ba1438d authored by Michael Niedermayer's avatar Michael Niedermayer

use native timebase for seeking

direction flag for seeking

Originally committed as revision 3577 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent ac8b03c0
...@@ -2777,7 +2777,7 @@ static void opt_input_file(const char *filename) ...@@ -2777,7 +2777,7 @@ static void opt_input_file(const char *filename)
/* if seeking requested, we execute it */ /* if seeking requested, we execute it */
if (start_time != 0) { if (start_time != 0) {
ret = av_seek_frame(ic, -1, timestamp); ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "%s: could not seek to position %0.3f\n", fprintf(stderr, "%s: could not seek to position %0.3f\n",
filename, (double)timestamp / AV_TIME_BASE); filename, (double)timestamp / AV_TIME_BASE);
......
...@@ -92,6 +92,7 @@ typedef struct VideoState { ...@@ -92,6 +92,7 @@ typedef struct VideoState {
int paused; int paused;
int last_paused; int last_paused;
int seek_req; int seek_req;
int seek_flags;
int64_t seek_pos; int64_t seek_pos;
AVFormatContext *ic; AVFormatContext *ic;
int dtg_active_format; int dtg_active_format;
...@@ -589,10 +590,11 @@ static double get_master_clock(VideoState *is) ...@@ -589,10 +590,11 @@ static double get_master_clock(VideoState *is)
} }
/* seek in the stream */ /* seek in the stream */
static void stream_seek(VideoState *is, int64_t pos) static void stream_seek(VideoState *is, int64_t pos, int rel)
{ {
is->seek_pos = pos; is->seek_pos = pos;
is->seek_req = 1; is->seek_req = 1;
is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
} }
/* pause or resume the video */ /* pause or resume the video */
...@@ -1335,7 +1337,7 @@ static int decode_thread(void *arg) ...@@ -1335,7 +1337,7 @@ static int decode_thread(void *arg)
/* add the stream start time */ /* add the stream start time */
if (ic->start_time != AV_NOPTS_VALUE) if (ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time; timestamp += ic->start_time;
ret = av_seek_frame(ic, -1, timestamp); ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "%s: could not seek to position %0.3f\n", fprintf(stderr, "%s: could not seek to position %0.3f\n",
is->filename, (double)timestamp / AV_TIME_BASE); is->filename, (double)timestamp / AV_TIME_BASE);
...@@ -1412,7 +1414,7 @@ static int decode_thread(void *arg) ...@@ -1412,7 +1414,7 @@ static int decode_thread(void *arg)
#endif #endif
if (is->seek_req) { if (is->seek_req) {
/* XXX: must lock decoder threads */ /* XXX: must lock decoder threads */
ret = av_seek_frame(is->ic, -1, is->seek_pos); ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "%s: error while seeking\n", is->ic->filename); fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
}else{ }else{
...@@ -1682,7 +1684,7 @@ void event_loop(void) ...@@ -1682,7 +1684,7 @@ void event_loop(void)
if (cur_stream) { if (cur_stream) {
pos = get_master_clock(cur_stream); pos = get_master_clock(cur_stream);
pos += incr; pos += incr;
stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE)); stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), incr);
} }
break; break;
default: default:
...@@ -1704,7 +1706,7 @@ void event_loop(void) ...@@ -1704,7 +1706,7 @@ void event_loop(void)
ss = (ns%60); ss = (ns%60);
fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100, fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d) \n", frac*100,
hh, mm, ss, thh, tmm, tss); hh, mm, ss, thh, tmm, tss);
stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration)); stream_seek(cur_stream, (int64_t)(cur_stream->ic->start_time+frac*cur_stream->ic->duration), 0);
} }
break; break;
case SDL_VIDEORESIZE: case SDL_VIDEORESIZE:
......
...@@ -757,14 +757,14 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, ...@@ -757,14 +757,14 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
return pts; return pts;
} }
static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts) static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
{ {
ASFContext *asf = s->priv_data; ASFContext *asf = s->priv_data;
if (asf->packet_size <= 0) if (asf->packet_size <= 0)
return -1; return -1;
if(av_seek_frame_binary(s, stream_index, pts)<0) if(av_seek_frame_binary(s, stream_index, pts, flags)<0)
return -1; return -1;
asf_reset_header(s); asf_reset_header(s);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
extern "C" { extern "C" {
#endif #endif
#define LIBAVFORMAT_BUILD 4618 #define LIBAVFORMAT_BUILD 4619
#define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT #define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT
#define LIBAVFORMAT_VERSION FFMPEG_VERSION #define LIBAVFORMAT_VERSION FFMPEG_VERSION
...@@ -165,10 +165,15 @@ typedef struct AVInputFormat { ...@@ -165,10 +165,15 @@ typedef struct AVInputFormat {
/* close the stream. The AVFormatContext and AVStreams are not /* close the stream. The AVFormatContext and AVStreams are not
freed by this function */ freed by this function */
int (*read_close)(struct AVFormatContext *); int (*read_close)(struct AVFormatContext *);
/* seek at or before a given timestamp (given in AV_TIME_BASE /**
units) relative to the frames in stream component stream_index */ * seek to a given timestamp relative to the frames in
* stream component stream_index
* @param stream_index must not be -1
* @param flags selects which direction should be preferred if no exact
* match is available
*/
int (*read_seek)(struct AVFormatContext *, int (*read_seek)(struct AVFormatContext *,
int stream_index, int64_t timestamp); int stream_index, int64_t timestamp, int flags);
/** /**
* gets the next timestamp in AV_TIME_BASE units. * gets the next timestamp in AV_TIME_BASE units.
*/ */
...@@ -553,7 +558,7 @@ AVFormatContext *av_alloc_format_context(void); ...@@ -553,7 +558,7 @@ AVFormatContext *av_alloc_format_context(void);
int av_find_stream_info(AVFormatContext *ic); int av_find_stream_info(AVFormatContext *ic);
int av_read_packet(AVFormatContext *s, AVPacket *pkt); int av_read_packet(AVFormatContext *s, AVPacket *pkt);
int av_read_frame(AVFormatContext *s, AVPacket *pkt); int av_read_frame(AVFormatContext *s, AVPacket *pkt);
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp); int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
int av_read_play(AVFormatContext *s); int av_read_play(AVFormatContext *s);
int av_read_pause(AVFormatContext *s); int av_read_pause(AVFormatContext *s);
void av_close_input_file(AVFormatContext *s); void av_close_input_file(AVFormatContext *s);
...@@ -561,11 +566,14 @@ AVStream *av_new_stream(AVFormatContext *s, int id); ...@@ -561,11 +566,14 @@ AVStream *av_new_stream(AVFormatContext *s, int id);
void av_set_pts_info(AVStream *s, int pts_wrap_bits, void av_set_pts_info(AVStream *s, int pts_wrap_bits,
int pts_num, int pts_den); int pts_num, int pts_den);
#define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
int av_find_default_stream_index(AVFormatContext *s); int av_find_default_stream_index(AVFormatContext *s);
int av_index_search_timestamp(AVStream *st, int timestamp); int av_index_search_timestamp(AVStream *st, int timestamp, int flags);
int av_add_index_entry(AVStream *st, int av_add_index_entry(AVStream *st,
int64_t pos, int64_t timestamp, int distance, int flags); int64_t pos, int64_t timestamp, int distance, int flags);
int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts); int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags);
/* media file output */ /* media file output */
int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
......
...@@ -1331,12 +1331,12 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index, ...@@ -1331,12 +1331,12 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
return timestamp; return timestamp;
} }
static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){ static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
MpegTSContext *ts = s->priv_data; MpegTSContext *ts = s->priv_data;
uint8_t buf[TS_PACKET_SIZE]; uint8_t buf[TS_PACKET_SIZE];
int64_t pos; int64_t pos;
if(av_seek_frame_binary(s, stream_index, target_ts) < 0) if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
return -1; return -1;
pos= url_ftell(&s->pb); pos= url_ftell(&s->pb);
......
...@@ -1373,11 +1373,11 @@ av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1); ...@@ -1373,11 +1373,11 @@ av_log(s, AV_LOG_DEBUG, "syncing from %lld\n", nut->packet_start[2]+1);
return AV_NOPTS_VALUE; return AV_NOPTS_VALUE;
} }
static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts){ static int nut_read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
// NUTContext *nut = s->priv_data; // NUTContext *nut = s->priv_data;
int64_t pos; int64_t pos;
if(av_seek_frame_binary(s, stream_index, target_ts) < 0) if(av_seek_frame_binary(s, stream_index, target_ts, flags) < 0)
return -1; return -1;
pos= url_ftell(&s->pb); pos= url_ftell(&s->pb);
......
...@@ -907,30 +907,21 @@ int av_add_index_entry(AVStream *st, ...@@ -907,30 +907,21 @@ int av_add_index_entry(AVStream *st,
sizeof(AVIndexEntry)); sizeof(AVIndexEntry));
st->index_entries= entries; st->index_entries= entries;
if(st->nb_index_entries){ index= av_index_search_timestamp(st, timestamp, 0);
index= av_index_search_timestamp(st, timestamp);
ie= &entries[index];
if(index<0){
index= st->nb_index_entries++;
ie= &entries[index];
assert(index==0 || ie[-1].timestamp < timestamp);
}else{
ie= &entries[index];
if(ie->timestamp != timestamp){ if(ie->timestamp != timestamp){
if(ie->timestamp < timestamp){ assert(ie->timestamp > timestamp);
index++; //index points to next instead of previous entry, maybe nonexistant
ie= &st->index_entries[index];
}else
assert(index==0);
if(index != st->nb_index_entries){
assert(index < st->nb_index_entries);
memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(st->nb_index_entries - index)); memmove(entries + index + 1, entries + index, sizeof(AVIndexEntry)*(st->nb_index_entries - index));
}
st->nb_index_entries++; st->nb_index_entries++;
}else{ }else if(ie->pos == pos && distance < ie->min_distance) //dont reduce the distance
if(ie->pos == pos && distance < ie->min_distance) //dont reduce the distance
distance= ie->min_distance; distance= ie->min_distance;
} }
}else{
index= st->nb_index_entries++;
ie= &entries[index];
}
ie->pos = pos; ie->pos = pos;
ie->timestamp = timestamp; ie->timestamp = timestamp;
...@@ -979,31 +970,36 @@ static int is_raw_stream(AVFormatContext *s) ...@@ -979,31 +970,36 @@ static int is_raw_stream(AVFormatContext *s)
return 1; return 1;
} }
/* return the largest index entry whose timestamp is <= /**
wanted_timestamp */ * gets the index for a specific timestamp.
int av_index_search_timestamp(AVStream *st, int wanted_timestamp) * @param backward if non zero then the returned index will correspond to
* the timestamp which is <= the requested one, if backward is 0
* then it will be >=
* @return < 0 if no such timestamp could be found
*/
int av_index_search_timestamp(AVStream *st, int wanted_timestamp, int backward)
{ {
AVIndexEntry *entries= st->index_entries; AVIndexEntry *entries= st->index_entries;
int nb_entries= st->nb_index_entries; int nb_entries= st->nb_index_entries;
int a, b, m; int a, b, m;
int64_t timestamp; int64_t timestamp;
if (nb_entries <= 0) a = - 1;
return -1; b = nb_entries;
a = 0;
b = nb_entries - 1;
while (a < b) { while (b - a > 1) {
m = (a + b + 1) >> 1; m = (a + b) >> 1;
timestamp = entries[m].timestamp; timestamp = entries[m].timestamp;
if (timestamp > wanted_timestamp) { if(timestamp >= wanted_timestamp)
b = m - 1; b = m;
} else { if(timestamp <= wanted_timestamp)
a = m; a = m;
} }
} m= backward ? a : b;
return a;
if(m == nb_entries)
return -1;
return m;
} }
#define DEBUG_SEEK #define DEBUG_SEEK
...@@ -1014,7 +1010,7 @@ int av_index_search_timestamp(AVStream *st, int wanted_timestamp) ...@@ -1014,7 +1010,7 @@ int av_index_search_timestamp(AVStream *st, int wanted_timestamp)
* @param target_ts target timestamp in the time base of the given stream * @param target_ts target timestamp in the time base of the given stream
* @param stream_index stream number * @param stream_index stream number
*/ */
int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts){ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){
AVInputFormat *avif= s->iformat; AVInputFormat *avif= s->iformat;
int64_t pos_min, pos_max, pos, pos_limit; int64_t pos_min, pos_max, pos, pos_limit;
int64_t ts_min, ts_max, ts; int64_t ts_min, ts_max, ts;
...@@ -1037,7 +1033,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts ...@@ -1037,7 +1033,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
if(st->index_entries){ if(st->index_entries){
AVIndexEntry *e; AVIndexEntry *e;
index= av_index_search_timestamp(st, target_ts); index= av_index_search_timestamp(st, target_ts, 1);
index= FFMAX(index, 0);
e= &st->index_entries[index]; e= &st->index_entries[index];
if(e->timestamp <= target_ts || e->pos == e->min_distance){ if(e->timestamp <= target_ts || e->pos == e->min_distance){
...@@ -1105,9 +1102,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts ...@@ -1105,9 +1102,8 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
if(no_change==0){ if(no_change==0){
int64_t approximate_keyframe_distance= pos_max - pos_limit; int64_t approximate_keyframe_distance= pos_max - pos_limit;
// interpolate position (better than dichotomy) // interpolate position (better than dichotomy)
pos = (int64_t)((double)(pos_max - pos_min) * pos = av_rescale(target_ts - ts_min, pos_max - pos_min, ts_max - ts_min)
(double)(target_ts - ts_min) / + pos_min - approximate_keyframe_distance;
(double)(ts_max - ts_min)) + pos_min - approximate_keyframe_distance;
}else if(no_change==1){ }else if(no_change==1){
// bisection, if interpolation failed to change min or max pos last time // bisection, if interpolation failed to change min or max pos last time
pos = (pos_min + pos_limit)>>1; pos = (pos_min + pos_limit)>>1;
...@@ -1130,20 +1126,19 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts ...@@ -1130,20 +1126,19 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts
av_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change); av_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change);
#endif #endif
assert(ts != AV_NOPTS_VALUE); assert(ts != AV_NOPTS_VALUE);
if (target_ts < ts) { if (target_ts <= ts) {
pos_limit = start_pos - 1; pos_limit = start_pos - 1;
pos_max = pos; pos_max = pos;
ts_max = ts; ts_max = ts;
} else { }
if (target_ts >= ts) {
pos_min = pos; pos_min = pos;
ts_min = ts; ts_min = ts;
/* check if we are lucky */
if (target_ts == ts)
break;
} }
} }
pos = pos_min; pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
#ifdef DEBUG_SEEK #ifdef DEBUG_SEEK
pos_min = pos; pos_min = pos;
ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX); ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);
...@@ -1155,18 +1150,51 @@ av_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%L ...@@ -1155,18 +1150,51 @@ av_log(s, AV_LOG_DEBUG, "%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%L
/* do the seek */ /* do the seek */
url_fseek(&s->pb, pos, SEEK_SET); url_fseek(&s->pb, pos, SEEK_SET);
ts= av_rescale(ts_min, AV_TIME_BASE*(int64_t)st->time_base.num, st->time_base.den);
for(i = 0; i < s->nb_streams; i++) { for(i = 0; i < s->nb_streams; i++) {
st = s->streams[i]; AVStream *st2 = s->streams[i];
st->cur_dts = av_rescale(ts, st->time_base.den, AV_TIME_BASE*(int64_t)st->time_base.num); st->cur_dts = av_rescale(ts,
st2->time_base.den * (int64_t)st ->time_base.num,
st ->time_base.den * (int64_t)st2->time_base.num);
} }
return 0; return 0;
} }
static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){
AVInputFormat *avif= s->iformat;
int64_t pos_min, pos_max;
#if 0
AVStream *st;
if (stream_index < 0)
return -1;
st= s->streams[stream_index];
#endif
pos_min = s->data_offset;
pos_max = url_filesize(url_fileno(&s->pb)) - 1;
if (pos < pos_min) pos= pos_min;
else if(pos > pos_max) pos= pos_max;
url_fseek(&s->pb, pos, SEEK_SET);
#if 0
for(i = 0; i < s->nb_streams; i++) {
st2 = s->streams[i];
st->cur_dts = av_rescale(ie->timestamp,
st2->time_base.den * (int64_t)st ->time_base.num,
st ->time_base.den * (int64_t)st2->time_base.num);
}
#endif
return 0;
}
static int av_seek_frame_generic(AVFormatContext *s, static int av_seek_frame_generic(AVFormatContext *s,
int stream_index, int64_t timestamp) int stream_index, int64_t timestamp, int flags)
{ {
int index, i; int index, i;
AVStream *st; AVStream *st;
...@@ -1182,7 +1210,7 @@ static int av_seek_frame_generic(AVFormatContext *s, ...@@ -1182,7 +1210,7 @@ static int av_seek_frame_generic(AVFormatContext *s,
} }
st = s->streams[stream_index]; st = s->streams[stream_index];
index = av_index_search_timestamp(st, timestamp); index = av_index_search_timestamp(st, timestamp, flags & AVSEEK_FLAG_BACKWARD);
if (index < 0) if (index < 0)
return -1; return -1;
...@@ -1191,43 +1219,49 @@ static int av_seek_frame_generic(AVFormatContext *s, ...@@ -1191,43 +1219,49 @@ static int av_seek_frame_generic(AVFormatContext *s,
av_read_frame_flush(s); av_read_frame_flush(s);
url_fseek(&s->pb, ie->pos, SEEK_SET); url_fseek(&s->pb, ie->pos, SEEK_SET);
timestamp= av_rescale(ie->timestamp, AV_TIME_BASE*(int64_t)st->time_base.num, st->time_base.den);
for(i = 0; i < s->nb_streams; i++) { for(i = 0; i < s->nb_streams; i++) {
st = s->streams[i]; AVStream *st2 = s->streams[i];
st->cur_dts = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE*(int64_t)st->time_base.num); st->cur_dts = av_rescale(ie->timestamp,
st2->time_base.den * (int64_t)st ->time_base.num,
st ->time_base.den * (int64_t)st2->time_base.num);
} }
return 0; return 0;
} }
/** /**
* Seek to the key frame just before the frame at timestamp * Seek to the key frame at timestamp.
* 'timestamp' in 'stream_index'. * 'timestamp' in 'stream_index'.
* @param stream_index If stream_index is (-1), a default * @param stream_index If stream_index is (-1), a default
* stream is selected * stream is selected
* @param timestamp timestamp in AV_TIME_BASE units * @param timestamp timestamp in AVStream.time_base units
* @param flags flags which select direction and seeking mode
* @return >= 0 on success * @return >= 0 on success
*/ */
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp) int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
{ {
int ret; int ret;
AVStream *st; AVStream *st;
av_read_frame_flush(s); av_read_frame_flush(s);
if(flags & AVSEEK_FLAG_BYTE)
return av_seek_frame_byte(s, stream_index, timestamp, flags);
if(stream_index < 0){ if(stream_index < 0){
stream_index= av_find_default_stream_index(s); stream_index= av_find_default_stream_index(s);
if(stream_index < 0) if(stream_index < 0)
return -1; return -1;
}
st= s->streams[stream_index];
st= s->streams[stream_index];
timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num); timestamp = av_rescale(timestamp, st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
}
st= s->streams[stream_index];
/* first, we try the format specific seek */ /* first, we try the format specific seek */
if (s->iformat->read_seek) if (s->iformat->read_seek)
ret = s->iformat->read_seek(s, stream_index, timestamp); ret = s->iformat->read_seek(s, stream_index, timestamp, flags);
else else
ret = -1; ret = -1;
if (ret >= 0) { if (ret >= 0) {
...@@ -1235,9 +1269,9 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp) ...@@ -1235,9 +1269,9 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp)
} }
if(s->iformat->read_timestamp) if(s->iformat->read_timestamp)
return av_seek_frame_binary(s, stream_index, timestamp); return av_seek_frame_binary(s, stream_index, timestamp, flags);
else else
return av_seek_frame_generic(s, stream_index, timestamp); return av_seek_frame_generic(s, stream_index, timestamp, flags);
} }
/*******************************************************/ /*******************************************************/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment