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 747492 - vaapisink: wayland improvements
vaapisink: wayland improvements
Status: RESOLVED FIXED
Product: gstreamer-vaapi
Classification: Other
Component: general
git master
Other Linux
: Normal normal
: ---
Assigned To: gstreamer-vaapi maintainer(s)
gstreamer-vaapi maintainer(s)
Depends on:
Blocks: 743569 748634
 
 
Reported: 2015-04-08 09:12 UTC by Michael Olbrich
Modified: 2015-05-18 13:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
wayland: release the frame in the buffer release callback (2.94 KB, patch)
2015-04-08 09:14 UTC, Michael Olbrich
committed Details | Review
vaapisink: implement unlock/unlock_stop for wayland (8.40 KB, patch)
2015-04-08 09:14 UTC, Michael Olbrich
none Details | Review
vaapisink: implement unlock/unlock_stop for wayland (8.41 KB, patch)
2015-04-12 08:23 UTC, Michael Olbrich
none Details | Review
wayland: wl_display_dispatch_queue() can block forever. (2.83 KB, patch)
2015-05-15 15:10 UTC, Víctor Manuel Jáquez Leal
committed Details | Review
vaapisink: implement unlock/unlock_stop for wayland (8.87 KB, patch)
2015-05-15 15:10 UTC, Víctor Manuel Jáquez Leal
committed Details | Review

Description Michael Olbrich 2015-04-08 09:12:30 UTC
The vaapisink has two problems when interacting with a wayland compositor:
1. the frame is release on the frame done callback. This is incorrect. The compositor may still use it until the buffer release callback is called.
2. wl_display_dispatch_queue() can block forever e.g. when the compositor exits. This can prevent a normal pipeline shutdown.

Here are two patches to fix these issues. I'm submitting both here because they tuch the same code and would conflict otherwise.
Comment 1 Michael Olbrich 2015-04-08 09:14:17 UTC
Created attachment 301105 [details] [review]
wayland: release the frame in the buffer release callback

The wayland compositor may still use the buffer when the frame done
callback is called.
Comment 2 Michael Olbrich 2015-04-08 09:14:58 UTC
Created attachment 301106 [details] [review]
vaapisink: implement unlock/unlock_stop for wayland

