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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
25 * SECTION:element-uvch264src
28 * A camera bin src element that wraps v4l2src and implements UVC H264
29 * Extension Units (XU) to control the H264 encoder in the camera
36 #include "gstuvch264_src.h"
41 /* uvch264_src properties */
43 PROP_JPEG_DECODER_NAME,
44 PROP_NUM_CLOCK_SAMPLES,
45 /* v4l2src properties */
57 PROP_NUM_REORDER_FRAMES,
59 PROP_LEAKY_BUCKET_SIZE,
60 /* Dynamic controls */
63 PROP_MAX_MBPS, /* read-only */
74 PROP_LTR_ENCODER_CONTROL,
76 /* In caps : frame interval (fps), width, height, profile, mux */
77 /* Ignored: temporal, spatial, SNR, MVC views, version, reset */
78 /* Events: LTR, generate IDR */
83 SIGNAL_GET_ENUM_SETTING,
84 SIGNAL_GET_BOOLEAN_SETTING,
85 SIGNAL_GET_INT_SETTING,
89 static guint _signals[LAST_SIGNAL];
92 #define DEFAULT_COLORSPACE_NAME "videoconvert"
93 #define DEFAULT_JPEG_DECODER_NAME "jpegdec"
94 #define DEFAULT_NUM_CLOCK_SAMPLES 0
95 #define DEFAULT_NUM_BUFFERS -1
96 #define DEFAULT_DEVICE "/dev/video0"
97 #define DEFAULT_DEVICE_NAME NULL
98 #define DEFAULT_INITIAL_BITRATE 3000000
99 #define DEFAULT_SLICE_UNITS 4
100 #define DEFAULT_SLICE_MODE UVC_H264_SLICEMODE_SLICEPERFRAME
101 #define DEFAULT_IFRAME_PERIOD 10000
102 #define DEFAULT_USAGE_TYPE UVC_H264_USAGETYPE_REALTIME
103 #define DEFAULT_ENTROPY UVC_H264_ENTROPY_CAVLC
104 #define DEFAULT_ENABLE_SEI FALSE
105 #define DEFAULT_NUM_REORDER_FRAMES 0
106 #define DEFAULT_PREVIEW_FLIPPED FALSE
107 #define DEFAULT_LEAKY_BUCKET_SIZE 1000
108 #define DEFAULT_RATE_CONTROL UVC_H264_RATECONTROL_CBR
109 #define DEFAULT_FIXED_FRAMERATE FALSE
110 #define DEFAULT_LEVEL_IDC 40
111 #define DEFAULT_PEAK_BITRATE DEFAULT_INITIAL_BITRATE
112 #define DEFAULT_AVERAGE_BITRATE DEFAULT_INITIAL_BITRATE
113 #define DEFAULT_MIN_QP 10
114 #define DEFAULT_MAX_QP 46
115 #define DEFAULT_LTR_BUFFER_SIZE 0
116 #define DEFAULT_LTR_ENCODER_CONTROL 0
118 #define NSEC_PER_SEC (G_USEC_PER_SEC * 1000)
121 GST_DEBUG_CATEGORY (uvc_h264_src_debug);
122 #define GST_CAT_DEFAULT uvc_h264_src_debug
124 #define gst_uvc_h264_src_parent_class parent_class
125 G_DEFINE_TYPE (GstUvcH264Src, gst_uvc_h264_src, GST_TYPE_BASE_CAMERA_SRC);
127 #define GST_UVC_H264_SRC_VF_CAPS_STR \
128 GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \
130 "width = " GST_VIDEO_SIZE_RANGE "," \
131 "height = " GST_VIDEO_SIZE_RANGE "," \
132 "framerate = " GST_VIDEO_FPS_RANGE
134 #define GST_UVC_H264_SRC_VID_CAPS_STR \
135 GST_UVC_H264_SRC_VF_CAPS_STR ";" \
137 "width = " GST_VIDEO_SIZE_RANGE ", " \
138 "height = " GST_VIDEO_SIZE_RANGE ", " \
139 "framerate = " GST_VIDEO_FPS_RANGE ", " \
140 "stream-format = (string) { byte-stream, avc }, " \
141 "alignment = (string) au, " \
142 "profile = (string) { high, main, baseline, constrained-baseline }"
145 * GstUvcH264Src!vfsrc:
147 * The video src pad template
149 static GstStaticPadTemplate vfsrc_template =
150 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
153 GST_STATIC_CAPS (GST_UVC_H264_SRC_VF_CAPS_STR));
155 static GstStaticPadTemplate imgsrc_template =
156 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
159 GST_STATIC_CAPS_NONE);
161 static GstStaticPadTemplate vidsrc_template =
162 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
165 GST_STATIC_CAPS (GST_UVC_H264_SRC_VID_CAPS_STR));
168 static void gst_uvc_h264_src_dispose (GObject * object);
169 static void gst_uvc_h264_src_set_property (GObject * object,
170 guint prop_id, const GValue * value, GParamSpec * pspec);
171 static void gst_uvc_h264_src_get_property (GObject * object,
172 guint prop_id, GValue * value, GParamSpec * pspec);
173 static gboolean gst_uvc_h264_src_event (GstPad * pad, GstObject * parent,
175 static gboolean gst_uvc_h264_src_send_event (GstElement * element,
177 static gboolean gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc *
179 static gboolean gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc,
180 GstCameraBinMode mode);
181 static gboolean gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc);
182 static void gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc);
183 static GstStateChangeReturn gst_uvc_h264_src_change_state (GstElement * element,
184 GstStateChange trans);
185 static GstPadProbeReturn gst_uvc_h264_src_buffer_probe (GstPad * pad,
186 GstPadProbeInfo * info, gpointer user_data);
187 static GstPadProbeReturn gst_uvc_h264_src_event_probe (GstPad * pad,
188 GstPadProbeInfo * info, gpointer user_data);
189 static void gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
190 GstPad * peer, gpointer user_data);
191 static gboolean gst_uvc_h264_src_query (GstPad * pad, GstObject * parent,
195 static void v4l2src_prepare_format (GstElement * v4l2src, gint fd,
196 GstCaps * caps, gpointer user_data);
197 static void fill_probe_commit (GstUvcH264Src * self,
198 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
199 guint32 width, guint32 height, guint32 profile,
200 UvcH264StreamFormat stream_format);
201 static gboolean xu_query (GstUvcH264Src * self, guint selector, guint query,
204 static void set_rate_control (GstUvcH264Src * self);
205 static void set_level_idc (GstUvcH264Src * self);
206 static void set_bitrate (GstUvcH264Src * self);
207 static void set_qp (GstUvcH264Src * self, gint type);
208 static void set_ltr (GstUvcH264Src * self);
209 static void update_rate_control (GstUvcH264Src * self);
210 static guint32 update_level_idc_and_get_max_mbps (GstUvcH264Src * self);
211 static void update_bitrate (GstUvcH264Src * self);
212 static gboolean update_qp (GstUvcH264Src * self, gint type);
213 static void update_ltr (GstUvcH264Src * self);
215 static gboolean gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self,
216 gchar * property, gint * mask, gint * default_value);
217 static gboolean gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self,
218 gchar * property, gboolean * changeable, gboolean * def);
219 static gboolean gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self,
220 gchar * property, gint * min, gint * def, gint * max);
223 gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass)
225 GObjectClass *gobject_class;
226 GstElementClass *gstelement_class;
227 GstBaseCameraSrcClass *gstbasecamerasrc_class;
229 parent_class = g_type_class_peek_parent (klass);
231 gobject_class = G_OBJECT_CLASS (klass);
232 gstelement_class = GST_ELEMENT_CLASS (klass);
233 gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass);
235 gobject_class->dispose = gst_uvc_h264_src_dispose;
236 gobject_class->set_property = gst_uvc_h264_src_set_property;
237 gobject_class->get_property = gst_uvc_h264_src_get_property;
239 gstelement_class->change_state = gst_uvc_h264_src_change_state;
240 gstelement_class->send_event = gst_uvc_h264_src_send_event;
242 gstbasecamerasrc_class->construct_pipeline =
243 gst_uvc_h264_src_construct_pipeline;
244 gstbasecamerasrc_class->set_mode = gst_uvc_h264_src_set_mode;
245 gstbasecamerasrc_class->start_capture = gst_uvc_h264_src_start_capture;
246 gstbasecamerasrc_class->stop_capture = gst_uvc_h264_src_stop_capture;
248 GST_DEBUG_CATEGORY_INIT (uvc_h264_src_debug, "uvch264src",
249 0, "UVC H264 Compliant camera bin source");
251 gst_element_class_set_static_metadata (gstelement_class,
254 "UVC H264 Encoding camera source",
255 "Youness Alaoui <youness.alaoui@collabora.co.uk>");
257 gst_element_class_add_static_pad_template (gstelement_class,
259 gst_element_class_add_static_pad_template (gstelement_class,
261 gst_element_class_add_static_pad_template (gstelement_class, &vfsrc_template);
264 g_object_class_install_property (gobject_class, PROP_COLORSPACE_NAME,
265 g_param_spec_string ("colorspace-name", "colorspace element name",
266 "The name of the colorspace element",
267 DEFAULT_COLORSPACE_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
268 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
269 g_object_class_install_property (gobject_class, PROP_JPEG_DECODER_NAME,
270 g_param_spec_string ("jpeg-decoder-name", "jpeg decoder element name",
271 "The name of the jpeg decoder element",
272 DEFAULT_JPEG_DECODER_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
273 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
275 g_object_class_install_property (gobject_class, PROP_NUM_CLOCK_SAMPLES,
276 g_param_spec_int ("num-clock-samples", "num-clock-samples",
277 "Number of clock samples to gather for the PTS synchronization"
279 0, G_MAXINT, DEFAULT_NUM_CLOCK_SAMPLES,
280 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | GST_PARAM_MUTABLE_PLAYING |
281 G_PARAM_STATIC_STRINGS));
283 /* v4l2src proxied properties */
284 g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
285 g_param_spec_int ("num-buffers", "num-buffers",
286 "Number of buffers to output before sending EOS (-1 = unlimited)",
287 -1, G_MAXINT, DEFAULT_NUM_BUFFERS,
288 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
289 g_object_class_install_property (gobject_class, PROP_DEVICE,
290 g_param_spec_string ("device", "device",
292 DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
293 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
294 g_param_spec_string ("device-name", "Device name",
295 "Name of the device", DEFAULT_DEVICE_NAME,
296 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
298 /* Static controls */
299 g_object_class_install_property (gobject_class, PROP_INITIAL_BITRATE,
300 g_param_spec_uint ("initial-bitrate", "Initial bitrate",
301 "Initial bitrate in bits/second (static control)",
302 0, G_MAXUINT, DEFAULT_INITIAL_BITRATE,
303 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
304 GST_PARAM_MUTABLE_READY));
305 g_object_class_install_property (gobject_class, PROP_SLICE_UNITS,
306 g_param_spec_uint ("slice-units", "Slice units",
307 "Slice units (static control)",
308 0, G_MAXUINT16, DEFAULT_SLICE_UNITS,
309 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
310 GST_PARAM_MUTABLE_READY));
311 g_object_class_install_property (gobject_class, PROP_SLICE_MODE,
312 g_param_spec_enum ("slice-mode", "Slice mode",
313 "Defines the unit of the slice-units property (static control)",
314 UVC_H264_SLICEMODE_TYPE,
315 DEFAULT_SLICE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
316 GST_PARAM_MUTABLE_READY));
317 g_object_class_install_property (gobject_class, PROP_IFRAME_PERIOD,
318 g_param_spec_uint ("iframe-period", "I Frame Period",
319 "Time between IDR frames in milliseconds (static control)",
320 0, G_MAXUINT16, DEFAULT_IFRAME_PERIOD,
321 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
322 GST_PARAM_MUTABLE_READY));
323 g_object_class_install_property (gobject_class, PROP_USAGE_TYPE,
324 g_param_spec_enum ("usage-type", "Usage type",
325 "The usage type (static control)",
326 UVC_H264_USAGETYPE_TYPE, DEFAULT_USAGE_TYPE,
327 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
328 GST_PARAM_MUTABLE_READY));
329 g_object_class_install_property (gobject_class, PROP_ENTROPY,
330 g_param_spec_enum ("entropy", "Entropy",
331 "Entropy (static control)",
332 UVC_H264_ENTROPY_TYPE, DEFAULT_ENTROPY,
333 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
334 GST_PARAM_MUTABLE_READY));
335 g_object_class_install_property (gobject_class, PROP_ENABLE_SEI,
336 g_param_spec_boolean ("enable-sei", "Enable SEI",
337 "Enable SEI picture timing (static control)",
338 DEFAULT_ENABLE_SEI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
339 GST_PARAM_MUTABLE_READY));
340 g_object_class_install_property (gobject_class, PROP_NUM_REORDER_FRAMES,
341 g_param_spec_uint ("num-reorder-frames", "Number of Reorder frames",
342 "Number of B frames between the references frames (static control)",
343 0, G_MAXUINT8, DEFAULT_NUM_REORDER_FRAMES,
344 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
345 GST_PARAM_MUTABLE_READY));
346 g_object_class_install_property (gobject_class, PROP_PREVIEW_FLIPPED,
347 g_param_spec_boolean ("preview-flipped", "Flip preview",
348 "Horizontal flipped image for non H.264 streams (static control)",
349 DEFAULT_PREVIEW_FLIPPED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
350 GST_PARAM_MUTABLE_READY));
351 g_object_class_install_property (gobject_class, PROP_LEAKY_BUCKET_SIZE,
352 g_param_spec_uint ("leaky-bucket-size", "Size of the leaky bucket size",
353 "Size of the leaky bucket size in milliseconds (static control)",
354 0, G_MAXUINT16, DEFAULT_LEAKY_BUCKET_SIZE,
355 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
356 GST_PARAM_MUTABLE_READY));
358 /* Dynamic controls */
359 g_object_class_install_property (gobject_class, PROP_RATE_CONTROL,
360 g_param_spec_enum ("rate-control", "Rate control",
361 "Rate control mode (static & dynamic control)",
362 UVC_H264_RATECONTROL_TYPE, DEFAULT_RATE_CONTROL,
363 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
364 GST_PARAM_MUTABLE_PLAYING));
365 g_object_class_install_property (gobject_class, PROP_FIXED_FRAMERATE,
366 g_param_spec_boolean ("fixed-framerate", "Fixed framerate",
367 "Fixed framerate (static & dynamic control)",
368 DEFAULT_FIXED_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
369 GST_PARAM_MUTABLE_PLAYING));
370 g_object_class_install_property (gobject_class, PROP_MAX_MBPS,
371 g_param_spec_uint ("max-mbps", "Max macroblocks/second",
372 "The number of macroblocks per second for the maximum processing rate",
373 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
374 g_object_class_install_property (gobject_class, PROP_LEVEL_IDC,
375 g_param_spec_uint ("level-idc", "Level IDC",
376 "Level IDC (dynamic control)",
377 0, G_MAXUINT8, DEFAULT_LEVEL_IDC,
378 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
379 GST_PARAM_MUTABLE_PLAYING));
380 g_object_class_install_property (gobject_class, PROP_PEAK_BITRATE,
381 g_param_spec_uint ("peak-bitrate", "Peak bitrate",
382 "The peak bitrate in bits/second (dynamic control)",
383 0, G_MAXUINT, DEFAULT_PEAK_BITRATE,
384 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
385 GST_PARAM_MUTABLE_PLAYING));
386 g_object_class_install_property (gobject_class, PROP_AVERAGE_BITRATE,
387 g_param_spec_uint ("average-bitrate", "Average bitrate",
388 "The average bitrate in bits/second (dynamic control)",
389 0, G_MAXUINT, DEFAULT_AVERAGE_BITRATE,
390 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
391 GST_PARAM_MUTABLE_PLAYING));
392 g_object_class_install_property (gobject_class, PROP_MIN_IFRAME_QP,
393 g_param_spec_int ("min-iframe-qp", "Minimum I frame QP",
394 "The minimum Quantization step size for I frames (dynamic control)",
395 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
396 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
397 GST_PARAM_MUTABLE_PLAYING));
398 g_object_class_install_property (gobject_class, PROP_MAX_IFRAME_QP,
399 g_param_spec_int ("max-iframe-qp", "Minimum I frame QP",
400 "The minimum Quantization step size for I frames (dynamic control)",
401 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
402 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
403 GST_PARAM_MUTABLE_PLAYING));
404 g_object_class_install_property (gobject_class, PROP_MIN_PFRAME_QP,
405 g_param_spec_int ("min-pframe-qp", "Minimum P frame QP",
406 "The minimum Quantization step size for P frames (dynamic control)",
407 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
408 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
409 GST_PARAM_MUTABLE_PLAYING));
410 g_object_class_install_property (gobject_class, PROP_MAX_PFRAME_QP,
411 g_param_spec_int ("max-pframe-qp", "Minimum P frame QP",
412 "The minimum Quantization step size for P frames (dynamic control)",
413 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
414 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
415 GST_PARAM_MUTABLE_PLAYING));
416 g_object_class_install_property (gobject_class, PROP_MIN_BFRAME_QP,
417 g_param_spec_int ("min-bframe-qp", "Minimum B frame QP",
418 "The minimum Quantization step size for B frames (dynamic control)",
419 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
420 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
421 GST_PARAM_MUTABLE_PLAYING));
422 g_object_class_install_property (gobject_class, PROP_MAX_BFRAME_QP,
423 g_param_spec_int ("max-bframe-qp", "Minimum B frame QP",
424 "The minimum Quantization step size for B frames (dynamic control)",
425 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
426 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
427 GST_PARAM_MUTABLE_PLAYING));
428 g_object_class_install_property (gobject_class, PROP_LTR_BUFFER_SIZE,
429 g_param_spec_int ("ltr-buffer-size", "LTR Buffer size",
430 "Total number of Long-Term Reference frames (dynamic control)",
431 0, G_MAXUINT8, DEFAULT_LTR_BUFFER_SIZE,
432 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
433 GST_PARAM_MUTABLE_PLAYING));
434 g_object_class_install_property (gobject_class, PROP_LTR_ENCODER_CONTROL,
435 g_param_spec_int ("ltr-encoder-control",
436 "LTR frames controlled by device",
437 "Number of LTR frames the device can control (dynamic control)", 0,
438 G_MAXUINT8, DEFAULT_LTR_ENCODER_CONTROL,
439 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
440 GST_PARAM_MUTABLE_PLAYING));
442 _signals[SIGNAL_GET_ENUM_SETTING] =
443 g_signal_new_class_handler ("get-enum-setting",
444 G_TYPE_FROM_CLASS (klass),
445 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
446 G_CALLBACK (gst_uvc_h264_src_get_enum_setting),
448 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
449 _signals[SIGNAL_GET_BOOLEAN_SETTING] =
450 g_signal_new_class_handler ("get-boolean-setting",
451 G_TYPE_FROM_CLASS (klass),
452 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
453 G_CALLBACK (gst_uvc_h264_src_get_boolean_setting), NULL, NULL, NULL,
454 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
455 _signals[SIGNAL_GET_INT_SETTING] =
456 g_signal_new_class_handler ("get-int-setting",
457 G_TYPE_FROM_CLASS (klass),
458 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
459 G_CALLBACK (gst_uvc_h264_src_get_int_setting), NULL, NULL, NULL,
460 G_TYPE_BOOLEAN, 4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER,
465 gst_uvc_h264_src_init (GstUvcH264Src * self)
468 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
470 gst_pad_set_query_function (self->vfsrc,
471 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query));
472 gst_element_add_pad (GST_ELEMENT (self), self->vfsrc);
475 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
477 gst_element_add_pad (GST_ELEMENT (self), self->imgsrc);
480 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
482 gst_pad_set_query_function (self->vidsrc,
483 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query));
484 gst_element_add_pad (GST_ELEMENT (self), self->vidsrc);
485 gst_pad_add_probe (self->vidsrc, GST_PAD_PROBE_TYPE_BUFFER,
486 gst_uvc_h264_src_buffer_probe, self, NULL);
487 gst_pad_add_probe (self->vfsrc, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
488 gst_uvc_h264_src_event_probe, self, NULL);
489 gst_pad_add_probe (self->vidsrc,
490 GST_PAD_PROBE_TYPE_EVENT_UPSTREAM | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
491 gst_uvc_h264_src_event_probe, self, NULL);
493 self->srcpad_event_func = GST_PAD_EVENTFUNC (self->vfsrc);
495 gst_pad_set_event_function (self->imgsrc, gst_uvc_h264_src_event);
496 gst_pad_set_event_function (self->vidsrc, gst_uvc_h264_src_event);
497 gst_pad_set_event_function (self->vfsrc, gst_uvc_h264_src_event);
499 g_signal_connect (self->vidsrc, "linked",
500 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
501 g_signal_connect (self->vidsrc, "unlinked",
502 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
503 g_signal_connect (self->vfsrc, "linked",
504 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
505 g_signal_connect (self->vfsrc, "unlinked",
506 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
509 gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), MODE_VIDEO);
511 self->main_format = UVC_H264_SRC_FORMAT_NONE;
512 self->main_width = 0;
513 self->main_height = 0;
514 self->main_frame_interval = 0;
515 self->main_stream_format = UVC_H264_STREAMFORMAT_ANNEXB;
516 self->main_profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
517 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
518 self->secondary_width = 0;
519 self->secondary_height = 0;
520 self->secondary_frame_interval = 0;
522 /* v4l2src properties */
523 self->num_buffers = DEFAULT_NUM_BUFFERS;
524 self->device = g_strdup (DEFAULT_DEVICE);
526 /* Static controls */
527 self->initial_bitrate = DEFAULT_INITIAL_BITRATE;
528 self->slice_units = DEFAULT_SLICE_UNITS;
529 self->slice_mode = DEFAULT_SLICE_MODE;
530 self->iframe_period = DEFAULT_IFRAME_PERIOD;
531 self->usage_type = DEFAULT_USAGE_TYPE;
532 self->entropy = DEFAULT_ENTROPY;
533 self->enable_sei = DEFAULT_ENABLE_SEI;
534 self->num_reorder_frames = DEFAULT_NUM_REORDER_FRAMES;
535 self->preview_flipped = DEFAULT_PREVIEW_FLIPPED;
536 self->leaky_bucket_size = DEFAULT_LEAKY_BUCKET_SIZE;
538 /* Dynamic controls */
539 self->rate_control = DEFAULT_RATE_CONTROL;
540 self->fixed_framerate = DEFAULT_FIXED_FRAMERATE;
541 self->level_idc = DEFAULT_LEVEL_IDC;
542 self->peak_bitrate = DEFAULT_PEAK_BITRATE;
543 self->average_bitrate = DEFAULT_AVERAGE_BITRATE;
544 self->min_qp[QP_I_FRAME] = DEFAULT_MIN_QP;
545 self->max_qp[QP_I_FRAME] = DEFAULT_MAX_QP;
546 self->min_qp[QP_P_FRAME] = DEFAULT_MIN_QP;
547 self->max_qp[QP_P_FRAME] = DEFAULT_MAX_QP;
548 self->min_qp[QP_B_FRAME] = DEFAULT_MIN_QP;
549 self->max_qp[QP_B_FRAME] = DEFAULT_MAX_QP;
550 self->ltr_buffer_size = DEFAULT_LTR_BUFFER_SIZE;
551 self->ltr_encoder_control = DEFAULT_LTR_ENCODER_CONTROL;
555 gst_uvc_h264_src_dispose (GObject * object)
557 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
560 libusb_exit (self->usb_ctx);
561 self->usb_ctx = NULL;
562 g_free (self->jpeg_decoder_name);
563 self->jpeg_decoder_name = NULL;
564 g_free (self->colorspace_name);
565 self->colorspace_name = NULL;
566 g_free (self->device);
569 G_OBJECT_CLASS (parent_class)->dispose (object);
573 gst_uvc_h264_src_set_property (GObject * object,
574 guint prop_id, const GValue * value, GParamSpec * pspec)
576 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
579 case PROP_COLORSPACE_NAME:
580 g_free (self->colorspace_name);
581 self->colorspace_name = g_value_dup_string (value);
583 case PROP_JPEG_DECODER_NAME:
584 g_free (self->jpeg_decoder_name);
585 self->jpeg_decoder_name = g_value_dup_string (value);
587 case PROP_NUM_CLOCK_SAMPLES:
588 self->num_clock_samples = g_value_get_int (value);
589 if (self->mjpg_demux)
590 g_object_set (self->mjpg_demux,
591 "num-clock-samples", self->num_clock_samples, NULL);
593 /* v4l2 properties */
594 case PROP_NUM_BUFFERS:
595 self->num_buffers = g_value_get_int (value);
597 g_object_set_property (G_OBJECT (self->v4l2_src), "num-buffers", value);
600 g_free (self->device);
601 self->device = g_value_dup_string (value);
603 g_object_set_property (G_OBJECT (self->v4l2_src), "device", value);
605 /* Static controls */
606 case PROP_INITIAL_BITRATE:
607 self->initial_bitrate = g_value_get_uint (value);
609 case PROP_SLICE_UNITS:
610 self->slice_units = g_value_get_uint (value);
612 case PROP_SLICE_MODE:
613 self->slice_mode = g_value_get_enum (value);
615 case PROP_IFRAME_PERIOD:
616 self->iframe_period = g_value_get_uint (value);
618 case PROP_USAGE_TYPE:
619 self->usage_type = g_value_get_enum (value);
622 self->entropy = g_value_get_enum (value);
624 case PROP_ENABLE_SEI:
625 self->enable_sei = g_value_get_boolean (value);
627 case PROP_NUM_REORDER_FRAMES:
628 self->num_reorder_frames = g_value_get_uint (value);
630 case PROP_PREVIEW_FLIPPED:
631 self->preview_flipped = g_value_get_boolean (value);
633 case PROP_LEAKY_BUCKET_SIZE:
634 self->leaky_bucket_size = g_value_get_uint (value);
638 /* Dynamic controls */
639 case PROP_RATE_CONTROL:
640 self->rate_control = g_value_get_enum (value);
641 set_rate_control (self);
642 update_rate_control (self);
644 case PROP_FIXED_FRAMERATE:
645 self->fixed_framerate = g_value_get_boolean (value);
646 set_rate_control (self);
647 update_rate_control (self);
650 self->level_idc = g_value_get_uint (value);
651 set_level_idc (self);
652 update_level_idc_and_get_max_mbps (self);
654 case PROP_PEAK_BITRATE:
655 self->peak_bitrate = g_value_get_uint (value);
657 update_bitrate (self);
659 case PROP_AVERAGE_BITRATE:
660 self->average_bitrate = g_value_get_uint (value);
662 update_bitrate (self);
664 case PROP_MIN_IFRAME_QP:
665 self->min_qp[QP_I_FRAME] = g_value_get_int (value);
666 set_qp (self, QP_I_FRAME);
667 update_qp (self, QP_I_FRAME);
669 case PROP_MAX_IFRAME_QP:
670 self->max_qp[QP_I_FRAME] = g_value_get_int (value);
671 set_qp (self, QP_I_FRAME);
672 update_qp (self, QP_I_FRAME);
674 case PROP_MIN_PFRAME_QP:
675 self->min_qp[QP_P_FRAME] = g_value_get_int (value);
676 set_qp (self, QP_P_FRAME);
677 update_qp (self, QP_P_FRAME);
679 case PROP_MAX_PFRAME_QP:
680 self->max_qp[QP_P_FRAME] = g_value_get_int (value);
681 set_qp (self, QP_P_FRAME);
682 update_qp (self, QP_P_FRAME);
684 case PROP_MIN_BFRAME_QP:
685 self->min_qp[QP_B_FRAME] = g_value_get_int (value);
686 set_qp (self, QP_B_FRAME);
687 update_qp (self, QP_B_FRAME);
689 case PROP_MAX_BFRAME_QP:
690 self->max_qp[QP_B_FRAME] = g_value_get_int (value);
691 set_qp (self, QP_B_FRAME);
692 update_qp (self, QP_B_FRAME);
694 case PROP_LTR_BUFFER_SIZE:
695 self->ltr_buffer_size = g_value_get_int (value);
699 case PROP_LTR_ENCODER_CONTROL:
700 self->ltr_encoder_control = g_value_get_int (value);
705 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
711 gst_uvc_h264_src_get_property (GObject * object,
712 guint prop_id, GValue * value, GParamSpec * pspec)
714 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
715 uvcx_video_config_probe_commit_t probe;
718 case PROP_INITIAL_BITRATE:
719 case PROP_SLICE_UNITS:
720 case PROP_SLICE_MODE:
721 case PROP_IFRAME_PERIOD:
722 case PROP_USAGE_TYPE:
724 case PROP_ENABLE_SEI:
725 case PROP_NUM_REORDER_FRAMES:
726 case PROP_PREVIEW_FLIPPED:
727 case PROP_LEAKY_BUCKET_SIZE:
728 fill_probe_commit (self, &probe, 0, 0, 0, 0, 0);
729 if (GST_STATE (self) >= GST_STATE_PAUSED) {
730 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
732 GST_WARNING_OBJECT (self, "probe_setting GET_CUR error");
740 case PROP_COLORSPACE_NAME:
741 g_value_set_string (value, self->colorspace_name);
743 case PROP_JPEG_DECODER_NAME:
744 g_value_set_string (value, self->jpeg_decoder_name);
746 case PROP_NUM_CLOCK_SAMPLES:
747 g_value_set_int (value, self->num_clock_samples);
749 /* v4l2src properties */
750 case PROP_NUM_BUFFERS:
751 g_value_set_int (value, self->num_buffers);
754 g_value_set_string (value, self->device);
756 case PROP_DEVICE_NAME:
758 g_object_get_property (G_OBJECT (self->v4l2_src), "device-name", value);
760 g_value_set_static_string (value, "");
762 /* Static controls */
763 case PROP_INITIAL_BITRATE:
764 g_value_set_uint (value, probe.dwBitRate);
766 case PROP_SLICE_UNITS:
767 g_value_set_uint (value, probe.wSliceUnits);
769 case PROP_SLICE_MODE:
770 g_value_set_enum (value, probe.wSliceMode);
772 case PROP_IFRAME_PERIOD:
773 g_value_set_uint (value, probe.wIFramePeriod);
775 case PROP_USAGE_TYPE:
776 g_value_set_enum (value, probe.bUsageType);
779 g_value_set_enum (value, probe.bEntropyCABAC);
781 case PROP_ENABLE_SEI:
782 g_value_set_boolean (value,
783 (probe.bTimestamp == UVC_H264_TIMESTAMP_SEI_ENABLE));
785 case PROP_NUM_REORDER_FRAMES:
786 g_value_set_uint (value, probe.bNumOfReorderFrames);
788 case PROP_PREVIEW_FLIPPED:
789 g_value_set_boolean (value,
790 (probe.bPreviewFlipped == UVC_H264_PREFLIPPED_HORIZONTAL));
792 case PROP_LEAKY_BUCKET_SIZE:
793 g_value_set_uint (value, probe.wLeakyBucketSize);
796 /* Dynamic controls */
797 case PROP_RATE_CONTROL:
798 update_rate_control (self);
799 g_value_set_enum (value, self->rate_control);
801 case PROP_FIXED_FRAMERATE:
802 update_rate_control (self);
803 g_value_set_boolean (value, self->fixed_framerate);
806 g_value_set_uint (value, update_level_idc_and_get_max_mbps (self));
809 update_level_idc_and_get_max_mbps (self);
810 g_value_set_uint (value, self->level_idc);
812 case PROP_PEAK_BITRATE:
813 update_bitrate (self);
814 g_value_set_uint (value, self->peak_bitrate);
816 case PROP_AVERAGE_BITRATE:
817 update_bitrate (self);
818 g_value_set_uint (value, self->average_bitrate);
820 case PROP_MIN_IFRAME_QP:
821 update_qp (self, QP_I_FRAME);
822 g_value_set_int (value, self->min_qp[QP_I_FRAME]);
824 case PROP_MAX_IFRAME_QP:
825 update_qp (self, QP_I_FRAME);
826 g_value_set_int (value, self->max_qp[QP_I_FRAME]);
828 case PROP_MIN_PFRAME_QP:
829 update_qp (self, QP_P_FRAME);
830 g_value_set_int (value, self->min_qp[QP_P_FRAME]);
832 case PROP_MAX_PFRAME_QP:
833 update_qp (self, QP_P_FRAME);
834 g_value_set_int (value, self->max_qp[QP_P_FRAME]);
836 case PROP_MIN_BFRAME_QP:
837 update_qp (self, QP_B_FRAME);
838 g_value_set_int (value, self->min_qp[QP_B_FRAME]);
840 case PROP_MAX_BFRAME_QP:
841 update_qp (self, QP_B_FRAME);
842 g_value_set_int (value, self->max_qp[QP_B_FRAME]);
844 case PROP_LTR_BUFFER_SIZE:
846 g_value_set_int (value, self->ltr_buffer_size);
848 case PROP_LTR_ENCODER_CONTROL:
850 g_value_set_int (value, self->ltr_encoder_control);
853 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
858 /* Set dynamic controls */
860 set_rate_control (GstUvcH264Src * self)
862 uvcx_rate_control_mode_t req;
864 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
865 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
869 req.bRateControlMode = self->rate_control;
870 if (self->fixed_framerate)
871 req.bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
873 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR, (guchar *) & req)) {
874 GST_WARNING_OBJECT (self, " RATE_CONTROL SET_CUR error");
880 set_level_idc (GstUvcH264Src * self)
882 uvcx_video_advance_config_t req;
884 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
886 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
890 req.blevel_idc = self->level_idc;
891 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_SET_CUR,
893 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG SET_CUR error");
899 set_bitrate (GstUvcH264Src * self)
901 uvcx_bitrate_layers_t req;
903 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
904 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
908 req.dwPeakBitrate = self->peak_bitrate;
909 req.dwAverageBitrate = self->average_bitrate;
910 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
911 GST_WARNING_OBJECT (self, " BITRATE_LAYERS SET_CUR error");
917 set_qp (GstUvcH264Src * self, gint type)
919 uvcx_qp_steps_layers_t req;
924 req.bFrameType = UVC_H264_QP_STEPS_I_FRAME_TYPE;
927 req.bFrameType = UVC_H264_QP_STEPS_P_FRAME_TYPE;
930 req.bFrameType = UVC_H264_QP_STEPS_B_FRAME_TYPE;
937 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
938 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
942 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
943 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
947 req.bMinQp = self->min_qp[type];
948 req.bMaxQp = self->max_qp[type];
949 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
950 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
956 set_ltr (GstUvcH264Src * self)
958 uvcx_ltr_buffer_size_control_t req;
960 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
962 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
966 req.bLTRBufferSize = self->ltr_buffer_size;
967 req.bLTREncoderControl = self->ltr_encoder_control;
968 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_SET_CUR,
970 GST_WARNING_OBJECT (self, "LTR_BUFFER_SIZE SET_CUR error");
975 /* Get Dynamic controls */
978 update_rate_control (GstUvcH264Src * self)
980 uvcx_rate_control_mode_t req;
982 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
983 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
987 if (self->rate_control != (req.bRateControlMode &
988 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG)) {
989 self->rate_control = (req.bRateControlMode &
990 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG);
991 g_object_notify (G_OBJECT (self), "rate-control");
993 if (self->fixed_framerate != ((req.bRateControlMode &
994 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0)) {
995 self->fixed_framerate = ((req.bRateControlMode &
996 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
997 g_object_notify (G_OBJECT (self), "fixed-framerate");
1003 update_level_idc_and_get_max_mbps (GstUvcH264Src * self)
1005 uvcx_video_advance_config_t req;
1007 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
1008 (guchar *) & req)) {
1009 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
1013 if (self->level_idc != req.blevel_idc) {
1014 self->level_idc = req.blevel_idc;
1015 g_object_notify (G_OBJECT (self), "level-idc");
1017 return req.dwMb_max;
1021 update_bitrate (GstUvcH264Src * self)
1023 uvcx_bitrate_layers_t req;
1025 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1026 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
1029 if (self->peak_bitrate != req.dwPeakBitrate) {
1030 self->peak_bitrate = req.dwPeakBitrate;
1031 g_object_notify (G_OBJECT (self), "peak-bitrate");
1033 if (self->average_bitrate != req.dwAverageBitrate) {
1034 self->average_bitrate = req.dwAverageBitrate;
1035 g_object_notify (G_OBJECT (self), "average-bitrate");
1040 update_qp (GstUvcH264Src * self, gint type)
1042 uvcx_qp_steps_layers_t req;
1048 frame_type = UVC_H264_QP_STEPS_I_FRAME_TYPE;
1051 frame_type = UVC_H264_QP_STEPS_P_FRAME_TYPE;
1054 frame_type = UVC_H264_QP_STEPS_B_FRAME_TYPE;
1059 req.bFrameType = frame_type;
1062 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
1063 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
1067 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1068 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
1072 if (req.bFrameType == frame_type) {
1073 if (self->min_qp[type] != req.bMinQp) {
1074 self->min_qp[type] = req.bMinQp;
1077 g_object_notify (G_OBJECT (self), "min-iframe-qp");
1080 g_object_notify (G_OBJECT (self), "min-pframe-qp");
1083 g_object_notify (G_OBJECT (self), "min-bframe-qp");
1089 if (self->max_qp[type] != req.bMaxQp) {
1090 self->max_qp[type] = req.bMaxQp;
1093 g_object_notify (G_OBJECT (self), "max-iframe-qp");
1096 g_object_notify (G_OBJECT (self), "max-pframe-qp");
1099 g_object_notify (G_OBJECT (self), "max-bframe-qp");
1107 self->min_qp[type] = 0xFF;
1108 self->max_qp[type] = 0xFF;
1114 update_ltr (GstUvcH264Src * self)
1116 uvcx_ltr_buffer_size_control_t req;
1118 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
1119 (guchar *) & req)) {
1120 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
1124 if (self->ltr_buffer_size != req.bLTRBufferSize) {
1125 self->ltr_buffer_size = req.bLTRBufferSize;
1126 g_object_notify (G_OBJECT (self), "ltr-buffer-size");
1128 if (self->ltr_encoder_control != req.bLTREncoderControl) {
1129 self->ltr_encoder_control = req.bLTREncoderControl;
1130 g_object_notify (G_OBJECT (self), "ltr-encoder-control");
1134 #define STORE_MIN_DEF_MAX(type) \
1135 *(type *)min = *((type *) (min_p + offset)); \
1136 *(type *)def = *((type *) (def_p + offset)); \
1137 *(type *)max = *((type *) (max_p + offset));
1140 probe_setting (GstUvcH264Src * self, uvcx_control_selector_t selector,
1141 guint offset, gint size, gpointer min, gpointer def, gpointer max)
1143 guchar *min_p, *def_p, *max_p;
1144 gboolean ret = FALSE;
1147 if (!xu_query (self, selector, UVC_GET_LEN, (guchar *) & len)) {
1148 GST_WARNING_OBJECT (self, "probe_setting GET_LEN error");
1151 min_p = g_malloc0 (len);
1152 def_p = g_malloc0 (len);
1153 max_p = g_malloc0 (len);
1155 if (!xu_query (self, selector, UVC_GET_MIN, min_p)) {
1156 GST_WARNING_OBJECT (self, "probe_setting GET_MIN error");
1159 if (!xu_query (self, selector, UVC_GET_DEF, def_p)) {
1160 GST_WARNING_OBJECT (self, "probe_setting GET_DEF error");
1163 if (!xu_query (self, selector, UVC_GET_MAX, max_p)) {
1164 GST_WARNING_OBJECT (self, "probe_setting GET_MAX error");
1170 STORE_MIN_DEF_MAX (gint8);
1174 STORE_MIN_DEF_MAX (guint8);
1178 STORE_MIN_DEF_MAX (gint16);
1182 STORE_MIN_DEF_MAX (guint16);
1186 STORE_MIN_DEF_MAX (gint32);
1190 STORE_MIN_DEF_MAX (guint32);
1206 test_enum_setting (GstUvcH264Src * self, guint offset, guint size,
1209 uvcx_video_config_probe_commit_t cur;
1210 uvcx_video_config_probe_commit_t req;
1211 guchar *req_p = (guchar *) & req;
1213 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, (guchar *) & cur)) {
1214 GST_WARNING_OBJECT (self, " GET_CUR error");
1221 *((guint8 *) (req_p + offset)) = (guint8) value;
1223 *((guint16 *) (req_p + offset)) = value;
1225 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, req_p)) {
1226 GST_WARNING_OBJECT (self, " SET_CUR error");
1230 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, req_p)) {
1231 GST_WARNING_OBJECT (self, " GET_CUR error");
1235 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, (guchar *) & cur)) {
1236 GST_WARNING_OBJECT (self, " SET_CUR error");
1241 return *((guint8 *) (req_p + offset)) == (guint8) value;
1243 return *((guint16 *) (req_p + offset)) == value;
1247 gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self, gchar * property,
1248 gint * mask, gint * default_value)
1250 guint8 min, def, max;
1252 gboolean ret = FALSE;
1254 if (g_strcmp0 (property, "slice-mode") == 0) {
1255 guint16 min16, def16, max16;
1258 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1259 offsetof (uvcx_video_config_probe_commit_t, wSliceMode), 2,
1260 &min16, &def16, &max16);
1262 *default_value = def16;
1264 for (en16 = min16; en16 <= max16; en16++) {
1265 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1266 wSliceMode), 2, en16))
1267 *mask |= (1 << en16);
1270 } else if (g_strcmp0 (property, "usage-type") == 0) {
1271 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1272 offsetof (uvcx_video_config_probe_commit_t, bUsageType), 1,
1275 *default_value = def;
1277 for (en = min; en <= max; en++) {
1278 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1279 bUsageType), 1, en))
1283 } else if (g_strcmp0 (property, "entropy") == 0) {
1284 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1285 offsetof (uvcx_video_config_probe_commit_t, bEntropyCABAC), 1,
1288 *mask = (1 << min) | (1 << max);
1289 *default_value = def;
1291 } else if (g_strcmp0 (property, "rate-control") == 0) {
1292 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1293 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode), 1,
1296 uvcx_rate_control_mode_t cur;
1298 *default_value = def;
1301 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR,
1302 (guchar *) & cur)) {
1303 GST_WARNING_OBJECT (self, " CONTROL_MODE GET_CUR error");
1307 for (en = min; en <= max; en++) {
1308 uvcx_rate_control_mode_t req = { 0, en };
1310 if (xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR,
1311 (guchar *) & req) &&
1312 xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR,
1313 (guchar *) & req) && req.bRateControlMode == en)
1316 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR,
1317 (guchar *) & cur)) {
1318 GST_WARNING_OBJECT (self, " CONTROL_MODE SET_CUR error");
1328 gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self, gchar * property,
1329 gboolean * changeable, gboolean * default_value)
1331 guint8 min, def, max;
1332 gboolean ret = FALSE;
1334 if (g_strcmp0 (property, "enable-sei") == 0) {
1335 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1336 offsetof (uvcx_video_config_probe_commit_t, bTimestamp), 1,
1337 &min, &def, &max))) {
1338 *changeable = (min != max);
1339 *default_value = (def != 0);
1341 } else if (g_strcmp0 (property, "preview-flipped") == 0) {
1342 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1343 offsetof (uvcx_video_config_probe_commit_t, bPreviewFlipped), 1,
1344 &min, &def, &max))) {
1345 *changeable = (min != max);
1346 *default_value = (def != 0);
1348 } else if (g_strcmp0 (property, "fixed-framerate") == 0) {
1349 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1350 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode),
1351 1, &min, &def, &max))) {
1352 *changeable = ((max & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1353 *default_value = ((def & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1361 gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self, gchar * property,
1362 gint * min, gint * def, gint * max)
1364 guint32 min32, def32, max32;
1365 guint16 min16, def16, max16;
1366 guint8 min8, def8, max8;
1367 gint8 smin8, sdef8, smax8;
1368 gboolean ret = FALSE;
1370 GST_DEBUG_OBJECT (self, "Probing int property %s", property);
1371 if (g_strcmp0 (property, "initial-bitrate") == 0) {
1372 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1373 offsetof (uvcx_video_config_probe_commit_t, dwBitRate), 4,
1374 &min32, &def32, &max32);
1380 } else if (g_strcmp0 (property, "slice-units") == 0) {
1381 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1382 offsetof (uvcx_video_config_probe_commit_t, wSliceUnits), 2,
1383 &min16, &def16, &max16);
1389 } else if (g_strcmp0 (property, "iframe-period") == 0) {
1390 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1391 offsetof (uvcx_video_config_probe_commit_t, wIFramePeriod), 2,
1392 &min16, &def16, &max16);
1398 } else if (g_strcmp0 (property, "num-reorder-frames") == 0) {
1399 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1400 offsetof (uvcx_video_config_probe_commit_t, bNumOfReorderFrames), 1,
1401 &min8, &def8, &max8);
1407 } else if (g_strcmp0 (property, "leaky-bucket-size") == 0) {
1408 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1409 offsetof (uvcx_video_config_probe_commit_t, wLeakyBucketSize), 2,
1410 &min16, &def16, &max16);
1416 } else if (g_strcmp0 (property, "level-idc") == 0) {
1417 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1418 offsetof (uvcx_video_advance_config_t, blevel_idc), 1,
1419 &min8, &def8, &max8);
1425 } else if (g_strcmp0 (property, "max-mbps") == 0) {
1426 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1427 offsetof (uvcx_video_advance_config_t, dwMb_max), 4,
1428 &min32, &def32, &max32);
1434 } else if (g_strcmp0 (property, "peak-bitrate") == 0) {
1435 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1436 offsetof (uvcx_bitrate_layers_t, dwPeakBitrate), 4,
1437 &min32, &def32, &max32);
1443 } else if (g_strcmp0 (property, "average-bitrate") == 0) {
1444 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1445 offsetof (uvcx_bitrate_layers_t, dwAverageBitrate), 4,
1446 &min32, &def32, &max32);
1452 } else if (g_strcmp0 (property, "min-iframe-qp") == 0) {
1453 if (update_qp (self, QP_I_FRAME))
1454 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1455 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1461 } else if (g_strcmp0 (property, "max-iframe-qp") == 0) {
1462 if (update_qp (self, QP_I_FRAME))
1463 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1464 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1470 } else if (g_strcmp0 (property, "min-pframe-qp") == 0) {
1471 if (update_qp (self, QP_P_FRAME))
1472 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1473 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1479 } else if (g_strcmp0 (property, "max-pframe-qp") == 0) {
1480 if (update_qp (self, QP_P_FRAME))
1481 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1482 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1488 } else if (g_strcmp0 (property, "min-bframe-qp") == 0) {
1489 if (update_qp (self, QP_B_FRAME))
1490 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1491 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1497 } else if (g_strcmp0 (property, "max-bframe-qp") == 0) {
1498 if (update_qp (self, QP_B_FRAME))
1499 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1500 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1506 } else if (g_strcmp0 (property, "ltr-buffer-size") == 0) {
1507 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1508 offsetof (uvcx_ltr_buffer_size_control_t, bLTRBufferSize), 1,
1509 &min8, &def8, &max8);
1515 } else if (g_strcmp0 (property, "ltr-encoder-control") == 0) {
1516 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1517 offsetof (uvcx_ltr_buffer_size_control_t, bLTREncoderControl), 1,
1518 &min8, &def8, &max8);
1525 g_return_val_if_reached (FALSE);
1531 static GstPadProbeReturn
1532 gst_uvc_h264_src_event_probe (GstPad * pad, GstPadProbeInfo * info,
1535 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1536 GstPadProbeReturn ret = GST_PAD_PROBE_OK;
1537 GstEvent *event = info->data;
1539 switch (GST_EVENT_TYPE (event)) {
1540 case GST_EVENT_SEGMENT:
1541 if (pad == self->vidsrc) {
1542 const GstSegment *s;
1544 gst_event_parse_segment (event, &s);
1545 gst_segment_copy_into (s, &self->segment);
1549 ret = self->reconfiguring ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK;
1558 static GstPadProbeReturn
1559 gst_uvc_h264_src_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
1562 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1563 GstBuffer *buffer = info->data;
1565 /* TODO: Check the NALU type and make sure it is a keyframe */
1566 if (self->key_unit_event) {
1567 GstClockTime ts, running_time, stream_time;
1568 gboolean all_headers;
1570 GstEvent *downstream;
1572 if (gst_video_event_parse_upstream_force_key_unit (self->key_unit_event,
1573 &ts, &all_headers, &count)) {
1574 if (!GST_CLOCK_TIME_IS_VALID (ts)) {
1575 ts = GST_BUFFER_TIMESTAMP (buffer);
1577 running_time = gst_segment_to_running_time (&self->segment,
1578 GST_FORMAT_TIME, ts);
1580 stream_time = gst_segment_to_stream_time (&self->segment,
1581 GST_FORMAT_TIME, ts);
1583 GST_DEBUG_OBJECT (self, "Sending downstream force-key-unit : %d - %d ts=%"
1584 GST_TIME_FORMAT " running time =%" GST_TIME_FORMAT " stream=%"
1585 GST_TIME_FORMAT, all_headers, count, GST_TIME_ARGS (ts),
1586 GST_TIME_ARGS (running_time), GST_TIME_ARGS (stream_time));
1587 downstream = gst_video_event_new_downstream_force_key_unit (ts,
1588 stream_time, running_time, all_headers, count);
1589 gst_pad_push_event (self->vidsrc, downstream);
1590 gst_event_replace (&self->key_unit_event, NULL);
1597 gst_uvc_h264_src_parse_event (GstUvcH264Src * self, GstPad * pad,
1600 const GstStructure *s = gst_event_get_structure (event);
1602 switch (GST_EVENT_TYPE (event)) {
1603 case GST_EVENT_CUSTOM_UPSTREAM:
1604 if (pad == self->vidsrc && self->main_format == UVC_H264_SRC_FORMAT_H264) {
1605 if (gst_video_event_is_force_key_unit (event)) {
1606 uvcx_picture_type_control_t req = { 0, 0 };
1608 gboolean all_headers;
1610 if (gst_video_event_parse_upstream_force_key_unit (event,
1611 &ts, &all_headers, NULL)) {
1612 GST_INFO_OBJECT (self, "Received upstream force-key-unit : %d %"
1613 GST_TIME_FORMAT, all_headers, GST_TIME_ARGS (ts));
1614 /* TODO: wait until 'ts' time is reached */
1616 req.wPicType = UVC_H264_PICTYPE_IDR_WITH_PPS_SPS;
1618 req.wPicType = UVC_H264_PICTYPE_IDR;
1620 if (!xu_query (self, UVCX_PICTURE_TYPE_CONTROL, UVC_SET_CUR,
1621 (guchar *) & req)) {
1622 GST_WARNING_OBJECT (self, " PICTURE_TYPE_CONTROL SET_CUR error");
1624 gst_event_replace (&self->key_unit_event, event);
1625 gst_event_unref (event);
1631 gst_structure_has_name (s, "uvc-h264-ltr-picture-control")) {
1632 guint put_at, encode_using;
1634 if (gst_structure_get_uint (s, "put-at", &put_at) &&
1635 gst_structure_get_uint (s, "encode-using", &encode_using)) {
1636 uvcx_ltr_picture_control req = { 0, put_at, encode_using };
1638 if (!xu_query (self, UVCX_LTR_PICTURE_CONTROL, UVC_SET_CUR,
1639 (guchar *) & req)) {
1640 GST_WARNING_OBJECT (self, " LTR PICTURE_CONTROL SET_CUR error");
1642 gst_event_unref (event);
1648 } else if (s && gst_structure_has_name (s, "uvc-h264-bitrate-control")) {
1649 guint average, peak;
1651 if (gst_structure_get_uint (s, "average-bitrate", &average) &&
1652 gst_structure_get_uint (s, "peak-bitrate", &peak)) {
1653 self->average_bitrate = average;
1654 self->peak_bitrate = peak;
1656 update_bitrate (self);
1658 gst_event_unref (event);
1662 } else if (s && gst_structure_has_name (s, "uvc-h264-qp-control")) {
1663 gint min_qp, max_qp;
1664 gboolean valid_event = FALSE;
1666 if (gst_structure_get_int (s, "min-iframe-qp", &min_qp) &&
1667 gst_structure_get_int (s, "max-iframe-qp", &max_qp)) {
1668 self->min_qp[QP_I_FRAME] = min_qp;
1669 self->max_qp[QP_I_FRAME] = max_qp;
1670 set_qp (self, QP_I_FRAME);
1671 update_qp (self, QP_I_FRAME);
1674 if (gst_structure_get_int (s, "min-pframe-qp", &min_qp) &&
1675 gst_structure_get_int (s, "max-pframe-qp", &max_qp)) {
1676 self->min_qp[QP_P_FRAME] = min_qp;
1677 self->max_qp[QP_P_FRAME] = max_qp;
1678 set_qp (self, QP_P_FRAME);
1679 update_qp (self, QP_P_FRAME);
1682 if (gst_structure_get_int (s, "min-bframe-qp", &min_qp) &&
1683 gst_structure_get_int (s, "max-bframe-qp", &max_qp)) {
1684 self->min_qp[QP_B_FRAME] = min_qp;
1685 self->max_qp[QP_B_FRAME] = max_qp;
1686 set_qp (self, QP_B_FRAME);
1687 update_qp (self, QP_B_FRAME);
1692 gst_event_unref (event);
1696 } else if (s && gst_structure_has_name (s, "uvc-h264-rate-control")) {
1697 UvcH264RateControl rate;
1698 gboolean fixed_framerate;
1700 if (gst_structure_get_enum (s, "rate-control",
1701 UVC_H264_RATECONTROL_TYPE, (gint *) & rate) &&
1702 gst_structure_get_boolean (s, "fixed-framerate",
1703 &fixed_framerate)) {
1704 self->rate_control = rate;
1705 self->fixed_framerate = fixed_framerate;
1706 set_rate_control (self);
1707 update_rate_control (self);
1709 gst_event_unref (event);
1713 } else if (s && gst_structure_has_name (s, "uvc-h264-level-idc")) {
1716 if (gst_structure_get_uint (s, "level-idc", &level_idc)) {
1717 self->level_idc = level_idc;
1718 set_level_idc (self);
1719 update_level_idc_and_get_max_mbps (self);
1721 gst_event_unref (event);
1734 gst_uvc_h264_src_send_event (GstElement * element, GstEvent * event)
1736 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
1738 if (gst_uvc_h264_src_parse_event (self, self->vidsrc, event))
1741 return GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
1745 gst_uvc_h264_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1747 GstUvcH264Src *self = GST_UVC_H264_SRC (GST_PAD_PARENT (pad));
1749 switch (GST_EVENT_TYPE (event)) {
1750 case GST_EVENT_SEGMENT:
1751 if (pad == self->vidsrc) {
1752 const GstSegment *s;
1754 gst_event_parse_segment (event, &s);
1755 gst_segment_copy_into (s, &self->segment);
1758 case GST_EVENT_FLUSH_STOP:
1759 if (pad == self->vidsrc)
1760 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
1763 if (gst_uvc_h264_src_parse_event (self, pad, event))
1767 return self->srcpad_event_func (pad, parent, event);
1771 xu_query (GstUvcH264Src * self, guint selector, guint query, guchar * data)
1773 struct uvc_xu_control_query xu;
1776 if (self->v4l2_fd == -1) {
1777 GST_WARNING_OBJECT (self, "Can't query XU with fd = -1");
1781 xu.unit = self->h264_unit_id;
1782 xu.selector = selector;
1784 xu.query = UVC_GET_LEN;
1785 xu.size = sizeof (len);
1786 xu.data = (unsigned char *) &len;
1787 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1788 GST_WARNING_OBJECT (self, "PROBE GET_LEN error");
1792 if (query == UVC_GET_LEN) {
1793 *((__u16 *) data) = len;
1798 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1807 fill_probe_commit (GstUvcH264Src * self,
1808 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
1809 guint32 width, guint32 height, guint32 profile,
1810 UvcH264StreamFormat stream_format)
1812 probe->dwFrameInterval = frame_interval;
1813 probe->dwBitRate = self->initial_bitrate;
1814 probe->wWidth = width;
1815 probe->wHeight = height;
1816 probe->wSliceUnits = self->slice_units;
1817 probe->wSliceMode = self->slice_mode;
1818 probe->wProfile = profile;
1819 probe->wIFramePeriod = self->iframe_period;
1820 probe->bUsageType = self->usage_type;
1821 probe->bRateControlMode = self->rate_control;
1822 if (self->fixed_framerate)
1823 probe->bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
1824 probe->bStreamFormat = stream_format;
1825 probe->bEntropyCABAC = self->entropy;
1826 probe->bTimestamp = self->enable_sei ?
1827 UVC_H264_TIMESTAMP_SEI_ENABLE : UVC_H264_TIMESTAMP_SEI_DISABLE;
1828 probe->bNumOfReorderFrames = self->num_reorder_frames;
1829 probe->bPreviewFlipped = self->preview_flipped ?
1830 UVC_H264_PREFLIPPED_HORIZONTAL : UVC_H264_PREFLIPPED_DISABLE;
1831 probe->wLeakyBucketSize = self->leaky_bucket_size;
1835 print_probe_commit (GstUvcH264Src * self,
1836 uvcx_video_config_probe_commit_t * probe)
1838 GST_DEBUG_OBJECT (self, " Frame interval : %d *100ns",
1839 probe->dwFrameInterval);
1840 GST_DEBUG_OBJECT (self, " Bit rate : %d", probe->dwBitRate);
1841 GST_DEBUG_OBJECT (self, " Hints : %X", probe->bmHints);
1842 GST_DEBUG_OBJECT (self, " Configuration index : %d",
1843 probe->wConfigurationIndex);
1844 GST_DEBUG_OBJECT (self, " Width : %d", probe->wWidth);
1845 GST_DEBUG_OBJECT (self, " Height : %d", probe->wHeight);
1846 GST_DEBUG_OBJECT (self, " Slice units : %d", probe->wSliceUnits);
1847 GST_DEBUG_OBJECT (self, " Slice mode : %X", probe->wSliceMode);
1848 GST_DEBUG_OBJECT (self, " Profile : %X", probe->wProfile);
1849 GST_DEBUG_OBJECT (self, " IFrame Period : %d ms", probe->wIFramePeriod);
1850 GST_DEBUG_OBJECT (self, " Estimated video delay : %d ms",
1851 probe->wEstimatedVideoDelay);
1852 GST_DEBUG_OBJECT (self, " Estimated max config delay : %d ms",
1853 probe->wEstimatedMaxConfigDelay);
1854 GST_DEBUG_OBJECT (self, " Usage type : %X", probe->bUsageType);
1855 GST_DEBUG_OBJECT (self, " Rate control mode : %X", probe->bRateControlMode);
1856 GST_DEBUG_OBJECT (self, " Temporal scale mode : %X",
1857 probe->bTemporalScaleMode);
1858 GST_DEBUG_OBJECT (self, " Spatial scale mode : %X",
1859 probe->bSpatialScaleMode);
1860 GST_DEBUG_OBJECT (self, " SNR scale mode : %X", probe->bSNRScaleMode);
1861 GST_DEBUG_OBJECT (self, " Stream mux option : %X", probe->bStreamMuxOption);
1862 GST_DEBUG_OBJECT (self, " Stream Format : %X", probe->bStreamFormat);
1863 GST_DEBUG_OBJECT (self, " Entropy CABAC : %X", probe->bEntropyCABAC);
1864 GST_DEBUG_OBJECT (self, " Timestamp : %X", probe->bTimestamp);
1865 GST_DEBUG_OBJECT (self, " Num of reorder frames : %d",
1866 probe->bNumOfReorderFrames);
1867 GST_DEBUG_OBJECT (self, " Preview flipped : %X", probe->bPreviewFlipped);
1868 GST_DEBUG_OBJECT (self, " View : %d", probe->bView);
1869 GST_DEBUG_OBJECT (self, " Stream ID : %X", probe->bStreamID);
1870 GST_DEBUG_OBJECT (self, " Spatial layer ratio : %f",
1871 ((probe->bSpatialLayerRatio & 0xF0) >> 4) +
1872 ((float) (probe->bSpatialLayerRatio & 0x0F)) / 16);
1873 GST_DEBUG_OBJECT (self, " Leaky bucket size : %d ms",
1874 probe->wLeakyBucketSize);
1878 configure_h264 (GstUvcH264Src * self, gint fd)
1880 uvcx_video_config_probe_commit_t probe;
1882 /* Set the secondary format first, so the last SET_CUR will be for the
1883 * H264 format. This way, we can still get the static control values with
1884 * a GET_CUR. Otherwise all static properties will return 0 because that's
1885 * what the GET_CUR of the raw format returns.
1887 if (self->secondary_format == UVC_H264_SRC_FORMAT_RAW) {
1888 memset (&probe, 0, sizeof (probe));
1889 probe.dwFrameInterval = self->secondary_frame_interval;
1890 probe.wWidth = self->secondary_width;
1891 probe.wHeight = self->secondary_height;
1892 probe.bStreamMuxOption = 5;
1894 GST_DEBUG_OBJECT (self, "RAW PROBE SET_CUR : ");
1895 print_probe_commit (self, &probe);
1897 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
1898 (guchar *) & probe)) {
1899 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
1903 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
1904 (guchar *) & probe)) {
1905 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
1908 GST_DEBUG_OBJECT (self, "RAW PROBE GET_CUR : ");
1909 print_probe_commit (self, &probe);
1911 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
1912 (guchar *) & probe)) {
1913 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
1917 /* Print MIN/MAX/DEF probe values for debugging purposes */
1918 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MIN,
1919 (guchar *) & probe)) {
1920 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
1923 GST_DEBUG_OBJECT (self, "PROBE GET_MIN : ");
1924 print_probe_commit (self, &probe);
1926 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MAX,
1927 (guchar *) & probe)) {
1928 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
1931 GST_DEBUG_OBJECT (self, "PROBE GET_MAX : ");
1932 print_probe_commit (self, &probe);
1934 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_DEF,
1935 (guchar *) & probe)) {
1936 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
1939 GST_DEBUG_OBJECT (self, "PROBE GET_DEF : ");
1940 print_probe_commit (self, &probe);
1942 fill_probe_commit (self, &probe, self->main_frame_interval,
1943 self->main_width, self->main_height, self->main_profile,
1944 self->main_stream_format);
1945 if (self->secondary_format != UVC_H264_SRC_FORMAT_NONE)
1946 probe.bStreamMuxOption = 3;
1948 probe.bStreamMuxOption = 0;
1949 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION | UVC_H264_BMHINTS_PROFILE |
1950 UVC_H264_BMHINTS_FRAME_INTERVAL;
1952 GST_DEBUG_OBJECT (self, "PROBE SET_CUR : ");
1953 print_probe_commit (self, &probe);
1955 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
1956 (guchar *) & probe)) {
1957 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
1961 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
1962 (guchar *) & probe)) {
1963 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
1966 GST_DEBUG_OBJECT (self, "PROBE GET_CUR : ");
1967 print_probe_commit (self, &probe);
1969 /* Must validate the settings accepted by the encoder */
1970 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
1971 (guchar *) & probe)) {
1972 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
1978 v4l2src_prepare_format (GstElement * v4l2src, gint fd, GstCaps * caps,
1981 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1983 if (self->main_format == UVC_H264_SRC_FORMAT_H264) {
1984 /* TODO: update static controls and g_object_notify those that changed */
1985 configure_h264 (self, fd);
1987 /* TODO: update dynamic controls on READY state */
1988 /* Configure dynamic controls */
1989 set_rate_control (self);
1990 update_rate_control (self);
1991 set_level_idc (self);
1992 update_level_idc_and_get_max_mbps (self);
1994 update_bitrate (self);
1995 set_qp (self, QP_I_FRAME);
1996 update_qp (self, QP_I_FRAME);
1997 set_qp (self, QP_P_FRAME);
1998 update_qp (self, QP_P_FRAME);
1999 set_qp (self, QP_B_FRAME);
2000 update_qp (self, QP_B_FRAME);
2007 _extract_caps_info (GstStructure * structure, guint16 * width, guint16 * height,
2008 guint32 * frame_interval)
2010 gint w, h, fps_n, fps_d;
2011 gboolean ret = TRUE;
2013 ret &= gst_structure_get_int (structure, "width", &w);
2014 ret &= gst_structure_get_int (structure, "height", &h);
2015 ret &= gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
2020 /* Interval is in 100ns */
2021 *frame_interval = GST_TIME_AS_NSECONDS ((fps_d * GST_SECOND) / fps_n) / 100;
2028 _extract_profile (GstStructure * structure)
2030 const gchar *profile_str;
2033 profile = UVC_H264_PROFILE_HIGH;
2034 profile_str = gst_structure_get_string (structure, "profile");
2036 if (!strcmp (profile_str, "constrained-baseline")) {
2037 profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
2038 } else if (!strcmp (profile_str, "baseline")) {
2039 profile = UVC_H264_PROFILE_BASELINE;
2040 } else if (!strcmp (profile_str, "main")) {
2041 profile = UVC_H264_PROFILE_MAIN;
2042 } else if (!strcmp (profile_str, "high")) {
2043 profile = UVC_H264_PROFILE_HIGH;
2049 static UvcH264StreamFormat
2050 _extract_stream_format (GstStructure * structure)
2052 const gchar *stream_format;
2054 stream_format = gst_structure_get_string (structure, "stream-format");
2055 if (stream_format) {
2056 if (!strcmp (stream_format, "avc"))
2057 return UVC_H264_STREAMFORMAT_NAL;
2058 else if (!strcmp (stream_format, "byte-stream"))
2059 return UVC_H264_STREAMFORMAT_ANNEXB;
2061 return UVC_H264_STREAMFORMAT_ANNEXB;
2065 _transform_caps (GstUvcH264Src * self, GstCaps * caps, const gchar * name)
2067 GstElement *el = gst_element_factory_make (name, NULL);
2068 GstElement *cf = gst_element_factory_make ("capsfilter", NULL);
2069 GstElement *fs = gst_element_factory_make ("fakesink", NULL);
2071 GstCaps *out_caps = NULL;
2073 if (!el || !cf || !fs) {
2075 gst_object_unref (el);
2077 gst_object_unref (cf);
2079 gst_object_unref (fs);
2083 gst_element_set_locked_state (el, TRUE);
2084 gst_element_set_locked_state (cf, TRUE);
2085 gst_element_set_locked_state (fs, TRUE);
2087 if (!gst_bin_add (GST_BIN (self), el)) {
2088 gst_object_unref (el);
2089 gst_object_unref (cf);
2090 gst_object_unref (fs);
2093 if (!gst_bin_add (GST_BIN (self), cf)) {
2094 gst_object_unref (cf);
2095 gst_object_unref (fs);
2096 gst_bin_remove (GST_BIN (self), el);
2099 if (!gst_bin_add (GST_BIN (self), fs)) {
2100 gst_object_unref (fs);
2101 gst_bin_remove (GST_BIN (self), el);
2102 gst_bin_remove (GST_BIN (self), cf);
2106 g_object_set (cf, "caps", caps, NULL);
2108 if (!gst_element_link (cf, fs))
2110 if (!gst_element_link (el, cf))
2113 sink = gst_element_get_static_pad (el, "sink");
2116 GST_DEBUG_OBJECT (self, "Transforming: %" GST_PTR_FORMAT, caps);
2118 caps = gst_pad_query_caps (sink, NULL);
2119 gst_object_unref (sink);
2121 GST_DEBUG_OBJECT (self, "Result: %" GST_PTR_FORMAT, out_caps);
2124 gst_bin_remove (GST_BIN (self), cf);
2125 gst_bin_remove (GST_BIN (self), el);
2126 gst_bin_remove (GST_BIN (self), fs);
2129 if (out_caps == NULL)
2130 out_caps = gst_caps_copy (caps);
2136 gst_uvc_h264_src_transform_caps (GstUvcH264Src * self, GstCaps * caps)
2138 GstCaps *h264 = gst_caps_new_empty_simple ("video/x-h264");
2139 GstCaps *jpg = gst_caps_new_empty_simple ("image/jpeg");
2140 GstCaps *h264_caps = gst_caps_intersect (h264, caps);
2141 GstCaps *jpg_caps = gst_caps_intersect (jpg, caps);
2143 /* TODO: Keep caps order after transformation */
2144 caps = _transform_caps (self, caps, self->colorspace_name);
2145 caps = gst_caps_make_writable (caps);
2147 if (!gst_caps_is_empty (h264_caps)) {
2148 gst_caps_append (caps, h264_caps);
2150 gst_caps_unref (h264_caps);
2153 if (!gst_caps_is_empty (jpg_caps)) {
2154 gst_caps_append (caps, jpg_caps);
2156 gst_caps_unref (jpg_caps);
2159 gst_caps_unref (h264);
2160 gst_caps_unref (jpg);
2166 gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad,
2167 GstCaps * v4l_caps, GstCaps * peer_caps, gboolean primary)
2169 GstCaps *caps = NULL;
2170 GstCaps *icaps = NULL;
2171 GstCaps *tcaps = NULL;
2174 if (v4l_caps == NULL || gst_caps_is_any (v4l_caps)) {
2175 GST_DEBUG_OBJECT (self, "v4l caps are invalid. not fixating");
2179 tcaps = gst_caps_intersect_full (peer_caps, v4l_caps,
2180 GST_CAPS_INTERSECT_FIRST);
2181 GST_DEBUG_OBJECT (self, "intersect: %" GST_PTR_FORMAT, tcaps);
2182 icaps = gst_caps_normalize (tcaps);
2184 /* Prefer the first caps we are compatible with that the peer proposed */
2185 for (i = 0; i < gst_caps_get_size (icaps); i++) {
2186 /* get intersection */
2187 GstCaps *ipcaps = gst_caps_copy_nth (icaps, i);
2188 GstStructure *s = gst_caps_get_structure (ipcaps, 0);
2190 GST_DEBUG_OBJECT (self, "Testing %s: %" GST_PTR_FORMAT,
2191 primary ? "primary" : "secondary", ipcaps);
2192 if (primary && gst_structure_has_name (s, "video/x-h264")) {
2193 uvcx_video_config_probe_commit_t probe;
2198 UvcH264StreamFormat stream_format;
2200 if (_extract_caps_info (s, &width, &height, &interval)) {
2201 profile = _extract_profile (s);
2202 stream_format = _extract_stream_format (s);
2203 fill_probe_commit (self, &probe, interval, width, height,
2204 profile, stream_format);
2205 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2206 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2208 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2209 (guchar *) & probe)) {
2210 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2214 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2215 (guchar *) & probe)) {
2216 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2219 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d==%d",
2220 probe.wWidth, width, probe.wHeight, height,
2221 probe.bStreamFormat, stream_format);
2222 if (probe.wWidth == width && probe.wHeight == height &&
2223 probe.bStreamFormat == stream_format) {
2228 } else if (!primary && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2229 uvcx_video_config_probe_commit_t probe;
2234 if (_extract_caps_info (s, &width, &height, &interval)) {
2235 if (gst_structure_has_name (s, "video/x-raw")) {
2237 const gchar *format = gst_structure_get_string (s, "format");
2239 if ((format = gst_structure_get_string (s, "format"))) {
2240 if (g_strcmp0 (format, "YUY2") == 0)
2242 else if (g_strcmp0 (format, "NV12") == 0)
2246 memset (&probe, 0, sizeof (probe));
2247 probe.dwFrameInterval = interval;
2248 probe.wWidth = width;
2249 probe.wHeight = height;
2250 probe.bStreamMuxOption = mux | 1;
2251 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2252 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2254 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2255 (guchar *) & probe)) {
2256 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2260 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2261 (guchar *) & probe)) {
2262 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2265 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d~=%d",
2266 probe.wWidth, width, probe.wHeight, height,
2267 probe.bStreamMuxOption, mux);
2268 if (probe.wWidth == width && probe.wHeight == height &&
2269 (probe.bStreamMuxOption & mux) != 0) {
2274 } else if (gst_structure_has_name (s, "image/jpeg")) {
2275 /* HACK ALERT: No way of figuring this one out but it seems the
2276 * camera doesn't allow for h264 muxing and jpeg resolution higher
2277 * than 640x480 so we shouldn't allow it */
2278 if (width <= 640 && height <= 480) {
2288 gst_caps_unref (ipcaps);
2292 caps = gst_caps_make_writable (caps);
2295 if (!gst_caps_is_empty (caps)) {
2296 caps = gst_caps_fixate (caps);
2297 GST_DEBUG_OBJECT (self, "fixated to: %" GST_PTR_FORMAT, caps);
2300 if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
2301 gst_caps_unref (caps);
2310 gst_uvc_h264_src_destroy_pipeline (GstUvcH264Src * self, gboolean v4l2src)
2312 GstIterator *iter = NULL;
2315 if (v4l2src && self->v4l2_src) {
2316 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2317 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2318 gst_object_unref (self->v4l2_src);
2319 self->v4l2_src = NULL;
2321 self->h264_unit_id = 0;
2323 if (self->mjpg_demux) {
2324 gst_bin_remove (GST_BIN (self), self->mjpg_demux);
2325 gst_element_set_state (self->mjpg_demux, GST_STATE_NULL);
2326 gst_object_unref (self->mjpg_demux);
2327 self->mjpg_demux = NULL;
2329 if (self->jpeg_dec) {
2330 gst_bin_remove (GST_BIN (self), self->jpeg_dec);
2331 gst_element_set_state (self->jpeg_dec, GST_STATE_NULL);
2332 gst_object_unref (self->jpeg_dec);
2333 self->jpeg_dec = NULL;
2335 if (self->vid_colorspace) {
2336 gst_bin_remove (GST_BIN (self), self->vid_colorspace);
2337 gst_element_set_state (self->vid_colorspace, GST_STATE_NULL);
2338 gst_object_unref (self->vid_colorspace);
2339 self->vid_colorspace = NULL;
2341 if (self->vf_colorspace) {
2342 gst_bin_remove (GST_BIN (self), self->vf_colorspace);
2343 gst_element_set_state (self->vf_colorspace, GST_STATE_NULL);
2344 gst_object_unref (self->vf_colorspace);
2345 self->vf_colorspace = NULL;
2347 iter = gst_bin_iterate_elements (GST_BIN (self));
2350 GValue data = { 0, };
2352 switch (gst_iterator_next (iter, &data)) {
2353 case GST_ITERATOR_OK:
2355 GstElement *child = g_value_get_object (&data);
2356 if (child != self->v4l2_src) {
2357 gst_bin_remove (GST_BIN (self), child);
2358 gst_element_set_state (child, GST_STATE_NULL);
2360 g_value_reset (&data);
2363 case GST_ITERATOR_RESYNC:
2364 gst_iterator_resync (iter);
2366 case GST_ITERATOR_ERROR:
2369 case GST_ITERATOR_DONE:
2374 gst_iterator_free (iter);
2378 ensure_v4l2src (GstUvcH264Src * self)
2380 gchar *device = NULL;
2381 GstClock *v4l2_clock = NULL;
2383 if (self->v4l2_src == NULL) {
2384 /* Create v4l2 source and set it up */
2385 self->v4l2_src = gst_element_factory_make ("v4l2src", NULL);
2386 if (!self->v4l2_src || !gst_bin_add (GST_BIN (self), self->v4l2_src))
2388 gst_object_ref (self->v4l2_src);
2389 g_signal_connect (self->v4l2_src, "prepare-format",
2390 (GCallback) v4l2src_prepare_format, self);
2393 g_object_get (self->v4l2_src, "device", &device, NULL);
2394 g_object_set (self->v4l2_src,
2395 "device", self->device, "num-buffers", self->num_buffers, NULL);
2397 v4l2_clock = gst_element_get_clock (self->v4l2_src);
2399 /* Set to NULL if the device changed */
2400 if (g_strcmp0 (device, self->device))
2401 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2404 if (gst_element_set_state (self->v4l2_src, GST_STATE_READY) !=
2405 GST_STATE_CHANGE_SUCCESS) {
2406 GST_DEBUG_OBJECT (self, "Unable to set v4l2src to READY state");
2410 /* Set/Update the fd and unit id after we go to READY */
2411 g_object_get (self->v4l2_src, "device-fd", &self->v4l2_fd, NULL);
2412 self->h264_unit_id =
2413 xu_get_id (GST_OBJECT (self), self->device, &self->usb_ctx);
2415 if (self->h264_unit_id == 0) {
2416 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
2417 ("Device is not a valid UVC H264 camera"), (NULL));
2421 /* going to state READY makes v4l2src lose its reference to the clock */
2423 gst_element_set_clock (self->v4l2_src, v4l2_clock);
2424 gst_element_set_base_time (self->v4l2_src,
2425 gst_element_get_base_time (GST_ELEMENT (self)));
2426 gst_object_unref (v4l2_clock);
2432 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2433 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2437 gst_object_unref (v4l2_clock);
2439 gst_object_unref (self->v4l2_src);
2440 self->v4l2_src = NULL;
2442 self->h264_unit_id = 0;
2448 gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
2450 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
2451 GstIterator *iter = NULL;
2452 gboolean iter_done = FALSE;
2453 GstPad *vf_pad = NULL;
2454 GstCaps *vf_caps = NULL;
2455 GstStructure *vf_struct = NULL;
2456 GstPad *vid_pad = NULL;
2457 GstCaps *vid_caps = NULL;
2458 GstStructure *vid_struct = NULL;
2459 GstCaps *src_caps = NULL;
2460 GstPad *v4l_pad = NULL;
2461 GstCaps *v4l_caps = NULL;
2462 gboolean jpg2raw = FALSE;
2466 RAW_NONE, ENCODED_NONE, NONE_RAW, NONE_ENCODED,
2467 H264_JPG, H264_RAW, H264_JPG2RAW, NONE_NONE,
2468 RAW_RAW, ENCODED_ENCODED,
2471 GST_DEBUG_OBJECT (self, "Construct pipeline");
2472 self->reconfiguring = TRUE;
2474 if (self->v4l2_src) {
2475 uvcx_encoder_reset req = { 0 };
2477 if (!xu_query (self, UVCX_ENCODER_RESET, UVC_SET_CUR, (guchar *) & req))
2478 GST_WARNING_OBJECT (self, " UVCX_ENCODER_RESET SET_CUR error");
2481 if (!ensure_v4l2src (self))
2484 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
2486 /* Potentially unlink v4l2src to the ghost pads */
2487 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), NULL);
2488 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), NULL);
2490 if (gst_pad_is_linked (self->vfsrc))
2491 vf_caps = gst_pad_peer_query_caps (self->vfsrc, NULL);
2492 if (gst_pad_is_linked (self->vidsrc))
2493 vid_caps = gst_pad_peer_query_caps (self->vidsrc, NULL);
2495 GST_DEBUG_OBJECT (self, "vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2496 GST_DEBUG_OBJECT (self, "vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2497 if (!self->started) {
2498 GST_DEBUG_OBJECT (self, "video not started. Ignoring vidsrc caps");
2500 gst_caps_unref (vid_caps);
2504 v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2505 v4l_caps = gst_pad_query_caps (v4l_pad, NULL);
2506 GST_DEBUG_OBJECT (self, "v4l2src caps : %" GST_PTR_FORMAT, v4l_caps);
2508 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vid_caps);
2510 gst_caps_unref (vid_caps);
2511 vid_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2513 gst_caps_unref (trans_caps);
2516 vid_struct = gst_caps_get_structure (vid_caps, 0);
2518 GST_WARNING_OBJECT (self, "Could not negotiate vidsrc caps format");
2519 gst_object_unref (v4l_pad);
2520 gst_caps_unref (v4l_caps);
2524 GST_DEBUG_OBJECT (self, "Fixated vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2526 if (vid_caps && gst_structure_has_name (vid_struct, "video/x-h264")) {
2527 self->main_format = UVC_H264_SRC_FORMAT_H264;
2528 if (!_extract_caps_info (vid_struct, &self->main_width,
2529 &self->main_height, &self->main_frame_interval)) {
2530 gst_object_unref (v4l_pad);
2531 gst_caps_unref (v4l_caps);
2535 self->main_stream_format = _extract_stream_format (vid_struct);
2536 self->main_profile = _extract_profile (vid_struct);
2538 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2542 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vf_caps);
2544 gst_caps_unref (vf_caps);
2545 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2548 /* If we couldn't find a suitable vf cap, try the jpeg2raw pipeline */
2549 if (!vf_caps && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2553 jpg_caps = _transform_caps (self, trans_caps, self->jpeg_decoder_name);
2555 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2557 gst_caps_unref (jpg_caps);
2559 gst_caps_unref (trans_caps);
2561 vf_struct = gst_caps_get_structure (vf_caps, 0);
2563 GST_WARNING_OBJECT (self, "Could not negotiate vfsrc caps format");
2564 gst_object_unref (v4l_pad);
2565 gst_caps_unref (v4l_caps);
2569 GST_DEBUG_OBJECT (self, "Fixated vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2570 gst_object_unref (v4l_pad);
2571 gst_caps_unref (v4l_caps);
2573 if (vf_caps && vid_caps &&
2574 !gst_structure_has_name (vid_struct, "video/x-h264")) {
2575 /* Allow for vfsrc+vidsrc to both be raw or jpeg */
2576 if (gst_structure_has_name (vid_struct, "image/jpeg") &&
2577 gst_structure_has_name (vf_struct, "image/jpeg")) {
2578 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2579 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2580 type = ENCODED_ENCODED;
2581 } else if (!gst_structure_has_name (vid_struct, "image/jpeg") &&
2582 !gst_structure_has_name (vf_struct, "image/jpeg")) {
2583 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2584 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2589 } else if (vf_caps && vid_caps) {
2590 guint32 smallest_frame_interval;
2592 if (!_extract_caps_info (vf_struct, &self->secondary_width,
2593 &self->secondary_height, &self->secondary_frame_interval))
2596 if (jpg2raw == FALSE && gst_structure_has_name (vf_struct, "image/jpeg")) {
2598 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2601 type = H264_JPG2RAW;
2602 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2605 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2608 smallest_frame_interval = MIN (self->main_frame_interval,
2609 self->secondary_frame_interval);
2610 /* Just to avoid a potential division by zero, set interval to 30 fps */
2611 if (smallest_frame_interval == 0)
2612 smallest_frame_interval = 333333;
2614 /* Frame interval is in 100ns units */
2615 src_caps = gst_caps_new_simple ("image/jpeg",
2616 "width", G_TYPE_INT, self->secondary_width,
2617 "height", G_TYPE_INT, self->secondary_height,
2618 "framerate", GST_TYPE_FRACTION,
2619 NSEC_PER_SEC / smallest_frame_interval, 100, NULL);
2620 } else if (vf_caps || vid_caps) {
2621 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2622 if (vid_struct && gst_structure_has_name (vid_struct, "video/x-h264")) {
2623 type = ENCODED_NONE;
2624 } else if (vid_struct && gst_structure_has_name (vid_struct, "image/jpeg")) {
2625 type = ENCODED_NONE;
2626 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2627 } else if (vf_struct && gst_structure_has_name (vf_struct, "image/jpeg")) {
2628 type = NONE_ENCODED;
2629 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2630 } else if (vid_struct) {
2632 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2633 } else if (vf_struct) {
2635 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2637 g_assert_not_reached ();
2639 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2643 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2644 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2649 GST_DEBUG_OBJECT (self, "None+None");
2650 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2653 GST_DEBUG_OBJECT (self, "Raw+None");
2654 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2656 if (!self->vid_colorspace ||
2657 !gst_bin_add (GST_BIN (self), self->vid_colorspace))
2659 gst_object_ref (self->vid_colorspace);
2660 if (!gst_element_link (self->v4l2_src, self->vid_colorspace))
2661 goto error_remove_all;
2662 vid_pad = gst_element_get_static_pad (self->vid_colorspace, "src");
2665 GST_DEBUG_OBJECT (self, "None+Raw");
2666 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2668 if (!self->vf_colorspace ||
2669 !gst_bin_add (GST_BIN (self), self->vf_colorspace))
2671 gst_object_ref (self->vf_colorspace);
2672 if (!gst_element_link (self->v4l2_src, self->vf_colorspace))
2673 goto error_remove_all;
2674 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2677 GST_DEBUG_OBJECT (self, "Encoded+None");
2678 vid_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2681 GST_DEBUG_OBJECT (self, "None+Encoded");
2682 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2685 GST_DEBUG_OBJECT (self, "H264+JPG");
2686 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
2687 if (!self->mjpg_demux || !gst_bin_add (GST_BIN (self), self->mjpg_demux))
2689 gst_object_ref (self->mjpg_demux);
2690 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2691 "num-clock-samples", self->num_clock_samples, NULL);
2692 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2694 goto error_remove_all;
2695 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2696 vf_pad = gst_element_get_static_pad (self->mjpg_demux, "jpeg");
2699 GST_DEBUG_OBJECT (self, "H264+Raw");
2700 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
2701 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2703 if (!self->mjpg_demux || !self->vf_colorspace)
2705 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2707 gst_object_ref (self->mjpg_demux);
2708 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2709 "num-clock-samples", self->num_clock_samples, NULL);
2710 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace)) {
2711 gst_object_unref (self->vf_colorspace);
2712 self->vf_colorspace = NULL;
2713 goto error_remove_all;
2715 gst_object_ref (self->vf_colorspace);
2716 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2718 goto error_remove_all;
2719 if (!gst_element_link_pads (self->mjpg_demux, "yuy2",
2720 self->vf_colorspace, "sink"))
2721 goto error_remove_all;
2722 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2723 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2726 GST_DEBUG_OBJECT (self, "H264+Raw(jpegdec)");
2727 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
2728 self->jpeg_dec = gst_element_factory_make (self->jpeg_decoder_name, NULL);
2729 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2731 if (!self->mjpg_demux || !self->jpeg_dec || !self->vf_colorspace)
2733 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2735 gst_object_ref (self->mjpg_demux);
2736 g_object_set (self->mjpg_demux, "device-fd", self->v4l2_fd,
2737 "num-clock-samples", self->num_clock_samples, NULL);
2738 if (!gst_bin_add (GST_BIN (self), self->jpeg_dec)) {
2739 gst_object_unref (self->jpeg_dec);
2740 self->jpeg_dec = NULL;
2741 gst_object_unref (self->vf_colorspace);
2742 self->vf_colorspace = NULL;
2743 goto error_remove_all;
2745 gst_object_ref (self->jpeg_dec);
2746 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace)) {
2747 gst_object_unref (self->vf_colorspace);
2748 self->vf_colorspace = NULL;
2749 goto error_remove_all;
2751 gst_object_ref (self->vf_colorspace);
2752 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2754 goto error_remove_all;
2755 if (!gst_element_link_pads (self->mjpg_demux, "jpeg", self->jpeg_dec,
2757 goto error_remove_all;
2758 if (!gst_element_link (self->jpeg_dec, self->vf_colorspace))
2759 goto error_remove_all;
2760 vid_pad = gst_element_get_static_pad (self->mjpg_demux, "h264");
2761 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2765 GstElement *tee = NULL;
2767 GST_DEBUG_OBJECT (self, "Raw+Raw");
2768 tee = gst_element_factory_make ("tee", NULL);
2769 if (!tee || !gst_bin_add (GST_BIN (self), tee)) {
2771 gst_object_unref (tee);
2774 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2776 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2778 if (!self->vf_colorspace || !self->vid_colorspace)
2780 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace))
2782 gst_object_ref (self->vf_colorspace);
2783 if (!gst_bin_add (GST_BIN (self), self->vid_colorspace)) {
2784 gst_object_unref (self->vid_colorspace);
2785 self->vid_colorspace = NULL;
2786 goto error_remove_all;
2788 gst_object_ref (self->vid_colorspace);
2789 if (!gst_element_link (self->v4l2_src, tee))
2790 goto error_remove_all;
2791 if (!gst_element_link (tee, self->vf_colorspace))
2792 goto error_remove_all;
2793 if (!gst_element_link (tee, self->vid_colorspace))
2794 goto error_remove_all;
2795 vf_pad = gst_element_get_static_pad (self->vf_colorspace, "src");
2796 vid_pad = gst_element_get_static_pad (self->vid_colorspace, "src");
2799 case ENCODED_ENCODED:
2801 GstElement *tee = NULL;
2803 GST_DEBUG_OBJECT (self, "Encoded+Encoded");
2804 tee = gst_element_factory_make ("tee", NULL);
2805 if (!tee || !gst_bin_add (GST_BIN (self), tee)) {
2807 gst_object_unref (tee);
2810 if (!gst_element_link (self->v4l2_src, tee))
2811 goto error_remove_all;
2812 vf_pad = gst_element_get_request_pad (tee, "src_%u");
2813 vid_pad = gst_element_get_request_pad (tee, "src_%u");
2818 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), vid_pad) ||
2819 !gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad))
2820 goto error_remove_all;
2822 gst_object_unref (vid_pad);
2824 gst_object_unref (vf_pad);
2825 vid_pad = vf_pad = NULL;
2828 gst_caps_unref (vf_caps);
2830 gst_caps_unref (vid_caps);
2832 gst_caps_unref (src_caps);
2833 vf_caps = vid_caps = src_caps = NULL;
2835 /* Sync children states, in sink to source order */
2836 if (self->vid_colorspace &&
2837 !gst_element_sync_state_with_parent (self->vid_colorspace))
2838 goto error_remove_all;
2839 if (self->vf_colorspace &&
2840 !gst_element_sync_state_with_parent (self->vf_colorspace))
2841 goto error_remove_all;
2842 if (self->jpeg_dec && !gst_element_sync_state_with_parent (self->jpeg_dec))
2843 goto error_remove_all;
2844 if (self->mjpg_demux &&
2845 !gst_element_sync_state_with_parent (self->mjpg_demux))
2846 goto error_remove_all;
2847 if (self->v4l2_src && !gst_element_sync_state_with_parent (self->v4l2_src))
2848 goto error_remove_all;
2850 /* Sync any remaining children states with bin's state */
2851 iter = gst_bin_iterate_elements (GST_BIN (self));
2853 while (!iter_done) {
2854 GstElement *child = NULL;
2855 GValue data = { 0, };
2857 switch (gst_iterator_next (iter, &data)) {
2858 case GST_ITERATOR_OK:
2859 child = g_value_get_object (&data);
2860 if (!gst_element_sync_state_with_parent (child)) {
2861 g_value_reset (&data);
2862 gst_iterator_free (iter);
2863 goto error_remove_all;
2865 g_value_reset (&data);
2867 case GST_ITERATOR_RESYNC:
2868 gst_iterator_resync (iter);
2870 case GST_ITERATOR_ERROR:
2873 case GST_ITERATOR_DONE:
2878 gst_iterator_free (iter);
2880 self->reconfiguring = FALSE;
2884 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
2886 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2887 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2891 gst_object_unref (self->v4l2_src);
2892 self->v4l2_src = NULL;
2894 self->h264_unit_id = 0;
2896 if (self->mjpg_demux)
2897 gst_object_unref (self->mjpg_demux);
2898 self->mjpg_demux = NULL;
2900 gst_object_unref (self->jpeg_dec);
2901 self->jpeg_dec = NULL;
2902 if (self->vid_colorspace)
2903 gst_object_unref (self->vid_colorspace);
2904 self->vid_colorspace = NULL;
2905 if (self->vf_colorspace)
2906 gst_object_unref (self->vf_colorspace);
2907 self->vf_colorspace = NULL;
2910 gst_caps_unref (src_caps);
2913 gst_caps_unref (vf_caps);
2915 gst_caps_unref (vid_caps);
2918 gst_object_unref (vid_pad);
2920 gst_object_unref (vf_pad);
2922 self->reconfiguring = FALSE;
2927 gst_uvc_h264_src_getcaps (GstPad * pad, GstObject * parent, GstQuery * query)
2929 GstUvcH264Src *self = GST_UVC_H264_SRC (parent);
2930 GstCaps *template = NULL;
2931 GstCaps *result = NULL;
2933 if (pad == self->vfsrc)
2934 template = gst_static_pad_template_get_caps (&vfsrc_template);
2935 else if (pad == self->vidsrc)
2936 template = gst_static_pad_template_get_caps (&vidsrc_template);
2938 template = gst_caps_new_empty ();
2940 if (self->v4l2_src) {
2942 GstPad *v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2943 GstCaps *v4l_caps = NULL;
2944 GstCaps *new_caps = NULL;
2946 gst_query_parse_caps (query, &filter);
2947 v4l_caps = gst_pad_query_caps (v4l_pad, filter);
2948 new_caps = gst_uvc_h264_src_transform_caps (self, v4l_caps);
2950 result = gst_caps_intersect (new_caps, template);
2951 gst_object_unref (v4l_pad);
2952 gst_caps_unref (v4l_caps);
2953 gst_caps_unref (new_caps);
2954 gst_caps_unref (template);
2963 gst_uvc_h264_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
2967 switch (GST_QUERY_TYPE (query)) {
2968 case GST_QUERY_CAPS:{
2971 caps = gst_uvc_h264_src_getcaps (pad, parent, query);
2972 gst_query_set_caps_result (query, caps);
2973 gst_caps_unref (caps);
2978 ret = gst_pad_query_default (pad, parent, query);
2986 gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode)
2988 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
2990 GST_DEBUG_OBJECT (self, "set mode to %d", mode);
2992 return (mode == MODE_VIDEO);
2996 gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc)
2998 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
2999 gboolean ret = TRUE;
3001 GST_DEBUG_OBJECT (self, "start capture");
3003 if (!self->started) {
3004 self->started = TRUE;
3005 if (GST_STATE (self) >= GST_STATE_READY) {
3006 ret = gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3008 GST_DEBUG_OBJECT (self, "Could not start capture");
3009 self->started = FALSE;
3010 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3019 gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc)
3021 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
3023 GST_DEBUG_OBJECT (self, "stop capture");
3025 if (self->started) {
3026 self->started = FALSE;
3027 if (GST_STATE (self) >= GST_STATE_READY)
3028 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3029 gst_base_camera_src_finish_capture (camerasrc);
3034 gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
3035 GstPad * peer, gpointer user_data)
3037 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
3038 gchar *pad_name = gst_pad_get_name (pad);
3040 GST_DEBUG_OBJECT (self, "Pad %s was (un)linked. Renegotiating", pad_name);
3042 if (GST_STATE (self) >= GST_STATE_READY)
3043 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3047 static GstStateChangeReturn
3048 gst_uvc_h264_src_change_state (GstElement * element, GstStateChange trans)
3050 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3051 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
3054 case GST_STATE_CHANGE_NULL_TO_READY:
3055 if (!ensure_v4l2src (self)) {
3056 ret = GST_STATE_CHANGE_FAILURE;
3059 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
3061 case GST_STATE_CHANGE_READY_TO_PAUSED:
3062 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3063 if (!self->v4l2_src)
3064 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3070 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans);
3072 if (ret == GST_STATE_CHANGE_FAILURE)
3076 case GST_STATE_CHANGE_READY_TO_NULL:
3077 gst_uvc_h264_src_destroy_pipeline (self, TRUE);