sys/ximage/ximagesink.c: Add debug macros on functions.
authorJulien Moutte <julien@moutte.net>
Tue, 22 Nov 2005 09:18:56 +0000 (09:18 +0000)
committerJulien Moutte <julien@moutte.net>
Tue, 22 Nov 2005 09:18:56 +0000 (09:18 +0000)
Original commit message from CVS:
2005-11-22  Julien MOUTTE  <julien@moutte.net>

* sys/ximage/ximagesink.c: (gst_ximagesink_event_thread),
(gst_ximagesink_class_init): Add debug macros on functions.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new),
(gst_xvimagesink_xwindow_draw_borders),
(gst_xvimagesink_xvimage_put),
(gst_xvimagesink_xwindow_update_geometry),
(gst_xvimagesink_handle_xevents),
(gst_xvimagesink_get_xv_support),
(gst_xvimagesink_event_thread), (gst_xvimagesink_xcontext_get),
(gst_xvimagesink_xcontext_clear),
(gst_xvimagesink_get_format_from_caps),
(gst_xvimagesink_setcaps),
(gst_xvimagesink_change_state), (gst_xvimagesink_show_frame),
(gst_xvimagesink_buffer_alloc),
(gst_xvimagesink_set_xwindow_id),
(gst_xvimagesink_expose), (gst_xvimagesink_set_property),
(gst_xvimagesink_get_property), (gst_xvimagesink_finalize),
(gst_xvimagesink_init), (gst_xvimagesink_class_init):
* sys/xvimage/xvimagesink.h: Refactoring to handle aspect ratio,
expose while being PAUSED, out of data flow navigation events,
etc..

ChangeLog
sys/ximage/ximagesink.c
sys/xvimage/xvimagesink.c
sys/xvimage/xvimagesink.h

index 37381fd2770bfdc13b41b6f7eb77dacf043009bf..1a4ec5276002b1113588a0b9f4e1bf51d5b99375 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2005-11-22  Julien MOUTTE  <julien@moutte.net>
+
+       * sys/ximage/ximagesink.c: (gst_ximagesink_event_thread),
+       (gst_ximagesink_class_init): Add debug macros on functions.
+       * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new),
+       (gst_xvimagesink_xwindow_draw_borders),
+       (gst_xvimagesink_xvimage_put),
+       (gst_xvimagesink_xwindow_update_geometry),
+       (gst_xvimagesink_handle_xevents), (gst_xvimagesink_get_xv_support),
+       (gst_xvimagesink_event_thread), (gst_xvimagesink_xcontext_get),
+       (gst_xvimagesink_xcontext_clear),
+       (gst_xvimagesink_get_format_from_caps), (gst_xvimagesink_setcaps),
+       (gst_xvimagesink_change_state), (gst_xvimagesink_show_frame),
+       (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id),
+       (gst_xvimagesink_expose), (gst_xvimagesink_set_property),
+       (gst_xvimagesink_get_property), (gst_xvimagesink_finalize),
+       (gst_xvimagesink_init), (gst_xvimagesink_class_init):
+       * sys/xvimage/xvimagesink.h: Refactoring to handle aspect ratio,
+       expose while being PAUSED, out of data flow navigation events, etc..
+
 2005-11-22  Thomas Vander Stichele  <thomas at apestaart dot org>
 
        * gst-libs/gst/audio/audio.c: (gst_audio_duration_from_pad_buffer):
index d59d934c3d1a89a5516ddb8761f3e623607b87d2..96e600d27ee2482883cc72d821758d3451f292b8 100644 (file)
@@ -792,7 +792,6 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
 static gpointer
 gst_ximagesink_event_thread (GstXImageSink * ximagesink)
 {
-
   g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
 
   while (ximagesink->running) {
@@ -1791,12 +1790,13 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
 
   gstelement_class->change_state = gst_ximagesink_change_state;
 
-  gstbasesink_class->get_caps = gst_ximagesink_getcaps;
-  gstbasesink_class->set_caps = gst_ximagesink_setcaps;
-  gstbasesink_class->buffer_alloc = gst_ximagesink_buffer_alloc;
-  gstbasesink_class->get_times = gst_ximagesink_get_times;
-  gstbasesink_class->preroll = gst_ximagesink_show_frame;
-  gstbasesink_class->render = gst_ximagesink_show_frame;
+  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
+  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
+  gstbasesink_class->buffer_alloc =
+      GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
+  gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
+  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
+  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
 }
 
 /* ============================================================= */
index 2597f1042dedfb086f173c0827e589f7a2a4817f..2a004414e9d8f2d8dbff439ae63e1e8bdf76df4c 100644 (file)
@@ -48,6 +48,12 @@ MotifWmHints, MwmHints;
 
 static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
 
+static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
+    xvimagesink, GstXWindow * xwindow);
+static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
+    GstCaps * caps);
+static void gst_xvimagesink_expose (GstXOverlay * overlay);
+
 //static void gst_xvimagesink_send_pending_navigation (GstXvImageSink * xvimagesink);
 
 /* ElementFactory information */
