diff --git a/ChangeLog b/ChangeLog index 295162b98a..b30c972531 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2004-01-09 Julien MOUTTE <julien@moutte.net> + + * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_chain): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * gst-libs/gst/xoverlay/xoverlay.c: + (gst_x_overlay_got_desired_size): Updating doc for the xid being 0. + * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * sys/ximage/ximagesink.c: (gst_ximagesink_chain), + (gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): Implementing + the bufferalloc_function to replace bufferpools, fixing the XOverlay + interface implementation to handle xid being 0 and fix some bugs + triggered by Benjamin's testcase. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain), + (gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): Implementing + the bufferalloc_function to replace bufferpools, fixing the XOverlay + interface implementation to handle xid being 0 and fix some bugs + triggered by Benjamin's testcase. + 2004-01-09 David Schleef <ds@schleef.org> * ext/librfb/gstrfbsrc.c: Hacking. Added actual decoding and @@ -39,7 +62,7 @@ * gst/videodrop/gstvideodrop.c: (gst_videodrop_getcaps), (gst_videodrop_link), (gst_videodrop_init): Fix negotiation. -2004-01-08 Julien MOUTTE,,, <julien@moutte.net> +2004-01-08 Julien MOUTTE <julien@moutte.net> * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): A configure event is not emiting the desired size signal. That fixes @@ -87,7 +110,7 @@ * gst/modplug/gstmodplug.cc: fix element description -2004-01-07 Julien MOUTTE,,, <julien@moutte.net> +2004-01-07 Julien MOUTTE <julien@moutte.net> * examples/gstplay/player.c: (got_time_tick), (got_stream_length), (got_video_size): Adding some new lines in g_print calls. diff --git a/gst-libs/gst/interfaces/xoverlay.c b/gst-libs/gst/interfaces/xoverlay.c index c0bbcec0c5..2efe296660 100644 --- a/gst-libs/gst/interfaces/xoverlay.c +++ b/gst-libs/gst/interfaces/xoverlay.c @@ -103,7 +103,8 @@ gst_x_overlay_base_init (gpointer g_class) * * This will call the video overlay's set_xwindow_id method. You should * use this method to tell to a XOverlay to display video output to a - * specific XWindow. + * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to + * stop using that window and create an internal one. */ void gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id) @@ -182,4 +183,3 @@ gst_x_overlay_got_desired_size (GstXOverlay *overlay, guint width, guint height) g_signal_emit (G_OBJECT (overlay), gst_x_overlay_signals[DESIRED_SIZE], 0, width, height); } - diff --git a/gst-libs/gst/xoverlay/xoverlay.c b/gst-libs/gst/xoverlay/xoverlay.c index c0bbcec0c5..2efe296660 100644 --- a/gst-libs/gst/xoverlay/xoverlay.c +++ b/gst-libs/gst/xoverlay/xoverlay.c @@ -103,7 +103,8 @@ gst_x_overlay_base_init (gpointer g_class) * * This will call the video overlay's set_xwindow_id method. You should * use this method to tell to a XOverlay to display video output to a - * specific XWindow. + * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to + * stop using that window and create an internal one. */ void gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id) @@ -182,4 +183,3 @@ gst_x_overlay_got_desired_size (GstXOverlay *overlay, guint width, guint height) g_signal_emit (G_OBJECT (overlay), gst_x_overlay_signals[DESIRED_SIZE], 0, width, height); } - diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c index fece73c558..69409a499b 100644 --- a/gst/videoscale/gstvideoscale.c +++ b/gst/videoscale/gstvideoscale.c @@ -370,9 +370,11 @@ gst_videoscale_chain (GstPad *pad, GstData *_data) g_return_if_fail (size == videoscale->from_buf_size); outbuf = gst_buffer_new(); - /* FIXME: handle bufferpools */ - GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size; - GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size); + outbuf = gst_pad_alloc_buffer (gst_pad_get_peer (pad), + GST_BUFFER_OFFSET_NONE, videoscale->to_buf_size); + + /*GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size;*/ + /*GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size);*/ GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf); g_return_if_fail(videoscale->format); diff --git a/gst/videotestsrc/gstvideotestsrc.c b/gst/videotestsrc/gstvideotestsrc.c index 6cb8939d46..e78208602f 100644 --- a/gst/videotestsrc/gstvideotestsrc.c +++ b/gst/videotestsrc/gstvideotestsrc.c @@ -418,7 +418,7 @@ gst_videotestsrc_get (GstPad * pad) GST_DEBUG ("size=%ld %dx%d", newsize, videotestsrc->width, videotestsrc->height); - buf = gst_buffer_new_and_alloc (newsize); + buf = gst_pad_alloc_buffer (pad, GST_BUFFER_OFFSET_NONE, newsize); g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL); videotestsrc->make_image (videotestsrc, (void *) GST_BUFFER_DATA (buf), diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c index 3a7ff12451..fda9c89a80 100644 --- a/sys/ximage/ximagesink.c +++ b/sys/ximage/ximagesink.c @@ -736,14 +736,14 @@ gst_ximagesink_chain (GstPad *pad, GstData *data) gst_clock_id_free (id); } -#if 0 - /* If we have a pool and the image is from this pool, simply put it. */ - if ( (ximagesink->bufferpool) && - (GST_BUFFER_BUFFERPOOL (buf) == ximagesink->bufferpool) ) - gst_ximagesink_ximage_put (ximagesink, GST_BUFFER_POOL_PRIVATE (buf)); + /* If this buffer has been allocated using our buffer management we simply + put the ximage which is in the PRIVATE pointer */ + if (GST_BUFFER_BUFFERPOOL (buf) == ximagesink) + { + gst_ximagesink_ximage_put (ximagesink, GST_BUFFER_POOL_PRIVATE (buf)); + } else /* Else we have to copy the data into our private image, */ { /* if we have one... */ -#endif if (ximagesink->ximage) { memcpy (ximagesink->ximage->ximage->data, @@ -757,9 +757,8 @@ gst_ximagesink_chain (GstPad *pad, GstData *data) gst_element_error (GST_ELEMENT (ximagesink), "no image to draw"); return; } -#if 0 } -#endif + /* set correct time for next buffer */ if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && ximagesink->framerate > 0) { ximagesink->time += GST_SECOND / ximagesink->framerate; @@ -770,18 +769,45 @@ gst_ximagesink_chain (GstPad *pad, GstData *data) gst_ximagesink_handle_xevents (ximagesink, pad); } -#if 0 -static GstBuffer* -gst_ximagesink_buffer_new (GstBufferPool *pool, - gint64 location, guint size, gpointer user_data) +/* Buffer management */ + +static void +gst_ximagesink_buffer_free (GstData *data) +{ + GstXImageSink *ximagesink; + GstXImage *ximage; + GstBuffer *buffer; + + ximagesink = GST_BUFFER_BUFFERPOOL (data); + ximage = GST_BUFFER_POOL_PRIVATE (data); + buffer = GST_BUFFER (data); + + /* If our geometry changed we can't reuse that image. */ + if ( (ximage->width != GST_VIDEOSINK_WIDTH (ximagesink)) || + (ximage->height != GST_VIDEOSINK_HEIGHT (ximagesink)) ) + gst_ximagesink_ximage_destroy (ximagesink, ximage); + else /* In that case we can reuse the image and add it to our image pool. */ + { + g_mutex_lock (ximagesink->pool_lock); + ximagesink->image_pool = g_slist_prepend (ximagesink->image_pool, ximage); + g_mutex_unlock (ximagesink->pool_lock); + } + + GST_BUFFER_DATA (buffer) = NULL; + + gst_buffer_default_free (buffer); +} + +static GstBuffer * +gst_ximagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size) { GstXImageSink *ximagesink; GstBuffer *buffer; GstXImage *ximage = NULL; gboolean not_found = TRUE; - ximagesink = GST_XIMAGESINK (user_data); - + ximagesink = GST_XIMAGESINK (gst_pad_get_parent (pad)); + g_mutex_lock (ximagesink->pool_lock); /* Walking through the pool cleaning unsuable images and searching for a @@ -803,22 +829,31 @@ gst_ximagesink_buffer_new (GstBufferPool *pool, ximage = NULL; } else /* We found a suitable image */ - break; + { + break; + } } } g_mutex_unlock (ximagesink->pool_lock); if (!ximage) /* We found no suitable image in the pool. Creating... */ - ximage = gst_ximagesink_ximage_new (ximagesink, - GST_VIDEOSINK_WIDTH (ximagesink), - GST_VIDEOSINK_HEIGHT (ximagesink)); + { + ximage = gst_ximagesink_ximage_new (ximagesink, + GST_VIDEOSINK_WIDTH (ximagesink), + GST_VIDEOSINK_HEIGHT (ximagesink)); + } if (ximage) { buffer = gst_buffer_new (); + + /* Storing some pointers in the buffer (bit hackish) */ + GST_BUFFER_BUFFERPOOL (buffer) = ximagesink; GST_BUFFER_POOL_PRIVATE (buffer) = ximage; + GST_BUFFER_DATA (buffer) = ximage->ximage->data; + GST_DATA_FREE_FUNC (buffer) = gst_ximagesink_buffer_free; GST_BUFFER_SIZE (buffer) = ximage->size; return buffer; } @@ -826,34 +861,6 @@ gst_ximagesink_buffer_new (GstBufferPool *pool, return NULL; } -static void -gst_ximagesink_buffer_free (GstBufferPool *pool, - GstBuffer *buffer, gpointer user_data) -{ - GstXImageSink *ximagesink; - GstXImage *ximage; - - ximagesink = GST_XIMAGESINK (user_data); - - ximage = GST_BUFFER_POOL_PRIVATE (buffer); - - /* If our geometry changed we can't reuse that image. */ - if ( (ximage->width != GST_VIDEOSINK_WIDTH (ximagesink)) || - (ximage->height != GST_VIDEOSINK_HEIGHT (ximagesink)) ) - gst_ximagesink_ximage_destroy (ximagesink, ximage); - else /* In that case we can reuse the image and add it to our image pool. */ - { - g_mutex_lock (ximagesink->pool_lock); - ximagesink->image_pool = g_slist_prepend (ximagesink->image_pool, ximage); - g_mutex_unlock (ximagesink->pool_lock); - } - - GST_BUFFER_DATA (buffer) = NULL; - - gst_buffer_default_free (buffer); -} -#endif - static void gst_ximagesink_imagepool_clear (GstXImageSink *ximagesink) { @@ -936,36 +943,112 @@ gst_ximagesink_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id) g_return_if_fail (ximagesink != NULL); g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + /* If we already use that window return */ + if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win)) + return; + + /* If the element has not initialized the X11 context try to do so */ if (!ximagesink->xcontext) ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink); - if ( (ximagesink->xwindow) && (ximagesink->ximage) ) - { /* If we are replacing a window we destroy pictures and window as they - are associated */ - gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage); - gst_ximagesink_imagepool_clear (ximagesink); - gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); + if (!ximagesink->xcontext) + { + g_warning ("ximagesink was unable to obtain the X11 context."); + return; } - xwindow = g_new0 (GstXWindow, 1); + /* Clear image pool as the images are unusable anyway */ + gst_ximagesink_imagepool_clear (ximagesink); - xwindow->win = xwindow_id; + /* Clear the ximage */ + if (ximagesink->ximage) + { + gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage); + ximagesink->ximage = NULL; + } - /* We get window geometry, set the event we want to receive, and create a GC */ - g_mutex_lock (ximagesink->x_lock); - XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr); - xwindow->width = attr.width; - xwindow->height = attr.height; - xwindow->internal = FALSE; - XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask | - StructureNotifyMask | PointerMotionMask | KeyPressMask | - KeyReleaseMask); - - xwindow->gc = XCreateGC (ximagesink->xcontext->disp, - xwindow->win, 0, NULL); - g_mutex_unlock (ximagesink->x_lock); + /* If a window is there already we destroy it */ + if (ximagesink->xwindow) + { + gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); + ximagesink->xwindow = NULL; + } - ximagesink->xwindow = xwindow; + /* If the xid is 0 we go back to an internal window */ + if (xwindow_id == 0) + { + /* If no width/height caps nego did not happen window will be created + during caps nego then */ + if (GST_VIDEOSINK_WIDTH (ximagesink) && + GST_VIDEOSINK_HEIGHT (ximagesink)) + { + xwindow = gst_ximagesink_xwindow_new (ximagesink, + GST_VIDEOSINK_WIDTH (ximagesink), + GST_VIDEOSINK_HEIGHT (ximagesink)); + } + } + else + { + xwindow = g_new0 (GstXWindow, 1); + + xwindow->win = xwindow_id; + + /* We get window geometry, set the event we want to receive, + and create a GC */ + g_mutex_lock (ximagesink->x_lock); + XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr); + xwindow->width = attr.width; + xwindow->height = attr.height; + xwindow->internal = FALSE; + XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask); + + xwindow->gc = XCreateGC (ximagesink->xcontext->disp, + xwindow->win, 0, NULL); + g_mutex_unlock (ximagesink->x_lock); + + /* If that new window geometry differs from our one we try to + renegotiate caps */ + if (xwindow->width != GST_VIDEOSINK_WIDTH (ximagesink) || + xwindow->height != GST_VIDEOSINK_HEIGHT (ximagesink)) + { + GstPadLinkReturn r; + r = gst_pad_try_set_caps (GST_VIDEOSINK_PAD (ximagesink), + gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, ximagesink->xcontext->bpp, + "depth", G_TYPE_INT, ximagesink->xcontext->depth, + "endianness", G_TYPE_INT, ximagesink->xcontext->endianness, + "red_mask", G_TYPE_INT, ximagesink->xcontext->visual->red_mask, + "green_mask", G_TYPE_INT, ximagesink->xcontext->visual->green_mask, + "blue_mask", G_TYPE_INT, ximagesink->xcontext->visual->blue_mask, + "width", G_TYPE_INT, xwindow->width & ~3, + "height", G_TYPE_INT, xwindow->height & ~3, + "framerate", G_TYPE_DOUBLE, ximagesink->framerate, + NULL)); + + /* If caps nego succeded updating our size */ + if ( (r == GST_PAD_LINK_OK) || (r == GST_PAD_LINK_DONE) ) + { + GST_VIDEOSINK_WIDTH (ximagesink) = xwindow->width & ~3; + GST_VIDEOSINK_HEIGHT (ximagesink) = xwindow->height & ~3; + } + } + } + + /* Recreating our ximage */ + if (!ximagesink->ximage && + GST_VIDEOSINK_WIDTH (ximagesink) && + GST_VIDEOSINK_HEIGHT (ximagesink)) + { + ximagesink->ximage = gst_ximagesink_ximage_new ( + ximagesink, + GST_VIDEOSINK_WIDTH (ximagesink), + GST_VIDEOSINK_HEIGHT (ximagesink)); + } + + if (xwindow) + ximagesink->xwindow = xwindow; } static void @@ -1040,7 +1123,9 @@ gst_ximagesink_init (GstXImageSink *ximagesink) gst_ximagesink_getcaps); gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (ximagesink), gst_ximagesink_fixate); - + gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (ximagesink), + gst_ximagesink_buffer_alloc); + ximagesink->xcontext = NULL; ximagesink->xwindow = NULL; ximagesink->ximage = NULL; diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index 4fea2627bc..13f5ae61fb 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -896,14 +896,12 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data) gst_clock_id_free (id); } -#if 0 - /* If we have a pool and the image is from this pool, simply put it. */ - if ( (xvimagesink->bufferpool) && - (GST_BUFFER_BUFFERPOOL (buf) == xvimagesink->bufferpool) ) + /* If this buffer has been allocated using our buffer management we simply + put the ximage which is in the PRIVATE pointer */ + if (GST_BUFFER_BUFFERPOOL (buf) == xvimagesink) gst_xvimagesink_xvimage_put (xvimagesink, GST_BUFFER_POOL_PRIVATE (buf)); else /* Else we have to copy the data into our private image, */ { /* if we have one... */ -#endif if (xvimagesink->xvimage) { memcpy (xvimagesink->xvimage->xvimage->data, @@ -917,9 +915,8 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data) gst_element_error (GST_ELEMENT (xvimagesink), "no image to draw"); return; } -#if 0 } -#endif + /* set correct time for next buffer */ if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && xvimagesink->framerate > 0) { xvimagesink->time += GST_SECOND / xvimagesink->framerate; @@ -930,72 +927,18 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data) gst_xvimagesink_handle_xevents (xvimagesink, pad); } -#if 0 -static GstBuffer* -gst_xvimagesink_buffer_new (GstBufferPool *pool, - gint64 location, guint size, gpointer user_data) -{ - GstXvImageSink *xvimagesink; - GstBuffer *buffer; - GstXvImage *xvimage = NULL; - gboolean not_found = TRUE; - - xvimagesink = GST_XVIMAGESINK (user_data); - - g_mutex_lock (xvimagesink->pool_lock); - - /* Walking through the pool cleaning unsuable images and searching for a - suitable one */ - while (not_found && xvimagesink->image_pool) - { - xvimage = xvimagesink->image_pool->data; - - if (xvimage) - { - /* Removing from the pool */ - xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool, - xvimagesink->image_pool); - - if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) || - (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) ) - { /* This image is unusable. Destroying... */ - gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage); - xvimage = NULL; - } - else /* We found a suitable image */ - break; - } - } - - g_mutex_unlock (xvimagesink->pool_lock); - - if (!xvimage) /* We found no suitable image in the pool. Creating... */ - xvimage = gst_xvimagesink_xvimage_new (xvimagesink, - GST_VIDEOSINK_WIDTH (xvimagesink), - GST_VIDEOSINK_HEIGHT (xvimagesink)); - - if (xvimage) - { - buffer = gst_buffer_new (); - GST_BUFFER_POOL_PRIVATE (buffer) = xvimage; - GST_BUFFER_DATA (buffer) = xvimage->xvimage->data; - GST_BUFFER_SIZE (buffer) = xvimage->size; - return buffer; - } - else - return NULL; -} +/* Buffer management */ static void -gst_xvimagesink_buffer_free (GstBufferPool *pool, - GstBuffer *buffer, gpointer user_data) +gst_xvimagesink_buffer_free (GstData *data) { GstXvImageSink *xvimagesink; GstXvImage *xvimage; + GstBuffer *buffer; - xvimagesink = GST_XVIMAGESINK (user_data); - - xvimage = GST_BUFFER_POOL_PRIVATE (buffer); + xvimagesink = GST_BUFFER_BUFFERPOOL (data); + xvimage = GST_BUFFER_POOL_PRIVATE (data); + buffer = GST_BUFFER (data); /* If our geometry changed we can't reuse that image. */ if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) || @@ -1013,7 +956,69 @@ gst_xvimagesink_buffer_free (GstBufferPool *pool, gst_buffer_default_free (buffer); } -#endif + +static GstBuffer * +gst_xvimagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size) +{ + GstXvImageSink *xvimagesink; + GstBuffer *buffer; + GstXvImage *xvimage = NULL; + gboolean not_found = TRUE; + + xvimagesink = GST_XVIMAGESINK (gst_pad_get_parent (pad)); + + g_mutex_lock (xvimagesink->pool_lock); + + /* Walking through the pool cleaning unsuable images and searching for a + suitable one */ + while (not_found && xvimagesink->image_pool) + { + xvimage = xvimagesink->image_pool->data; + + if (xvimage) + { + /* Removing from the pool */ + xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool, + xvimagesink->image_pool); + + if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) || + (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) ) + { /* This image is unusable. Destroying... */ + gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage); + xvimage = NULL; + } + else /* We found a suitable image */ + { + break; + } + } + } + + g_mutex_unlock (xvimagesink->pool_lock); + + if (!xvimage) /* We found no suitable image in the pool. Creating... */ + { + xvimage = gst_xvimagesink_xvimage_new (xvimagesink, + GST_VIDEOSINK_WIDTH (xvimagesink), + GST_VIDEOSINK_HEIGHT (xvimagesink)); + } + + if (xvimage) + { + buffer = gst_buffer_new (); + + /* Storing some pointers in the buffer (bit hackish) */ + GST_BUFFER_BUFFERPOOL (buffer) = xvimagesink; + GST_BUFFER_POOL_PRIVATE (buffer) = xvimage; + + GST_BUFFER_DATA (buffer) = xvimage->xvimage->data; + GST_DATA_FREE_FUNC (buffer) = gst_xvimagesink_buffer_free; + GST_BUFFER_SIZE (buffer) = xvimage->size; + return buffer; + } + else + return NULL; +} static void gst_xvimagesink_imagepool_clear (GstXvImageSink *xvimagesink) @@ -1091,36 +1096,85 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id) g_return_if_fail (xvimagesink != NULL); g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + /* If we already use that window return */ + if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) + return; + + /* If the element has not initialized the X11 context try to do so */ if (!xvimagesink->xcontext) xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink); - if ( (xvimagesink->xwindow) && (xvimagesink->xvimage) ) - { /* If we are replacing a window we destroy pictures and window as they - are associated */ - gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage); - gst_xvimagesink_imagepool_clear (xvimagesink); - gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + if (!xvimagesink->xcontext) + { + g_warning ("xvimagesink was unable to obtain the X11 context."); + return; } - xwindow = g_new0 (GstXWindow, 1); + /* Clear image pool as the images are unusable anyway */ + gst_xvimagesink_imagepool_clear (xvimagesink); - xwindow->win = xwindow_id; + /* Clear the xvimage */ + if (xvimagesink->xvimage) + { + gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage); + xvimagesink->xvimage = NULL; + } - /* We get window geometry, set the event we want to receive, and create a GC */ - g_mutex_lock (xvimagesink->x_lock); - XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr); - xwindow->width = attr.width; - xwindow->height = attr.height; - xwindow->internal = FALSE; - XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask | - StructureNotifyMask | PointerMotionMask | KeyPressMask | - KeyReleaseMask); - - xwindow->gc = XCreateGC (xvimagesink->xcontext->disp, - xwindow->win, 0, NULL); - g_mutex_unlock (xvimagesink->x_lock); + /* If a window is there already we destroy it */ + if (xvimagesink->xwindow) + { + gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + xvimagesink->xwindow = NULL; + } - xvimagesink->xwindow = xwindow; + /* If the xid is 0 we go back to an internal window */ + if (xwindow_id == 0) + { + /* If no width/height caps nego did not happen window will be created + during caps nego then */ + if (GST_VIDEOSINK_WIDTH (xvimagesink) && + GST_VIDEOSINK_HEIGHT (xvimagesink)) + { + xwindow = gst_xvimagesink_xwindow_new (xvimagesink, + GST_VIDEOSINK_WIDTH (xvimagesink), + GST_VIDEOSINK_HEIGHT (xvimagesink)); + } + } + else + { + xwindow = g_new0 (GstXWindow, 1); + + xwindow->win = xwindow_id; + + /* We get window geometry, set the event we want to receive, + and create a GC */ + g_mutex_lock (xvimagesink->x_lock); + XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr); + xwindow->width = attr.width; + xwindow->height = attr.height; + xwindow->internal = FALSE; + XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask); + + xwindow->gc = XCreateGC (xvimagesink->xcontext->disp, + xwindow->win, 0, NULL); + g_mutex_unlock (xvimagesink->x_lock); + } + + /* Recreating our xvimage */ + if (!xvimagesink->xvimage && + GST_VIDEOSINK_WIDTH (xvimagesink) && + GST_VIDEOSINK_HEIGHT (xvimagesink)) + { + xvimagesink->xvimage = gst_xvimagesink_xvimage_new ( + xvimagesink, + GST_VIDEOSINK_WIDTH (xvimagesink), + GST_VIDEOSINK_HEIGHT (xvimagesink)); + } + + if (xwindow) + xvimagesink->xwindow = xwindow; } static void @@ -1195,7 +1249,9 @@ gst_xvimagesink_init (GstXvImageSink *xvimagesink) gst_xvimagesink_getcaps); gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (xvimagesink), gst_xvimagesink_fixate); - + gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (xvimagesink), + gst_xvimagesink_buffer_alloc); + xvimagesink->xcontext = NULL; xvimagesink->xwindow = NULL; xvimagesink->xvimage = NULL;