rfbsrc: port to 1.0

https://bugzilla.gnome.org/show_bug.cgi?id=700038
This commit is contained in:
Aleix Conchillo Flaque 2013-05-09 16:41:32 -07:00 committed by Tim-Philipp Müller
parent 275e104be6
commit 42783e676e
4 changed files with 146 additions and 60 deletions

View file

@ -339,7 +339,6 @@ dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED=" cdxaparse \ GST_PLUGINS_NONPORTED=" cdxaparse \
dccp faceoverlay \ dccp faceoverlay \
hdvparse ivfparse jp2kdecimator \ hdvparse ivfparse jp2kdecimator \
librfb \
mve mythtv nsf nuvdemux \ mve mythtv nsf nuvdemux \
patchdetect real \ patchdetect real \
sdi stereo tta \ sdi stereo tta \
@ -428,7 +427,7 @@ if test "x$HAVE_CPU_I386" != "xyes" && test "x$HAVE_CPU_X86_64" != "xyes"; then
fi fi
dnl disable gst plugins we might not be able to build on this 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 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([sys/socket.h], HAVE_SYS_SOCKET_H=yes)
AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes) AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes)

View file

@ -5,7 +5,8 @@ plugin_LTLIBRARIES = libgstrfbsrc.la
libgstrfbsrc_la_SOURCES = gstrfbsrc.c libgstrfbsrc_la_SOURCES = gstrfbsrc.c
libgstrfbsrc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) -I$(srcdir)/.. 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_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstrfbsrc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) libgstrfbsrc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
@ -29,14 +30,14 @@ noinst_HEADERS = \
Android.mk: Makefile.am $(BUILT_SOURCES) Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \ androgenizer \
-:PROJECT libgstlibrfb -:SHARED libgstlibrfb \ -:PROJECT libgstrfbsrc -:SHARED libgstrfbsrc \
-:TAGS eng debug \ -:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libgstlibrfb_la_SOURCES) \ -:SOURCES $(libgstrfbsrc_la_SOURCES) \
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstlibrfb_la_CFLAGS) \ -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrfbsrc_la_CFLAGS) \
-:LDFLAGS $(libgstlibrfb_la_LDFLAGS) \ -:LDFLAGS $(libgstrfbsrc_la_LDFLAGS) \
$(libgstlibrfb_la_LIBADD) \ $(libgstrfbsrc_la_LIBADD) \
-ldl \ -ldl \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-$(GST_API_VERSION)' \
> $@ > $@

View file

