From 42783e676e34de906491df97bc13012766d7d108 Mon Sep 17 00:00:00 2001 From: Aleix Conchillo Flaque Date: Thu, 9 May 2013 16:41:32 -0700 Subject: [PATCH] rfbsrc: port to 1.0 https://bugzilla.gnome.org/show_bug.cgi?id=700038 --- configure.ac | 3 +- gst/librfb/Makefile.am | 15 ++-- gst/librfb/gstrfbsrc.c | 185 +++++++++++++++++++++++++++++------------ gst/librfb/gstrfbsrc.h | 3 + 4 files changed, 146 insertions(+), 60 deletions(-) diff --git a/configure.ac b/configure.ac index 876ad96587..5ae6e4e35a 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/gst/librfb/Makefile.am b/gst/librfb/Makefile.am index 342bd6f69d..28e2c404b7 100644 --- a/gst/librfb/Makefile.am +++ b/gst/librfb/Makefile.am @@ -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)' \ > $@ diff --git a/gst/librfb/gstrfbsrc.c b/gst/librfb/gstrfbsrc.c index dc18e45cab..563f35974a 100644 --- a/gst/librfb/gstrfbsrc.c +++ b/gst/librfb/gstrfbsrc.c @@ -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 , " - "Andre Moreira Magalhaes , " - "Thijs Vermeir "); -} +#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 , " + "Andre Moreira Magalhaes , " + "Thijs Vermeir "); } 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) { diff --git a/gst/librfb/gstrfbsrc.h b/gst/librfb/gstrfbsrc.h index 4d9cbe4865..a85dc6eb06 100644 --- a/gst/librfb/gstrfbsrc.h +++ b/gst/librfb/gstrfbsrc.h @@ -24,6 +24,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -59,6 +60,8 @@ struct _GstRfbSrc guint button_mask; + GstBufferPool *pool; + /* protocol version */ guint version_major; guint version_minor;