Blame sys/xvimage/xvimagesink.c

Packit 971217
/* GStreamer
Packit 971217
 * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
Packit 971217
 *               <2009>,<2010> Stefan Kost <stefan.kost@nokia.com>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
/**
Packit 971217
 * SECTION:element-xvimagesink
Packit 971217
 * @title: xvimagesink
Packit 971217
 *
Packit 971217
 * XvImageSink renders video frames to a drawable (XWindow) on a local display
Packit 971217
 * using the XVideo extension. Rendering to a remote display is theoretically
Packit 971217
 * possible but i doubt that the XVideo extension is actually available when
Packit 971217
 * connecting to a remote display. This element can receive a Window ID from the
Packit 971217
 * application through the #GstVideoOverlay interface and will then render
Packit 971217
 * video frames in this drawable. If no Window ID was provided by the
Packit 971217
 * application, the element will create its own internal window and render
Packit 971217
 * into it.
Packit 971217
 *
Packit 971217
 * ## Scaling
Packit 971217
 *
Packit 971217
 * The XVideo extension, when it's available, handles hardware accelerated
Packit 971217
 * scaling of video frames. This means that the element will just accept
Packit 971217
 * incoming video frames no matter their geometry and will then put them to the
Packit 971217
 * drawable scaling them on the fly. Using the #GstXvImageSink:force-aspect-ratio
Packit 971217
 * property it is possible to enforce scaling with a constant aspect ratio,
Packit 971217
 * which means drawing black borders around the video frame.
Packit 971217
 *
Packit 971217
 * ## Events
Packit 971217
 *
Packit 971217
 * XvImageSink creates a thread to handle events coming from the drawable. There
Packit 971217
 * are several kind of events that can be grouped in 2 big categories: input
Packit 971217
 * events and window state related events. Input events will be translated to
Packit 971217
 * navigation events and pushed upstream for other elements to react on them.
Packit 971217
 * This includes events such as pointer moves, key press/release, clicks etc...
Packit 971217
 * Other events are used to handle the drawable appearance even when the data
Packit 971217
 * is not flowing (GST_STATE_PAUSED). That means that even when the element is
Packit 971217
 * paused, it will receive expose events from the drawable and draw the latest
Packit 971217
 * frame with correct borders/aspect-ratio.
Packit 971217
 *
Packit 971217
 * ## Pixel aspect ratio
Packit 971217
 *
Packit 971217
 * When changing state to GST_STATE_READY, XvImageSink will open a connection to
Packit 971217
 * the display specified in the #GstXvImageSink:display property or the
Packit 971217
 * default display if nothing specified. Once this connection is open it will
Packit 971217
 * inspect the display configuration including the physical display geometry and
Packit 971217
 * then calculate the pixel aspect ratio. When receiving video frames with a
Packit 971217
 * different pixel aspect ratio, XvImageSink will use hardware scaling to
Packit 971217
 * display the video frames correctly on display's pixel aspect ratio.
Packit 971217
 * Sometimes the calculated pixel aspect ratio can be wrong, it is
Packit 971217
 * then possible to enforce a specific pixel aspect ratio using the
Packit 971217
 * #GstXvImageSink:pixel-aspect-ratio property.
Packit 971217
 *
Packit 971217
 * ## Examples
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 -v videotestsrc ! xvimagesink
Packit 971217
 * ]|
Packit 971217
 *  A pipeline to test hardware scaling.
Packit 971217
 * When the test video signal appears you can resize the window and see that
Packit 971217
 * video frames are scaled through hardware (no extra CPU cost). By default
Packit 971217
 * the image will never be distorted when scaled, instead black borders will
Packit 971217
 * be added if needed.
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 -v videotestsrc ! xvimagesink force-aspect-ratio=false
Packit 971217
 * ]|
Packit 971217
 *  Same pipeline with #GstXvImageSink:force-aspect-ratio property set to
Packit 971217
 * false. You can observe that no borders are drawn around the scaled image
Packit 971217
 * now and it will be distorted to fill the entire frame instead of respecting
Packit 971217
 * the aspect ratio.
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 -v videotestsrc ! navigationtest ! xvimagesink
Packit 971217
 * ]|
Packit 971217
 *  A pipeline to test navigation events.
Packit 971217
 * While moving the mouse pointer over the test signal you will see a black box
Packit 971217
 * following the mouse pointer. If you press the mouse button somewhere on the
Packit 971217
 * video and release it somewhere else a green box will appear where you pressed
Packit 971217
 * the button and a red one where you released it. (The navigationtest element
Packit 971217
 * is part of gst-plugins-good.) You can observe here that even if the images
Packit 971217
 * are scaled through hardware the pointer coordinates are converted back to the
Packit 971217
 * original video frame geometry so that the box can be drawn to the correct
Packit 971217
 * position. This also handles borders correctly, limiting coordinates to the
Packit 971217
 * image area
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 -v videotestsrc ! video/x-raw, pixel-aspect-ratio=4/3 ! xvimagesink
Packit 971217
 * ]|
Packit 971217
 *  This is faking a 4/3 pixel aspect ratio caps on video frames produced by
Packit 971217
 * videotestsrc, in most cases the pixel aspect ratio of the display will be
Packit 971217
 * 1/1. This means that XvImageSink will have to do the scaling to convert
Packit 971217
 * incoming frames to a size that will match the display pixel aspect ratio
Packit 971217
 * (from 320x240 to 320x180 in this case).
Packit 971217
 * |[
Packit 971217
 * gst-launch-1.0 -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100
Packit 971217
 * ]|
Packit 971217
 *  Demonstrates how to use the colorbalance interface.
Packit 971217
 *
Packit 971217
 */
Packit 971217
Packit 971217
/* for developers: there are two useful tools : xvinfo and xvattr */
Packit 971217
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
/* Our interfaces */
Packit 971217
#include <gst/video/navigation.h>
Packit 971217
#include <gst/video/videooverlay.h>
Packit 971217
#include <gst/video/colorbalance.h>
Packit 971217
/* Helper functions */
Packit 971217
#include <gst/video/gstvideometa.h>
Packit 971217
Packit 971217
/* Object header */
Packit 971217
#include "xvimagesink.h"
Packit 971217
#include "xvimageallocator.h"
Packit 971217
Packit 971217
/* Debugging category */
Packit 971217
#include <gst/gstinfo.h>
Packit 971217
Packit 971217
/* for XkbKeycodeToKeysym */
Packit 971217
#include <X11/XKBlib.h>
Packit 971217
Packit 971217
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xv_image_sink);
Packit 971217
GST_DEBUG_CATEGORY_EXTERN (CAT_PERFORMANCE);
Packit 971217
#define GST_CAT_DEFAULT gst_debug_xv_image_sink
Packit 971217
Packit 971217
typedef struct
Packit 971217
{
Packit 971217
  unsigned long flags;
Packit 971217
  unsigned long functions;
Packit 971217
  unsigned long decorations;
Packit 971217
  long input_mode;
Packit 971217
  unsigned long status;
Packit 971217
}
Packit 971217
MotifWmHints, MwmHints;
Packit 971217
Packit 971217
#define MWM_HINTS_DECORATIONS   (1L << 1)
Packit 971217
Packit 971217
static gboolean gst_xv_image_sink_open (GstXvImageSink * xvimagesink);
Packit 971217
static void gst_xv_image_sink_close (GstXvImageSink * xvimagesink);
Packit 971217
static void gst_xv_image_sink_xwindow_update_geometry (GstXvImageSink *
Packit 971217
    xvimagesink);
Packit 971217
static void gst_xv_image_sink_expose (GstVideoOverlay * overlay);
Packit 971217
Packit 971217
/* Default template - initiated with class struct to allow gst-register to work
Packit 971217
   without X running */
Packit 971217
static GstStaticPadTemplate gst_xv_image_sink_sink_template_factory =
Packit 971217
GST_STATIC_PAD_TEMPLATE ("sink",
Packit 971217
    GST_PAD_SINK,
Packit 971217
    GST_PAD_ALWAYS,
Packit 971217
    GST_STATIC_CAPS ("video/x-raw, "
Packit 971217
        "framerate = (fraction) [ 0, MAX ], "
Packit 971217
        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
Packit 971217
    );
Packit 971217
Packit 971217
enum
Packit 971217
{
Packit 971217
  PROP_0,
Packit 971217
  PROP_CONTRAST,
Packit 971217
  PROP_BRIGHTNESS,
Packit 971217
  PROP_HUE,
Packit 971217
  PROP_SATURATION,
Packit 971217
  PROP_DISPLAY,
Packit 971217
  PROP_SYNCHRONOUS,
Packit 971217
  PROP_PIXEL_ASPECT_RATIO,
Packit 971217
  PROP_FORCE_ASPECT_RATIO,
Packit 971217
  PROP_HANDLE_EVENTS,
Packit 971217
  PROP_DEVICE,
Packit 971217
  PROP_DEVICE_NAME,
Packit 971217
  PROP_HANDLE_EXPOSE,
Packit 971217
  PROP_DOUBLE_BUFFER,
Packit 971217
  PROP_AUTOPAINT_COLORKEY,
Packit 971217
  PROP_COLORKEY,
Packit 971217
  PROP_DRAW_BORDERS,
Packit 971217
  PROP_WINDOW_WIDTH,
Packit 971217
  PROP_WINDOW_HEIGHT,
Packit 971217
  PROP_LAST
Packit 971217
};
Packit 971217
Packit 971217
/* ============================================================= */
Packit 971217
/*                                                               */
Packit 971217
/*                       Public Methods                          */
Packit 971217
/*                                                               */
Packit 971217
/* ============================================================= */
Packit 971217
Packit 971217
/* =========================================== */
Packit 971217
/*                                             */
Packit 971217
/*          Object typing & Creation           */
Packit 971217
/*                                             */
Packit 971217
/* =========================================== */
Packit 971217
static void gst_xv_image_sink_navigation_init (GstNavigationInterface * iface);
Packit 971217
static void gst_xv_image_sink_video_overlay_init (GstVideoOverlayInterface *
Packit 971217
    iface);
Packit 971217
static void gst_xv_image_sink_colorbalance_init (GstColorBalanceInterface *
Packit 971217
    iface);
Packit 971217
#define gst_xv_image_sink_parent_class parent_class
Packit 971217
G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xv_image_sink, GST_TYPE_VIDEO_SINK,
Packit 971217
    G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
Packit 971217
        gst_xv_image_sink_navigation_init);