@ -60,19 +60,15 @@ GST_DEBUG_CATEGORY (rfbdecoder_debug);
#define GST_CAT_DEFAULT rfbsrc_debug #define GST_CAT_DEFAULT rfbsrc_debug
static GstStaticPadTemplate gst_rfb_src_template = static GstStaticPadTemplate gst_rfb_src_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-rgb, " GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")
"bpp = (int) [1, 255], " "; " GST_VIDEO_CAPS_MAKE ("BGR")
"depth = (int) [1, 255], " "; " GST_VIDEO_CAPS_MAKE ("RGBx")
"endianness = (int) [1234, 4321], " "; " GST_VIDEO_CAPS_MAKE ("BGRx")
"red_mask = (int) [min, max], " "; " GST_VIDEO_CAPS_MAKE ("xRGB")
"green_mask = (int) [min, max], " "; " GST_VIDEO_CAPS_MAKE ("xBGR")));
"blue_mask = (int) [min, max], "
"width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (fraction) 0/1")
);
static void gst_rfb_src_finalize (GObject * object); static void gst_rfb_src_finalize (GObject * object);
static void gst_rfb_src_set_property (GObject * object, guint prop_id, 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, static void gst_rfb_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); 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_start (GstBaseSrc * bsrc);
static gboolean gst_rfb_src_stop (GstBaseSrc * bsrc); static gboolean gst_rfb_src_stop (GstBaseSrc * bsrc);
static gboolean gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event); static gboolean gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event);
static GstFlowReturn gst_rfb_src_create (GstPushSrc * psrc, static GstFlowReturn gst_rfb_src_create (GstPushSrc * psrc,
GstBuffer ** outbuf); GstBuffer ** outbuf);
GST_BOILERPLATE (GstRfbSrc, gst_rfb_src, GstPushSrc, GST_TYPE_PUSH_SRC); #define gst_rfb_src_parent_class parent_class
G_DEFINE_TYPE (GstRfbSrc, gst_rfb_src, 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>");
}
static void static void
gst_rfb_src_class_init (GstRfbSrcClass * klass) gst_rfb_src_class_init (GstRfbSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstBaseSrcClass *gstbasesrc_class; GstBaseSrcClass *gstbasesrc_class;
GstElementClass *gstelement_class;
GstPushSrcClass *gstpushsrc_class; GstPushSrcClass *gstpushsrc_class;
GST_DEBUG_CATEGORY_INIT (rfbsrc_debug, "rfbsrc", 0, "rfb src element"); GST_DEBUG_CATEGORY_INIT (rfbsrc_debug, "rfbsrc", 0, "rfb src element");
GST_DEBUG_CATEGORY_INIT (rfbdecoder_debug, "rfbdecoder", 0, "rfb decoder"); 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", g_param_spec_boolean ("view-only", "Only view the desktop",
"only view the desktop", FALSE, "only view the desktop", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 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->start = GST_DEBUG_FUNCPTR (gst_rfb_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rfb_src_stop); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_rfb_src_stop);
gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_rfb_src_event); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_rfb_src_event);
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_rfb_src_create); 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 static void
gst_rfb_src_init (GstRfbSrc * src, GstRfbSrcClass * klass) gst_rfb_src_init (GstRfbSrc * src)
{ {
GstBaseSrc *bsrc = GST_BASE_SRC (src); GstBaseSrc *bsrc = GST_BASE_SRC (src);
@ -190,6 +187,8 @@ gst_rfb_src_init (GstRfbSrc * src, GstRfbSrcClass * klass)
src->view_only = FALSE; src->view_only = FALSE;
src->pool = NULL;
src->decoder = rfb_decoder_new (); src->decoder = rfb_decoder_new ();
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -209,6 +208,10 @@ gst_rfb_src_finalize (GObject * object)
GstRfbSrc *src = GST_RFB_SRC (object); GstRfbSrc *src = GST_RFB_SRC (object);
g_free (src->host); g_free (src->host);
if (src->pool) {
gst_object_unref (src->pool);
src->pool = NULL;
}
if (src->decoder) { if (src->decoder) {
rfb_decoder_free (src->decoder); rfb_decoder_free (src->decoder);
g_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 static gboolean
gst_rfb_src_start (GstBaseSrc * bsrc) gst_rfb_src_start (GstBaseSrc * bsrc)
{ {
GstRfbSrc *src = GST_RFB_SRC (bsrc); GstRfbSrc *src = GST_RFB_SRC (bsrc);
RfbDecoder *decoder; RfbDecoder *decoder;
GstCaps *caps; GstCaps *caps;
GstVideoInfo vinfo;
GstVideoFormat vformat;
guint32 red_mask, green_mask, blue_mask; guint32 red_mask, green_mask, blue_mask;
decoder = src->decoder; 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", GST_DEBUG_OBJECT (src, "setting caps width to %d and height to %d",
decoder->rect_width, decoder->rect_height); 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; red_mask = decoder->red_max << decoder->red_shift;
green_mask = decoder->green_max << decoder->green_shift; green_mask = decoder->green_max << decoder->green_shift;
blue_mask = decoder->blue_max << decoder->blue_shift; blue_mask = decoder->blue_max << decoder->blue_shift;
gst_caps_set_simple (caps, "width", G_TYPE_INT, decoder->rect_width, vformat = gst_video_format_from_masks (decoder->depth, decoder->bpp,
"height", G_TYPE_INT, decoder->rect_height, decoder->big_endian ? G_BIG_ENDIAN : G_LITTLE_ENDIAN,
"bpp", G_TYPE_INT, decoder->bpp, red_mask, green_mask, blue_mask, 0);
"depth", G_TYPE_INT, decoder->depth,
"endianness", G_TYPE_INT, G_BIG_ENDIAN, gst_video_info_init (&vinfo);
"red_mask", G_TYPE_INT, GST_READ_UINT32_BE (&red_mask),
"green_mask", G_TYPE_INT, GST_READ_UINT32_BE (&green_mask), gst_video_info_set_format (&vinfo, vformat, decoder->rect_width,
"blue_mask", G_TYPE_INT, GST_READ_UINT32_BE (&blue_mask), NULL); decoder->rect_height);
caps = gst_video_info_to_caps (&vinfo);
gst_pad_set_caps (GST_BASE_SRC_PAD (bsrc), caps); gst_pad_set_caps (GST_BASE_SRC_PAD (bsrc), caps);
gst_rfb_negotiate_pool (src, caps);
gst_caps_unref (caps); gst_caps_unref (caps);
return TRUE; return TRUE;
@ -445,7 +528,7 @@ gst_rfb_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
{ {
GstRfbSrc *src = GST_RFB_SRC (psrc); GstRfbSrc *src = GST_RFB_SRC (psrc);
RfbDecoder *decoder = src->decoder; RfbDecoder *decoder = src->decoder;
gulong newsize; GstMapInfo info;
GstFlowReturn ret; GstFlowReturn ret;
rfb_decoder_send_update_request (decoder, src->incremental_update, 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); rfb_decoder_iterate (decoder);
} }
newsize = GST_BASE_SRC (psrc)->blocksize;
/* Create the buffer. */ /* Create the buffer. */
ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)), ret = gst_buffer_pool_acquire_buffer (src->pool, outbuf, NULL);
GST_BUFFER_OFFSET_NONE, newsize,
GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) { if (G_UNLIKELY (ret != GST_FLOW_OK)) {
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
memcpy (GST_BUFFER_DATA (*outbuf), decoder->frame, newsize); gst_buffer_map (*outbuf, &info, GST_MAP_WRITE);
GST_BUFFER_SIZE (*outbuf) = newsize;
GST_BUFFER_TIMESTAMP (*outbuf) = memcpy (info.data, decoder->frame, info.size);
GST_BUFFER_PTS (*outbuf) =
gst_clock_get_time (GST_ELEMENT_CLOCK (src)) - gst_clock_get_time (GST_ELEMENT_CLOCK (src)) -
GST_ELEMENT_CAST (src)->base_time; GST_ELEMENT_CAST (src)->base_time;
gst_buffer_unmap (*outbuf, &info);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -482,7 +565,7 @@ gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event)
GstRfbSrc *src = GST_RFB_SRC (bsrc); GstRfbSrc *src = GST_RFB_SRC (bsrc);
gdouble x, y; gdouble x, y;
gint button; gint button;
GstStructure *structure; const GstStructure *structure;
const gchar *event_type; const gchar *event_type;
gboolean key_event, key_press; gboolean key_event, key_press;
@ -495,7 +578,7 @@ gst_rfb_src_event (GstBaseSrc * bsrc, GstEvent * event)
if (src->view_only) if (src->view_only)
break; break;
structure = event->structure; structure = gst_event_get_structure (event);
event_type = gst_structure_get_string (structure, "event"); event_type = gst_structure_get_string (structure, "event");
if (strcmp (event_type, "key-press") == 0) { if (strcmp (event_type, "key-press") == 0) {

View file

@ -24,6 +24,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/base/gstpushsrc.h> #include <gst/base/gstpushsrc.h>
#include <gst/video/gstvideopool.h>
#include <librfb/rfb.h> #include <librfb/rfb.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -59,6 +60,8 @@ struct _GstRfbSrc
guint button_mask; guint button_mask;
GstBufferPool *pool;
/* protocol version */ /* protocol version */
guint version_major; guint version_major;
guint version_minor; guint version_minor;