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 721666 - videodecoder: push newsegment earlier for reverse playback
videodecoder: push newsegment earlier for reverse playback
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
unspecified
Other All
: Normal normal
: 1.2.3
Assigned To: GStreamer Maintainers
GStreamer Maintainers
: 681634 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2014-01-07 00:09 UTC by Thiago Sousa Santos
Modified: 2014-01-13 11:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
videodecoder: push newsegment earlier for reverse playback (1.77 KB, patch)
2014-01-07 00:09 UTC, Thiago Sousa Santos
needs-work Details | Review
videodecoder: use new segment earlier for reverse playback (2.44 KB, patch)
2014-01-08 15:26 UTC, Thiago Sousa Santos
reviewed Details | Review
tests: videodecoder: add test for reverse playback (8.70 KB, patch)
2014-01-08 15:26 UTC, Thiago Sousa Santos
committed Details | Review
videodecoder: use new segment earlier for reverse playback (2.87 KB, patch)
2014-01-10 13:09 UTC, Thiago Sousa Santos
committed Details | Review
Log time seek (61.61 KB, text/plain)
2014-01-10 16:28 UTC, Eric
  Details

Description Thiago Sousa Santos 2014-01-07 00:09:45 UTC
For reverse playback, videodecoder creates a list of frames to push
and then reverses it and pushes. The problem is that the frame events
will get attached to the 1st buffer of the list. So, they will be pushed
last.

This causes an assertion as a few buffers will be pushed before a new segment
event for example.

My concern here is which/how to push events without breaking serialization.
Should we care about multiple new segments in the list? What about caps events?
Comment 1 Thiago Sousa Santos 2014-01-07 00:09:48 UTC
Created attachment 265488 [details] [review]
videodecoder: push newsegment earlier for reverse playback

As events are 'attached' to video frames in videodecoder, when doing
reverse playback the new segment event will be attached to the
first frame. And this frame is pushed last, so a few frames are
pushed before a new segment.

To prevent this, iterate over the list of pending frame events and push
the new segment event before processing the buffers.
Comment 2 Sebastian Dröge (slomo) 2014-01-07 08:04:19 UTC
Comment on attachment 265488 [details] [review]
videodecoder: push newsegment earlier for reverse playback

You need to push all events <= SEGMENT here. Also I think you need to do that while pushing all the frames, and there make sure that handling of multiple events of the same type is done in order. That is, push the oldest SEGMENT event, then buffers that come before it. Then the next SEGMENT event, then buffers before that, etc.
Comment 3 Thiago Sousa Santos 2014-01-08 15:26:01 UTC
Created attachment 265711 [details] [review]
videodecoder: use new segment earlier for reverse playback

For reverse playback, the segment event will only be pushed when
the first buffer is actually pushed. But for decoding frames and storing
those into the list to be pushed the output_segment.rate value is used
to determine if it is forward or reverse playback.

In case a previous segment event (or none) is in use it will mistakenly
think it is doing forward playback and push the buffers immediatelly and
try to clip buffers based on an old segment (or an uninitialized one, leading
to an assertion)

This patch fixes this by copying the segment earlier if on reverse playback
Comment 4 Thiago Sousa Santos 2014-01-08 15:26:08 UTC
Created attachment 265712 [details] [review]
tests: videodecoder: add test for reverse playback

