[FFmpeg-devel] [RFC] mpegts: Provide a monotonic timestamp to the outside world

Harald Axmann harald.axmann at hotmail.com
Wed Oct 24 21:20:07 CEST 2012


On 23.10.2012 03:59, Michael Niedermayer wrote:
> On Mon, Oct 22, 2012 at 11:39:34PM +0200, Harald Axmann wrote:
>> But just as a fundamental question: Is there any reason to keep the
>> original time stamp, as Hendrik Leppkes requested. [...]
> assume you have external references to timestamps, or you want to
> cut and then merge pieces of TS without timestamps changing
> or you have a audio and a video TS file and want them syncronized
> against each other (assuming their timestamps allow this)
> i guess there are many other cases ...

Okay, I understand.

On Mon, Oct 22, 2012 at 11:39:34PM +0200, Harald Axmann wrote:
> What I could do is have a look if it is possible to change XBMC's 
> seeking algorithm to a byte-based version for file formats allowing 
> discontinuities. Perhaps this would be the cleanest solution for XBMC.

I had a look at the seeking algorithm in FFmpeg. XBMC calls 
av_seek_frame, which then decides to use time based search, not byte 
based (AVSEEK_FLAG_BYTE not set for mpegts). So I conclude that for a 
proper TS file time based search is yet adequate.

So we could try to find a basic solution, which does not break anything 
and fixes seeking for proper TS files (with PCR wrap) at least. Before I 
prepared the code to patch the mpegts time stamp, I proposed a fix of 
ff_gen_search, which adds time stamp wrapping there (see the attached 
patch). It was dropped, because it breaks the index.

On Sun Aug 19 17:09:31 CEST 2012, Michael Niedermayer wrote:
> the first problem is the index (see av_index* and ff_seek_frame_binary)
> it is required to be ordered and it wont be for such files.

In fact XBMC uses an older version of FFmpeg, which never builds an 
index for mpegts, as I read the code. So the problem never showed up. 
Anyway I think that it is reasonable to add wrapping to ff_gen_search. 
After all it does not make sense to search for time stamp, that cannot 
even exist in the file.

Of course for the current state of FFmpeg we would have to find a 
solution for the index. I will have a look at it.

What do think of this proposal in general?

[1] http://ffmpeg.org/pipermail/ffmpeg-devel/2012-August/129720.html
-------------- next part --------------
diff --git a/lib/ffmpeg/libavformat/utils.c b/lib/ffmpeg/libavformat/utils.c
index 63f89dd..f6dc2ad 100644
--- a/lib/ffmpeg/libavformat/utils.c
+++ b/lib/ffmpeg/libavformat/utils.c
@@ -1699,6 +1700,8 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
         return pos_min;
     }
 
+    target_ts = (target_ts - ts_min) & timestamp_mask;
+
     if(ts_max == AV_NOPTS_VALUE){
         int step= 1024;
         filesize = avio_size(s->pb);
@@ -1706,6 +1709,8 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
         do{
             pos_max -= step;
             ts_max = read_timestamp(s, stream_index, &pos_max, pos_max + step);
+            if(ts_max != AV_NOPTS_VALUE)
+                ts_max = (ts_max - ts_min) & timestamp_mask;
             step += step;
         }while(ts_max == AV_NOPTS_VALUE && pos_max >= step);
         if (ts_max == AV_NOPTS_VALUE)
@@ -1716,13 +1721,17 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
             int64_t tmp_ts= read_timestamp(s, stream_index, &tmp_pos, INT64_MAX);
             if(tmp_ts == AV_NOPTS_VALUE)
                 break;
-            ts_max= tmp_ts;
+            ts_max= (tmp_ts - ts_min) & timestamp_mask;
             pos_max= tmp_pos;
             if(tmp_pos >= filesize)
                 break;
         }
         pos_limit= pos_max;
-    }
+    }else
+        ts_max = (ts_max - ts_min) & timestamp_mask;
+
+    int64_t ts_min_orig = ts_min;
+    ts_min = 0;
 
     if(ts_max <= target_ts){
         *ts_ret= ts_max;
@@ -1773,6 +1782,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
             return -1;
         }
         assert(ts != AV_NOPTS_VALUE);
+        ts = (ts - ts_min_orig) & timestamp_mask;
         if (target_ts <= ts) {
             pos_limit = start_pos - 1;
             pos_max = pos;
@@ -1786,6 +1796,7 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts,
 
     pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
     ts  = (flags & AVSEEK_FLAG_BACKWARD) ?  ts_min :  ts_max;
+    ts  = (ts + ts_min_orig) & timestamp_mask;
 #if 0
     pos_min = pos;
     ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX);


More information about the ffmpeg-devel mailing list