Packit 971217
    G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
Packit 971217
        gst_xv_image_sink_video_overlay_init);
Packit 971217
    G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
Packit 971217
        gst_xv_image_sink_colorbalance_init));
Packit 971217
Packit 971217
Packit 971217
/* ============================================================= */
Packit 971217
/*                                                               */
Packit 971217
/*                       Private Methods                         */
Packit 971217
/*                                                               */
Packit 971217
/* ============================================================= */
Packit 971217
Packit 971217
Packit 971217
/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
Packit 971217
 * if no window was available  */
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_xvimage_put (GstXvImageSink * xvimagesink,
Packit 971217
    GstBuffer * xvimage)
Packit 971217
{
Packit 971217
  GstXvImageMemory *mem;
Packit 971217
  GstVideoCropMeta *crop;
Packit 971217
  GstVideoRectangle result;
Packit 971217
  gboolean draw_border = FALSE;
Packit 971217
  GstVideoRectangle src = { 0, };
Packit 971217
  GstVideoRectangle dst = { 0, };
Packit 971217
  GstVideoRectangle mem_crop;
Packit 971217
  GstXWindow *xwindow;
Packit 971217
Packit 971217
  /* We take the flow_lock. If expose is in there we don't want to run
Packit 971217
     concurrently from the data flow thread */
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  if (G_UNLIKELY ((xwindow = xvimagesink->xwindow) == NULL)) {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
  /* Draw borders when displaying the first frame. After this
Packit 971217
     draw borders only on expose event or after a size change. */
Packit 971217
  if (!xvimagesink->cur_image || xvimagesink->redraw_border) {
Packit 971217
    draw_border = xvimagesink->draw_borders;
Packit 971217
    xvimagesink->redraw_border = FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
  /* Store a reference to the last image we put, lose the previous one */
Packit 971217
  if (xvimage && xvimagesink->cur_image != xvimage) {
Packit 971217
    if (xvimagesink->cur_image) {
Packit 971217
      GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
Packit 971217
      gst_buffer_unref (xvimagesink->cur_image);
Packit 971217
    }
Packit 971217
    GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
Packit 971217
    xvimagesink->cur_image = gst_buffer_ref (xvimage);
Packit 971217
  }
Packit 971217
Packit 971217
  /* Expose sends a NULL image, we take the latest frame */
Packit 971217
  if (!xvimage) {
Packit 971217
    if (xvimagesink->cur_image) {
Packit 971217
      draw_border = TRUE;
Packit 971217
      xvimage = xvimagesink->cur_image;
Packit 971217
    } else {
Packit 971217
      g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
      return TRUE;
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  mem = (GstXvImageMemory *) gst_buffer_peek_memory (xvimage, 0);
Packit 971217
  gst_xvimage_memory_get_crop (mem, &mem_crop);
Packit 971217
Packit 971217
  crop = gst_buffer_get_video_crop_meta (xvimage);
Packit 971217
Packit 971217
  if (crop) {
Packit 971217
    src.x = crop->x + mem_crop.x;
Packit 971217
    src.y = crop->y + mem_crop.y;
Packit 971217
    src.w = crop->width;
Packit 971217
    src.h = crop->height;
Packit 971217
    GST_LOG_OBJECT (xvimagesink,
Packit 971217
        "crop %dx%d-%dx%d", crop->x, crop->y, crop->width, crop->height);
Packit 971217
  } else {
Packit 971217
    src = mem_crop;
Packit 971217
  }
Packit 971217
Packit 971217
  if (xvimagesink->keep_aspect) {
Packit 971217
    GstVideoRectangle s;
Packit 971217
Packit 971217
    /* We take the size of the source material as it was negotiated and
Packit 971217
     * corrected for DAR. This size can be different from the cropped size in
Packit 971217
     * which case the image will be scaled to fit the negotiated size. */
Packit 971217
    s.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
Packit 971217
    s.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
Packit 971217
    dst.w = xwindow->render_rect.w;
Packit 971217
    dst.h = xwindow->render_rect.h;
Packit 971217
Packit 971217
    gst_video_sink_center_rect (s, dst, &result, TRUE);
Packit 971217
    result.x += xwindow->render_rect.x;
Packit 971217
    result.y += xwindow->render_rect.y;
Packit 971217
  } else {
Packit 971217
    memcpy (&result, &xwindow->render_rect, sizeof (GstVideoRectangle));
Packit 971217
  }
Packit 971217
Packit 971217
  gst_xvimage_memory_render (mem, &src, xwindow, &result, draw_border);
Packit 971217
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_xwindow_set_title (GstXvImageSink * xvimagesink,
Packit 971217
    GstXWindow * xwindow, const gchar * media_title)
Packit 971217
{
Packit 971217
  if (media_title) {
Packit 971217
    g_free (xvimagesink->media_title);
Packit 971217
    xvimagesink->media_title = g_strdup (media_title);
Packit 971217
  }
Packit 971217
  if (xwindow) {
Packit 971217
    /* we have a window */
Packit 971217
    const gchar *app_name;
Packit 971217
    const gchar *title = NULL;
Packit 971217
    gchar *title_mem = NULL;
Packit 971217
Packit 971217
    /* set application name as a title */
Packit 971217
    app_name = g_get_application_name ();
Packit 971217
Packit 971217
    if (app_name && xvimagesink->media_title) {
Packit 971217
      title = title_mem = g_strconcat (xvimagesink->media_title, " : ",
Packit 971217
          app_name, NULL);
Packit 971217
    } else if (app_name) {
Packit 971217
      title = app_name;
Packit 971217
    } else if (xvimagesink->media_title) {
Packit 971217
      title = xvimagesink->media_title;
Packit 971217
    }
Packit 971217
Packit 971217
    gst_xwindow_set_title (xwindow, title);
Packit 971217
    g_free (title_mem);
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
/* This function handles a GstXWindow creation
Packit 971217
 * The width and height are the actual pixel size on the display */
Packit 971217
static GstXWindow *
Packit 971217
gst_xv_image_sink_xwindow_new (GstXvImageSink * xvimagesink,
Packit 971217
    gint width, gint height)
Packit 971217
{
Packit 971217
  GstXWindow *xwindow = NULL;
Packit 971217
  GstXvContext *context;
Packit 971217
Packit 971217
  g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL);
Packit 971217
Packit 971217
  context = xvimagesink->context;
Packit 971217
Packit 971217
  xwindow = gst_xvcontext_create_xwindow (context, width, height);
Packit 971217
Packit 971217
  /* set application name as a title */
Packit 971217
  gst_xv_image_sink_xwindow_set_title (xvimagesink, xwindow, NULL);
Packit 971217
Packit 971217
  gst_xwindow_set_event_handling (xwindow, xvimagesink->handle_events);
Packit 971217
Packit 971217
  gst_video_overlay_got_window_handle (GST_VIDEO_OVERLAY (xvimagesink),
Packit 971217
      xwindow->win);
Packit 971217
Packit 971217
  return xwindow;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_xwindow_update_geometry (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
Packit 971217
Packit 971217
  /* Update the window geometry */
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  if (G_LIKELY (xvimagesink->xwindow))
Packit 971217
    gst_xwindow_update_geometry (xvimagesink->xwindow);
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
}
Packit 971217
Packit 971217
/* This function commits our internal colorbalance settings to our grabbed Xv
Packit 971217
   port. If the context is not initialized yet it simply returns */
Packit 971217
static void
Packit 971217
gst_xv_image_sink_update_colorbalance (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  GstXvContext *context;
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
Packit 971217
Packit 971217
  /* If we haven't initialized the X context we can't update anything */
Packit 971217
  if ((context = xvimagesink->context) == NULL)
Packit 971217
    return;
Packit 971217
Packit 971217
  gst_xvcontext_update_colorbalance (context, &xvimagesink->config);
Packit 971217
}
Packit 971217
Packit 971217
/* This function handles XEvents that might be in the queue. It generates
Packit 971217
   GstEvent that will be sent upstream in the pipeline to handle interactivity
Packit 971217
   and navigation. It will also listen for configure events on the window to
Packit 971217
   trigger caps renegotiation so on the fly software scaling can work. */
Packit 971217
static void
Packit 971217
gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  XEvent e;
Packit 971217
  gint pointer_x = 0, pointer_y = 0;
Packit 971217
  gboolean pointer_moved = FALSE;
Packit 971217
  gboolean exposed = FALSE, configured = FALSE;
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
Packit 971217
Packit 971217
  /* Handle Interaction, produces navigation events */
Packit 971217
Packit 971217
  /* We get all pointer motion events, only the last position is
Packit 971217
     interesting. */
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
  while (XCheckWindowEvent (xvimagesink->context->disp,
Packit 971217
          xvimagesink->xwindow->win, PointerMotionMask, &e)) {
Packit 971217
    g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
    switch (e.type) {
Packit 971217
      case MotionNotify:
Packit 971217
        pointer_x = e.xmotion.x;
Packit 971217
        pointer_y = e.xmotion.y;
Packit 971217
        pointer_moved = TRUE;
Packit 971217
        break;
Packit 971217
      default:
Packit 971217
        break;
Packit 971217
    }
Packit 971217
    g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
    g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
  }
Packit 971217
Packit 971217
  if (pointer_moved) {
Packit 971217
    g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
    GST_DEBUG ("xvimagesink pointer moved over window at %d,%d",
Packit 971217
        pointer_x, pointer_y);
Packit 971217
    gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
Packit 971217
        "mouse-move", 0, e.xbutton.x, e.xbutton.y);
Packit 971217
Packit 971217
    g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
    g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
  }
Packit 971217
Packit 971217
  /* We get all events on our window to throw them upstream */
Packit 971217
  while (XCheckWindowEvent (xvimagesink->context->disp,
Packit 971217
          xvimagesink->xwindow->win,
Packit 971217
          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
Packit 971217
          &e)) {
Packit 971217
    KeySym keysym;
Packit 971217
    const char *key_str = NULL;
Packit 971217
Packit 971217
    /* We lock only for the X function call */
Packit 971217
    g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
    switch (e.type) {
Packit 971217
      case ButtonPress:
Packit 971217
        /* Mouse button pressed over our window. We send upstream
Packit 971217
           events for interactivity/navigation */
Packit 971217
        GST_DEBUG ("xvimagesink button %d pressed over window at %d,%d",
Packit 971217
            e.xbutton.button, e.xbutton.x, e.xbutton.y);
Packit 971217
        gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
Packit 971217
            "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
Packit 971217
        break;
Packit 971217
      case ButtonRelease:
Packit 971217
        /* Mouse button released over our window. We send upstream
Packit 971217
           events for interactivity/navigation */
Packit 971217
        GST_DEBUG ("xvimagesink button %d released over window at %d,%d",
Packit 971217
            e.xbutton.button, e.xbutton.x, e.xbutton.y);
Packit 971217
        gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
Packit 971217
            "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
Packit 971217
        break;
Packit 971217
      case KeyPress:
Packit 971217
      case KeyRelease:
Packit 971217
        /* Key pressed/released over our window. We send upstream
Packit 971217
           events for interactivity/navigation */
Packit 971217
        g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
        keysym = XkbKeycodeToKeysym (xvimagesink->context->disp,
Packit 971217
            e.xkey.keycode, 0, 0);
Packit 971217
        if (keysym != NoSymbol) {
Packit 971217
          key_str = XKeysymToString (keysym);
Packit 971217
        } else {
Packit 971217
          key_str = "unknown";
Packit 971217
        }
Packit 971217
        g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
        GST_DEBUG_OBJECT (xvimagesink,
Packit 971217
            "key %d pressed over window at %d,%d (%s)",
Packit 971217
            e.xkey.keycode, e.xkey.x, e.xkey.y, key_str);
Packit 971217
        gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
Packit 971217
            e.type == KeyPress ? "key-press" : "key-release", key_str);
Packit 971217
        break;
Packit 971217
      default:
Packit 971217
        GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)",
Packit 971217
            e.type);
Packit 971217
    }
Packit 971217
    g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
    g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
  }
Packit 971217
Packit 971217
  /* Handle Expose */
Packit 971217
  while (XCheckWindowEvent (xvimagesink->context->disp,
Packit 971217
          xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
Packit 971217
    switch (e.type) {
Packit 971217
      case Expose:
Packit 971217
        exposed = TRUE;
Packit 971217
        break;
Packit 971217
      case ConfigureNotify:
Packit 971217
        g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
        g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
        gst_xv_image_sink_xwindow_update_geometry (xvimagesink);
Packit 971217
Packit 971217
        g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
        g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
        configured = TRUE;
Packit 971217
        break;
Packit 971217
      default:
Packit 971217
        break;
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  if (xvimagesink->handle_expose && (exposed || configured)) {
Packit 971217
    g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
    gst_xv_image_sink_expose (GST_VIDEO_OVERLAY (xvimagesink));
Packit 971217
Packit 971217
    g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
    g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
  }
Packit 971217
Packit 971217
  /* Handle Display events */
Packit 971217
  while (XPending (xvimagesink->context->disp)) {
Packit 971217
    XNextEvent (xvimagesink->context->disp, &e);
Packit 971217
Packit 971217
    switch (e.type) {
Packit 971217
      case ClientMessage:{
Packit 971217
        Atom wm_delete;
Packit 971217
Packit 971217
        wm_delete = XInternAtom (xvimagesink->context->disp,
Packit 971217
            "WM_DELETE_WINDOW", True);
Packit 971217
        if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) {
Packit 971217
          /* Handle window deletion by posting an error on the bus */
Packit 971217
          GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
Packit 971217
              ("Output window was closed"), (NULL));
Packit 971217
Packit 971217
          g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
          gst_xwindow_destroy (xvimagesink->xwindow);
Packit 971217
          xvimagesink->xwindow = NULL;
Packit 971217
          g_mutex_lock (&xvimagesink->context->lock);
Packit 971217
        }
Packit 971217
        break;
Packit 971217
      }
Packit 971217
      default:
Packit 971217
        break;
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  g_mutex_unlock (&xvimagesink->context->lock);
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
}
Packit 971217
Packit 971217
static gpointer
Packit 971217
gst_xv_image_sink_event_thread (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL);
Packit 971217
Packit 971217
  GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  while (xvimagesink->running) {
Packit 971217
    GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
    if (xvimagesink->xwindow) {
Packit 971217
      gst_xv_image_sink_handle_xevents (xvimagesink);
Packit 971217
    }
Packit 971217
    /* FIXME: do we want to align this with the framerate or anything else? */
Packit 971217
    g_usleep (G_USEC_PER_SEC / 20);
Packit 971217
Packit 971217
    GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  }
Packit 971217
  GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
  return NULL;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_manage_event_thread (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  GThread *thread = NULL;
Packit 971217
Packit 971217
  /* don't start the thread too early */
Packit 971217
  if (xvimagesink->context == NULL) {
Packit 971217
    return;
Packit 971217
  }
Packit 971217
Packit 971217
  GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  if (xvimagesink->handle_expose || xvimagesink->handle_events) {
Packit 971217
    if (!xvimagesink->event_thread) {
Packit 971217
      /* Setup our event listening thread */
Packit 971217
      GST_DEBUG_OBJECT (xvimagesink, "run xevent thread, expose %d, events %d",
Packit 971217
          xvimagesink->handle_expose, xvimagesink->handle_events);
Packit 971217
      xvimagesink->running = TRUE;
Packit 971217
      xvimagesink->event_thread = g_thread_try_new ("xvimagesink-events",
Packit 971217
          (GThreadFunc) gst_xv_image_sink_event_thread, xvimagesink, NULL);
Packit 971217
    }
Packit 971217
  } else {
Packit 971217
    if (xvimagesink->event_thread) {
Packit 971217
      GST_DEBUG_OBJECT (xvimagesink, "stop xevent thread, expose %d, events %d",
Packit 971217
          xvimagesink->handle_expose, xvimagesink->handle_events);
Packit 971217
      xvimagesink->running = FALSE;
Packit 971217
      /* grab thread and mark it as NULL */
Packit 971217
      thread = xvimagesink->event_thread;
Packit 971217
      xvimagesink->event_thread = NULL;
Packit 971217
    }
Packit 971217
  }
Packit 971217
  GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
  /* Wait for our event thread to finish */
Packit 971217
  if (thread)
Packit 971217
    g_thread_join (thread);
Packit 971217
Packit 971217
}
Packit 971217
Packit 971217
/* Element stuff */
Packit 971217
Packit 971217
static GstCaps *
Packit 971217
gst_xv_image_sink_getcaps (GstBaseSink * bsink, GstCaps * filter)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
  GstCaps *caps;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (bsink);
Packit 971217
Packit 971217
  if (xvimagesink->context) {
Packit 971217
    if (filter)
Packit 971217
      return gst_caps_intersect_full (filter, xvimagesink->context->caps,
Packit 971217
          GST_CAPS_INTERSECT_FIRST);
Packit 971217
    else
Packit 971217
      return gst_caps_ref (xvimagesink->context->caps);
Packit 971217
  }
Packit 971217
Packit 971217
  caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (xvimagesink));
Packit 971217
  if (filter) {
Packit 971217
    GstCaps *intersection;
Packit 971217
Packit 971217
    intersection =
Packit 971217
        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
Packit 971217
    gst_caps_unref (caps);
Packit 971217
    caps = intersection;
Packit 971217
  }
Packit 971217
  return caps;
Packit 971217
}
Packit 971217
Packit 971217
static GstBufferPool *
Packit 971217
gst_xv_image_sink_create_pool (GstXvImageSink * xvimagesink, GstCaps * caps,
Packit 971217
    gsize size, gint min)
Packit 971217
{
Packit 971217
  GstBufferPool *pool;
Packit 971217
  GstStructure *config;
Packit 971217
Packit 971217
  pool = gst_xvimage_buffer_pool_new (xvimagesink->allocator);
Packit 971217
Packit 971217
  config = gst_buffer_pool_get_config (pool);
Packit 971217
  gst_buffer_pool_config_set_params (config, caps, size, min, 0);
Packit 971217
Packit 971217
  if (!gst_buffer_pool_set_config (pool, config))
Packit 971217
    goto config_failed;
Packit 971217
Packit 971217
  return pool;
Packit 971217
Packit 971217
config_failed:
Packit 971217
  {
Packit 971217
    GST_ERROR_OBJECT (xvimagesink, "failed to set config.");
Packit 971217
    gst_object_unref (pool);
Packit 971217
    return NULL;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
  GstXvContext *context;
Packit 971217
  GstBufferPool *newpool, *oldpool;
Packit 971217
  GstVideoInfo info;
Packit 971217
  guint32 im_format = 0;
Packit 971217
  gint video_par_n, video_par_d;        /* video's PAR */
Packit 971217
  gint display_par_n, display_par_d;    /* display's PAR */
Packit 971217
  guint num, den;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (bsink);
Packit 971217
  context = xvimagesink->context;
Packit 971217
Packit 971217
  GST_DEBUG_OBJECT (xvimagesink,
Packit 971217
      "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %"
Packit 971217
      GST_PTR_FORMAT, context->caps, caps);
Packit 971217
Packit 971217
  if (!gst_caps_can_intersect (context->caps, caps))
Packit 971217
    goto incompatible_caps;
Packit 971217
Packit 971217
  if (!gst_video_info_from_caps (&info, caps))
Packit 971217
    goto invalid_format;
Packit 971217
Packit 971217
  xvimagesink->fps_n = info.fps_n;
Packit 971217
  xvimagesink->fps_d = info.fps_d;
Packit 971217
Packit 971217
  xvimagesink->video_width = info.width;
Packit 971217
  xvimagesink->video_height = info.height;
Packit 971217
Packit 971217
  im_format = gst_xvcontext_get_format_from_info (context, &info;;
Packit 971217
  if (im_format == -1)
Packit 971217
    goto invalid_format;
Packit 971217
Packit 971217
  gst_xvcontext_set_colorimetry (context, &info.colorimetry);
Packit 971217
Packit 971217
  /* get aspect ratio from caps if it's present, and
Packit 971217
   * convert video width and height to a display width and height
Packit 971217
   * using wd / hd = wv / hv * PARv / PARd */
Packit 971217
Packit 971217
  /* get video's PAR */
Packit 971217
  video_par_n = info.par_n;
Packit 971217
  video_par_d = info.par_d;
Packit 971217
Packit 971217
  /* get display's PAR */
Packit 971217
  if (xvimagesink->par) {
Packit 971217
    display_par_n = gst_value_get_fraction_numerator (xvimagesink->par);
Packit 971217
    display_par_d = gst_value_get_fraction_denominator (xvimagesink->par);
Packit 971217
  } else {
Packit 971217
    display_par_n = 1;
Packit 971217
    display_par_d = 1;
Packit 971217
  }
Packit 971217
Packit 971217
  if (!gst_video_calculate_display_ratio (&num, &den, info.width,
Packit 971217
          info.height, video_par_n, video_par_d, display_par_n, display_par_d))
Packit 971217
    goto no_disp_ratio;
Packit 971217
Packit 971217
  GST_DEBUG_OBJECT (xvimagesink,
Packit 971217
      "video width/height: %dx%d, calculated display ratio: %d/%d",
Packit 971217
      info.width, info.height, num, den);
Packit 971217
Packit 971217
  /* now find a width x height that respects this display ratio.
Packit 971217
   * prefer those that have one of w/h the same as the incoming video
Packit 971217
   * using wd / hd = num / den */
Packit 971217
Packit 971217
  /* start with same height, because of interlaced video */
Packit 971217
  /* check hd / den is an integer scale factor, and scale wd with the PAR */
Packit 971217
  if (info.height % den == 0) {
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink, "keeping video height");
Packit 971217
    GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
Packit 971217
        gst_util_uint64_scale_int (info.height, num, den);
Packit 971217
    GST_VIDEO_SINK_HEIGHT (xvimagesink) = info.height;
Packit 971217
  } else if (info.width % num == 0) {
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink, "keeping video width");
Packit 971217
    GST_VIDEO_SINK_WIDTH (xvimagesink) = info.width;
Packit 971217
    GST_VIDEO_SINK_HEIGHT (xvimagesink) = (guint)
Packit 971217
        gst_util_uint64_scale_int (info.width, den, num);
Packit 971217
  } else {
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height");
Packit 971217
    GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
Packit 971217
        gst_util_uint64_scale_int (info.height, num, den);
Packit 971217
    GST_VIDEO_SINK_HEIGHT (xvimagesink) = info.height;
Packit 971217
  }
Packit 971217
  GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d",
Packit 971217
      GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink));
Packit 971217
Packit 971217
  /* Notify application to set xwindow id now */
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  if (!xvimagesink->xwindow) {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
    gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (xvimagesink));
Packit 971217
  } else {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
  }
Packit 971217
Packit 971217
  /* Creating our window and our image with the display size in pixels */
Packit 971217
  if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 ||
Packit 971217
      GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0)
