diff --git a/libavformat/avformat.h b/libavformat/avformat.h index df87339e8bb8d8add9507895dbdddb12cde3a434..8fec18deee2a652b162d28837677e689203f6674 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -472,6 +472,7 @@ int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); int av_add_index_entry(AVStream *st, 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); +void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); /* media file output */ int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); diff --git a/libavformat/ogg2.c b/libavformat/ogg2.c index 2af5a4f9aada03d47b768b485e6f01b9947ee7e3..254415b7a37fe20b932e2f730e4f314c722bdcca 100644 --- a/libavformat/ogg2.c +++ b/libavformat/ogg2.c @@ -201,7 +201,6 @@ ogg_new_stream (AVFormatContext * s, uint32_t serial) return AVERROR_NOMEM; av_set_pts_info(st, 64, 1, 1000000); - st->start_time = 0; return idx; } @@ -495,6 +494,16 @@ ogg_get_length (AVFormatContext * s) ogg->size = size; 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; } @@ -572,12 +581,14 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, ogg_t *ogg = s->priv_data; ByteIOContext *bc = &s->pb; 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; 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); int i = -1; @@ -599,9 +610,25 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, break; 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; tmax = pts; }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; tmin = pts; } @@ -615,7 +642,8 @@ ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts, pts = AV_NOPTS_VALUE; } - return pts; + av_update_cur_dts(s, st, pts); + return 0; #if 0 //later... diff --git a/libavformat/utils.c b/libavformat/utils.c index 2c882faf4401bae85ee2d45390120204d880ffba..cefce88abca32ac69c6ecba5aae559f64b7496e2 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -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 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; for(i = 0; i < s->nb_streams; i++) {