rfbsrc: port to 1.0
authorAleix Conchillo Flaque <aleix@oblong.com>
Thu, 9 May 2013 23:41:32 +0000 (16:41 -0700)
committerTim-Philipp Müller <tim@centricular.net>
Fri, 10 May 2013 19:43:16 +0000 (20:43 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=700038

configure.ac
gst/librfb/Makefile.am
gst/librfb/gstrfbsrc.c
gst/librfb/gstrfbsrc.h

index 876ad96..5ae6e4e 100644 (file)
@@ -339,7 +339,6 @@ dnl Make sure you have a space before and after all plugins
 GST_PLUGINS_NONPORTED=" cdxaparse \
  dccp faceoverlay \
  hdvparse ivfparse jp2kdecimator \
- librfb \
  mve mythtv nsf nuvdemux \
  patchdetect real \
  sdi stereo tta \
@@ -428,7 +427,7 @@ if test "x$HAVE_CPU_I386" != "xyes" && test "x$HAVE_CPU_X86_64" != "xyes"; then
 fi
 
 dnl disable gst plugins we might not be able to build on this
-dnl platform: librfb (ugly but minimally invasive)
+dnl platform: (ugly but minimally invasive)
 dnl FIXME: maybe move to sys, or make work with winsock2
 AC_CHECK_HEADERS([sys/socket.h], HAVE_SYS_SOCKET_H=yes)
 AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes)
index 342bd6f..28e2c40 100644 (file)
@@ -5,7 +5,8 @@ plugin_LTLIBRARIES = libgstrfbsrc.la
 
 libgstrfbsrc_la_SOURCES = gstrfbsrc.c
 libgstrfbsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) -I$(srcdir)/..
-libgstrfbsrc_la_LIBADD = $(GST_BASE_LIBS) $(X11_LIBS) $(WINSOCK2_LIBS) librfb.la
+libgstrfbsrc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \
+       $(GST_LIBS) $(X11_LIBS) librfb.la
 libgstrfbsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstrfbsrc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
@@ -29,14 +30,14 @@ noinst_HEADERS = \
 
 Android.mk: Makefile.am $(BUILT_SOURCES)
        androgenizer \
-       -:PROJECT libgstlibrfb -:SHARED libgstlibrfb \
+       -:PROJECT libgstrfbsrc -:SHARED libgstrfbsrc \
         -:TAGS eng debug \
          -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-        -:SOURCES $(libgstlibrfb_la_SOURCES) \
-        -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstlibrfb_la_CFLAGS) \
-        -:LDFLAGS $(libgstlibrfb_la_LDFLAGS) \
-                  $(libgstlibrfb_la_LIBADD) \
+        -:SOURCES $(libgstrfbsrc_la_SOURCES) \
+        -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrfbsrc_la_CFLAGS) \
+        -:LDFLAGS $(libgstrfbsrc_la_LDFLAGS) \
+                  $(libgstrfbsrc_la_LIBADD) \
                   -ldl \
         -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-                      LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
+                      LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-$(GST_API_VERSION)' \
        > $@
index dc18e45..563f359 100644 (file)
@@ -60,19 +60,15 @@ GST_DEBUG_CATEGORY (rfbdecoder_debug);
 #define GST_CAT_DEFAULT rfbsrc_debug
 
 static GstStaticPadTemplate gst_rfb_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
+    GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-rgb, "
-        "bpp = (int) [1, 255], "
-        "depth = (int) [1, 255], "
-        "endianness = (int) [1234, 4321], "
-        "red_mask = (int) [min, max], "
-        "green_mask = (int) [min, max], "
-        "blue_mask = (int) [min, max], "
-        "width = (int) [ 16, 4096 ], "
-        "height = (int) [ 16, 4096 ], " "framerate = (fraction) 0/1")
-    );
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")
+        "; " GST_VIDEO_CAPS_MAKE ("BGR")
+        "; " GST_VIDEO_CAPS_MAKE ("RGBx")
+        "; " GST_VIDEO_CAPS_MAKE ("BGRx")
+        "; " GST_VIDEO_CAPS_MAKE ("xRGB")
+        "; " GST_VIDEO_CAPS_MAKE ("xBGR")));
 
 static void gst_rfb_src_finalize (GObject * object);
 static void gst_rfb_src_set_property (GObject * object, guint prop_id,
@@ -80,37 +76,25 @@ static void gst_rfb_src_set_property (GObject * object, guint prop_id,
 static void gst_rfb_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
+static GstCaps *gst_rfb_src_fixate (GstBaseSrc * bsrc, GstCaps * caps);
 static gboolean gst_rfb_src_start (GstBaseSrc * bsrc);
 static gboolean gst_rfb_src_stop (GstBaseSrc * bsrc);
 static gboolean gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event);
 static GstFlowReturn gst_rfb_src_create (GstPushSrc * psrc,
     GstBuffer ** outbuf);
 
-GST_BOILERPLATE (GstRfbSrc, gst_rfb_src, GstPushSrc, GST_TYPE_PUSH_SRC);
-
-static void
-gst_rfb_src_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_rfb_src_template));
-
-  gst_element_class_set_static_metadata (element_class, "Rfb source",
-      "Source/Video",
-      "Creates a rfb video stream",
-      "David A. Schleef <ds@schleef.org>, "
-      "Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>, "
-      "Thijs Vermeir <thijsvermeir@gmail.com>");
-}
+#define gst_rfb_src_parent_class parent_class
+G_DEFINE_TYPE (GstRfbSrc, gst_rfb_src, GST_TYPE_PUSH_SRC);
 
 static void
 gst_rfb_src_class_init (GstRfbSrcClass * klass)
 {
   GObjectClass *gobject_class;
   GstBaseSrcClass *gstbasesrc_class;
+  GstElementClass *gstelement_class;
   GstPushSrcClass *gstpushsrc_class;
 
+
   GST_DEBUG_CATEGORY_INIT (rfbsrc_debug, "rfbsrc", 0, "rfb src element");
   GST_DEBUG_CATEGORY_INIT (rfbdecoder_debug, "rfbdecoder", 0, "rfb decoder");
 
@@ -166,14 +150,27 @@ gst_rfb_src_class_init (GstRfbSrcClass * klass)
       g_param_spec_boolean ("view-only", "Only view the desktop",
           "only view the desktop", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_rfb_src_fixate);
   gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_rfb_src_start);
   gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rfb_src_stop);
   gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_rfb_src_event);
   gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rfb_src_create);