Packit 971217
    goto no_display_size;
Packit 971217
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  if (!xvimagesink->xwindow) {
Packit 971217
    xvimagesink->xwindow = gst_xv_image_sink_xwindow_new (xvimagesink,
Packit 971217
        GST_VIDEO_SINK_WIDTH (xvimagesink),
Packit 971217
        GST_VIDEO_SINK_HEIGHT (xvimagesink));
Packit 971217
  }
Packit 971217
Packit 971217
  if (xvimagesink->pending_render_rect) {
Packit 971217
    xvimagesink->pending_render_rect = FALSE;
Packit 971217
    gst_xwindow_set_render_rectangle (xvimagesink->xwindow,
Packit 971217
        xvimagesink->render_rect.x, xvimagesink->render_rect.y,
Packit 971217
        xvimagesink->render_rect.w, xvimagesink->render_rect.h);
Packit 971217
  }
Packit 971217
Packit 971217
  xvimagesink->info = info;
Packit 971217
Packit 971217
  /* After a resize, we want to redraw the borders in case the new frame size
Packit 971217
   * doesn't cover the same area */
Packit 971217
  xvimagesink->redraw_border = TRUE;
Packit 971217
Packit 971217
  /* create a new pool for the new configuration */
Packit 971217
  newpool = gst_xv_image_sink_create_pool (xvimagesink, caps, info.size, 2);