Otherwise wl_display_dispatch_queue() might prevent the pipeline from
shutting down. This can happen e.g. if the wayland compositor exits while
the pipeline is running.
Comment 3 Olivier Crête 2015-04-08 14:56:29 UTC
I wrote something similar last week. Another problem is that wl_surface_frame never happens if the surface is not on a visible output, at least in Weston. My version didn't have the poll, I just tried to read from the socket, and if there was nothing, I just dropped the incoming frame.
Comment 4 Víctor Manuel Jáquez Leal 2015-04-10 15:28:15 UTC
(In reply to Michael Olbrich from comment #2)
> Created attachment 301106 [details] [review] [review]
> vaapisink: implement unlock/unlock_stop for wayland
> 
> Otherwise wl_display_dispatch_queue() might prevent the pipeline from
> shutting down. This can happen e.g. if the wayland compositor exits while
> the pipeline is running.

this patch shows this errors:

gstvaapiwindow.c:524:3: error: non-void function 'gst_vaapi_window_unlock' should return a value
      [-Wreturn-type]
  g_return_if_fail (window != NULL);
  ^
/opt/gnome/jh/include/glib-2.0/glib/gmessages.h:373:3: note: expanded from macro 'g_return_if_fail'
         return;                                                        \
         ^
gstvaapiwindow.c:545:3: error: non-void function 'gst_vaapi_window_unlock_stop' should return a value
      [-Wreturn-type]
  g_return_if_fail (window != NULL);
  ^
/opt/gnome/jh/include/glib-2.0/glib/gmessages.h:373:3: note: expanded from macro 'g_return_if_fail'
         return;                                                        \
         ^
Comment 5 Víctor Manuel Jáquez Leal 2015-04-10 15:39:31 UTC
Review of attachment 301106 [details] [review]:

::: gst-libs/gst/vaapi/gstvaapiwindow.c
@@ -512,0 +512,13 @@
+
+/**
+ * gst_vaapi_window_unlock:
... 10 more ...

you should use g_return_val_if_fail()

@@ -512,0 +512,34 @@
+
+/**
+ * gst_vaapi_window_unlock:
... 31 more ...

ditto

::: gst/vaapi/gstvaapisink.c
@@ +1536,3 @@
+{
+  GstVaapiSink *const sink = GST_VAAPISINK_CAST (base_sink);
+  return !sink->window || gst_vaapi_window_unlock (sink->window);

Though I love this expression, it is not common in gstreamer or gstreamer-vaapi.

I prefer

if (sink->window)
  return gst_vaapi_window_unlock (sink->window);

return FALSE;

The compiler should do the optimization ;)

@@ +1543,3 @@
+{
+  GstVaapiSink *const sink = GST_VAAPISINK_CAST (base_sink);
+  return !sink->window || gst_vaapi_window_unlock_stop (sink->window);

ditto
Comment 6 Víctor Manuel Jáquez Leal 2015-04-10 15:56:24 UTC
Review of attachment 301105 [details] [review]:

::: gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
@@ -332,2 +332,2 @@
   if (priv->frame == frame)
-    priv->frame = NULL;
+    priv->frame_busy = FALSE;

Though it is not common in gstreamer-vaapi, I think, for this purposes, the use of g_atomic_int_set() is better.

@@ -474,2 +490,3 @@
     return FALSE;
   priv->frame = frame;
+  priv->frame_busy = TRUE;

ditto
Comment 7 Olivier Crête 2015-04-10 16:13:06 UTC
Review of attachment 301106 [details] [review]:

::: gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
@@ +201,3 @@
+        break;
+      }
+      wl_display_read_events (wl_display);

This whole thing is problematic because you could have more than one vaapisink that share the same wl_display, and you can have more than one thread going this thing at a time. So instead, I think you need a separate thread in  GstVaapiWaylandDisplay that polls and reads from the socket, and then the various sinks can wait on that..

See how it is implemented in waylandsink for reference.
Comment 8 Michael Olbrich 2015-04-12 08:23:08 UTC
Created attachment 301396 [details] [review]
vaapisink: implement unlock/unlock_stop for wayland

I've fixed the broken assertions. I'm not 100% sure why I don't see those errors. Probably because gstreamer is built with --disable-debug?

And I changed unlock (and lock) to:

[...]
if (sink->window)
  return gst_vaapi_window_unlock (sink->window);

return TRUE;
[...]

Notice the 'TRUE'. That's what my original code did and I'm pretty sure that this should succeed if no handler exists.
Comment 9 Michael Olbrich 2015-04-12 08:25:39 UTC
(In reply to Víctor Manuel Jáquez Leal from comment #6)
> Review of attachment 301105 [details] [review] [review]:
> 
> ::: gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
> @@ -332,2 +332,2 @@
>    if (priv->frame == frame)
> -    priv->frame = NULL;
> +    priv->frame_busy = FALSE;
> 
> Though it is not common in gstreamer-vaapi, I think, for this purposes, the
> use of g_atomic_int_set() is better.

I'm not sure if that is a good idea. Currently frame_busy is defined as "guint frame_busy:1;" and I don't think it can be modified atomically. And It's only modified from the same thread anyways.
Comment 10 Michael Olbrich 2015-04-12 08:31:49 UTC
(In reply to Olivier Crête from comment #7)
> Review of attachment 301106 [details] [review] [review]:
> 
> ::: gst-libs/gst/vaapi/gstvaapiwindow_wayland.c
> @@ +201,3 @@
> +        break;
> +      }
> +      wl_display_read_events (wl_display);
> 
> This whole thing is problematic because you could have more than one
> vaapisink that share the same wl_display, and you can have more than one
> thread going this thing at a time. So instead, I think you need a separate
> thread in  GstVaapiWaylandDisplay that polls and reads from the socket, and
> then the various sinks can wait on that..
> 
> See how it is implemented in waylandsink for reference.

Actually, the wayland API is designed to handle exactly this case:
- With wl_display_prepare_read() all threads announce their intention to read.
- wl_display_read_events() is thread save. On threads reads, the other wait for it to finish.
- With wl_display_dispatch_queue_pending() each thread dispatches its own events.
Comment 11 Olivier Crête 2015-04-16 17:55:49 UTC
++ on the patches then, I didn't understand the wayland thing correctly.
Comment 12 Víctor Manuel Jáquez Leal 2015-04-17 09:12:49 UTC
I'm sorry for taking so long to merge these patches, but I'm learning wayland. I want to merge bug #705821 and bug #747902 too, if you want to review them.
Comment 13 Gwenole Beauchesne 2015-04-17 09:23:11 UTC
Review of attachment 301105 [details] [review]:

LGTM. Thanks.
Comment 14 Gwenole Beauchesne 2015-04-17 09:24:18 UTC
Review of attachment 301396 [details] [review]:

Where does unlock/unlock_stop paradigm come from?
Comment 15 Gwenole Beauchesne 2015-04-17 09:29:57 UTC
Review of attachment 301396 [details] [review]:

Nevermind, from GstBaseSink. :)
Comment 16 Gwenole Beauchesne 2015-04-17 09:43:56 UTC
Better names needed here though. {Lock/}Unlock should be reserved to the traditional resources locking paradigm. Something like unblock/unblock_cancel() but it's still too vague imho. Thanks.
Comment 17 Víctor Manuel Jáquez Leal 2015-04-21 16:10:22 UTC
Comment on attachment 301105 [details] [review]
wayland: release the frame in the buffer release callback

commit 7548c72a7d7db3e1d1d2bb2965a08d028907565a
Author: Michael Olbrich <m.olbrich@pengutronix.de>
Date:   Tue Feb 3 16:52:06 2015 +0100

    wayland: free frame in buffer release callback
    
    The Wayland compositor may still use the buffer when the frame done
    callback is called.
    
    This patch destroys the frame (which contains the buffer) until the
    release callback is called. The draw termination callback only controls
    the display queue dispatching.
    
    Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747492
Comment 18 Víctor Manuel Jáquez Leal 2015-05-15 15:10:42 UTC
Created attachment 303428 [details] [review]
wayland: wl_display_dispatch_queue() can block forever.

wl_display_dispatch_queue() might prevent the pipeline from shutting
down. This can happen e.g. if the wayland compositor exits while the
pipeline is running.

This patch replaces it with these steps:

- With wl_display_prepare_read() all threads announce their intention
  to read.
- wl_display_read_events() is thread save. On threads reads, the other
  wait for it to finish.
- With wl_display_dispatch_queue_pending() each thread dispatches its
  own events.

wl_display_dispatch_queue_pending() was defined since wayland 1.0.2

Original-patch-by: Michael Olbrich <m.olbrich@pengutronix.de>
* stripped out the unlock() unlock_stop() logic
* stripped out the poll handling

Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>

https://bugzilla.gnome.org/show_bug.cgi?id=749078
Comment 19 Víctor Manuel Jáquez Leal 2015-05-15 15:10:48 UTC
Created attachment 303429 [details] [review]
vaapisink: implement unlock/unlock_stop for wayland

Otherwise wl_display_dispatch_queue() might prevent the pipeline from
shutting down. This can happen e.g. if the wayland compositor exits while
the pipeline is running.

Changes:
* renamed unlock()/unlock_stop() to unblock()/unblock_cancel() in gstvaapiwindow
* splitted the patch removing wl_display_dispatch_queue()

Signed-off-by: Víctor Manuel Jáquez Leal <victorx.jaquez@intel.com>

https://bugzilla.gnome.org/show_bug.cgi?id=747492

https://bugzilla.gnome.org/show_bug.cgi?id=749078
Comment 20 Víctor Manuel Jáquez Leal 2015-05-15 15:16:14 UTC
I uploaded a second version of the Michael's patch, but I split it in two patches: one making the sync() non-blocking and the second one with the unlock()/unlock_stop() logic with the changes recommended by Gwenole.

I use these patches in bug #749078

If you are OK with them, I'll push them along with those in bug #749078 next Monday.
Comment 21 Víctor Manuel Jáquez Leal 2015-05-18 13:21:13 UTC
Attachment 303428 [details] pushed as 522ec79 - wayland: wl_display_dispatch_queue() can block forever.
Attachment 303429 [details] pushed as 11b9260 - vaapisink: implement unlock/unlock_stop for wayland