summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2010-07-30 11:27:27 +0200
committerCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2010-07-30 11:33:13 +0200
commitaa193a7b4391f98367c9d0f27b220cdd6bcb8db7 (patch)
tree290342e09f07c2f587ff5fbad9e7a1e03bafb15c
parent57175ece9e629520c89112571bcea8c99b3cd581 (diff)
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.
-rw-r--r--sys/vdpau/gstvdp/gstvdpoutputsrcpad.c143
-rw-r--r--sys/vdpau/gstvdp/gstvdpoutputsrcpad.h2
-rw-r--r--sys/vdpau/gstvdpvideopostprocess.c116
-rw-r--r--sys/vdpau/gstvdpvideopostprocess.h2
4 files changed, 107 insertions, 156 deletions
diff --git a/sys/vdpau/gstvdp/gstvdpoutputsrcpad.c b/sys/vdpau/gstvdp/gstvdpoutputsrcpad.c
index 9813f68ef..078f325e6 100644
--- a/sys/vdpau/gstvdp/gstvdpoutputsrcpad.c
+++ b/sys/vdpau/gstvdp/gstvdpoutputsrcpad.c
@@ -17,12 +17,13 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gstvdputils.h"
#include "gstvdpvideobuffer.h"
+#include "gstvdpoutputbufferpool.h"
#include "gstvdpoutputsrcpad.h"
GST_DEBUG_CATEGORY_STATIC (gst_vdp_output_src_pad_debug);
#define GST_CAT_DEFAULT gst_vdp_output_src_pad_debug
@@ -43,17 +44,19 @@ enum _GstVdpOutputSrcPadFormat
struct _GstVdpOutputSrcPad
{
GstPad pad;
GstCaps *caps;
- GstCaps *input_caps;
+ GstCaps *output_caps;
GstVdpOutputSrcPadFormat output_format;
VdpRGBAFormat rgba_format;
gint width, height;
+ GstVdpBufferPool *bpool;
+
/* properties */
GstVdpDevice *device;
};
struct _GstVdpOutputSrcPadClass
{
@@ -123,72 +126,35 @@ gst_vdp_output_src_pad_push (GstVdpOutputSrcPad * vdp_pad,
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);
- }
-
+ 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
gst_vdp_output_src_pad_alloc_with_caps (GstVdpOutputSrcPad * vdp_pad,
GstCaps * caps, GstVdpOutputBuffer ** output_buf, GError ** error)
{
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;
if (!GST_IS_VDP_OUTPUT_BUFFER (*output_buf))
goto invalid_buf;
@@ -241,77 +207,59 @@ gst_vdp_output_src_pad_alloc_buffer (GstVdpOutputSrcPad * vdp_pad,
}
return GST_FLOW_OK;
}
-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);
-
- 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_structure_get_int (structure, "width", &vdp_pad->width))
+ return FALSE;
+ if (!gst_structure_get_int (structure, "height", &vdp_pad->height))
+ return FALSE;
- if (gst_caps_is_empty (src_caps))
- goto not_negotiated;
+ if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
+ if (!gst_vdp_caps_to_rgba_format (caps, &vdp_pad->rgba_format))
+ return FALSE;
- gst_pad_fixate_caps (GST_PAD_CAST (vdp_pad), src_caps);
+ /* 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);
- GST_DEBUG ("src_caps: %" GST_PTR_FORMAT, src_caps);
+ if (vdp_pad->output_caps)
+ gst_caps_unref (vdp_pad->output_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))
- return FALSE;
+ 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 *
gst_vdp_output_src_pad_getcaps (GstPad * pad)
{
GstVdpOutputSrcPad *vdp_pad = (GstVdpOutputSrcPad *) pad;
@@ -334,14 +282,22 @@ gst_vdp_output_src_pad_activate_push (GstPad * pad, gboolean active)
if (!active) {
if (vdp_pad->caps)
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;
}
return TRUE;
}
@@ -410,17 +366,20 @@ gst_vdp_output_src_pad_set_property (GObject * object, guint prop_id,
static void
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));
}
static void
gst_vdp_output_src_pad_class_init (GstVdpOutputSrcPadClass * klass)
diff --git a/sys/vdpau/gstvdp/gstvdpoutputsrcpad.h b/sys/vdpau/gstvdp/gstvdpoutputsrcpad.h
index be3f3ec68..02981a31c 100644
--- a/sys/vdpau/gstvdp/gstvdpoutputsrcpad.h
+++ b/sys/vdpau/gstvdp/gstvdpoutputsrcpad.h
@@ -40,14 +40,12 @@ typedef struct _GstVdpOutputSrcPadClass GstVdpOutputSrcPadClass;
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, 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);
G_END_DECLS
#endif /* _GST_VDP_OUTPUT_SRC_PAD_H_ */
diff --git a/sys/vdpau/gstvdpvideopostprocess.c b/sys/vdpau/gstvdpvideopostprocess.c
index e77b41dd6..8311f28ce 100644
--- a/sys/vdpau/gstvdpvideopostprocess.c
+++ b/sys/vdpau/gstvdpvideopostprocess.c
@@ -471,24 +471,37 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
GstVdpVideoPostProcess *vpp =
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
GstStructure *structure;
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")) {
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;
+
+ 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;
+ }
}
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) ||
@@ -519,22 +532,51 @@ gst_vdp_vpp_sink_setcaps (GstPad * pad, GstCaps * caps)
vpp->field_duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
}
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);
if (video_caps)
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
gst_vdp_vpp_flush (GstVdpVideoPostProcess * vpp)
{
gint i;
@@ -559,13 +601,13 @@ gst_vdp_vpp_start (GstVdpVideoPostProcess * vpp)
vpp->field_duration = GST_CLOCK_TIME_NONE;
vpp->earliest_time = GST_CLOCK_TIME_NONE;
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;
vpp->past_pictures[i].buf = NULL;
}
vpp->n_future_pictures = 0;
@@ -587,12 +629,15 @@ device_error:
static gboolean
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;
status = device->vdp_video_mixer_destroy (vpp->mixer);
if (status != VDP_STATUS_OK) {
@@ -735,12 +780,13 @@ gst_vdp_vpp_chain (GstPad * pad, GstBuffer * buffer)
{
GstVdpVideoPostProcess *vpp =
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
GstClockTime qostime;
GstFlowReturn ret = GST_FLOW_OK;
+ GError *err;
GST_DEBUG ("chain");
/* can only do QoS if the segment is in TIME */
if (vpp->segment.format != GST_FORMAT_TIME)
goto no_qos;
@@ -787,14 +833,15 @@ no_qos:
gst_vdp_vpp_flush (vpp);
}
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;
if (!gst_vdp_video_buffer_upload (video_buf, buffer, vpp->fourcc,
vpp->width, vpp->height)) {
gst_buffer_unref (GST_BUFFER (video_buf));
@@ -829,14 +876,13 @@ done:
error:
gst_buffer_unref (buffer);
goto done;
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;
}
static GstCaps *
gst_vdp_vpp_sink_getcaps (GstPad * pad)
@@ -858,65 +904,12 @@ gst_vdp_vpp_sink_getcaps (GstPad * pad)
gst_object_unref (vpp);
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)
{
GstVdpVideoPostProcess *vpp =
GST_VDP_VIDEO_POST_PROCESS (gst_pad_get_parent (pad));
gboolean res;
@@ -1288,13 +1281,12 @@ gst_vdp_vpp_init (GstVdpVideoPostProcess * vpp,
gst_pad_set_getcaps_function (vpp->sinkpad, gst_vdp_vpp_sink_getcaps);
gst_pad_set_setcaps_function (vpp->sinkpad, gst_vdp_vpp_sink_setcaps);
gst_pad_set_chain_function (vpp->sinkpad,
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
gst_vdp_vpp_finalize (GObject * object)
{
}
diff --git a/sys/vdpau/gstvdpvideopostprocess.h b/sys/vdpau/gstvdpvideopostprocess.h
index 678015800..da57e827a 100644
--- a/sys/vdpau/gstvdpvideopostprocess.h
+++ b/sys/vdpau/gstvdpvideopostprocess.h
@@ -22,12 +22,13 @@
#define __GST_VDP_VIDEO_POST_PROCESS_H__
#include <gst/gst.h>
#include "gstvdp/gstvdpdevice.h"
#include "gstvdp/gstvdpvideobuffer.h"
+#include "gstvdp/gstvdpvideobufferpool.h"
G_BEGIN_DECLS
#define MAX_PICTURES 6
typedef struct _GstVdpPicture GstVdpPicture;
@@ -69,12 +70,13 @@ struct _GstVdpVideoPostProcess
GstPad *sinkpad, *srcpad;
gboolean native_input;
VdpChromaType chroma_type;
gint width, height;
guint32 fourcc;
+ GstVdpBufferPool *vpool;
gboolean got_par;
gint par_n, par_d;
gboolean interlaced;
GstClockTime field_duration;