From 6f2dfb71e6a58c3988c1c8f3eeeeaea29973b656 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 13 Dec 2013 11:52:47 +0100 Subject: [PATCH] plugins: factor out display creation process. Move common VA display creation code to GstVaapiPluginBase, with the default display type remaining "any". Also add a "display-changed" hook so that subclasses could perform additional tasks when/if the VA display changed, due to a new display type request for instance. All plug-ins are updated to cope with the new internal APIs. --- gst/vaapi/gstvaapidecode.c | 3 +- gst/vaapi/gstvaapidownload.c | 3 +- gst/vaapi/gstvaapiencode.c | 3 +- gst/vaapi/gstvaapipluginbase.c | 60 ++++++++++++++++++++++++++++ gst/vaapi/gstvaapipluginbase.h | 15 +++++++ gst/vaapi/gstvaapipluginutil.c | 34 ++++++---------- gst/vaapi/gstvaapipluginutil.h | 6 +-- gst/vaapi/gstvaapipostproc.c | 3 +- gst/vaapi/gstvaapisink.c | 89 ++++++++++++++++++++++++------------------ gst/vaapi/gstvaapisink.h | 1 - gst/vaapi/gstvaapiupload.c | 3 +- 11 files changed, 143 insertions(+), 77 deletions(-) diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 102f0d4..2228122 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -603,8 +603,7 @@ gst_vaapidecode_set_context(GstElement *element, GstContext *context) static inline gboolean gst_vaapidecode_ensure_display(GstVaapiDecode *decode) { - return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY, - &GST_VAAPI_PLUGIN_BASE_DISPLAY(decode)); + return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(decode)); } static inline guint diff --git a/gst/vaapi/gstvaapidownload.c b/gst/vaapi/gstvaapidownload.c index c596625..ed33bc4 100644 --- a/gst/vaapi/gstvaapidownload.c +++ b/gst/vaapi/gstvaapidownload.c @@ -275,8 +275,7 @@ gst_vaapidownload_init(GstVaapiDownload *download) static inline gboolean gst_vaapidownload_ensure_display(GstVaapiDownload *download) { - return gst_vaapi_ensure_display(download, GST_VAAPI_DISPLAY_TYPE_ANY, - &GST_VAAPI_PLUGIN_BASE_DISPLAY(download)); + return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(download)); } static gboolean diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c index 4227377..c8b670b 100644 --- a/gst/vaapi/gstvaapiencode.c +++ b/gst/vaapi/gstvaapiencode.c @@ -113,8 +113,7 @@ enum static inline gboolean ensure_display (GstVaapiEncode * encode) { - return gst_vaapi_ensure_display (encode, - GST_VAAPI_DISPLAY_TYPE_ANY, &GST_VAAPI_PLUGIN_BASE_DISPLAY (encode)); + return gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (encode)); } static gboolean diff --git a/gst/vaapi/gstvaapipluginbase.c b/gst/vaapi/gstvaapipluginbase.c index b2d7d80..366d616 100644 --- a/gst/vaapi/gstvaapipluginbase.c +++ b/gst/vaapi/gstvaapipluginbase.c @@ -24,12 +24,20 @@ #include "gst/vaapi/sysdeps.h" #include "gstvaapipluginbase.h" +#include "gstvaapipluginutil.h" +/* Default debug category is from the subclass */ #define GST_CAT_DEFAULT (plugin->debug_category) +static void +default_display_changed (GstVaapiPluginBase * plugin) +{ +} + void gst_vaapi_plugin_base_class_init (GstVaapiPluginBaseClass * klass) { + klass->display_changed = default_display_changed; } void @@ -37,6 +45,9 @@ gst_vaapi_plugin_base_init (GstVaapiPluginBase * plugin, GstDebugCategory * debug_category) { plugin->debug_category = debug_category; + + plugin->display_type = GST_VAAPI_DISPLAY_TYPE_ANY; + plugin->display_type_req = GST_VAAPI_DISPLAY_TYPE_ANY; } void @@ -74,3 +85,52 @@ gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin) { gst_vaapi_display_replace (&plugin->display, NULL); } + +/** + * gst_vaapi_plugin_base_set_display_type: + * @plugin: a #GstVaapiPluginBase + * @display_type: the new request #GstVaapiDisplayType + * + * Requests a new display type. The change is effective at the next + * call to gst_vaapi_plugin_base_ensure_display(). + */ +void +gst_vaapi_plugin_base_set_display_type (GstVaapiPluginBase * plugin, + GstVaapiDisplayType display_type) +{ + plugin->display_type_req = display_type; +} + +/* Checks wether display type 1 is compatible with display type 2 */ +static gboolean +display_type_is_compatible (GstVaapiDisplayType type1, + GstVaapiDisplayType type2) +{ + return (type1 == type2 || type2 == GST_VAAPI_DISPLAY_TYPE_ANY); +} + +/** + * gst_vaapi_plugin_base_ensure_display: + * @plugin: a #GstVaapiPluginBase + * + * Ensures the display stored in @plugin complies with the requested + * display type constraints. + * + * Returns: %TRUE if the display was created to match the requested + * type, %FALSE otherwise. + */ +gboolean +gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin) +{ + if (plugin->display && display_type_is_compatible (plugin->display_type, + plugin->display_type_req)) + return TRUE; + gst_vaapi_display_replace (&plugin->display, NULL); + + if (!gst_vaapi_ensure_display (plugin, plugin->display_type_req)) + return FALSE; + plugin->display_type = gst_vaapi_display_get_display_type (plugin->display); + + GST_VAAPI_PLUGIN_BASE_GET_CLASS (plugin)->display_changed (plugin); + return TRUE; +} diff --git a/gst/vaapi/gstvaapipluginbase.h b/gst/vaapi/gstvaapipluginbase.h index 2e3c27d..952d309 100644 --- a/gst/vaapi/gstvaapipluginbase.h +++ b/gst/vaapi/gstvaapipluginbase.h @@ -70,6 +70,8 @@ typedef struct _GstVaapiPluginBaseClass GstVaapiPluginBaseClass; #define GST_VAAPI_PLUGIN_BASE_DISPLAY(plugin) \ (GST_VAAPI_PLUGIN_BASE(plugin)->display) +#define GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(plugin) \ + (GST_VAAPI_PLUGIN_BASE(plugin)->display_type) #define GST_VAAPI_PLUGIN_BASE_DISPLAY_REPLACE(plugin, new_display) \ (gst_vaapi_display_replace(&GST_VAAPI_PLUGIN_BASE_DISPLAY(plugin), \ (new_display))) @@ -89,6 +91,8 @@ struct _GstVaapiPluginBase GstDebugCategory *debug_category; GstVaapiDisplay *display; + GstVaapiDisplayType display_type; + GstVaapiDisplayType display_type_req; }; struct _GstVaapiPluginBaseClass @@ -102,6 +106,8 @@ struct _GstVaapiPluginBaseClass GstBaseTransformClass transform; GstVideoSinkClass sink; } parent_class; + + void (*display_changed) (GstVaapiPluginBase * plugin); }; G_GNUC_INTERNAL @@ -125,6 +131,15 @@ G_GNUC_INTERNAL void gst_vaapi_plugin_base_close (GstVaapiPluginBase * plugin); +G_GNUC_INTERNAL +void +gst_vaapi_plugin_base_set_display_type (GstVaapiPluginBase * plugin, + GstVaapiDisplayType display_type); + +G_GNUC_INTERNAL +gboolean +gst_vaapi_plugin_base_ensure_display (GstVaapiPluginBase * plugin); + G_END_DECLS #endif /* GST_VAAPI_PLUGIN_BASE_H */ diff --git a/gst/vaapi/gstvaapipluginutil.c b/gst/vaapi/gstvaapipluginutil.c index 92f9ec5..2e4c97e 100644 --- a/gst/vaapi/gstvaapipluginutil.c +++ b/gst/vaapi/gstvaapipluginutil.c @@ -37,6 +37,7 @@ # include #endif #include "gstvaapipluginutil.h" +#include "gstvaapipluginbase.h" /* Preferred first */ static const char *display_types[] = { @@ -88,45 +89,31 @@ static const DisplayMap g_display_map[] = { }; static GstVaapiDisplay * -gst_vaapi_create_display(GstVaapiDisplayType *display_type) +gst_vaapi_create_display(GstVaapiDisplayType display_type) { GstVaapiDisplay *display = NULL; const DisplayMap *m; for (m = g_display_map; m->type_str != NULL; m++) { - if (*display_type != GST_VAAPI_DISPLAY_TYPE_ANY && - *display_type != m->type) + if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY && + display_type != m->type) continue; display = m->create_display(NULL); - if (display) { - *display_type = m->type; - break; - } - - if (*display_type != GST_VAAPI_DISPLAY_TYPE_ANY) + if (display || display_type != GST_VAAPI_DISPLAY_TYPE_ANY) break; } return display; } gboolean -gst_vaapi_ensure_display( - gpointer element, - GstVaapiDisplayType display_type, - GstVaapiDisplay **display_ptr -) +gst_vaapi_ensure_display(gpointer element, GstVaapiDisplayType type) { + GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(element); GstVaapiDisplay *display; GstVideoContext *context; g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE); - g_return_val_if_fail(display_ptr != NULL, FALSE); - - /* Already exist ? */ - display = *display_ptr; - if (display) - return TRUE; context = GST_VIDEO_CONTEXT(element); g_return_val_if_fail(context != NULL, FALSE); @@ -134,16 +121,17 @@ gst_vaapi_ensure_display( gst_vaapi_video_context_prepare(context, display_types); /* Neighbour found and it updated the display */ - if (*display_ptr) + if (plugin->display) return TRUE; /* If no neighboor, or application not interested, use system default */ - display = gst_vaapi_create_display(&display_type); + display = gst_vaapi_create_display(type); if (!display) return FALSE; gst_vaapi_video_context_propagate(context, display); - *display_ptr = display; + GST_VAAPI_PLUGIN_BASE_DISPLAY_REPLACE(plugin, display); + gst_vaapi_display_unref(display); return TRUE; } diff --git a/gst/vaapi/gstvaapipluginutil.h b/gst/vaapi/gstvaapipluginutil.h index 76194d0..8336efb 100644 --- a/gst/vaapi/gstvaapipluginutil.h +++ b/gst/vaapi/gstvaapipluginutil.h @@ -30,11 +30,7 @@ G_GNUC_INTERNAL gboolean -gst_vaapi_ensure_display( - gpointer element, - GstVaapiDisplayType display_type, - GstVaapiDisplay **display -); +gst_vaapi_ensure_display(gpointer element, GstVaapiDisplayType type); G_GNUC_INTERNAL void diff --git a/gst/vaapi/gstvaapipostproc.c b/gst/vaapi/gstvaapipostproc.c index 97eea32..f269b70 100755 --- a/gst/vaapi/gstvaapipostproc.c +++ b/gst/vaapi/gstvaapipostproc.c @@ -272,8 +272,7 @@ gst_vaapipostproc_set_context(GstElement *element, GstContext *context) static inline gboolean gst_vaapipostproc_ensure_display(GstVaapiPostproc *postproc) { - return gst_vaapi_ensure_display(postproc, GST_VAAPI_DISPLAY_TYPE_ANY, - &GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc)); + return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(postproc)); } static gboolean diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c index bb2f68a..fd89804 100644 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -187,18 +187,23 @@ static GstFlowReturn gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer); static void -gst_vaapisink_video_overlay_set_window_handle(GstVideoOverlay *overlay, guintptr window) +gst_vaapisink_video_overlay_set_window_handle(GstVideoOverlay *overlay, + guintptr window) { GstVaapiSink * const sink = GST_VAAPISINK(overlay); + GstVaapiDisplayType display_type = GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink); /* Disable GLX rendering when vaapisink is using a foreign X window. It's pretty much useless */ - if (sink->display_type == GST_VAAPI_DISPLAY_TYPE_GLX) - sink->display_type = GST_VAAPI_DISPLAY_TYPE_X11; + if (display_type == GST_VAAPI_DISPLAY_TYPE_GLX) { + display_type = GST_VAAPI_DISPLAY_TYPE_X11; + gst_vaapi_plugin_base_set_display_type(GST_VAAPI_PLUGIN_BASE(sink), + display_type); + } sink->foreign_window = TRUE; - switch (sink->display_type) { + switch (display_type) { #if USE_X11 case GST_VAAPI_DISPLAY_TYPE_X11: gst_vaapisink_ensure_window_xid(sink, window); @@ -347,28 +352,26 @@ get_display_type_name(GstVaapiDisplayType display_type) static inline gboolean gst_vaapisink_ensure_display(GstVaapiSink *sink) { - GstVaapiDisplayType display_type; - GstVaapiRenderMode render_mode; - const gboolean had_display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink) != NULL; + return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(sink)); +} - if (!gst_vaapi_ensure_display(sink, sink->display_type, &GST_VAAPI_PLUGIN_BASE_DISPLAY(sink))) - return FALSE; +static void +gst_vaapisink_display_changed(GstVaapiPluginBase *plugin) +{ + GstVaapiSink * const sink = GST_VAAPISINK(plugin); + GstVaapiRenderMode render_mode; - display_type = gst_vaapi_display_get_display_type(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); - if (display_type != sink->display_type || (!had_display && GST_VAAPI_PLUGIN_BASE_DISPLAY(sink))) { - GST_INFO("created %s %p", get_display_type_name(display_type), - GST_VAAPI_PLUGIN_BASE_DISPLAY(sink)); - sink->display_type = display_type; + GST_INFO("created %s %p", get_display_type_name(plugin->display_type), + plugin->display); - sink->use_overlay = - gst_vaapi_display_get_render_mode(GST_VAAPI_PLUGIN_BASE_DISPLAY(sink), &render_mode) && - render_mode == GST_VAAPI_RENDER_MODE_OVERLAY; - GST_DEBUG("use %s rendering mode", sink->use_overlay ? "overlay" : "texture"); + sink->use_overlay = + gst_vaapi_display_get_render_mode(plugin->display, &render_mode) && + render_mode == GST_VAAPI_RENDER_MODE_OVERLAY; + GST_DEBUG("use %s rendering mode", + sink->use_overlay ? "overlay" : "texture"); - sink->use_rotation = gst_vaapi_display_has_property( - GST_VAAPI_PLUGIN_BASE_DISPLAY(sink), GST_VAAPI_DISPLAY_PROP_ROTATION); - } - return TRUE; + sink->use_rotation = gst_vaapi_display_has_property(plugin->display, + GST_VAAPI_DISPLAY_PROP_ROTATION); } static gboolean @@ -512,7 +515,9 @@ gst_vaapisink_ensure_window(GstVaapiSink *sink, guint width, guint height) GstVaapiDisplay * const display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); if (!sink->window) { - switch (sink->display_type) { + const GstVaapiDisplayType display_type = + GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink); + switch (display_type) { #if USE_GLX case GST_VAAPI_DISPLAY_TYPE_GLX: sink->window = gst_vaapi_window_glx_new(display, width, height); @@ -536,7 +541,7 @@ gst_vaapisink_ensure_window(GstVaapiSink *sink, guint width, guint height) break; #endif default: - GST_ERROR("unsupported display type %d", sink->display_type); + GST_ERROR("unsupported display type %d", display_type); return FALSE; } } @@ -580,7 +585,7 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) gst_vaapi_window_replace(&sink->window, NULL); - switch (sink->display_type) { + switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { #if USE_GLX case GST_VAAPI_DISPLAY_TYPE_GLX: sink->window = gst_vaapi_window_glx_new_with_xid(display, xid); @@ -590,7 +595,8 @@ gst_vaapisink_ensure_window_xid(GstVaapiSink *sink, guintptr window_id) sink->window = gst_vaapi_window_x11_new_with_xid(display, xid); break; default: - GST_ERROR("unsupported display type %d", sink->display_type); + GST_ERROR("unsupported display type %d", + GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)); return FALSE; } return sink->window != NULL; @@ -780,8 +786,12 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps) GstVaapiDisplay *display; guint win_width, win_height; + if (!gst_vaapisink_ensure_display(sink)) + return FALSE; + display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); + #if USE_DRM - if (sink->display_type == GST_VAAPI_DISPLAY_TYPE_DRM) + if (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink) == GST_VAAPI_DISPLAY_TYPE_DRM) return TRUE; #endif @@ -800,10 +810,6 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps) gst_caps_replace(&sink->caps, caps); - if (!gst_vaapisink_ensure_display(sink)) - return FALSE; - display = GST_VAAPI_PLUGIN_BASE_DISPLAY(sink); - #if !GST_CHECK_VERSION(1,0,0) if (sink->use_video_raw) { /* Ensure the uploader is set up for upstream allocated buffers */ @@ -1228,7 +1234,7 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *src_buffer) if (!gst_vaapi_apply_composition(surface, src_buffer)) GST_WARNING("could not update subtitles"); - switch (sink->display_type) { + switch (GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)) { #if USE_DRM case GST_VAAPI_DISPLAY_TYPE_DRM: success = TRUE; @@ -1254,7 +1260,8 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *src_buffer) break; #endif default: - GST_ERROR("unsupported display type %d", sink->display_type); + GST_ERROR("unsupported display type %d", + GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)); success = FALSE; break; } @@ -1403,7 +1410,8 @@ gst_vaapisink_set_property( switch (prop_id) { case PROP_DISPLAY_TYPE: - sink->display_type = g_value_get_enum(value); + gst_vaapi_plugin_base_set_display_type(GST_VAAPI_PLUGIN_BASE(sink), + g_value_get_enum(value)); break; case PROP_FULLSCREEN: sink->fullscreen = g_value_get_boolean(value); @@ -1441,7 +1449,7 @@ gst_vaapisink_get_property( switch (prop_id) { case PROP_DISPLAY_TYPE: - g_value_set_enum(value, sink->display_type); + g_value_set_enum(value, GST_VAAPI_PLUGIN_BASE_DISPLAY_TYPE(sink)); break; case PROP_FULLSCREEN: g_value_set_boolean(value, sink->fullscreen); @@ -1473,12 +1481,15 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) GObjectClass * const object_class = G_OBJECT_CLASS(klass); GstElementClass * const element_class = GST_ELEMENT_CLASS(klass); GstBaseSinkClass * const basesink_class = GST_BASE_SINK_CLASS(klass); + GstVaapiPluginBaseClass * const base_plugin_class = + GST_VAAPI_PLUGIN_BASE_CLASS(klass); GstPadTemplate *pad_template; GST_DEBUG_CATEGORY_INIT(gst_debug_vaapisink, GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC); - gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass)); + gst_vaapi_plugin_base_class_init(base_plugin_class); + base_plugin_class->display_changed = gst_vaapisink_display_changed; object_class->finalize = gst_vaapisink_finalize; object_class->set_property = gst_vaapisink_set_property; @@ -1598,7 +1609,10 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) static void gst_vaapisink_init(GstVaapiSink *sink) { - gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(sink), GST_CAT_DEFAULT); + GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(sink); + + gst_vaapi_plugin_base_init(plugin, GST_CAT_DEFAULT); + gst_vaapi_plugin_base_set_display_type(plugin, DEFAULT_DISPLAY_TYPE); sink->caps = NULL; sink->window = NULL; @@ -1613,7 +1627,6 @@ gst_vaapisink_init(GstVaapiSink *sink) sink->foreign_window = FALSE; sink->fullscreen = FALSE; sink->synchronous = FALSE; - sink->display_type = DEFAULT_DISPLAY_TYPE; sink->rotation = DEFAULT_ROTATION; sink->rotation_req = DEFAULT_ROTATION; sink->use_reflection = FALSE; diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h index 491f1b4..8aae2ff 100644 --- a/gst/vaapi/gstvaapisink.h +++ b/gst/vaapi/gstvaapisink.h @@ -71,7 +71,6 @@ struct _GstVaapiSink { GstVaapiUploader *uploader; GstCaps *caps; - GstVaapiDisplayType display_type; GstVaapiWindow *window; guint window_width; guint window_height; diff --git a/gst/vaapi/gstvaapiupload.c b/gst/vaapi/gstvaapiupload.c index ce84d20..25ebcd0 100644 --- a/gst/vaapi/gstvaapiupload.c +++ b/gst/vaapi/gstvaapiupload.c @@ -251,8 +251,7 @@ gst_vaapiupload_init(GstVaapiUpload *upload) static inline gboolean gst_vaapiupload_ensure_display(GstVaapiUpload *upload) { - return gst_vaapi_ensure_display(upload, GST_VAAPI_DISPLAY_TYPE_ANY, - &GST_VAAPI_PLUGIN_BASE_DISPLAY(upload)); + return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(upload)); } static gboolean -- 2.7.4