diff options
author | Sjoerd Simons <sjoerd@greynoise.nl> | 2013-01-18 22:49:19 +0100 |
---|---|---|
committer | Sjoerd Simons <sjoerd@luon.net> | 2013-02-11 22:04:59 +0100 |
commit | 14637e2a271222ae04356cfa7b88cb34775d2d0d (patch) | |
tree | 2e8e8c0bb888d5ae217638244f70762ec20db6cb /sys/uvch264 | |
parent | 381fcda68b079b59f6d68b4f47f24e4885d592ba (diff) | |
download | gstreamer-plugins-bad-14637e2a271222ae04356cfa7b88cb34775d2d0d.tar.gz |
uvch264src: Port to gstreamer 1.0
Diffstat (limited to 'sys/uvch264')
-rw-r--r-- | sys/uvch264/Makefile.am | 5 | ||||
-rw-r--r-- | sys/uvch264/gstuvch264.c | 2 | ||||
-rw-r--r-- | sys/uvch264/gstuvch264_mjpgdemux.c | 230 | ||||
-rw-r--r-- | sys/uvch264/gstuvch264_src.c | 274 |
4 files changed, 237 insertions, 274 deletions
diff --git a/sys/uvch264/Makefile.am b/sys/uvch264/Makefile.am index a647fa998..be99159c3 100644 --- a/sys/uvch264/Makefile.am +++ b/sys/uvch264/Makefile.am @@ -1,6 +1,3 @@ -glib_gen_prefix = __gst_uvc_h264 -glib_gen_basename = gstuvch264 - plugin_LTLIBRARIES = libgstuvch264.la libgstuvch264_la_SOURCES = gstuvch264.c \ @@ -27,7 +24,7 @@ libgstuvch264_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ $(GST_LIBS) \ $(G_UDEV_LIBS) \ $(LIBUSB_LIBS) \ - $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-$(GST_MAJORMINOR).la + $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_API_VERSION@.la noinst_HEADERS = gstuvch264_mjpgdemux.h \ gstuvch264_src.h \ diff --git a/sys/uvch264/gstuvch264.c b/sys/uvch264/gstuvch264.c index 665f04a4f..96f544f99 100644 --- a/sys/uvch264/gstuvch264.c +++ b/sys/uvch264/gstuvch264.c @@ -45,6 +45,6 @@ plugin_init (GstPlugin * plugin) GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "uvch264", + uvch264, "UVC compliant H264 encoding cameras plugin", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/uvch264/gstuvch264_mjpgdemux.c b/sys/uvch264/gstuvch264_mjpgdemux.c index ff768cb4f..28f9ce5d5 100644 --- a/sys/uvch264/gstuvch264_mjpgdemux.c +++ b/sys/uvch264/gstuvch264_mjpgdemux.c @@ -96,8 +96,8 @@ static GstStaticPadTemplate yuy2src_pad_template = GST_STATIC_PAD_TEMPLATE ("yuy2", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "format = (fourcc) YUY2, " + GST_STATIC_CAPS ("video/x-raw, " + "format = (string) YUY2, " "width = (int) [ 0, MAX ], " "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0/1, MAX ] ") ); @@ -105,8 +105,8 @@ static GstStaticPadTemplate nv12src_pad_template = GST_STATIC_PAD_TEMPLATE ("nv12", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "format = (fourcc) NV21, " + GST_STATIC_CAPS ("video/x-raw, " + "format = (string) NV21, " "width = (int) [ 0, MAX ], " "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0/1, MAX ] ") ); @@ -164,53 +164,22 @@ static void gst_uvc_h264_mjpg_demux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_uvc_h264_mjpg_demux_dispose (GObject * object); static GstFlowReturn gst_uvc_h264_mjpg_demux_chain (GstPad * pad, - GstBuffer * buffer); -static gboolean gst_uvc_h264_mjpg_demux_sink_setcaps (GstPad * pad, - GstCaps * caps); -static GstCaps *gst_uvc_h264_mjpg_demux_getcaps (GstPad * pad); + GstObject * parent, GstBuffer * buffer); +static gboolean gst_uvc_h264_mjpg_demux_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); +static gboolean gst_uvc_h264_mjpg_demux_query (GstPad * pad, + GstObject * parent, GstQuery * query); -#define _do_init(x) \ - GST_DEBUG_CATEGORY_INIT (uvc_h264_mjpg_demux_debug, \ - "uvch264_mjpgdemux", 0, "UVC H264 MJPG Demuxer"); - -GST_BOILERPLATE_FULL (GstUvcH264MjpgDemux, gst_uvc_h264_mjpg_demux, GstElement, - GST_TYPE_ELEMENT, _do_init); - -static void -gst_uvc_h264_mjpg_demux_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstPadTemplate *pt; - - /* do not use gst_element_class_add_static_pad_template to stay compatible - * with gstreamer 0.10.35 */ - pt = gst_static_pad_template_get (&mjpgsink_pad_template); - gst_element_class_add_pad_template (element_class, pt); - gst_object_unref (pt); - pt = gst_static_pad_template_get (&jpegsrc_pad_template); - gst_element_class_add_pad_template (element_class, pt); - gst_object_unref (pt); - pt = gst_static_pad_template_get (&h264src_pad_template); - gst_element_class_add_pad_template (element_class, pt); - gst_object_unref (pt); - pt = gst_static_pad_template_get (&yuy2src_pad_template); - gst_element_class_add_pad_template (element_class, pt); - gst_object_unref (pt); - pt = gst_static_pad_template_get (&nv12src_pad_template); - gst_element_class_add_pad_template (element_class, pt); - gst_object_unref (pt); - - gst_element_class_set_static_metadata (element_class, - "UVC H264 MJPG Demuxer", - "Video/Demuxer", - "Demux UVC H264 auxiliary streams from MJPG images", - "Youness Alaoui <youness.alaoui@collabora.co.uk>"); -} +#define gst_uvc_h264_mjpg_demux_parent_class parent_class +G_DEFINE_TYPE (GstUvcH264MjpgDemux, gst_uvc_h264_mjpg_demux, GST_TYPE_ELEMENT); static void gst_uvc_h264_mjpg_demux_class_init (GstUvcH264MjpgDemuxClass * klass) { GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *element_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); g_type_class_add_private (gobject_class, sizeof (GstUvcH264MjpgDemuxPrivate)); @@ -218,6 +187,26 @@ gst_uvc_h264_mjpg_demux_class_init (GstUvcH264MjpgDemuxClass * klass) gobject_class->get_property = gst_uvc_h264_mjpg_demux_get_property; gobject_class->dispose = gst_uvc_h264_mjpg_demux_dispose; + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&mjpgsink_pad_template)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&jpegsrc_pad_template)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&h264src_pad_template)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&yuy2src_pad_template)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&nv12src_pad_template)); + + gst_element_class_set_static_metadata (element_class, + "UVC H264 MJPG Demuxer", + "Video/Demuxer", + "Demux UVC H264 auxiliary streams from MJPG images", + "Youness Alaoui <youness.alaoui@collabora.co.uk>"); g_object_class_install_property (gobject_class, PROP_DEVICE_FD, g_param_spec_int ("device-fd", "device-fd", @@ -230,11 +219,13 @@ gst_uvc_h264_mjpg_demux_class_init (GstUvcH264MjpgDemuxClass * klass) " (-1 = unlimited)", 0, G_MAXINT, DEFAULT_NUM_CLOCK_SAMPLES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + GST_DEBUG_CATEGORY_INIT (uvc_h264_mjpg_demux_debug, + "uvch264_mjpgdemux", 0, "UVC H264 MJPG Demuxer"); } static void -gst_uvc_h264_mjpg_demux_init (GstUvcH264MjpgDemux * self, - GstUvcH264MjpgDemuxClass * g_class) +gst_uvc_h264_mjpg_demux_init (GstUvcH264MjpgDemux * self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_UVC_H264_MJPG_DEMUX, GstUvcH264MjpgDemuxPrivate); @@ -247,17 +238,17 @@ gst_uvc_h264_mjpg_demux_init (GstUvcH264MjpgDemux * self, gst_pad_new_from_static_template (&mjpgsink_pad_template, "sink"); gst_pad_set_chain_function (self->priv->sink_pad, GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_chain)); - gst_pad_set_setcaps_function (self->priv->sink_pad, - GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_sink_setcaps)); - gst_pad_set_getcaps_function (self->priv->sink_pad, - GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_getcaps)); + gst_pad_set_event_function (self->priv->sink_pad, + GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_sink_event)); + gst_pad_set_query_function (self->priv->sink_pad, + GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_query)); gst_element_add_pad (GST_ELEMENT (self), self->priv->sink_pad); /* JPEG */ self->priv->jpeg_pad = gst_pad_new_from_static_template (&jpegsrc_pad_template, "jpeg"); - gst_pad_set_getcaps_function (self->priv->jpeg_pad, - GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_getcaps)); + gst_pad_set_query_function (self->priv->jpeg_pad, + GST_DEBUG_FUNCPTR (gst_uvc_h264_mjpg_demux_query)); gst_element_add_pad (GST_ELEMENT (self), self->priv->jpeg_pad); /* H264 */ @@ -278,11 +269,11 @@ gst_uvc_h264_mjpg_demux_init (GstUvcH264MjpgDemux * self, gst_pad_use_fixed_caps (self->priv->nv12_pad); gst_element_add_pad (GST_ELEMENT (self), self->priv->nv12_pad); - self->priv->h264_caps = gst_caps_new_simple ("video/x-h264", NULL); - self->priv->yuy2_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), NULL); - self->priv->nv12_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '2'), NULL); + self->priv->h264_caps = gst_caps_new_empty_simple ("video/x-h264"); + self->priv->yuy2_caps = gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, "YUY2", NULL); + self->priv->nv12_caps = gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, "NV12", NULL); self->priv->h264_width = self->priv->h264_height = 0; self->priv->yuy2_width = self->priv->yuy2_height = 0; self->priv->nv12_width = self->priv->nv12_height = 0; @@ -369,31 +360,40 @@ gst_uvc_h264_mjpg_demux_get_property (GObject * object, } } - static gboolean -gst_uvc_h264_mjpg_demux_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_uvc_h264_mjpg_demux_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { - GstUvcH264MjpgDemux *self = GST_UVC_H264_MJPG_DEMUX (GST_OBJECT_PARENT (pad)); + GstUvcH264MjpgDemux *self = GST_UVC_H264_MJPG_DEMUX (parent); - return gst_pad_set_caps (self->priv->jpeg_pad, caps); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS: + return gst_pad_push_event (self->priv->jpeg_pad, event); + default: + break; + } + return gst_pad_event_default (pad, parent, event); } -static GstCaps * -gst_uvc_h264_mjpg_demux_getcaps (GstPad * pad) +static gboolean +gst_uvc_h264_mjpg_demux_query (GstPad * pad, GstObject * parent, + GstQuery * query) { - GstUvcH264MjpgDemux *self = GST_UVC_H264_MJPG_DEMUX (GST_OBJECT_PARENT (pad)); - GstCaps *result = NULL; - - if (pad == self->priv->jpeg_pad) - result = gst_pad_peer_get_caps (self->priv->sink_pad); - else if (pad == self->priv->sink_pad) - result = gst_pad_peer_get_caps (self->priv->jpeg_pad); - - /* TODO: intersect with template and fixate caps */ - if (result == NULL) - result = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + GstUvcH264MjpgDemux *self = GST_UVC_H264_MJPG_DEMUX (parent); + gboolean ret = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + if (pad == self->priv->sink_pad) + ret = gst_pad_peer_query (self->priv->jpeg_pad, query); + else + ret = gst_pad_peer_query (self->priv->sink_pad, query); + break; + default: + ret = gst_pad_query_default (pad, parent, query); + } - return result; + return ret; } static gboolean @@ -456,35 +456,37 @@ _pts_to_timestamp (GstUvcH264MjpgDemux * self, GstBuffer * buf, guint32 pts) } static GstFlowReturn -gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) +gst_uvc_h264_mjpg_demux_chain (GstPad * pad, + GstObject * parent, GstBuffer * buf) { GstUvcH264MjpgDemux *self; GstFlowReturn ret = GST_FLOW_OK; - GstBufferList *jpeg_buf = gst_buffer_list_new (); - GstBufferListIterator *jpeg_it = gst_buffer_list_iterate (jpeg_buf); - GstBufferList *aux_buf = NULL; - GstBufferListIterator *aux_it = NULL; + GstBuffer *jpeg_buf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_METADATA, + 0, 0); + GstBuffer *aux_buf = NULL; AuxiliaryStreamHeader aux_header = { 0 }; - GstBuffer *sub_buffer = NULL; guint32 aux_size = 0; GstPad *aux_pad = NULL; GstCaps **aux_caps = NULL; guint last_offset; guint i; guchar *data; - guint size; + gsize size; + GstMapInfo info; self = GST_UVC_H264_MJPG_DEMUX (GST_PAD_PARENT (pad)); last_offset = 0; - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - if (data == NULL || size == 0) { + size = gst_buffer_get_size (buf); + if (size == 0) { ret = gst_pad_push (self->priv->jpeg_pad, buf); goto done; } - gst_buffer_list_iterator_add_group (jpeg_it); + gst_buffer_map (buf, &info, GST_MAP_READ); + + data = info.data; + for (i = 0; i < size - 1; i++) { /* Check for APP4 (0xe4) marker in the jpeg */ if (data[i] == 0xff && data[i + 1] == 0xe4) { @@ -511,9 +513,9 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) /* Add JPEG data between the last offset and this market */ if (i - last_offset > 0) { - sub_buffer = gst_buffer_create_sub (buf, last_offset, i - last_offset); - gst_buffer_copy_metadata (sub_buffer, buf, GST_BUFFER_COPY_ALL); - gst_buffer_list_iterator_add (jpeg_it, sub_buffer); + GstMemory *m = gst_memory_copy (info.memory, last_offset, + i - last_offset); + gst_buffer_append_memory (jpeg_buf, m); } last_offset = i + 2 + segment_size; @@ -584,16 +586,18 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) goto done; if (*width != aux_header.width || *height != aux_header.height) { - GstCaps *peercaps = gst_pad_peer_get_caps (aux_pad); + GstCaps *peercaps = gst_pad_peer_query_caps (aux_pad, NULL); GstStructure *s = NULL; gint fps_num = 1000000000 / aux_header.frame_interval; gint fps_den = 100; /* TODO: intersect with pad template */ GST_DEBUG ("peercaps : %" GST_PTR_FORMAT, peercaps); - if (peercaps && !gst_caps_is_any (peercaps)) + if (peercaps && !gst_caps_is_any (peercaps)) { + peercaps = gst_caps_make_writable (peercaps); s = gst_caps_get_structure (peercaps, 0); - if (s) { + } + if (s && gst_structure_has_field (s, "framerate")) { /* TODO: make sure it contains the right format/width/height */ gst_structure_fixate_field_nearest_fraction (s, "framerate", fps_num, fps_den); @@ -619,9 +623,7 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) } /* Create new auxiliary buffer list and adjust i/segment size */ - aux_buf = gst_buffer_list_new (); - aux_it = gst_buffer_list_iterate (aux_buf); - gst_buffer_list_iterator_add_group (aux_it); + aux_buf = gst_buffer_new (); } i += sizeof (aux_header) + sizeof (aux_size); @@ -637,26 +639,24 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) } if (segment_size > 0) { - sub_buffer = gst_buffer_create_sub (buf, i, segment_size); - GST_BUFFER_DURATION (sub_buffer) = + GstMemory *m; + m = gst_memory_copy (info.memory, i, segment_size); + + GST_BUFFER_DURATION (aux_buf) = aux_header.frame_interval * 100 * GST_NSECOND; - gst_buffer_copy_metadata (sub_buffer, buf, GST_BUFFER_COPY_TIMESTAMPS); - gst_buffer_set_caps (sub_buffer, *aux_caps); - _pts_to_timestamp (self, sub_buffer, aux_header.pts); + _pts_to_timestamp (self, aux_buf, aux_header.pts); - gst_buffer_list_iterator_add (aux_it, sub_buffer); + gst_buffer_append_memory (aux_buf, m); aux_size -= segment_size; /* Push completed aux data */ if (aux_size == 0) { - gst_buffer_list_iterator_free (aux_it); - aux_it = NULL; GST_DEBUG_OBJECT (self, "Pushing %" GST_FOURCC_FORMAT " auxiliary buffer %" GST_PTR_FORMAT, GST_FOURCC_ARGS (aux_header.type), *aux_caps); - ret = gst_pad_push_list (aux_pad, aux_buf); + ret = gst_pad_push (aux_pad, aux_buf); aux_buf = NULL; if (ret != GST_FLOW_OK) { GST_WARNING_OBJECT (self, "Error pushing %" GST_FOURCC_FORMAT @@ -668,19 +668,17 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) i += segment_size - 1; } else if (data[i] == 0xff && data[i + 1] == 0xda) { + GstMemory *m; /* The APP4 markers must be before the SOS marker, so this is the end */ GST_DEBUG_OBJECT (self, "Found SOS marker."); - sub_buffer = gst_buffer_create_sub (buf, last_offset, size - last_offset); - gst_buffer_copy_metadata (sub_buffer, buf, GST_BUFFER_COPY_ALL); - gst_buffer_list_iterator_add (jpeg_it, sub_buffer); + m = gst_memory_copy (info.memory, last_offset, size - last_offset); + gst_buffer_append_memory (jpeg_buf, m); last_offset = size; break; } } - gst_buffer_list_iterator_free (jpeg_it); - jpeg_it = NULL; if (aux_buf != NULL) { GST_ELEMENT_ERROR (self, STREAM, DEMUX, @@ -693,10 +691,10 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) /* this means there was no SOS marker in the jpg, so we assume the JPG was just a container */ GST_DEBUG_OBJECT (self, "SOS marker wasn't found. MJPG is container only"); - gst_buffer_list_unref (jpeg_buf); + gst_buffer_unref (jpeg_buf); jpeg_buf = NULL; } else { - ret = gst_pad_push_list (self->priv->jpeg_pad, jpeg_buf); + ret = gst_pad_push (self->priv->jpeg_pad, jpeg_buf); jpeg_buf = NULL; } @@ -707,14 +705,10 @@ gst_uvc_h264_mjpg_demux_chain (GstPad * pad, GstBuffer * buf) done: /* In case of error, unref whatever was left */ - if (aux_it) - gst_buffer_list_iterator_free (aux_it); if (aux_buf) - gst_buffer_list_unref (aux_buf); - if (jpeg_it) - gst_buffer_list_iterator_free (jpeg_it); + gst_buffer_unref (aux_buf); if (jpeg_buf) - gst_buffer_list_unref (jpeg_buf); + gst_buffer_unref (jpeg_buf); /* We must always unref the input buffer since we never push it out */ gst_buffer_unref (buf); diff --git a/sys/uvch264/gstuvch264_src.c b/sys/uvch264/gstuvch264_src.c index a42039ac3..1e8e1319b 100644 --- a/sys/uvch264/gstuvch264_src.c +++ b/sys/uvch264/gstuvch264_src.c @@ -41,7 +41,6 @@ #include <string.h> #include "gstuvch264_src.h" -#include "gstuvch264-marshal.h" #include <gudev/gudev.h> #include <libusb.h> #ifndef LIBUSB_CLASS_VIDEO @@ -154,40 +153,11 @@ static guint _signals[LAST_SIGNAL]; GST_DEBUG_CATEGORY (uvc_h264_src_debug); #define GST_CAT_DEFAULT uvc_h264_src_debug -GST_BOILERPLATE (GstUvcH264Src, gst_uvc_h264_src, - GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); - -#define GST_UVC_H264_SRC_VF_CAPS_STR \ - GST_VIDEO_CAPS_RGB ";" \ - GST_VIDEO_CAPS_RGB";" \ - GST_VIDEO_CAPS_BGR";" \ - GST_VIDEO_CAPS_RGBx";" \ - GST_VIDEO_CAPS_xRGB";" \ - GST_VIDEO_CAPS_BGRx";" \ - GST_VIDEO_CAPS_xBGR";" \ - GST_VIDEO_CAPS_RGBA";" \ - GST_VIDEO_CAPS_ARGB";" \ - GST_VIDEO_CAPS_BGRA";" \ - GST_VIDEO_CAPS_ABGR";" \ - GST_VIDEO_CAPS_RGB_16";" \ - GST_VIDEO_CAPS_RGB_15";" \ - "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \ - "width = "GST_VIDEO_SIZE_RANGE" , " \ - "height = " GST_VIDEO_SIZE_RANGE ", " \ - "framerate = "GST_VIDEO_FPS_RANGE ";" \ - GST_VIDEO_CAPS_GRAY8";" \ - GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \ - GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" \ - GST_VIDEO_CAPS_YUV ("{ I420 , NV12 , NV21 , YV12 , YUY2 ," \ - " Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY ," \ - " Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420}") ";" \ - "image/jpeg, " \ - "width = " GST_VIDEO_SIZE_RANGE ", " \ - "height = " GST_VIDEO_SIZE_RANGE ", " \ - "framerate = " GST_VIDEO_FPS_RANGE +#define gst_uvc_h264_src_parent_class parent_class +G_DEFINE_TYPE (GstUvcH264Src, gst_uvc_h264_src, GST_TYPE_BASE_CAMERA_SRC); #define GST_UVC_H264_SRC_VID_CAPS_STR \ - GST_UVC_H264_SRC_VF_CAPS_STR ";" \ + GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \ "video/x-h264, " \ "width = " GST_VIDEO_SIZE_RANGE ", " \ "height = " GST_VIDEO_SIZE_RANGE ", " \ @@ -200,7 +170,7 @@ static GstStaticPadTemplate vfsrc_template = GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_UVC_H264_SRC_VF_CAPS_STR)); + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL))); static GstStaticPadTemplate imgsrc_template = GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME, @@ -220,7 +190,8 @@ static void gst_uvc_h264_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_uvc_h264_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean gst_uvc_h264_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_uvc_h264_src_event (GstPad * pad, GstObject * parent, + GstEvent * event); static gboolean gst_uvc_h264_src_send_event (GstElement * element, GstEvent * event); static gboolean gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * @@ -231,17 +202,18 @@ static gboolean gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc); static void gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc); static GstStateChangeReturn gst_uvc_h264_src_change_state (GstElement * element, GstStateChange trans); -static gboolean gst_uvc_h264_src_buffer_probe (GstPad * pad, - GstBuffer * buffer, gpointer user_data); -static gboolean gst_uvc_h264_src_event_probe (GstPad * pad, - GstEvent * event, gpointer user_data); +static GstPadProbeReturn gst_uvc_h264_src_buffer_probe (GstPad * pad, + GstPadProbeInfo * info, gpointer user_data); +static GstPadProbeReturn gst_uvc_h264_src_event_probe (GstPad * pad, + GstPadProbeInfo * info, gpointer user_data); static void gst_uvc_h264_src_pad_linking_cb (GstPad * pad, GstPad * peer, gpointer user_data); -static GstCaps *gst_uvc_h264_src_getcaps (GstPad * pad); +static gboolean gst_uvc_h264_src_query (GstPad * pad, GstObject * parent, + GstQuery * query); -static void v4l2src_prepare_format (GstElement * v4l2src, gint fd, guint fourcc, - guint width, guint height, gpointer user_data); +static void v4l2src_prepare_format (GstElement * v4l2src, gint fd, + GstCaps * caps, gpointer user_data); static void fill_probe_commit (GstUvcH264Src * self, uvcx_video_config_probe_commit_t * probe, guint32 frame_interval, guint32 width, guint32 height, guint32 profile, @@ -268,42 +240,14 @@ static gboolean gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self, gchar * property, gint * min, gint * def, gint * max); static void -gst_uvc_h264_src_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - GstPadTemplate *pt; - - GST_DEBUG_CATEGORY_INIT (uvc_h264_src_debug, "uvch264_src", - 0, "UVC H264 Compliant camera bin source"); - - gst_element_class_set_static_metadata (gstelement_class, - "UVC H264 Source", - "Source/Video", - "UVC H264 Encoding camera source", - "Youness Alaoui <youness.alaoui@collabora.co.uk>"); - - /* Don't use gst_element_class_add_static_pad_template in order to keep - * the plugin compatible with gst 0.10.35 */ - pt = gst_static_pad_template_get (&vidsrc_template); - gst_element_class_add_pad_template (gstelement_class, pt); - gst_object_unref (pt); - - pt = gst_static_pad_template_get (&imgsrc_template); - gst_element_class_add_pad_template (gstelement_class, pt); - gst_object_unref (pt); - - pt = gst_static_pad_template_get (&vfsrc_template); - gst_element_class_add_pad_template (gstelement_class, pt); - gst_object_unref (pt); -} - -static void gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; GstBaseCameraSrcClass *gstbasecamerasrc_class; + parent_class = g_type_class_peek_parent (klass); + gobject_class = G_OBJECT_CLASS (klass); gstelement_class = GST_ELEMENT_CLASS (klass); gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass); @@ -321,6 +265,24 @@ gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass) gstbasecamerasrc_class->start_capture = gst_uvc_h264_src_start_capture; gstbasecamerasrc_class->stop_capture = gst_uvc_h264_src_stop_capture; + GST_DEBUG_CATEGORY_INIT (uvc_h264_src_debug, "uvch264_src", + 0, "UVC H264 Compliant camera bin source"); + + gst_element_class_set_static_metadata (gstelement_class, + "UVC H264 Source", + "Source/Video", + "UVC H264 Encoding camera source", + "Youness Alaoui <youness.alaoui@collabora.co.uk>"); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&vidsrc_template)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&imgsrc_template)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&vfsrc_template)); + /* Properties */ g_object_class_install_property (gobject_class, PROP_COLORSPACE_NAME, g_param_spec_string ("colorspace-name", "colorspace element name", @@ -519,17 +481,16 @@ gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass) G_CALLBACK (gst_uvc_h264_src_get_int_setting), NULL, NULL, NULL, G_TYPE_BOOLEAN, 4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, 0); - } static void -gst_uvc_h264_src_init (GstUvcH264Src * self, GstUvcH264SrcClass * klass) +gst_uvc_h264_src_init (GstUvcH264Src * self) { self->vfsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, GST_PAD_SRC); - gst_pad_set_getcaps_function (self->vfsrc, - GST_DEBUG_FUNCPTR (gst_uvc_h264_src_getcaps)); + gst_pad_set_query_function (self->vfsrc, + GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query)); gst_element_add_pad (GST_ELEMENT (self), self->vfsrc); self->imgsrc = @@ -540,15 +501,15 @@ gst_uvc_h264_src_init (GstUvcH264Src * self, GstUvcH264SrcClass * klass) self->vidsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME, GST_PAD_SRC); - gst_pad_set_getcaps_function (self->vidsrc, - GST_DEBUG_FUNCPTR (gst_uvc_h264_src_getcaps)); + gst_pad_set_query_function (self->vidsrc, + GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query)); gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); - gst_pad_add_buffer_probe (self->vidsrc, - (GCallback) gst_uvc_h264_src_buffer_probe, self); - gst_pad_add_event_probe (self->vfsrc, - (GCallback) gst_uvc_h264_src_event_probe, self); - gst_pad_add_event_probe (self->vidsrc, - (GCallback) gst_uvc_h264_src_event_probe, self); + gst_pad_add_probe (self->vidsrc, GST_PAD_PROBE_TYPE_BUFFER, + gst_uvc_h264_src_buffer_probe, self, NULL); + gst_pad_add_probe (self->vfsrc, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, + gst_uvc_h264_src_event_probe, self, NULL); + gst_pad_add_probe (self->vidsrc, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, + gst_uvc_h264_src_event_probe, self, NULL); self->srcpad_event_func = GST_PAD_EVENTFUNC (self->vfsrc); @@ -1536,23 +1497,24 @@ gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self, gchar * property, return ret; } -static gboolean -gst_uvc_h264_src_event_probe (GstPad * pad, GstEvent * event, +static GstPadProbeReturn +gst_uvc_h264_src_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstUvcH264Src *self = GST_UVC_H264_SRC (user_data); - gboolean ret = TRUE; + GstPadProbeReturn ret = GST_PAD_PROBE_OK; + GstEvent *event = info->data; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: - ret = !self->reconfiguring; + ret = self->reconfiguring ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK; break; - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: if (pad == self->vidsrc) { - ret = !self->vid_newseg; + ret = self->vid_newseg ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK; self->vid_newseg = TRUE; } else if (pad == self->vfsrc) { - ret = !self->vf_newseg; + ret = self->vf_newseg ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK; self->vf_newseg = TRUE; } break; @@ -1563,11 +1525,12 @@ gst_uvc_h264_src_event_probe (GstPad * pad, GstEvent * event, return ret; } -static gboolean -gst_uvc_h264_src_buffer_probe (GstPad * pad, GstBuffer * buffer, +static GstPadProbeReturn +gst_uvc_h264_src_buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstUvcH264Src *self = GST_UVC_H264_SRC (user_data); + GstBuffer *buffer = info->data; /* TODO: Check the NALU type and make sure it is a keyframe */ if (self->key_unit_event) { @@ -1760,22 +1723,17 @@ gst_uvc_h264_src_send_event (GstElement * element, GstEvent * event) } static gboolean -gst_uvc_h264_src_event (GstPad * pad, GstEvent * event) +gst_uvc_h264_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstUvcH264Src *self = GST_UVC_H264_SRC (GST_PAD_PARENT (pad)); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: if (!self->vid_newseg && pad == self->vidsrc) { - gboolean update; - gdouble rate, applied_rate; - GstFormat format; - gint64 start, stop, position; - - gst_event_parse_new_segment_full (event, &update, &rate, - &applied_rate, &format, &start, &stop, &position); - gst_segment_set_newsegment (&self->segment, update, rate, format, - start, stop, position); + const GstSegment *s; + + gst_event_parse_segment (event, &s); + gst_segment_copy_into (s, &self->segment); } break; case GST_EVENT_FLUSH_STOP: @@ -1791,7 +1749,7 @@ gst_uvc_h264_src_event (GstPad * pad, GstEvent * event) return TRUE; break; } - return self->srcpad_event_func (pad, event); + return self->srcpad_event_func (pad, parent, event); } static guint8 @@ -2094,14 +2052,11 @@ configure_h264 (GstUvcH264Src * self, gint fd) } static void -v4l2src_prepare_format (GstElement * v4l2src, gint fd, guint fourcc, - guint width, guint height, gpointer user_data) +v4l2src_prepare_format (GstElement * v4l2src, gint fd, GstCaps * caps, + gpointer user_data) { GstUvcH264Src *self = GST_UVC_H264_SRC (user_data); - GST_DEBUG_OBJECT (self, "v4l2src prepare-format with FCC %" GST_FOURCC_FORMAT, - GST_FOURCC_ARGS (fourcc)); - if (self->main_format == UVC_H264_SRC_FORMAT_H264) { /* TODO: update static controls and g_object_notify those that changed */ configure_h264 (self, fd); @@ -2237,7 +2192,7 @@ _transform_caps (GstUvcH264Src * self, GstCaps * caps, const gchar * name) goto error_remove; GST_DEBUG_OBJECT (self, "Transforming: %" GST_PTR_FORMAT, caps); - out_caps = gst_pad_get_caps (sink); + caps = gst_pad_query_caps (sink, NULL); gst_object_unref (sink); GST_DEBUG_OBJECT (self, "Result: %" GST_PTR_FORMAT, out_caps); @@ -2257,33 +2212,30 @@ done: static GstCaps * gst_uvc_h264_src_transform_caps (GstUvcH264Src * self, GstCaps * caps) { - GstCaps *h264 = gst_caps_new_simple ("video/x-h264", NULL); - GstCaps *jpg = gst_caps_new_simple ("image/jpeg", NULL); + GstCaps *h264 = gst_caps_new_empty_simple ("video/x-h264"); + GstCaps *jpg = gst_caps_new_empty_simple ("image/jpeg"); GstCaps *h264_caps = gst_caps_intersect (h264, caps); GstCaps *jpg_caps = gst_caps_intersect (jpg, caps); /* TODO: Keep caps order after transformation */ caps = _transform_caps (self, caps, self->colorspace_name); + caps = gst_caps_make_writable (caps); if (!gst_caps_is_empty (h264_caps)) { - GstCaps *temp = gst_caps_union (caps, h264_caps); - gst_caps_unref (caps); - caps = temp; + gst_caps_append (caps, h264_caps); + } else { + gst_caps_unref (h264_caps); } + if (!gst_caps_is_empty (jpg_caps)) { - GstCaps *temp = gst_caps_union (caps, jpg_caps); - gst_caps_unref (caps); - caps = temp; + gst_caps_append (caps, jpg_caps); + } else { + gst_caps_unref (jpg_caps); } - if (h264_caps) - gst_caps_unref (h264_caps); - if (jpg_caps) - gst_caps_unref (jpg_caps); gst_caps_unref (h264); gst_caps_unref (jpg); - return caps; } @@ -2305,7 +2257,6 @@ gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad, GST_CAPS_INTERSECT_FIRST); GST_DEBUG_OBJECT (self, "intersect: %" GST_PTR_FORMAT, tcaps); icaps = gst_caps_normalize (tcaps); - gst_caps_unref (tcaps); /* Prefer the first caps we are compatible with that the peer proposed */ for (i = 0; i < gst_caps_get_size (icaps); i++) { @@ -2358,14 +2309,14 @@ gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad, guint32 interval; if (_extract_caps_info (s, &width, &height, &interval)) { - if (gst_structure_has_name (s, "video/x-raw-yuv")) { - guint32 fcc = 0; + if (gst_structure_has_name (s, "video/x-raw")) { guint8 mux = 0; + const gchar *format = gst_structure_get_string (s, "format"); - if (gst_structure_get_fourcc (s, "format", &fcc)) { - if (fcc == GST_MAKE_FOURCC ('Y', 'U', 'Y', '2')) + if ((format = gst_structure_get_string (s, "format"))) { + if (g_strcmp0 (format, "YUY2") == 0) mux = 4; - else if (fcc == GST_MAKE_FOURCC ('N', 'V', '1', '2')) + else if (g_strcmp0 (format, "NV12") == 0) mux = 8; } if (mux != 0) { @@ -2416,11 +2367,10 @@ gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad, if (caps) { caps = gst_caps_make_writable (caps); - gst_caps_truncate (caps); /* now fixate */ if (!gst_caps_is_empty (caps)) { - gst_pad_fixate_caps (v4l_pad, caps); + caps = gst_caps_fixate (caps); GST_DEBUG_OBJECT (self, "fixated to: %" GST_PTR_FORMAT, caps); } @@ -2474,16 +2424,19 @@ gst_uvc_h264_src_destroy_pipeline (GstUvcH264Src * self, gboolean v4l2src) iter = gst_bin_iterate_elements (GST_BIN (self)); done = FALSE; while (!done) { - GstElement *item = NULL; + GValue data = { 0, }; - switch (gst_iterator_next (iter, (gpointer *) & item)) { + switch (gst_iterator_next (iter, &data)) { case GST_ITERATOR_OK: - if (item != self->v4l2_src) { - gst_bin_remove (GST_BIN (self), item); - gst_element_set_state (item, GST_STATE_NULL); + { + GstElement *child = g_value_get_object (&data); + if (child != self->v4l2_src) { + gst_bin_remove (GST_BIN (self), child); + gst_element_set_state (child, GST_STATE_NULL); } - gst_object_unref (item); + g_value_reset (&data); break; + } case GST_ITERATOR_RESYNC: gst_iterator_resync (iter); break; @@ -2608,8 +2561,8 @@ gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), NULL); gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), NULL); - vf_caps = gst_pad_peer_get_caps (self->vfsrc); - vid_caps = gst_pad_peer_get_caps (self->vidsrc); + vf_caps = gst_pad_peer_query_caps (self->vfsrc, NULL); + vid_caps = gst_pad_peer_query_caps (self->vidsrc, NULL); GST_DEBUG_OBJECT (self, "vfsrc caps : %" GST_PTR_FORMAT, vf_caps); GST_DEBUG_OBJECT (self, "vidsrc caps : %" GST_PTR_FORMAT, vid_caps); @@ -2621,7 +2574,7 @@ gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) } v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src"); - v4l_caps = gst_pad_get_caps (v4l_pad); + v4l_caps = gst_pad_query_caps (v4l_pad, NULL); GST_DEBUG_OBJECT (self, "v4l2src caps : %" GST_PTR_FORMAT, v4l_caps); if (vid_caps) { GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vid_caps); @@ -2926,8 +2879,8 @@ gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) } if (!gst_element_link (self->v4l2_src, tee)) goto error_remove_all; - vf_pad = gst_element_get_request_pad (tee, "src%d"); - vid_pad = gst_element_get_request_pad (tee, "src%d"); + vf_pad = gst_element_get_request_pad (tee, "src_%u"); + vid_pad = gst_element_get_request_pad (tee, "src_%u"); } break; } @@ -2968,16 +2921,18 @@ gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) iter = gst_bin_iterate_elements (GST_BIN (self)); iter_done = FALSE; while (!iter_done) { - GstElement *item = NULL; + GstElement *child = NULL; + GValue data = { 0, }; - switch (gst_iterator_next (iter, (gpointer *) & item)) { + switch (gst_iterator_next (iter, &data)) { case GST_ITERATOR_OK: - if (!gst_element_sync_state_with_parent (item)) { - gst_object_unref (item); + child = g_value_get_object (&data); + if (!gst_element_sync_state_with_parent (child)) { + g_value_reset (&data); gst_iterator_free (iter); goto error_remove_all; } - gst_object_unref (item); + g_value_reset (&data); break; case GST_ITERATOR_RESYNC: gst_iterator_resync (iter); @@ -3039,9 +2994,9 @@ error: } static GstCaps * -gst_uvc_h264_src_getcaps (GstPad * pad) +gst_uvc_h264_src_getcaps (GstPad * pad, GstObject * parent) { - GstUvcH264Src *self = GST_UVC_H264_SRC (GST_OBJECT_PARENT (pad)); + GstUvcH264Src *self = GST_UVC_H264_SRC (parent); GstCaps *template = NULL; GstCaps *result = NULL; @@ -3054,7 +3009,7 @@ gst_uvc_h264_src_getcaps (GstPad * pad) if (self->v4l2_src) { GstPad *v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src"); - GstCaps *v4l_caps = gst_pad_get_caps (v4l_pad); + GstCaps *v4l_caps = gst_pad_query_caps (v4l_pad, NULL); GstCaps *new_caps = gst_uvc_h264_src_transform_caps (self, v4l_caps); result = gst_caps_intersect (new_caps, template); @@ -3070,6 +3025,23 @@ gst_uvc_h264_src_getcaps (GstPad * pad) } static gboolean +gst_uvc_h264_src_query (GstPad * pad, GstObject * parent, GstQuery * query) +{ + gboolean ret = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + gst_query_set_caps_result (query, gst_uvc_h264_src_getcaps (pad, parent)); + ret = TRUE; + default: + ret = gst_pad_query_default (pad, parent, query); + break; + } + return ret; +} + + +static gboolean gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc); |