diff options
author | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2010-07-30 11:20:35 +0200 |
---|---|---|
committer | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2010-07-30 11:33:13 +0200 |
commit | 57175ece9e629520c89112571bcea8c99b3cd581 (patch) | |
tree | cea0373c893f5138182c6e9fd53000b0d02ca09d | |
parent | c0e1fba08943e6b4873d0c3e0e2ae23c768de84f (diff) |
vdpausink: use GstVdpOutputBufferPool to alloc our buffers
This way we'll reuse our GstVdpOutputBuffers if they're of the same size and
rgba-format
-rw-r--r-- | sys/vdpau/gstvdpsink.c | 91 | ||||
-rw-r--r-- | sys/vdpau/gstvdpsink.h | 1 |
2 files changed, 39 insertions, 53 deletions
diff --git a/sys/vdpau/gstvdpsink.c b/sys/vdpau/gstvdpsink.c index 933990f8c..70bcd6bfe 100644 --- a/sys/vdpau/gstvdpsink.c +++ b/sys/vdpau/gstvdpsink.c @@ -27,12 +27,13 @@ #include <gst/interfaces/xoverlay.h> /* Debugging category */ #include <gst/gstinfo.h> #include "gstvdp/gstvdpoutputbuffer.h" +#include "gstvdp/gstvdpoutputbufferpool.h" /* Object header */ #include "gstvdpsink.h" GST_DEBUG_CATEGORY_STATIC (gst_vdp_sink_debug); #define GST_CAT_DEFAULT gst_vdp_sink_debug @@ -565,20 +566,22 @@ gst_vdp_sink_get_allowed_caps (GstVdpDevice * device, GValue * par) gst_structure_set_value (structure, "pixel-aspect-ratio", par); } return caps; } -static GstVdpDevice * -gst_vdp_sink_setup_device (VdpSink * vdp_sink) +static gboolean +gst_vdp_sink_open_device (VdpSink * vdp_sink) { GstVdpDevice *device; - device = gst_vdp_get_device (vdp_sink->display_name); - if (!device) - return NULL; + vdp_sink->device = device = gst_vdp_get_device (vdp_sink->display_name); + if (!vdp_sink->device) + return FALSE; + + vdp_sink->bpool = gst_vdp_output_buffer_pool_new (device); vdp_sink->caps = gst_vdp_sink_get_allowed_caps (device, vdp_sink->par); GST_DEBUG ("runtime calculated caps: %" GST_PTR_FORMAT, vdp_sink->caps); /* call XSynchronize with the current value of synchronous */ GST_DEBUG_OBJECT (vdp_sink, "XSynchronize called with %s", @@ -587,13 +590,13 @@ gst_vdp_sink_setup_device (VdpSink * vdp_sink) /* Setup our event listening thread */ vdp_sink->running = TRUE; vdp_sink->event_thread = g_thread_create ( (GThreadFunc) gst_vdp_sink_event_thread, vdp_sink, TRUE, NULL); - return device; + return TRUE; } static gboolean gst_vdp_sink_start (GstBaseSink * bsink) { VdpSink *vdp_sink = GST_VDP_SINK (bsink); @@ -605,16 +608,14 @@ gst_vdp_sink_start (GstBaseSink * bsink) vdp_sink->event_thread = NULL; vdp_sink->fps_n = 0; vdp_sink->fps_d = 1; GST_OBJECT_LOCK (vdp_sink); - if (!vdp_sink->device) { - if (!(vdp_sink->device = gst_vdp_sink_setup_device (vdp_sink))) - res = FALSE; - } + if (!vdp_sink->device) + res = gst_vdp_sink_open_device (vdp_sink); GST_OBJECT_UNLOCK (vdp_sink); return res; } static void @@ -628,12 +629,13 @@ gst_vdp_device_clear (VdpSink * vdp_sink) return; } GST_OBJECT_UNLOCK (vdp_sink); g_mutex_lock (vdp_sink->x_lock); + g_object_unref (vdp_sink->bpool); g_object_unref (vdp_sink->device); vdp_sink->device = NULL; g_mutex_unlock (vdp_sink->x_lock); } @@ -729,12 +731,14 @@ gst_vdp_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) GST_VIDEO_SINK_WIDTH (vdp_sink) = new_width; GST_VIDEO_SINK_HEIGHT (vdp_sink) = new_height; vdp_sink->fps_n = gst_value_get_fraction_numerator (fps); vdp_sink->fps_d = gst_value_get_fraction_denominator (fps); + gst_vdp_buffer_pool_set_caps (vdp_sink->bpool, caps); + /* Notify application to set xwindow id now */ g_mutex_lock (vdp_sink->flow_lock); if (!vdp_sink->window) { g_mutex_unlock (vdp_sink->flow_lock); gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (vdp_sink)); } else { @@ -891,38 +895,20 @@ gst_vdp_sink_event (GstBaseSink * sink, GstEvent * event) if (GST_BASE_SINK_CLASS (parent_class)->event) return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); else return TRUE; } -static GstFlowReturn -gst_vdp_sink_get_output_buffer (VdpSink * vdp_sink, GstCaps * caps, - GstBuffer ** buf) +static void +gst_vdp_sink_post_error (VdpSink * vdp_sink, GError * error) { - GstStructure *structure; - gint width, height; - gint rgba_format; + GstMessage *message; - structure = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (structure, "width", &width) || - !gst_structure_get_int (structure, "height", &height) || - !gst_structure_get_int (structure, "rgba-format", &rgba_format)) { - GST_WARNING_OBJECT (vdp_sink, "invalid caps for buffer allocation %" - GST_PTR_FORMAT, caps); - return GST_FLOW_ERROR; - } - - *buf = GST_BUFFER (gst_vdp_output_buffer_new (vdp_sink->device, - rgba_format, width, height, NULL)); - if (*buf == NULL) { - return GST_FLOW_ERROR; - } - - gst_buffer_set_caps (*buf, caps); - - return GST_FLOW_OK; + message = gst_message_new_error (GST_OBJECT (vdp_sink), error, NULL); + gst_element_post_message (GST_ELEMENT (vdp_sink), message); + g_error_free (error); } /* Buffer management * * The buffer_alloc function must either return a buffer with given size and * caps or create a buffer with different caps attached to the buffer. This @@ -936,39 +922,35 @@ static GstFlowReturn gst_vdp_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { VdpSink *vdp_sink; GstStructure *structure = NULL; GstFlowReturn ret = GST_FLOW_OK; - GstCaps *alloc_caps; - gboolean alloc_unref = FALSE; gint width, height; + GstCaps *alloc_caps; gint w_width, w_height; + GError *err; vdp_sink = GST_VDP_SINK (bsink); GST_LOG_OBJECT (vdp_sink, "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT " and offset %" G_GUINT64_FORMAT, size, caps, offset); - /* assume we're going to alloc what was requested, keep track of - * wheter we need to unref or not. When we suggest a new format - * upstream we will create a new caps that we need to unref. */ - alloc_caps = caps; - alloc_unref = FALSE; - /* get struct to see what is requested */ structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "width", &width) || !gst_structure_get_int (structure, "height", &height)) { GST_WARNING_OBJECT (vdp_sink, "invalid caps for buffer allocation %" GST_PTR_FORMAT, caps); ret = GST_FLOW_NOT_NEGOTIATED; goto beach; } + alloc_caps = gst_caps_ref (caps); + /* We take the flow_lock because the window might go away */ g_mutex_lock (vdp_sink->flow_lock); if (!vdp_sink->window) { g_mutex_unlock (vdp_sink->flow_lock); goto alloc; } @@ -1004,32 +986,36 @@ gst_vdp_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, /* see if peer accepts our new suggestion, if there is no peer, this * function returns true. */ if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (vdp_sink), desired_caps)) { /* we will not alloc a buffer of the new suggested caps. Make sure * we also unref this new caps after we set it on the buffer. */ - alloc_caps = desired_caps; - alloc_unref = TRUE; - width = w_width; - height = w_height; GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT, desired_caps); + gst_caps_unref (alloc_caps); + alloc_caps = desired_caps; } else { GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT, desired_caps); /* we alloc a buffer with the original incomming caps already in the * width and height variables */ + gst_caps_unref (desired_caps); } } alloc: - ret = gst_vdp_sink_get_output_buffer (vdp_sink, alloc_caps, buf); - - /* could be our new reffed suggestion or the original unreffed caps */ - if (alloc_unref) - gst_caps_unref (alloc_caps); + gst_vdp_buffer_pool_set_caps (vdp_sink->bpool, alloc_caps); + gst_caps_unref (alloc_caps); + + err = NULL; + *buf = + GST_BUFFER_CAST (gst_vdp_buffer_pool_get_buffer (vdp_sink->bpool, &err)); + if (!*buf) { + gst_vdp_sink_post_error (vdp_sink, err); + return GST_FLOW_ERROR; + } beach: return ret; } /* Interfaces stuff */ @@ -1118,14 +1104,13 @@ gst_vdp_sink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id) if (vdp_sink->window && (xwindow_id == vdp_sink->window->win)) { g_mutex_unlock (vdp_sink->flow_lock); return; } /* If the element has not initialized the X11 context try to do so */ - if (!vdp_sink->device - && !(vdp_sink->device = gst_vdp_sink_setup_device (vdp_sink))) { + if (!vdp_sink->device && !gst_vdp_sink_open_device (vdp_sink)) { g_mutex_unlock (vdp_sink->flow_lock); /* we have thrown a GST_ELEMENT_ERROR now */ return; } /* If a window is there already we destroy it */ diff --git a/sys/vdpau/gstvdpsink.h b/sys/vdpau/gstvdpsink.h index 6d1ff07df..c26b64d37 100644 --- a/sys/vdpau/gstvdpsink.h +++ b/sys/vdpau/gstvdpsink.h @@ -96,12 +96,13 @@ struct _VdpSink { /* Our element stuff */ GstVideoSink videosink; char *display_name; GstVdpDevice *device; + GstVdpBufferPool *bpool; GstCaps *caps; GstVdpWindow *window; GstBuffer *cur_image; GThread *event_thread; |