Commit 42783e67 authored by Aleix Conchillo Flaque's avatar Aleix Conchillo Flaque Committed by Tim-Philipp Müller
parent 275e104b
......@@ -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)
......
......@@ -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)' \
> $@
......@@ -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) {
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment