Commit 22ffac70 authored by Reimar Döffinger's avatar Reimar Döffinger

Try to find out correct start time to make seeking faster and add some

extra checks to make sure the seeking function will not hang forever.

Originally committed as revision 5814 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 8dfe9094
...@@ -472,6 +472,7 @@ int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); ...@@ -472,6 +472,7 @@ int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
int av_add_index_entry(AVStream *st, int av_add_index_entry(AVStream *st,
int64_t pos, int64_t timestamp, int size, int distance, int flags); int64_t pos, int64_t timestamp, int size, int distance, int flags);
int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags); int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags);
void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp);
/* media file output */ /* media file output */
int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
......
...@@ -201,7 +201,6 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial) ...@@ -201,7 +201,6 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial)
return AVERROR_NOMEM; return AVERROR_NOMEM;
av_set_pts_info(st, 64, 1, 1000000); av_set_pts_info(st, 64, 1, 1000000);
st->start_time = 0;
return idx; return idx;
} }
...@@ -495,6 +494,16 @@ ogg_get_length (AVFormatContext * s) ...@@ -495,6 +494,16 @@ ogg_get_length (AVFormatContext * s)
ogg->size = size; ogg->size = size;
ogg_restore (s, 0); ogg_restore (s, 0);
ogg_save (s);
while (ogg_read_page (s, &i)) {
if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
break;
}
if (i == idx) {
s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
s->streams[idx]->duration -= s->streams[idx]->start_time;
}
ogg_restore (s, 0);
return 0; return 0;
} }
...@@ -572,12 +581,14 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, ...@@ -572,12 +581,14 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
ogg_t *ogg = s->priv_data; ogg_t *ogg = s->priv_data;
ByteIOContext *bc = &s->pb; ByteIOContext *bc = &s->pb;
uint64_t min = 0, max = ogg->size; uint64_t min = 0, max = ogg->size;
uint64_t tmin = 0, tmax = st->duration; uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
int64_t pts = AV_NOPTS_VALUE; int64_t pts = AV_NOPTS_VALUE;
ogg_save (s); ogg_save (s);
while (min <= max){ if ((uint64_t)target_ts < tmin || target_ts < 0)
target_ts = tmin;
while (min <= max && tmin < tmax){
uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin); uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
int i = -1; int i = -1;
...@@ -599,9 +610,25 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, ...@@ -599,9 +610,25 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
break; break;
if (pts > target_ts){ if (pts > target_ts){
if (max == p && tmax == pts) {
// probably our tmin is wrong, causing us to always end up too late in the file
tmin = (target_ts + tmin + 1) / 2;
if (tmin == target_ts) {
url_fseek(bc, min, SEEK_SET);
break;
}
}
max = p; max = p;
tmax = pts; tmax = pts;
}else{ }else{
if (min == p && tmin == pts) {
// probably our tmax is wrong, causing us to always end up too early in the file
tmax = (target_ts + tmax) / 2;
if (tmax == target_ts) {
url_fseek(bc, max, SEEK_SET);
break;
}
}
min = p; min = p;
tmin = pts; tmin = pts;
} }
...@@ -615,7 +642,8 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, ...@@ -615,7 +642,8 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
pts = AV_NOPTS_VALUE; pts = AV_NOPTS_VALUE;
} }
return pts; av_update_cur_dts(s, st, pts);
return 0;
#if 0 #if 0
//later... //later...
......
...@@ -1097,7 +1097,7 @@ static void av_read_frame_flush(AVFormatContext *s) ...@@ -1097,7 +1097,7 @@ static void av_read_frame_flush(AVFormatContext *s)
* @param timestamp new dts expressed in time_base of param ref_st * @param timestamp new dts expressed in time_base of param ref_st
* @param ref_st reference stream giving time_base of param timestamp * @param ref_st reference stream giving time_base of param timestamp
*/ */
static void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){
int i; int i;
for(i = 0; i < s->nb_streams; i++) { for(i = 0; i < s->nb_streams; i++) {
......
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