Packit 971217
Packit 971217
  /* we don't activate the internal pool yet as it may not be needed */
Packit 971217
  oldpool = xvimagesink->pool;
Packit 971217
  xvimagesink->pool = newpool;
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  /* deactivate and unref the old internal pool */
Packit 971217
  if (oldpool) {
Packit 971217
    gst_buffer_pool_set_active (oldpool, FALSE);
Packit 971217
    gst_object_unref (oldpool);
Packit 971217
  }
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
Packit 971217
  /* ERRORS */
Packit 971217
incompatible_caps:
Packit 971217
  {
Packit 971217
    GST_ERROR_OBJECT (xvimagesink, "caps incompatible");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
invalid_format:
Packit 971217
  {
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink,
Packit 971217
        "Could not locate image format from caps %" GST_PTR_FORMAT, caps);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_disp_ratio:
Packit 971217
  {
Packit 971217
    GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
Packit 971217
        ("Error calculating the output display ratio of the video."));
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_display_size:
Packit 971217
  {
Packit 971217
    GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
Packit 971217
        ("Error calculating the output display size of the video."));
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static GstStateChangeReturn
Packit 971217
gst_xv_image_sink_change_state (GstElement * element, GstStateChange transition)
Packit 971217
{
Packit 971217
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (element);
Packit 971217
Packit 971217
  switch (transition) {
Packit 971217
    case GST_STATE_CHANGE_NULL_TO_READY:
Packit 971217
      if (!gst_xv_image_sink_open (xvimagesink))
Packit 971217
        goto error;
Packit 971217
      break;
Packit 971217
    case GST_STATE_CHANGE_READY_TO_PAUSED:
Packit 971217
      break;
Packit 971217
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
Packit 971217
      break;
Packit 971217
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      break;
Packit 971217
  }
Packit 971217
Packit 971217
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
Packit 971217
Packit 971217
  switch (transition) {
Packit 971217
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
Packit 971217
      break;
Packit 971217
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Packit 971217
      xvimagesink->fps_n = 0;
Packit 971217
      xvimagesink->fps_d = 1;
Packit 971217
      GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
Packit 971217
      GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
Packit 971217
      g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
      if (xvimagesink->pool)
Packit 971217
        gst_buffer_pool_set_active (xvimagesink->pool, FALSE);
Packit 971217
      g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
      break;
Packit 971217
    case GST_STATE_CHANGE_READY_TO_NULL:
Packit 971217
      gst_xv_image_sink_close (xvimagesink);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  return ret;
Packit 971217
Packit 971217
error:
Packit 971217
  {
Packit 971217
    return GST_STATE_CHANGE_FAILURE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
Packit 971217
    GstClockTime * start, GstClockTime * end)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (bsink);
Packit 971217
Packit 971217
  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
Packit 971217
    *start = GST_BUFFER_TIMESTAMP (buf);
Packit 971217
    if (GST_BUFFER_DURATION_IS_VALID (buf)) {
Packit 971217
      *end = *start + GST_BUFFER_DURATION (buf);
Packit 971217
    } else {
Packit 971217
      if (xvimagesink->fps_n > 0) {
Packit 971217
        *end = *start +
Packit 971217
            gst_util_uint64_scale_int (GST_SECOND, xvimagesink->fps_d,
Packit 971217
            xvimagesink->fps_n);
Packit 971217
      }
Packit 971217
    }
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static GstFlowReturn
Packit 971217
gst_xv_image_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
Packit 971217
{
Packit 971217
  GstFlowReturn res;
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
  GstBuffer *to_put = NULL;
Packit 971217
  GstMemory *mem;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (vsink);
Packit 971217
Packit 971217
  if (gst_buffer_n_memory (buf) == 1 && (mem = gst_buffer_peek_memory (buf, 0))
Packit 971217
      && gst_xvimage_memory_is_from_context (mem, xvimagesink->context)) {
Packit 971217
    /* If this buffer has been allocated using our buffer management we simply
Packit 971217
       put the ximage which is in the PRIVATE pointer */
Packit 971217
    GST_LOG_OBJECT (xvimagesink, "buffer %p from our pool, writing directly",
Packit 971217
        buf);
Packit 971217
    to_put = buf;
Packit 971217
    res = GST_FLOW_OK;
Packit 971217
  } else {
Packit 971217
    GstVideoFrame src, dest;
Packit 971217
    GstBufferPoolAcquireParams params = { 0, };
Packit 971217
Packit 971217
    /* Else we have to copy the data into our private image, */
Packit 971217
    /* if we have one... */
Packit 971217
    GST_LOG_OBJECT (xvimagesink, "buffer %p not from our pool, copying", buf);
Packit 971217
Packit 971217
    /* we should have a pool, configured in setcaps */
Packit 971217
    if (xvimagesink->pool == NULL)
Packit 971217
      goto no_pool;
Packit 971217
Packit 971217
    if (!gst_buffer_pool_set_active (xvimagesink->pool, TRUE))
Packit 971217
      goto activate_failed;
Packit 971217
Packit 971217
    /* take a buffer from our pool, if there is no buffer in the pool something
Packit 971217
     * is seriously wrong, waiting for the pool here might deadlock when we try
Packit 971217
     * to go to PAUSED because we never flush the pool then. */
Packit 971217
    params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
Packit 971217
    res = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &to_put, &params);
Packit 971217
    if (res != GST_FLOW_OK)
Packit 971217
      goto no_buffer;
Packit 971217
Packit 971217
    GST_CAT_LOG_OBJECT (CAT_PERFORMANCE, xvimagesink,
Packit 971217
        "slow copy buffer %p into bufferpool buffer %p", buf, to_put);
Packit 971217
Packit 971217
    if (!gst_video_frame_map (&src, &xvimagesink->info, buf, GST_MAP_READ))
Packit 971217
      goto invalid_buffer;
Packit 971217
Packit 971217
    if (!gst_video_frame_map (&dest, &xvimagesink->info, to_put, GST_MAP_WRITE)) {
Packit 971217
      gst_video_frame_unmap (&src;;
Packit 971217
      goto invalid_buffer;
Packit 971217
    }
Packit 971217
Packit 971217
    gst_video_frame_copy (&dest, &src;;
Packit 971217
Packit 971217
    gst_video_frame_unmap (&dest);
Packit 971217
    gst_video_frame_unmap (&src;;
Packit 971217
  }
Packit 971217
Packit 971217
  if (!gst_xv_image_sink_xvimage_put (xvimagesink, to_put))
Packit 971217
    goto no_window;
Packit 971217
Packit 971217
done:
Packit 971217
  if (to_put != buf)
Packit 971217
    gst_buffer_unref (to_put);
Packit 971217
Packit 971217
  return res;
Packit 971217
Packit 971217
  /* ERRORS */
Packit 971217
no_pool:
Packit 971217
  {
Packit 971217
    GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
Packit 971217
        ("Internal error: can't allocate images"),
Packit 971217
        ("We don't have a bufferpool negotiated"));
Packit 971217
    return GST_FLOW_ERROR;
Packit 971217
  }
Packit 971217
no_buffer:
Packit 971217
  {
Packit 971217
    /* No image available. That's very bad ! */
Packit 971217
    GST_WARNING_OBJECT (xvimagesink, "could not create image");
Packit 971217
    return GST_FLOW_OK;
Packit 971217
  }
Packit 971217
invalid_buffer:
Packit 971217
  {
Packit 971217
    /* No Window available to put our image into */
Packit 971217
    GST_WARNING_OBJECT (xvimagesink, "could not map image");
Packit 971217
    res = GST_FLOW_OK;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
no_window:
Packit 971217
  {
Packit 971217
    /* No Window available to put our image into */
Packit 971217
    GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
Packit 971217
    res = GST_FLOW_ERROR;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
activate_failed:
Packit 971217
  {
Packit 971217
    GST_ERROR_OBJECT (xvimagesink, "failed to activate bufferpool.");
Packit 971217
    res = GST_FLOW_ERROR;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_event (GstBaseSink * sink, GstEvent * event)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (sink);
Packit 971217
Packit 971217
  switch (GST_EVENT_TYPE (event)) {
Packit 971217
    case GST_EVENT_TAG:{
Packit 971217
      GstTagList *l;
Packit 971217
      gchar *title = NULL;
Packit 971217
Packit 971217
      gst_event_parse_tag (event, &l);
Packit 971217
      gst_tag_list_get_string (l, GST_TAG_TITLE, &title);
Packit 971217
Packit 971217
      if (title) {
Packit 971217
        GST_DEBUG_OBJECT (xvimagesink, "got tags, title='%s'", title);
Packit 971217
        gst_xv_image_sink_xwindow_set_title (xvimagesink, xvimagesink->xwindow,
Packit 971217
            title);
Packit 971217
Packit 971217
        g_free (title);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    }
Packit 971217
    default:
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (bsink);
Packit 971217
  GstBufferPool *pool = NULL;
Packit 971217
  GstCaps *caps;
Packit 971217
  GstVideoInfo info;
Packit 971217
  guint size;
Packit 971217
  gboolean need_pool;
Packit 971217
Packit 971217
  gst_query_parse_allocation (query, &caps, &need_pool);
Packit 971217
Packit 971217
  if (caps == NULL)
Packit 971217
    goto no_caps;
Packit 971217
Packit 971217
  if (!gst_video_info_from_caps (&info, caps))
Packit 971217
    goto invalid_caps;
Packit 971217
Packit 971217
  /* the normal size of a frame */
Packit 971217
  size = info.size;
Packit 971217
Packit 971217
  if (need_pool) {
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink, "create new pool");
Packit 971217
    pool = gst_xv_image_sink_create_pool (xvimagesink, caps, info.size, 0);
Packit 971217
Packit 971217
    if (pool == NULL)
Packit 971217
      goto no_pool;
Packit 971217
  }
Packit 971217
Packit 971217
  /* we need at least 2 buffer because we hold on to the last one */
Packit 971217
  gst_query_add_allocation_pool (query, pool, size, 2, 0);
Packit 971217
  if (pool)
Packit 971217
    gst_object_unref (pool);
Packit 971217
Packit 971217
  /* we also support various metadata */
Packit 971217
  gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
Packit 971217
  gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
Packit 971217
  /* ERRORS */
Packit 971217
no_caps:
Packit 971217
  {
Packit 971217
    GST_DEBUG_OBJECT (bsink, "no caps specified");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
invalid_caps:
Packit 971217
  {
Packit 971217
    GST_DEBUG_OBJECT (bsink, "invalid caps specified");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_pool:
Packit 971217
  {
Packit 971217
    /* Already warned in create_pool */
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
/* Interfaces stuff */
Packit 971217
static void
Packit 971217
gst_xv_image_sink_navigation_send_event (GstNavigation * navigation,
Packit 971217
    GstStructure * structure)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (navigation);
Packit 971217
  gboolean handled = FALSE;
Packit 971217
  GstEvent *event = NULL;
Packit 971217
Packit 971217
  GstVideoRectangle src = { 0, };
Packit 971217
  GstVideoRectangle dst = { 0, };
Packit 971217
  GstVideoRectangle result;
Packit 971217
  gdouble x, y, xscale = 1.0, yscale = 1.0;
Packit 971217
  GstXWindow *xwindow;
Packit 971217
Packit 971217
  /* We take the flow_lock while we look at the window */
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  if (!(xwindow = xvimagesink->xwindow)) {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
    gst_structure_free (structure);
Packit 971217
    return;
Packit 971217
  }
Packit 971217
Packit 971217
  if (xvimagesink->keep_aspect) {
Packit 971217
    /* We get the frame position using the calculated geometry from _setcaps
Packit 971217
       that respect pixel aspect ratios */
Packit 971217
    src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
Packit 971217
    src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
Packit 971217
    dst.w = xwindow->render_rect.w;
Packit 971217
    dst.h = xwindow->render_rect.h;
Packit 971217
Packit 971217
    gst_video_sink_center_rect (src, dst, &result, TRUE);
Packit 971217
    result.x += xwindow->render_rect.x;
Packit 971217
    result.y += xwindow->render_rect.y;
Packit 971217
  } else {
Packit 971217
    memcpy (&result, &xwindow->render_rect, sizeof (GstVideoRectangle));
Packit 971217
  }
Packit 971217
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  /* We calculate scaling using the original video frames geometry to include
Packit 971217
     pixel aspect ratio scaling. */
Packit 971217
  xscale = (gdouble) xvimagesink->video_width / result.w;
Packit 971217
  yscale = (gdouble) xvimagesink->video_height / result.h;
Packit 971217
Packit 971217
  /* Converting pointer coordinates to the non scaled geometry */
Packit 971217
  if (gst_structure_get_double (structure, "pointer_x", &x)) {
Packit 971217
    x = MIN (x, result.x + result.w);
Packit 971217
    x = MAX (x - result.x, 0);
Packit 971217
    gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
Packit 971217
        (gdouble) x * xscale, NULL);
Packit 971217
  }
Packit 971217
  if (gst_structure_get_double (structure, "pointer_y", &y)) {
Packit 971217
    y = MIN (y, result.y + result.h);
Packit 971217
    y = MAX (y - result.y, 0);
Packit 971217
    gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
Packit 971217
        (gdouble) y * yscale, NULL);
Packit 971217
  }
Packit 971217
Packit 971217
  event = gst_event_new_navigation (structure);
Packit 971217
  if (event) {
Packit 971217
    gst_event_ref (event);
Packit 971217
    handled = gst_pad_push_event (GST_VIDEO_SINK_PAD (xvimagesink), event);
Packit 971217
Packit 971217
    if (!handled)
Packit 971217
      gst_element_post_message ((GstElement *) xvimagesink,
Packit 971217
          gst_navigation_message_new_event ((GstObject *) xvimagesink, event));
Packit 971217
Packit 971217
    gst_event_unref (event);
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_navigation_init (GstNavigationInterface * iface)
Packit 971217
{
Packit 971217
  iface->send_event = gst_xv_image_sink_navigation_send_event;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_set_window_handle (GstVideoOverlay * overlay, guintptr id)
Packit 971217
{
Packit 971217
  XID xwindow_id = id;
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay);
Packit 971217
  GstXWindow *xwindow = NULL;
Packit 971217
  GstXvContext *context;
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
Packit 971217
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  /* If we already use that window return */
Packit 971217
  if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
    return;
Packit 971217
  }
Packit 971217
Packit 971217
  /* If the element has not initialized the X11 context try to do so */
Packit 971217
  if (!xvimagesink->context &&
Packit 971217
      !(xvimagesink->context =
Packit 971217
          gst_xvcontext_new (&xvimagesink->config, NULL))) {
Packit 971217
    g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
    /* we have thrown a GST_ELEMENT_ERROR now */
Packit 971217
    return;
Packit 971217
  }
Packit 971217
Packit 971217
  context = xvimagesink->context;
Packit 971217
Packit 971217
  gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
Packit 971217
  /* If a window is there already we destroy it */
Packit 971217
  if (xvimagesink->xwindow) {
Packit 971217
    gst_xwindow_destroy (xvimagesink->xwindow);
Packit 971217
    xvimagesink->xwindow = NULL;
Packit 971217
  }
Packit 971217
Packit 971217
  /* If the xid is 0 we go back to an internal window */
Packit 971217
  if (xwindow_id == 0) {
Packit 971217
    /* If no width/height caps nego did not happen window will be created
Packit 971217
       during caps nego then */
Packit 971217
    if (GST_VIDEO_SINK_WIDTH (xvimagesink)
Packit 971217
        && GST_VIDEO_SINK_HEIGHT (xvimagesink)) {
Packit 971217
      xwindow =
Packit 971217
          gst_xv_image_sink_xwindow_new (xvimagesink,
Packit 971217
          GST_VIDEO_SINK_WIDTH (xvimagesink),
Packit 971217
          GST_VIDEO_SINK_HEIGHT (xvimagesink));
Packit 971217
    }
Packit 971217
  } else {
Packit 971217
    xwindow = gst_xvcontext_create_xwindow_from_xid (context, xwindow_id);
Packit 971217
    gst_xwindow_set_event_handling (xwindow, xvimagesink->handle_events);
Packit 971217
  }
Packit 971217
Packit 971217
  if (xwindow)
Packit 971217
    xvimagesink->xwindow = xwindow;
Packit 971217
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_expose (GstVideoOverlay * overlay)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay);
Packit 971217
Packit 971217
  GST_DEBUG ("doing expose");
Packit 971217
  gst_xv_image_sink_xwindow_update_geometry (xvimagesink);
Packit 971217
  gst_xv_image_sink_xvimage_put (xvimagesink, NULL);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_set_event_handling (GstVideoOverlay * overlay,
Packit 971217
    gboolean handle_events)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay);
Packit 971217
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  xvimagesink->handle_events = handle_events;
Packit 971217
  if (G_LIKELY (xvimagesink->xwindow))
Packit 971217
    gst_xwindow_set_event_handling (xvimagesink->xwindow, handle_events);
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_set_render_rectangle (GstVideoOverlay * overlay, gint x,
Packit 971217
    gint y, gint width, gint height)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (overlay);
Packit 971217
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
  if (G_LIKELY (xvimagesink->xwindow)) {
Packit 971217
    gst_xwindow_set_render_rectangle (xvimagesink->xwindow, x, y, width,
Packit 971217
        height);
Packit 971217
  } else {
Packit 971217
    xvimagesink->render_rect.x = x;
Packit 971217
    xvimagesink->render_rect.y = y;
Packit 971217
    xvimagesink->render_rect.w = width;
Packit 971217
    xvimagesink->render_rect.h = height;
Packit 971217
    xvimagesink->pending_render_rect = TRUE;
Packit 971217
  }
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_video_overlay_init (GstVideoOverlayInterface * iface)
Packit 971217
{
Packit 971217
  iface->set_window_handle = gst_xv_image_sink_set_window_handle;
Packit 971217
  iface->expose = gst_xv_image_sink_expose;
Packit 971217
  iface->handle_events = gst_xv_image_sink_set_event_handling;
Packit 971217
  iface->set_render_rectangle = gst_xv_image_sink_set_render_rectangle;
Packit 971217
}
Packit 971217
Packit 971217
static const GList *
Packit 971217
gst_xv_image_sink_colorbalance_list_channels (GstColorBalance * balance)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance);
Packit 971217
Packit 971217
  g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), NULL);
Packit 971217
Packit 971217
  if (xvimagesink->context)
Packit 971217
    return xvimagesink->context->channels_list;
Packit 971217
  else
Packit 971217
    return NULL;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_colorbalance_set_value (GstColorBalance * balance,
Packit 971217
    GstColorBalanceChannel * channel, gint value)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance);
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink));
Packit 971217
  g_return_if_fail (channel->label != NULL);
Packit 971217
Packit 971217
  xvimagesink->config.cb_changed = TRUE;
Packit 971217
Packit 971217
  /* Normalize val to [-1000, 1000] */
Packit 971217
  value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
Packit 971217
      (double) (channel->max_value - channel->min_value));
Packit 971217
Packit 971217
  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
Packit 971217
    xvimagesink->config.hue = value;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
Packit 971217
    xvimagesink->config.saturation = value;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
Packit 971217
    xvimagesink->config.contrast = value;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
Packit 971217
    xvimagesink->config.brightness = value;
Packit 971217
  } else {
Packit 971217
    g_warning ("got an unknown channel %s", channel->label);
Packit 971217
    return;
Packit 971217
  }
Packit 971217
Packit 971217
  gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
}
Packit 971217
Packit 971217
static gint
Packit 971217
gst_xv_image_sink_colorbalance_get_value (GstColorBalance * balance,
Packit 971217
    GstColorBalanceChannel * channel)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (balance);