Checks that buffers are pushed backwards in reverse playback
Comment 5 Sebastian Dröge (slomo) 2014-01-09 16:34:15 UTC
I think this is only a workaround. You should not special case the segment event, but handle all events < segment like this and properly push them at the right time.
Comment 6 Thiago Sousa Santos 2014-01-09 16:40:58 UTC
(In reply to comment #5)
> I think this is only a workaround. You should not special case the segment
> event, but handle all events < segment like this and properly push them at the
> right time.

AFAIK they are being pushed on the right time, the problem is on decoder_finish_frame:

  if (decoder->output_segment.rate < 0.0) {
    GST_LOG_OBJECT (decoder, "queued frame");
    priv->output_queued = g_list_prepend (priv->output_queued, output_buffer);
  } else {
    ret = gst_video_decoder_clip_and_push_buf (decoder, output_buffer);
  }

It needs the output_segment to be properly set to be able to know if it is doing reverse playback and avoiding trying to push the buffers.

Note that the segment event isn't discarded or pushed at that check, it is just applied to output_segment so this piece of code works reliably.
Comment 7 Sebastian Dröge (slomo) 2014-01-09 16:50:21 UTC
I see, but this could cause the wrong segment to be set if there are multiple ones, right? They will all have the same playback direction but might have other differences. But I guess this is fine, it will do the right thing later on as far as I can see it
Comment 8 Sebastian Dröge (slomo) 2014-01-10 08:27:23 UTC
*** Bug 681634 has been marked as a duplicate of this bug. ***
Comment 9 Thiago Sousa Santos 2014-01-10 13:09:27 UTC
Created attachment 265913 [details] [review]
videodecoder: use new segment earlier for reverse playback

Updated patch to make sure that the relevant events are pushed
before any buffer, otherwise we can get 'buffer before segment' asserts
Comment 10 Sebastian Dröge (slomo) 2014-01-10 13:16:32 UTC
Review of attachment 265913 [details] [review]:

Makes sense, does it also fix the duplicate here and the other bug about the segment format?
Comment 11 Thiago Sousa Santos 2014-01-10 13:23:58 UTC
It fixes the duplicate, waiting for confirmation on the other bug before pushing.
Comment 12 Eric 2014-01-10 16:28:49 UTC
Created attachment 265943 [details]
Log time seek

This is what hapen when the src element accept a seek with format = GST_FORMAT_TIME so no byte offset is calculated.

It look like the gst_element_seek never exit;
Comment 13 Eric 2014-01-10 16:41:14 UTC
(In reply to comment #12)
> Created an attachment (id=265943) [details]
> Log time seek
> 
> This is what hapen when the src element accept a seek with format =
> GST_FORMAT_TIME so no byte offset is calculated.
> 
> It look like the gst_element_seek never exit;
Actually, it does exit, but then I have to kill my application to stop it...
I'll try to provide more details...
Comment 14 Eric 2014-01-10 16:51:52 UTC
Looks like in my case, gst_video_decoder_flush_parse isn't even called...
Comment 15 Aleix Conchillo Flaqué 2014-01-11 01:06:11 UTC
Review of attachment 265913 [details] [review]:

::: gst-libs/gst/video/gstvideodecoder.c
@@ +1961,3 @@
+          GST_ERROR_OBJECT (dec, "Segment at frame %p %" GST_TIME_FORMAT,
+              frame, GST_TIME_ARGS (GST_BUFFER_PTS (frame->input_buffer)));
+          gst_event_copy_segment (event, &segment);

Isn't using GST_ERROR_OBJECT a problem?
Comment 16 Aleix Conchillo Flaqué 2014-01-11 01:16:08 UTC
Review of attachment 265913 [details] [review]:

::: gst-libs/gst/video/gstvideodecoder.c
@@ +1968,3 @@
+        dec->priv->pending_events =
+            g_list_append (dec->priv->pending_events, event);
+        frame->events = g_list_delete_link (frame->events, cur);

Trying to understand the patch.

Why do we need to move the event from the frame and put it in the pending events list?

Don't they get all pushed in gst_video_decoder_prepare_finish_frame? First, the pending events and then the frame events?
Comment 17 Thiago Sousa Santos 2014-01-13 09:28:46 UTC
Pushed to master

commit b1e728a8540d6aab44d4b7c489120b3acf896385
Author: Thiago Santos <ts.santos@sisa.samsung.com>
Date:   Wed Jan 8 11:29:29 2014 -0300

    tests: videodecoder: add test for reverse playback
    
    Checks that buffers are pushed backwards in reverse playback
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721666

commit 5b8e1925b566b57b516c76f12610d42e6ad2b791
Author: Thiago Santos <ts.santos@sisa.samsung.com>
Date:   Mon Jan 6 20:53:15 2014 -0300

    videodecoder: use new segment earlier for reverse playback
    
    For reverse playback, the segment event will only be pushed when
    the first buffer is actually pushed. But for decoding frames and storing
    those into the list to be pushed the output_segment.rate value is used
    to determine if it is forward or reverse playback.
    
    In case a previous segment event (or none) is in use it will mistakenly
    think it is doing forward playback and push the buffers immediatelly and
    try to clip buffers based on an old segment (or an uninitialized one, leading
    to an assertion)
    
    This patch fixes this by copying the segment earlier if on reverse playback
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721666
Comment 18 Thiago Sousa Santos 2014-01-13 11:15:05 UTC
Pushed to 1.2

commit bcc99d6d7a069473a93ecf8b72e5bdfe78f78096
Author: Thiago Santos <ts.santos@sisa.samsung.com>
Date:   Wed Jan 8 11:29:29 2014 -0300

    tests: videodecoder: add test for reverse playback
    
    Checks that buffers are pushed backwards in reverse playback
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721666

commit 6216366d25eb327dc18803a5bded793b434f6aa5
Author: Thiago Santos <ts.santos@sisa.samsung.com>
Date:   Mon Jan 6 20:53:15 2014 -0300

    videodecoder: use new segment earlier for reverse playback
    
    For reverse playback, the segment event will only be pushed when
    the first buffer is actually pushed. But for decoding frames and storing
    those into the list to be pushed the output_segment.rate value is used
    to determine if it is forward or reverse playback.
    
    In case a previous segment event (or none) is in use it will mistakenly
    think it is doing forward playback and push the buffers immediatelly and
    try to clip buffers based on an old segment (or an uninitialized one, leading
    to an assertion)
    
    This patch fixes this by copying the segment earlier if on reverse playback
    
    https://bugzilla.gnome.org/show_bug.cgi?id=721666
Comment 19 Thiago Sousa Santos 2014-01-13 11:15:52 UTC
(In reply to comment #15)
> Review of attachment 265913 [details] [review]:
> 
> ::: gst-libs/gst/video/gstvideodecoder.c
> @@ +1961,3 @@
> +          GST_ERROR_OBJECT (dec, "Segment at frame %p %" GST_TIME_FORMAT,
> +              frame, GST_TIME_ARGS (GST_BUFFER_PTS (frame->input_buffer)));
> +          gst_event_copy_segment (event, &segment);
> 
> Isn't using GST_ERROR_OBJECT a problem?

This was fixed on the final version of the patch, thanks for pointing it out
Comment 20 Thiago Sousa Santos 2014-01-13 11:22:21 UTC
(In reply to comment #16)
> Review of attachment 265913 [details] [review]:
> 
> ::: gst-libs/gst/video/gstvideodecoder.c
> @@ +1968,3 @@
> +        dec->priv->pending_events =
> +            g_list_append (dec->priv->pending_events, event);
> +        frame->events = g_list_delete_link (frame->events, cur);
> 
> Trying to understand the patch.
> 
> Why do we need to move the event from the frame and put it in the pending
> events list?
> 
> Don't they get all pushed in gst_video_decoder_prepare_finish_frame? First, the
> pending events and then the frame events?

For reverse playback, the buffers will be pushed in reverse order, but some events need to be pushed before any data and they are usually attached to the first buffer. To be sure that those events are going to be pushed early enough, move them to the pending events list, so they will be pushed before any of the buffers.