From: Carl-Anton Ingmarsson Date: Wed, 17 Mar 2010 19:59:08 +0000 (+0100) Subject: vdpau: add better error handling to GstVdpOutputSrcPad X-Git-Tag: 1.19.3~507^2~17155 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c4f60760edd70b9cd502f6ceca1d076a4e81b36c;p=platform%2Fupstream%2Fgstreamer.git vdpau: add better error handling to GstVdpOutputSrcPad gst_vdp_output_src_pad_push, gst_vdp_output_src_pad_alloc_buffer and gst_vdp_output_src_pad_get_device now take a GError parameter to be able to signal errors to the caller --- diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 4332d6e..98c874a 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -3,8 +3,7 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ gstvdpmpegdec.c \ mpegutil.c \ - gstvdp.c \ - gstvdputils.c \ + gstvdpau.c \ gstvdpvideopostprocess.c \ gstvdpsink.c @@ -26,10 +25,12 @@ lib_LTLIBRARIES = libgstvdp-@GST_MAJORMINOR@.la libgstvdp_@GST_MAJORMINOR@_la_SOURCES = \ gstvdpdevice.c \ + gstvdputils.c \ gstvdpvideobuffer.c \ gstvdpoutputbuffer.c \ gstvdpvideosrcpad.c \ - gstvdpoutputsrcpad.c + gstvdpoutputsrcpad.c \ + gstvdp.c libgstvdp_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/vdpau libgstvdp_@GST_MAJORMINOR@include_HEADERS = \ @@ -39,8 +40,12 @@ libgstvdp_@GST_MAJORMINOR@include_HEADERS = \ gstvdpvideosrcpad.h \ gstvdpoutputsrcpad.h -libgstvdp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) -libgstvdp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(VDPAU_LIBS) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) +libgstvdp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) + +libgstvdp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(X11_LIBS) $(VDPAU_LIBS) \ + -lgstvideo-$(GST_MAJORMINOR) + libgstvdp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_LT_LDFLAGS) $(GST_ALL_LDFLAGS) libgstvdp_@GST_MAJORMINOR@_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/sys/vdpau/gstvdpoutputbuffer.c b/sys/vdpau/gstvdpoutputbuffer.c index 443895c..04a3cb5 100644 --- a/sys/vdpau/gstvdpoutputbuffer.c +++ b/sys/vdpau/gstvdpoutputbuffer.c @@ -28,7 +28,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_vdp_output_buffer_debug); #define GST_CAT_DEFAULT gst_vdp_output_buffer_debug #define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_vdp_output_buffer_debug, "vdpauoutputbuffer", 0, "VDPAU output buffer"); +GST_DEBUG_CATEGORY_INIT (gst_vdp_output_buffer_debug, "vdpoutputbuffer", 0, "VDPAU output buffer"); GstVdpOutputBuffer * gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format, @@ -47,6 +47,7 @@ gst_vdp_output_buffer_new (GstVdpDevice * device, VdpRGBAFormat rgba_format, return NULL; } + buffer = (GstVdpOutputBuffer *) gst_mini_object_new (GST_TYPE_VDP_OUTPUT_BUFFER); @@ -339,6 +340,7 @@ gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer * output_buf, } default: + g_assert_not_reached (); return FALSE; } @@ -347,7 +349,7 @@ gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer * output_buf, gboolean gst_vdp_output_buffer_download (GstVdpOutputBuffer * output_buf, - GstBuffer * outbuf) + GstBuffer * outbuf, GError ** error) { guint8 *data[1]; guint32 stride[1]; @@ -387,9 +389,10 @@ gst_vdp_output_buffer_download (GstVdpOutputBuffer * output_buf, stride); GST_LOG_OBJECT (output_buf, "Got status %d from vdp_output_get_bits_native", status); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ERROR_OBJECT (output_buf, - "Couldn't get data from vdpau, Error returned from vdpau was: %s", + g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, + "Couldn't get data from vdpau, error returned from vdpau was: %s", device->vdp_get_error_string (status)); return FALSE; } diff --git a/sys/vdpau/gstvdpoutputbuffer.h b/sys/vdpau/gstvdpoutputbuffer.h index f67ba66..be6a30e 100644 --- a/sys/vdpau/gstvdpoutputbuffer.h +++ b/sys/vdpau/gstvdpoutputbuffer.h @@ -50,7 +50,7 @@ GstCaps *gst_vdp_output_buffer_get_allowed_caps (GstVdpDevice *device); gboolean gst_vdp_caps_to_rgba_format (GstCaps *caps, VdpRGBAFormat *rgba_format); gboolean gst_vdp_output_buffer_calculate_size (GstVdpOutputBuffer *output_buf, guint *size); -gboolean gst_vdp_output_buffer_download (GstVdpOutputBuffer *output_buf, GstBuffer *outbuf); +gboolean gst_vdp_output_buffer_download (GstVdpOutputBuffer *output_buf, GstBuffer *outbuf, GError **error); #define GST_VDP_OUTPUT_CAPS \ "video/x-vdpau-output, " \ diff --git a/sys/vdpau/gstvdpoutputsrcpad.c b/sys/vdpau/gstvdpoutputsrcpad.c index 1f0404f..571610a 100644 --- a/sys/vdpau/gstvdpoutputsrcpad.c +++ b/sys/vdpau/gstvdpoutputsrcpad.c @@ -18,6 +18,7 @@ * Boston, MA 02111-1307, USA. */ +#include "gstvdputils.h" #include "gstvdpvideobuffer.h" #include "gstvdpoutputsrcpad.h" @@ -47,6 +48,7 @@ struct _GstVdpOutputSrcPad GstCaps *caps; GstVdpDevice *device; + GstCaps *input_caps; GstVdpOutputSrcPadFormat output_format; VdpRGBAFormat rgba_format; gint width, height; @@ -69,10 +71,10 @@ G_DEFINE_TYPE_WITH_CODE (GstVdpOutputSrcPad, gst_vdp_output_src_pad, GstFlowReturn gst_vdp_output_src_pad_push (GstVdpOutputSrcPad * vdp_pad, - GstVdpOutputBuffer * output_buf) + GstVdpOutputBuffer * output_buf, GError ** error) { GstPad *pad; - GstBuffer *out_buf; + GstBuffer *outbuf; g_return_val_if_fail (GST_IS_VDP_OUTPUT_SRC_PAD (vdp_pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_VDP_OUTPUT_BUFFER (output_buf), GST_FLOW_ERROR); @@ -87,31 +89,27 @@ gst_vdp_output_src_pad_push (GstVdpOutputSrcPad * vdp_pad, { guint size; - if (!gst_vdp_output_buffer_calculate_size (output_buf, &size)) { - GST_ERROR_OBJECT (vdp_pad, "Couldn't calculate buffer size for caps"); - gst_buffer_unref (GST_BUFFER_CAST (output_buf)); - return GST_FLOW_ERROR; - } + gst_vdp_output_buffer_calculate_size (output_buf, &size); - out_buf = gst_buffer_new_and_alloc (size); - gst_buffer_set_caps (out_buf, GST_PAD_CAPS (vdp_pad)); + /* FIXME: we don't do pad_alloc here since we really want a buffer of + * the specified size */ + outbuf = gst_buffer_new_and_alloc (size); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (vdp_pad)); - if (!gst_vdp_output_buffer_download (output_buf, out_buf)) { - GST_ERROR_OBJECT (vdp_pad, - "Couldn't convert from GstVdpVideoBuffer to the requested format"); + if (!gst_vdp_output_buffer_download (output_buf, outbuf, error)) { gst_buffer_unref (GST_BUFFER_CAST (output_buf)); - gst_buffer_unref (out_buf); + gst_buffer_unref (outbuf); + return GST_FLOW_ERROR; } - gst_buffer_copy_metadata (out_buf, (const GstBuffer *) output_buf, + gst_buffer_copy_metadata (outbuf, (const GstBuffer *) output_buf, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); gst_buffer_unref (GST_BUFFER_CAST (output_buf)); break; } - case GST_VDP_OUTPUT_SRC_PAD_FORMAT_VDPAU: { - out_buf = GST_BUFFER_CAST (output_buf); + outbuf = GST_BUFFER_CAST (output_buf); break; } @@ -120,9 +118,9 @@ gst_vdp_output_src_pad_push (GstVdpOutputSrcPad * vdp_pad, break; } - gst_buffer_set_caps (out_buf, GST_PAD_CAPS (vdp_pad)); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (vdp_pad)); - return gst_pad_push (pad, out_buf); + return gst_pad_push (pad, outbuf); } static void @@ -140,11 +138,92 @@ gst_vdp_output_src_pad_update_caps (GstVdpOutputSrcPad * vdp_pad) gst_caps_unref (allowed_caps); } else vdp_pad->caps = allowed_caps; + + GST_DEBUG_OBJECT (vdp_pad, "allowed caps: %" GST_PTR_FORMAT, vdp_pad->caps); +} + +static GstFlowReturn +gst_vdp_output_src_pad_create_buffer (GstVdpOutputSrcPad * vdp_pad, + GstVdpOutputBuffer ** output_buf, GError ** error) +{ + GstFlowReturn ret; + GstBuffer *neg_buf; + GstStructure *structure; + + /* negotiate */ + ret = gst_pad_alloc_buffer_and_set_caps (GST_PAD_CAST (vdp_pad), + GST_BUFFER_OFFSET_NONE, 0, GST_PAD_CAPS (vdp_pad), &neg_buf); + + if (ret == GST_FLOW_OK) { + gint new_width, new_height; + + structure = gst_caps_get_structure (GST_BUFFER_CAPS (neg_buf), 0); + if (!gst_structure_get_int (structure, "width", &new_width) || + !gst_structure_get_int (structure, "height", &new_height)) + goto invalid_caps; + + if (new_width != vdp_pad->width || new_height != vdp_pad->height) { + GST_DEBUG_OBJECT (vdp_pad, "new dimensions: %dx%d", new_width, + new_height); + + vdp_pad->width = new_width; + vdp_pad->height = new_height; + + gst_caps_set_simple (vdp_pad->input_caps, + "width", G_TYPE_INT, new_width, + "height", G_TYPE_INT, new_height, NULL); + } + + gst_buffer_unref (neg_buf); + } + + *output_buf = gst_vdp_output_buffer_new (vdp_pad->device, + vdp_pad->rgba_format, vdp_pad->width, vdp_pad->height); + if (!*output_buf) + goto output_buf_error; + + gst_buffer_set_caps (GST_BUFFER_CAST (*output_buf), vdp_pad->input_caps); + + return GST_FLOW_OK; + +invalid_caps: + gst_buffer_unref (neg_buf); + + g_set_error (error, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, + "Sink element allocated buffer with invalid caps"); + return GST_FLOW_ERROR; + +output_buf_error: + gst_buffer_unref (neg_buf); + g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, + "Couldn't create a GstVdpOutputBuffer"); + return GST_FLOW_ERROR; + +} + +static gboolean +gst_vdp_output_src_pad_open_device (GstVdpOutputSrcPad * vdp_pad, + GError ** error) +{ + GstVdpDevice *device; + + vdp_pad->device = device = gst_vdp_get_device (vdp_pad->display); + if (G_UNLIKELY (!vdp_pad->device)) + goto device_error; + + gst_vdp_output_src_pad_update_caps (vdp_pad); + + return TRUE; + +device_error: + g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_READ, + "Couldn't create GstVdpDevice"); + return FALSE; } GstFlowReturn gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad * vdp_pad, - GstVdpOutputBuffer ** output_buf) + GstVdpOutputBuffer ** output_buf, GError ** error) { GstCaps *caps; GstFlowReturn ret; @@ -158,47 +237,15 @@ gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad * vdp_pad, switch (vdp_pad->output_format) { case GST_VDP_OUTPUT_SRC_PAD_FORMAT_RGB: { - GstVdpDevice *device; - - GstBuffer *neg_buf; - GstStructure *structure; - gint width, height; - if (G_UNLIKELY (!vdp_pad->device)) { - vdp_pad->device = gst_vdp_get_device (vdp_pad->display); - if (G_UNLIKELY (!vdp_pad->device)) - goto device_error; - - gst_vdp_output_src_pad_update_caps (vdp_pad); + if (!gst_vdp_output_src_pad_open_device (vdp_pad, error)) + return GST_FLOW_ERROR; } - device = vdp_pad->device; - /* negotiate */ - ret = gst_pad_alloc_buffer (GST_PAD_CAST (vdp_pad), - GST_BUFFER_OFFSET_NONE, 0, caps, &neg_buf); + ret = gst_vdp_output_src_pad_create_buffer (vdp_pad, output_buf, error); if (ret != GST_FLOW_OK) return ret; - structure = gst_caps_get_structure (GST_BUFFER_CAPS (neg_buf), 0); - if (!gst_structure_get_int (structure, "width", &width) || - !gst_structure_get_int (structure, "height", &height)) { - gst_buffer_unref (neg_buf); - GST_ERROR_OBJECT (vdp_pad, - "Sink element allocated buffer with invalid caps"); - return GST_FLOW_ERROR; - } - - *output_buf = gst_vdp_output_buffer_new (device, vdp_pad->rgba_format, - width, height); - if (!*output_buf) { - gst_buffer_unref (neg_buf); - goto output_buf_error; - } - - gst_buffer_set_caps (GST_BUFFER_CAST (*output_buf), - GST_BUFFER_CAPS (neg_buf)); - gst_buffer_unref (neg_buf); - break; } @@ -232,40 +279,53 @@ gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad * vdp_pad, return GST_FLOW_OK; -device_error: - GST_ERROR_OBJECT (vdp_pad, "Couldn't create GstVdpDevice"); - return GST_FLOW_ERROR; - -output_buf_error: - GST_ERROR_OBJECT (vdp_pad, "Couldn't create GstVdpVideoBuffer"); - return GST_FLOW_ERROR; - wrong_caps: - GST_ERROR_OBJECT (vdp_pad, "Sink element returned buffer with wrong caps"); gst_buffer_unref (GST_BUFFER_CAST (*output_buf)); + + g_set_error (error, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, + "Sink element returned buffer with wrong caps"); return GST_FLOW_ERROR; } gboolean -gst_vdp_output_src_pad_set_caps (GstVdpOutputSrcPad * vdp_pad, GstCaps * caps) +gst_vdp_output_src_pad_negotiate_output (GstVdpOutputSrcPad * vdp_pad, + GstCaps * video_caps) { + GstCaps *allowed_caps, *output_caps, *src_caps; const GstStructure *structure; g_return_val_if_fail (GST_IS_VDP_OUTPUT_SRC_PAD (vdp_pad), FALSE); + g_return_val_if_fail (GST_IS_CAPS (video_caps), FALSE); - if (G_UNLIKELY (!caps)) - return gst_pad_set_caps (GST_PAD (vdp_pad), caps); + allowed_caps = gst_pad_get_caps (GST_PAD_CAST (vdp_pad)); + GST_DEBUG ("caps: %" GST_PTR_FORMAT, allowed_caps); + allowed_caps = gst_pad_peer_get_caps (GST_PAD_CAST (vdp_pad)); + GST_DEBUG ("peer_caps: %" GST_PTR_FORMAT, allowed_caps); - if (G_UNLIKELY (!GST_IS_CAPS (caps) || !gst_caps_is_fixed (caps))) - return FALSE; + allowed_caps = gst_pad_get_allowed_caps (GST_PAD_CAST (vdp_pad)); + if (G_UNLIKELY (!allowed_caps)) + goto allowed_caps_error; + if (G_UNLIKELY (gst_caps_is_empty (allowed_caps))) { + gst_caps_unref (allowed_caps); + goto allowed_caps_error; + } + GST_DEBUG ("allowed_caps: %" GST_PTR_FORMAT, allowed_caps); + + output_caps = gst_vdp_video_to_output_caps (video_caps); + src_caps = gst_caps_intersect (output_caps, allowed_caps); + gst_caps_unref (output_caps); + gst_caps_unref (allowed_caps); + + if (gst_caps_is_empty (src_caps)) + goto not_negotiated; + + gst_pad_fixate_caps (GST_PAD_CAST (vdp_pad), src_caps); + + GST_DEBUG ("src_caps: %" GST_PTR_FORMAT, src_caps); - structure = gst_caps_get_structure (caps, 0); + structure = gst_caps_get_structure (src_caps, 0); if (gst_structure_has_name (structure, "video/x-raw-rgb")) { - if (!gst_vdp_caps_to_rgba_format (caps, &vdp_pad->rgba_format)) - return FALSE; - if (!gst_structure_get_int (structure, "width", &vdp_pad->width)) - return FALSE; - if (!gst_structure_get_int (structure, "height", &vdp_pad->height)) + if (!gst_vdp_caps_to_rgba_format (src_caps, &vdp_pad->rgba_format)) return FALSE; vdp_pad->output_format = GST_VDP_OUTPUT_SRC_PAD_FORMAT_RGB; @@ -273,21 +333,35 @@ gst_vdp_output_src_pad_set_caps (GstVdpOutputSrcPad * vdp_pad, GstCaps * caps) if (!gst_structure_get_int (structure, "rgba-format", (gint *) & vdp_pad->rgba_format)) return FALSE; - if (!gst_structure_get_int (structure, "width", &vdp_pad->width)) - return FALSE; - if (!gst_structure_get_int (structure, "height", &vdp_pad->height)) - return FALSE; vdp_pad->output_format = GST_VDP_OUTPUT_SRC_PAD_FORMAT_VDPAU; } else return FALSE; - return gst_pad_set_caps (GST_PAD (vdp_pad), caps); + if (!gst_structure_get_int (structure, "width", &vdp_pad->width)) + return FALSE; + if (!gst_structure_get_int (structure, "height", &vdp_pad->height)) + return FALSE; + + if (gst_pad_set_caps (GST_PAD (vdp_pad), src_caps)) { + vdp_pad->input_caps = gst_caps_copy (video_caps); + return TRUE; + } + return FALSE; + +allowed_caps_error: + GST_ERROR_OBJECT (vdp_pad, "Got invalid allowed caps"); + return FALSE; + +not_negotiated: + gst_caps_unref (src_caps); + GST_ERROR_OBJECT (vdp_pad, "Couldn't find suitable output format"); + return FALSE; } GstFlowReturn gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad * vdp_pad, - GstVdpDevice ** device) + GstVdpDevice ** device, GError ** error) { g_return_val_if_fail (GST_IS_VDP_OUTPUT_SRC_PAD (vdp_pad), FALSE); @@ -305,9 +379,10 @@ gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad * vdp_pad, structure = gst_caps_get_structure (src_caps, 0); if (gst_structure_has_name (structure, "video/x-raw-rgb")) { - vdp_pad->device = gst_vdp_get_device (vdp_pad->display); - if (G_UNLIKELY (!vdp_pad->device)) - goto device_error; + if (!gst_vdp_output_src_pad_open_device (vdp_pad, error)) { + gst_caps_unref (src_caps); + return GST_FLOW_ERROR; + } } else { @@ -317,7 +392,7 @@ gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad * vdp_pad, ret = gst_pad_alloc_buffer (GST_PAD (vdp_pad), 0, 0, src_caps, &buf); if (ret != GST_FLOW_OK) { gst_caps_unref (src_caps); - return ret; + goto alloc_failed; } if (!gst_caps_is_equal_fixed (src_caps, GST_BUFFER_CAPS (buf))) { @@ -335,12 +410,14 @@ gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad * vdp_pad, *device = vdp_pad->device; return GST_FLOW_OK; -device_error: - GST_ERROR_OBJECT (vdp_pad, "Couldn't create GstVdpDevice"); +alloc_failed: + g_set_error (error, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, + "Couldn't allocate buffer"); return GST_FLOW_ERROR; wrong_caps: - GST_ERROR_OBJECT (vdp_pad, "Sink element returned buffer with wrong caps"); + g_set_error (error, GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, + "Sink element returned buffer with wrong caps"); return GST_FLOW_ERROR; } diff --git a/sys/vdpau/gstvdpoutputsrcpad.h b/sys/vdpau/gstvdpoutputsrcpad.h index e9fc61f..64ce157 100644 --- a/sys/vdpau/gstvdpoutputsrcpad.h +++ b/sys/vdpau/gstvdpoutputsrcpad.h @@ -38,12 +38,12 @@ G_BEGIN_DECLS typedef struct _GstVdpOutputSrcPad GstVdpOutputSrcPad; typedef struct _GstVdpOutputSrcPadClass GstVdpOutputSrcPadClass; -GstFlowReturn gst_vdp_output_src_pad_push (GstVdpOutputSrcPad *vdp_pad, GstVdpOutputBuffer *output_buf); -GstFlowReturn gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad *vdp_pad, GstVdpOutputBuffer **output_buf); +GstFlowReturn gst_vdp_output_src_pad_push (GstVdpOutputSrcPad *vdp_pad, GstVdpOutputBuffer *output_buf, GError **error); +GstFlowReturn gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad *vdp_pad, GstVdpOutputBuffer **output_buf, GError **error); -GstFlowReturn gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad *vdp_pad, GstVdpDevice **device); +GstFlowReturn gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad *vdp_pad, GstVdpDevice **device, GError **error); -gboolean gst_vdp_output_src_pad_set_caps (GstVdpOutputSrcPad *vdp_pad, GstCaps *caps); +gboolean gst_vdp_output_src_pad_negotiate_output (GstVdpOutputSrcPad *vdp_pad, GstCaps *video_caps); GstVdpOutputSrcPad *gst_vdp_output_src_pad_new (GstCaps * templ_caps); GType gst_vdp_output_src_pad_get_type (void) G_GNUC_CONST; diff --git a/sys/vdpau/gstvdpvideopostprocess.c b/sys/vdpau/gstvdpvideopostprocess.c index 9f762ca..ef1ebc5 100644 --- a/sys/vdpau/gstvdpvideopostprocess.c +++ b/sys/vdpau/gstvdpvideopostprocess.c @@ -352,16 +352,30 @@ gst_vdp_vpp_add_buffer (GstVdpVideoPostProcess * vpp, GstVdpVideoBuffer * buf) } } +static void +gst_vdp_vpp_post_error (GstVdpVideoPostProcess * vpp, GError * error) +{ + GstMessage *message; + + message = gst_message_new_error (GST_OBJECT (vpp), error, NULL); + gst_element_post_message (GST_ELEMENT (vpp), message); +} + static GstFlowReturn gst_vdp_vpp_open_device (GstVdpVideoPostProcess * vpp) { GstFlowReturn ret; + GError *err = NULL; GST_DEBUG ("open_device"); ret = gst_vdp_output_src_pad_get_device (GST_VDP_OUTPUT_SRC_PAD (vpp->srcpad), - &vpp->device); + &vpp->device, &err); + if (ret == GST_FLOW_ERROR) { + gst_vdp_vpp_post_error (vpp, err); + g_error_free (err); + } return ret; } @@ -477,11 +491,33 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps) GstVdpVideoPostProcess *vpp = GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad)); GstStructure *structure; - GstCaps *output_caps, *allowed_caps, *src_caps; + GstCaps *video_caps = NULL; gboolean res = FALSE; - /* extract interlaced flag */ + /* check if the input is non native */ structure = gst_caps_get_structure (caps, 0); + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + if (!gst_structure_get_fourcc (structure, "format", &vpp->fourcc)) + goto done; + vpp->native_input = FALSE; + video_caps = gst_vdp_video_buffer_parse_yuv_caps (caps); + if (!video_caps) + goto done; + } else { + vpp->native_input = TRUE; + video_caps = gst_caps_copy (caps); + } + + + structure = gst_caps_get_structure (video_caps, 0); + if (!gst_structure_get_int (structure, "width", &vpp->width) || + !gst_structure_get_int (structure, "height", &vpp->height) || + !gst_structure_get_int (structure, "chroma-type", + (gint *) & vpp->chroma_type)) + goto done; + + + /* get interlaced flag */ gst_structure_get_boolean (structure, "interlaced", &vpp->interlaced); /* extract par */ @@ -493,54 +529,9 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps) } else vpp->got_par = FALSE; - if (gst_structure_has_name (structure, "video/x-vdpau-video")) { - - if (!gst_structure_get_int (structure, "width", &vpp->width) || - !gst_structure_get_int (structure, "height", &vpp->height) || - !gst_structure_get_int (structure, "chroma-type", - (gint *) & vpp->chroma_type)) - goto done; - - output_caps = gst_vdp_video_to_output_caps (caps); - vpp->native_input = TRUE; - } else { - vpp->native_input = FALSE; - if (!gst_vdp_video_buffer_parse_yuv_caps (caps, &vpp->chroma_type, - &vpp->width, &vpp->height)) - goto done; - if (!gst_structure_get_fourcc (structure, "format", &vpp->fourcc)) - goto done; - - output_caps = gst_vdp_yuv_to_output_caps (caps); - } - GST_DEBUG ("output_caps: %" GST_PTR_FORMAT, output_caps); - - allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad); - GST_DEBUG ("allowed_caps: %" GST_PTR_FORMAT, allowed_caps); - if (G_UNLIKELY (!allowed_caps)) - goto allowed_caps_error; - if (G_UNLIKELY (gst_caps_is_empty (allowed_caps))) { - gst_caps_unref (allowed_caps); - goto allowed_caps_error; - } - - src_caps = gst_caps_intersect (output_caps, allowed_caps); - gst_caps_unref (output_caps); - gst_caps_unref (allowed_caps); - - if (gst_caps_is_empty (src_caps)) { - gst_caps_unref (src_caps); - goto not_negotiated; - } - gst_pad_fixate_caps (vpp->srcpad, src_caps); - - GST_DEBUG ("src_caps: %" GST_PTR_FORMAT, src_caps); - if (gst_vdp_vpp_is_interlaced (vpp)) { gint fps_n, fps_d; - structure = gst_caps_get_structure (src_caps, 0); - if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) { gst_fraction_double (&fps_n, &fps_d); gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, fps_n, @@ -551,21 +542,16 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps) gst_structure_remove_field (structure, "interlaced"); } - res = gst_vdp_output_src_pad_set_caps (GST_VDP_OUTPUT_SRC_PAD (vpp->srcpad), - src_caps); + res = + gst_vdp_output_src_pad_negotiate_output (GST_VDP_OUTPUT_SRC_PAD + (vpp->srcpad), video_caps); done: gst_object_unref (vpp); - return res; + if (video_caps) + gst_caps_unref (video_caps); -allowed_caps_error: - gst_caps_unref (output_caps); - goto done; - -not_negotiated: - GST_DEBUG_OBJECT (vpp, "Couldn't find suitable output format"); - res = FALSE; - goto done; + return res; } static void @@ -632,6 +618,7 @@ gst_vdp_vpp_drain (GstVdpVideoPostProcess * vpp) ¤t_pic, &video_surfaces_past_count, video_surfaces_past, &video_surfaces_future_count, video_surfaces_future)) { + GError *err; GstVdpOutputBuffer *outbuf; GstStructure *structure; @@ -643,14 +630,12 @@ gst_vdp_vpp_drain (GstVdpVideoPostProcess * vpp) GstVdpDevice *device; VdpStatus status; + err = NULL; ret = gst_vdp_output_src_pad_alloc_buffer ((GstVdpOutputSrcPad *) vpp->srcpad, - &outbuf); + &outbuf, &err); if (ret != GST_FLOW_OK) - break; - - gst_vdp_output_src_pad_set_caps ((GstVdpOutputSrcPad *) vpp->srcpad, - GST_BUFFER_CAPS (outbuf)); + goto output_pad_error; src_r.w = vpp->width; src_r.h = vpp->height; @@ -664,10 +649,8 @@ gst_vdp_vpp_drain (GstVdpVideoPostProcess * vpp) structure = gst_caps_get_structure (GST_BUFFER_CAPS (outbuf), 0); if (!gst_structure_get_int (structure, "width", &dest_r.w) || - !gst_structure_get_int (structure, "height", &dest_r.h)) { - gst_buffer_unref (GST_BUFFER (outbuf)); + !gst_structure_get_int (structure, "height", &dest_r.h)) goto invalid_caps; - } if (vpp->force_aspect_ratio) { GstVideoRectangle res_r; @@ -690,14 +673,8 @@ gst_vdp_vpp_drain (GstVdpVideoPostProcess * vpp) current_pic.structure, video_surfaces_past_count, video_surfaces_past, current_pic.buf->surface, video_surfaces_future_count, video_surfaces_future, NULL, outbuf->surface, NULL, &rect, 0, NULL); - if (status != VDP_STATUS_OK) { - gst_buffer_unref (GST_BUFFER (outbuf)); - GST_ELEMENT_ERROR (vpp, RESOURCE, READ, - ("Could not postprocess frame"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return GST_FLOW_ERROR; - } + if (status != VDP_STATUS_OK) + goto render_error; GST_BUFFER_TIMESTAMP (outbuf) = current_pic.timestamp; if (gst_vdp_vpp_is_interlaced (vpp)) @@ -714,21 +691,38 @@ gst_vdp_vpp_drain (GstVdpVideoPostProcess * vpp) if (GST_BUFFER_FLAG_IS_SET (current_pic.buf, GST_BUFFER_FLAG_GAP)) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); + err = NULL; ret = gst_vdp_output_src_pad_push ((GstVdpOutputSrcPad *) vpp->srcpad, - outbuf); + outbuf, &err); if (ret != GST_FLOW_OK) - break; + goto output_pad_error; continue; + + render_error: + gst_buffer_unref (GST_BUFFER (outbuf)); + GST_ELEMENT_ERROR (vpp, RESOURCE, READ, + ("Could not postprocess frame"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + ret = GST_FLOW_ERROR; + + invalid_caps: + gst_buffer_unref (GST_BUFFER (outbuf)); + GST_ELEMENT_ERROR (vpp, STREAM, FAILED, ("Invalid output caps"), (NULL)); + ret = GST_FLOW_ERROR; + break; + + output_pad_error: + if (ret == GST_FLOW_ERROR && err != NULL) { + gst_vdp_vpp_post_error (vpp, err); + g_error_free (err); + } + break; } return ret; - -invalid_caps: - GST_ELEMENT_ERROR (vpp, STREAM, FAILED, ("Invalid output caps"), (NULL)); - return GST_FLOW_ERROR; - } static GstFlowReturn diff --git a/sys/vdpau/gstvdpvideopostprocess.h b/sys/vdpau/gstvdpvideopostprocess.h index a1a03b6..537b3d4 100644 --- a/sys/vdpau/gstvdpvideopostprocess.h +++ b/sys/vdpau/gstvdpvideopostprocess.h @@ -45,6 +45,7 @@ typedef enum GST_VDP_DEINTERLACE_MODE_INTERLACED, GST_VDP_DEINTERLACE_MODE_DISABLED } GstVdpDeinterlaceModes; + typedef enum { GST_VDP_DEINTERLACE_METHOD_BOB,