On Mon, 16 Mar 2015, Derek Buitenhuis wrote:

The current behavior may produce packets in a different order
after seeking, compared to demuxing linearly from the beginning.
This is because the MOV demuxer seeks in each stream based on
timestamp, which may not necessarily match the original packet
order.

The wording here makes it sound weirder than it is - packets sure are returned in the same order (i.e. there is no pair of packets that are returned in a different order than before) - just that some streams may start further ahead/behind.

What about:

The current behavior may produce a different sequence of packets after seeking, compared to demuxing linearly from the beginning. This is because the MOV demuxer seeks in each stream individually, based on timestamp, which may set each stream at a slightly different position than if the file would have been read sequentially.

This makes implementing certain operations, such as segmenting,
quite hard, and slower than need be.

Therefore, add an option which retains the same packet order
after seeking, as when a file is demuxed linearly. This is
accomplished by seeking in the other streams, based on file
position, rather than timestamp.

The positional search in the index entries is implemented as
a linear search since, in MOV, the index entries may be out of
order in terms of file position, in particularily insane files.

Technically, this isn't a complete guarantee either. The cases where it'd break down sure are pathological though, but I think an even better solution isn't much harder.

This would break down if samples from within one single track aren't linearly ordered within the file - consider this pathological case:

0v0 0a1 1v2 1a9 2v3 3v4 2a5 3a6

(Where XvY means packet X in stream v, at byte pos Y.)

So the audio stream is muxed non-linearly - packet 1 in stream a is at byte pos 9, which is much further. If seeking to 3v, the audio stream would start at 3a right now; you want it to start at 2a, but it would stop at packet 1a since it has got a byte pos higher than the seek target pos.

Yes, this is quite pathological, but if you're going to do a linear search, you can just as well do one that actually does the same thing as actual reading (sans reading the packet payloads).

I actually tried doing this, and it doesn't seem to be any harder (the code actually turned out shorter). I'll post an updated patch showing how I did this.

@@ -3500,6 +3537,10 @@ static int mov_read_seek(AVFormatContext *s, int 
stream_index, int64_t sample_ti
#define OFFSET(x) offsetof(MOVContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption mov_options[] = {
+    {"seek_keep_order",
+        "If seeking, keep the same packet demuxing order as if demuxing 
linearly.",
+        OFFSET(seek_keep_order), AV_OPT_TYPE_INT, { .i64 = 0 },
+        0, 1, FLAGS},

I'm not totally satisified with this option name, but I'm not sure what to call it instead. Because there _is_ a tradeoff at place, while this makes it sound like "sure - why would I _not_ want it?".

FWIW, when testing this on a file that isn't completely perfectly interleaved (with samples in 0.5 second chunks per stream), I get a 0.5 second burst of frames played rapidly after seeking in avplay, while I get perfect playback immediately when seeking with the code as it is today. So for playback I think the current behaviour may make more sense.

What about this?

+    {"seek_streams_individually",
+        "Seek each stream individually to the to the closest point "
+        OFFSET(seek_individually), AV_OPT_TYPE_INT, { .i64 = 1 },
+        0, 1, FLAGS},


I'll send an updated version of the patch with the changes I mentioned.

// Martin
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to