4 * Copyright (C) 2012 Cisco Systems, Inc.
5 * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 * SECTION:element-uvch264-src
27 * A camera bin src element that wraps v4l2src and implements UVC H264
28 * Extension Units (XU) to control the H264 encoder in the camera
35 #include <gst/video/video.h>
36 #include <linux/uvcvideo.h>
37 #include <linux/usb/video.h>
38 #include <sys/ioctl.h>
41 #if defined (HAVE_GUDEV) && defined (HAVE_LIBUSB)
42 #include <gudev/gudev.h>
48 int8_t bDescriptorType;
49 int8_t bDescriptorSubType;
51 uint8_t guidExtensionCode[16];
52 } __attribute__ ((__packed__)) xu_descriptor;
54 #define GUID_FORMAT "02X%02X%02X%02X-%02X%02X%02X%02X-"\
55 "%02X%02X%02X%02X-%02X%02X%02X%02X"
56 #define GUID_ARGS(guid) guid[0], guid[1], guid[2], guid[3], \
57 guid[4], guid[5], guid[6], guid[7], \
58 guid[8], guid[9], guid[10], guid[11], \
59 guid[12], guid[13], guid[14], guid[15]
61 #define USB_VIDEO_CONTROL 1
62 #define USB_VIDEO_CONTROL_INTERFACE 0x24
63 #define USB_VIDEO_CONTROL_XU_TYPE 0x06
66 #include "gstuvch264_src.h"
67 #include "gstuvch264-marshal.h"
69 #ifndef UVCIOC_XU_FIND_UNIT
70 /* Define the needed structure if <linux/uvcvideo.h> is too old.
71 * This might fail though if the kernel itself does not support it.
73 struct uvc_xu_find_unit
78 #define UVCIOC_XU_FIND_UNIT _IOWR('u', 0x22, struct uvc_xu_find_unit)
85 /* uvch264_src properties */
87 PROP_JPEG_DECODER_NAME,
88 PROP_NUM_CLOCK_SAMPLES,
89 /* v4l2src properties */
101 PROP_NUM_REORDER_FRAMES,
102 PROP_PREVIEW_FLIPPED,
103 PROP_LEAKY_BUCKET_SIZE,
104 /* Dynamic controls */
106 PROP_FIXED_FRAMERATE,
107 PROP_MAX_MBPS, /* read-only */
110 PROP_AVERAGE_BITRATE,
117 PROP_LTR_BUFFER_SIZE,
118 PROP_LTR_ENCODER_CONTROL,
120 /* In caps : frame interval (fps), width, height, profile, mux */
121 /* Ignored: temporal, spatial, SNR, MVC views, version, reset */
122 /* Events: LTR, generate IDR */
127 SIGNAL_GET_ENUM_SETTING,
128 SIGNAL_GET_BOOLEAN_SETTING,
129 SIGNAL_GET_INT_SETTING,
133 static guint _signals[LAST_SIGNAL];
136 #define DEFAULT_COLORSPACE_NAME "ffmpegcolorspace"
137 #define DEFAULT_JPEG_DECODER_NAME "jpegdec"
138 #define DEFAULT_NUM_CLOCK_SAMPLES 0
139 #define DEFAULT_NUM_BUFFERS -1
140 #define DEFAULT_DEVICE "/dev/video0"
141 #define DEFAULT_DEVICE_NAME NULL
142 #define DEFAULT_INITIAL_BITRATE 3000000
143 #define DEFAULT_SLICE_UNITS 4
144 #define DEFAULT_SLICE_MODE UVC_H264_SLICEMODE_SLICEPERFRAME
145 #define DEFAULT_IFRAME_PERIOD 10000
146 #define DEFAULT_USAGE_TYPE UVC_H264_USAGETYPE_REALTIME
147 #define DEFAULT_ENTROPY UVC_H264_ENTROPY_CAVLC
148 #define DEFAULT_ENABLE_SEI FALSE
149 #define DEFAULT_NUM_REORDER_FRAMES 0
150 #define DEFAULT_PREVIEW_FLIPPED FALSE
151 #define DEFAULT_LEAKY_BUCKET_SIZE 1000
152 #define DEFAULT_RATE_CONTROL UVC_H264_RATECONTROL_CBR
153 #define DEFAULT_FIXED_FRAMERATE FALSE
154 #define DEFAULT_LEVEL_IDC 40
155 #define DEFAULT_PEAK_BITRATE DEFAULT_INITIAL_BITRATE
156 #define DEFAULT_AVERAGE_BITRATE DEFAULT_INITIAL_BITRATE
157 #define DEFAULT_MIN_QP 10
158 #define DEFAULT_MAX_QP 46
159 #define DEFAULT_LTR_BUFFER_SIZE 0
160 #define DEFAULT_LTR_ENCODER_CONTROL 0
162 #define NSEC_PER_SEC (G_USEC_PER_SEC * 1000)
165 GST_DEBUG_CATEGORY (uvc_h264_src_debug);
166 #define GST_CAT_DEFAULT uvc_h264_src_debug
168 GST_BOILERPLATE (GstUvcH264Src, gst_uvc_h264_src,
169 GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC);
171 #define GST_UVC_H264_SRC_VF_CAPS_STR \
172 GST_VIDEO_CAPS_RGB ";" \
173 GST_VIDEO_CAPS_RGB";" \
174 GST_VIDEO_CAPS_BGR";" \
175 GST_VIDEO_CAPS_RGBx";" \
176 GST_VIDEO_CAPS_xRGB";" \
177 GST_VIDEO_CAPS_BGRx";" \
178 GST_VIDEO_CAPS_xBGR";" \
179 GST_VIDEO_CAPS_RGBA";" \
180 GST_VIDEO_CAPS_ARGB";" \
181 GST_VIDEO_CAPS_BGRA";" \
182 GST_VIDEO_CAPS_ABGR";" \
183 GST_VIDEO_CAPS_RGB_16";" \
184 GST_VIDEO_CAPS_RGB_15";" \
185 "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \
186 "width = "GST_VIDEO_SIZE_RANGE" , " \
187 "height = " GST_VIDEO_SIZE_RANGE ", " \
188 "framerate = "GST_VIDEO_FPS_RANGE ";" \
189 GST_VIDEO_CAPS_GRAY8";" \
190 GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \
191 GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" \
192 GST_VIDEO_CAPS_YUV ("{ I420 , NV12 , NV21 , YV12 , YUY2 ," \
193 " Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY ," \
194 " Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420}") ";" \
196 "width = " GST_VIDEO_SIZE_RANGE ", " \
197 "height = " GST_VIDEO_SIZE_RANGE ", " \
198 "framerate = " GST_VIDEO_FPS_RANGE
200 #define GST_UVC_H264_SRC_VID_CAPS_STR \
201 GST_UVC_H264_SRC_VF_CAPS_STR ";" \
203 "width = " GST_VIDEO_SIZE_RANGE ", " \
204 "height = " GST_VIDEO_SIZE_RANGE ", " \
205 "framerate = " GST_VIDEO_FPS_RANGE ", " \
206 "stream-format = (string) { byte-stream, avc }, " \
207 "alignment = (string) { au }, " \
208 "profile = (string) { high, main, baseline, constrained-baseline }"
210 static GstStaticPadTemplate vfsrc_template =
211 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
214 GST_STATIC_CAPS (GST_UVC_H264_SRC_VF_CAPS_STR));
216 static GstStaticPadTemplate imgsrc_template =
217 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
220 GST_STATIC_CAPS_NONE);
222 static GstStaticPadTemplate vidsrc_template =
223 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
226 GST_STATIC_CAPS (GST_UVC_H264_SRC_VID_CAPS_STR));
229 static void gst_uvc_h264_src_dispose (GObject * object);
230 static void gst_uvc_h264_src_set_property (GObject * object,
231 guint prop_id, const GValue * value, GParamSpec * pspec);
232 static void gst_uvc_h264_src_get_property (GObject * object,
233 guint prop_id, GValue * value, GParamSpec * pspec);
234 static gboolean gst_uvc_h264_src_event (GstPad * pad, GstEvent * event);
235 static gboolean gst_uvc_h264_src_send_event (GstElement * element,
237 static gboolean gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc *
239 static gboolean gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc,
240 GstCameraBinMode mode);
241 static gboolean gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc);
242 static void gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc);
243 static GstStateChangeReturn gst_uvc_h264_src_change_state (GstElement * element,
244 GstStateChange trans);
245 static gboolean gst_uvc_h264_src_buffer_probe (GstPad * pad,
246 GstBuffer * buffer, gpointer user_data);
247 static gboolean gst_uvc_h264_src_event_probe (GstPad * pad,
248 GstEvent * event, gpointer user_data);
249 static void gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
250 GstPad * peer, gpointer user_data);
251 static GstCaps *gst_uvc_h264_src_getcaps (GstPad * pad);
254 static void v4l2src_prepare_format (GstElement * v4l2src, gint fd, guint fourcc,
255 guint width, guint height, gpointer user_data);
256 static void fill_probe_commit (GstUvcH264Src * self,
257 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
258 guint32 width, guint32 height, guint32 profile,
259 UvcH264StreamFormat stream_format);
260 static gboolean xu_query (GstUvcH264Src * self, guint selector, guint query,
263 static void set_rate_control (GstUvcH264Src * self);
264 static void set_level_idc (GstUvcH264Src * self);
265 static void set_bitrate (GstUvcH264Src * self);
266 static void set_qp (GstUvcH264Src * self, gint type);
267 static void set_ltr (GstUvcH264Src * self);
268 static void update_rate_control (GstUvcH264Src * self);
269 static guint32 update_level_idc_and_get_max_mbps (GstUvcH264Src * self);
270 static void update_bitrate (GstUvcH264Src * self);
271 static gboolean update_qp (GstUvcH264Src * self, gint type);
272 static void update_ltr (GstUvcH264Src * self);
274 static gboolean gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self,
275 gchar * property, gint * mask, gint * default_value);
276 static gboolean gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self,
277 gchar * property, gboolean * changeable, gboolean * def);
278 static gboolean gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self,
279 gchar * property, gint * min, gint * def, gint * max);
282 gst_uvc_h264_src_base_init (gpointer g_class)
284 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
287 GST_DEBUG_CATEGORY_INIT (uvc_h264_src_debug, "uvch264_src",
288 0, "UVC H264 Compliant camera bin source");
290 gst_element_class_set_details_simple (gstelement_class,
293 "UVC H264 Encoding camera source",
294 "Youness Alaoui <youness.alaoui@collabora.co.uk>");
296 /* Don't use gst_element_class_add_static_pad_template in order to keep
297 * the plugin compatible with gst 0.10.35 */
298 pt = gst_static_pad_template_get (&vidsrc_template);
299 gst_element_class_add_pad_template (gstelement_class, pt);
300 gst_object_unref (pt);
302 pt = gst_static_pad_template_get (&imgsrc_template);
303 gst_element_class_add_pad_template (gstelement_class, pt);
304 gst_object_unref (pt);
306 pt = gst_static_pad_template_get (&vfsrc_template);
307 gst_element_class_add_pad_template (gstelement_class, pt);
308 gst_object_unref (pt);
312 gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass)
314 GObjectClass *gobject_class;
315 GstElementClass *gstelement_class;
316 GstBaseCameraSrcClass *gstbasecamerasrc_class;
318 gobject_class = G_OBJECT_CLASS (klass);
319 gstelement_class = GST_ELEMENT_CLASS (klass);
320 gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass);
322 gobject_class->dispose = gst_uvc_h264_src_dispose;
323 gobject_class->set_property = gst_uvc_h264_src_set_property;
324 gobject_class->get_property = gst_uvc_h264_src_get_property;
326 gstelement_class->change_state = gst_uvc_h264_src_change_state;
327 gstelement_class->send_event = gst_uvc_h264_src_send_event;
329 gstbasecamerasrc_class->construct_pipeline =
330 gst_uvc_h264_src_construct_pipeline;
331 gstbasecamerasrc_class->set_mode = gst_uvc_h264_src_set_mode;
332 gstbasecamerasrc_class->start_capture = gst_uvc_h264_src_start_capture;
333 gstbasecamerasrc_class->stop_capture = gst_uvc_h264_src_stop_capture;
336 g_object_class_install_property (gobject_class, PROP_COLORSPACE_NAME,
337 g_param_spec_string ("colorspace-name", "colorspace element name",
338 "The name of the colorspace element",
339 DEFAULT_COLORSPACE_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
340 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
341 g_object_class_install_property (gobject_class, PROP_JPEG_DECODER_NAME,
342 g_param_spec_string ("jpeg-decoder-name", "jpeg decoder element name",
343 "The name of the jpeg decoder element",
344 DEFAULT_JPEG_DECODER_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
345 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
347 g_object_class_install_property (gobject_class, PROP_NUM_CLOCK_SAMPLES,
348 g_param_spec_int ("num-clock-samples", "num-clock-samples",
349 "Number of clock samples to gather for the PTS synchronization"
351 0, G_MAXINT, DEFAULT_NUM_CLOCK_SAMPLES,
352 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | GST_PARAM_MUTABLE_PLAYING |
353 G_PARAM_STATIC_STRINGS));
355 /* v4l2src proxied properties */
356 g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
357 g_param_spec_int ("num-buffers", "num-buffers",
358 "Number of buffers to output before sending EOS (-1 = unlimited)",
359 -1, G_MAXINT, DEFAULT_NUM_BUFFERS,
360 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361 g_object_class_install_property (gobject_class, PROP_DEVICE,
362 g_param_spec_string ("device", "device",
364 DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
365 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
366 g_param_spec_string ("device-name", "Device name",
367 "Name of the device", DEFAULT_DEVICE_NAME,
368 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
370 /* Static controls */
371 g_object_class_install_property (gobject_class, PROP_INITIAL_BITRATE,
372 g_param_spec_uint ("initial-bitrate", "Initial bitrate",
373 "Initial bitrate in bits/second (static control)",
374 0, G_MAXUINT, DEFAULT_INITIAL_BITRATE,
375 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
376 GST_PARAM_MUTABLE_READY));
377 g_object_class_install_property (gobject_class, PROP_SLICE_UNITS,
378 g_param_spec_uint ("slice-units", "Slice units",
379 "Slice units (static control)",
380 0, G_MAXUINT16, DEFAULT_SLICE_UNITS,
381 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
382 GST_PARAM_MUTABLE_READY));
383 g_object_class_install_property (gobject_class, PROP_SLICE_MODE,
384 g_param_spec_enum ("slice-mode", "Slice mode",
385 "Defines the unit of the slice-units property (static control)",
386 UVC_H264_SLICEMODE_TYPE,
387 DEFAULT_SLICE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
388 GST_PARAM_MUTABLE_READY));
389 g_object_class_install_property (gobject_class, PROP_IFRAME_PERIOD,
390 g_param_spec_uint ("iframe-period", "I Frame Period",
391 "Time between IDR frames in milliseconds (static control)",
392 0, G_MAXUINT16, DEFAULT_IFRAME_PERIOD,
393 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
394 GST_PARAM_MUTABLE_READY));
395 g_object_class_install_property (gobject_class, PROP_USAGE_TYPE,
396 g_param_spec_enum ("usage-type", "Usage type",
397 "The usage type (static control)",
398 UVC_H264_USAGETYPE_TYPE, DEFAULT_USAGE_TYPE,
399 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
400 GST_PARAM_MUTABLE_READY));
401 g_object_class_install_property (gobject_class, PROP_ENTROPY,
402 g_param_spec_enum ("entropy", "Entropy",
403 "Entropy (static control)",
404 UVC_H264_ENTROPY_TYPE, DEFAULT_ENTROPY,
405 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
406 GST_PARAM_MUTABLE_READY));
407 g_object_class_install_property (gobject_class, PROP_ENABLE_SEI,
408 g_param_spec_boolean ("enable-sei", "Enable SEI",
409 "Enable SEI picture timing (static control)",
410 DEFAULT_ENABLE_SEI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
411 GST_PARAM_MUTABLE_READY));
412 g_object_class_install_property (gobject_class, PROP_NUM_REORDER_FRAMES,
413 g_param_spec_uint ("num-reorder-frames", "Number of Reorder frames",
414 "Number of B frames between the references frames (static control)",
415 0, G_MAXUINT8, DEFAULT_NUM_REORDER_FRAMES,
416 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
417 GST_PARAM_MUTABLE_READY));
418 g_object_class_install_property (gobject_class, PROP_PREVIEW_FLIPPED,
419 g_param_spec_boolean ("preview-flipped", "Flip preview",
420 "Horizontal flipped image for non H.264 streams (static control)",
421 DEFAULT_PREVIEW_FLIPPED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
422 GST_PARAM_MUTABLE_READY));
423 g_object_class_install_property (gobject_class, PROP_LEAKY_BUCKET_SIZE,
424 g_param_spec_uint ("leaky-bucket-size", "Size of the leaky bucket size",
425 "Size of the leaky bucket size in milliseconds (static control)",
426 0, G_MAXUINT16, DEFAULT_LEAKY_BUCKET_SIZE,
427 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
428 GST_PARAM_MUTABLE_READY));
430 /* Dynamic controls */
431 g_object_class_install_property (gobject_class, PROP_RATE_CONTROL,
432 g_param_spec_enum ("rate-control", "Rate control",
433 "Rate control mode (static & dynamic control)",
434 UVC_H264_RATECONTROL_TYPE, DEFAULT_RATE_CONTROL,
435 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
436 GST_PARAM_MUTABLE_PLAYING));
437 g_object_class_install_property (gobject_class, PROP_FIXED_FRAMERATE,
438 g_param_spec_boolean ("fixed-framerate", "Fixed framerate",
439 "Fixed framerate (static & dynamic control)",
440 DEFAULT_FIXED_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
441 GST_PARAM_MUTABLE_PLAYING));
442 g_object_class_install_property (gobject_class, PROP_MAX_MBPS,
443 g_param_spec_uint ("max-mbps", "Max macroblocks/second",
444 "The number of macroblocks per second for the maximum processing rate",
445 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
446 g_object_class_install_property (gobject_class, PROP_LEVEL_IDC,
447 g_param_spec_uint ("level-idc", "Level IDC",
448 "Level IDC (dynamic control)",
449 0, G_MAXUINT8, DEFAULT_LEVEL_IDC,
450 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
451 GST_PARAM_MUTABLE_PLAYING));
452 g_object_class_install_property (gobject_class, PROP_PEAK_BITRATE,
453 g_param_spec_uint ("peak-bitrate", "Peak bitrate",
454 "The peak bitrate in bits/second (dynamic control)",
455 0, G_MAXUINT, DEFAULT_PEAK_BITRATE,
456 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
457 GST_PARAM_MUTABLE_PLAYING));
458 g_object_class_install_property (gobject_class, PROP_AVERAGE_BITRATE,
459 g_param_spec_uint ("average-bitrate", "Average bitrate",
460 "The average bitrate in bits/second (dynamic control)",
461 0, G_MAXUINT, DEFAULT_AVERAGE_BITRATE,
462 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
463 GST_PARAM_MUTABLE_PLAYING));
464 g_object_class_install_property (gobject_class, PROP_MIN_IFRAME_QP,
465 g_param_spec_int ("min-iframe-qp", "Minimum I frame QP",
466 "The minimum Quantization step size for I frames (dynamic control)",
467 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
468 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
469 GST_PARAM_MUTABLE_PLAYING));
470 g_object_class_install_property (gobject_class, PROP_MAX_IFRAME_QP,
471 g_param_spec_int ("max-iframe-qp", "Minimum I frame QP",
472 "The minimum Quantization step size for I frames (dynamic control)",
473 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
474 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
475 GST_PARAM_MUTABLE_PLAYING));
476 g_object_class_install_property (gobject_class, PROP_MIN_PFRAME_QP,
477 g_param_spec_int ("min-pframe-qp", "Minimum P frame QP",
478 "The minimum Quantization step size for P frames (dynamic control)",
479 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
480 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
481 GST_PARAM_MUTABLE_PLAYING));
482 g_object_class_install_property (gobject_class, PROP_MAX_PFRAME_QP,
483 g_param_spec_int ("max-pframe-qp", "Minimum P frame QP",
484 "The minimum Quantization step size for P frames (dynamic control)",
485 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
486 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
487 GST_PARAM_MUTABLE_PLAYING));
488 g_object_class_install_property (gobject_class, PROP_MIN_BFRAME_QP,
489 g_param_spec_int ("min-bframe-qp", "Minimum B frame QP",
490 "The minimum Quantization step size for B frames (dynamic control)",
491 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
492 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
493 GST_PARAM_MUTABLE_PLAYING));
494 g_object_class_install_property (gobject_class, PROP_MAX_BFRAME_QP,
495 g_param_spec_int ("max-bframe-qp", "Minimum B frame QP",
496 "The minimum Quantization step size for B frames (dynamic control)",
497 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
498 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
499 GST_PARAM_MUTABLE_PLAYING));
500 g_object_class_install_property (gobject_class, PROP_LTR_BUFFER_SIZE,
501 g_param_spec_int ("ltr-buffer-size", "LTR Buffer size",
502 "Total number of Long-Term Reference frames (dynamic control)",
503 0, G_MAXUINT8, DEFAULT_LTR_BUFFER_SIZE,
504 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
505 GST_PARAM_MUTABLE_PLAYING));
506 g_object_class_install_property (gobject_class, PROP_LTR_ENCODER_CONTROL,
507 g_param_spec_int ("ltr-encoder-control", "LTR frames controled by device",
508 "Number of LTR frames the device can control (dynamic control)",
509 0, G_MAXUINT8, DEFAULT_LTR_ENCODER_CONTROL,
510 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
511 GST_PARAM_MUTABLE_PLAYING));
513 _signals[SIGNAL_GET_ENUM_SETTING] =
514 g_signal_new_class_handler ("get-enum-setting",
515 G_TYPE_FROM_CLASS (klass),
516 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
517 G_CALLBACK (gst_uvc_h264_src_get_enum_setting),
518 NULL, NULL, __gst_uvc_h264_marshal_BOOLEAN__STRING_POINTER_POINTER,
519 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
520 _signals[SIGNAL_GET_BOOLEAN_SETTING] =
521 g_signal_new_class_handler ("get-boolean-setting",
522 G_TYPE_FROM_CLASS (klass),
523 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
524 G_CALLBACK (gst_uvc_h264_src_get_boolean_setting), NULL, NULL,
525 __gst_uvc_h264_marshal_BOOLEAN__STRING_POINTER_POINTER,
526 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
527 _signals[SIGNAL_GET_INT_SETTING] =
528 g_signal_new_class_handler ("get-int-setting",
529 G_TYPE_FROM_CLASS (klass),
530 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
531 G_CALLBACK (gst_uvc_h264_src_get_int_setting), NULL, NULL,
532 __gst_uvc_h264_marshal_BOOLEAN__STRING_POINTER_POINTER_POINTER,
533 G_TYPE_BOOLEAN, 4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER,
539 gst_uvc_h264_src_init (GstUvcH264Src * self, GstUvcH264SrcClass * klass)
542 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
544 gst_pad_set_getcaps_function (self->vfsrc,
545 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_getcaps));
546 gst_element_add_pad (GST_ELEMENT (self), self->vfsrc);
549 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
551 gst_element_add_pad (GST_ELEMENT (self), self->imgsrc);
554 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
556 gst_pad_set_getcaps_function (self->vidsrc,
557 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_getcaps));
558 gst_element_add_pad (GST_ELEMENT (self), self->vidsrc);
559 gst_pad_add_buffer_probe (self->vidsrc,
560 (GCallback) gst_uvc_h264_src_buffer_probe, self);
561 gst_pad_add_event_probe (self->vfsrc,
562 (GCallback) gst_uvc_h264_src_event_probe, self);
563 gst_pad_add_event_probe (self->vidsrc,
564 (GCallback) gst_uvc_h264_src_event_probe, self);
566 self->srcpad_event_func = GST_PAD_EVENTFUNC (self->vfsrc);
568 gst_pad_set_event_function (self->imgsrc, gst_uvc_h264_src_event);
569 gst_pad_set_event_function (self->vidsrc, gst_uvc_h264_src_event);
570 gst_pad_set_event_function (self->vfsrc, gst_uvc_h264_src_event);
572 g_signal_connect (self->vidsrc, "linked",
573 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
574 g_signal_connect (self->vidsrc, "unlinked",
575 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
576 g_signal_connect (self->vfsrc, "linked",
577 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
578 g_signal_connect (self->vfsrc, "unlinked",
579 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
581 self->vid_newseg = FALSE;
582 self->vf_newseg = FALSE;
584 gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), MODE_VIDEO);
586 self->main_format = UVC_H264_SRC_FORMAT_NONE;
587 self->main_width = 0;
588 self->main_height = 0;
589 self->main_frame_interval = 0;
590 self->main_stream_format = UVC_H264_STREAMFORMAT_ANNEXB;
591 self->main_profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
592 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
593 self->secondary_width = 0;
594 self->secondary_height = 0;
595 self->secondary_frame_interval = 0;
597 /* v4l2src properties */
598 self->num_buffers = DEFAULT_NUM_BUFFERS;
599 self->device = g_strdup (DEFAULT_DEVICE);
601 /* Static controls */
602 self->initial_bitrate = DEFAULT_INITIAL_BITRATE;
603 self->slice_units = DEFAULT_SLICE_UNITS;
604 self->slice_mode = DEFAULT_SLICE_MODE;
605 self->iframe_period = DEFAULT_IFRAME_PERIOD;
606 self->usage_type = DEFAULT_USAGE_TYPE;
607 self->entropy = DEFAULT_ENTROPY;
608 self->enable_sei = DEFAULT_ENABLE_SEI;
609 self->num_reorder_frames = DEFAULT_NUM_REORDER_FRAMES;
610 self->preview_flipped = DEFAULT_PREVIEW_FLIPPED;
611 self->leaky_bucket_size = DEFAULT_LEAKY_BUCKET_SIZE;
613 /* Dynamic controls */
614 self->rate_control = DEFAULT_RATE_CONTROL;
615 self->fixed_framerate = DEFAULT_FIXED_FRAMERATE;
616 self->level_idc = DEFAULT_LEVEL_IDC;
617 self->peak_bitrate = DEFAULT_PEAK_BITRATE;
618 self->average_bitrate = DEFAULT_AVERAGE_BITRATE;
619 self->min_qp[QP_I_FRAME] = DEFAULT_MIN_QP;
620 self->max_qp[QP_I_FRAME] = DEFAULT_MAX_QP;
621 self->min_qp[QP_P_FRAME] = DEFAULT_MIN_QP;
622 self->max_qp[QP_P_FRAME] = DEFAULT_MAX_QP;
623 self->min_qp[QP_B_FRAME] = DEFAULT_MIN_QP;
624 self->max_qp[QP_B_FRAME] = DEFAULT_MAX_QP;
625 self->ltr_buffer_size = DEFAULT_LTR_BUFFER_SIZE;
626 self->ltr_encoder_control = DEFAULT_LTR_ENCODER_CONTROL;
630 gst_uvc_h264_src_dispose (GObject * object)
632 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
634 #if defined (HAVE_GUDEV) && defined (HAVE_LIBUSB)
636 libusb_exit (self->usb_ctx);
637 self->usb_ctx = NULL;
642 G_OBJECT_CLASS (parent_class)->dispose (object);
646 gst_uvc_h264_src_set_property (GObject * object,
647 guint prop_id, const GValue * value, GParamSpec * pspec)
649 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
652 case PROP_COLORSPACE_NAME:
653 g_free (self->colorspace_name);
654 self->colorspace_name = g_value_dup_string (value);
656 case PROP_JPEG_DECODER_NAME:
657 g_free (self->jpeg_decoder_name);
658 self->jpeg_decoder_name = g_value_dup_string (value);
660 case PROP_NUM_CLOCK_SAMPLES:
661 self->num_clock_samples = g_value_get_int (value);
662 if (self->mjpg_demux)
663 g_object_set (self->mjpg_demux,
664 "num-clock-samples", self->num_clock_samples, NULL);
666 /* v4l2 properties */
667 case PROP_NUM_BUFFERS:
668 self->num_buffers = g_value_get_int (value);
670 g_object_set_property (G_OBJECT (self->v4l2_src), "num-buffers", value);
673 g_free (self->device);
674 self->device = g_value_dup_string (value);
676 g_object_set_property (G_OBJECT (self->v4l2_src), "device", value);
678 /* Static controls */
679 case PROP_INITIAL_BITRATE:
680 self->initial_bitrate = g_value_get_uint (value);
682 case PROP_SLICE_UNITS:
683 self->slice_units = g_value_get_uint (value);
685 case PROP_SLICE_MODE:
686 self->slice_mode = g_value_get_enum (value);
688 case PROP_IFRAME_PERIOD:
689 self->iframe_period = g_value_get_uint (value);
691 case PROP_USAGE_TYPE:
692 self->usage_type = g_value_get_enum (value);
695 self->entropy = g_value_get_enum (value);
697 case PROP_ENABLE_SEI:
698 self->enable_sei = g_value_get_boolean (value);
700 case PROP_NUM_REORDER_FRAMES:
701 self->num_reorder_frames = g_value_get_uint (value);
703 case PROP_PREVIEW_FLIPPED:
704 self->preview_flipped = g_value_get_boolean (value);
706 case PROP_LEAKY_BUCKET_SIZE:
707 self->leaky_bucket_size = g_value_get_uint (value);
711 /* Dynamic controls */
712 case PROP_RATE_CONTROL:
713 self->rate_control = g_value_get_enum (value);
714 set_rate_control (self);
715 update_rate_control (self);
717 case PROP_FIXED_FRAMERATE:
718 self->fixed_framerate = g_value_get_boolean (value);
719 set_rate_control (self);
720 update_rate_control (self);
723 self->level_idc = g_value_get_uint (value);
724 set_level_idc (self);
725 update_level_idc_and_get_max_mbps (self);
727 case PROP_PEAK_BITRATE:
728 self->peak_bitrate = g_value_get_uint (value);
730 update_bitrate (self);
732 case PROP_AVERAGE_BITRATE:
733 self->average_bitrate = g_value_get_uint (value);
735 update_bitrate (self);
737 case PROP_MIN_IFRAME_QP:
738 self->min_qp[QP_I_FRAME] = g_value_get_int (value);
739 set_qp (self, QP_I_FRAME);
740 update_qp (self, QP_I_FRAME);
742 case PROP_MAX_IFRAME_QP:
743 self->max_qp[QP_I_FRAME] = g_value_get_int (value);
744 set_qp (self, QP_I_FRAME);
745 update_qp (self, QP_I_FRAME);
747 case PROP_MIN_PFRAME_QP:
748 self->min_qp[QP_P_FRAME] = g_value_get_int (value);
749 set_qp (self, QP_P_FRAME);
750 update_qp (self, QP_P_FRAME);
752 case PROP_MAX_PFRAME_QP:
753 self->max_qp[QP_P_FRAME] = g_value_get_int (value);
754 set_qp (self, QP_P_FRAME);
755 update_qp (self, QP_P_FRAME);
757 case PROP_MIN_BFRAME_QP:
758 self->min_qp[QP_B_FRAME] = g_value_get_int (value);
759 set_qp (self, QP_B_FRAME);
760 update_qp (self, QP_B_FRAME);
762 case PROP_MAX_BFRAME_QP:
763 self->max_qp[QP_B_FRAME] = g_value_get_int (value);
764 set_qp (self, QP_B_FRAME);
765 update_qp (self, QP_B_FRAME);
767 case PROP_LTR_BUFFER_SIZE:
768 self->ltr_buffer_size = g_value_get_int (value);
772 case PROP_LTR_ENCODER_CONTROL:
773 self->ltr_encoder_control = g_value_get_int (value);
778 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
784 gst_uvc_h264_src_get_property (GObject * object,
785 guint prop_id, GValue * value, GParamSpec * pspec)
787 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
788 uvcx_video_config_probe_commit_t probe;
791 case PROP_INITIAL_BITRATE:
792 case PROP_SLICE_UNITS:
793 case PROP_SLICE_MODE:
794 case PROP_IFRAME_PERIOD:
795 case PROP_USAGE_TYPE:
797 case PROP_ENABLE_SEI:
798 case PROP_NUM_REORDER_FRAMES:
799 case PROP_PREVIEW_FLIPPED:
800 case PROP_LEAKY_BUCKET_SIZE:
801 fill_probe_commit (self, &probe, 0, 0, 0, 0, 0);
802 if (GST_STATE (self) >= GST_STATE_PAUSED) {
803 xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
812 case PROP_COLORSPACE_NAME:
813 g_value_set_string (value, self->colorspace_name);
815 case PROP_JPEG_DECODER_NAME:
816 g_value_set_string (value, self->jpeg_decoder_name);
818 case PROP_NUM_CLOCK_SAMPLES:
819 g_value_set_int (value, self->num_clock_samples);
821 /* v4l2src properties */
822 case PROP_NUM_BUFFERS:
823 g_value_set_int (value, self->num_buffers);
826 g_value_set_string (value, self->device);
828 case PROP_DEVICE_NAME:
830 g_object_get_property (G_OBJECT (self->v4l2_src), "device-name", value);
832 g_value_set_static_string (value, "");
834 /* Static controls */
835 case PROP_INITIAL_BITRATE:
836 g_value_set_uint (value, probe.dwBitRate);
838 case PROP_SLICE_UNITS:
839 g_value_set_uint (value, probe.wSliceUnits);
841 case PROP_SLICE_MODE:
842 g_value_set_enum (value, probe.wSliceMode);
844 case PROP_IFRAME_PERIOD:
845 g_value_set_uint (value, probe.wIFramePeriod);
847 case PROP_USAGE_TYPE:
848 g_value_set_enum (value, probe.bUsageType);
851 g_value_set_enum (value, probe.bEntropyCABAC);
853 case PROP_ENABLE_SEI:
854 g_value_set_boolean (value,
855 (probe.bTimestamp == UVC_H264_TIMESTAMP_SEI_ENABLE));
857 case PROP_NUM_REORDER_FRAMES:
858 g_value_set_uint (value, probe.bNumOfReorderFrames);
860 case PROP_PREVIEW_FLIPPED:
861 g_value_set_boolean (value,
862 (probe.bPreviewFlipped == UVC_H264_PREFLIPPED_HORIZONTAL));
864 case PROP_LEAKY_BUCKET_SIZE:
865 g_value_set_uint (value, probe.wLeakyBucketSize);
868 /* Dynamic controls */
869 case PROP_RATE_CONTROL:
870 update_rate_control (self);
871 g_value_set_enum (value, self->rate_control);
873 case PROP_FIXED_FRAMERATE:
874 update_rate_control (self);
875 g_value_set_boolean (value, self->fixed_framerate);
878 g_value_set_uint (value, update_level_idc_and_get_max_mbps (self));
881 update_level_idc_and_get_max_mbps (self);
882 g_value_set_uint (value, self->level_idc);
884 case PROP_PEAK_BITRATE:
885 update_bitrate (self);
886 g_value_set_uint (value, self->peak_bitrate);
888 case PROP_AVERAGE_BITRATE:
889 update_bitrate (self);
890 g_value_set_uint (value, self->average_bitrate);
892 case PROP_MIN_IFRAME_QP:
893 update_qp (self, QP_I_FRAME);
894 g_value_set_int (value, self->min_qp[QP_I_FRAME]);
896 case PROP_MAX_IFRAME_QP:
897 update_qp (self, QP_I_FRAME);
898 g_value_set_int (value, self->max_qp[QP_I_FRAME]);
900 case PROP_MIN_PFRAME_QP:
901 update_qp (self, QP_P_FRAME);
902 g_value_set_int (value, self->min_qp[QP_P_FRAME]);
904 case PROP_MAX_PFRAME_QP:
905 update_qp (self, QP_P_FRAME);
906 g_value_set_int (value, self->max_qp[QP_P_FRAME]);
908 case PROP_MIN_BFRAME_QP:
909 update_qp (self, QP_B_FRAME);
910 g_value_set_int (value, self->min_qp[QP_B_FRAME]);
912 case PROP_MAX_BFRAME_QP:
913 update_qp (self, QP_B_FRAME);
914 g_value_set_int (value, self->max_qp[QP_B_FRAME]);
916 case PROP_LTR_BUFFER_SIZE:
918 g_value_set_int (value, self->ltr_buffer_size);
920 case PROP_LTR_ENCODER_CONTROL:
922 g_value_set_int (value, self->ltr_encoder_control);
925 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
930 /* Set dynamic controls */
932 set_rate_control (GstUvcH264Src * self)
934 uvcx_rate_control_mode_t req;
936 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
937 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
941 req.bRateControlMode = self->rate_control;
942 if (self->fixed_framerate)
943 req.bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
945 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR, (guchar *) & req)) {
946 GST_WARNING_OBJECT (self, " RATE_CONTROL SET_CUR error");
952 set_level_idc (GstUvcH264Src * self)
954 uvcx_video_advance_config_t req;
956 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
958 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
962 req.blevel_idc = self->level_idc;
963 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_SET_CUR,
965 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG SET_CUR error");
971 set_bitrate (GstUvcH264Src * self)
973 uvcx_bitrate_layers_t req;
975 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
976 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
980 req.dwPeakBitrate = self->peak_bitrate;
981 req.dwAverageBitrate = self->average_bitrate;
982 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
983 GST_WARNING_OBJECT (self, " BITRATE_LAYERS SET_CUR error");
989 set_qp (GstUvcH264Src * self, gint type)
991 uvcx_qp_steps_layers_t req;
996 req.bFrameType = UVC_H264_QP_STEPS_I_FRAME_TYPE;
999 req.bFrameType = UVC_H264_QP_STEPS_P_FRAME_TYPE;
1002 req.bFrameType = UVC_H264_QP_STEPS_B_FRAME_TYPE;
1009 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
1010 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
1014 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1015 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
1019 req.bMinQp = self->min_qp[type];
1020 req.bMaxQp = self->max_qp[type];
1021 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
1022 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
1028 set_ltr (GstUvcH264Src * self)
1030 uvcx_ltr_buffer_size_control_t req;
1032 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
1033 (guchar *) & req)) {
1034 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
1038 req.bLTRBufferSize = self->ltr_buffer_size;
1039 req.bLTREncoderControl = self->ltr_encoder_control;
1040 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_SET_CUR,
1041 (guchar *) & req)) {
1042 GST_WARNING_OBJECT (self, "LTR_BUFFER_SIZE SET_CUR error");
1047 /* Get Dynamic controls */
1050 update_rate_control (GstUvcH264Src * self)
1052 uvcx_rate_control_mode_t req;
1054 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
1055 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
1059 if (self->rate_control != (req.bRateControlMode &
1060 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG)) {
1061 self->rate_control = (req.bRateControlMode &
1062 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG);
1063 g_object_notify (G_OBJECT (self), "rate-control");
1065 if (self->fixed_framerate != ((req.bRateControlMode &
1066 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0)) {
1067 self->fixed_framerate = ((req.bRateControlMode &
1068 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1069 g_object_notify (G_OBJECT (self), "fixed-framerate");
1075 update_level_idc_and_get_max_mbps (GstUvcH264Src * self)
1077 uvcx_video_advance_config_t req;
1079 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
1080 (guchar *) & req)) {
1081 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
1085 if (self->level_idc != req.blevel_idc) {
1086 self->level_idc = req.blevel_idc;
1087 g_object_notify (G_OBJECT (self), "level-idc");
1089 return req.dwMb_max;
1093 update_bitrate (GstUvcH264Src * self)
1095 uvcx_bitrate_layers_t req;
1097 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1098 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
1101 if (self->peak_bitrate != req.dwPeakBitrate) {
1102 self->peak_bitrate = req.dwPeakBitrate;
1103 g_object_notify (G_OBJECT (self), "peak-bitrate");
1105 if (self->average_bitrate != req.dwAverageBitrate) {
1106 self->average_bitrate = req.dwAverageBitrate;
1107 g_object_notify (G_OBJECT (self), "average-bitrate");
1112 update_qp (GstUvcH264Src * self, gint type)
1114 uvcx_qp_steps_layers_t req;
1120 frame_type = UVC_H264_QP_STEPS_I_FRAME_TYPE;
1123 frame_type = UVC_H264_QP_STEPS_P_FRAME_TYPE;
1126 frame_type = UVC_H264_QP_STEPS_B_FRAME_TYPE;
1131 req.bFrameType = frame_type;
1134 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
1135 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
1139 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1140 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
1144 if (req.bFrameType == frame_type) {
1145 if (self->min_qp[type] != req.bMinQp) {
1146 self->min_qp[type] = req.bMinQp;
1149 g_object_notify (G_OBJECT (self), "min-iframe-qp");
1152 g_object_notify (G_OBJECT (self), "min-pframe-qp");
1155 g_object_notify (G_OBJECT (self), "min-bframe-qp");
1161 if (self->max_qp[type] != req.bMaxQp) {
1162 self->max_qp[type] = req.bMaxQp;
1165 g_object_notify (G_OBJECT (self), "max-iframe-qp");
1168 g_object_notify (G_OBJECT (self), "max-pframe-qp");
1171 g_object_notify (G_OBJECT (self), "max-bframe-qp");
1179 self->min_qp[type] = 0xFF;
1180 self->max_qp[type] = 0xFF;
1186 update_ltr (GstUvcH264Src * self)
1188 uvcx_ltr_buffer_size_control_t req;
1190 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
1191 (guchar *) & req)) {
1192 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
1196 if (self->ltr_buffer_size != req.bLTRBufferSize) {
1197 self->ltr_buffer_size = req.bLTRBufferSize;
1198 g_object_notify (G_OBJECT (self), "ltr-buffer-size");
1200 if (self->ltr_encoder_control != req.bLTREncoderControl) {
1201 self->ltr_encoder_control = req.bLTREncoderControl;
1202 g_object_notify (G_OBJECT (self), "ltr-encoder-control");
1206 #define STORE_MIN_DEF_MAX(type) \
1207 *(type *)min = *((type *) (min_p + offset)); \
1208 *(type *)def = *((type *) (def_p + offset)); \
1209 *(type *)max = *((type *) (max_p + offset));
1212 probe_setting (GstUvcH264Src * self, uvcx_control_selector_t selector,
1213 guint offset, gint size, gpointer min, gpointer def, gpointer max)
1215 guchar *min_p, *def_p, *max_p;
1216 gboolean ret = FALSE;
1219 if (!xu_query (self, selector, UVC_GET_LEN, (guchar *) & len)) {
1220 GST_WARNING_OBJECT (self, "probe_setting GET_LEN error");
1223 min_p = g_malloc0 (len);
1224 def_p = g_malloc0 (len);
1225 max_p = g_malloc0 (len);
1227 if (!xu_query (self, selector, UVC_GET_MIN, min_p)) {
1228 GST_WARNING_OBJECT (self, "probe_setting GET_MIN error");
1231 if (!xu_query (self, selector, UVC_GET_DEF, def_p)) {
1232 GST_WARNING_OBJECT (self, "probe_setting GET_DEF error");
1235 if (!xu_query (self, selector, UVC_GET_MAX, max_p)) {
1236 GST_WARNING_OBJECT (self, "probe_setting GET_MAX error");
1242 STORE_MIN_DEF_MAX (gint8);
1246 STORE_MIN_DEF_MAX (guint8);
1250 STORE_MIN_DEF_MAX (gint16);
1254 STORE_MIN_DEF_MAX (guint16);
1258 STORE_MIN_DEF_MAX (gint32);
1262 STORE_MIN_DEF_MAX (guint32);
1278 test_enum_setting (GstUvcH264Src * self, guint offset, guint size,
1281 uvcx_video_config_probe_commit_t cur;
1282 uvcx_video_config_probe_commit_t req;
1283 guchar *req_p = (guchar *) & req;
1285 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, (guchar *) & cur)) {
1286 GST_WARNING_OBJECT (self, " GET_CUR error");
1293 *((guint8 *) (req_p + offset)) = (guint8) value;
1295 *((guint16 *) (req_p + offset)) = value;
1297 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, req_p)) {
1298 GST_WARNING_OBJECT (self, " SET_CUR error");
1302 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, req_p)) {
1303 GST_WARNING_OBJECT (self, " GET_CUR error");
1307 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, (guchar *) & cur)) {
1308 GST_WARNING_OBJECT (self, " SET_CUR error");
1313 return *((guint8 *) (req_p + offset)) == (guint8) value;
1315 return *((guint16 *) (req_p + offset)) == value;
1319 gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self, gchar * property,
1320 gint * mask, gint * default_value)
1322 guint8 min, def, max;
1324 gboolean ret = FALSE;
1326 if (g_strcmp0 (property, "slice-mode") == 0) {
1327 guint16 min16, def16, max16;
1330 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1331 offsetof (uvcx_video_config_probe_commit_t, wSliceMode), 2,
1332 &min16, &def16, &max16);
1334 *default_value = def16;
1336 for (en16 = min16; en16 <= max16; en16++) {
1337 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1338 wSliceMode), 2, en16))
1339 *mask |= (1 << en16);
1342 } else if (g_strcmp0 (property, "usage-type") == 0) {
1343 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1344 offsetof (uvcx_video_config_probe_commit_t, bUsageType), 1,
1347 *default_value = def;
1349 for (en = min; en <= max; en++) {
1350 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1351 bUsageType), 1, en))
1355 } else if (g_strcmp0 (property, "entropy") == 0) {
1356 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1357 offsetof (uvcx_video_config_probe_commit_t, bEntropyCABAC), 1,
1360 *mask = (1 << min) | (1 << max);
1361 *default_value = def;
1363 } else if (g_strcmp0 (property, "rate-control") == 0) {
1364 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1365 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode), 1,
1368 uvcx_rate_control_mode_t cur;
1370 *default_value = def;
1373 xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & cur);
1375 for (en = min; en <= max; en++) {
1376 uvcx_rate_control_mode_t req = { 0, en };
1378 if (xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR,
1379 (guchar *) & req) &&
1380 xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR,
1381 (guchar *) & req) && req.bRateControlMode == en)
1384 xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR, (guchar *) & cur);
1392 gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self, gchar * property,
1393 gboolean * changeable, gboolean * default_value)
1395 guint8 min, def, max;
1396 gboolean ret = FALSE;
1398 if (g_strcmp0 (property, "enable-sei") == 0) {
1399 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1400 offsetof (uvcx_video_config_probe_commit_t, bTimestamp), 1,
1402 *changeable = (min != max);
1403 *default_value = (def != 0);
1404 } else if (g_strcmp0 (property, "preview-flipped") == 0) {
1405 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1406 offsetof (uvcx_video_config_probe_commit_t, bPreviewFlipped), 1,
1408 *changeable = (min != max);
1409 *default_value = (def != 0);
1410 } else if (g_strcmp0 (property, "fixed-framerate") == 0) {
1411 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1412 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode), 1,
1414 *changeable = ((max & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1415 *default_value = ((def & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1422 gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self, gchar * property,
1423 gint * min, gint * def, gint * max)
1425 guint32 min32, def32, max32;
1426 guint16 min16, def16, max16;
1427 guint8 min8, def8, max8;
1428 gint8 smin8, sdef8, smax8;
1429 gboolean ret = FALSE;
1431 GST_DEBUG_OBJECT (self, "Probing int property %s", property);
1432 if (g_strcmp0 (property, "initial-bitrate") == 0) {
1433 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1434 offsetof (uvcx_video_config_probe_commit_t, dwBitRate), 4,
1435 &min32, &def32, &max32);
1439 } else if (g_strcmp0 (property, "slice-units") == 0) {
1440 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1441 offsetof (uvcx_video_config_probe_commit_t, wSliceUnits), 2,
1442 &min16, &def16, &max16);
1446 } else if (g_strcmp0 (property, "iframe-period") == 0) {
1447 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1448 offsetof (uvcx_video_config_probe_commit_t, wIFramePeriod), 2,
1449 &min16, &def16, &max16);
1453 } else if (g_strcmp0 (property, "num-reorder-frames") == 0) {
1454 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1455 offsetof (uvcx_video_config_probe_commit_t, bNumOfReorderFrames), 1,
1456 &min8, &def8, &max8);
1460 } else if (g_strcmp0 (property, "leaky-bucket-size") == 0) {
1461 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1462 offsetof (uvcx_video_config_probe_commit_t, wLeakyBucketSize), 2,
1463 &min16, &def16, &max16);
1467 } else if (g_strcmp0 (property, "level-idc") == 0) {
1468 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1469 offsetof (uvcx_video_advance_config_t, blevel_idc), 1,
1470 &min8, &def8, &max8);
1474 } else if (g_strcmp0 (property, "max-mbps") == 0) {
1475 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1476 offsetof (uvcx_video_advance_config_t, dwMb_max), 4,
1477 &min32, &def32, &max32);
1481 } else if (g_strcmp0 (property, "peak-bitrate") == 0) {
1482 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1483 offsetof (uvcx_bitrate_layers_t, dwPeakBitrate), 4,
1484 &min32, &def32, &max32);
1488 } else if (g_strcmp0 (property, "average-bitrate") == 0) {
1489 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1490 offsetof (uvcx_bitrate_layers_t, dwAverageBitrate), 4,
1491 &min32, &def32, &max32);
1495 } else if (g_strcmp0 (property, "min-iframe-qp") == 0) {
1496 if (update_qp (self, QP_I_FRAME))
1497 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1498 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1502 } else if (g_strcmp0 (property, "max-iframe-qp") == 0) {
1503 if (update_qp (self, QP_I_FRAME))
1504 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1505 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1509 } else if (g_strcmp0 (property, "min-pframe-qp") == 0) {
1510 if (update_qp (self, QP_P_FRAME))
1511 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1512 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1516 } else if (g_strcmp0 (property, "max-pframe-qp") == 0) {
1517 if (update_qp (self, QP_P_FRAME))
1518 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1519 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1523 } else if (g_strcmp0 (property, "min-bframe-qp") == 0) {
1524 if (update_qp (self, QP_B_FRAME))
1525 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1526 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1530 } else if (g_strcmp0 (property, "max-bframe-qp") == 0) {
1531 if (update_qp (self, QP_B_FRAME))
1532 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1533 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1537 } else if (g_strcmp0 (property, "ltr-buffer-size") == 0) {
1538 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1539 offsetof (uvcx_ltr_buffer_size_control_t, bLTRBufferSize), 1,
1540 &min8, &def8, &max8);
1544 } else if (g_strcmp0 (property, "ltr-encoder-control") == 0) {
1545 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1546 offsetof (uvcx_ltr_buffer_size_control_t, bLTREncoderControl), 1,
1547 &min8, &def8, &max8);
1557 gst_uvc_h264_src_event_probe (GstPad * pad, GstEvent * event,
1560 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1561 gboolean ret = TRUE;
1563 switch (GST_EVENT_TYPE (event)) {
1565 ret = !self->reconfiguring;
1567 case GST_EVENT_NEWSEGMENT:
1568 if (pad == self->vidsrc) {
1569 ret = !self->vid_newseg;
1570 self->vid_newseg = TRUE;
1571 } else if (pad == self->vfsrc) {
1572 ret = !self->vf_newseg;
1573 self->vf_newseg = TRUE;
1584 gst_uvc_h264_src_buffer_probe (GstPad * pad, GstBuffer * buffer,
1587 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1589 /* TODO: Check the NALU type and make sure it is a keyframe */
1590 if (self->key_unit_event) {
1591 GstClockTime ts, running_time, stream_time;
1592 gboolean all_headers;
1594 GstEvent *downstream;
1596 if (gst_video_event_parse_upstream_force_key_unit (self->key_unit_event,
1597 &ts, &all_headers, &count)) {
1598 if (!GST_CLOCK_TIME_IS_VALID (ts)) {
1599 ts = GST_BUFFER_TIMESTAMP (buffer);
1601 running_time = gst_segment_to_running_time (&self->segment,
1602 GST_FORMAT_TIME, ts);
1604 stream_time = gst_segment_to_stream_time (&self->segment,
1605 GST_FORMAT_TIME, ts);
1607 GST_DEBUG_OBJECT (self, "Sending downstream force-key-unit : %d - %d ts=%"
1608 GST_TIME_FORMAT " running time =%" GST_TIME_FORMAT " stream=%"
1609 GST_TIME_FORMAT, all_headers, count, GST_TIME_ARGS (ts),
1610 GST_TIME_ARGS (running_time), GST_TIME_ARGS (stream_time));
1611 downstream = gst_video_event_new_downstream_force_key_unit (ts,
1612 running_time, stream_time, all_headers, count);
1613 gst_pad_push_event (self->vidsrc, downstream);
1614 gst_event_replace (&self->key_unit_event, NULL);
1621 gst_uvc_h264_src_parse_event (GstUvcH264Src * self, GstPad * pad,
1624 const GstStructure *s = gst_event_get_structure (event);
1626 switch (GST_EVENT_TYPE (event)) {
1627 case GST_EVENT_CUSTOM_UPSTREAM:
1628 if (pad == self->vidsrc && self->main_format == UVC_H264_SRC_FORMAT_H264) {
1629 if (gst_video_event_is_force_key_unit (event)) {
1630 uvcx_picture_type_control_t req = { 0, 0 };
1632 gboolean all_headers;
1634 if (gst_video_event_parse_upstream_force_key_unit (event,
1635 &ts, &all_headers, NULL)) {
1636 GST_INFO_OBJECT (self, "Received upstream force-key-unit : %d %"
1637 GST_TIME_FORMAT, all_headers, GST_TIME_ARGS (ts));
1638 /* TODO: wait until 'ts' time is reached */
1640 req.wPicType = UVC_H264_PICTYPE_IDR_WITH_PPS_SPS;
1642 req.wPicType = UVC_H264_PICTYPE_IDR;
1644 if (!xu_query (self, UVCX_PICTURE_TYPE_CONTROL, UVC_SET_CUR,
1645 (guchar *) & req)) {
1646 GST_WARNING_OBJECT (self, " PICTURE_TYPE_CONTROL SET_CUR error");
1648 gst_event_replace (&self->key_unit_event, event);
1649 gst_event_unref (event);
1655 gst_structure_has_name (s, "uvc-h264-ltr-picture-control")) {
1656 guint put_at, encode_using;
1658 if (gst_structure_get_uint (s, "put-at", &put_at) &&
1659 gst_structure_get_uint (s, "encode-using", &encode_using)) {
1660 uvcx_ltr_picture_control req = { 0, put_at, encode_using };
1662 if (!xu_query (self, UVCX_LTR_PICTURE_CONTROL, UVC_SET_CUR,
1663 (guchar *) & req)) {
1664 GST_WARNING_OBJECT (self, " LTR PICTURE_CONTROL SET_CUR error");
1666 gst_event_unref (event);
1672 } else if (s && gst_structure_has_name (s, "uvc-h264-bitrate-control")) {
1673 guint average, peak;
1675 if (gst_structure_get_uint (s, "average-bitrate", &average) &&
1676 gst_structure_get_uint (s, "peak-bitrate", &peak)) {
1677 self->average_bitrate = average;
1678 self->peak_bitrate = peak;
1680 update_bitrate (self);
1682 gst_event_unref (event);
1686 } else if (s && gst_structure_has_name (s, "uvc-h264-qp-control")) {
1687 gint min_qp, max_qp;
1688 gboolean valid_event = FALSE;
1690 if (gst_structure_get_int (s, "min-iframe-qp", &min_qp) &&
1691 gst_structure_get_int (s, "max-iframe-qp", &max_qp)) {
1692 self->min_qp[QP_I_FRAME] = min_qp;
1693 self->max_qp[QP_I_FRAME] = max_qp;
1694 set_qp (self, QP_I_FRAME);
1695 update_qp (self, QP_I_FRAME);
1698 if (gst_structure_get_int (s, "min-pframe-qp", &min_qp) &&
1699 gst_structure_get_int (s, "max-pframe-qp", &max_qp)) {
1700 self->min_qp[QP_P_FRAME] = min_qp;
1701 self->max_qp[QP_P_FRAME] = max_qp;
1702 set_qp (self, QP_P_FRAME);
1703 update_qp (self, QP_P_FRAME);
1706 if (gst_structure_get_int (s, "min-bframe-qp", &min_qp) &&
1707 gst_structure_get_int (s, "max-bframe-qp", &max_qp)) {
1708 self->min_qp[QP_B_FRAME] = min_qp;
1709 self->max_qp[QP_B_FRAME] = max_qp;
1710 set_qp (self, QP_B_FRAME);
1711 update_qp (self, QP_B_FRAME);
1716 gst_event_unref (event);
1720 } else if (s && gst_structure_has_name (s, "uvc-h264-rate-control")) {
1721 UvcH264RateControl rate;
1722 gboolean fixed_framerate;
1724 if (gst_structure_get_enum (s, "rate-control",
1725 UVC_H264_RATECONTROL_TYPE, (gint *) & rate) &&
1726 gst_structure_get_boolean (s, "fixed-framerate",
1727 &fixed_framerate)) {
1728 self->rate_control = rate;
1729 self->fixed_framerate = fixed_framerate;
1730 set_rate_control (self);
1731 update_rate_control (self);
1733 gst_event_unref (event);
1737 } else if (s && gst_structure_has_name (s, "uvc-h264-level-idc")) {
1740 if (gst_structure_get_uint (s, "level-idc", &level_idc)) {
1741 self->level_idc = level_idc;
1742 set_level_idc (self);
1743 update_level_idc_and_get_max_mbps (self);
1745 gst_event_unref (event);
1749 if (s && gst_structure_has_name (s, "renegotiate")) {
1750 GST_DEBUG_OBJECT (self, "Received renegotiate on %s",
1751 GST_PAD_NAME (pad));
1752 /* TODO: Do not reconstruct pipeline twice if we receive
1753 the event on both pads */
1754 if (GST_STATE (self) >= GST_STATE_READY) {
1755 /* TODO: diff the caps */
1756 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
1769 gst_uvc_h264_src_send_event (GstElement * element, GstEvent * event)
1771 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
1773 if (gst_uvc_h264_src_parse_event (self, self->vidsrc, event))
1776 return GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
1780 gst_uvc_h264_src_event (GstPad * pad, GstEvent * event)
1782 GstUvcH264Src *self = GST_UVC_H264_SRC (GST_PAD_PARENT (pad));
1784 switch (GST_EVENT_TYPE (event)) {
1785 case GST_EVENT_NEWSEGMENT:
1786 if (!self->vid_newseg && pad == self->vidsrc) {
1788 gdouble rate, applied_rate;
1790 gint64 start, stop, position;
1792 gst_event_parse_new_segment_full (event, &update, &rate,
1793 &applied_rate, &format, &start, &stop, &position);
1794 gst_segment_set_newsegment (&self->segment, update, rate, format,
1795 start, stop, position);
1798 case GST_EVENT_FLUSH_STOP:
1799 if (pad == self->vidsrc) {
1800 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
1801 self->vid_newseg = FALSE;
1803 if (pad == self->vfsrc)
1804 self->vf_newseg = FALSE;
1807 if (gst_uvc_h264_src_parse_event (self, pad, event))
1811 return self->srcpad_event_func (pad, event);
1815 xu_get_id (GstUvcH264Src * self)
1817 struct uvc_xu_find_unit xu;
1818 static const __u8 guid[16] = GUID_UVCX_H264_XU;
1820 if (self->v4l2_fd == -1) {
1821 GST_WARNING_OBJECT (self, "Can't query XU with fd = -1");
1825 memcpy (xu.guid, guid, 16);
1828 if (-1 == ioctl (self->v4l2_fd, UVCIOC_XU_FIND_UNIT, &xu)) {
1829 #if defined (HAVE_GUDEV) && defined (HAVE_LIBUSB)
1830 /* Fallback on libusb */
1831 GUdevClient *client;
1832 GUdevDevice *udevice;
1833 GUdevDevice *parent;
1836 libusb_device **device_list = NULL;
1837 libusb_device *device = NULL;
1841 GST_DEBUG_OBJECT (self, "XU_FIND_UNIT ioctl failed. Fallback on libusb");
1843 if (self->usb_ctx == NULL)
1844 libusb_init (&self->usb_ctx);
1846 client = g_udev_client_new (NULL);
1848 udevice = g_udev_client_query_by_device_file (client, self->device);
1850 parent = g_udev_device_get_parent_with_subsystem (udevice, "usb",
1853 busnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "busnum");
1854 devnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "devnum");
1856 cnt = libusb_get_device_list (self->usb_ctx, &device_list);
1857 for (i = 0; i < cnt; i++) {
1858 if (busnum == libusb_get_bus_number (device_list[i]) &&
1859 devnum == libusb_get_device_address (device_list[i])) {
1860 device = libusb_ref_device (device_list[i]);
1864 libusb_free_device_list (device_list, 1);
1865 g_object_unref (parent);
1867 g_object_unref (udevice);
1869 g_object_unref (client);
1873 struct libusb_device_descriptor desc;
1875 if (libusb_get_device_descriptor (device, &desc) == 0) {
1876 for (i = 0; i < desc.bNumConfigurations; ++i) {
1877 struct libusb_config_descriptor *config = NULL;
1879 if (libusb_get_config_descriptor (device, i, &config) == 0) {
1880 for (j = 0; j < config->bNumInterfaces; j++) {
1881 for (k = 0; k < config->interface[j].num_altsetting; k++) {
1882 const struct libusb_interface_descriptor *interface;
1883 const guint8 *ptr = NULL;
1885 interface = &config->interface[j].altsetting[k];
1886 if (interface->bInterfaceClass != LIBUSB_CLASS_VIDEO ||
1887 interface->bInterfaceSubClass != USB_VIDEO_CONTROL)
1889 ptr = interface->extra;
1890 while (ptr - interface->extra +
1891 sizeof (xu_descriptor) < interface->extra_length) {
1892 xu_descriptor *desc = (xu_descriptor *) ptr;
1894 GST_DEBUG_OBJECT (self, "Found VideoControl interface with "
1895 "unit id %d : %" GUID_FORMAT, desc->bUnitID,
1896 GUID_ARGS (desc->guidExtensionCode));
1897 if (desc->bDescriptorType == USB_VIDEO_CONTROL_INTERFACE &&
1898 desc->bDescriptorSubType == USB_VIDEO_CONTROL_XU_TYPE &&
1899 memcmp (desc->guidExtensionCode, guid, 16) == 0) {
1900 guint8 unit_id = desc->bUnitID;
1902 GST_DEBUG_OBJECT (self, "Found H264 XU unit : %d", unit_id);
1904 libusb_unref_device (device);
1907 ptr += desc->bLength;
1914 libusb_unref_device (device);
1917 GST_WARNING_OBJECT (self, "XU_FIND_UNIT ioctl failed");
1926 xu_query (GstUvcH264Src * self, guint selector, guint query, guchar * data)
1928 struct uvc_xu_control_query xu;
1931 if (self->v4l2_fd == -1) {
1932 GST_WARNING_OBJECT (self, "Can't query XU with fd = -1");
1936 xu.unit = self->h264_unit_id;
1937 xu.selector = selector;
1939 xu.query = UVC_GET_LEN;
1940 xu.size = sizeof (len);
1941 xu.data = (unsigned char *) &len;
1942 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1943 GST_WARNING_OBJECT (self, "PROBE GET_LEN error");
1947 if (query == UVC_GET_LEN) {
1948 *((__u16 *) data) = len;
1953 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1962 fill_probe_commit (GstUvcH264Src * self,
1963 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
1964 guint32 width, guint32 height, guint32 profile,
1965 UvcH264StreamFormat stream_format)
1967 probe->dwFrameInterval = frame_interval;
1968 probe->dwBitRate = self->initial_bitrate;
1969 probe->wWidth = width;
1970 probe->wHeight = height;
1971 probe->wSliceUnits = self->slice_units;
1972 probe->wSliceMode = self->slice_mode;
1973 probe->wProfile = profile;
1974 probe->wIFramePeriod = self->iframe_period;
1975 probe->bUsageType = self->usage_type;
1976 probe->bRateControlMode = self->rate_control;
1977 if (self->fixed_framerate)
1978 probe->bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
1979 probe->bStreamFormat = stream_format;
1980 probe->bEntropyCABAC = self->entropy;
1981 probe->bTimestamp = self->enable_sei ?
1982 UVC_H264_TIMESTAMP_SEI_ENABLE : UVC_H264_TIMESTAMP_SEI_DISABLE;
1983 probe->bNumOfReorderFrames = self->num_reorder_frames;
1984 probe->bPreviewFlipped = self->preview_flipped ?
1985 UVC_H264_PREFLIPPED_HORIZONTAL : UVC_H264_PREFLIPPED_DISABLE;
1986 probe->wLeakyBucketSize = self->leaky_bucket_size;
1990 print_probe_commit (GstUvcH264Src * self,
1991 uvcx_video_config_probe_commit_t * probe)
1993 GST_DEBUG_OBJECT (self, " Frame interval : %d *100ns",
1994 probe->dwFrameInterval);
1995 GST_DEBUG_OBJECT (self, " Bit rate : %d", probe->dwBitRate);
1996 GST_DEBUG_OBJECT (self, " Hints : %X", probe->bmHints);
1997 GST_DEBUG_OBJECT (self, " Configuration index : %d",
1998 probe->wConfigurationIndex);
1999 GST_DEBUG_OBJECT (self, " Width : %d", probe->wWidth);
2000 GST_DEBUG_OBJECT (self, " Height : %d", probe->wHeight);
2001 GST_DEBUG_OBJECT (self, " Slice units : %d", probe->wSliceUnits);
2002 GST_DEBUG_OBJECT (self, " Slice mode : %X", probe->wSliceMode);
2003 GST_DEBUG_OBJECT (self, " Profile : %X", probe->wProfile);
2004 GST_DEBUG_OBJECT (self, " IFrame Period : %d ms", probe->wIFramePeriod);
2005 GST_DEBUG_OBJECT (self, " Estimated video delay : %d ms",
2006 probe->wEstimatedVideoDelay);
2007 GST_DEBUG_OBJECT (self, " Estimated max config delay : %d ms",
2008 probe->wEstimatedMaxConfigDelay);
2009 GST_DEBUG_OBJECT (self, " Usage type : %X", probe->bUsageType);
2010 GST_DEBUG_OBJECT (self, " Rate control mode : %X", probe->bRateControlMode);
2011 GST_DEBUG_OBJECT (self, " Temporal scale mode : %X",
2012 probe->bTemporalScaleMode);
2013 GST_DEBUG_OBJECT (self, " Spatial scale mode : %X",
2014 probe->bSpatialScaleMode);
2015 GST_DEBUG_OBJECT (self, " SNR scale mode : %X", probe->bSNRScaleMode);
2016 GST_DEBUG_OBJECT (self, " Stream mux option : %X", probe->bStreamMuxOption);
2017 GST_DEBUG_OBJECT (self, " Stream Format : %X", probe->bStreamFormat);
2018 GST_DEBUG_OBJECT (self, " Entropy CABAC : %X", probe->bEntropyCABAC);
2019 GST_DEBUG_OBJECT (self, " Timestamp : %X", probe->bTimestamp);
2020 GST_DEBUG_OBJECT (self, " Num of reorder frames : %d",
2021 probe->bNumOfReorderFrames);
2022 GST_DEBUG_OBJECT (self, " Preview flipped : %X", probe->bPreviewFlipped);
2023 GST_DEBUG_OBJECT (self, " View : %d", probe->bView);
2024 GST_DEBUG_OBJECT (self, " Stream ID : %X", probe->bStreamID);
2025 GST_DEBUG_OBJECT (self, " Spatial layer ratio : %f",
2026 ((probe->bSpatialLayerRatio & 0xF0) >> 4) +
2027 ((float) (probe->bSpatialLayerRatio & 0x0F)) / 16);
2028 GST_DEBUG_OBJECT (self, " Leaky bucket size : %d ms",
2029 probe->wLeakyBucketSize);
2033 configure_h264 (GstUvcH264Src * self, gint fd)
2035 uvcx_video_config_probe_commit_t probe;
2037 /* Set the secondary format first, so the last SET_CUR will be for the
2038 * H264 format. This way, we can still get the static control values with
2039 * a GET_CUR. Otherwise all static properties will return 0 because that's
2040 * what the GET_CUR of the raw format returns.
2042 if (self->secondary_format == UVC_H264_SRC_FORMAT_RAW) {
2043 memset (&probe, 0, sizeof (probe));
2044 probe.dwFrameInterval = self->secondary_frame_interval;
2045 probe.wWidth = self->secondary_width;
2046 probe.wHeight = self->secondary_height;
2047 probe.bStreamMuxOption = 5;
2049 GST_DEBUG_OBJECT (self, "RAW PROBE SET_CUR : ");
2050 print_probe_commit (self, &probe);
2052 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2053 (guchar *) & probe)) {
2054 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2058 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2059 (guchar *) & probe)) {
2060 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2063 GST_DEBUG_OBJECT (self, "RAW PROBE GET_CUR : ");
2064 print_probe_commit (self, &probe);
2066 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
2067 (guchar *) & probe)) {
2068 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
2072 /* Print MIN/MAX/DEF probe values for debugging purposes */
2073 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MIN,
2074 (guchar *) & probe)) {
2075 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2078 GST_DEBUG_OBJECT (self, "PROBE GET_MIN : ");
2079 print_probe_commit (self, &probe);
2081 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MAX,
2082 (guchar *) & probe)) {
2083 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2086 GST_DEBUG_OBJECT (self, "PROBE GET_MAX : ");
2087 print_probe_commit (self, &probe);
2089 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_DEF,
2090 (guchar *) & probe)) {
2091 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2094 GST_DEBUG_OBJECT (self, "PROBE GET_DEF : ");
2095 print_probe_commit (self, &probe);
2097 fill_probe_commit (self, &probe, self->main_frame_interval,
2098 self->main_width, self->main_height, self->main_profile,
2099 self->main_stream_format);
2100 if (self->secondary_format != UVC_H264_SRC_FORMAT_NONE)
2101 probe.bStreamMuxOption = 3;
2103 probe.bStreamMuxOption = 0;
2104 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION | UVC_H264_BMHINTS_PROFILE |
2105 UVC_H264_BMHINTS_FRAME_INTERVAL;
2107 GST_DEBUG_OBJECT (self, "PROBE SET_CUR : ");
2108 print_probe_commit (self, &probe);
2110 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2111 (guchar *) & probe)) {
2112 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2116 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2117 (guchar *) & probe)) {
2118 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2121 GST_DEBUG_OBJECT (self, "PROBE GET_CUR : ");
2122 print_probe_commit (self, &probe);
2124 /* Must validate the settings accepted by the encoder */
2125 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
2126 (guchar *) & probe)) {
2127 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
2133 v4l2src_prepare_format (GstElement * v4l2src, gint fd, guint fourcc,
2134 guint width, guint height, gpointer user_data)
2136 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
2138 GST_DEBUG_OBJECT (self, "v4l2src prepare-format with FCC %" GST_FOURCC_FORMAT,
2139 GST_FOURCC_ARGS (fourcc));
2141 if (self->main_format == UVC_H264_SRC_FORMAT_H264) {
2142 /* TODO: update static controls and g_object_notify those that changed */
2143 configure_h264 (self, fd);
2145 /* TODO: update dynamic controls on READY state */
2146 /* Configure dynamic controls */
2147 set_rate_control (self);
2148 update_rate_control (self);
2149 set_level_idc (self);
2150 update_level_idc_and_get_max_mbps (self);
2152 update_bitrate (self);
2153 set_qp (self, QP_I_FRAME);
2154 update_qp (self, QP_I_FRAME);
2155 set_qp (self, QP_P_FRAME);
2156 update_qp (self, QP_P_FRAME);
2157 set_qp (self, QP_B_FRAME);
2158 update_qp (self, QP_B_FRAME);
2165 _extract_caps_info (GstStructure * structure, guint16 * width, guint16 * height,
2166 guint32 * frame_interval)
2168 gint w, h, fps_n, fps_d;
2169 gboolean ret = TRUE;
2171 ret &= gst_structure_get_int (structure, "width", &w);
2172 ret &= gst_structure_get_int (structure, "height", &h);
2173 ret &= gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
2178 /* Interval is in 100ns */
2179 *frame_interval = GST_TIME_AS_NSECONDS ((fps_d * GST_SECOND) / fps_n) / 100;
2186 _extract_profile (GstStructure * structure)
2188 const gchar *profile_str;
2191 profile = UVC_H264_PROFILE_HIGH;
2192 profile_str = gst_structure_get_string (structure, "profile");
2194 if (!strcmp (profile_str, "constrained-baseline")) {
2195 profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
2196 } else if (!strcmp (profile_str, "baseline")) {
2197 profile = UVC_H264_PROFILE_BASELINE;
2198 } else if (!strcmp (profile_str, "main")) {
2199 profile = UVC_H264_PROFILE_MAIN;
2200 } else if (!strcmp (profile_str, "high")) {
2201 profile = UVC_H264_PROFILE_HIGH;
2207 static UvcH264StreamFormat
2208 _extract_stream_format (GstStructure * structure)
2210 const gchar *stream_format;
2212 stream_format = gst_structure_get_string (structure, "stream-format");
2213 if (stream_format) {
2214 if (!strcmp (stream_format, "avc"))
2215 return UVC_H264_STREAMFORMAT_NAL;
2216 else if (!strcmp (stream_format, "byte-stream"))
2217 return UVC_H264_STREAMFORMAT_ANNEXB;
2219 return UVC_H264_STREAMFORMAT_ANNEXB;
2223 _transform_caps (GstUvcH264Src * self, GstCaps * caps, const gchar * name)
2225 GstElement *el = gst_element_factory_make (name, NULL);
2226 GstElement *cf = gst_element_factory_make ("capsfilter", NULL);
2229 if (!el || !cf || !gst_bin_add (GST_BIN (self), el)) {
2231 gst_object_unref (el);
2233 gst_object_unref (cf);
2236 if (!gst_bin_add (GST_BIN (self), cf)) {
2237 gst_object_unref (cf);
2238 gst_bin_remove (GST_BIN (self), el);
2241 if (!gst_element_link (el, cf))
2244 sink = gst_element_get_static_pad (el, "sink");
2247 g_object_set (cf, "caps", caps, NULL);
2249 caps = gst_pad_get_caps (sink);
2250 gst_object_unref (sink);
2253 gst_bin_remove (GST_BIN (self), cf);
2254 gst_bin_remove (GST_BIN (self), el);
2261 gst_uvc_h264_src_transform_caps (GstUvcH264Src * self, GstCaps * caps)
2263 GstCaps *h264 = gst_caps_new_simple ("video/x-h264", NULL);
2264 GstCaps *jpg = gst_caps_new_simple ("image/jpeg", NULL);
2265 GstCaps *h264_caps = gst_caps_intersect (h264, caps);
2266 GstCaps *jpg_caps = gst_caps_intersect (jpg, caps);
2268 /* TODO: Keep caps order after transformation */
2269 caps = _transform_caps (self, caps, self->colorspace_name);
2271 if (!gst_caps_is_empty (h264_caps)) {
2272 GstCaps *temp = gst_caps_union (caps, h264_caps);
2273 gst_caps_unref (caps);
2276 if (!gst_caps_is_empty (jpg_caps)) {
2277 GstCaps *temp = gst_caps_union (caps, jpg_caps);
2278 gst_caps_unref (caps);
2283 gst_caps_unref (h264_caps);
2285 gst_caps_unref (jpg_caps);
2286 gst_caps_unref (h264);
2287 gst_caps_unref (jpg);
2294 gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad,
2295 GstCaps * v4l_caps, GstCaps * peer_caps, gboolean primary)
2297 GstCaps *caps = NULL;
2298 GstCaps *icaps = NULL;
2299 GstCaps *tcaps = NULL;
2302 if (v4l_caps == NULL || gst_caps_is_any (v4l_caps)) {
2303 GST_DEBUG_OBJECT (self, "v4l caps are invalid. not fixating");
2307 tcaps = gst_caps_intersect_full (peer_caps, v4l_caps,
2308 GST_CAPS_INTERSECT_FIRST);
2309 GST_DEBUG_OBJECT (self, "intersect: %" GST_PTR_FORMAT, tcaps);
2310 icaps = gst_caps_normalize (tcaps);
2311 gst_caps_unref (tcaps);
2313 /* Prefer the first caps we are compatible with that the peer proposed */
2314 for (i = 0; i < gst_caps_get_size (icaps); i++) {
2315 /* get intersection */
2316 GstCaps *ipcaps = gst_caps_copy_nth (icaps, i);
2317 GstStructure *s = gst_caps_get_structure (ipcaps, 0);
2319 GST_DEBUG_OBJECT (self, "Testing %s: %" GST_PTR_FORMAT,
2320 primary ? "primary" : "secondary", ipcaps);
2321 if (primary && gst_structure_has_name (s, "video/x-h264")) {
2322 uvcx_video_config_probe_commit_t probe;
2327 UvcH264StreamFormat stream_format;
2329 if (_extract_caps_info (s, &width, &height, &interval)) {
2330 profile = _extract_profile (s);
2331 stream_format = _extract_stream_format (s);
2332 fill_probe_commit (self, &probe, interval, width, height,
2333 profile, stream_format);
2334 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2335 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2337 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2338 (guchar *) & probe)) {
2339 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2343 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2344 (guchar *) & probe)) {
2345 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2348 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d==%d",
2349 probe.wWidth, width, probe.wHeight, height,
2350 probe.bStreamFormat, stream_format);
2351 if (probe.wWidth == width && probe.wHeight == height &&
2352 probe.bStreamFormat == stream_format) {
2357 } else if (!primary && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2358 uvcx_video_config_probe_commit_t probe;
2363 if (_extract_caps_info (s, &width, &height, &interval)) {
2364 if (gst_structure_has_name (s, "video/x-raw-yuv")) {
2368 if (gst_structure_get_fourcc (s, "format", &fcc)) {
2369 if (fcc == GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'))
2371 else if (fcc == GST_MAKE_FOURCC ('N', 'V', '1', '2'))
2375 memset (&probe, 0, sizeof (probe));
2376 probe.dwFrameInterval = interval;
2377 probe.wWidth = width;
2378 probe.wHeight = height;
2379 probe.bStreamMuxOption = mux | 1;
2380 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2381 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2383 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2384 (guchar *) & probe)) {
2385 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2389 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2390 (guchar *) & probe)) {
2391 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2394 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d~=%d",
2395 probe.wWidth, width, probe.wHeight, height,
2396 probe.bStreamMuxOption, mux);
2397 if (probe.wWidth == width && probe.wHeight == height &&
2398 (probe.bStreamMuxOption & mux) != 0) {
2403 } else if (gst_structure_has_name (s, "image/jpeg")) {
2404 /* HACK ALERT: No way of figuring this one out but it seems the
2405 * camera doesn't allow for h264 muxing and jpeg resolution higher
2406 * than 640x480 so we shouldn't allow it */
2407 if (width <= 640 && height <= 480) {
2417 gst_caps_unref (ipcaps);
2421 caps = gst_caps_make_writable (caps);
2422 gst_caps_truncate (caps);
2425 if (!gst_caps_is_empty (caps)) {
2426 gst_pad_fixate_caps (v4l_pad, caps);
2427 GST_DEBUG_OBJECT (self, "fixated to: %" GST_PTR_FORMAT, caps);
2430 if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
2431 gst_caps_unref (caps);
2440 gst_uvc_h264_src_destroy_pipeline (GstUvcH264Src * self, gboolean v4l2src)
2442 GstIterator *iter = NULL;
2445 if (v4l2src && self->v4l2_src) {
2446 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2447 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2448 gst_object_unref (self->v4l2_src);
2449 self->v4l2_src = NULL;
2451 self->h264_unit_id = 0;
2453 if (self->mjpg_demux) {
2454 gst_bin_remove (GST_BIN (self), self->mjpg_demux);
2455 gst_element_set_state (self->mjpg_demux, GST_STATE_NULL);
2456 gst_object_unref (self->mjpg_demux);
2457 self->mjpg_demux = NULL;
2459 if (self->jpeg_dec) {
2460 gst_bin_remove (GST_BIN (self), self->jpeg_dec);
2461 gst_element_set_state (self->jpeg_dec, GST_STATE_NULL);
2462 gst_object_unref (self->jpeg_dec);
2463 self->jpeg_dec = NULL;
2465 if (self->vid_colorspace) {
2466 gst_bin_remove (GST_BIN (self), self->vid_colorspace);
2467 gst_element_set_state (self->vid_colorspace, GST_STATE_NULL);
2468 gst_object_unref (self->vid_colorspace);
2469 self->vid_colorspace = NULL;
2471 if (self->vf_colorspace) {
2472 gst_bin_remove (GST_BIN (self), self->vf_colorspace);
2473 gst_element_set_state (self->vf_colorspace, GST_STATE_NULL);
2474 gst_object_unref (self->vf_colorspace);
2475 self->vf_colorspace = NULL;
2477 iter = gst_bin_iterate_elements (GST_BIN (self));
2480 GstElement *item = NULL;
2482 switch (gst_iterator_next (iter, (gpointer *) & item)) {
2483 case GST_ITERATOR_OK:
2484 if (item != self->v4l2_src) {
2485 gst_bin_remove (GST_BIN (self), item);
2486 gst_element_set_state (item, GST_STATE_NULL);
2488 gst_object_unref (item);
2490 case GST_ITERATOR_RESYNC:
2491 gst_iterator_resync (iter);
2493 case GST_ITERATOR_ERROR:
2496 case GST_ITERATOR_DONE:
2501 gst_iterator_free (iter);
2505 ensure_v4l2src (GstUvcH264Src * self)
2507 gchar *device = NULL;
2508 GstClock *v4l2_clock = NULL;
2510 if (self->v4l2_src == NULL) {
2511 /* Create v4l2 source and set it up */
2512 self->v4l2_src = gst_element_factory_make ("v4l2src", NULL);
2513 if (!self->v4l2_src || !gst_bin_add (GST_BIN (self), self->v4l2_src))
2515 gst_object_ref (self->v4l2_src);
2516 g_signal_connect (self->v4l2_src, "prepare-format",
2517 (GCallback) v4l2src_prepare_format, self);
2520 g_object_get (self->v4l2_src, "device", &device, NULL);
2521 g_object_set (self->v4l2_src,
2522 "device", self->device, "num-buffers", self->num_buffers, NULL);
2524 v4l2_clock = gst_element_get_clock (self->v4l2_src);
2526 /* Set to NULL if the device changed */
2527 if (g_strcmp0 (device, self->device))
2528 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2531 if (gst_element_set_state (self->v4l2_src, GST_STATE_READY) !=
2532 GST_STATE_CHANGE_SUCCESS) {
2533 GST_DEBUG_OBJECT (self, "Unable to set v4l2src to READY state");
2537 /* Set/Update the fd and unit id after we go to READY */
2538 g_object_get (self->v4l2_src, "device-fd", &self->v4l2_fd, NULL);
2539 self->h264_unit_id = xu_get_id (self);
2541 if (self->h264_unit_id == 0) {
2542 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
2543 ("Device is not a valid UVC H264 camera"), (NULL));
2547 /* going to state READY makes v4l2src lose its reference to the clock */
2549 gst_element_set_clock (self->v4l2_src, v4l2_clock);
2550 gst_element_set_base_time (self->v4l2_src,
2551 gst_element_get_base_time (GST_ELEMENT (self)));
2552 gst_object_unref (v4l2_clock);
2558 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2559 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2563 gst_object_unref (self->v4l2_src);
2564 self->v4l2_src = NULL;
2566 self->h264_unit_id = 0;
2572 gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
2574 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
2575 GstIterator *iter = NULL;
2576 gboolean iter_done = FALSE;
2577 GstPad *vf_pad = NULL;
2578 GstCaps *vf_caps = NULL;
2579 GstStructure *vf_struct = NULL;
2580 GstPad *vid_pad = NULL;
2581 GstCaps *vid_caps = NULL;
2582 GstStructure *vid_struct = NULL;
2583 GstCaps *src_caps = NULL;
2584 GstPad *v4l_pad = NULL;
2585 GstCaps *v4l_caps = NULL;
2586 gboolean jpg2raw = FALSE;
2590 RAW_NONE, ENCODED_NONE, NONE_RAW, NONE_ENCODED,
2591 H264_JPG, H264_RAW, H264_JPG2RAW, NONE_NONE,
2592 RAW_RAW, ENCODED_ENCODED,
2595 GST_DEBUG_OBJECT (self, "Construct pipeline");
2596 self->reconfiguring = TRUE;
2598 if (self->v4l2_src) {
2599 uvcx_encoder_reset req = { 0 };
2601 if (!xu_query (self, UVCX_ENCODER_RESET, UVC_SET_CUR, (guchar *) & req))
2602 GST_WARNING_OBJECT (self, " UVCX_ENCODER_RESET SET_CUR error");
2605 if (!ensure_v4l2src (self))
2608 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
2610 /* Potentially unlink v4l2src to the ghost pads */
2611 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), NULL);
2612 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), NULL);
2614 vf_caps = gst_pad_peer_get_caps (self->vfsrc);
2615 vid_caps = gst_pad_peer_get_caps (self->vidsrc);
2617 GST_DEBUG_OBJECT (self, "vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2618 GST_DEBUG_OBJECT (self, "vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2619 if (!self->started) {
2620 GST_DEBUG_OBJECT (self, "video not started. Ignoring vidsrc caps");
2622 gst_caps_unref (vid_caps);
2626 v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2627 v4l_caps = gst_pad_get_caps (v4l_pad);
2628 GST_DEBUG_OBJECT (self, "v4l2src caps : %" GST_PTR_FORMAT, v4l_caps);
2630 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vid_caps);
2632 gst_caps_unref (vid_caps);
2633 vid_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2635 gst_caps_unref (trans_caps);
2638 vid_struct = gst_caps_get_structure (vid_caps, 0);
2640 GST_WARNING_OBJECT (self, "Could not negotiate vidsrc caps format");
2641 gst_object_unref (v4l_pad);
2642 gst_caps_unref (v4l_caps);
2646 GST_DEBUG_OBJECT (self, "Fixated vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2648 if (vid_caps && gst_structure_has_name (vid_struct, "video/x-h264")) {
2649 self->main_format = UVC_H264_SRC_FORMAT_H264;
2650 if (!_extract_caps_info (vid_struct, &self->main_width,
2651 &self->main_height, &self->main_frame_interval)) {
2652 gst_object_unref (v4l_pad);
2653 gst_caps_unref (v4l_caps);
2657 self->main_stream_format = _extract_stream_format (vid_struct);
2658 self->main_profile = _extract_profile (vid_struct);
2660 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2664 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vf_caps);
2666 gst_caps_unref (vf_caps);
2667 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2670 /* If we couldn't find a suitable vf cap, try the jpeg2raw pipeline */
2671 if (!vf_caps && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2675 jpg_caps = _transform_caps (self, trans_caps, self->jpeg_decoder_name);
2677 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2679 gst_caps_unref (jpg_caps);
2681 gst_caps_unref (trans_caps);
2683 vf_struct = gst_caps_get_structure (vf_caps, 0);
2685 GST_WARNING_OBJECT (self, "Could not negotiate vfsrc caps format");
2686 gst_object_unref (v4l_pad);
2687 gst_caps_unref (v4l_caps);
2691 GST_DEBUG_OBJECT (self, "Fixated vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2692 gst_object_unref (v4l_pad);
2693 gst_caps_unref (v4l_caps);
2695 if (vf_caps && vid_caps &&
2696 !gst_structure_has_name (vid_struct, "video/x-h264")) {
2697 /* Allow for vfsrc+vidsrc to both be raw or jpeg */
2698 if (gst_structure_has_name (vid_struct, "image/jpeg") &&
2699 gst_structure_has_name (vf_struct, "image/jpeg")) {
2700 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2701 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2702 type = ENCODED_ENCODED;
2703 } else if (!gst_structure_has_name (vid_struct, "image/jpeg") &&
2704 !gst_structure_has_name (vf_struct, "image/jpeg")) {
2705 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2706 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2711 } else if (vf_caps && vid_caps) {
2712 guint32 smallest_frame_interval;
2714 if (!_extract_caps_info (vf_struct, &self->secondary_width,
2715 &self->secondary_height, &self->secondary_frame_interval))
2718 if (jpg2raw == FALSE && gst_structure_has_name (vf_struct, "image/jpeg")) {
2720 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2723 type = H264_JPG2RAW;
2724 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2727 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2730 smallest_frame_interval = MIN (self->main_frame_interval,
2731 self->secondary_frame_interval);
2732 /* Just to avoid a potential division by zero, set interval to 30 fps */
2733 if (smallest_frame_interval == 0)
2734 smallest_frame_interval = 333333;
2736 /* Frame interval is in 100ns units */
2737 src_caps = gst_caps_new_simple ("image/jpeg",
2738 "width", G_TYPE_INT, self->secondary_width,
2739 "height", G_TYPE_INT, self->secondary_height,
2740 "framerate", GST_TYPE_FRACTION,
2741 NSEC_PER_SEC / smallest_frame_interval, 100, NULL);
2742 } else if (vf_caps || vid_caps) {
2743 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2744 if (vid_struct && gst_structure_has_name (vid_struct, "video/x-h264")) {
2745 type = ENCODED_NONE;
2746 } else if (vid_struct && gst_structure_has_name (vid_struct, "image/jpeg")) {
2747 type = ENCODED_NONE;
2748 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2749 } else if (vf_struct && gst_structure_has_name (vf_struct, "image/jpeg")) {
2750 type = NONE_ENCODED;
2751 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2752 } else if (vid_struct) {
2754 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2755 } else if (vf_struct) {
2757 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2759 g_assert_not_reached ();
2763 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2764 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2769 GST_DEBUG_OBJECT (self, "None+None");
2770 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2773 GST_DEBUG_OBJECT (self, "Raw+None");
2774 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2776 if (!self->vid_colorspace ||
2777 !gst_bin_add (GST_BIN (self), self->vid_colorspace))
2779 gst_object_ref (self->vid_colorspace);
2780 if (!gst_element_link (self->v4l2_src, self->vid_colorspace))
2781 goto error_remove_all;
2782 vid_pad = gst_element_get_static_pad (self->vid_colorspace, "src");
2785 GST_DEBUG_OBJECT (self, "None+Raw");
2786 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2788 if (!self->vf_colorspace ||
2789 !gst_bin_add (GST_BIN (self), self->vf_colorspace))
2791 gst_object_ref (self->vf_colorspace);
2792 if (!gst_element_link (self->v4l2_src, self->vf_colorspace))
2793 goto error_remove_all;
2794 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2797 GST_DEBUG_OBJECT (self, "Encoded+None");
2798 vid_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2801 GST_DEBUG_OBJECT (self, "None+Encoded");
2802 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2805 GST_DEBUG_OBJECT (self, "H264+JPG");
2806 self->mjpg_demux = gst_element_factory_make ("uvch264_mjpgdemux", NULL);
2807 if (!self->mjpg_demux || !gst_bin_add (GST_BIN (self), self->mjpg_demux))
2809 gst_object_ref (self->mjpg_demux);
2810 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2811 "num-clock-samples", self->num_clock_samples, NULL);
2812 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2814 goto error_remove_all;
2815 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2816 vf_pad = gst_element_get_static_pad (self->mjpg_demux, "jpeg");
2819 GST_DEBUG_OBJECT (self, "H264+Raw");
2820 self->mjpg_demux = gst_element_factory_make ("uvch264_mjpgdemux", NULL);
2821 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2823 if (!self->mjpg_demux || !self->vf_colorspace)
2825 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2827 gst_object_ref (self->mjpg_demux);
2828 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2829 "num-clock-samples", self->num_clock_samples, NULL);
2830 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace)) {
2831 gst_object_unref (self->vf_colorspace);
2832 self->vf_colorspace = NULL;
2833 goto error_remove_all;
2835 gst_object_ref (self->vf_colorspace);
2836 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2838 goto error_remove_all;
2839 if (!gst_element_link_pads (self->mjpg_demux, "yuy2",
2840 self->vf_colorspace, "sink"))
2841 goto error_remove_all;
2842 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2843 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2846 GST_DEBUG_OBJECT (self, "H264+Raw(jpegdec)");
2847 self->mjpg_demux = gst_element_factory_make ("uvch264_mjpgdemux", NULL);
2848 self->jpeg_dec = gst_element_factory_make (self->jpeg_decoder_name, NULL);
2849 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2851 if (!self->mjpg_demux || !self->jpeg_dec || !self->vf_colorspace)
2853 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2855 gst_object_ref (self->mjpg_demux);
2856 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2857 "num-clock-samples", self->num_clock_samples, NULL);
2858 if (!gst_bin_add (GST_BIN (self), self->jpeg_dec)) {
2859 gst_object_unref (self->jpeg_dec);
2860 self->jpeg_dec = NULL;
2861 gst_object_unref (self->vf_colorspace);
2862 self->vf_colorspace = NULL;
2863 goto error_remove_all;
2865 gst_object_ref (self->jpeg_dec);
2866 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace)) {
2867 gst_object_unref (self->vf_colorspace);
2868 self->vf_colorspace = NULL;
2869 goto error_remove_all;
2871 gst_object_ref (self->vf_colorspace);
2872 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2874 goto error_remove_all;
2875 if (!gst_element_link_pads (self->mjpg_demux, "jpeg", self->jpeg_dec,
2877 goto error_remove_all;
2878 if (!gst_element_link (self->jpeg_dec, self->vf_colorspace))
2879 goto error_remove_all;
2880 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2881 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2885 GstElement *tee = NULL;
2887 GST_DEBUG_OBJECT (self, "Raw+Raw");
2888 tee = gst_element_factory_make ("tee", NULL);
2889 if (!tee || !gst_bin_add (GST_BIN (self), tee)) {
2891 gst_object_unref (tee);
2894 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2896 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2898 if (!self->vf_colorspace || !self->vid_colorspace)
2900 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace))
2902 gst_object_ref (self->vf_colorspace);
2903 if (!gst_bin_add (GST_BIN (self), self->vid_colorspace)) {
2904 gst_object_unref (self->vid_colorspace);
2905 self->vid_colorspace = NULL;
2906 goto error_remove_all;
2908 gst_object_ref (self->vid_colorspace);
2909 if (!gst_element_link (self->v4l2_src, tee))
2910 goto error_remove_all;
2911 if (!gst_element_link (tee, self->vf_colorspace))
2912 goto error_remove_all;
2913 if (!gst_element_link (tee, self->vid_colorspace))
2914 goto error_remove_all;
2915 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2916 vid_pad = gst_element_get_static_pad (self->vid_colorspace, "src");
2919 case ENCODED_ENCODED:
2921 GstElement *tee = NULL;
2923 GST_DEBUG_OBJECT (self, "Encoded+Encoded");
2924 tee = gst_element_factory_make ("tee", NULL);
2925 if (!tee || !gst_bin_add (GST_BIN (self), tee)) {
2927 gst_object_unref (tee);
2930 if (!gst_element_link (self->v4l2_src, tee))
2931 goto error_remove_all;
2932 vf_pad = gst_element_get_request_pad (tee, "src%d");
2933 vid_pad = gst_element_get_request_pad (tee, "src%d");
2938 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), vid_pad) ||
2939 !gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad))
2940 goto error_remove_all;
2942 gst_object_unref (vid_pad);
2944 gst_object_unref (vf_pad);
2945 vid_pad = vf_pad = NULL;
2948 gst_caps_unref (vf_caps);
2950 gst_caps_unref (vid_caps);
2952 gst_caps_unref (src_caps);
2953 vf_caps = vid_caps = src_caps = NULL;
2955 /* Sync children states, in sink to source order */
2956 if (self->vid_colorspace &&
2957 !gst_element_sync_state_with_parent (self->vid_colorspace))
2958 goto error_remove_all;
2959 if (self->vf_colorspace &&
2960 !gst_element_sync_state_with_parent (self->vf_colorspace))
2961 goto error_remove_all;
2962 if (self->jpeg_dec && !gst_element_sync_state_with_parent (self->jpeg_dec))
2963 goto error_remove_all;
2964 if (self->mjpg_demux &&
2965 !gst_element_sync_state_with_parent (self->mjpg_demux))
2966 goto error_remove_all;
2967 if (self->v4l2_src && !gst_element_sync_state_with_parent (self->v4l2_src))
2968 goto error_remove_all;
2970 /* Sync any remaining children states with bin's state */
2971 iter = gst_bin_iterate_elements (GST_BIN (self));
2973 while (!iter_done) {
2974 GstElement *item = NULL;
2976 switch (gst_iterator_next (iter, (gpointer *) & item)) {
2977 case GST_ITERATOR_OK:
2978 if (!gst_element_sync_state_with_parent (item)) {
2979 gst_object_unref (item);
2980 gst_iterator_free (iter);
2981 goto error_remove_all;
2983 gst_object_unref (item);
2985 case GST_ITERATOR_RESYNC:
2986 gst_iterator_resync (iter);
2988 case GST_ITERATOR_ERROR:
2991 case GST_ITERATOR_DONE:
2996 gst_iterator_free (iter);
2998 self->reconfiguring = FALSE;
3002 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
3004 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
3005 gst_bin_remove (GST_BIN (self), self->v4l2_src);
3009 gst_object_unref (self->v4l2_src);
3010 self->v4l2_src = NULL;
3012 self->h264_unit_id = 0;
3014 if (self->mjpg_demux)
3015 gst_object_unref (self->mjpg_demux);
3016 self->mjpg_demux = NULL;
3018 gst_object_unref (self->jpeg_dec);
3019 self->jpeg_dec = NULL;
3020 if (self->vid_colorspace)
3021 gst_object_unref (self->vid_colorspace);
3022 self->vid_colorspace = NULL;
3023 if (self->vf_colorspace)
3024 gst_object_unref (self->vf_colorspace);
3025 self->vf_colorspace = NULL;
3028 gst_caps_unref (src_caps);
3031 gst_caps_unref (vf_caps);
3033 gst_caps_unref (vid_caps);
3036 gst_object_unref (vid_pad);
3038 gst_object_unref (vf_pad);
3040 self->reconfiguring = FALSE;
3045 gst_uvc_h264_src_getcaps (GstPad * pad)
3047 GstUvcH264Src *self = GST_UVC_H264_SRC (GST_OBJECT_PARENT (pad));
3048 GstCaps *template = NULL;
3049 GstCaps *result = NULL;
3051 if (pad == self->vfsrc)
3052 template = gst_static_pad_template_get_caps (&vfsrc_template);
3053 else if (pad == self->vidsrc)
3054 template = gst_static_pad_template_get_caps (&vidsrc_template);
3056 template = gst_caps_new_empty ();
3058 if (self->v4l2_src) {
3059 GstPad *v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
3060 GstCaps *v4l_caps = gst_pad_get_caps (v4l_pad);
3061 GstCaps *new_caps = gst_uvc_h264_src_transform_caps (self, v4l_caps);
3063 result = gst_caps_intersect (new_caps, template);
3064 gst_object_unref (v4l_pad);
3065 gst_caps_unref (v4l_caps);
3066 gst_caps_unref (new_caps);
3067 gst_caps_unref (template);
3076 gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode)
3078 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
3080 GST_DEBUG_OBJECT (self, "set mode to %d", mode);
3082 return (mode == MODE_VIDEO);
3086 gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc)
3088 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
3089 gboolean ret = TRUE;
3091 GST_DEBUG_OBJECT (self, "start capture");
3093 if (!self->started) {
3094 self->started = TRUE;
3095 if (GST_STATE (self) >= GST_STATE_READY) {
3096 ret = gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3098 GST_DEBUG_OBJECT (self, "Could not start capture");
3099 self->started = FALSE;
3100 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3109 gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc)
3111 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
3113 GST_DEBUG_OBJECT (self, "stop capture");
3115 if (self->started) {
3116 self->started = FALSE;
3117 if (GST_STATE (self) >= GST_STATE_READY)
3118 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3119 gst_base_camera_src_finish_capture (camerasrc);
3124 gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
3125 GstPad * peer, gpointer user_data)
3127 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
3128 gchar *pad_name = gst_pad_get_name (pad);
3130 GST_DEBUG_OBJECT (self, "Pad %s was (un)linked. Renegotiating", pad_name);
3132 if (GST_STATE (self) >= GST_STATE_READY)
3133 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3137 static GstStateChangeReturn
3138 gst_uvc_h264_src_change_state (GstElement * element, GstStateChange trans)
3140 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3141 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
3144 case GST_STATE_CHANGE_NULL_TO_READY:
3145 if (!ensure_v4l2src (self)) {
3146 ret = GST_STATE_CHANGE_FAILURE;
3149 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
3151 case GST_STATE_CHANGE_READY_TO_PAUSED:
3152 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3153 if (!self->v4l2_src)
3154 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3160 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans);
3162 if (ret == GST_STATE_CHANGE_FAILURE)
3166 case GST_STATE_CHANGE_PAUSED_TO_READY:
3167 self->vid_newseg = FALSE;
3168 self->vf_newseg = FALSE;
3170 case GST_STATE_CHANGE_READY_TO_NULL:
3171 gst_uvc_h264_src_destroy_pipeline (self, TRUE);