if (err < 0)
goto fail;
- if (pb)
+ if (pb && !ic->data_offset)
ic->data_offset = url_ftell(&ic->pb);
*ic_ptr = ic;
AVInputFormat *avif= s->iformat;
int64_t pos_min, pos_max, pos, pos_limit;
int64_t ts_min, ts_max, ts;
- int64_t start_pos, filesize;
- int index, no_change;
+ int index;
AVStream *st;
if (stream_index < 0)
}
}
+ pos= av_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp);
+ if(pos<0)
+ return -1;
+
+ /* do the seek */
+ url_fseek(&s->pb, pos, SEEK_SET);
+
+ av_update_cur_dts(s, st, ts);
+
+ return 0;
+}
+
+/**
+ * Does a binary search using read_timestamp().
+ * this isnt supposed to be called directly by a user application, but by demuxers
+ * @param target_ts target timestamp in the time base of the given stream
+ * @param stream_index stream number
+ */
+int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )){
+ int64_t pos, ts;
+ int64_t start_pos, filesize;
+ int no_change;
+
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_DEBUG, "gen_seek: %d %"PRId64"\n", stream_index, target_ts);
+#endif
+
if(ts_min == AV_NOPTS_VALUE){
pos_min = s->data_offset;
- ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
if (ts_min == AV_NOPTS_VALUE)
return -1;
}
pos_max = filesize - 1;
do{
pos_max -= step;
- ts_max = avif->read_timestamp(s, stream_index, &pos_max, pos_max + step);
+ ts_max = read_timestamp(s, stream_index, &pos_max, pos_max + step);
step += step;
}while(ts_max == AV_NOPTS_VALUE && pos_max >= step);
if (ts_max == AV_NOPTS_VALUE)
for(;;){
int64_t tmp_pos= pos_max + 1;
- int64_t tmp_ts= avif->read_timestamp(s, stream_index, &tmp_pos, INT64_MAX);
+ int64_t tmp_ts= read_timestamp(s, stream_index, &tmp_pos, INT64_MAX);
if(tmp_ts == AV_NOPTS_VALUE)
break;
ts_max= tmp_ts;
pos= pos_limit;
start_pos= pos;
- ts = avif->read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1
+ ts = read_timestamp(s, stream_index, &pos, INT64_MAX); //may pass pos_limit instead of -1
if(pos == pos_max)
no_change++;
else
ts = (flags & AVSEEK_FLAG_BACKWARD) ? ts_min : ts_max;
#ifdef DEBUG_SEEK
pos_min = pos;
- ts_min = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
pos_min++;
- ts_max = avif->read_timestamp(s, stream_index, &pos_min, INT64_MAX);
+ ts_max = read_timestamp(s, stream_index, &pos_min, INT64_MAX);
av_log(s, AV_LOG_DEBUG, "pos=0x%"PRIx64" %"PRId64"<=%"PRId64"<=%"PRId64"\n",
pos, ts_min, target_ts, ts_max);
#endif
- /* do the seek */
- url_fseek(&s->pb, pos, SEEK_SET);
-
- av_update_cur_dts(s, st, ts);
-
- return 0;
+ *ts_ret= ts;
+ return pos;
}
static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){