[FFmpeg-cvslog] avformat/vobsub: fix seeking.

Clément Bœsch git at videolan.org
Tue Sep 10 21:50:28 CEST 2013


ffmpeg | branch: release/1.2 | Clément Bœsch <u at pkh.me> | Sun Sep  8 09:43:53 2013 +0200| [8cea63c48ae004b240a925bcbd882985928149bd] | committer: Clément Bœsch

avformat/vobsub: fix seeking.

(cherry picked from commit f8678dcef3c5b0ea82e898e1f419863409fa135f)

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=8cea63c48ae004b240a925bcbd882985928149bd
---

 libavformat/mpeg.c      |   16 ++++++++++++++++
 libavformat/subtitles.c |   16 ++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 4eaffd8..82957a1 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -649,6 +649,7 @@ static int vobsub_read_header(AVFormatContext *s)
             st->id = stream_id;
             st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
             st->codec->codec_id   = AV_CODEC_ID_DVD_SUBTITLE;
+            avpriv_set_pts_info(st, 64, 1, 1000);
             av_dict_set(&st->metadata, "language", id, 0);
             av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id);
             header_parsed = 1;
@@ -806,6 +807,21 @@ static int vobsub_read_seek(AVFormatContext *s, int stream_index,
                             int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
 {
     MpegDemuxContext *vobsub = s->priv_data;
+
+    /* Rescale requested timestamps based on the first stream (timebase is the
+     * same for all subtitles stream within a .idx/.sub). Rescaling is done just
+     * like in avformat_seek_file(). */
+    if (stream_index == -1 && s->nb_streams != 1) {
+        AVRational time_base = s->streams[0]->time_base;
+        ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
+        min_ts = av_rescale_rnd(min_ts, time_base.den,
+                                time_base.num * (int64_t)AV_TIME_BASE,
+                                AV_ROUND_UP   | AV_ROUND_PASS_MINMAX);
+        max_ts = av_rescale_rnd(max_ts, time_base.den,
+                                time_base.num * (int64_t)AV_TIME_BASE,
+                                AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
+    }
+
     return ff_subtitles_queue_seek(&vobsub->q, s, stream_index,
                                    min_ts, ts, max_ts, flags);
 }
diff --git a/libavformat/subtitles.c b/libavformat/subtitles.c
index 37ba0cb..e128bce 100644
--- a/libavformat/subtitles.c
+++ b/libavformat/subtitles.c
@@ -108,7 +108,8 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st
         for (i = 0; i < q->nb_subs; i++) {
             int64_t pts = q->subs[i].pts;
             uint64_t ts_diff = FFABS(pts - ts);
-            if (pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) {
+            if ((stream_index == -1 || q->subs[i].stream_index == stream_index) &&
+                pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) {
                 min_ts_diff = ts_diff;
                 idx = i;
             }
@@ -118,13 +119,24 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st
         /* look back in the latest subtitles for overlapping subtitles */
         ts_selected = q->subs[idx].pts;
         for (i = idx - 1; i >= 0; i--) {
-            if (q->subs[i].duration <= 0)
+            if (q->subs[i].duration <= 0 ||
+                (stream_index != -1 && q->subs[i].stream_index != stream_index))
                 continue;
             if (q->subs[i].pts > ts_selected - q->subs[i].duration)
                 idx = i;
             else
                 break;
         }
+
+        /* If the queue is used to store multiple subtitles streams (like with
+         * VobSub) and the stream index is not specified, we need to make sure
+         * to focus on the smallest file position offset for a same timestamp;
+         * queue is ordered by pts and then filepos, so we can take the first
+         * entry for a given timestamp. */
+        if (stream_index == -1)
+            while (idx > 0 && q->subs[idx - 1].pts == q->subs[idx].pts)
+                idx--;
+
         q->current_sub_idx = idx;
     }
     return 0;



More information about the ffmpeg-cvslog mailing list