After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 652195 - matroskademux: seeking in non-finalized matroska files does not work correctly
matroskademux: seeking in non-finalized matroska files does not work correctly
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other Linux
: Normal normal
: 0.10.31
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2011-06-09 14:24 UTC by Branko Subasic
Modified: 2011-12-21 18:31 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch for improving seeking in not-yet-finalized files (1.11 KB, patch)
2011-06-09 14:24 UTC, Branko Subasic
none Details | Review
Avoid looping when searching for clusters in a file still being recorded (2.79 KB, patch)
2011-06-16 13:07 UTC, Branko Subasic
committed Details | Review
test prog (4.69 KB, text/x-csrc)
2011-09-14 15:00 UTC, Branko Subasic
  Details
Scan file for time code of the last block in the last cluster (10.96 KB, patch)
2011-12-20 14:22 UTC, Branko Subasic
none Details | Review
Adds function for scanning byte reader backwards (9.68 KB, patch)
2011-12-20 14:23 UTC, Branko Subasic
none Details | Review
matroskademux: do not consider duration of non-finalized file (2.97 KB, patch)
2011-12-21 14:43 UTC, Mark Nauwelaerts
none Details | Review
Always invalidate duration for non-finalized files (2.97 KB, patch)
2011-12-21 16:47 UTC, Branko Subasic
committed Details | Review

Description Branko Subasic 2011-06-09 14:24:18 UTC
Created attachment 189549 [details] [review]
Patch for improving seeking in not-yet-finalized files

Create the following pipeline.

filesrc ! matroskademux ! queue ! ffdec_h264 ! xvimagesink

Put the pipeline in PAUSED state.
Do a seek a bit into a matroska file and then put the pipeline in playing state.

This works fine with a matroska file that is finalized, i.e. finished.
But if you try the same with a matroska file that is not finalized, e.g. still
being recorded, then seeking is only possible in the segment defined by the buffers queued in the queue.

When playing a file that is still being recorded the duration is not yet written to the matroska file header, and the demuxer will update it's segment's duration whenever it reads a new frame from the file. In the case of the pipline above it means that the duration will be what the 'max-size-time' property of the queue is set to. Because that's how much the demuxer has read so far. 
Then, when creating the seeksegment, gst_segment_set_seek() will CLAMP the start and stop variables so that they do not exceed the actual duration of the segment.

I have attached a attached a patch to the demuxer that I think solves the problem. Could you please take a look at it?

/Branko
Comment 1 Branko Subasic 2011-06-16 13:07:56 UTC
Created attachment 190041 [details] [review]
Avoid looping when searching for clusters in a file still being recorded
Comment 2 Tim-Philipp Müller 2011-07-01 18:00:48 UTC
I'm not so sure about the seeking patch. Not that I think it's wrong, I just don't really think it improves behaviour that much. Isn't there something more clever we can do in the demuxer, like scan backwards from file end to get a timecode and figure out the duration? Check upstream for size changes? etc.
Comment 3 Branko Subasic 2011-09-14 15:00:52 UTC
Created attachment 196504 [details]
test prog

Attached a small C-program that shows the problem. It sets up a pipeline as described above, pauses, seeks from 5-10 secs, and then goes to play. Works fine with a finalized file.

With a non-finalized file, however, it only works with the seek patch.
Comment 4 Branko Subasic 2011-12-20 14:22:04 UTC
Created attachment 203953 [details] [review]
Scan file for time code of the last block in the last cluster

New way of handling files with unknown duration. Before the seek is done a check is made to see if the file size has changed since the previous seek. If it has then the file is scanned backwards to find the last cluster. The time code of the last block in the last cluster will be set as new duration.
Comment 5 Branko Subasic 2011-12-20 14:23:21 UTC
Created attachment 203954 [details] [review]
Adds function for scanning byte reader backwards

Make sit possible to scan the byte reader data backwards
Comment 6 Mark Nauwelaerts 2011-12-21 14:43:21 UTC
Created attachment 204040 [details] [review]
matroskademux: do not consider duration of non-finalized file