@@ -81,7 +87,8 @@ enum
   ARG_SATURATION,
   ARG_DISPLAY,
   ARG_SYNCHRONOUS,
-  ARG_PIXEL_ASPECT_RATIO
+  ARG_PIXEL_ASPECT_RATIO,
+  ARG_FORCE_ASPECT_RATIO
       /* FILL ME */
 };
 
@@ -328,20 +335,33 @@ beach:
 
 /* This function handles GstXvImage creation depending on XShm availability */
 static GstXvImageBuffer *
-gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink,
-    gint width, gint height)
+gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
 {
   GstXvImageBuffer *xvimage = NULL;
+  GstStructure *structure = NULL;
   gboolean succeeded = FALSE;
 
   g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-  GST_LOG_OBJECT (xvimagesink, "creating %dx%d", width, height);
+
 
   xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
 
-  xvimage->width = width;
-  xvimage->height = height;
-  xvimage->im_format = xvimagesink->xcontext->im_format;
+  structure = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
+      !gst_structure_get_int (structure, "height", &xvimage->height)) {
+    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+  }
+
+  GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
+      xvimage->height);
+
+  /* We should probably get that from the caps as well */
+  xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
+  if (!xvimage->im_format) {
+    GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
+        GST_PTR_FORMAT, caps);
+  }
   xvimage->xvimagesink = gst_object_ref (xvimagesink);
 
   g_mutex_lock (xvimagesink->x_lock);
@@ -421,21 +441,89 @@ beach:
   return xvimage;
 }
 
+/* We are called with the x_lock taken */
+static void
+gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
+    GstXWindow * xwindow, GstVideoRectangle rect)
+{
+  g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
+  g_return_if_fail (xwindow != NULL);
+
+  XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
+      xvimagesink->xcontext->black);
+
+  /* Left border */
+  if (rect.x > 0) {
+    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
+        0, 0, rect.x, xwindow->height);
+  }
+
+  /* Right border */
+  if ((rect.x + rect.w) < xwindow->width) {
+    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
+        rect.x + rect.w, 0, xwindow->width, xwindow->height);
+  }
+
+  /* Top border */
+  if (rect.y > 0) {
+    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
+        0, 0, xwindow->width, rect.y);
+  }
+
+  /* Bottom border */
+  if ((rect.y + rect.h) < xwindow->height) {
+    XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
+        0, rect.y + rect.h, xwindow->width, xwindow->height);
+  }
+}
+
 /* This function puts a GstXvImage on a GstXvImageSink's window */
 static void
 gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
     GstXvImageBuffer * xvimage)
 {
-  g_return_if_fail (xvimage != NULL);
+  GstVideoRectangle src, dst, result;
+
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
   g_return_if_fail (xvimagesink->xwindow != NULL);
 
-  /* Store a reference to the last image we put */
-  if (xvimagesink->cur_image != xvimage)
-    xvimagesink->cur_image = xvimage;
+  if (!xvimage) {
+    return;
+  }
+
+  /* We take the flow_lock. If expose is in there we don't want to run 
+     concurrently from the data flow thread */
+  g_mutex_lock (xvimagesink->flow_lock);
+
+  /* Store a reference to the last image we put, loose the previous one */
+  if (xvimagesink->cur_image != xvimage) {
+    if (xvimagesink->cur_image) {
+      GST_DEBUG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
+      gst_buffer_unref (xvimagesink->cur_image);
+    }
+    xvimagesink->cur_image = GST_XVIMAGE_BUFFER (gst_buffer_ref (xvimage));
+  }
+
+  gst_xvimagesink_xwindow_update_geometry (xvimagesink, xvimagesink->xwindow);
+
+  src.w = xvimage->width;
+  src.h = xvimage->height;
+  dst.w = xvimagesink->xwindow->width;
+  dst.h = xvimagesink->xwindow->height;
+
+  if (xvimagesink->keep_aspect) {
+    gst_video_sink_center_rect (src, dst, &result, TRUE);
+  } else {
+    result.x = result.y = 0;
+    result.w = dst.w;
+    result.h = dst.h;
+  }
 
   g_mutex_lock (xvimagesink->x_lock);
 
+  gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow,
+      result);
+
   /* We scale to the window's geometry */
 #ifdef HAVE_XSHM
   if (xvimagesink->xcontext->use_xshm) {
@@ -448,7 +536,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         xvimagesink->xwindow->win,
         xvimagesink->xwindow->gc, xvimage->xvimage,
         0, 0, xvimage->width, xvimage->height,
-        0, 0, xvimagesink->xwindow->width, xvimagesink->xwindow->height, FALSE);
+        result.x, result.y, result.w, result.h, FALSE);
   } else
 #endif /* HAVE_XSHM */
   {
@@ -457,12 +545,14 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
         xvimagesink->xwindow->win,
         xvimagesink->xwindow->gc, xvimage->xvimage,
         0, 0, xvimage->width, xvimage->height,
-        0, 0, xvimagesink->xwindow->width, xvimagesink->xwindow->height);
+        result.x, result.y, result.w, result.h);
   }
 
   XSync (xvimagesink->xcontext->disp, FALSE);
 
   g_mutex_unlock (xvimagesink->x_lock);
+
+  g_mutex_unlock (xvimagesink->flow_lock);
 }
 
 static gboolean
@@ -574,24 +664,23 @@ gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink,
   g_free (xwindow);
 }
 
-/* This function resizes a GstXWindow.
- * The width and height are the actual pixel size on the display. */
 static void
-gst_xvimagesink_xwindow_resize (GstXvImageSink * xvimagesink,
-    GstXWindow * xwindow, guint width, guint height)
+gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink,
+    GstXWindow * xwindow)
 {
+  XWindowAttributes attr;
+
   g_return_if_fail (xwindow != NULL);
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
 
+  /* Update the window geometry */
   g_mutex_lock (xvimagesink->x_lock);
 
-  xwindow->width = width;
-  xwindow->height = height;
-
-  XResizeWindow (xvimagesink->xcontext->disp, xwindow->win,
-      xwindow->width, xwindow->height);
+  XGetWindowAttributes (xvimagesink->xcontext->disp,
+      xvimagesink->xwindow->win, &attr);
 
-  XSync (xvimagesink->xcontext->disp, FALSE);
+  xvimagesink->xwindow->width = attr.width;
+  xvimagesink->xwindow->height = attr.height;
 
   g_mutex_unlock (xvimagesink->x_lock);
 }
@@ -684,7 +773,7 @@ gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink)
    and navigation. It will also listen for configure events on the window to
    trigger caps renegotiation so on the fly software scaling can work. */
 static void
-gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
+gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
 {
   XEvent e;
   guint pointer_x = 0, pointer_y = 0;
@@ -724,22 +813,14 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
   g_mutex_lock (xvimagesink->x_lock);
   while (XCheckWindowEvent (xvimagesink->xcontext->disp,
           xvimagesink->xwindow->win,
-          StructureNotifyMask | KeyPressMask |
-          KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, &e)) {
+          KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
+          &e)) {
     KeySym keysym;
 
     /* We lock only for the X function call */
     g_mutex_unlock (xvimagesink->x_lock);
 
     switch (e.type) {
-      case ConfigureNotify:
-        /* Window got resized or moved. We update our data. */
-        GST_DEBUG ("xvimagesink window is at %d, %d with geometry : %d,%d",
-            e.xconfigure.x, e.xconfigure.y,
-            e.xconfigure.width, e.xconfigure.height);
-        xvimagesink->xwindow->width = e.xconfigure.width;
-        xvimagesink->xwindow->height = e.xconfigure.height;
-        break;
       case ButtonPress:
         /* Mouse button pressed over our window. We send upstream
            events for interactivity/navigation */
@@ -780,6 +861,35 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
     g_mutex_lock (xvimagesink->x_lock);
   }
   g_mutex_unlock (xvimagesink->x_lock);
+
+  /* Handle Expose */
+  {
+    gboolean exposed = FALSE, configured = FALSE;
+
+    g_mutex_lock (xvimagesink->x_lock);
+    while (XCheckWindowEvent (xvimagesink->xcontext->disp,
+            xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask,
+            &e)) {
+      g_mutex_unlock (xvimagesink->x_lock);
+
+      switch (e.type) {
+        case Expose:
+          exposed = TRUE;
+          break;
+        case ConfigureNotify:
+          configured = TRUE;
+        default:
+          break;
+      }
+
+      g_mutex_lock (xvimagesink->x_lock);
+    }
+    g_mutex_unlock (xvimagesink->x_lock);
+
+    if (exposed || configured) {
+      gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
+    }
+  }
 }
 
 /* This function generates a caps with all supported format by the first
@@ -889,22 +999,6 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
             "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
             "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
             "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
-
-        /* For RGB caps we store them and the image
-           format so that we can get back the format
-           when sinkconnect will give us a caps without
-           format property */
-        if (format_caps) {
-          GstXvImageFormat *format = NULL;
-
-          format = g_new0 (GstXvImageFormat, 1);
-          if (format) {
-            format->format = formats[i].id;
-            format->caps = gst_caps_copy (format_caps);
-            xcontext->formats_list =
-                g_list_append (xcontext->formats_list, format);
-          }
-        }
         break;
       }
       case XvYUV:
