mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
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
This commit is contained in:
parent
ff7381109f
commit
c4f60760ed
7 changed files with 264 additions and 184 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, " \
|
||||
|
|
|
@ -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_vdp_output_buffer_calculate_size (output_buf, &size);
|
||||
|
||||
/* 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, outbuf, error)) {
|
||||
gst_buffer_unref (GST_BUFFER_CAST (output_buf));
|
||||
gst_buffer_unref (outbuf);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
out_buf = gst_buffer_new_and_alloc (size);
|
||||
gst_buffer_set_caps (out_buf, 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");
|
||||
gst_buffer_unref (GST_BUFFER_CAST (output_buf));
|
||||
gst_buffer_unref (out_buf);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
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 (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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
if (video_caps)
|
||||
gst_caps_unref (video_caps);
|
||||
|
||||
return res;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef enum
|
|||
GST_VDP_DEINTERLACE_MODE_INTERLACED,
|
||||
GST_VDP_DEINTERLACE_MODE_DISABLED
|
||||
} GstVdpDeinterlaceModes;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_VDP_DEINTERLACE_METHOD_BOB,
|
||||
|
|
Loading…
Reference in a new issue