While it is slightly painful saying so given the effort that has been put into the previous patches, it seems those patches introduce a whole lot of code and complexity for a play/seek-file-being-created (corner) case

More importantly, however, I believe the present patch also supports this corner case in a much easier and clearer way, namely simply invalidate the (currently determined) duration in the segment (to avoid it messing with requested seek position).  This is also not really a hack, since the duration being invalidated is not really that valid/informative anyway (and only temporary).

Likewise, the duration being determined (by lots of code seeking/scanning to the end) is only "marginal" in that it will be outdated the moment it is determined (as the file is still growing in this case).  In particular, e.g. truncating a requested segment.stop position to an updated (but already outdated) duration would not be quite right either, since the file could still grow that position.  And moreover, performing a seek near the end will have the duration updated anyway (when streaming resumes at that point).
Comment 7 Branko Subasic 2011-12-21 14:55:52 UTC
Well, my first attempt was to set the duration of the seeksegment to -1, i.e. to invalidate the duration. Patch is included in my first post above. That solved the problem. Those few lines, perhaps combined with checking whether the file size has changed, would solve the problem with ~350 lines less of code than my last patch. Would that be OK?
Comment 8 Mark Nauwelaerts 2011-12-21 15:04:11 UTC
It would be OK in my book; the hackish-level of the first version has been somewhat mitigated by doing the size check (in view of Comment #2).

And as said, doing a whole lot of clever stuff which will only yield outdated results (given the situation of a moving target) seems marginally beneficial (to say the least).

But that may all be just me ... ;)
Comment 9 Branko Subasic 2011-12-21 15:24:20 UTC
Couldn't agree more ;-)
Sorry for my previous post. Didn't see that you had already done what I suggested.

However, I think we need to change the patch slightly. It doesn't work with a non-finalized file that doesn't grow, for example a file that is the result of a recording being interrupted. In that case only the first seek will result in the duration being invalidated. The following seeks the file size will not have changed, and the current duration of the segment will be used to clamp the seek.

We either have to invalidate the duration every time (for non-finalized files only, of course), or save the duration in the segment.
Comment 10 Mark Nauwelaerts 2011-12-21 15:34:32 UTC
Hm, yes, how to detect/define non-finalized; probably checking whether file has a valid recorded duration ?

So, what about:
* if duration is ever updated by _parse_block whatever
=> assume file does not have a valid duration => invalidate when seeking
* otherwise, do not mess with duration
Comment 11 Branko Subasic 2011-12-21 16:47:52 UTC
Created attachment 204046 [details] [review]
Always invalidate duration for non-finalized files

Last (?) patch. If the segment duration is ever updated in the gst_matroska_demux_parse_blockgroup_or_simpleblock function the file is considered non-finalized, and the duration is always invalidated when seeking.
Comment 12 Mark Nauwelaerts 2011-12-21 17:20:34 UTC
OK, thanks, committed:

--- master ----
commit a7d6690f92e6c739d3b3e28d99d1f7840f8c59d9
Author: Branko Subasic <branko@axis.com>
Date:   Wed Dec 21 17:43:10 2011 +0100

    matroskademux: do not consider duration of non-finalized file
    
    ... to avoid it clamping requested seek position.
    
    Non-finalized file case, determined by whether
    _parse_blockgroup_or_simpleblock ever updates the segment duration.
    
    Fixes #652195.

---- 0.10 ----
commit 49b228fe33fbe6360a30563277a2c222bc729cf7
Author: Branko Subasic <branko@axis.com>
Date:   Wed Dec 21 17:43:10 2011 +0100

    matroskademux: do not consider duration of non-finalized file
    
    ... to avoid it clamping requested seek position.
    
    Non-finalized file case, determined by whether
    _parse_blockgroup_or_simpleblock ever updates the segment duration.
    
    Fixes #652195.
Comment 13 Branko Subasic 2011-12-21 18:31:13 UTC
Great, thanks for taking the time.