@@ -919,6 +1013,17 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
         break;
     }
 
+    if (format_caps) {
+      GstXvImageFormat *format = NULL;
+
+      format = g_new0 (GstXvImageFormat, 1);
+      if (format) {
+        format->format = formats[i].id;
+        format->caps = gst_caps_copy (format_caps);
+        xcontext->formats_list = g_list_append (xcontext->formats_list, format);
+      }
+    }
+
     gst_caps_append (caps, format_caps);
   }
 
@@ -938,6 +1043,21 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
   return caps;
 }
 
+static gpointer
+gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink)
+{
+  g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
+
+  while (xvimagesink->running) {
+    if (xvimagesink->xwindow) {
+      gst_xvimagesink_handle_xevents (xvimagesink);
+    }
+    g_usleep (50000);
+  }
+
+  return NULL;
+}
+
 /* This function calculates the pixel aspect ratio based on the properties
  * in the xcontext structure and stores it there. */
 static void
@@ -1155,6 +1275,10 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
 
   g_mutex_unlock (xvimagesink->x_lock);
 
+  /* Setup our event listening thread */
+  xvimagesink->event_thread = g_thread_create (
+      (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
+
   return xcontext;
 }
 
@@ -1168,6 +1292,12 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
   g_return_if_fail (xvimagesink->xcontext != NULL);
 
+  /* Wait for our event thread */
+  if (xvimagesink->event_thread) {
+    g_thread_join (xvimagesink->event_thread);
+    xvimagesink->event_thread = NULL;
+  }
+
   formats_list = xvimagesink->xcontext->formats_list;
 
   while (formats_list) {
@@ -1227,38 +1357,10 @@ gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
 
 /* Element stuff */
 
-#if 0
-static GstCaps *
-gst_xvimagesink_fixate (GstPad * pad, const GstCaps * caps)
-{
-  GstStructure *structure;
-  GstCaps *newcaps;
-
-  if (gst_caps_get_size (caps) > 1)
-    return NULL;
-
-  newcaps = gst_caps_copy (caps);
-  structure = gst_caps_get_structure (newcaps, 0);
-
-  if (gst_structure_fixate_field_nearest_int (structure, "width", 320)) {
-    return newcaps;
-  }
-  if (gst_structure_fixate_field_nearest_int (structure, "height", 240)) {
-    return newcaps;
-  }
-  if (gst_structure_fixate_field_nearest_double (structure, "framerate", 30.0)) {
-    return newcaps;
-  }
-
-  gst_caps_unref (newcaps);
-  return NULL;
-}
-#endif
-
 /* This function tries to get a format matching with a given caps in the
    supported list of formats we generated in gst_xvimagesink_get_xv_support */
 static gint
-gst_xvimagesink_get_fourcc_from_caps (GstXvImageSink * xvimagesink,
+gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
     GstCaps * caps)
 {
   GList *list = NULL;
@@ -1274,8 +1376,10 @@ gst_xvimagesink_get_fourcc_from_caps (GstXvImageSink * xvimagesink,
       GstCaps *icaps = NULL;
 
       icaps = gst_caps_intersect (caps, format->caps);
-      if (!gst_caps_is_empty (icaps))
+      if (!gst_caps_is_empty (icaps)) {
+        gst_caps_unref (icaps);
         return format->format;
+      }
     }
     list = g_list_next (list);
   }
@@ -1338,11 +1442,7 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
 
   xvimagesink->video_width = video_width;
   xvimagesink->video_height = video_height;
-  if (!gst_structure_get_fourcc (structure, "format", &im_format)) {
-    im_format =
-        gst_xvimagesink_get_fourcc_from_caps (xvimagesink,
-        gst_caps_copy (caps));
-  }
+  im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
   if (im_format == 0) {
     return FALSE;
   }
@@ -1410,12 +1510,6 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
     xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
         GST_VIDEO_SINK_WIDTH (xvimagesink),
         GST_VIDEO_SINK_HEIGHT (xvimagesink));
-  else {
-    if (xvimagesink->xwindow->internal)
-      gst_xvimagesink_xwindow_resize (xvimagesink, xvimagesink->xwindow,
-          GST_VIDEO_SINK_WIDTH (xvimagesink),
-          GST_VIDEO_SINK_HEIGHT (xvimagesink));
-  }
 
   /* We renew our xvimage only if size or format changed;
    * the xvimage is the same size as the video pixel size */
@@ -1447,6 +1541,7 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+      xvimagesink->running = TRUE;
       /* Initializing the XContext */
       if (!xvimagesink->xcontext &&
           !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink)))
@@ -1486,6 +1581,7 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
+      xvimagesink->running = FALSE;
       if (xvimagesink->xvimage) {
         gst_xvimage_buffer_free (xvimagesink->xvimage);
         xvimagesink->xvimage = NULL;
@@ -1551,7 +1647,7 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
       GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
 
       xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
-          xvimagesink->video_width, xvimagesink->video_height);
+          GST_BUFFER_CAPS (buf));
 
       if (!xvimagesink->xvimage)
         goto no_image;
@@ -1564,9 +1660,6 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
     gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
   }
 
-  gst_xvimagesink_handle_xevents (xvimagesink,
-      GST_VIDEO_SINK_PAD (xvimagesink));
-
   return GST_FLOW_OK;
 
   /* ERRORS */
@@ -1582,13 +1675,6 @@ no_image:
 
 /* Buffer management */
 
-#if 0
-static void
-gst_xvimagesink_buffer_free (GstBuffer * buffer)
-{
-}
-#endif
-
 static GstFlowReturn
 gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
@@ -1598,14 +1684,6 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 
   xvimagesink = GST_XVIMAGESINK (bsink);
 
-  /* FIXME, we should just parse the caps, and provide a buffer in this format,
-   * we should not just reconfigure ourselves yet */
-  if (caps && caps != GST_PAD_CAPS (GST_VIDEO_SINK_PAD (xvimagesink))) {
-    if (!gst_xvimagesink_setcaps (bsink, caps)) {
-      return GST_FLOW_NOT_NEGOTIATED;
-    }
-  }
-
   g_mutex_lock (xvimagesink->pool_lock);
 
   /* Walking through the pool cleaning unusable images and searching for a
@@ -1638,8 +1716,7 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
   if (!xvimage) {
     /* We found no suitable image in the pool. Creating... */
     GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
-    xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
-        xvimagesink->video_width, xvimagesink->video_height);
+    xvimage = gst_xvimagesink_xvimage_new (xvimagesink, caps);
   }
   if (xvimage) {
     gst_buffer_set_caps (GST_BUFFER (xvimage), caps);
@@ -1665,58 +1742,6 @@ gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass)
   klass->supported = gst_xvimagesink_interface_supported;
 }
 
-#if 0
-/*
- * This function is called with the stream-lock held
- */
-static void
-gst_xvimagesink_send_pending_navigation (GstXvImageSink * xvimagesink)
-{
-  GSList *cur;
-  GSList *pend_events;
-
-  g_mutex_lock (xvimagesink->nav_lock);
-  pend_events = xvimagesink->pend_nav_events;
-  xvimagesink->pend_nav_events = NULL;
-  g_mutex_unlock (xvimagesink->nav_lock);
-
-  cur = pend_events;
-  while (cur) {
-    GstEvent *event = cur->data;
-    GstStructure *structure;
-    double x, y;
-
-    if (event) {
-      structure = event->event_data.structure.structure;
-
-      if (!GST_PAD_PEER (GST_VIDEO_SINK_PAD (xvimagesink))) {
-        gst_event_unref (event);
-        cur = g_slist_next (cur);
-        continue;
-      }
-
-      /* Converting pointer coordinates to the non scaled geometry */
-      if (gst_structure_get_double (structure, "pointer_x", &x)) {
-        x *= xvimagesink->video_width;
-        x /= xvimagesink->xwindow->width;
-        gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL);
-      }
-      if (gst_structure_get_double (structure, "pointer_y", &y)) {
-        y *= xvimagesink->video_height;
-        y /= xvimagesink->xwindow->height;
-        gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL);
-      }
-
-      gst_pad_send_event (gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)),
-          event);
-    }
-    cur = g_slist_next (cur);
-  }
-
-  g_slist_free (pend_events);
-}
-#endif
-
 static void
 gst_xvimagesink_navigation_send_event (GstNavigation * navigation,
     GstStructure * structure)
