vdpausink: rework presentation blocking a bit

instead of blocking until the previous surface has been displayed, we new only
add surfaces to the queue if it's idle.
This commit is contained in:
Carl-Anton Ingmarsson 2009-10-27 22:04:10 +01:00
parent ea364d7a5a
commit 9c1b87aaa6
3 changed files with 26 additions and 25 deletions

View file

@ -123,7 +123,9 @@ gst_vdp_device_constructed (GObject * object)
{VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,
&device->vdp_presentation_queue_block_until_surface_idle},
{VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR,
&device->vdp_presentation_queue_set_background_color}
&device->vdp_presentation_queue_set_background_color},
{VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,
&device->vdp_presentation_queue_query_surface_status}
};
device->display = XOpenDisplay (device->display_name);

View file

@ -88,6 +88,7 @@ struct _GstVdpDevice
VdpPresentationQueueDisplay *vdp_presentation_queue_display;
VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle;
VdpPresentationQueueSetBackgroundColor *vdp_presentation_queue_set_background_color;
VdpPresentationQueueQuerySurfaceStatus *vdp_presentation_queue_query_surface_status;
};
GType gst_vdp_device_get_type (void) G_GNUC_CONST;

View file

@ -780,7 +780,6 @@ static GstFlowReturn
gst_vdp_sink_show_frame (GstBaseSink * bsink, GstBuffer * outbuf)
{
VdpSink *vdp_sink = GST_VDP_SINK (bsink);
GstVdpOutputBuffer *prev_image = NULL;
VdpStatus status;
GstVdpDevice *device;
@ -795,13 +794,24 @@ gst_vdp_sink_show_frame (GstBaseSink * bsink, GstBuffer * outbuf)
return GST_FLOW_ERROR;
}
/* Store a reference to the last image we put, lose the previous one */
if (outbuf && vdp_sink->cur_image != outbuf) {
if (vdp_sink->cur_image) {
prev_image = GST_VDP_OUTPUT_BUFFER (vdp_sink->cur_image);
device = vdp_sink->device;
if (vdp_sink->cur_image) {
VdpOutputSurface surface =
GST_VDP_OUTPUT_BUFFER (vdp_sink->cur_image)->surface;
VdpPresentationQueueStatus queue_status;
VdpTime pres_time;
g_mutex_lock (vdp_sink->x_lock);
status =
device->vdp_presentation_queue_query_surface_status (vdp_sink->window->
queue, surface, &queue_status, &pres_time);
g_mutex_unlock (vdp_sink->x_lock);
if (queue_status == VDP_PRESENTATION_QUEUE_STATUS_QUEUED) {
g_mutex_unlock (vdp_sink->flow_lock);
return GST_FLOW_OK;
}
GST_LOG_OBJECT (vdp_sink, "reffing %p as our current image", outbuf);
vdp_sink->cur_image = gst_buffer_ref (outbuf);
}
/* Expose sends a NULL image, we take the latest frame */
@ -818,7 +828,6 @@ gst_vdp_sink_show_frame (GstBaseSink * bsink, GstBuffer * outbuf)
g_mutex_lock (vdp_sink->x_lock);
device = vdp_sink->device;
status = device->vdp_presentation_queue_display (vdp_sink->window->queue,
GST_VDP_OUTPUT_BUFFER (outbuf)->surface, 0, 0, 0);
if (status != VDP_STATUS_OK) {
@ -832,24 +841,13 @@ gst_vdp_sink_show_frame (GstBaseSink * bsink, GstBuffer * outbuf)
return GST_FLOW_ERROR;
}
if (prev_image) {
VdpTime time;
/* block till the previous surface has been displayed */
status =
device->vdp_presentation_queue_block_until_surface_idle (vdp_sink->
window->queue, prev_image->surface, &time);
if (status != VDP_STATUS_OK) {
GST_ELEMENT_ERROR (vdp_sink, RESOURCE, READ,
("Could not display frame"),
("Error returned from vdpau was: %s",
device->vdp_get_error_string (status)));
if (!vdp_sink->cur_image)
vdp_sink->cur_image = gst_buffer_ref (outbuf);
g_mutex_unlock (vdp_sink->x_lock);
g_mutex_unlock (vdp_sink->flow_lock);
return GST_FLOW_ERROR;
}
gst_buffer_unref (GST_BUFFER (prev_image));
else if (vdp_sink->cur_image != outbuf) {
gst_buffer_unref (vdp_sink->cur_image);
vdp_sink->cur_image = gst_buffer_ref (outbuf);
}
XSync (vdp_sink->device->display, FALSE);