From db4de40ebf4a40ea2c2b22182a060ff13eab70b4 Mon Sep 17 00:00:00 2001 From: Julien Moutte Date: Sat, 21 Jan 2006 22:40:03 +0000 Subject: [PATCH] sys/xvimage/xvimagesink.c: I think one day i'll completely undestand how caps negotiation is supposed to work. This r... Original commit message from CVS: 2006-01-21 Julien MOUTTE * sys/xvimage/xvimagesink.c: (gst_xvimagesink_buffer_alloc): I think one day i'll completely undestand how caps negotiation is supposed to work. This refactoring handles buffer_alloc called with caps we can't handle. We definitely don't want a set_caps with those caps, so we define and allocate a buffer we would like to receive. --- ChangeLog | 9 ++++ sys/xvimage/xvimagesink.c | 93 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb280cc797..f228265fbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-01-21 Julien MOUTTE + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_buffer_alloc): + I think one day i'll completely undestand how caps negotiation + is supposed to work. This refactoring handles buffer_alloc + called with caps we can't handle. We definitely don't want a + set_caps with those caps, so we define and allocate a buffer + we would like to receive. + 2006-01-19 Tim-Philipp Müller * gst/playback/gstplaybasebin.c: (setup_source): diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index 8b2e299f6c..85d52ad736 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -1804,11 +1804,86 @@ static GstFlowReturn gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { + GstFlowReturn ret = GST_FLOW_OK; GstXvImageSink *xvimagesink; GstXvImageBuffer *xvimage = NULL; + GstCaps *intersection = NULL; + GstStructure *structure = NULL; + gint width, height, image_format; xvimagesink = GST_XVIMAGESINK (bsink); + GST_DEBUG_OBJECT (xvimagesink, "buffer alloc requested with caps %" + GST_PTR_FORMAT "intersecting with our caps %" GST_PTR_FORMAT, caps, + xvimagesink->xcontext->caps); + + /* Check the caps against our xcontext */ + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps); + GST_DEBUG_OBJECT (xvimagesink, "intersection in buffer alloc returned %" + GST_PTR_FORMAT, intersection); + + if (gst_caps_is_empty (intersection)) { + /* So we don't support this kind of buffer, let's define one we'd like */ + GstCaps *new_caps = gst_caps_copy (caps); + + structure = gst_caps_get_structure (new_caps, 0); + + /* Try with YUV first */ + gst_structure_set_name (structure, "video/x-raw-yuv"); + gst_structure_remove_field (structure, "format"); + gst_structure_remove_field (structure, "endianness"); + gst_structure_remove_field (structure, "depth"); + gst_structure_remove_field (structure, "bpp"); + gst_structure_remove_field (structure, "red_mask"); + gst_structure_remove_field (structure, "green_mask"); + gst_structure_remove_field (structure, "blue_mask"); + gst_structure_remove_field (structure, "alpha_mask"); + + /* Reuse intersection with Xcontext */ + gst_caps_unref (intersection); + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); + + if (gst_caps_is_empty (intersection)) { + /* Now try with RGB */ + gst_structure_set_name (structure, "video/x-raw-rgb"); + /* And interset again */ + gst_caps_unref (intersection); + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); + + if (gst_caps_is_empty (intersection)) { + GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with " + "caps %" GST_PTR_FORMAT "but our xcontext caps %" GST_PTR_FORMAT + "are completely incompatible with those caps", new_caps, + xvimagesink->xcontext->caps); + gst_caps_unref (new_caps); + ret = GST_FLOW_UNEXPECTED; + goto beach; + } + } + + /* Clean this copy */ + gst_caps_unref (new_caps); + /* We want fixed caps */ + gst_caps_truncate (intersection); + + GST_DEBUG_OBJECT (xvimagesink, "allocating a buffer with caps %" + GST_PTR_FORMAT, intersection); + } + + /* Get image format from caps */ + image_format = gst_xvimagesink_get_format_from_caps (xvimagesink, + intersection); + + /* Get geometry from caps */ + structure = gst_caps_get_structure (intersection, 0); + if (!gst_structure_get_int (structure, "width", &width) || + !gst_structure_get_int (structure, "height", &height) || !image_format) { + GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %" + GST_PTR_FORMAT, intersection); + ret = GST_FLOW_UNEXPECTED; + goto beach; + } + g_mutex_lock (xvimagesink->pool_lock); /* Walking through the pool cleaning unusable images and searching for a @@ -1822,9 +1897,8 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, xvimagesink->image_pool); /* We check for geometry or image format changes */ - if ((xvimage->width != xvimagesink->video_width) || - (xvimage->height != xvimagesink->video_height) || - (xvimage->im_format != xvimagesink->xcontext->im_format)) { + if ((xvimage->width != width) || + (xvimage->height != height) || (xvimage->im_format != image_format)) { /* This image is unusable. Destroying... */ gst_xvimage_buffer_free (xvimage); xvimage = NULL; @@ -1841,14 +1915,21 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, if (!xvimage) { /* We found no suitable image in the pool. Creating... */ GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage"); - xvimage = gst_xvimagesink_xvimage_new (xvimagesink, caps); + xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection); } + if (xvimage) { - gst_buffer_set_caps (GST_BUFFER (xvimage), caps); + gst_buffer_set_caps (GST_BUFFER (xvimage), intersection); } + *buf = GST_BUFFER (xvimage); - return GST_FLOW_OK; +beach: + if (intersection) { + gst_caps_unref (intersection); + } + + return ret; } /* Interfaces stuff */