+
+  gstelement_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_rfb_src_template));
+
+  gst_element_class_set_static_metadata (gstelement_class, "Rfb source",
+      "Source/Video",
+      "Creates a rfb video stream",
+      "David A. Schleef <ds@schleef.org>, "
+      "Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>, "
+      "Thijs Vermeir <thijsvermeir@gmail.com>");
 }
 
 static void
-gst_rfb_src_init (GstRfbSrc * src, GstRfbSrcClass * klass)
+gst_rfb_src_init (GstRfbSrc * src)
 {
   GstBaseSrc *bsrc = GST_BASE_SRC (src);
 
@@ -190,6 +187,8 @@ gst_rfb_src_init (GstRfbSrc * src, GstRfbSrcClass * klass)
 
   src->view_only = FALSE;
 
+  src->pool = NULL;
+
   src->decoder = rfb_decoder_new ();
 
 #ifdef G_OS_WIN32
@@ -209,6 +208,10 @@ gst_rfb_src_finalize (GObject * object)
   GstRfbSrc *src = GST_RFB_SRC (object);
 
   g_free (src->host);
+  if (src->pool) {
+    gst_object_unref (src->pool);
+    src->pool = NULL;
+  }
   if (src->decoder) {
     rfb_decoder_free (src->decoder);
     g_free (src->decoder);
@@ -354,12 +357,90 @@ gst_rfb_src_get_property (GObject * object, guint prop_id,
   }
 }
 
+static GstCaps *
+gst_rfb_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
+{
+  GstRfbSrc *src = GST_RFB_SRC (bsrc);
+  RfbDecoder *decoder;
+  GstStructure *structure;
+  guint i;
+
+  decoder = src->decoder;
+
+  GST_DEBUG_OBJECT (src, "fixating caps %" GST_PTR_FORMAT, caps);
+
+  caps = gst_caps_make_writable (caps);
+
+  for (i = 0; i < gst_caps_get_size (caps); ++i) {
+    structure = gst_caps_get_structure (caps, i);
+
+    gst_structure_fixate_field_nearest_int (structure,
+        "width", decoder->rect_width);
+    gst_structure_fixate_field_nearest_int (structure,
+        "height", decoder->rect_height);
+    gst_structure_fixate_field (structure, "format");
+  }
+
+  GST_DEBUG_OBJECT (src, "fixated caps %" GST_PTR_FORMAT, caps);
+
+  caps = GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
+
+  return caps;
+}
+
+static void
+gst_rfb_negotiate_pool (GstRfbSrc * src, GstCaps * caps)
+{
+  GstQuery *query;
+  GstBufferPool *pool = NULL;
+  guint size, min, max;
+  GstStructure *config;
+
+  /* find a pool for the negotiated caps now */
+  query = gst_query_new_allocation (caps, TRUE);
+
+  if (!gst_pad_peer_query (GST_BASE_SRC_PAD (src), query)) {
+    /* not a problem, we use the defaults of query */
+    GST_DEBUG_OBJECT (src, "could not get downstream ALLOCATION hints");
+  }
+
+  if (gst_query_get_n_allocation_pools (query) > 0) {
+    /* we got configuration from our peer, parse them */
+    gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
+  } else {
+    GST_DEBUG_OBJECT (src, "didn't get downstream pool hints");
+    size = GST_BASE_SRC (src)->blocksize;
+    min = max = 0;
+  }
+
+  if (pool == NULL) {
+    /* we did not get a pool, make one ourselves then */
+    pool = gst_video_buffer_pool_new ();
+  }
+
+  if (src->pool)
+    gst_object_unref (src->pool);
+  src->pool = pool;
+
+  config = gst_buffer_pool_get_config (pool);
+  gst_buffer_pool_config_set_params (config, caps, size, min, max);
+  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+  gst_buffer_pool_set_config (pool, config);
+  // and activate
+  gst_buffer_pool_set_active (pool, TRUE);
+
+  gst_query_unref (query);
+}
+
 static gboolean
 gst_rfb_src_start (GstBaseSrc * bsrc)
 {
   GstRfbSrc *src = GST_RFB_SRC (bsrc);
   RfbDecoder *decoder;
   GstCaps *caps;
+  GstVideoInfo vinfo;
+  GstVideoFormat vformat;
   guint32 red_mask, green_mask, blue_mask;
 
   decoder = src->decoder;
@@ -398,23 +479,25 @@ gst_rfb_src_start (GstBaseSrc * bsrc)
   GST_DEBUG_OBJECT (src, "setting caps width to %d and height to %d",
       decoder->rect_width, decoder->rect_height);
 
-  caps =
-      gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (bsrc)));
-
   red_mask = decoder->red_max << decoder->red_shift;
   green_mask = decoder->green_max << decoder->green_shift;
   blue_mask = decoder->blue_max << decoder->blue_shift;
 