@@ -1776,6 +1801,8 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
     /* we have thrown a GST_ELEMENT_ERROR now */
     return;
 
+  g_mutex_lock (xvimagesink->flow_lock);
+
   gst_xvimagesink_update_colorbalance (xvimagesink);
 
   /* Clear image pool as the images are unusable anyway */
@@ -1827,29 +1854,19 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
 
   if (xwindow)
     xvimagesink->xwindow = xwindow;
+
+  g_mutex_unlock (xvimagesink->flow_lock);
 }
 
 static void
 gst_xvimagesink_expose (GstXOverlay * overlay)
 {
-  XWindowAttributes attr;
   GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
 
   if (!xvimagesink->xwindow)
     return;
 
-  /* Update the window geometry */
-  g_mutex_lock (xvimagesink->x_lock);
-  XGetWindowAttributes (xvimagesink->xcontext->disp,
-      xvimagesink->xwindow->win, &attr);
-  g_mutex_unlock (xvimagesink->x_lock);
-
-  xvimagesink->xwindow->width = attr.width;
-  xvimagesink->xwindow->height = attr.height;
-
-  if (xvimagesink->cur_image) {
-    gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->cur_image);
-  }
+  gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->cur_image);
 }
 
 static void
@@ -2001,6 +2018,9 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
           gst_value_get_fraction_numerator (xvimagesink->par),
           gst_value_get_fraction_denominator (xvimagesink->par));
       break;
+    case ARG_FORCE_ASPECT_RATIO:
+      xvimagesink->keep_aspect = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2040,6 +2060,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
       if (xvimagesink->par)
         g_value_transform (xvimagesink->par, value);
       break;
+    case ARG_FORCE_ASPECT_RATIO:
+      g_value_set_boolean (value, xvimagesink->keep_aspect);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2069,6 +2092,10 @@ gst_xvimagesink_finalize (GObject * object)
     g_mutex_free (xvimagesink->x_lock);
     xvimagesink->x_lock = NULL;
   }
+  if (xvimagesink->flow_lock) {
+    g_mutex_free (xvimagesink->flow_lock);
+    xvimagesink->flow_lock = NULL;
+  }
   if (xvimagesink->pool_lock) {
     g_mutex_free (xvimagesink->pool_lock);
     xvimagesink->pool_lock = NULL;
@@ -2095,11 +2122,14 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
   xvimagesink->video_height = 0;
 
   xvimagesink->x_lock = g_mutex_new ();
+  xvimagesink->flow_lock = g_mutex_new ();
 
   xvimagesink->image_pool = NULL;
   xvimagesink->pool_lock = g_mutex_new ();
 
   xvimagesink->synchronous = FALSE;
+  xvimagesink->running = FALSE;
+  xvimagesink->keep_aspect = FALSE;
   xvimagesink->par = NULL;
 }
 
@@ -2153,13 +2183,16 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
   g_object_class_install_property (gobject_class, ARG_PIXEL_ASPECT_RATIO,
       g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
           "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, ARG_FORCE_ASPECT_RATIO,
+      g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
+          "When enabled, scaling will respect original aspect ratio", FALSE,
+          G_PARAM_READWRITE));
 
   gobject_class->finalize = gst_xvimagesink_finalize;
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state);
 
-  //gstbasesink_class->get_template = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_template);
   gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
   gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
   gstbasesink_class->buffer_alloc =
index 31a0b99ca4fd35643e91863b0c5386a8c795a4a5..41062f20e77c282ee69cf3a13a1df59bfd18b2cc 100644 (file)
@@ -145,6 +145,9 @@ struct _GstXvImageSink {
   gboolean cb_changed;
 
   GMutex *x_lock;
+  GMutex *flow_lock;
+  
+  GThread *event_thread;
 
   guint video_width, video_height;     /* size of incoming video;
                                         * used as the size for XvImage */
@@ -154,6 +157,8 @@ struct _GstXvImageSink {
   GSList *image_pool;
 
   gboolean synchronous;
+  gboolean running;
+  gboolean keep_aspect;
 };
 
 struct _GstXvImageSinkClass {