mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
vdpauvideopostprocess: use GstVdp[Video|Output]BufferPool to cache our buffers
This way we'll reuse the GstVdp[Video|Output]Buffers if they're of the same size and chroma-type/rgba-format. Also remove gst_vdp_output_src_pad_negotiate and set a "setcaps" function on GstVdpOutputSrcPad instead, leaving negotiation to GstVdpVideoPostProcess.
This commit is contained in:
parent
57175ece9e
commit
aa193a7b43
4 changed files with 108 additions and 157 deletions
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "gstvdputils.h"
|
||||
#include "gstvdpvideobuffer.h"
|
||||
#include "gstvdpoutputbufferpool.h"
|
||||
|
||||
#include "gstvdpoutputsrcpad.h"
|
||||
|
||||
|
@ -46,11 +47,13 @@ struct _GstVdpOutputSrcPad
|
|||
|
||||
GstCaps *caps;
|
||||
|
||||
GstCaps *input_caps;
|
||||
GstCaps *output_caps;
|
||||
GstVdpOutputSrcPadFormat output_format;
|
||||
VdpRGBAFormat rgba_format;
|
||||
gint width, height;
|
||||
|
||||
GstVdpBufferPool *bpool;
|
||||
|
||||
/* properties */
|
||||
GstVdpDevice *device;
|
||||
};
|
||||
|
@ -126,57 +129,20 @@ gst_vdp_output_src_pad_create_buffer (GstVdpOutputSrcPad * vdp_pad,
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (ret == GST_FLOW_OK)
|
||||
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, NULL);
|
||||
*output_buf =
|
||||
(GstVdpOutputBuffer *) gst_vdp_buffer_pool_get_buffer (vdp_pad->bpool,
|
||||
error);
|
||||
if (!*output_buf)
|
||||
goto output_buf_error;
|
||||
|
||||
gst_buffer_set_caps (GST_BUFFER_CAST (*output_buf), vdp_pad->input_caps);
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
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 GstFlowReturn
|
||||
|
@ -185,7 +151,7 @@ gst_vdp_output_src_pad_alloc_with_caps (GstVdpOutputSrcPad * vdp_pad,
|
|||
{
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = gst_pad_alloc_buffer ((GstPad *) vdp_pad, 0, 0, caps,
|
||||
ret = gst_pad_alloc_buffer_and_set_caps ((GstPad *) vdp_pad, 0, 0, caps,
|
||||
(GstBuffer **) output_buf);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
@ -244,71 +210,53 @@ gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad * vdp_pad,
|
|||
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_vdp_output_src_pad_negotiate_output (GstVdpOutputSrcPad * vdp_pad,
|
||||
GstCaps * video_caps)
|
||||
static gboolean
|
||||
gst_vdp_output_src_pad_setcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
GstCaps *allowed_caps, *output_caps, *src_caps;
|
||||
GstVdpOutputSrcPad *vdp_pad = GST_VDP_OUTPUT_SRC_PAD (pad);
|
||||
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);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
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);
|
||||
if (!gst_structure_get_int (structure, "width", &vdp_pad->width))
|
||||
return FALSE;
|
||||
if (!gst_structure_get_int (structure, "height", &vdp_pad->height))
|
||||
return FALSE;
|
||||
|
||||
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 (src_caps, &vdp_pad->rgba_format))
|
||||
if (!gst_vdp_caps_to_rgba_format (caps, &vdp_pad->rgba_format))
|
||||
return FALSE;
|
||||
|
||||
/* create buffer pool if we dont't have one */
|
||||
if (!vdp_pad->bpool)
|
||||
vdp_pad->bpool = gst_vdp_output_buffer_pool_new (vdp_pad->device);
|
||||
|
||||
if (vdp_pad->output_caps)
|
||||
gst_caps_unref (vdp_pad->output_caps);
|
||||
|
||||
vdp_pad->output_caps = gst_caps_new_simple ("video/x-vdpau-output",
|
||||
"rgba-format", G_TYPE_INT, vdp_pad->rgba_format,
|
||||
"width", G_TYPE_INT, vdp_pad->width, "height", G_TYPE_INT,
|
||||
vdp_pad->height, NULL);
|
||||
gst_vdp_buffer_pool_set_caps (vdp_pad->bpool, vdp_pad->output_caps);
|
||||
|
||||
vdp_pad->output_format = GST_VDP_OUTPUT_SRC_PAD_FORMAT_RGB;
|
||||
} else if (gst_structure_has_name (structure, "video/x-vdpau-output")) {
|
||||
if (!gst_structure_get_int (structure, "rgba-format",
|
||||
(gint *) & vdp_pad->rgba_format))
|
||||
return FALSE;
|
||||
|
||||
/* don't need the buffer pool */
|
||||
if (vdp_pad->bpool) {
|
||||
gst_object_unref (vdp_pad->bpool);
|
||||
vdp_pad->bpool = NULL;
|
||||
}
|
||||
|
||||
vdp_pad->output_format = GST_VDP_OUTPUT_SRC_PAD_FORMAT_VDPAU;
|
||||
} else
|
||||
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;
|
||||
|
||||
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;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
|
@ -337,8 +285,16 @@ gst_vdp_output_src_pad_activate_push (GstPad * pad, gboolean active)
|
|||
gst_caps_unref (vdp_pad->caps);
|
||||
vdp_pad->caps = NULL;
|
||||
|
||||
if (vdp_pad->output_caps)
|
||||
gst_caps_unref (vdp_pad->output_caps);
|
||||
vdp_pad->output_caps = NULL;
|
||||
|
||||
if (vdp_pad->bpool)
|
||||
g_object_unref (vdp_pad->bpool);
|
||||
vdp_pad->bpool = NULL;
|
||||
|
||||
if (vdp_pad->device)
|
||||
gst_object_unref (vdp_pad->device);
|
||||
g_object_unref (vdp_pad->device);
|
||||
vdp_pad->device = NULL;
|
||||
}
|
||||
|
||||
|
@ -413,11 +369,14 @@ gst_vdp_output_src_pad_init (GstVdpOutputSrcPad * vdp_pad)
|
|||
GstPad *pad = GST_PAD (vdp_pad);
|
||||
|
||||
vdp_pad->caps = NULL;
|
||||
|
||||
vdp_pad->output_caps = NULL;
|
||||
vdp_pad->bpool = NULL;
|
||||
vdp_pad->device = NULL;
|
||||
|
||||
gst_pad_set_getcaps_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_vdp_output_src_pad_getcaps));
|
||||
gst_pad_set_setcaps_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_vdp_output_src_pad_setcaps));
|
||||
gst_pad_set_activatepush_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_vdp_output_src_pad_activate_push));
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@ GstFlowReturn gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad *vdp_pad,
|
|||
|
||||
GstFlowReturn gst_vdp_output_src_pad_get_device (GstVdpOutputSrcPad *vdp_pad, GstVdpDevice **device, GError **error);
|
||||
|
||||
gboolean gst_vdp_output_src_pad_negotiate_output (GstVdpOutputSrcPad *vdp_pad, GstCaps *video_caps);
|
||||
|
||||
GstVdpOutputSrcPad *gst_vdp_output_src_pad_new (GstPadTemplate *templ, const gchar *name);
|
||||
GType gst_vdp_output_src_pad_get_type (void);
|
||||
|
||||
|
|
|
@ -474,6 +474,8 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstCaps *video_caps = NULL;
|
||||
gboolean res = FALSE;
|
||||
|
||||
GstCaps *allowed_caps, *output_caps, *src_caps;
|
||||
|
||||
/* check if the input is non native */
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
|
||||
|
@ -483,9 +485,20 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
video_caps = gst_vdp_video_buffer_parse_yuv_caps (caps);
|
||||
if (!video_caps)
|
||||
goto done;
|
||||
|
||||
if (!vpp->vpool)
|
||||
vpp->vpool = gst_vdp_video_buffer_pool_new (vpp->device);
|
||||
|
||||
gst_vdp_buffer_pool_set_caps (vpp->vpool, video_caps);
|
||||
|
||||
} else {
|
||||
vpp->native_input = TRUE;
|
||||
video_caps = gst_caps_copy (caps);
|
||||
|
||||
if (vpp->vpool) {
|
||||
g_object_unref (vpp->vpool);
|
||||
vpp->vpool = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -522,9 +535,29 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gst_structure_remove_field (structure, "interlaced");
|
||||
}
|
||||
|
||||
res =
|
||||
gst_vdp_output_src_pad_negotiate_output (GST_VDP_OUTPUT_SRC_PAD
|
||||
(vpp->srcpad), video_caps);
|
||||
allowed_caps = gst_pad_get_allowed_caps (vpp->srcpad);
|
||||
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 (allowed_caps);
|
||||
gst_caps_unref (output_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps))
|
||||
goto not_negotiated;
|
||||
|
||||
gst_pad_fixate_caps (vpp->srcpad, src_caps);
|
||||
|
||||
GST_DEBUG ("src_caps: %" GST_PTR_FORMAT, src_caps);
|
||||
|
||||
res = gst_pad_set_caps (vpp->srcpad, src_caps);
|
||||
gst_caps_unref (src_caps);
|
||||
|
||||
done:
|
||||
gst_object_unref (vpp);
|
||||
|
@ -532,6 +565,15 @@ done:
|
|||
gst_caps_unref (video_caps);
|
||||
|
||||
return res;
|
||||
|
||||
allowed_caps_error:
|
||||
GST_ERROR_OBJECT (vpp, "Got invalid allowed caps");
|
||||
goto done;
|
||||
|
||||
not_negotiated:
|
||||
gst_caps_unref (src_caps);
|
||||
GST_ERROR_OBJECT (vpp, "Couldn't find suitable output format");
|
||||
goto done;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -562,7 +604,7 @@ gst_vdp_vpp_start (GstVdpVideoPostProcess * vpp)
|
|||
vpp->discont = FALSE;
|
||||
|
||||
vpp->mixer = VDP_INVALID_HANDLE;
|
||||
vpp->device = NULL;
|
||||
vpp->vpool = NULL;
|
||||
|
||||
for (i = 0; i < MAX_PICTURES; i++) {
|
||||
vpp->future_pictures[i].buf = NULL;
|
||||
|
@ -590,6 +632,9 @@ gst_vdp_vpp_stop (GstVdpVideoPostProcess * vpp)
|
|||
{
|
||||
gst_vdp_vpp_flush (vpp);
|
||||
|
||||
if (vpp->vpool)
|
||||
g_object_unref (vpp->vpool);
|
||||
|
||||
if (vpp->mixer != VDP_INVALID_HANDLE) {
|
||||
GstVdpDevice *device = vpp->device;
|
||||
VdpStatus status;
|
||||
|
@ -738,6 +783,7 @@ gst_vdp_vpp_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
GstClockTime qostime;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GError *err;
|
||||
|
||||
GST_DEBUG ("chain");
|
||||
|
||||
|
@ -790,8 +836,9 @@ no_qos:
|
|||
if (!vpp->native_input) {
|
||||
GstVdpVideoBuffer *video_buf;
|
||||
|
||||
video_buf = gst_vdp_video_buffer_new (vpp->device, vpp->chroma_type,
|
||||
vpp->width, vpp->height, NULL);
|
||||
err = NULL;
|
||||
video_buf =
|
||||
(GstVdpVideoBuffer *) gst_vdp_buffer_pool_get_buffer (vpp->vpool, &err);
|
||||
if (G_UNLIKELY (!video_buf))
|
||||
goto video_buf_error;
|
||||
|
||||
|
@ -832,8 +879,7 @@ error:
|
|||
|
||||
video_buf_error:
|
||||
gst_buffer_unref (GST_BUFFER (buffer));
|
||||
GST_ELEMENT_ERROR (vpp, RESOURCE, READ,
|
||||
("Couldn't create GstVdpVideoBuffer"), (NULL));
|
||||
gst_vdp_vpp_post_error (vpp, err);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
@ -861,59 +907,6 @@ gst_vdp_vpp_sink_getcaps (GstPad * pad)
|
|||
return caps;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_vdp_vpp_sink_bufferalloc (GstPad * pad, guint64 offset, guint size,
|
||||
GstCaps * caps, GstBuffer ** buf)
|
||||
{
|
||||
GstVdpVideoPostProcess *vpp =
|
||||
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
|
||||
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||
GstStructure *structure;
|
||||
|
||||
GST_DEBUG ("buffer_alloc");
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
if (gst_structure_has_name (structure, "video/x-vdpau-video")) {
|
||||
gint width, height;
|
||||
VdpChromaType chroma_type;
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &width) ||
|
||||
!gst_structure_get_int (structure, "height", &height) ||
|
||||
!gst_structure_get_int (structure, "chroma-type",
|
||||
(gint *) & chroma_type))
|
||||
goto invalid_caps;
|
||||
|
||||
*buf =
|
||||
GST_BUFFER (gst_vdp_video_buffer_new (vpp->device, chroma_type, width,
|
||||
height, NULL));
|
||||
|
||||
if (*buf == NULL)
|
||||
goto video_buffer_error;
|
||||
} else
|
||||
*buf = gst_buffer_new_and_alloc (size);
|
||||
|
||||
GST_BUFFER_SIZE (*buf) = size;
|
||||
GST_BUFFER_OFFSET (*buf) = offset;
|
||||
|
||||
gst_buffer_set_caps (*buf, caps);
|
||||
|
||||
ret = GST_FLOW_OK;
|
||||
|
||||
done:
|
||||
gst_object_unref (vpp);
|
||||
return ret;
|
||||
|
||||
invalid_caps:
|
||||
GST_ELEMENT_ERROR (vpp, STREAM, FAILED, ("Invalid caps"), (NULL));
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
|
||||
video_buffer_error:
|
||||
GST_ELEMENT_ERROR (vpp, RESOURCE, READ,
|
||||
("Couldn't create GstVdpVideoBuffer"), (NULL));
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vdp_vpp_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
|
@ -1291,7 +1284,6 @@ gst_vdp_vpp_init (GstVdpVideoPostProcess * vpp,
|
|||
GST_DEBUG_FUNCPTR (gst_vdp_vpp_chain));
|
||||
gst_pad_set_event_function (vpp->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_vdp_vpp_sink_event));
|
||||
gst_pad_set_bufferalloc_function (vpp->sinkpad, gst_vdp_vpp_sink_bufferalloc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "gstvdp/gstvdpdevice.h"
|
||||
#include "gstvdp/gstvdpvideobuffer.h"
|
||||
#include "gstvdp/gstvdpvideobufferpool.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -72,6 +73,7 @@ struct _GstVdpVideoPostProcess
|
|||
VdpChromaType chroma_type;
|
||||
gint width, height;
|
||||
guint32 fourcc;
|
||||
GstVdpBufferPool *vpool;
|
||||
|
||||
gboolean got_par;
|
||||
gint par_n, par_d;
|
||||
|
|
Loading…
Reference in a new issue