mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 08:41:07 +00:00
uvch264src: Port to gstreamer 1.0
This commit is contained in:
parent
381fcda68b
commit
14637e2a27
4 changed files with 236 additions and 273 deletions
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
GstUvcH264MjpgDemux *self = GST_UVC_H264_MJPG_DEMUX (parent);
|
||||
gboolean ret = FALSE;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/* TODO: intersect with template and fixate caps */
|
||||
if (result == NULL)
|
||||
result = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
|
||||
|
||||
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);
|
||||
|
|
|
@ -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,
|
||||
|
@ -267,36 +239,6 @@ static gboolean gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self,
|
|||
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)
|
||||
{
|
||||
|
@ -304,6 +246,8 @@ gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass)
|
|||
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;
|
||||
const GstSegment *s;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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, h264_caps);
|
||||
} else {
|
||||
gst_caps_unref (h264_caps);
|
||||
}
|
||||
|
||||
if (h264_caps)
|
||||
gst_caps_unref (h264_caps);
|
||||
if (jpg_caps)
|
||||
if (!gst_caps_is_empty (jpg_caps)) {
|
||||
gst_caps_append (caps, jpg_caps);
|
||||
} else {
|
||||
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);
|
||||
|
@ -3069,6 +3024,23 @@ gst_uvc_h264_src_getcaps (GstPad * pad)
|
|||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue