X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=sys%2Fxvimage%2Fxvimagesink.c;h=1f8729ee25a7f1ec8e645684162f1b7cd19b997b;hb=dab39bf42bdabdf239747e3227a99caf3274be23;hp=a54e18f6e5f17485d99ee9f7d1f8f7a31fa04471;hpb=b950b930aeae4cc2fcb266eed1c431236701b9c2;p=platform%2Fupstream%2Fgst-plugins-base.git diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c index a54e18f..1f8729e 100644 --- a/sys/xvimage/xvimagesink.c +++ b/sys/xvimage/xvimagesink.c @@ -14,8 +14,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** @@ -25,9 +25,10 @@ * using the XVideo extension. Rendering to a remote display is theoretically * possible but i doubt that the XVideo extension is actually available when * connecting to a remote display. This element can receive a Window ID from the - * application through the XOverlay interface and will then render video frames - * in this drawable. If no Window ID was provided by the application, the - * element will create its own internal window and render into it. + * application through the #GstVideoOverlay interface and will then render + * video frames in this drawable. If no Window ID was provided by the + * application, the element will create its own internal window and render + * into it. * * * Scaling @@ -72,17 +73,20 @@ * * Examples * |[ - * gst-launch -v videotestsrc ! xvimagesink + * gst-launch-1.0 -v videotestsrc ! xvimagesink * ]| A pipeline to test hardware scaling. * When the test video signal appears you can resize the window and see that - * video frames are scaled through hardware (no extra CPU cost). + * video frames are scaled through hardware (no extra CPU cost). By default + * the image will never be distorted when scaled, instead black borders will + * be added if needed. * |[ - * gst-launch -v videotestsrc ! xvimagesink force-aspect-ratio=true - * ]| Same pipeline with #GstXvImageSink:force-aspect-ratio property set to true - * You can observe the borders drawn around the scaled image respecting aspect - * ratio. + * gst-launch-1.0 -v videotestsrc ! xvimagesink force-aspect-ratio=false + * ]| Same pipeline with #GstXvImageSink:force-aspect-ratio property set to + * false. You can observe that no borders are drawn around the scaled image + * now and it will be distorted to fill the entire frame instead of respecting + * the aspect ratio. * |[ - * gst-launch -v videotestsrc ! navigationtest ! xvimagesink + * gst-launch-1.0 -v videotestsrc ! navigationtest ! xvimagesink * ]| A pipeline to test navigation events. * While moving the mouse pointer over the test signal you will see a black box * following the mouse pointer. If you press the mouse button somewhere on the @@ -94,15 +98,14 @@ * position. This also handles borders correctly, limiting coordinates to the * image area * |[ - * gst-launch -v videotestsrc ! video/x-raw, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink + * gst-launch-1.0 -v videotestsrc ! video/x-raw, pixel-aspect-ratio=4/3 ! xvimagesink * ]| This is faking a 4/3 pixel aspect ratio caps on video frames produced by * videotestsrc, in most cases the pixel aspect ratio of the display will be * 1/1. This means that XvImageSink will have to do the scaling to convert * incoming frames to a size that will match the display pixel aspect ratio - * (from 320x240 to 320x180 in this case). Note that you might have to escape - * some characters for your shell like '\(fraction\)'. + * (from 320x240 to 320x180 in this case). * |[ - * gst-launch -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100 + * gst-launch-1.0 -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100 * ]| Demonstrates how to use the colorbalance interface. * */ @@ -114,8 +117,7 @@ #endif /* Our interfaces */ -#include -#include +#include #include #include /* Helper functions */ @@ -123,15 +125,17 @@ /* Object header */ #include "xvimagesink.h" +#include "xvimageallocator.h" /* Debugging category */ #include -#include "gst/glib-compat-private.h" +/* for XkbKeycodeToKeysym */ +#include -GST_DEBUG_CATEGORY_EXTERN (gst_debug_xvimagesink); +GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_image_sink); GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); -#define GST_CAT_DEFAULT gst_debug_xvimagesink +#define GST_CAT_DEFAULT gst_debug_xv_image_sink typedef struct { @@ -145,14 +149,15 @@ MotifWmHints, MwmHints; #define MWM_HINTS_DECORATIONS (1L << 1) -static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink); -static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * +static gboolean gst_xv_image_sink_open (GstXvImageSink * xvimagesink); +static void gst_xv_image_sink_close (GstXvImageSink * xvimagesink); +static void gst_xv_image_sink_xwindow_update_geometry (GstXvImageSink * xvimagesink); -static void gst_xvimagesink_expose (GstVideoOverlay * overlay); +static void gst_xv_image_sink_expose (GstVideoOverlay * overlay); /* Default template - initiated with class struct to allow gst-register to work without X running */ -static GstStaticPadTemplate gst_xvimagesink_sink_template_factory = +static GstStaticPadTemplate gst_xv_image_sink_sink_template_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -195,24 +200,19 @@ enum /* Object typing & Creation */ /* */ /* =========================================== */ -static void gst_xvimagesink_navigation_init (GstNavigationInterface * iface); -static void gst_xvimagesink_video_overlay_init (GstVideoOverlayInterface * +static void gst_xv_image_sink_navigation_init (GstNavigationInterface * iface); +static void gst_xv_image_sink_video_overlay_init (GstVideoOverlayInterface * iface); -static void gst_xvimagesink_colorbalance_init (GstColorBalanceInterface * +static void gst_xv_image_sink_colorbalance_init (GstColorBalanceInterface * iface); -static void -gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface * - iface); -#define gst_xvimagesink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xvimagesink, GST_TYPE_VIDEO_SINK, +#define gst_xv_image_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xv_image_sink, GST_TYPE_VIDEO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, - gst_xvimagesink_navigation_init); + gst_xv_image_sink_navigation_init); G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, - gst_xvimagesink_video_overlay_init); + gst_xv_image_sink_video_overlay_init); G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE, - gst_xvimagesink_colorbalance_init); - G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE, - gst_xvimagesink_property_probe_interface_init)); + gst_xv_image_sink_colorbalance_init)); /* ============================================================= */ @@ -222,74 +222,35 @@ G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xvimagesink, GST_TYPE_VIDEO_SINK, /* ============================================================= */ -/* We are called with the x_lock taken */ -static void -gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink, - GstXWindow * xwindow, GstVideoRectangle rect) -{ - gint t1, t2; - - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); - g_return_if_fail (xwindow != NULL); - - XSetForeground (xvimagesink->xcontext->disp, xwindow->gc, - xvimagesink->xcontext->black); - - /* Left border */ - if (rect.x > xvimagesink->render_rect.x) { - XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, - xvimagesink->render_rect.x, xvimagesink->render_rect.y, - rect.x - xvimagesink->render_rect.x, xvimagesink->render_rect.h); - } - - /* Right border */ - t1 = rect.x + rect.w; - t2 = xvimagesink->render_rect.x + xvimagesink->render_rect.w; - if (t1 < t2) { - XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, - t1, xvimagesink->render_rect.y, t2 - t1, xvimagesink->render_rect.h); - } - - /* Top border */ - if (rect.y > xvimagesink->render_rect.y) { - XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, - xvimagesink->render_rect.x, xvimagesink->render_rect.y, - xvimagesink->render_rect.w, rect.y - xvimagesink->render_rect.y); - } - - /* Bottom border */ - t1 = rect.y + rect.h; - t2 = xvimagesink->render_rect.y + xvimagesink->render_rect.h; - if (t1 < t2) { - XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, - xvimagesink->render_rect.x, t1, xvimagesink->render_rect.w, t2 - t1); - } -} - /* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE * if no window was available */ static gboolean -gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage) +gst_xv_image_sink_xvimage_put (GstXvImageSink * xvimagesink, + GstBuffer * xvimage) { - GstXvImageMeta *meta; + GstXvImageMemory *mem; GstVideoCropMeta *crop; GstVideoRectangle result; gboolean draw_border = FALSE; - GstVideoRectangle src, dst; + GstVideoRectangle src = { 0, }; + GstVideoRectangle dst = { 0, }; + GstVideoRectangle mem_crop; + GstXWindow *xwindow; /* We take the flow_lock. If expose is in there we don't want to run concurrently from the data flow thread */ - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); - if (G_UNLIKELY (xvimagesink->xwindow == NULL)) { - g_mutex_unlock (xvimagesink->flow_lock); + if (G_UNLIKELY ((xwindow = xvimagesink->xwindow) == NULL)) { + g_mutex_unlock (&xvimagesink->flow_lock); return FALSE; } /* Draw borders when displaying the first frame. After this draw borders only on expose event or after a size change. */ if (!xvimagesink->cur_image || xvimagesink->redraw_border) { - draw_border = TRUE; + draw_border = xvimagesink->draw_borders; + xvimagesink->redraw_border = FALSE; } /* Store a reference to the last image we put, lose the previous one */ @@ -308,116 +269,54 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage) draw_border = TRUE; xvimage = xvimagesink->cur_image; } else { - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); return TRUE; } } - meta = gst_buffer_get_xvimage_meta (xvimage); + mem = (GstXvImageMemory *) gst_buffer_peek_memory (xvimage, 0); + gst_xvimage_memory_get_crop (mem, &mem_crop); crop = gst_buffer_get_video_crop_meta (xvimage); if (crop) { - src.x = crop->x + meta->x; - src.y = crop->y + meta->y; + src.x = crop->x + mem_crop.x; + src.y = crop->y + mem_crop.y; src.w = crop->width; src.h = crop->height; + GST_LOG_OBJECT (xvimagesink, + "crop %dx%d-%dx%d", crop->x, crop->y, crop->width, crop->height); } else { - src.x = meta->x; - src.y = meta->y; - src.w = meta->width; - src.h = meta->height; + src = mem_crop; } if (xvimagesink->keep_aspect) { - dst.w = xvimagesink->render_rect.w; - dst.h = xvimagesink->render_rect.h; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - result.x += xvimagesink->render_rect.x; - result.y += xvimagesink->render_rect.y; + GstVideoRectangle s; + + /* We take the size of the source material as it was negotiated and + * corrected for DAR. This size can be different from the cropped size in + * which case the image will be scaled to fit the negotiated size. */ + s.w = GST_VIDEO_SINK_WIDTH (xvimagesink); + s.h = GST_VIDEO_SINK_HEIGHT (xvimagesink); + dst.w = xwindow->render_rect.w; + dst.h = xwindow->render_rect.h; + + gst_video_sink_center_rect (s, dst, &result, TRUE); + result.x += xwindow->render_rect.x; + result.y += xwindow->render_rect.y; } else { - memcpy (&result, &xvimagesink->render_rect, sizeof (GstVideoRectangle)); - } - - g_mutex_lock (xvimagesink->x_lock); - - if (draw_border && xvimagesink->draw_borders) { - gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow, - result); - xvimagesink->redraw_border = FALSE; - } -#ifdef HAVE_XSHM - if (xvimagesink->xcontext->use_xshm) { - GST_LOG_OBJECT (xvimagesink, - "XvShmPutImage with image %dx%d and window %dx%d, from xvimage %" - GST_PTR_FORMAT, meta->width, meta->height, - xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage); - - XvShmPutImage (xvimagesink->xcontext->disp, - xvimagesink->xcontext->xv_port_id, - xvimagesink->xwindow->win, - xvimagesink->xwindow->gc, meta->xvimage, - src.x, src.y, src.w, src.h, - result.x, result.y, result.w, result.h, FALSE); - } else -#endif /* HAVE_XSHM */ - { - XvPutImage (xvimagesink->xcontext->disp, - xvimagesink->xcontext->xv_port_id, - xvimagesink->xwindow->win, - xvimagesink->xwindow->gc, meta->xvimage, - src.x, src.y, src.w, src.h, result.x, result.y, result.w, result.h); - } - - XSync (xvimagesink->xcontext->disp, FALSE); - - g_mutex_unlock (xvimagesink->x_lock); - - g_mutex_unlock (xvimagesink->flow_lock); - - return TRUE; -} - -static gboolean -gst_xvimagesink_xwindow_decorate (GstXvImageSink * xvimagesink, - GstXWindow * window) -{ - Atom hints_atom = None; - MotifWmHints *hints; - - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE); - g_return_val_if_fail (window != NULL, FALSE); - - g_mutex_lock (xvimagesink->x_lock); - - hints_atom = XInternAtom (xvimagesink->xcontext->disp, "_MOTIF_WM_HINTS", - True); - if (hints_atom == None) { - g_mutex_unlock (xvimagesink->x_lock); - return FALSE; + memcpy (&result, &xwindow->render_rect, sizeof (GstVideoRectangle)); } - hints = g_malloc0 (sizeof (MotifWmHints)); - - hints->flags |= MWM_HINTS_DECORATIONS; - hints->decorations = 1 << 0; - - XChangeProperty (xvimagesink->xcontext->disp, window->win, - hints_atom, hints_atom, 32, PropModeReplace, - (guchar *) hints, sizeof (MotifWmHints) / sizeof (long)); - - XSync (xvimagesink->xcontext->disp, FALSE); - - g_mutex_unlock (xvimagesink->x_lock); + gst_xvimage_memory_render (mem, &src, xwindow, &result, draw_border); - g_free (hints); + g_mutex_unlock (&xvimagesink->flow_lock); return TRUE; } static void -gst_xvimagesink_xwindow_set_title (GstXvImageSink * xvimagesink, +gst_xv_image_sink_xwindow_set_title (GstXvImageSink * xvimagesink, GstXWindow * xwindow, const gchar * media_title) { if (media_title) { @@ -426,98 +325,46 @@ gst_xvimagesink_xwindow_set_title (GstXvImageSink * xvimagesink, } if (xwindow) { /* we have a window */ - if (xwindow->internal) { - XTextProperty xproperty; - const gchar *app_name; - const gchar *title = NULL; - gchar *title_mem = NULL; - - /* set application name as a title */ - app_name = g_get_application_name (); - - if (app_name && xvimagesink->media_title) { - title = title_mem = g_strconcat (xvimagesink->media_title, " : ", - app_name, NULL); - } else if (app_name) { - title = app_name; - } else if (xvimagesink->media_title) { - title = xvimagesink->media_title; - } - - if (title) { - if ((XStringListToTextProperty (((char **) &title), 1, - &xproperty)) != 0) { - XSetWMName (xvimagesink->xcontext->disp, xwindow->win, &xproperty); - XFree (xproperty.value); - } - - g_free (title_mem); - } + const gchar *app_name; + const gchar *title = NULL; + gchar *title_mem = NULL; + + /* set application name as a title */ + app_name = g_get_application_name (); + + if (app_name && xvimagesink->media_title) { + title = title_mem = g_strconcat (xvimagesink->media_title, " : ", + app_name, NULL); + } else if (app_name) { + title = app_name; + } else if (xvimagesink->media_title) { + title = xvimagesink->media_title; } + + gst_xwindow_set_title (xwindow, title); + g_free (title_mem); } } /* This function handles a GstXWindow creation * The width and height are the actual pixel size on the display */ static GstXWindow * -gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink, +gst_xv_image_sink_xwindow_new (GstXvImageSink * xvimagesink, gint width, gint height) { GstXWindow *xwindow = NULL; - XGCValues values; - - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); - - xwindow = g_new0 (GstXWindow, 1); - - xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; - xvimagesink->render_rect.w = width; - xvimagesink->render_rect.h = height; + GstXvContext *context; - xwindow->width = width; - xwindow->height = height; - xwindow->internal = TRUE; + g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL); - g_mutex_lock (xvimagesink->x_lock); + context = xvimagesink->context; - xwindow->win = XCreateSimpleWindow (xvimagesink->xcontext->disp, - xvimagesink->xcontext->root, - 0, 0, width, height, 0, 0, xvimagesink->xcontext->black); - - /* We have to do that to prevent X from redrawing the background on - * ConfigureNotify. This takes away flickering of video when resizing. */ - XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None); + xwindow = gst_xvcontext_create_xwindow (context, width, height); /* set application name as a title */ - gst_xvimagesink_xwindow_set_title (xvimagesink, xwindow, NULL); - - if (xvimagesink->handle_events) { - Atom wm_delete; - - XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask | - StructureNotifyMask | PointerMotionMask | KeyPressMask | - KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); - - /* Tell the window manager we'd like delete client messages instead of - * being killed */ - wm_delete = XInternAtom (xvimagesink->xcontext->disp, - "WM_DELETE_WINDOW", True); - if (wm_delete != None) { - (void) XSetWMProtocols (xvimagesink->xcontext->disp, xwindow->win, - &wm_delete, 1); - } - } + gst_xv_image_sink_xwindow_set_title (xvimagesink, xwindow, NULL); - xwindow->gc = XCreateGC (xvimagesink->xcontext->disp, - xwindow->win, 0, &values); - - XMapRaised (xvimagesink->xcontext->disp, xwindow->win); - - XSync (xvimagesink->xcontext->disp, FALSE); - - g_mutex_unlock (xvimagesink->x_lock); - - gst_xvimagesink_xwindow_decorate (xvimagesink, xwindow); + gst_xwindow_set_event_handling (xwindow, xvimagesink->handle_events); gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (xvimagesink), xwindow->win); @@ -525,144 +372,32 @@ gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink, return xwindow; } -/* This function destroys a GstXWindow */ -static void -gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink, - GstXWindow * xwindow) -{ - g_return_if_fail (xwindow != NULL); - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); - - g_mutex_lock (xvimagesink->x_lock); - - /* If we did not create that window we just free the GC and let it live */ - if (xwindow->internal) - XDestroyWindow (xvimagesink->xcontext->disp, xwindow->win); - else - XSelectInput (xvimagesink->xcontext->disp, xwindow->win, 0); - - XFreeGC (xvimagesink->xcontext->disp, xwindow->gc); - - XSync (xvimagesink->xcontext->disp, FALSE); - - g_mutex_unlock (xvimagesink->x_lock); - - g_free (xwindow); -} - static void -gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink) +gst_xv_image_sink_xwindow_update_geometry (GstXvImageSink * xvimagesink) { - XWindowAttributes attr; - - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink)); /* Update the window geometry */ - g_mutex_lock (xvimagesink->x_lock); - if (G_UNLIKELY (xvimagesink->xwindow == NULL)) { - g_mutex_unlock (xvimagesink->x_lock); - return; - } - - XGetWindowAttributes (xvimagesink->xcontext->disp, - xvimagesink->xwindow->win, &attr); - - xvimagesink->xwindow->width = attr.width; - xvimagesink->xwindow->height = attr.height; - - if (!xvimagesink->have_render_rect) { - xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; - xvimagesink->render_rect.w = attr.width; - xvimagesink->render_rect.h = attr.height; - } - - g_mutex_unlock (xvimagesink->x_lock); -} - -static void -gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink, - GstXWindow * xwindow) -{ - g_return_if_fail (xwindow != NULL); - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); - - g_mutex_lock (xvimagesink->x_lock); - - XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, - xwindow->win); - - XSync (xvimagesink->xcontext->disp, FALSE); - - g_mutex_unlock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->flow_lock); + if (G_LIKELY (xvimagesink->xwindow)) + gst_xwindow_update_geometry (xvimagesink->xwindow); + g_mutex_unlock (&xvimagesink->flow_lock); } /* This function commits our internal colorbalance settings to our grabbed Xv - port. If the xcontext is not initialized yet it simply returns */ + port. If the context is not initialized yet it simply returns */ static void -gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink) +gst_xv_image_sink_update_colorbalance (GstXvImageSink * xvimagesink) { - GList *channels = NULL; + GstXvContext *context; - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink)); /* If we haven't initialized the X context we can't update anything */ - if (xvimagesink->xcontext == NULL) + if ((context = xvimagesink->context) == NULL) return; - /* Don't set the attributes if they haven't been changed, to avoid - * rounding errors changing the values */ - if (!xvimagesink->cb_changed) - return; - - /* For each channel of the colorbalance we calculate the correct value - doing range conversion and then set the Xv port attribute to match our - values. */ - channels = xvimagesink->xcontext->channels_list; - - while (channels) { - if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) { - GstColorBalanceChannel *channel = NULL; - Atom prop_atom; - gint value = 0; - gdouble convert_coef; - - channel = GST_COLOR_BALANCE_CHANNEL (channels->data); - g_object_ref (channel); - - /* Our range conversion coef */ - convert_coef = (channel->max_value - channel->min_value) / 2000.0; - - if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { - value = xvimagesink->hue; - } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { - value = xvimagesink->saturation; - } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { - value = xvimagesink->contrast; - } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { - value = xvimagesink->brightness; - } else { - g_warning ("got an unknown channel %s", channel->label); - g_object_unref (channel); - return; - } - - /* Committing to Xv port */ - g_mutex_lock (xvimagesink->x_lock); - prop_atom = - XInternAtom (xvimagesink->xcontext->disp, channel->label, True); - if (prop_atom != None) { - int xv_value; - xv_value = - floor (0.5 + (value + 1000) * convert_coef + channel->min_value); - XvSetPortAttribute (xvimagesink->xcontext->disp, - xvimagesink->xcontext->xv_port_id, prop_atom, xv_value); - } - g_mutex_unlock (xvimagesink->x_lock); - - g_object_unref (channel); - } - channels = g_list_next (channels); - } + gst_xvcontext_update_colorbalance (context, &xvimagesink->config); } /* This function handles XEvents that might be in the queue. It generates @@ -670,25 +405,25 @@ gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink) and navigation. It will also listen for configure events on the window to trigger caps renegotiation so on the fly software scaling can work. */ static void -gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) +gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) { XEvent e; guint pointer_x = 0, pointer_y = 0; gboolean pointer_moved = FALSE; gboolean exposed = FALSE, configured = FALSE; - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink)); /* Handle Interaction, produces navigation events */ /* We get all pointer motion events, only the last position is interesting. */ - g_mutex_lock (xvimagesink->flow_lock); - g_mutex_lock (xvimagesink->x_lock); - while (XCheckWindowEvent (xvimagesink->xcontext->disp, + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); + while (XCheckWindowEvent (xvimagesink->context->disp, xvimagesink->xwindow->win, PointerMotionMask, &e)) { - g_mutex_unlock (xvimagesink->x_lock); - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); switch (e.type) { case MotionNotify: @@ -699,33 +434,34 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) default: break; } - g_mutex_lock (xvimagesink->flow_lock); - g_mutex_lock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); } if (pointer_moved) { - g_mutex_unlock (xvimagesink->x_lock); - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); GST_DEBUG ("xvimagesink pointer moved over window at %d,%d", pointer_x, pointer_y); gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink), "mouse-move", 0, e.xbutton.x, e.xbutton.y); - g_mutex_lock (xvimagesink->flow_lock); - g_mutex_lock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); } /* We get all events on our window to throw them upstream */ - while (XCheckWindowEvent (xvimagesink->xcontext->disp, + while (XCheckWindowEvent (xvimagesink->context->disp, xvimagesink->xwindow->win, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, &e)) { KeySym keysym; + const char *key_str = NULL; /* We lock only for the X function call */ - g_mutex_unlock (xvimagesink->x_lock); - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); switch (e.type) { case ButtonPress: @@ -748,44 +484,44 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) case KeyRelease: /* Key pressed/released over our window. We send upstream events for interactivity/navigation */ - GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d", - e.xkey.keycode, e.xkey.x, e.xkey.y); - g_mutex_lock (xvimagesink->x_lock); - keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp, - e.xkey.keycode, 0); - g_mutex_unlock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->context->lock); + keysym = XkbKeycodeToKeysym (xvimagesink->context->disp, + e.xkey.keycode, 0, 0); if (keysym != NoSymbol) { - char *key_str = NULL; - - g_mutex_lock (xvimagesink->x_lock); key_str = XKeysymToString (keysym); - g_mutex_unlock (xvimagesink->x_lock); - gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), - e.type == KeyPress ? "key-press" : "key-release", key_str); } else { - gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), - e.type == KeyPress ? "key-press" : "key-release", "unknown"); + key_str = "unknown"; } + g_mutex_unlock (&xvimagesink->context->lock); + GST_DEBUG_OBJECT (xvimagesink, + "key %d pressed over window at %d,%d (%s)", + e.xkey.keycode, e.xkey.x, e.xkey.y, key_str); + gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), + e.type == KeyPress ? "key-press" : "key-release", key_str); break; default: GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)", e.type); } - g_mutex_lock (xvimagesink->flow_lock); - g_mutex_lock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); } /* Handle Expose */ - while (XCheckWindowEvent (xvimagesink->xcontext->disp, + while (XCheckWindowEvent (xvimagesink->context->disp, xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) { switch (e.type) { case Expose: exposed = TRUE; break; case ConfigureNotify: - g_mutex_unlock (xvimagesink->x_lock); - gst_xvimagesink_xwindow_update_geometry (xvimagesink); - g_mutex_lock (xvimagesink->x_lock); + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); + + gst_xv_image_sink_xwindow_update_geometry (xvimagesink); + + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); configured = TRUE; break; default: @@ -794,34 +530,34 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) } if (xvimagesink->handle_expose && (exposed || configured)) { - g_mutex_unlock (xvimagesink->x_lock); - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); - gst_xvimagesink_expose (GST_VIDEO_OVERLAY (xvimagesink)); + gst_xv_image_sink_expose (GST_VIDEO_OVERLAY (xvimagesink)); - g_mutex_lock (xvimagesink->flow_lock); - g_mutex_lock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->context->lock); } /* Handle Display events */ - while (XPending (xvimagesink->xcontext->disp)) { - XNextEvent (xvimagesink->xcontext->disp, &e); + while (XPending (xvimagesink->context->disp)) { + XNextEvent (xvimagesink->context->disp, &e); switch (e.type) { case ClientMessage:{ Atom wm_delete; - wm_delete = XInternAtom (xvimagesink->xcontext->disp, + wm_delete = XInternAtom (xvimagesink->context->disp, "WM_DELETE_WINDOW", True); if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) { /* Handle window deletion by posting an error on the bus */ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND, ("Output window was closed"), (NULL)); - g_mutex_unlock (xvimagesink->x_lock); - gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + g_mutex_unlock (&xvimagesink->context->lock); + gst_xwindow_destroy (xvimagesink->xwindow); xvimagesink->xwindow = NULL; - g_mutex_lock (xvimagesink->x_lock); + g_mutex_lock (&xvimagesink->context->lock); } break; } @@ -830,325 +566,21 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) } } - g_mutex_unlock (xvimagesink->x_lock); - g_mutex_unlock (xvimagesink->flow_lock); -} - -static void -gst_lookup_xv_port_from_adaptor (GstXContext * xcontext, - XvAdaptorInfo * adaptors, int adaptor_no) -{ - gint j; - gint res; - - /* Do we support XvImageMask ? */ - if (!(adaptors[adaptor_no].type & XvImageMask)) { - GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", - adaptors[adaptor_no].name); - return; - } - - /* We found such an adaptor, looking for an available port */ - for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) { - /* We try to grab the port */ - res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0); - if (Success == res) { - xcontext->xv_port_id = adaptors[adaptor_no].base_id + j; - GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, - adaptors[adaptor_no].num_ports); - } else { - GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, - adaptors[adaptor_no].name, res); - } - } -} - -/* This function generates a caps with all supported format by the first - Xv grabable port we find. We store each one of the supported formats in a - format list and append the format to a newly created caps that we return - If this function does not return NULL because of an error, it also grabs - the port via XvGrabPort */ -static GstCaps * -gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, - GstXContext * xcontext) -{ - gint i; - XvAdaptorInfo *adaptors; - gint nb_formats; - XvImageFormatValues *formats = NULL; - guint nb_encodings; - XvEncodingInfo *encodings = NULL; - gulong max_w = G_MAXINT, max_h = G_MAXINT; - GstCaps *caps = NULL; - GstCaps *rgb_caps = NULL; - - g_return_val_if_fail (xcontext != NULL, NULL); - - /* First let's check that XVideo extension is available */ - if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) { - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, - ("Could not initialise Xv output"), - ("XVideo extension is not available")); - return NULL; - } - - /* Then we get adaptors list */ - if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root, - &xcontext->nb_adaptors, &adaptors)) { - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, - ("Could not initialise Xv output"), - ("Failed getting XV adaptors list")); - return NULL; - } - - xcontext->xv_port_id = 0; - - GST_DEBUG ("Found %u XV adaptor(s)", xcontext->nb_adaptors); - - xcontext->adaptors = - (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *)); - - /* Now fill up our adaptor name array */ - for (i = 0; i < xcontext->nb_adaptors; i++) { - xcontext->adaptors[i] = g_strdup (adaptors[i].name); - } - - if (xvimagesink->adaptor_no >= 0 && - xvimagesink->adaptor_no < xcontext->nb_adaptors) { - /* Find xv port from user defined adaptor */ - gst_lookup_xv_port_from_adaptor (xcontext, adaptors, - xvimagesink->adaptor_no); - } - - if (!xcontext->xv_port_id) { - /* Now search for an adaptor that supports XvImageMask */ - for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) { - gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i); - xvimagesink->adaptor_no = i; - } - } - - XvFreeAdaptorInfo (adaptors); - - if (!xcontext->xv_port_id) { - xvimagesink->adaptor_no = -1; - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, BUSY, - ("Could not initialise Xv output"), ("No port available")); - return NULL; - } - - /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */ - { - int count, todo = 3; - XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp, - xcontext->xv_port_id, &count); - static const char autopaint[] = "XV_AUTOPAINT_COLORKEY"; - static const char dbl_buffer[] = "XV_DOUBLE_BUFFER"; - static const char colorkey[] = "XV_COLORKEY"; - - GST_DEBUG_OBJECT (xvimagesink, "Checking %d Xv port attributes", count); - - xvimagesink->have_autopaint_colorkey = FALSE; - xvimagesink->have_double_buffer = FALSE; - xvimagesink->have_colorkey = FALSE; - - for (i = 0; ((i < count) && todo); i++) - if (!strcmp (attr[i].name, autopaint)) { - const Atom atom = XInternAtom (xcontext->disp, autopaint, False); - - /* turn on autopaint colorkey */ - XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, - (xvimagesink->autopaint_colorkey ? 1 : 0)); - todo--; - xvimagesink->have_autopaint_colorkey = TRUE; - } else if (!strcmp (attr[i].name, dbl_buffer)) { - const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False); - - XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, - (xvimagesink->double_buffer ? 1 : 0)); - todo--; - xvimagesink->have_double_buffer = TRUE; - } else if (!strcmp (attr[i].name, colorkey)) { - /* Set the colorkey, default is something that is dark but hopefully - * won't randomly appear on the screen elsewhere (ie not black or greys) - * can be overridden by setting "colorkey" property - */ - const Atom atom = XInternAtom (xcontext->disp, colorkey, False); - guint32 ckey = 0; - gboolean set_attr = TRUE; - guint cr, cg, cb; - - /* set a colorkey in the right format RGB565/RGB888 - * We only handle these 2 cases, because they're the only types of - * devices we've encountered. If we don't recognise it, leave it alone - */ - cr = (xvimagesink->colorkey >> 16); - cg = (xvimagesink->colorkey >> 8) & 0xFF; - cb = (xvimagesink->colorkey) & 0xFF; - switch (xcontext->depth) { - case 16: /* RGB 565 */ - cr >>= 3; - cg >>= 2; - cb >>= 3; - ckey = (cr << 11) | (cg << 5) | cb; - break; - case 24: - case 32: /* RGB 888 / ARGB 8888 */ - ckey = (cr << 16) | (cg << 8) | cb; - break; - default: - GST_DEBUG_OBJECT (xvimagesink, - "Unknown bit depth %d for Xv Colorkey - not adjusting", - xcontext->depth); - set_attr = FALSE; - break; - } - - if (set_attr) { - ckey = CLAMP (ckey, (guint32) attr[i].min_value, - (guint32) attr[i].max_value); - GST_LOG_OBJECT (xvimagesink, - "Setting color key for display depth %d to 0x%x", - xcontext->depth, ckey); - - XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, - (gint) ckey); - } - todo--; - xvimagesink->have_colorkey = TRUE; - } - - XFree (attr); - } - - /* Get the list of encodings supported by the adapter and look for the - * XV_IMAGE encoding so we can determine the maximum width and height - * supported */ - XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings, - &encodings); - - for (i = 0; i < nb_encodings; i++) { - GST_LOG_OBJECT (xvimagesink, - "Encoding %d, name %s, max wxh %lux%lu rate %d/%d", - i, encodings[i].name, encodings[i].width, encodings[i].height, - encodings[i].rate.numerator, encodings[i].rate.denominator); - if (strcmp (encodings[i].name, "XV_IMAGE") == 0) { - max_w = encodings[i].width; - max_h = encodings[i].height; - } - } - - XvFreeEncodingInfo (encodings); - - /* We get all image formats supported by our port */ - formats = XvListImageFormats (xcontext->disp, - xcontext->xv_port_id, &nb_formats); - caps = gst_caps_new_empty (); - for (i = 0; i < nb_formats; i++) { - GstCaps *format_caps = NULL; - gboolean is_rgb_format = FALSE; - GstVideoFormat vformat; - - /* We set the image format of the xcontext to an existing one. This - is just some valid image format for making our xshm calls check before - caps negotiation really happens. */ - xcontext->im_format = formats[i].id; - - switch (formats[i].type) { - case XvRGB: - { - XvImageFormatValues *fmt = &(formats[i]); - gint endianness; - - endianness = - (fmt->byte_order == LSBFirst ? G_LITTLE_ENDIAN : G_BIG_ENDIAN); - - vformat = gst_video_format_from_masks (fmt->depth, fmt->bits_per_pixel, - endianness, fmt->red_mask, fmt->green_mask, fmt->blue_mask, 0); - if (vformat == GST_VIDEO_FORMAT_UNKNOWN) - break; - - format_caps = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (vformat), - "width", GST_TYPE_INT_RANGE, 1, max_w, - "height", GST_TYPE_INT_RANGE, 1, max_h, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - - is_rgb_format = TRUE; - break; - } - case XvYUV: - { - vformat = gst_video_format_from_fourcc (formats[i].id); - if (vformat == GST_VIDEO_FORMAT_UNKNOWN) - break; - - format_caps = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (vformat), - "width", GST_TYPE_INT_RANGE, 1, max_w, - "height", GST_TYPE_INT_RANGE, 1, max_h, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - break; - } - default: - vformat = GST_VIDEO_FORMAT_UNKNOWN; - g_assert_not_reached (); - break; - } - - if (format_caps) { - GstXvImageFormat *format = NULL; - - format = g_new0 (GstXvImageFormat, 1); - if (format) { - format->format = formats[i].id; - format->vformat = vformat; - format->caps = gst_caps_copy (format_caps); - xcontext->formats_list = g_list_append (xcontext->formats_list, format); - } - - if (is_rgb_format) { - if (rgb_caps == NULL) - rgb_caps = format_caps; - else - gst_caps_append (rgb_caps, format_caps); - } else - gst_caps_append (caps, format_caps); - } - } - - /* Collected all caps into either the caps or rgb_caps structures. - * Append rgb_caps on the end of YUV, so that YUV is always preferred */ - if (rgb_caps) - gst_caps_append (caps, rgb_caps); - - if (formats) - XFree (formats); - - GST_DEBUG ("Generated the following caps: %" GST_PTR_FORMAT, caps); - - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0); - GST_ELEMENT_ERROR (xvimagesink, STREAM, WRONG_TYPE, (NULL), - ("No supported format found")); - return NULL; - } - - return caps; + g_mutex_unlock (&xvimagesink->context->lock); + g_mutex_unlock (&xvimagesink->flow_lock); } static gpointer -gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink) +gst_xv_image_sink_event_thread (GstXvImageSink * xvimagesink) { - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL); GST_OBJECT_LOCK (xvimagesink); while (xvimagesink->running) { GST_OBJECT_UNLOCK (xvimagesink); if (xvimagesink->xwindow) { - gst_xvimagesink_handle_xevents (xvimagesink); + gst_xv_image_sink_handle_xevents (xvimagesink); } /* FIXME: do we want to align this with the framerate or anything else? */ g_usleep (G_USEC_PER_SEC / 20); @@ -1161,12 +593,12 @@ gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink) } static void -gst_xvimagesink_manage_event_thread (GstXvImageSink * xvimagesink) +gst_xv_image_sink_manage_event_thread (GstXvImageSink * xvimagesink) { GThread *thread = NULL; /* don't start the thread too early */ - if (xvimagesink->xcontext == NULL) { + if (xvimagesink->context == NULL) { return; } @@ -1177,13 +609,8 @@ gst_xvimagesink_manage_event_thread (GstXvImageSink * xvimagesink) GST_DEBUG_OBJECT (xvimagesink, "run xevent thread, expose %d, events %d", xvimagesink->handle_expose, xvimagesink->handle_events); xvimagesink->running = TRUE; -#if !GLIB_CHECK_VERSION (2, 31, 0) - xvimagesink->event_thread = g_thread_create ( - (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL); -#else xvimagesink->event_thread = g_thread_try_new ("xvimagesink-events", - (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, NULL); -#endif + (GThreadFunc) gst_xv_image_sink_event_thread, xvimagesink, NULL); } } else { if (xvimagesink->event_thread) { @@ -1203,330 +630,22 @@ gst_xvimagesink_manage_event_thread (GstXvImageSink * xvimagesink) } - -/* This function calculates the pixel aspect ratio based on the properties - * in the xcontext structure and stores it there. */ -static void -gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) -{ - static const gint par[][2] = { - {1, 1}, /* regular screen */ - {16, 15}, /* PAL TV */ - {11, 10}, /* 525 line Rec.601 video */ - {54, 59}, /* 625 line Rec.601 video */ - {64, 45}, /* 1280x1024 on 16:9 display */ - {5, 3}, /* 1280x1024 on 4:3 display */ - {4, 3} /* 800x600 on 16:9 display */ - }; - gint i; - gint index; - gdouble ratio; - gdouble delta; - -#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1]))) - - /* first calculate the "real" ratio based on the X values; - * which is the "physical" w/h divided by the w/h in pixels of the display */ - ratio = (gdouble) (xcontext->widthmm * xcontext->height) - / (xcontext->heightmm * xcontext->width); - - /* DirectFB's X in 720x576 reports the physical dimensions wrong, so - * override here */ - if (xcontext->width == 720 && xcontext->height == 576) { - ratio = 4.0 * 576 / (3.0 * 720); - } - GST_DEBUG ("calculated pixel aspect ratio: %f", ratio); - - /* now find the one from par[][2] with the lowest delta to the real one */ - delta = DELTA (0); - index = 0; - - for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) { - gdouble this_delta = DELTA (i); - - if (this_delta < delta) { - index = i; - delta = this_delta; - } - } - - GST_DEBUG ("Decided on index %d (%d/%d)", index, - par[index][0], par[index][1]); - - g_free (xcontext->par); - xcontext->par = g_new0 (GValue, 1); - g_value_init (xcontext->par, GST_TYPE_FRACTION); - gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]); - GST_DEBUG ("set xcontext PAR to %d/%d", - gst_value_get_fraction_numerator (xcontext->par), - gst_value_get_fraction_denominator (xcontext->par)); -} - -/* This function gets the X Display and global info about it. Everything is - stored in our object and will be cleaned when the object is disposed. Note - here that caps for supported format are generated without any window or - image creation */ -static GstXContext * -gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink) -{ - GstXContext *xcontext = NULL; - XPixmapFormatValues *px_formats = NULL; - gint nb_formats = 0, i, j, N_attr; - XvAttribute *xv_attr; - Atom prop_atom; - const char *channels[4] = { "XV_HUE", "XV_SATURATION", - "XV_BRIGHTNESS", "XV_CONTRAST" - }; - - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); - - xcontext = g_new0 (GstXContext, 1); - xcontext->im_format = 0; - - g_mutex_lock (xvimagesink->x_lock); - - xcontext->disp = XOpenDisplay (xvimagesink->display_name); - - if (!xcontext->disp) { - g_mutex_unlock (xvimagesink->x_lock); - g_free (xcontext); - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, - ("Could not initialise Xv output"), ("Could not open display")); - return NULL; - } - - xcontext->screen = DefaultScreenOfDisplay (xcontext->disp); - xcontext->screen_num = DefaultScreen (xcontext->disp); - xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num); - xcontext->root = DefaultRootWindow (xcontext->disp); - xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num); - xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num); - xcontext->depth = DefaultDepthOfScreen (xcontext->screen); - - xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); - xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); - xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num); - xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num); - - GST_DEBUG_OBJECT (xvimagesink, "X reports %dx%d pixels and %d mm x %d mm", - xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm); - - gst_xvimagesink_calculate_pixel_aspect_ratio (xcontext); - /* We get supported pixmap formats at supported depth */ - px_formats = XListPixmapFormats (xcontext->disp, &nb_formats); - - if (!px_formats) { - XCloseDisplay (xcontext->disp); - g_mutex_unlock (xvimagesink->x_lock); - g_free (xcontext->par); - g_free (xcontext); - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, - ("Could not initialise Xv output"), ("Could not get pixel formats")); - return NULL; - } - - /* We get bpp value corresponding to our running depth */ - for (i = 0; i < nb_formats; i++) { - if (px_formats[i].depth == xcontext->depth) - xcontext->bpp = px_formats[i].bits_per_pixel; - } - - XFree (px_formats); - - xcontext->endianness = - (ImageByteOrder (xcontext->disp) == - LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN; - - /* our caps system handles 24/32bpp RGB as big-endian. */ - if ((xcontext->bpp == 24 || xcontext->bpp == 32) && - xcontext->endianness == G_LITTLE_ENDIAN) { - xcontext->endianness = G_BIG_ENDIAN; - xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask); - xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask); - xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask); - if (xcontext->bpp == 24) { - xcontext->visual->red_mask >>= 8; - xcontext->visual->green_mask >>= 8; - xcontext->visual->blue_mask >>= 8; - } - } - - xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext); - - /* Search for XShm extension support */ -#ifdef HAVE_XSHM - if (XShmQueryExtension (xcontext->disp) && - gst_xvimagesink_check_xshm_calls (xvimagesink, xcontext)) { - xcontext->use_xshm = TRUE; - GST_DEBUG ("xvimagesink is using XShm extension"); - } else -#endif /* HAVE_XSHM */ - { - xcontext->use_xshm = FALSE; - GST_DEBUG ("xvimagesink is not using XShm extension"); - } - - if (!xcontext->caps) { - XCloseDisplay (xcontext->disp); - g_mutex_unlock (xvimagesink->x_lock); - g_free (xcontext->par); - g_free (xcontext); - /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */ - return NULL; - } - - xv_attr = XvQueryPortAttributes (xcontext->disp, - xcontext->xv_port_id, &N_attr); - - - /* Generate the channels list */ - for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) { - XvAttribute *matching_attr = NULL; - - /* Retrieve the property atom if it exists. If it doesn't exist, - * the attribute itself must not either, so we can skip */ - prop_atom = XInternAtom (xcontext->disp, channels[i], True); - if (prop_atom == None) - continue; - - if (xv_attr != NULL) { - for (j = 0; j < N_attr && matching_attr == NULL; ++j) - if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) - matching_attr = xv_attr + j; - } - - if (matching_attr) { - GstColorBalanceChannel *channel; - - channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); - channel->label = g_strdup (channels[i]); - channel->min_value = matching_attr ? matching_attr->min_value : -1000; - channel->max_value = matching_attr ? matching_attr->max_value : 1000; - - xcontext->channels_list = g_list_append (xcontext->channels_list, - channel); - - /* If the colorbalance settings have not been touched we get Xv values - as defaults and update our internal variables */ - if (!xvimagesink->cb_changed) { - gint val; - - XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, - prop_atom, &val); - /* Normalize val to [-1000, 1000] */ - val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / - (double) (channel->max_value - channel->min_value)); - - if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) - xvimagesink->hue = val; - else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) - xvimagesink->saturation = val; - else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) - xvimagesink->brightness = val; - else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) - xvimagesink->contrast = val; - } - } - } - - if (xv_attr) - XFree (xv_attr); - - g_mutex_unlock (xvimagesink->x_lock); - - return xcontext; -} - -/* This function cleans the X context. Closing the Display, releasing the XV - port and unrefing the caps for supported formats. */ -static void -gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink) -{ - GList *formats_list, *channels_list; - GstXContext *xcontext; - gint i = 0; - - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); - - GST_OBJECT_LOCK (xvimagesink); - if (xvimagesink->xcontext == NULL) { - GST_OBJECT_UNLOCK (xvimagesink); - return; - } - - /* Take the XContext from the sink and clean it up */ - xcontext = xvimagesink->xcontext; - xvimagesink->xcontext = NULL; - - GST_OBJECT_UNLOCK (xvimagesink); - - - formats_list = xcontext->formats_list; - - while (formats_list) { - GstXvImageFormat *format = formats_list->data; - - gst_caps_unref (format->caps); - g_free (format); - formats_list = g_list_next (formats_list); - } - - if (xcontext->formats_list) - g_list_free (xcontext->formats_list); - - channels_list = xcontext->channels_list; - - while (channels_list) { - GstColorBalanceChannel *channel = channels_list->data; - - g_object_unref (channel); - channels_list = g_list_next (channels_list); - } - - if (xcontext->channels_list) - g_list_free (xcontext->channels_list); - - gst_caps_unref (xcontext->caps); - if (xcontext->last_caps) - gst_caps_replace (&xcontext->last_caps, NULL); - - for (i = 0; i < xcontext->nb_adaptors; i++) { - g_free (xcontext->adaptors[i]); - } - - g_free (xcontext->adaptors); - - g_free (xcontext->par); - - g_mutex_lock (xvimagesink->x_lock); - - GST_DEBUG_OBJECT (xvimagesink, "Closing display and freeing X Context"); - - XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0); - - XCloseDisplay (xcontext->disp); - - g_mutex_unlock (xvimagesink->x_lock); - - g_free (xcontext); -} - /* Element stuff */ static GstCaps * -gst_xvimagesink_getcaps (GstBaseSink * bsink, GstCaps * filter) +gst_xv_image_sink_getcaps (GstBaseSink * bsink, GstCaps * filter) { GstXvImageSink *xvimagesink; GstCaps *caps; - xvimagesink = GST_XVIMAGESINK (bsink); + xvimagesink = GST_XV_IMAGE_SINK (bsink); - if (xvimagesink->xcontext) { + if (xvimagesink->context) { if (filter) - return gst_caps_intersect_full (filter, xvimagesink->xcontext->caps, + return gst_caps_intersect_full (filter, xvimagesink->context->caps, GST_CAPS_INTERSECT_FIRST); else - return gst_caps_ref (xvimagesink->xcontext->caps); + return gst_caps_ref (xvimagesink->context->caps); } caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (xvimagesink)); @@ -1541,44 +660,67 @@ gst_xvimagesink_getcaps (GstBaseSink * bsink, GstCaps * filter) return caps; } +static GstBufferPool * +gst_xv_image_sink_create_pool (GstXvImageSink * xvimagesink, GstCaps * caps, + gsize size, gint min) +{ + GstBufferPool *pool; + GstStructure *config; + + pool = gst_xvimage_buffer_pool_new (xvimagesink->allocator); + + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, size, min, 0); + + if (!gst_buffer_pool_set_config (pool, config)) + goto config_failed; + + return pool; + +config_failed: + { + GST_ERROR_OBJECT (xvimagesink, "failed to set config."); + gst_object_unref (pool); + return NULL; + } +} + static gboolean -gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) +gst_xv_image_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) { GstXvImageSink *xvimagesink; - GstStructure *structure; + GstXvContext *context; GstBufferPool *newpool, *oldpool; GstVideoInfo info; guint32 im_format = 0; gint video_par_n, video_par_d; /* video's PAR */ gint display_par_n, display_par_d; /* display's PAR */ guint num, den; - gint size; - xvimagesink = GST_XVIMAGESINK (bsink); + xvimagesink = GST_XV_IMAGE_SINK (bsink); + context = xvimagesink->context; GST_DEBUG_OBJECT (xvimagesink, "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" - GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps); + GST_PTR_FORMAT, context->caps, caps); - if (!gst_caps_can_intersect (xvimagesink->xcontext->caps, caps)) + if (!gst_caps_can_intersect (context->caps, caps)) goto incompatible_caps; if (!gst_video_info_from_caps (&info, caps)) goto invalid_format; - structure = gst_caps_get_structure (caps, 0); - xvimagesink->fps_n = info.fps_n; xvimagesink->fps_d = info.fps_d; xvimagesink->video_width = info.width; xvimagesink->video_height = info.height; - im_format = gst_xvimagesink_get_format_from_info (xvimagesink, &info); + im_format = gst_xvcontext_get_format_from_info (context, &info); if (im_format == -1) goto invalid_format; - size = info.size; + gst_xvcontext_set_colorimetry (context, &info.colorimetry); /* get aspect ratio from caps if it's present, and * convert video width and height to a display width and height @@ -1631,12 +773,12 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink)); /* Notify application to set xwindow id now */ - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); if (!xvimagesink->xwindow) { - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (xvimagesink)); } else { - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); } /* Creating our window and our image with the display size in pixels */ @@ -1644,9 +786,9 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0) goto no_display_size; - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); if (!xvimagesink->xwindow) { - xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink, + xvimagesink->xwindow = gst_xv_image_sink_xwindow_new (xvimagesink, GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink)); } @@ -1658,21 +800,16 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) xvimagesink->redraw_border = TRUE; /* create a new pool for the new configuration */ - newpool = gst_xvimage_buffer_pool_new (xvimagesink); - - structure = gst_buffer_pool_get_config (newpool); - gst_buffer_pool_config_set (structure, caps, size, 2, 0, 0, 15); - if (!gst_buffer_pool_set_config (newpool, structure)) - goto config_failed; + newpool = gst_xv_image_sink_create_pool (xvimagesink, caps, info.size, 2); + /* we don't activate the internal pool yet as it may not be needed */ oldpool = xvimagesink->pool; xvimagesink->pool = newpool; - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); - /* unref the old sink */ + /* deactivate and unref the old internal pool */ if (oldpool) { - /* we don't deactivate, some elements might still be using it, it will - * be deactivated when the last ref is gone */ + gst_buffer_pool_set_active (oldpool, FALSE); gst_object_unref (oldpool); } @@ -1702,50 +839,20 @@ no_display_size: ("Error calculating the output display ratio of the video.")); return FALSE; } -config_failed: - { - GST_ERROR_OBJECT (xvimagesink, "failed to set config."); - g_mutex_unlock (xvimagesink->flow_lock); - return FALSE; - } } static GstStateChangeReturn -gst_xvimagesink_change_state (GstElement * element, GstStateChange transition) +gst_xv_image_sink_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstXvImageSink *xvimagesink; - GstXContext *xcontext = NULL; - xvimagesink = GST_XVIMAGESINK (element); + xvimagesink = GST_XV_IMAGE_SINK (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - /* Initializing the XContext */ - if (xvimagesink->xcontext == NULL) { - xcontext = gst_xvimagesink_xcontext_get (xvimagesink); - if (xcontext == NULL) { - ret = GST_STATE_CHANGE_FAILURE; - goto beach; - } - GST_OBJECT_LOCK (xvimagesink); - if (xcontext) - xvimagesink->xcontext = xcontext; - GST_OBJECT_UNLOCK (xvimagesink); - } - - /* update object's par with calculated one if not set yet */ - if (!xvimagesink->par) { - xvimagesink->par = g_new0 (GValue, 1); - gst_value_init_and_copy (xvimagesink->par, xvimagesink->xcontext->par); - GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR"); - } - /* call XSynchronize with the current value of synchronous */ - GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s", - xvimagesink->synchronous ? "TRUE" : "FALSE"); - XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous); - gst_xvimagesink_update_colorbalance (xvimagesink); - gst_xvimagesink_manage_event_thread (xvimagesink); + if (!gst_xv_image_sink_open (xvimagesink)) + goto error; break; case GST_STATE_CHANGE_READY_TO_PAUSED: break; @@ -1767,29 +874,32 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition) xvimagesink->fps_d = 1; GST_VIDEO_SINK_WIDTH (xvimagesink) = 0; GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0; - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); if (xvimagesink->pool) gst_buffer_pool_set_active (xvimagesink->pool, FALSE); - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); break; case GST_STATE_CHANGE_READY_TO_NULL: - gst_xvimagesink_reset (xvimagesink); + gst_xv_image_sink_close (xvimagesink); break; default: break; } - -beach: return ret; + +error: + { + return GST_STATE_CHANGE_FAILURE; + } } static void -gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf, +gst_xv_image_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, GstClockTime * start, GstClockTime * end) { GstXvImageSink *xvimagesink; - xvimagesink = GST_XVIMAGESINK (bsink); + xvimagesink = GST_XV_IMAGE_SINK (bsink); if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { *start = GST_BUFFER_TIMESTAMP (buf); @@ -1806,18 +916,17 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf, } static GstFlowReturn -gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) +gst_xv_image_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) { GstFlowReturn res; GstXvImageSink *xvimagesink; - GstXvImageMeta *meta; - GstBuffer *to_put; + GstBuffer *to_put = NULL; + GstMemory *mem; - xvimagesink = GST_XVIMAGESINK (vsink); + xvimagesink = GST_XV_IMAGE_SINK (vsink); - meta = gst_buffer_get_xvimage_meta (buf); - - if (meta && meta->sink == xvimagesink) { + if (gst_buffer_n_memory (buf) == 1 && (mem = gst_buffer_peek_memory (buf, 0)) + && gst_xvimage_memory_is_from_context (mem, xvimagesink->context)) { /* If this buffer has been allocated using our buffer management we simply put the ximage which is in the PRIVATE pointer */ GST_LOG_OBJECT (xvimagesink, "buffer %p from our pool, writing directly", @@ -1826,6 +935,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) res = GST_FLOW_OK; } else { GstVideoFrame src, dest; + GstBufferPoolAcquireParams params = { 0, }; /* Else we have to copy the data into our private image, */ /* if we have one... */ @@ -1838,16 +948,16 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) if (!gst_buffer_pool_set_active (xvimagesink->pool, TRUE)) goto activate_failed; - /* take a buffer form our pool */ - res = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &to_put, NULL); + /* take a buffer from our pool, if there is no buffer in the pool something + * is seriously wrong, waiting for the pool here might deadlock when we try + * to go to PAUSED because we never flush the pool then. */ + params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT; + res = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &to_put, ¶ms); if (res != GST_FLOW_OK) goto no_buffer; - if (gst_buffer_get_size (to_put) < gst_buffer_get_size (buf)) - goto wrong_size; - GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink, - "slow copy into bufferpool buffer %p", to_put); + "slow copy buffer %p into bufferpool buffer %p", buf, to_put); if (!gst_video_frame_map (&src, &xvimagesink->info, buf, GST_MAP_READ)) goto invalid_buffer; @@ -1863,7 +973,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) gst_video_frame_unmap (&src); } - if (!gst_xvimagesink_xvimage_put (xvimagesink, to_put)) + if (!gst_xv_image_sink_xvimage_put (xvimagesink, to_put)) goto no_window; done: @@ -1884,22 +994,12 @@ no_buffer: { /* No image available. That's very bad ! */ GST_WARNING_OBJECT (xvimagesink, "could not create image"); - return res; - } -wrong_size: - { - GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, - ("Failed to create output image buffer"), - ("XServer allocated buffer size did not match input buffer %" - G_GSIZE_FORMAT " - %" G_GSIZE_FORMAT, gst_buffer_get_size (to_put), - gst_buffer_get_size (buf))); - res = GST_FLOW_ERROR; - goto done; + return GST_FLOW_OK; } invalid_buffer: { /* No Window available to put our image into */ - GST_WARNING_OBJECT (xvimagesink, "could map image"); + GST_WARNING_OBJECT (xvimagesink, "could not map image"); res = GST_FLOW_OK; goto done; } @@ -1919,9 +1019,9 @@ activate_failed: } static gboolean -gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) +gst_xv_image_sink_event (GstBaseSink * sink, GstEvent * event) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (sink); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (sink); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_TAG:{ @@ -1933,7 +1033,7 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) if (title) { GST_DEBUG_OBJECT (xvimagesink, "got tags, title='%s'", title); - gst_xvimagesink_xwindow_set_title (xvimagesink, xvimagesink->xwindow, + gst_xv_image_sink_xwindow_set_title (xvimagesink, xvimagesink->xwindow, title); g_free (title); @@ -1947,11 +1047,10 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) } static gboolean -gst_xvimagesink_propose_allocation (GstBaseSink * bsink, GstQuery * query) +gst_xv_image_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (bsink); - GstBufferPool *pool; - GstStructure *config; + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (bsink); + GstBufferPool *pool = NULL; GstCaps *caps; guint size; gboolean need_pool; @@ -1961,51 +1060,31 @@ gst_xvimagesink_propose_allocation (GstBaseSink * bsink, GstQuery * query) if (caps == NULL) goto no_caps; - g_mutex_lock (xvimagesink->flow_lock); - if ((pool = xvimagesink->pool)) - gst_object_ref (pool); - g_mutex_unlock (xvimagesink->flow_lock); - - if (pool != NULL) { - const GstCaps *pcaps; - - /* we had a pool, check caps */ - GST_DEBUG_OBJECT (xvimagesink, "check existing pool caps"); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_get (config, &pcaps, &size, NULL, NULL, NULL, NULL); - - if (!gst_caps_is_equal (caps, pcaps)) { - GST_DEBUG_OBJECT (xvimagesink, "pool has different caps"); - /* different caps, we can't use this pool */ - gst_object_unref (pool); - pool = NULL; - } - } - if (pool == NULL && need_pool) { + if (need_pool) { GstVideoInfo info; - GST_DEBUG_OBJECT (xvimagesink, "create new pool"); - pool = gst_xvimage_buffer_pool_new (xvimagesink); - if (!gst_video_info_from_caps (&info, caps)) goto invalid_caps; + GST_DEBUG_OBJECT (xvimagesink, "create new pool"); + pool = gst_xv_image_sink_create_pool (xvimagesink, caps, info.size, 0); + /* the normal size of a frame */ size = info.size; - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set (config, caps, size, 0, 0, 0, 0); - if (!gst_buffer_pool_set_config (pool, config)) - goto config_failed; + if (pool == NULL) + goto no_pool; + } + + if (pool) { + /* we need at least 2 buffer because we hold on to the last one */ + gst_query_add_allocation_pool (query, pool, size, 2, 0); + gst_object_unref (pool); } - /* we need at least 2 buffer because we hold on to the last one */ - gst_query_set_allocation_params (query, size, 2, 0, 0, 0, pool); /* we also support various metadata */ - gst_query_add_allocation_meta (query, GST_VIDEO_META_API); - gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API); - - gst_object_unref (pool); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL); return TRUE; @@ -2020,113 +1099,125 @@ invalid_caps: GST_DEBUG_OBJECT (bsink, "invalid caps specified"); return FALSE; } -config_failed: +no_pool: { - GST_DEBUG_OBJECT (bsink, "failed setting config"); + /* Already warned in create_pool */ return FALSE; } } /* Interfaces stuff */ static void -gst_xvimagesink_navigation_send_event (GstNavigation * navigation, +gst_xv_image_sink_navigation_send_event (GstNavigation * navigation, GstStructure * structure) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (navigation); - GstPad *peer; + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (navigation); + gboolean handled = FALSE; + GstEvent *event = NULL; - if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)))) { - GstEvent *event; - GstVideoRectangle src, dst, result; - gdouble x, y, xscale = 1.0, yscale = 1.0; + GstVideoRectangle src = { 0, }; + GstVideoRectangle dst = { 0, }; + GstVideoRectangle result; + gdouble x, y, xscale = 1.0, yscale = 1.0; + GstXWindow *xwindow; - event = gst_event_new_navigation (structure); + /* We take the flow_lock while we look at the window */ + g_mutex_lock (&xvimagesink->flow_lock); - /* We take the flow_lock while we look at the window */ - g_mutex_lock (xvimagesink->flow_lock); + if (!(xwindow = xvimagesink->xwindow)) { + g_mutex_unlock (&xvimagesink->flow_lock); + return; + } - if (!xvimagesink->xwindow) { - g_mutex_unlock (xvimagesink->flow_lock); - return; - } + if (xvimagesink->keep_aspect) { + /* We get the frame position using the calculated geometry from _setcaps + that respect pixel aspect ratios */ + src.w = GST_VIDEO_SINK_WIDTH (xvimagesink); + src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink); + dst.w = xwindow->render_rect.w; + dst.h = xwindow->render_rect.h; - if (xvimagesink->keep_aspect) { - /* We get the frame position using the calculated geometry from _setcaps - that respect pixel aspect ratios */ - src.w = GST_VIDEO_SINK_WIDTH (xvimagesink); - src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink); - dst.w = xvimagesink->render_rect.w; - dst.h = xvimagesink->render_rect.h; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - result.x += xvimagesink->render_rect.x; - result.y += xvimagesink->render_rect.y; - } else { - memcpy (&result, &xvimagesink->render_rect, sizeof (GstVideoRectangle)); - } + gst_video_sink_center_rect (src, dst, &result, TRUE); + result.x += xwindow->render_rect.x; + result.y += xwindow->render_rect.y; + } else { + memcpy (&result, &xwindow->render_rect, sizeof (GstVideoRectangle)); + } - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); - /* We calculate scaling using the original video frames geometry to include - pixel aspect ratio scaling. */ - xscale = (gdouble) xvimagesink->video_width / result.w; - yscale = (gdouble) xvimagesink->video_height / result.h; + /* We calculate scaling using the original video frames geometry to include + pixel aspect ratio scaling. */ + xscale = (gdouble) xvimagesink->video_width / result.w; + yscale = (gdouble) xvimagesink->video_height / result.h; - /* Converting pointer coordinates to the non scaled geometry */ - if (gst_structure_get_double (structure, "pointer_x", &x)) { - x = MIN (x, result.x + result.w); - x = MAX (x - result.x, 0); - gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, - (gdouble) x * xscale, NULL); - } - if (gst_structure_get_double (structure, "pointer_y", &y)) { - y = MIN (y, result.y + result.h); - y = MAX (y - result.y, 0); - gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, - (gdouble) y * yscale, NULL); - } + /* Converting pointer coordinates to the non scaled geometry */ + if (gst_structure_get_double (structure, "pointer_x", &x)) { + x = MIN (x, result.x + result.w); + x = MAX (x - result.x, 0); + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, + (gdouble) x * xscale, NULL); + } + if (gst_structure_get_double (structure, "pointer_y", &y)) { + y = MIN (y, result.y + result.h); + y = MAX (y - result.y, 0); + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, + (gdouble) y * yscale, NULL); + } + + event = gst_event_new_navigation (structure); + if (event) { + gst_event_ref (event); + handled = gst_pad_push_event (GST_VIDEO_SINK_PAD (xvimagesink), event); - gst_pad_send_event (peer, event); - gst_object_unref (peer); + if (!handled) + gst_element_post_message ((GstElement *) xvimagesink, + gst_navigation_message_new_event ((GstObject *) xvimagesink, event)); + + gst_event_unref (event); } } static void -gst_xvimagesink_navigation_init (GstNavigationInterface * iface) +gst_xv_image_sink_navigation_init (GstNavigationInterface * iface) { - iface->send_event = gst_xvimagesink_navigation_send_event; + iface->send_event = gst_xv_image_sink_navigation_send_event; } static void -gst_xvimagesink_set_window_handle (GstVideoOverlay * overlay, guintptr id) +gst_xv_image_sink_set_window_handle (GstVideoOverlay * overlay, guintptr id) { XID xwindow_id = id; - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay); GstXWindow *xwindow = NULL; + GstXvContext *context; - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink)); - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); /* If we already use that window return */ if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) { - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); return; } /* If the element has not initialized the X11 context try to do so */ - if (!xvimagesink->xcontext && - !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) { - g_mutex_unlock (xvimagesink->flow_lock); + if (!xvimagesink->context && + !(xvimagesink->context = + gst_xvcontext_new (&xvimagesink->config, NULL))) { + g_mutex_unlock (&xvimagesink->flow_lock); /* we have thrown a GST_ELEMENT_ERROR now */ return; } - gst_xvimagesink_update_colorbalance (xvimagesink); + context = xvimagesink->context; + + gst_xv_image_sink_update_colorbalance (xvimagesink); /* If a window is there already we destroy it */ if (xvimagesink->xwindow) { - gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + gst_xwindow_destroy (xvimagesink->xwindow); xvimagesink->xwindow = NULL; } @@ -2137,185 +1228,128 @@ gst_xvimagesink_set_window_handle (GstVideoOverlay * overlay, guintptr id) if (GST_VIDEO_SINK_WIDTH (xvimagesink) && GST_VIDEO_SINK_HEIGHT (xvimagesink)) { xwindow = - gst_xvimagesink_xwindow_new (xvimagesink, + gst_xv_image_sink_xwindow_new (xvimagesink, GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink)); } } else { - XWindowAttributes attr; - - xwindow = g_new0 (GstXWindow, 1); - xwindow->win = xwindow_id; - - /* 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; - if (!xvimagesink->have_render_rect) { - xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; - xvimagesink->render_rect.w = attr.width; - xvimagesink->render_rect.h = attr.height; - } - if (xvimagesink->handle_events) { - 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); + xwindow = gst_xvcontext_create_xwindow_from_xid (context, xwindow_id); + gst_xwindow_set_event_handling (xwindow, xvimagesink->handle_events); } if (xwindow) xvimagesink->xwindow = xwindow; - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); } static void -gst_xvimagesink_expose (GstVideoOverlay * overlay) +gst_xv_image_sink_expose (GstVideoOverlay * overlay) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay); GST_DEBUG ("doing expose"); - gst_xvimagesink_xwindow_update_geometry (xvimagesink); - gst_xvimagesink_xvimage_put (xvimagesink, NULL); + gst_xv_image_sink_xwindow_update_geometry (xvimagesink); + gst_xv_image_sink_xvimage_put (xvimagesink, NULL); } static void -gst_xvimagesink_set_event_handling (GstVideoOverlay * overlay, +gst_xv_image_sink_set_event_handling (GstVideoOverlay * overlay, gboolean handle_events) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay); + g_mutex_lock (&xvimagesink->flow_lock); xvimagesink->handle_events = handle_events; - - g_mutex_lock (xvimagesink->flow_lock); - - if (G_UNLIKELY (!xvimagesink->xwindow)) { - g_mutex_unlock (xvimagesink->flow_lock); - return; - } - - g_mutex_lock (xvimagesink->x_lock); - - if (handle_events) { - if (xvimagesink->xwindow->internal) { - XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, - ExposureMask | StructureNotifyMask | PointerMotionMask | - KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); - } else { - XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, - ExposureMask | StructureNotifyMask | PointerMotionMask | - KeyPressMask | KeyReleaseMask); - } - } else { - XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, 0); - } - - g_mutex_unlock (xvimagesink->x_lock); - - g_mutex_unlock (xvimagesink->flow_lock); + if (G_LIKELY (xvimagesink->xwindow)) + gst_xwindow_set_event_handling (xvimagesink->xwindow, handle_events); + g_mutex_unlock (&xvimagesink->flow_lock); } static void -gst_xvimagesink_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y, - gint width, gint height) +gst_xv_image_sink_set_render_rectangle (GstVideoOverlay * overlay, gint x, + gint y, gint width, gint height) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); - - /* FIXME: how about some locking? */ - if (width >= 0 && height >= 0) { - xvimagesink->render_rect.x = x; - xvimagesink->render_rect.y = y; - xvimagesink->render_rect.w = width; - xvimagesink->render_rect.h = height; - xvimagesink->have_render_rect = TRUE; - } else { - xvimagesink->render_rect.x = 0; - xvimagesink->render_rect.y = 0; - xvimagesink->render_rect.w = xvimagesink->xwindow->width; - xvimagesink->render_rect.h = xvimagesink->xwindow->height; - xvimagesink->have_render_rect = FALSE; - } + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay); + + g_mutex_lock (&xvimagesink->flow_lock); + if (G_LIKELY (xvimagesink->xwindow)) + gst_xwindow_set_render_rectangle (xvimagesink->xwindow, x, y, width, + height); + g_mutex_unlock (&xvimagesink->flow_lock); } static void -gst_xvimagesink_video_overlay_init (GstVideoOverlayInterface * iface) +gst_xv_image_sink_video_overlay_init (GstVideoOverlayInterface * iface) { - iface->set_window_handle = gst_xvimagesink_set_window_handle; - iface->expose = gst_xvimagesink_expose; - iface->handle_events = gst_xvimagesink_set_event_handling; - iface->set_render_rectangle = gst_xvimagesink_set_render_rectangle; + iface->set_window_handle = gst_xv_image_sink_set_window_handle; + iface->expose = gst_xv_image_sink_expose; + iface->handle_events = gst_xv_image_sink_set_event_handling; + iface->set_render_rectangle = gst_xv_image_sink_set_render_rectangle; } static const GList * -gst_xvimagesink_colorbalance_list_channels (GstColorBalance * balance) +gst_xv_image_sink_colorbalance_list_channels (GstColorBalance * balance) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance); - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL); - if (xvimagesink->xcontext) - return xvimagesink->xcontext->channels_list; + if (xvimagesink->context) + return xvimagesink->context->channels_list; else return NULL; } static void -gst_xvimagesink_colorbalance_set_value (GstColorBalance * balance, +gst_xv_image_sink_colorbalance_set_value (GstColorBalance * balance, GstColorBalanceChannel * channel, gint value) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance); - g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink)); g_return_if_fail (channel->label != NULL); - xvimagesink->cb_changed = TRUE; + xvimagesink->config.cb_changed = TRUE; /* Normalize val to [-1000, 1000] */ value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) / (double) (channel->max_value - channel->min_value)); if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { - xvimagesink->hue = value; + xvimagesink->config.hue = value; } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { - xvimagesink->saturation = value; + xvimagesink->config.saturation = value; } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { - xvimagesink->contrast = value; + xvimagesink->config.contrast = value; } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { - xvimagesink->brightness = value; + xvimagesink->config.brightness = value; } else { g_warning ("got an unknown channel %s", channel->label); return; } - gst_xvimagesink_update_colorbalance (xvimagesink); + gst_xv_image_sink_update_colorbalance (xvimagesink); } static gint -gst_xvimagesink_colorbalance_get_value (GstColorBalance * balance, +gst_xv_image_sink_colorbalance_get_value (GstColorBalance * balance, GstColorBalanceChannel * channel) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance); gint value = 0; - g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0); + g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), 0); g_return_val_if_fail (channel->label != NULL, 0); if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { - value = xvimagesink->hue; + value = xvimagesink->config.hue; } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { - value = xvimagesink->saturation; + value = xvimagesink->config.saturation; } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { - value = xvimagesink->contrast; + value = xvimagesink->config.contrast; } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { - value = xvimagesink->brightness; + value = xvimagesink->config.brightness; } else { g_warning ("got an unknown channel %s", channel->label); } @@ -2327,17 +1361,24 @@ gst_xvimagesink_colorbalance_get_value (GstColorBalance * balance, return value; } +static GstColorBalanceType +gst_xv_image_sink_colorbalance_get_balance_type (GstColorBalance * balance) +{ + return GST_COLOR_BALANCE_HARDWARE; +} + static void -gst_xvimagesink_colorbalance_init (GstColorBalanceInterface * iface) +gst_xv_image_sink_colorbalance_init (GstColorBalanceInterface * iface) { - GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE; - iface->list_channels = gst_xvimagesink_colorbalance_list_channels; - iface->set_value = gst_xvimagesink_colorbalance_set_value; - iface->get_value = gst_xvimagesink_colorbalance_get_value; + iface->list_channels = gst_xv_image_sink_colorbalance_list_channels; + iface->set_value = gst_xv_image_sink_colorbalance_set_value; + iface->get_value = gst_xv_image_sink_colorbalance_get_value; + iface->get_balance_type = gst_xv_image_sink_colorbalance_get_balance_type; } +#if 0 static const GList * -gst_xvimagesink_probe_get_properties (GstPropertyProbe * probe) +gst_xv_image_sink_probe_get_properties (GstPropertyProbe * probe) { GObjectClass *klass = G_OBJECT_GET_CLASS (probe); static GList *list = NULL; @@ -2358,10 +1399,10 @@ gst_xvimagesink_probe_get_properties (GstPropertyProbe * probe) } static void -gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe, +gst_xv_image_sink_probe_probe_property (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe); switch (prop_id) { case PROP_DEVICE: @@ -2370,9 +1411,9 @@ gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe, case PROP_COLORKEY: GST_DEBUG_OBJECT (xvimagesink, "probing device list and get capabilities"); - if (!xvimagesink->xcontext) { - GST_DEBUG_OBJECT (xvimagesink, "generating xcontext"); - xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink); + if (!xvimagesink->context) { + GST_DEBUG_OBJECT (xvimagesink, "generating context"); + xvimagesink->context = gst_xv_image_sink_context_get (xvimagesink); } break; default: @@ -2382,10 +1423,10 @@ gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe, } static gboolean -gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe, +gst_xv_image_sink_probe_needs_probe (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe); gboolean ret = FALSE; switch (prop_id) { @@ -2393,7 +1434,7 @@ gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe, case PROP_AUTOPAINT_COLORKEY: case PROP_DOUBLE_BUFFER: case PROP_COLORKEY: - if (xvimagesink->xcontext != NULL) { + if (xvimagesink->context != NULL) { ret = FALSE; } else { ret = TRUE; @@ -2408,14 +1449,14 @@ gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe, } static GValueArray * -gst_xvimagesink_probe_get_values (GstPropertyProbe * probe, +gst_xv_image_sink_probe_get_values (GstPropertyProbe * probe, guint prop_id, const GParamSpec * pspec) { - GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe); GValueArray *array = NULL; - if (G_UNLIKELY (!xvimagesink->xcontext)) { - GST_WARNING_OBJECT (xvimagesink, "we don't have any xcontext, can't " + if (G_UNLIKELY (!xvimagesink->context)) { + GST_WARNING_OBJECT (xvimagesink, "we don't have any context, can't " "get values"); goto beach; } @@ -2426,10 +1467,10 @@ gst_xvimagesink_probe_get_values (GstPropertyProbe * probe, guint i; GValue value = { 0 }; - array = g_value_array_new (xvimagesink->xcontext->nb_adaptors); + array = g_value_array_new (xvimagesink->context->nb_adaptors); g_value_init (&value, G_TYPE_STRING); - for (i = 0; i < xvimagesink->xcontext->nb_adaptors; i++) { + for (i = 0; i < xvimagesink->context->nb_adaptors; i++) { gchar *adaptor_id_s = g_strdup_printf ("%u", i); g_value_set_string (&value, adaptor_id_s); @@ -2486,14 +1527,15 @@ beach: } static void -gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface * +gst_xv_image_sink_property_probe_interface_init (GstPropertyProbeInterface * iface) { - iface->get_properties = gst_xvimagesink_probe_get_properties; - iface->probe_property = gst_xvimagesink_probe_probe_property; - iface->needs_probe = gst_xvimagesink_probe_needs_probe; - iface->get_values = gst_xvimagesink_probe_get_values; + iface->get_properties = gst_xv_image_sink_probe_get_properties; + iface->probe_property = gst_xv_image_sink_probe_probe_property; + iface->needs_probe = gst_xv_image_sink_probe_needs_probe; + iface->get_values = gst_xv_image_sink_probe_get_values; } +#endif /* =========================================== */ /* */ @@ -2502,45 +1544,45 @@ gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface * /* =========================================== */ static void -gst_xvimagesink_set_property (GObject * object, guint prop_id, +gst_xv_image_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstXvImageSink *xvimagesink; - g_return_if_fail (GST_IS_XVIMAGESINK (object)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (object)); - xvimagesink = GST_XVIMAGESINK (object); + xvimagesink = GST_XV_IMAGE_SINK (object); switch (prop_id) { case PROP_HUE: - xvimagesink->hue = g_value_get_int (value); - xvimagesink->cb_changed = TRUE; - gst_xvimagesink_update_colorbalance (xvimagesink); + xvimagesink->config.hue = g_value_get_int (value); + xvimagesink->config.cb_changed = TRUE; + gst_xv_image_sink_update_colorbalance (xvimagesink); break; case PROP_CONTRAST: - xvimagesink->contrast = g_value_get_int (value); - xvimagesink->cb_changed = TRUE; - gst_xvimagesink_update_colorbalance (xvimagesink); + xvimagesink->config.contrast = g_value_get_int (value); + xvimagesink->config.cb_changed = TRUE; + gst_xv_image_sink_update_colorbalance (xvimagesink); break; case PROP_BRIGHTNESS: - xvimagesink->brightness = g_value_get_int (value); - xvimagesink->cb_changed = TRUE; - gst_xvimagesink_update_colorbalance (xvimagesink); + xvimagesink->config.brightness = g_value_get_int (value); + xvimagesink->config.cb_changed = TRUE; + gst_xv_image_sink_update_colorbalance (xvimagesink); break; case PROP_SATURATION: - xvimagesink->saturation = g_value_get_int (value); - xvimagesink->cb_changed = TRUE; - gst_xvimagesink_update_colorbalance (xvimagesink); + xvimagesink->config.saturation = g_value_get_int (value); + xvimagesink->config.cb_changed = TRUE; + gst_xv_image_sink_update_colorbalance (xvimagesink); break; case PROP_DISPLAY: - xvimagesink->display_name = g_strdup (g_value_get_string (value)); + g_free (xvimagesink->config.display_name); + xvimagesink->config.display_name = g_strdup (g_value_get_string (value)); break; case PROP_SYNCHRONOUS: xvimagesink->synchronous = g_value_get_boolean (value); - if (xvimagesink->xcontext) { - XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous); - GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s", - xvimagesink->synchronous ? "TRUE" : "FALSE"); + if (xvimagesink->context) { + gst_xvcontext_set_synchronous (xvimagesink->context, + xvimagesink->synchronous); } break; case PROP_PIXEL_ASPECT_RATIO: @@ -2559,25 +1601,25 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id, xvimagesink->keep_aspect = g_value_get_boolean (value); break; case PROP_HANDLE_EVENTS: - gst_xvimagesink_set_event_handling (GST_VIDEO_OVERLAY (xvimagesink), + gst_xv_image_sink_set_event_handling (GST_VIDEO_OVERLAY (xvimagesink), g_value_get_boolean (value)); - gst_xvimagesink_manage_event_thread (xvimagesink); + gst_xv_image_sink_manage_event_thread (xvimagesink); break; case PROP_DEVICE: - xvimagesink->adaptor_no = atoi (g_value_get_string (value)); + xvimagesink->config.adaptor_nr = atoi (g_value_get_string (value)); break; case PROP_HANDLE_EXPOSE: xvimagesink->handle_expose = g_value_get_boolean (value); - gst_xvimagesink_manage_event_thread (xvimagesink); + gst_xv_image_sink_manage_event_thread (xvimagesink); break; case PROP_DOUBLE_BUFFER: xvimagesink->double_buffer = g_value_get_boolean (value); break; case PROP_AUTOPAINT_COLORKEY: - xvimagesink->autopaint_colorkey = g_value_get_boolean (value); + xvimagesink->config.autopaint_colorkey = g_value_get_boolean (value); break; case PROP_COLORKEY: - xvimagesink->colorkey = g_value_get_int (value); + xvimagesink->config.colorkey = g_value_get_int (value); break; case PROP_DRAW_BORDERS: xvimagesink->draw_borders = g_value_get_boolean (value); @@ -2589,30 +1631,30 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id, } static void -gst_xvimagesink_get_property (GObject * object, guint prop_id, +gst_xv_image_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstXvImageSink *xvimagesink; - g_return_if_fail (GST_IS_XVIMAGESINK (object)); + g_return_if_fail (GST_IS_XV_IMAGE_SINK (object)); - xvimagesink = GST_XVIMAGESINK (object); + xvimagesink = GST_XV_IMAGE_SINK (object); switch (prop_id) { case PROP_HUE: - g_value_set_int (value, xvimagesink->hue); + g_value_set_int (value, xvimagesink->config.hue); break; case PROP_CONTRAST: - g_value_set_int (value, xvimagesink->contrast); + g_value_set_int (value, xvimagesink->config.contrast); break; case PROP_BRIGHTNESS: - g_value_set_int (value, xvimagesink->brightness); + g_value_set_int (value, xvimagesink->config.brightness); break; case PROP_SATURATION: - g_value_set_int (value, xvimagesink->saturation); + g_value_set_int (value, xvimagesink->config.saturation); break; case PROP_DISPLAY: - g_value_set_string (value, xvimagesink->display_name); + g_value_set_string (value, xvimagesink->config.display_name); break; case PROP_SYNCHRONOUS: g_value_set_boolean (value, xvimagesink->synchronous); @@ -2629,16 +1671,17 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, break; case PROP_DEVICE: { - char *adaptor_no_s = g_strdup_printf ("%u", xvimagesink->adaptor_no); + char *adaptor_nr_s = + g_strdup_printf ("%u", xvimagesink->config.adaptor_nr); - g_value_set_string (value, adaptor_no_s); - g_free (adaptor_no_s); + g_value_set_string (value, adaptor_nr_s); + g_free (adaptor_nr_s); break; } case PROP_DEVICE_NAME: - if (xvimagesink->xcontext && xvimagesink->xcontext->adaptors) { + if (xvimagesink->context && xvimagesink->context->adaptors) { g_value_set_string (value, - xvimagesink->xcontext->adaptors[xvimagesink->adaptor_no]); + xvimagesink->context->adaptors[xvimagesink->config.adaptor_nr]); } else { g_value_set_string (value, NULL); } @@ -2650,10 +1693,10 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, g_value_set_boolean (value, xvimagesink->double_buffer); break; case PROP_AUTOPAINT_COLORKEY: - g_value_set_boolean (value, xvimagesink->autopaint_colorkey); + g_value_set_boolean (value, xvimagesink->config.autopaint_colorkey); break; case PROP_COLORKEY: - g_value_set_int (value, xvimagesink->colorkey); + g_value_set_int (value, xvimagesink->config.colorkey); break; case PROP_DRAW_BORDERS: g_value_set_boolean (value, xvimagesink->draw_borders); @@ -2676,10 +1719,54 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, } } +static gboolean +gst_xv_image_sink_open (GstXvImageSink * xvimagesink) +{ + GError *error = NULL; + + /* Initializing the XvContext unless already done through GstVideoOverlay */ + if (!xvimagesink->context) { + GstXvContext *context; + if (!(context = gst_xvcontext_new (&xvimagesink->config, &error))) + goto no_context; + + GST_OBJECT_LOCK (xvimagesink); + xvimagesink->context = context; + } else + GST_OBJECT_LOCK (xvimagesink); + /* make an allocator for this context */ + xvimagesink->allocator = gst_xvimage_allocator_new (xvimagesink->context); + GST_OBJECT_UNLOCK (xvimagesink); + + /* update object's par with calculated one if not set yet */ + if (!xvimagesink->par) { + xvimagesink->par = g_new0 (GValue, 1); + gst_value_init_and_copy (xvimagesink->par, xvimagesink->context->par); + GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR"); + } + /* call XSynchronize with the current value of synchronous */ + gst_xvcontext_set_synchronous (xvimagesink->context, + xvimagesink->synchronous); + gst_xv_image_sink_update_colorbalance (xvimagesink); + gst_xv_image_sink_manage_event_thread (xvimagesink); + + return TRUE; + +no_context: + { + gst_element_message_full (GST_ELEMENT (xvimagesink), GST_MESSAGE_ERROR, + error->domain, error->code, g_strdup ("Could not initialise Xv output"), + g_strdup (error->message), __FILE__, GST_FUNCTION, __LINE__); + g_clear_error (&error); + return FALSE; + } +} + static void -gst_xvimagesink_reset (GstXvImageSink * xvimagesink) +gst_xv_image_sink_close (GstXvImageSink * xvimagesink) { GThread *thread; + GstXvContext *context; GST_OBJECT_LOCK (xvimagesink); xvimagesink->running = FALSE; @@ -2697,7 +1784,7 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink) xvimagesink->cur_image = NULL; } - g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (&xvimagesink->flow_lock); if (xvimagesink->pool) { gst_object_unref (xvimagesink->pool); @@ -2705,96 +1792,91 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink) } if (xvimagesink->xwindow) { - gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow); - gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + gst_xwindow_clear (xvimagesink->xwindow); + gst_xwindow_destroy (xvimagesink->xwindow); xvimagesink->xwindow = NULL; } - g_mutex_unlock (xvimagesink->flow_lock); + g_mutex_unlock (&xvimagesink->flow_lock); - xvimagesink->render_rect.x = xvimagesink->render_rect.y = - xvimagesink->render_rect.w = xvimagesink->render_rect.h = 0; - xvimagesink->have_render_rect = FALSE; + if (xvimagesink->allocator) { + gst_object_unref (xvimagesink->allocator); + xvimagesink->allocator = NULL; + } + + GST_OBJECT_LOCK (xvimagesink); + /* grab context and mark it as NULL */ + context = xvimagesink->context; + xvimagesink->context = NULL; + GST_OBJECT_UNLOCK (xvimagesink); - gst_xvimagesink_xcontext_clear (xvimagesink); + if (context) + gst_xvcontext_unref (context); } /* Finalize is called only once, dispose can be called multiple times. * We use mutexes and don't reset stuff to NULL here so let's register * as a finalize. */ static void -gst_xvimagesink_finalize (GObject * object) +gst_xv_image_sink_finalize (GObject * object) { GstXvImageSink *xvimagesink; - xvimagesink = GST_XVIMAGESINK (object); + xvimagesink = GST_XV_IMAGE_SINK (object); - gst_xvimagesink_reset (xvimagesink); + gst_xv_image_sink_close (xvimagesink); - if (xvimagesink->display_name) { - g_free (xvimagesink->display_name); - xvimagesink->display_name = NULL; - } + gst_xvcontext_config_clear (&xvimagesink->config); if (xvimagesink->par) { g_free (xvimagesink->par); xvimagesink->par = NULL; } - if (xvimagesink->x_lock) { - g_mutex_free (xvimagesink->x_lock); - xvimagesink->x_lock = NULL; - } - if (xvimagesink->flow_lock) { - g_mutex_free (xvimagesink->flow_lock); - xvimagesink->flow_lock = NULL; - } - + g_mutex_clear (&xvimagesink->flow_lock); g_free (xvimagesink->media_title); G_OBJECT_CLASS (parent_class)->finalize (object); } static void -gst_xvimagesink_init (GstXvImageSink * xvimagesink) +gst_xv_image_sink_init (GstXvImageSink * xvimagesink) { - xvimagesink->display_name = NULL; - xvimagesink->adaptor_no = 0; - xvimagesink->xcontext = NULL; + xvimagesink->config.display_name = NULL; + xvimagesink->config.adaptor_nr = 0; + xvimagesink->config.autopaint_colorkey = TRUE; + xvimagesink->config.double_buffer = TRUE; + /* on 16bit displays this becomes r,g,b = 1,2,3 + * on 24bit displays this becomes r,g,b = 8,8,16 + * as a port atom value */ + xvimagesink->config.colorkey = (8 << 16) | (8 << 8) | 16; + xvimagesink->config.hue = xvimagesink->config.saturation = 0; + xvimagesink->config.contrast = xvimagesink->config.brightness = 0; + xvimagesink->config.cb_changed = FALSE; + + xvimagesink->context = NULL; xvimagesink->xwindow = NULL; xvimagesink->cur_image = NULL; - xvimagesink->hue = xvimagesink->saturation = 0; - xvimagesink->contrast = xvimagesink->brightness = 0; - xvimagesink->cb_changed = FALSE; - xvimagesink->fps_n = 0; xvimagesink->fps_d = 0; xvimagesink->video_width = 0; xvimagesink->video_height = 0; - xvimagesink->x_lock = g_mutex_new (); - xvimagesink->flow_lock = g_mutex_new (); + g_mutex_init (&xvimagesink->flow_lock); xvimagesink->pool = NULL; xvimagesink->synchronous = FALSE; - xvimagesink->double_buffer = TRUE; xvimagesink->running = FALSE; - xvimagesink->keep_aspect = FALSE; + xvimagesink->keep_aspect = TRUE; xvimagesink->handle_events = TRUE; xvimagesink->par = NULL; xvimagesink->handle_expose = TRUE; - xvimagesink->autopaint_colorkey = TRUE; - /* on 16bit displays this becomes r,g,b = 1,2,3 - * on 24bit displays this becomes r,g,b = 8,8,16 - * as a port atom value - */ - xvimagesink->colorkey = (8 << 16) | (8 << 8) | 16; xvimagesink->draw_borders = TRUE; } static void -gst_xvimagesink_class_init (GstXvImageSinkClass * klass) +gst_xv_image_sink_class_init (GstXvImageSinkClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -2808,8 +1890,8 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) parent_class = g_type_class_peek_parent (klass); - gobject_class->set_property = gst_xvimagesink_set_property; - gobject_class->get_property = gst_xvimagesink_get_property; + gobject_class->set_property = gst_xv_image_sink_set_property; + gobject_class->get_property = gst_xv_image_sink_get_property; g_object_class_install_property (gobject_class, PROP_CONTRAST, g_param_spec_int ("contrast", "Contrast", "The contrast of the video", @@ -2839,7 +1921,7 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio", - "When enabled, scaling will respect original aspect ratio", FALSE, + "When enabled, scaling will respect original aspect ratio", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS, g_param_spec_boolean ("handle-events", "Handle XEvents", @@ -2858,8 +1940,6 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * * When enabled, the current frame will always be drawn in response to X * Expose. - * - * Since: 0.10.14 */ g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE, g_param_spec_boolean ("handle-expose", "Handle expose", @@ -2871,8 +1951,6 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * GstXvImageSink:double-buffer * * Whether to double-buffer the output. - * - * Since: 0.10.14 */ g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER, g_param_spec_boolean ("double-buffer", "Double-buffer", @@ -2882,8 +1960,6 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * GstXvImageSink:autopaint-colorkey * * Whether to autofill overlay with colorkey - * - * Since: 0.10.21 */ g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY, g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey", @@ -2893,8 +1969,6 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * GstXvImageSink:colorkey * * Color to use for the overlay mask. - * - * Since: 0.10.21 */ g_object_class_install_property (gobject_class, PROP_COLORKEY, g_param_spec_int ("colorkey", "Colorkey", @@ -2906,11 +1980,9 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * * Draw black borders when using GstXvImageSink:force-aspect-ratio to fill * unused parts of the video area. - * - * Since: 0.10.21 */ g_object_class_install_property (gobject_class, PROP_DRAW_BORDERS, - g_param_spec_boolean ("draw-borders", "Colorkey", + g_param_spec_boolean ("draw-borders", "Draw Borders", "Draw black borders to fill unused area in force-aspect-ratio mode", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -2918,8 +1990,6 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * GstXvImageSink:window-width * * Actual width of the video window. - * - * Since: 0.10.32 */ g_object_class_install_property (gobject_class, PROP_WINDOW_WIDTH, g_param_spec_uint64 ("window-width", "window-width", @@ -2930,32 +2000,32 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) * GstXvImageSink:window-height * * Actual height of the video window. - * - * Since: 0.10.32 */ g_object_class_install_property (gobject_class, PROP_WINDOW_HEIGHT, g_param_spec_uint64 ("window-height", "window-height", "Height of the window", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - gobject_class->finalize = gst_xvimagesink_finalize; + gobject_class->finalize = gst_xv_image_sink_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Video sink", "Sink/Video", "A Xv based videosink", "Julien Moutte "); gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory)); + gst_static_pad_template_get (&gst_xv_image_sink_sink_template_factory)); gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state); + GST_DEBUG_FUNCPTR (gst_xv_image_sink_change_state); - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps); - gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps); - gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times); + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xv_image_sink_getcaps); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xv_image_sink_setcaps); + gstbasesink_class->get_times = + GST_DEBUG_FUNCPTR (gst_xv_image_sink_get_times); gstbasesink_class->propose_allocation = - GST_DEBUG_FUNCPTR (gst_xvimagesink_propose_allocation); - gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event); + GST_DEBUG_FUNCPTR (gst_xv_image_sink_propose_allocation); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xv_image_sink_event); - videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame); + videosink_class->show_frame = + GST_DEBUG_FUNCPTR (gst_xv_image_sink_show_frame); }