diff options
Diffstat (limited to 'gst/vaapi/gstvaapidecodebin.c')
-rw-r--r-- | gst/vaapi/gstvaapidecodebin.c | 182 |
1 files changed, 123 insertions, 59 deletions
diff --git a/gst/vaapi/gstvaapidecodebin.c b/gst/vaapi/gstvaapidecodebin.c index ad814e77..f147f1c5 100644 --- a/gst/vaapi/gstvaapidecodebin.c +++ b/gst/vaapi/gstvaapidecodebin.c @@ -27,6 +27,7 @@ #include <gst/pbutils/pbutils.h> #include "gstvaapipluginutil.h" #include "gstvaapidecodebin.h" +#include "gstvaapivideocontext.h" #define GST_PLUGIN_NAME "vaapidecodebin" #define GST_PLUGIN_DESC "A Bin of VA-API elements: vaapidecode ! queue ! vaapipostproc" @@ -101,30 +102,73 @@ GST_STATIC_PAD_TEMPLATE ("src", G_DEFINE_TYPE (GstVaapiDecodeBin, gst_vaapi_decode_bin, GST_TYPE_BIN); -/* Remove the vaapipostproc if already added and reset the ghost pad target */ static void -disable_vpp (GstVaapiDecodeBin * vaapidecbin) +post_missing_element_message (GstVaapiDecodeBin * vaapidecbin, + const gchar * missing_factory) { - GstPad *pad; - GstStateChangeReturn ret; - GstState state; - - /*Fixme: Add run-time disabling support */ - ret = - gst_element_get_state (GST_ELEMENT (vaapidecbin), &state, NULL, - GST_CLOCK_TIME_NONE); - if (ret != GST_STATE_CHANGE_SUCCESS || state > GST_STATE_NULL) { - GST_WARNING_OBJECT (vaapidecbin, "Failed to set disable-vpp property!,," - "No support for run-time disabling, Ignoring the user request to disable VPP."); - return; + GstMessage *msg; + + GST_ERROR_OBJECT (vaapidecbin, "Failed to create %s element", + missing_factory); + msg = + gst_missing_element_message_new (GST_ELEMENT_CAST (vaapidecbin), + missing_factory); + gst_element_post_message (GST_ELEMENT_CAST (vaapidecbin), msg); +} + +static gboolean +activate_vpp (GstVaapiDecodeBin * vaapidecbin) +{ + GstElement *src; + + if (vaapidecbin->ghost_pad_src || vaapidecbin->postproc) + return TRUE; + + if (!vaapidecbin->has_vpp || vaapidecbin->disable_vpp) { + src = vaapidecbin->queue; + goto connect_src_ghost_pad; } - gst_element_set_state (vaapidecbin->postproc, GST_STATE_NULL); - gst_bin_remove (GST_BIN (vaapidecbin), vaapidecbin->postproc); + /* create the postproc */ + vaapidecbin->postproc = + gst_element_factory_make ("vaapipostproc", "vaapipostproc"); + if (!vaapidecbin->postproc) + goto error_element_missing; + + g_object_set (G_OBJECT (vaapidecbin->postproc), "deinterlace-method", + vaapidecbin->deinterlace_method, NULL); + + gst_bin_add (GST_BIN (vaapidecbin), vaapidecbin->postproc); + if (!gst_element_link_pads_full (vaapidecbin->queue, "src", + vaapidecbin->postproc, "sink", GST_PAD_LINK_CHECK_NOTHING)) + goto error_link_pad; + + GST_DEBUG_OBJECT (vaapidecbin, "Enabling VPP"); + src = vaapidecbin->postproc; - pad = gst_element_get_static_pad (GST_ELEMENT (vaapidecbin->queue), "src"); - gst_ghost_pad_set_target ((GstGhostPad *) vaapidecbin->ghost_pad_src, pad); - gst_object_unref (pad); + goto connect_src_ghost_pad; + +error_element_missing: + { + post_missing_element_message (vaapidecbin, "vaapipostproc"); + return FALSE; + } +error_link_pad: + { + GST_ERROR_OBJECT (vaapidecbin, "Failed to link the child elements"); + return FALSE; + } +connect_src_ghost_pad: + { + GstPad *srcpad, *ghostpad; + + srcpad = gst_element_get_static_pad (src, "src"); + ghostpad = gst_ghost_pad_new ("src", srcpad); + vaapidecbin->ghost_pad_src = ghostpad; + gst_object_unref (srcpad); + gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghostpad); + return TRUE; + } } static void @@ -155,11 +199,19 @@ gst_vaapi_decode_bin_set_property (GObject * object, vaapidecbin->deinterlace_method, NULL); break; case PROP_DISABLE_VPP: - vaapidecbin->disable_vpp = g_value_get_boolean (value); - /* Remove the vaapipostpro */ - if (vaapidecbin->disable_vpp && vaapidecbin->postproc) - disable_vpp (vaapidecbin); + { + gboolean disable_vpp; + + disable_vpp = g_value_get_boolean (value); + if (!disable_vpp && !vaapidecbin->has_vpp) + GST_WARNING_OBJECT (vaapidecbin, + "Cannot enable VPP since the VA driver does not support it"); + else + vaapidecbin->disable_vpp = disable_vpp; + + /* @TODO: Add run-time disabling support */ break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -195,17 +247,61 @@ gst_vaapi_decode_bin_get_property (GObject * object, } static void +gst_vaapi_decode_bin_handle_message (GstBin * bin, GstMessage * message) +{ + GstVaapiDecodeBin *vaapidecbin = GST_VAAPI_DECODE_BIN (bin); + GstMessageType type; + GstContext *context = NULL; + const gchar *context_type; + GstVaapiDisplay *display = NULL; + + type = GST_MESSAGE_TYPE (message); + if (type != GST_MESSAGE_HAVE_CONTEXT) + goto bail; + gst_message_parse_have_context (message, &context); + if (!context) + goto bail; + context_type = gst_context_get_context_type (context); + if (g_strcmp0 (context_type, GST_VAAPI_DISPLAY_CONTEXT_TYPE_NAME) != 0) + goto bail; + if (!gst_vaapi_video_context_get_display (context, &display)) + goto bail; + + vaapidecbin->has_vpp = gst_vaapi_display_has_video_processing (display); + + /* the underlying VA driver implementation doesn't support video + * post-processing, hence we have to disable it */ + if (!vaapidecbin->has_vpp) { + GST_WARNING_OBJECT (vaapidecbin, "VA driver doesn't support VPP"); + if (!vaapidecbin->disable_vpp) { + vaapidecbin->disable_vpp = TRUE; + } + } + + activate_vpp (vaapidecbin); + +bail: + GST_BIN_CLASS (gst_vaapi_decode_bin_parent_class)->handle_message (bin, + message); +} + +static void gst_vaapi_decode_bin_class_init (GstVaapiDecodeBinClass * klass) { GObjectClass *gobject_class; GstElementClass *element_class; + GstBinClass *bin_class; gobject_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + bin_class = GST_BIN_CLASS (klass); gobject_class->set_property = gst_vaapi_decode_bin_set_property; gobject_class->get_property = gst_vaapi_decode_bin_get_property; + bin_class->handle_message = + GST_DEBUG_FUNCPTR (gst_vaapi_decode_bin_handle_message); + gst_element_class_set_static_metadata (element_class, "VA-API Decode Bin", "Codec/Decoder/Video", @@ -279,35 +375,11 @@ gst_vaapi_decode_bin_configure (GstVaapiDecodeBin * vaapidecbin) vaapidecbin->queue, "sink", GST_PAD_LINK_CHECK_NOTHING)) goto error_link_pad; - if (!vaapidecbin->disable_vpp) { - /* create the postproc */ - vaapidecbin->postproc = - gst_element_factory_make ("vaapipostproc", "vaapipostproc"); - if (!vaapidecbin->postproc) { - missing_factory = "vaapipostproc"; - goto error_element_missing; - } - - g_object_set (G_OBJECT (vaapidecbin->postproc), - "deinterlace-method", vaapidecbin->deinterlace_method, NULL); - - gst_bin_add (GST_BIN (vaapidecbin), vaapidecbin->postproc); - if (!gst_element_link_pads_full (vaapidecbin->queue, "src", - vaapidecbin->postproc, "sink", GST_PAD_LINK_CHECK_NOTHING)) - goto error_link_pad; - } - return TRUE; error_element_missing: { - GstMessage *msg; - GST_ERROR_OBJECT (vaapidecbin, "Failed to create %s element", - missing_factory); - msg = - gst_missing_element_message_new (GST_ELEMENT_CAST (vaapidecbin), - missing_factory); - gst_element_post_message (GST_ELEMENT_CAST (vaapidecbin), msg); + post_missing_element_message (vaapidecbin, missing_factory); return FALSE; } error_link_pad: @@ -321,7 +393,9 @@ static void gst_vaapi_decode_bin_init (GstVaapiDecodeBin * vaapidecbin) { GstPad *element_pad, *ghost_pad; - GstElement *src_element; + + /* let's assume we have VPP until we prove the opposite */ + vaapidecbin->has_vpp = TRUE; if (!gst_vaapi_decode_bin_configure (vaapidecbin)) return; @@ -334,14 +408,4 @@ gst_vaapi_decode_bin_init (GstVaapiDecodeBin * vaapidecbin) GST_PAD_PAD_TEMPLATE (element_pad)); gst_object_unref (element_pad); gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghost_pad); - - /* create ghost pad src */ - src_element = - vaapidecbin->disable_vpp ? vaapidecbin->queue : vaapidecbin->postproc; - element_pad = gst_element_get_static_pad (GST_ELEMENT (src_element), "src"); - - ghost_pad = gst_ghost_pad_new ("src", element_pad); - vaapidecbin->ghost_pad_src = ghost_pad; - gst_object_unref (element_pad); - gst_element_add_pad (GST_ELEMENT (vaapidecbin), ghost_pad); } |