Packit 971217
  gint value = 0;
Packit 971217
Packit 971217
  g_return_val_if_fail (GST_IS_XV_IMAGE_SINK (xvimagesink), 0);
Packit 971217
  g_return_val_if_fail (channel->label != NULL, 0);
Packit 971217
Packit 971217
  if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
Packit 971217
    value = xvimagesink->config.hue;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
Packit 971217
    value = xvimagesink->config.saturation;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
Packit 971217
    value = xvimagesink->config.contrast;
Packit 971217
  } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
Packit 971217
    value = xvimagesink->config.brightness;
Packit 971217
  } else {
Packit 971217
    g_warning ("got an unknown channel %s", channel->label);
Packit 971217
  }
Packit 971217
Packit 971217
  /* Normalize val to [channel->min_value, channel->max_value] */
Packit 971217
  value = channel->min_value + (channel->max_value - channel->min_value) *
Packit 971217
      (value + 1000) / 2000;
Packit 971217
Packit 971217
  return value;
Packit 971217
}
Packit 971217
Packit 971217
static GstColorBalanceType
Packit 971217
gst_xv_image_sink_colorbalance_get_balance_type (GstColorBalance * balance)
Packit 971217
{
Packit 971217
  return GST_COLOR_BALANCE_HARDWARE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_colorbalance_init (GstColorBalanceInterface * iface)
Packit 971217
{
Packit 971217
  iface->list_channels = gst_xv_image_sink_colorbalance_list_channels;
Packit 971217
  iface->set_value = gst_xv_image_sink_colorbalance_set_value;
Packit 971217
  iface->get_value = gst_xv_image_sink_colorbalance_get_value;
Packit 971217
  iface->get_balance_type = gst_xv_image_sink_colorbalance_get_balance_type;
Packit 971217
}
Packit 971217
Packit 971217
#if 0
Packit 971217
static const GList *
Packit 971217
gst_xv_image_sink_probe_get_properties (GstPropertyProbe * probe)
Packit 971217
{
Packit 971217
  GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
Packit 971217
  static GList *list = NULL;
Packit 971217
Packit 971217
  if (!list) {
Packit 971217
    list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
Packit 971217
    list =
Packit 971217
        g_list_append (list, g_object_class_find_property (klass,
Packit 971217
            "autopaint-colorkey"));
Packit 971217
    list =
Packit 971217
        g_list_append (list, g_object_class_find_property (klass,
Packit 971217
            "double-buffer"));
Packit 971217
    list =
Packit 971217
        g_list_append (list, g_object_class_find_property (klass, "colorkey"));
Packit 971217
  }
Packit 971217
Packit 971217
  return list;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_probe_probe_property (GstPropertyProbe * probe,
Packit 971217
    guint prop_id, const GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe);
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_DEVICE:
Packit 971217
    case PROP_AUTOPAINT_COLORKEY:
Packit 971217
    case PROP_DOUBLE_BUFFER:
Packit 971217
    case PROP_COLORKEY:
Packit 971217
      GST_DEBUG_OBJECT (xvimagesink,
Packit 971217
          "probing device list and get capabilities");
Packit 971217
      if (!xvimagesink->context) {
Packit 971217
        GST_DEBUG_OBJECT (xvimagesink, "generating context");
Packit 971217
        xvimagesink->context = gst_xv_image_sink_context_get (xvimagesink);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_probe_needs_probe (GstPropertyProbe * probe,
Packit 971217
    guint prop_id, const GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe);
Packit 971217
  gboolean ret = FALSE;
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_DEVICE:
Packit 971217
    case PROP_AUTOPAINT_COLORKEY:
Packit 971217
    case PROP_DOUBLE_BUFFER:
Packit 971217
    case PROP_COLORKEY:
Packit 971217
      if (xvimagesink->context != NULL) {
Packit 971217
        ret = FALSE;
Packit 971217
      } else {
Packit 971217
        ret = TRUE;
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
Packit 971217
  return ret;
Packit 971217
}
Packit 971217
Packit 971217
static GValueArray *
Packit 971217
gst_xv_image_sink_probe_get_values (GstPropertyProbe * probe,
Packit 971217
    guint prop_id, const GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink = GST_XV_IMAGE_SINK (probe);
Packit 971217
  GValueArray *array = NULL;
Packit 971217
Packit 971217
  if (G_UNLIKELY (!xvimagesink->context)) {
Packit 971217
    GST_WARNING_OBJECT (xvimagesink, "we don't have any context, can't "
Packit 971217
        "get values");
Packit 971217
    goto beach;
Packit 971217
  }
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_DEVICE:
Packit 971217
    {
Packit 971217
      guint i;
Packit 971217
      GValue value = { 0 };
Packit 971217
Packit 971217
      array = g_value_array_new (xvimagesink->context->nb_adaptors);
Packit 971217
      g_value_init (&value, G_TYPE_STRING);
Packit 971217
Packit 971217
      for (i = 0; i < xvimagesink->context->nb_adaptors; i++) {
Packit 971217
        gchar *adaptor_id_s = g_strdup_printf ("%u", i);
Packit 971217
Packit 971217
        g_value_set_string (&value, adaptor_id_s);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_free (adaptor_id_s);
Packit 971217
      }
Packit 971217
      g_value_unset (&value);
Packit 971217
      break;
Packit 971217
    }
Packit 971217
    case PROP_AUTOPAINT_COLORKEY:
Packit 971217
      if (xvimagesink->have_autopaint_colorkey) {
Packit 971217
        GValue value = { 0 };
Packit 971217
Packit 971217
        array = g_value_array_new (2);
Packit 971217
        g_value_init (&value, G_TYPE_BOOLEAN);
Packit 971217
        g_value_set_boolean (&value, FALSE);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_value_set_boolean (&value, TRUE);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_value_unset (&value);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    case PROP_DOUBLE_BUFFER:
Packit 971217
      if (xvimagesink->have_double_buffer) {
Packit 971217
        GValue value = { 0 };
Packit 971217
Packit 971217
        array = g_value_array_new (2);
Packit 971217
        g_value_init (&value, G_TYPE_BOOLEAN);
Packit 971217
        g_value_set_boolean (&value, FALSE);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_value_set_boolean (&value, TRUE);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_value_unset (&value);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    case PROP_COLORKEY:
Packit 971217
      if (xvimagesink->have_colorkey) {
Packit 971217
        GValue value = { 0 };
Packit 971217
Packit 971217
        array = g_value_array_new (1);
Packit 971217
        g_value_init (&value, GST_TYPE_INT_RANGE);
Packit 971217
        gst_value_set_int_range (&value, 0, 0xffffff);
Packit 971217
        g_value_array_append (array, &value);
Packit 971217
        g_value_unset (&value);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
Packit 971217
beach:
Packit 971217
  return array;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_property_probe_interface_init (GstPropertyProbeInterface *
Packit 971217
    iface)
Packit 971217
{
Packit 971217
  iface->get_properties = gst_xv_image_sink_probe_get_properties;
Packit 971217
  iface->probe_property = gst_xv_image_sink_probe_probe_property;
Packit 971217
  iface->needs_probe = gst_xv_image_sink_probe_needs_probe;
Packit 971217
  iface->get_values = gst_xv_image_sink_probe_get_values;
Packit 971217
}
Packit 971217
#endif
Packit 971217
Packit 971217
/* =========================================== */
Packit 971217
/*                                             */
Packit 971217
/*              Init & Class init              */
Packit 971217
/*                                             */
Packit 971217
/* =========================================== */
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_set_property (GObject * object, guint prop_id,
Packit 971217
    const GValue * value, GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (object));
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (object);
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_HUE:
Packit 971217
      xvimagesink->config.hue = g_value_get_int (value);
Packit 971217
      xvimagesink->config.cb_changed = TRUE;
Packit 971217
      gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_CONTRAST:
Packit 971217
      xvimagesink->config.contrast = g_value_get_int (value);
Packit 971217
      xvimagesink->config.cb_changed = TRUE;
Packit 971217
      gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_BRIGHTNESS:
Packit 971217
      xvimagesink->config.brightness = g_value_get_int (value);
Packit 971217
      xvimagesink->config.cb_changed = TRUE;
Packit 971217
      gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_SATURATION:
Packit 971217
      xvimagesink->config.saturation = g_value_get_int (value);
Packit 971217
      xvimagesink->config.cb_changed = TRUE;
Packit 971217
      gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_DISPLAY:
Packit 971217
      g_free (xvimagesink->config.display_name);
Packit 971217
      xvimagesink->config.display_name = g_strdup (g_value_get_string (value));
Packit 971217
      break;
Packit 971217
    case PROP_SYNCHRONOUS:
Packit 971217
      xvimagesink->synchronous = g_value_get_boolean (value);
Packit 971217
      if (xvimagesink->context) {
Packit 971217
        gst_xvcontext_set_synchronous (xvimagesink->context,
Packit 971217
            xvimagesink->synchronous);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    case PROP_PIXEL_ASPECT_RATIO:
Packit 971217
      g_free (xvimagesink->par);
Packit 971217
      xvimagesink->par = g_new0 (GValue, 1);
Packit 971217
      g_value_init (xvimagesink->par, GST_TYPE_FRACTION);
Packit 971217
      if (!g_value_transform (value, xvimagesink->par)) {
Packit 971217
        g_warning ("Could not transform string to aspect ratio");
Packit 971217
        gst_value_set_fraction (xvimagesink->par, 1, 1);
Packit 971217
      }
Packit 971217
      GST_DEBUG_OBJECT (xvimagesink, "set PAR to %d/%d",
Packit 971217
          gst_value_get_fraction_numerator (xvimagesink->par),
Packit 971217
          gst_value_get_fraction_denominator (xvimagesink->par));
Packit 971217
      break;
Packit 971217
    case PROP_FORCE_ASPECT_RATIO:
Packit 971217
      xvimagesink->keep_aspect = g_value_get_boolean (value);
Packit 971217
      break;
Packit 971217
    case PROP_HANDLE_EVENTS:
Packit 971217
      gst_xv_image_sink_set_event_handling (GST_VIDEO_OVERLAY (xvimagesink),
Packit 971217
          g_value_get_boolean (value));
Packit 971217
      gst_xv_image_sink_manage_event_thread (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_DEVICE:
Packit 971217
      xvimagesink->config.adaptor_nr = atoi (g_value_get_string (value));
Packit 971217
      break;
Packit 971217
    case PROP_HANDLE_EXPOSE:
Packit 971217
      xvimagesink->handle_expose = g_value_get_boolean (value);
Packit 971217
      gst_xv_image_sink_manage_event_thread (xvimagesink);
Packit 971217
      break;
Packit 971217
    case PROP_DOUBLE_BUFFER:
Packit 971217
      xvimagesink->double_buffer = g_value_get_boolean (value);
Packit 971217
      break;
Packit 971217
    case PROP_AUTOPAINT_COLORKEY:
Packit 971217
      xvimagesink->config.autopaint_colorkey = g_value_get_boolean (value);
Packit 971217
      break;
Packit 971217
    case PROP_COLORKEY:
Packit 971217
      xvimagesink->config.colorkey = g_value_get_int (value);
Packit 971217
      break;
Packit 971217
    case PROP_DRAW_BORDERS:
Packit 971217
      xvimagesink->draw_borders = g_value_get_boolean (value);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value))
Packit 971217
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_get_property (GObject * object, guint prop_id,
Packit 971217
    GValue * value, GParamSpec * pspec)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
Packit 971217
  g_return_if_fail (GST_IS_XV_IMAGE_SINK (object));
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (object);
Packit 971217
Packit 971217
  switch (prop_id) {
Packit 971217
    case PROP_HUE:
Packit 971217
      g_value_set_int (value, xvimagesink->config.hue);
Packit 971217
      break;
Packit 971217
    case PROP_CONTRAST:
Packit 971217
      g_value_set_int (value, xvimagesink->config.contrast);
Packit 971217
      break;
Packit 971217
    case PROP_BRIGHTNESS:
Packit 971217
      g_value_set_int (value, xvimagesink->config.brightness);
Packit 971217
      break;
Packit 971217
    case PROP_SATURATION:
Packit 971217
      g_value_set_int (value, xvimagesink->config.saturation);
Packit 971217
      break;
Packit 971217
    case PROP_DISPLAY:
Packit 971217
      g_value_set_string (value, xvimagesink->config.display_name);
Packit 971217
      break;
Packit 971217
    case PROP_SYNCHRONOUS:
Packit 971217
      g_value_set_boolean (value, xvimagesink->synchronous);
Packit 971217
      break;
Packit 971217
    case PROP_PIXEL_ASPECT_RATIO:
Packit 971217
      if (xvimagesink->par)
Packit 971217
        g_value_transform (xvimagesink->par, value);
Packit 971217
      break;
Packit 971217
    case PROP_FORCE_ASPECT_RATIO:
Packit 971217
      g_value_set_boolean (value, xvimagesink->keep_aspect);
Packit 971217
      break;
Packit 971217
    case PROP_HANDLE_EVENTS:
Packit 971217
      g_value_set_boolean (value, xvimagesink->handle_events);
Packit 971217
      break;
Packit 971217
    case PROP_DEVICE:
Packit 971217
    {
Packit 971217
      char *adaptor_nr_s =
Packit 971217
          g_strdup_printf ("%u", xvimagesink->config.adaptor_nr);
Packit 971217
Packit 971217
      g_value_set_string (value, adaptor_nr_s);
Packit 971217
      g_free (adaptor_nr_s);
Packit 971217
      break;
Packit 971217
    }
Packit 971217
    case PROP_DEVICE_NAME:
Packit 971217
      if (xvimagesink->context && xvimagesink->context->adaptors) {
Packit 971217
        g_value_set_string (value,
Packit 971217
            xvimagesink->context->adaptors[xvimagesink->config.adaptor_nr]);
Packit 971217
      } else {
Packit 971217
        g_value_set_string (value, NULL);
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    case PROP_HANDLE_EXPOSE:
Packit 971217
      g_value_set_boolean (value, xvimagesink->handle_expose);
Packit 971217
      break;
Packit 971217
    case PROP_DOUBLE_BUFFER:
Packit 971217
      g_value_set_boolean (value, xvimagesink->double_buffer);
Packit 971217
      break;
Packit 971217
    case PROP_AUTOPAINT_COLORKEY:
Packit 971217
      g_value_set_boolean (value, xvimagesink->config.autopaint_colorkey);
Packit 971217
      break;
Packit 971217
    case PROP_COLORKEY:
Packit 971217
      g_value_set_int (value, xvimagesink->config.colorkey);
Packit 971217
      break;
Packit 971217
    case PROP_DRAW_BORDERS:
Packit 971217
      g_value_set_boolean (value, xvimagesink->draw_borders);
Packit 971217
      break;
Packit 971217
    case PROP_WINDOW_WIDTH:
Packit 971217
      if (xvimagesink->xwindow)
Packit 971217
        g_value_set_uint64 (value, xvimagesink->xwindow->width);
Packit 971217
      else
Packit 971217
        g_value_set_uint64 (value, 0);
Packit 971217
      break;
Packit 971217
    case PROP_WINDOW_HEIGHT:
Packit 971217
      if (xvimagesink->xwindow)
Packit 971217
        g_value_set_uint64 (value, xvimagesink->xwindow->height);
Packit 971217
      else
Packit 971217
        g_value_set_uint64 (value, 0);
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 971217
      break;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
gst_xv_image_sink_open (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  GError *error = NULL;
Packit 971217
Packit 971217
  /* Initializing the XvContext unless already done through GstVideoOverlay */
Packit 971217
  if (!xvimagesink->context) {
Packit 971217
    GstXvContext *context;
Packit 971217
    if (!(context = gst_xvcontext_new (&xvimagesink->config, &error)))
Packit 971217
      goto no_context;
Packit 971217
Packit 971217
    GST_OBJECT_LOCK (xvimagesink);
Packit 971217
    xvimagesink->context = context;
Packit 971217
  } else
Packit 971217
    GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  /* make an allocator for this context */
Packit 971217
  xvimagesink->allocator = gst_xvimage_allocator_new (xvimagesink->context);
Packit 971217
  GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
  /* update object's par with calculated one if not set yet */
Packit 971217
  if (!xvimagesink->par) {
Packit 971217
    xvimagesink->par = g_new0 (GValue, 1);
Packit 971217
    gst_value_init_and_copy (xvimagesink->par, xvimagesink->context->par);
Packit 971217
    GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR");
Packit 971217
  }
Packit 971217
  /* call XSynchronize with the current value of synchronous */
Packit 971217
  gst_xvcontext_set_synchronous (xvimagesink->context,
Packit 971217
      xvimagesink->synchronous);
Packit 971217
  gst_xv_image_sink_update_colorbalance (xvimagesink);
Packit 971217
  gst_xv_image_sink_manage_event_thread (xvimagesink);
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
Packit 971217
no_context:
Packit 971217
  {
Packit 971217
    gst_element_message_full (GST_ELEMENT (xvimagesink), GST_MESSAGE_ERROR,
Packit 971217
        error->domain, error->code, g_strdup ("Could not initialise Xv output"),
Packit 971217
        g_strdup (error->message), __FILE__, GST_FUNCTION, __LINE__);
Packit 971217
    g_clear_error (&error);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_close (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  GThread *thread;
Packit 971217
  GstXvContext *context;
Packit 971217
Packit 971217
  GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  xvimagesink->running = FALSE;
Packit 971217
  /* grab thread and mark it as NULL */
Packit 971217
  thread = xvimagesink->event_thread;
Packit 971217
  xvimagesink->event_thread = NULL;
Packit 971217
  GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
  /* Wait for our event thread to finish before we clean up our stuff. */
Packit 971217
  if (thread)
Packit 971217
    g_thread_join (thread);
Packit 971217
Packit 971217
  if (xvimagesink->cur_image) {
Packit 971217
    gst_buffer_unref (xvimagesink->cur_image);
Packit 971217
    xvimagesink->cur_image = NULL;
Packit 971217
  }
Packit 971217
Packit 971217
  g_mutex_lock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  if (xvimagesink->pool) {
Packit 971217
    gst_object_unref (xvimagesink->pool);
Packit 971217
    xvimagesink->pool = NULL;
Packit 971217
  }
Packit 971217
Packit 971217
  if (xvimagesink->xwindow) {
Packit 971217
    gst_xwindow_clear (xvimagesink->xwindow);
Packit 971217
    gst_xwindow_destroy (xvimagesink->xwindow);
Packit 971217
    xvimagesink->xwindow = NULL;
Packit 971217
  }
Packit 971217
  g_mutex_unlock (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  if (xvimagesink->allocator) {
Packit 971217
    gst_object_unref (xvimagesink->allocator);
Packit 971217
    xvimagesink->allocator = NULL;
Packit 971217
  }
Packit 971217
Packit 971217
  GST_OBJECT_LOCK (xvimagesink);
Packit 971217
  /* grab context and mark it as NULL */
Packit 971217
  context = xvimagesink->context;
Packit 971217
  xvimagesink->context = NULL;
Packit 971217
  GST_OBJECT_UNLOCK (xvimagesink);
Packit 971217
Packit 971217
  if (context)
Packit 971217
    gst_xvcontext_unref (context);
Packit 971217
}
Packit 971217
Packit 971217
/* Finalize is called only once, dispose can be called multiple times.
Packit 971217
 * We use mutexes and don't reset stuff to NULL here so let's register
Packit 971217
 * as a finalize. */
Packit 971217
static void
Packit 971217
gst_xv_image_sink_finalize (GObject * object)
Packit 971217
{
Packit 971217
  GstXvImageSink *xvimagesink;
Packit 971217
Packit 971217
  xvimagesink = GST_XV_IMAGE_SINK (object);
Packit 971217
Packit 971217
  gst_xv_image_sink_close (xvimagesink);
Packit 971217
Packit 971217
  gst_xvcontext_config_clear (&xvimagesink->config);
Packit 971217
Packit 971217
  if (xvimagesink->par) {
Packit 971217
    g_free (xvimagesink->par);
Packit 971217
    xvimagesink->par = NULL;
Packit 971217
  }
Packit 971217
  g_mutex_clear (&xvimagesink->flow_lock);
Packit 971217
  g_free (xvimagesink->media_title);
Packit 971217
Packit 971217
  G_OBJECT_CLASS (parent_class)->finalize (object);
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_init (GstXvImageSink * xvimagesink)
Packit 971217
{
Packit 971217
  xvimagesink->config.display_name = NULL;
Packit 971217
  xvimagesink->config.adaptor_nr = 0;
Packit 971217
  xvimagesink->config.autopaint_colorkey = TRUE;
Packit 971217
  xvimagesink->config.double_buffer = TRUE;
Packit 971217
  /* on 16bit displays this becomes r,g,b = 1,2,3
Packit 971217
   * on 24bit displays this becomes r,g,b = 8,8,16
Packit 971217
   * as a port atom value */
Packit 971217
  xvimagesink->config.colorkey = (8 << 16) | (8 << 8) | 16;
Packit 971217
  xvimagesink->config.hue = xvimagesink->config.saturation = 0;
Packit 971217
  xvimagesink->config.contrast = xvimagesink->config.brightness = 0;
Packit 971217
  xvimagesink->config.cb_changed = FALSE;
Packit 971217
Packit 971217
  xvimagesink->context = NULL;
Packit 971217
  xvimagesink->xwindow = NULL;
Packit 971217
  xvimagesink->cur_image = NULL;
Packit 971217
Packit 971217
  xvimagesink->fps_n = 0;
Packit 971217
  xvimagesink->fps_d = 0;
Packit 971217
  xvimagesink->video_width = 0;
Packit 971217
  xvimagesink->video_height = 0;
Packit 971217
Packit 971217
  g_mutex_init (&xvimagesink->flow_lock);
Packit 971217
Packit 971217
  xvimagesink->pool = NULL;
Packit 971217
Packit 971217
  xvimagesink->synchronous = FALSE;
Packit 971217
  xvimagesink->running = FALSE;
Packit 971217
  xvimagesink->keep_aspect = TRUE;
Packit 971217
  xvimagesink->handle_events = TRUE;
Packit 971217
  xvimagesink->par = NULL;
Packit 971217
  xvimagesink->handle_expose = TRUE;
Packit 971217
Packit 971217
  xvimagesink->draw_borders = TRUE;
Packit 971217
}
Packit 971217
Packit 971217
static void
Packit 971217
gst_xv_image_sink_class_init (GstXvImageSinkClass * klass)
Packit 971217
{
Packit 971217
  GObjectClass *gobject_class;
Packit 971217
  GstElementClass *gstelement_class;
Packit 971217
  GstBaseSinkClass *gstbasesink_class;
Packit 971217
  GstVideoSinkClass *videosink_class;
Packit 971217
Packit 971217
  gobject_class = (GObjectClass *) klass;
Packit 971217
  gstelement_class = (GstElementClass *) klass;
Packit 971217
  gstbasesink_class = (GstBaseSinkClass *) klass;
Packit 971217
  videosink_class = (GstVideoSinkClass *) klass;
Packit 971217
Packit 971217
  parent_class = g_type_class_peek_parent (klass);
Packit 971217
Packit 971217
  gobject_class->set_property = gst_xv_image_sink_set_property;
Packit 971217
  gobject_class->get_property = gst_xv_image_sink_get_property;
Packit 971217
Packit 971217
  g_object_class_install_property (gobject_class, PROP_CONTRAST,
Packit 971217
      g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
Packit 971217
          -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
Packit 971217
      g_param_spec_int ("brightness", "Brightness",
Packit 971217
          "The brightness of the video", -1000, 1000, 0,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_HUE,
Packit 971217
      g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_SATURATION,
Packit 971217
      g_param_spec_int ("saturation", "Saturation",
Packit 971217
          "The saturation of the video", -1000, 1000, 0,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_DISPLAY,
Packit 971217
      g_param_spec_string ("display", "Display", "X Display name", NULL,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
Packit 971217
      g_param_spec_boolean ("synchronous", "Synchronous",
Packit 971217
          "When enabled, runs the X display in synchronous mode. "
Packit 971217
          "(unrelated to A/V sync, used only for debugging)", FALSE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
Packit 971217
      g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
Packit 971217
          "The pixel aspect ratio of the device", "1/1",
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
Packit 971217
      g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
Packit 971217
          "When enabled, scaling will respect original aspect ratio", TRUE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS,
Packit 971217
      g_param_spec_boolean ("handle-events", "Handle XEvents",
Packit 971217
          "When enabled, XEvents will be selected and handled", TRUE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_DEVICE,
Packit 971217
      g_param_spec_string ("device", "Adaptor number",
Packit 971217
          "The number of the video adaptor", "0",
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
Packit 971217
      g_param_spec_string ("device-name", "Adaptor name",
Packit 971217
          "The name of the video adaptor", NULL,
Packit 971217
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  gst_video_overlay_install_properties (gobject_class, PROP_LAST);
Packit 971217
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:handle-expose
Packit 971217
   *
Packit 971217
   * When enabled, the current frame will always be drawn in response to X
Packit 971217
   * Expose.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE,
Packit 971217
      g_param_spec_boolean ("handle-expose", "Handle expose",
Packit 971217
          "When enabled, "
Packit 971217
          "the current frame will always be drawn in response to X Expose "
Packit 971217
          "events", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:double-buffer
Packit 971217
   *
Packit 971217
   * Whether to double-buffer the output.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
Packit 971217
      g_param_spec_boolean ("double-buffer", "Double-buffer",
Packit 971217
          "Whether to double-buffer the output", TRUE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:autopaint-colorkey
Packit 971217
   *
Packit 971217
   * Whether to autofill overlay with colorkey
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
Packit 971217
      g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
Packit 971217
          "Whether to autofill overlay with colorkey", TRUE,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:colorkey
Packit 971217
   *
Packit 971217
   * Color to use for the overlay mask.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_COLORKEY,
Packit 971217
      g_param_spec_int ("colorkey", "Colorkey",
Packit 971217
          "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
Packit 971217
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:draw-borders
Packit 971217
   *
Packit 971217
   * Draw black borders when using GstXvImageSink:force-aspect-ratio to fill
Packit 971217
   * unused parts of the video area.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_DRAW_BORDERS,
Packit 971217
      g_param_spec_boolean ("draw-borders", "Draw Borders",
Packit 971217
          "Draw black borders to fill unused area in force-aspect-ratio mode",
Packit 971217
          TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:window-width
Packit 971217
   *
Packit 971217
   * Actual width of the video window.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_WINDOW_WIDTH,
Packit 971217
      g_param_spec_uint64 ("window-width", "window-width",
Packit 971217
          "Width of the window", 0, G_MAXUINT64, 0,
Packit 971217
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  /**
Packit 971217
   * GstXvImageSink:window-height
Packit 971217
   *
Packit 971217
   * Actual height of the video window.
Packit 971217
   */
Packit 971217
  g_object_class_install_property (gobject_class, PROP_WINDOW_HEIGHT,
Packit 971217
      g_param_spec_uint64 ("window-height", "window-height",
Packit 971217
          "Height of the window", 0, G_MAXUINT64, 0,
Packit 971217
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 971217
Packit 971217
  gobject_class->finalize = gst_xv_image_sink_finalize;
Packit 971217
Packit 971217
  gst_element_class_set_static_metadata (gstelement_class,
Packit 971217
      "Video sink", "Sink/Video",
Packit 971217
      "A Xv based videosink", "Julien Moutte <julien@moutte.net>");
Packit 971217
Packit 971217
  gst_element_class_add_static_pad_template (gstelement_class,
Packit 971217
      &gst_xv_image_sink_sink_template_factory);
Packit 971217
Packit 971217
  gstelement_class->change_state =
Packit 971217
      GST_DEBUG_FUNCPTR (gst_xv_image_sink_change_state);
Packit 971217
Packit 971217
  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xv_image_sink_getcaps);
Packit 971217
  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xv_image_sink_setcaps);
Packit 971217
  gstbasesink_class->get_times =
Packit 971217
      GST_DEBUG_FUNCPTR (gst_xv_image_sink_get_times);
Packit 971217
  gstbasesink_class->propose_allocation =
Packit 971217
      GST_DEBUG_FUNCPTR (gst_xv_image_sink_propose_allocation);
Packit 971217
  gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xv_image_sink_event);
Packit 971217
Packit 971217
  videosink_class->show_frame =
Packit 971217
      GST_DEBUG_FUNCPTR (gst_xv_image_sink_show_frame);
Packit 971217
}