-  gst_caps_set_simple (caps, "width", G_TYPE_INT, decoder->rect_width,
-      "height", G_TYPE_INT, decoder->rect_height,
-      "bpp", G_TYPE_INT, decoder->bpp,
-      "depth", G_TYPE_INT, decoder->depth,
-      "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-      "red_mask", G_TYPE_INT, GST_READ_UINT32_BE (&red_mask),
-      "green_mask", G_TYPE_INT, GST_READ_UINT32_BE (&green_mask),
-      "blue_mask", G_TYPE_INT, GST_READ_UINT32_BE (&blue_mask), NULL);
+  vformat = gst_video_format_from_masks (decoder->depth, decoder->bpp,
+      decoder->big_endian ? G_BIG_ENDIAN : G_LITTLE_ENDIAN,
+      red_mask, green_mask, blue_mask, 0);
+
+  gst_video_info_init (&vinfo);
+
+  gst_video_info_set_format (&vinfo, vformat, decoder->rect_width,
+      decoder->rect_height);
+
+  caps = gst_video_info_to_caps (&vinfo);
 
   gst_pad_set_caps (GST_BASE_SRC_PAD (bsrc), caps);
+
+  gst_rfb_negotiate_pool (src, caps);
+
   gst_caps_unref (caps);
 
   return TRUE;
@@ -445,7 +528,7 @@ gst_rfb_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
 {
   GstRfbSrc *src = GST_RFB_SRC (psrc);
   RfbDecoder *decoder = src->decoder;
-  gulong newsize;
+  GstMapInfo info;
   GstFlowReturn ret;
 
   rfb_decoder_send_update_request (decoder, src->incremental_update,
@@ -456,23 +539,23 @@ gst_rfb_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
     rfb_decoder_iterate (decoder);
   }
 
-  newsize = GST_BASE_SRC (psrc)->blocksize;
-
   /* Create the buffer. */
-  ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
-      GST_BUFFER_OFFSET_NONE, newsize,
-      GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf);
+  ret = gst_buffer_pool_acquire_buffer (src->pool, outbuf, NULL);
 
   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
     return GST_FLOW_ERROR;
   }
 
-  memcpy (GST_BUFFER_DATA (*outbuf), decoder->frame, newsize);
-  GST_BUFFER_SIZE (*outbuf) = newsize;
-  GST_BUFFER_TIMESTAMP (*outbuf) =
+  gst_buffer_map (*outbuf, &info, GST_MAP_WRITE);
+
+  memcpy (info.data, decoder->frame, info.size);
+
+  GST_BUFFER_PTS (*outbuf) =
       gst_clock_get_time (GST_ELEMENT_CLOCK (src)) -
       GST_ELEMENT_CAST (src)->base_time;
 
+  gst_buffer_unmap (*outbuf, &info);
+
   return GST_FLOW_OK;
 }
 
@@ -482,7 +565,7 @@ gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event)
   GstRfbSrc *src = GST_RFB_SRC (bsrc);
   gdouble x, y;
   gint button;
-  GstStructure *structure;
+  const GstStructure *structure;
   const gchar *event_type;
   gboolean key_event, key_press;
 
@@ -495,7 +578,7 @@ gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event)
       if (src->view_only)
         break;
 
-      structure = event->structure;
+      structure = gst_event_get_structure (event);
       event_type = gst_structure_get_string (structure, "event");
 
       if (strcmp (event_type, "key-press") == 0) {
index 4d9cbe4..a85dc6e 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstpushsrc.h>
+#include <gst/video/gstvideopool.h>
 #include <librfb/rfb.h>
 
 G_BEGIN_DECLS
@@ -59,6 +60,8 @@ struct _GstRfbSrc
 
   guint button_mask;
 
+  GstBufferPool *pool;
+
   /* protocol version */
   guint version_major;
   guint version_minor;