1 /*
2 * GStreamer
3 *
4 * Copyright (C) 2012 Cisco Systems, Inc.
5 * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>
6 *
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.
11 *
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.
16 *
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.
21 */
22
23
24 /**
25 * SECTION:element-uvch264-src
26 * @title: uvch264-src
27 *
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
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include "gstuvch264_src.h"
37
38 #include <gst/video/video.h>
39 #include <linux/uvcvideo.h>
40 #include <linux/usb/video.h>
41 #include <sys/ioctl.h>
42 #include <string.h>
43
44 #include "gstuvch264_src.h"
45 #include <gudev/gudev.h>
46 #include <libusb.h>
47 #ifndef LIBUSB_CLASS_VIDEO
48 #define LIBUSB_CLASS_VIDEO 0x0e
49 #endif
50
51 typedef struct
52 {
53 int8_t bLength;
54 int8_t bDescriptorType;
55 int8_t bDescriptorSubType;
56 int8_t bUnitID;
57 uint8_t guidExtensionCode[16];
58 } __attribute__ ((__packed__)) xu_descriptor;
59
60 #define GUID_FORMAT "02X%02X%02X%02X-%02X%02X%02X%02X-"\
61 "%02X%02X%02X%02X-%02X%02X%02X%02X"
62 #define GUID_ARGS(guid) guid[0], guid[1], guid[2], guid[3], \
63 guid[4], guid[5], guid[6], guid[7], \
64 guid[8], guid[9], guid[10], guid[11], \
65 guid[12], guid[13], guid[14], guid[15]
66
67 #define USB_VIDEO_CONTROL 1
68 #define USB_VIDEO_CONTROL_INTERFACE 0x24
69 #define USB_VIDEO_CONTROL_XU_TYPE 0x06
70
71 enum
72 {
73 PROP_0,
74 /* uvch264_src properties */
75 PROP_COLORSPACE_NAME,
76 PROP_JPEG_DECODER_NAME,
77 PROP_NUM_CLOCK_SAMPLES,
78 /* v4l2src properties */
79 PROP_NUM_BUFFERS,
80 PROP_DEVICE,
81 PROP_DEVICE_NAME,
82 /* Static controls */
83 PROP_INITIAL_BITRATE,
84 PROP_SLICE_UNITS,
85 PROP_SLICE_MODE,
86 PROP_IFRAME_PERIOD,
87 PROP_USAGE_TYPE,
88 PROP_ENTROPY,
89 PROP_ENABLE_SEI,
90 PROP_NUM_REORDER_FRAMES,
91 PROP_PREVIEW_FLIPPED,
92 PROP_LEAKY_BUCKET_SIZE,
93 /* Dynamic controls */
94 PROP_RATE_CONTROL,
95 PROP_FIXED_FRAMERATE,
96 PROP_MAX_MBPS, /* read-only */
97 PROP_LEVEL_IDC,
98 PROP_PEAK_BITRATE,
99 PROP_AVERAGE_BITRATE,
100 PROP_MIN_IFRAME_QP,
101 PROP_MAX_IFRAME_QP,
102 PROP_MIN_PFRAME_QP,
103 PROP_MAX_PFRAME_QP,
104 PROP_MIN_BFRAME_QP,
105 PROP_MAX_BFRAME_QP,
106 PROP_LTR_BUFFER_SIZE,
107 PROP_LTR_ENCODER_CONTROL,
108 };
109 /* In caps : frame interval (fps), width, height, profile, mux */
110 /* Ignored: temporal, spatial, SNR, MVC views, version, reset */
111 /* Events: LTR, generate IDR */
112
113 enum
114 {
115 /* action signals */
116 SIGNAL_GET_ENUM_SETTING,
117 SIGNAL_GET_BOOLEAN_SETTING,
118 SIGNAL_GET_INT_SETTING,
119 LAST_SIGNAL
120 };
121
122 static guint _signals[LAST_SIGNAL];
123
124 /* Default values */
125 #define DEFAULT_COLORSPACE_NAME "videoconvert"
126 #define DEFAULT_JPEG_DECODER_NAME "jpegdec"
127 #define DEFAULT_NUM_CLOCK_SAMPLES 0
128 #define DEFAULT_NUM_BUFFERS -1
129 #define DEFAULT_DEVICE "/dev/video0"
130 #define DEFAULT_DEVICE_NAME NULL
131 #define DEFAULT_INITIAL_BITRATE 3000000
132 #define DEFAULT_SLICE_UNITS 4
133 #define DEFAULT_SLICE_MODE UVC_H264_SLICEMODE_SLICEPERFRAME
134 #define DEFAULT_IFRAME_PERIOD 10000
135 #define DEFAULT_USAGE_TYPE UVC_H264_USAGETYPE_REALTIME
136 #define DEFAULT_ENTROPY UVC_H264_ENTROPY_CAVLC
137 #define DEFAULT_ENABLE_SEI FALSE
138 #define DEFAULT_NUM_REORDER_FRAMES 0
139 #define DEFAULT_PREVIEW_FLIPPED FALSE
140 #define DEFAULT_LEAKY_BUCKET_SIZE 1000
141 #define DEFAULT_RATE_CONTROL UVC_H264_RATECONTROL_CBR
142 #define DEFAULT_FIXED_FRAMERATE FALSE
143 #define DEFAULT_LEVEL_IDC 40
144 #define DEFAULT_PEAK_BITRATE DEFAULT_INITIAL_BITRATE
145 #define DEFAULT_AVERAGE_BITRATE DEFAULT_INITIAL_BITRATE
146 #define DEFAULT_MIN_QP 10
147 #define DEFAULT_MAX_QP 46
148 #define DEFAULT_LTR_BUFFER_SIZE 0
149 #define DEFAULT_LTR_ENCODER_CONTROL 0
150
151 #define NSEC_PER_SEC (G_USEC_PER_SEC * 1000)
152
153
154 GST_DEBUG_CATEGORY (uvc_h264_src_debug);
155 #define GST_CAT_DEFAULT uvc_h264_src_debug
156
157 #define gst_uvc_h264_src_parent_class parent_class
158 G_DEFINE_TYPE (GstUvcH264Src, gst_uvc_h264_src, GST_TYPE_BASE_CAMERA_SRC);
159
160 #define GST_UVC_H264_SRC_VF_CAPS_STR \
161 GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \
162 "image/jpeg," \
163 "width = " GST_VIDEO_SIZE_RANGE "," \
164 "height = " GST_VIDEO_SIZE_RANGE "," \
165 "framerate = " GST_VIDEO_FPS_RANGE
166
167 #define GST_UVC_H264_SRC_VID_CAPS_STR \
168 GST_UVC_H264_SRC_VF_CAPS_STR ";" \
169 "video/x-h264, " \
170 "width = " GST_VIDEO_SIZE_RANGE ", " \
171 "height = " GST_VIDEO_SIZE_RANGE ", " \
172 "framerate = " GST_VIDEO_FPS_RANGE ", " \
173 "stream-format = (string) { byte-stream, avc }, " \
174 "alignment = (string) au, " \
175 "profile = (string) { high, main, baseline, constrained-baseline }"
176
177 static GstStaticPadTemplate vfsrc_template =
178 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
179 GST_PAD_SRC,
180 GST_PAD_ALWAYS,
181 GST_STATIC_CAPS (GST_UVC_H264_SRC_VF_CAPS_STR));
182
183 static GstStaticPadTemplate imgsrc_template =
184 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
185 GST_PAD_SRC,
186 GST_PAD_ALWAYS,
187 GST_STATIC_CAPS_NONE);
188
189 static GstStaticPadTemplate vidsrc_template =
190 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
191 GST_PAD_SRC,
192 GST_PAD_ALWAYS,
193 GST_STATIC_CAPS (GST_UVC_H264_SRC_VID_CAPS_STR));
194
195
196 static void gst_uvc_h264_src_dispose (GObject * object);
197 static void gst_uvc_h264_src_set_property (GObject * object,
198 guint prop_id, const GValue * value, GParamSpec * pspec);
199 static void gst_uvc_h264_src_get_property (GObject * object,
200 guint prop_id, GValue * value, GParamSpec * pspec);
201 static gboolean gst_uvc_h264_src_event (GstPad * pad, GstObject * parent,
202 GstEvent * event);
203 static gboolean gst_uvc_h264_src_send_event (GstElement * element,
204 GstEvent * event);
205 static gboolean gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc *
206 bcamsrc);
207 static gboolean gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc,
208 GstCameraBinMode mode);
209 static gboolean gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc);
210 static void gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc);
211 static GstStateChangeReturn gst_uvc_h264_src_change_state (GstElement * element,
212 GstStateChange trans);
213 static GstPadProbeReturn gst_uvc_h264_src_buffer_probe (GstPad * pad,
214 GstPadProbeInfo * info, gpointer user_data);
215 static GstPadProbeReturn gst_uvc_h264_src_event_probe (GstPad * pad,
216 GstPadProbeInfo * info, gpointer user_data);
217 static void gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
218 GstPad * peer, gpointer user_data);
219 static gboolean gst_uvc_h264_src_query (GstPad * pad, GstObject * parent,
220 GstQuery * query);
221
222
223 static void v4l2src_prepare_format (GstElement * v4l2src, gint fd,
224 GstCaps * caps, gpointer user_data);
225 static void fill_probe_commit (GstUvcH264Src * self,
226 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
227 guint32 width, guint32 height, guint32 profile,
228 UvcH264StreamFormat stream_format);
229 static gboolean xu_query (GstUvcH264Src * self, guint selector, guint query,
230 guchar * data);
231
232 static void set_rate_control (GstUvcH264Src * self);
233 static void set_level_idc (GstUvcH264Src * self);
234 static void set_bitrate (GstUvcH264Src * self);
235 static void set_qp (GstUvcH264Src * self, gint type);
236 static void set_ltr (GstUvcH264Src * self);
237 static void update_rate_control (GstUvcH264Src * self);
238 static guint32 update_level_idc_and_get_max_mbps (GstUvcH264Src * self);
239 static void update_bitrate (GstUvcH264Src * self);
240 static gboolean update_qp (GstUvcH264Src * self, gint type);
241 static void update_ltr (GstUvcH264Src * self);
242
243 static gboolean gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self,
244 gchar * property, gint * mask, gint * default_value);
245 static gboolean gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self,
246 gchar * property, gboolean * changeable, gboolean * def);
247 static gboolean gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self,
248 gchar * property, gint * min, gint * def, gint * max);
249
250 static void
gst_uvc_h264_src_class_init(GstUvcH264SrcClass * klass)251 gst_uvc_h264_src_class_init (GstUvcH264SrcClass * klass)
252 {
253 GObjectClass *gobject_class;
254 GstElementClass *gstelement_class;
255 GstBaseCameraSrcClass *gstbasecamerasrc_class;
256
257 parent_class = g_type_class_peek_parent (klass);
258
259 gobject_class = G_OBJECT_CLASS (klass);
260 gstelement_class = GST_ELEMENT_CLASS (klass);
261 gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass);
262
263 gobject_class->dispose = gst_uvc_h264_src_dispose;
264 gobject_class->set_property = gst_uvc_h264_src_set_property;
265 gobject_class->get_property = gst_uvc_h264_src_get_property;
266
267 gstelement_class->change_state = gst_uvc_h264_src_change_state;
268 gstelement_class->send_event = gst_uvc_h264_src_send_event;
269
270 gstbasecamerasrc_class->construct_pipeline =
271 gst_uvc_h264_src_construct_pipeline;
272 gstbasecamerasrc_class->set_mode = gst_uvc_h264_src_set_mode;
273 gstbasecamerasrc_class->start_capture = gst_uvc_h264_src_start_capture;
274 gstbasecamerasrc_class->stop_capture = gst_uvc_h264_src_stop_capture;
275
276 GST_DEBUG_CATEGORY_INIT (uvc_h264_src_debug, "uvch264src",
277 0, "UVC H264 Compliant camera bin source");
278
279 gst_element_class_set_static_metadata (gstelement_class,
280 "UVC H264 Source",
281 "Source/Video",
282 "UVC H264 Encoding camera source",
283 "Youness Alaoui <youness.alaoui@collabora.co.uk>");
284
285 gst_element_class_add_static_pad_template (gstelement_class,
286 &vidsrc_template);
287 gst_element_class_add_static_pad_template (gstelement_class,
288 &imgsrc_template);
289 gst_element_class_add_static_pad_template (gstelement_class, &vfsrc_template);
290
291 /* Properties */
292 g_object_class_install_property (gobject_class, PROP_COLORSPACE_NAME,
293 g_param_spec_string ("colorspace-name", "colorspace element name",
294 "The name of the colorspace element",
295 DEFAULT_COLORSPACE_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
296 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
297 g_object_class_install_property (gobject_class, PROP_JPEG_DECODER_NAME,
298 g_param_spec_string ("jpeg-decoder-name", "jpeg decoder element name",
299 "The name of the jpeg decoder element",
300 DEFAULT_JPEG_DECODER_NAME, G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
301 GST_PARAM_MUTABLE_READY | G_PARAM_STATIC_STRINGS));
302
303 g_object_class_install_property (gobject_class, PROP_NUM_CLOCK_SAMPLES,
304 g_param_spec_int ("num-clock-samples", "num-clock-samples",
305 "Number of clock samples to gather for the PTS synchronization"
306 " (-1 = unlimited)",
307 0, G_MAXINT, DEFAULT_NUM_CLOCK_SAMPLES,
308 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | GST_PARAM_MUTABLE_PLAYING |
309 G_PARAM_STATIC_STRINGS));
310
311 /* v4l2src proxied properties */
312 g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
313 g_param_spec_int ("num-buffers", "num-buffers",
314 "Number of buffers to output before sending EOS (-1 = unlimited)",
315 -1, G_MAXINT, DEFAULT_NUM_BUFFERS,
316 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317 g_object_class_install_property (gobject_class, PROP_DEVICE,
318 g_param_spec_string ("device", "device",
319 "Device location",
320 DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
321 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
322 g_param_spec_string ("device-name", "Device name",
323 "Name of the device", DEFAULT_DEVICE_NAME,
324 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
325
326 /* Static controls */
327 g_object_class_install_property (gobject_class, PROP_INITIAL_BITRATE,
328 g_param_spec_uint ("initial-bitrate", "Initial bitrate",
329 "Initial bitrate in bits/second (static control)",
330 0, G_MAXUINT, DEFAULT_INITIAL_BITRATE,
331 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
332 GST_PARAM_MUTABLE_READY));
333 g_object_class_install_property (gobject_class, PROP_SLICE_UNITS,
334 g_param_spec_uint ("slice-units", "Slice units",
335 "Slice units (static control)",
336 0, G_MAXUINT16, DEFAULT_SLICE_UNITS,
337 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
338 GST_PARAM_MUTABLE_READY));
339 g_object_class_install_property (gobject_class, PROP_SLICE_MODE,
340 g_param_spec_enum ("slice-mode", "Slice mode",
341 "Defines the unit of the slice-units property (static control)",
342 UVC_H264_SLICEMODE_TYPE,
343 DEFAULT_SLICE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
344 GST_PARAM_MUTABLE_READY));
345 g_object_class_install_property (gobject_class, PROP_IFRAME_PERIOD,
346 g_param_spec_uint ("iframe-period", "I Frame Period",
347 "Time between IDR frames in milliseconds (static control)",
348 0, G_MAXUINT16, DEFAULT_IFRAME_PERIOD,
349 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
350 GST_PARAM_MUTABLE_READY));
351 g_object_class_install_property (gobject_class, PROP_USAGE_TYPE,
352 g_param_spec_enum ("usage-type", "Usage type",
353 "The usage type (static control)",
354 UVC_H264_USAGETYPE_TYPE, DEFAULT_USAGE_TYPE,
355 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
356 GST_PARAM_MUTABLE_READY));
357 g_object_class_install_property (gobject_class, PROP_ENTROPY,
358 g_param_spec_enum ("entropy", "Entropy",
359 "Entropy (static control)",
360 UVC_H264_ENTROPY_TYPE, DEFAULT_ENTROPY,
361 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
362 GST_PARAM_MUTABLE_READY));
363 g_object_class_install_property (gobject_class, PROP_ENABLE_SEI,
364 g_param_spec_boolean ("enable-sei", "Enable SEI",
365 "Enable SEI picture timing (static control)",
366 DEFAULT_ENABLE_SEI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
367 GST_PARAM_MUTABLE_READY));
368 g_object_class_install_property (gobject_class, PROP_NUM_REORDER_FRAMES,
369 g_param_spec_uint ("num-reorder-frames", "Number of Reorder frames",
370 "Number of B frames between the references frames (static control)",
371 0, G_MAXUINT8, DEFAULT_NUM_REORDER_FRAMES,
372 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
373 GST_PARAM_MUTABLE_READY));
374 g_object_class_install_property (gobject_class, PROP_PREVIEW_FLIPPED,
375 g_param_spec_boolean ("preview-flipped", "Flip preview",
376 "Horizontal flipped image for non H.264 streams (static control)",
377 DEFAULT_PREVIEW_FLIPPED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
378 GST_PARAM_MUTABLE_READY));
379 g_object_class_install_property (gobject_class, PROP_LEAKY_BUCKET_SIZE,
380 g_param_spec_uint ("leaky-bucket-size", "Size of the leaky bucket size",
381 "Size of the leaky bucket size in milliseconds (static control)",
382 0, G_MAXUINT16, DEFAULT_LEAKY_BUCKET_SIZE,
383 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
384 GST_PARAM_MUTABLE_READY));
385
386 /* Dynamic controls */
387 g_object_class_install_property (gobject_class, PROP_RATE_CONTROL,
388 g_param_spec_enum ("rate-control", "Rate control",
389 "Rate control mode (static & dynamic control)",
390 UVC_H264_RATECONTROL_TYPE, DEFAULT_RATE_CONTROL,
391 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
392 GST_PARAM_MUTABLE_PLAYING));
393 g_object_class_install_property (gobject_class, PROP_FIXED_FRAMERATE,
394 g_param_spec_boolean ("fixed-framerate", "Fixed framerate",
395 "Fixed framerate (static & dynamic control)",
396 DEFAULT_FIXED_FRAMERATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
397 GST_PARAM_MUTABLE_PLAYING));
398 g_object_class_install_property (gobject_class, PROP_MAX_MBPS,
399 g_param_spec_uint ("max-mbps", "Max macroblocks/second",
400 "The number of macroblocks per second for the maximum processing rate",
401 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
402 g_object_class_install_property (gobject_class, PROP_LEVEL_IDC,
403 g_param_spec_uint ("level-idc", "Level IDC",
404 "Level IDC (dynamic control)",
405 0, G_MAXUINT8, DEFAULT_LEVEL_IDC,
406 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
407 GST_PARAM_MUTABLE_PLAYING));
408 g_object_class_install_property (gobject_class, PROP_PEAK_BITRATE,
409 g_param_spec_uint ("peak-bitrate", "Peak bitrate",
410 "The peak bitrate in bits/second (dynamic control)",
411 0, G_MAXUINT, DEFAULT_PEAK_BITRATE,
412 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
413 GST_PARAM_MUTABLE_PLAYING));
414 g_object_class_install_property (gobject_class, PROP_AVERAGE_BITRATE,
415 g_param_spec_uint ("average-bitrate", "Average bitrate",
416 "The average bitrate in bits/second (dynamic control)",
417 0, G_MAXUINT, DEFAULT_AVERAGE_BITRATE,
418 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
419 GST_PARAM_MUTABLE_PLAYING));
420 g_object_class_install_property (gobject_class, PROP_MIN_IFRAME_QP,
421 g_param_spec_int ("min-iframe-qp", "Minimum I frame QP",
422 "The minimum Quantization step size for I frames (dynamic control)",
423 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
424 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
425 GST_PARAM_MUTABLE_PLAYING));
426 g_object_class_install_property (gobject_class, PROP_MAX_IFRAME_QP,
427 g_param_spec_int ("max-iframe-qp", "Minimum I frame QP",
428 "The minimum Quantization step size for I frames (dynamic control)",
429 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
430 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
431 GST_PARAM_MUTABLE_PLAYING));
432 g_object_class_install_property (gobject_class, PROP_MIN_PFRAME_QP,
433 g_param_spec_int ("min-pframe-qp", "Minimum P frame QP",
434 "The minimum Quantization step size for P frames (dynamic control)",
435 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
436 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
437 GST_PARAM_MUTABLE_PLAYING));
438 g_object_class_install_property (gobject_class, PROP_MAX_PFRAME_QP,
439 g_param_spec_int ("max-pframe-qp", "Minimum P frame QP",
440 "The minimum Quantization step size for P frames (dynamic control)",
441 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
442 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
443 GST_PARAM_MUTABLE_PLAYING));
444 g_object_class_install_property (gobject_class, PROP_MIN_BFRAME_QP,
445 g_param_spec_int ("min-bframe-qp", "Minimum B frame QP",
446 "The minimum Quantization step size for B frames (dynamic control)",
447 -G_MAXINT8, G_MAXINT8, DEFAULT_MIN_QP,
448 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
449 GST_PARAM_MUTABLE_PLAYING));
450 g_object_class_install_property (gobject_class, PROP_MAX_BFRAME_QP,
451 g_param_spec_int ("max-bframe-qp", "Minimum B frame QP",
452 "The minimum Quantization step size for B frames (dynamic control)",
453 -G_MAXINT8, G_MAXINT8, DEFAULT_MAX_QP,
454 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
455 GST_PARAM_MUTABLE_PLAYING));
456 g_object_class_install_property (gobject_class, PROP_LTR_BUFFER_SIZE,
457 g_param_spec_int ("ltr-buffer-size", "LTR Buffer size",
458 "Total number of Long-Term Reference frames (dynamic control)",
459 0, G_MAXUINT8, DEFAULT_LTR_BUFFER_SIZE,
460 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
461 GST_PARAM_MUTABLE_PLAYING));
462 g_object_class_install_property (gobject_class, PROP_LTR_ENCODER_CONTROL,
463 g_param_spec_int ("ltr-encoder-control", "LTR frames controled by device",
464 "Number of LTR frames the device can control (dynamic control)",
465 0, G_MAXUINT8, DEFAULT_LTR_ENCODER_CONTROL,
466 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
467 GST_PARAM_MUTABLE_PLAYING));
468
469 _signals[SIGNAL_GET_ENUM_SETTING] =
470 g_signal_new_class_handler ("get-enum-setting",
471 G_TYPE_FROM_CLASS (klass),
472 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
473 G_CALLBACK (gst_uvc_h264_src_get_enum_setting),
474 NULL, NULL, NULL,
475 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
476 _signals[SIGNAL_GET_BOOLEAN_SETTING] =
477 g_signal_new_class_handler ("get-boolean-setting",
478 G_TYPE_FROM_CLASS (klass),
479 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
480 G_CALLBACK (gst_uvc_h264_src_get_boolean_setting), NULL, NULL, NULL,
481 G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, 0);
482 _signals[SIGNAL_GET_INT_SETTING] =
483 g_signal_new_class_handler ("get-int-setting",
484 G_TYPE_FROM_CLASS (klass),
485 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
486 G_CALLBACK (gst_uvc_h264_src_get_int_setting), NULL, NULL, NULL,
487 G_TYPE_BOOLEAN, 4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER,
488 G_TYPE_POINTER, 0);
489 }
490
491 static void
gst_uvc_h264_src_init(GstUvcH264Src * self)492 gst_uvc_h264_src_init (GstUvcH264Src * self)
493 {
494 self->vfsrc =
495 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
496 GST_PAD_SRC);
497 gst_pad_set_query_function (self->vfsrc,
498 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query));
499 gst_element_add_pad (GST_ELEMENT (self), self->vfsrc);
500
501 self->imgsrc =
502 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
503 GST_PAD_SRC);
504 gst_element_add_pad (GST_ELEMENT (self), self->imgsrc);
505
506 self->vidsrc =
507 gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
508 GST_PAD_SRC);
509 gst_pad_set_query_function (self->vidsrc,
510 GST_DEBUG_FUNCPTR (gst_uvc_h264_src_query));
511 gst_element_add_pad (GST_ELEMENT (self), self->vidsrc);
512 gst_pad_add_probe (self->vidsrc, GST_PAD_PROBE_TYPE_BUFFER,
513 gst_uvc_h264_src_buffer_probe, self, NULL);
514 gst_pad_add_probe (self->vfsrc, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
515 gst_uvc_h264_src_event_probe, self, NULL);
516 gst_pad_add_probe (self->vidsrc,
517 GST_PAD_PROBE_TYPE_EVENT_UPSTREAM | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
518 gst_uvc_h264_src_event_probe, self, NULL);
519
520 self->srcpad_event_func = GST_PAD_EVENTFUNC (self->vfsrc);
521
522 gst_pad_set_event_function (self->imgsrc, gst_uvc_h264_src_event);
523 gst_pad_set_event_function (self->vidsrc, gst_uvc_h264_src_event);
524 gst_pad_set_event_function (self->vfsrc, gst_uvc_h264_src_event);
525
526 g_signal_connect (self->vidsrc, "linked",
527 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
528 g_signal_connect (self->vidsrc, "unlinked",
529 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
530 g_signal_connect (self->vfsrc, "linked",
531 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
532 g_signal_connect (self->vfsrc, "unlinked",
533 (GCallback) gst_uvc_h264_src_pad_linking_cb, self);
534
535 self->v4l2_fd = -1;
536 gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), MODE_VIDEO);
537
538 self->main_format = UVC_H264_SRC_FORMAT_NONE;
539 self->main_width = 0;
540 self->main_height = 0;
541 self->main_frame_interval = 0;
542 self->main_stream_format = UVC_H264_STREAMFORMAT_ANNEXB;
543 self->main_profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
544 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
545 self->secondary_width = 0;
546 self->secondary_height = 0;
547 self->secondary_frame_interval = 0;
548
549 /* v4l2src properties */
550 self->num_buffers = DEFAULT_NUM_BUFFERS;
551 self->device = g_strdup (DEFAULT_DEVICE);
552
553 /* Static controls */
554 self->initial_bitrate = DEFAULT_INITIAL_BITRATE;
555 self->slice_units = DEFAULT_SLICE_UNITS;
556 self->slice_mode = DEFAULT_SLICE_MODE;
557 self->iframe_period = DEFAULT_IFRAME_PERIOD;
558 self->usage_type = DEFAULT_USAGE_TYPE;
559 self->entropy = DEFAULT_ENTROPY;
560 self->enable_sei = DEFAULT_ENABLE_SEI;
561 self->num_reorder_frames = DEFAULT_NUM_REORDER_FRAMES;
562 self->preview_flipped = DEFAULT_PREVIEW_FLIPPED;
563 self->leaky_bucket_size = DEFAULT_LEAKY_BUCKET_SIZE;
564
565 /* Dynamic controls */
566 self->rate_control = DEFAULT_RATE_CONTROL;
567 self->fixed_framerate = DEFAULT_FIXED_FRAMERATE;
568 self->level_idc = DEFAULT_LEVEL_IDC;
569 self->peak_bitrate = DEFAULT_PEAK_BITRATE;
570 self->average_bitrate = DEFAULT_AVERAGE_BITRATE;
571 self->min_qp[QP_I_FRAME] = DEFAULT_MIN_QP;
572 self->max_qp[QP_I_FRAME] = DEFAULT_MAX_QP;
573 self->min_qp[QP_P_FRAME] = DEFAULT_MIN_QP;
574 self->max_qp[QP_P_FRAME] = DEFAULT_MAX_QP;
575 self->min_qp[QP_B_FRAME] = DEFAULT_MIN_QP;
576 self->max_qp[QP_B_FRAME] = DEFAULT_MAX_QP;
577 self->ltr_buffer_size = DEFAULT_LTR_BUFFER_SIZE;
578 self->ltr_encoder_control = DEFAULT_LTR_ENCODER_CONTROL;
579 }
580
581 static void
gst_uvc_h264_src_dispose(GObject * object)582 gst_uvc_h264_src_dispose (GObject * object)
583 {
584 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
585
586 if (self->usb_ctx)
587 libusb_exit (self->usb_ctx);
588 self->usb_ctx = NULL;
589 g_free (self->jpeg_decoder_name);
590 self->jpeg_decoder_name = NULL;
591 g_free (self->colorspace_name);
592 self->colorspace_name = NULL;
593 g_free (self->device);
594 self->device = NULL;
595
596 G_OBJECT_CLASS (parent_class)->dispose (object);
597 }
598
599 static void
gst_uvc_h264_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)600 gst_uvc_h264_src_set_property (GObject * object,
601 guint prop_id, const GValue * value, GParamSpec * pspec)
602 {
603 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
604
605 switch (prop_id) {
606 case PROP_COLORSPACE_NAME:
607 g_free (self->colorspace_name);
608 self->colorspace_name = g_value_dup_string (value);
609 break;
610 case PROP_JPEG_DECODER_NAME:
611 g_free (self->jpeg_decoder_name);
612 self->jpeg_decoder_name = g_value_dup_string (value);
613 break;
614 case PROP_NUM_CLOCK_SAMPLES:
615 self->num_clock_samples = g_value_get_int (value);
616 if (self->mjpg_demux)
617 g_object_set (self->mjpg_demux,
618 "num-clock-samples", self->num_clock_samples, NULL);
619 break;
620 /* v4l2 properties */
621 case PROP_NUM_BUFFERS:
622 self->num_buffers = g_value_get_int (value);
623 if (self->v4l2_src)
624 g_object_set_property (G_OBJECT (self->v4l2_src), "num-buffers", value);
625 break;
626 case PROP_DEVICE:
627 g_free (self->device);
628 self->device = g_value_dup_string (value);
629 if (self->v4l2_src)
630 g_object_set_property (G_OBJECT (self->v4l2_src), "device", value);
631 break;
632 /* Static controls */
633 case PROP_INITIAL_BITRATE:
634 self->initial_bitrate = g_value_get_uint (value);
635 break;
636 case PROP_SLICE_UNITS:
637 self->slice_units = g_value_get_uint (value);
638 break;
639 case PROP_SLICE_MODE:
640 self->slice_mode = g_value_get_enum (value);
641 break;
642 case PROP_IFRAME_PERIOD:
643 self->iframe_period = g_value_get_uint (value);
644 break;
645 case PROP_USAGE_TYPE:
646 self->usage_type = g_value_get_enum (value);
647 break;
648 case PROP_ENTROPY:
649 self->entropy = g_value_get_enum (value);
650 break;
651 case PROP_ENABLE_SEI:
652 self->enable_sei = g_value_get_boolean (value);
653 break;
654 case PROP_NUM_REORDER_FRAMES:
655 self->num_reorder_frames = g_value_get_uint (value);
656 break;
657 case PROP_PREVIEW_FLIPPED:
658 self->preview_flipped = g_value_get_boolean (value);
659 break;
660 case PROP_LEAKY_BUCKET_SIZE:
661 self->leaky_bucket_size = g_value_get_uint (value);
662 break;
663
664
665 /* Dynamic controls */
666 case PROP_RATE_CONTROL:
667 self->rate_control = g_value_get_enum (value);
668 set_rate_control (self);
669 update_rate_control (self);
670 break;
671 case PROP_FIXED_FRAMERATE:
672 self->fixed_framerate = g_value_get_boolean (value);
673 set_rate_control (self);
674 update_rate_control (self);
675 break;
676 case PROP_LEVEL_IDC:
677 self->level_idc = g_value_get_uint (value);
678 set_level_idc (self);
679 update_level_idc_and_get_max_mbps (self);
680 break;
681 case PROP_PEAK_BITRATE:
682 self->peak_bitrate = g_value_get_uint (value);
683 set_bitrate (self);
684 update_bitrate (self);
685 break;
686 case PROP_AVERAGE_BITRATE:
687 self->average_bitrate = g_value_get_uint (value);
688 set_bitrate (self);
689 update_bitrate (self);
690 break;
691 case PROP_MIN_IFRAME_QP:
692 self->min_qp[QP_I_FRAME] = g_value_get_int (value);
693 set_qp (self, QP_I_FRAME);
694 update_qp (self, QP_I_FRAME);
695 break;
696 case PROP_MAX_IFRAME_QP:
697 self->max_qp[QP_I_FRAME] = g_value_get_int (value);
698 set_qp (self, QP_I_FRAME);
699 update_qp (self, QP_I_FRAME);
700 break;
701 case PROP_MIN_PFRAME_QP:
702 self->min_qp[QP_P_FRAME] = g_value_get_int (value);
703 set_qp (self, QP_P_FRAME);
704 update_qp (self, QP_P_FRAME);
705 break;
706 case PROP_MAX_PFRAME_QP:
707 self->max_qp[QP_P_FRAME] = g_value_get_int (value);
708 set_qp (self, QP_P_FRAME);
709 update_qp (self, QP_P_FRAME);
710 break;
711 case PROP_MIN_BFRAME_QP:
712 self->min_qp[QP_B_FRAME] = g_value_get_int (value);
713 set_qp (self, QP_B_FRAME);
714 update_qp (self, QP_B_FRAME);
715 break;
716 case PROP_MAX_BFRAME_QP:
717 self->max_qp[QP_B_FRAME] = g_value_get_int (value);
718 set_qp (self, QP_B_FRAME);
719 update_qp (self, QP_B_FRAME);
720 break;
721 case PROP_LTR_BUFFER_SIZE:
722 self->ltr_buffer_size = g_value_get_int (value);
723 set_ltr (self);
724 update_ltr (self);
725 break;
726 case PROP_LTR_ENCODER_CONTROL:
727 self->ltr_encoder_control = g_value_get_int (value);
728 set_ltr (self);
729 update_ltr (self);
730 break;
731 default:
732 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
733 break;
734 }
735 }
736
737 static void
gst_uvc_h264_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)738 gst_uvc_h264_src_get_property (GObject * object,
739 guint prop_id, GValue * value, GParamSpec * pspec)
740 {
741 GstUvcH264Src *self = GST_UVC_H264_SRC (object);
742 uvcx_video_config_probe_commit_t probe;
743
744 switch (prop_id) {
745 case PROP_INITIAL_BITRATE:
746 case PROP_SLICE_UNITS:
747 case PROP_SLICE_MODE:
748 case PROP_IFRAME_PERIOD:
749 case PROP_USAGE_TYPE:
750 case PROP_ENTROPY:
751 case PROP_ENABLE_SEI:
752 case PROP_NUM_REORDER_FRAMES:
753 case PROP_PREVIEW_FLIPPED:
754 case PROP_LEAKY_BUCKET_SIZE:
755 fill_probe_commit (self, &probe, 0, 0, 0, 0, 0);
756 if (GST_STATE (self) >= GST_STATE_PAUSED) {
757 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
758 (guchar *) & probe))
759 GST_WARNING_OBJECT (self, "probe_setting GET_CUR error");
760 }
761 break;
762 default:
763 break;
764 }
765
766 switch (prop_id) {
767 case PROP_COLORSPACE_NAME:
768 g_value_set_string (value, self->colorspace_name);
769 break;
770 case PROP_JPEG_DECODER_NAME:
771 g_value_set_string (value, self->jpeg_decoder_name);
772 break;
773 case PROP_NUM_CLOCK_SAMPLES:
774 g_value_set_int (value, self->num_clock_samples);
775 break;
776 /* v4l2src properties */
777 case PROP_NUM_BUFFERS:
778 g_value_set_int (value, self->num_buffers);
779 break;
780 case PROP_DEVICE:
781 g_value_set_string (value, self->device);
782 break;
783 case PROP_DEVICE_NAME:
784 if (self->v4l2_src)
785 g_object_get_property (G_OBJECT (self->v4l2_src), "device-name", value);
786 else
787 g_value_set_static_string (value, "");
788 break;
789 /* Static controls */
790 case PROP_INITIAL_BITRATE:
791 g_value_set_uint (value, probe.dwBitRate);
792 break;
793 case PROP_SLICE_UNITS:
794 g_value_set_uint (value, probe.wSliceUnits);
795 break;
796 case PROP_SLICE_MODE:
797 g_value_set_enum (value, probe.wSliceMode);
798 break;
799 case PROP_IFRAME_PERIOD:
800 g_value_set_uint (value, probe.wIFramePeriod);
801 break;
802 case PROP_USAGE_TYPE:
803 g_value_set_enum (value, probe.bUsageType);
804 break;
805 case PROP_ENTROPY:
806 g_value_set_enum (value, probe.bEntropyCABAC);
807 break;
808 case PROP_ENABLE_SEI:
809 g_value_set_boolean (value,
810 (probe.bTimestamp == UVC_H264_TIMESTAMP_SEI_ENABLE));
811 break;
812 case PROP_NUM_REORDER_FRAMES:
813 g_value_set_uint (value, probe.bNumOfReorderFrames);
814 break;
815 case PROP_PREVIEW_FLIPPED:
816 g_value_set_boolean (value,
817 (probe.bPreviewFlipped == UVC_H264_PREFLIPPED_HORIZONTAL));
818 break;
819 case PROP_LEAKY_BUCKET_SIZE:
820 g_value_set_uint (value, probe.wLeakyBucketSize);
821 break;
822
823 /* Dynamic controls */
824 case PROP_RATE_CONTROL:
825 update_rate_control (self);
826 g_value_set_enum (value, self->rate_control);
827 break;
828 case PROP_FIXED_FRAMERATE:
829 update_rate_control (self);
830 g_value_set_boolean (value, self->fixed_framerate);
831 break;
832 case PROP_MAX_MBPS:
833 g_value_set_uint (value, update_level_idc_and_get_max_mbps (self));
834 break;
835 case PROP_LEVEL_IDC:
836 update_level_idc_and_get_max_mbps (self);
837 g_value_set_uint (value, self->level_idc);
838 break;
839 case PROP_PEAK_BITRATE:
840 update_bitrate (self);
841 g_value_set_uint (value, self->peak_bitrate);
842 break;
843 case PROP_AVERAGE_BITRATE:
844 update_bitrate (self);
845 g_value_set_uint (value, self->average_bitrate);
846 break;
847 case PROP_MIN_IFRAME_QP:
848 update_qp (self, QP_I_FRAME);
849 g_value_set_int (value, self->min_qp[QP_I_FRAME]);
850 break;
851 case PROP_MAX_IFRAME_QP:
852 update_qp (self, QP_I_FRAME);
853 g_value_set_int (value, self->max_qp[QP_I_FRAME]);
854 break;
855 case PROP_MIN_PFRAME_QP:
856 update_qp (self, QP_P_FRAME);
857 g_value_set_int (value, self->min_qp[QP_P_FRAME]);
858 break;
859 case PROP_MAX_PFRAME_QP:
860 update_qp (self, QP_P_FRAME);
861 g_value_set_int (value, self->max_qp[QP_P_FRAME]);
862 break;
863 case PROP_MIN_BFRAME_QP:
864 update_qp (self, QP_B_FRAME);
865 g_value_set_int (value, self->min_qp[QP_B_FRAME]);
866 break;
867 case PROP_MAX_BFRAME_QP:
868 update_qp (self, QP_B_FRAME);
869 g_value_set_int (value, self->max_qp[QP_B_FRAME]);
870 break;
871 case PROP_LTR_BUFFER_SIZE:
872 update_ltr (self);
873 g_value_set_int (value, self->ltr_buffer_size);
874 break;
875 case PROP_LTR_ENCODER_CONTROL:
876 update_ltr (self);
877 g_value_set_int (value, self->ltr_encoder_control);
878 break;
879 default:
880 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
881 break;
882 }
883 }
884
885 /* Set dynamic controls */
886 static void
set_rate_control(GstUvcH264Src * self)887 set_rate_control (GstUvcH264Src * self)
888 {
889 uvcx_rate_control_mode_t req;
890
891 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
892 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
893 return;
894 }
895
896 req.bRateControlMode = self->rate_control;
897 if (self->fixed_framerate)
898 req.bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
899
900 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR, (guchar *) & req)) {
901 GST_WARNING_OBJECT (self, " RATE_CONTROL SET_CUR error");
902 return;
903 }
904 }
905
906 static void
set_level_idc(GstUvcH264Src * self)907 set_level_idc (GstUvcH264Src * self)
908 {
909 uvcx_video_advance_config_t req;
910
911 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
912 (guchar *) & req)) {
913 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
914 return;
915 }
916
917 req.blevel_idc = self->level_idc;
918 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_SET_CUR,
919 (guchar *) & req)) {
920 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG SET_CUR error");
921 return;
922 }
923 }
924
925 static void
set_bitrate(GstUvcH264Src * self)926 set_bitrate (GstUvcH264Src * self)
927 {
928 uvcx_bitrate_layers_t req;
929
930 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
931 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
932 return;
933 }
934
935 req.dwPeakBitrate = self->peak_bitrate;
936 req.dwAverageBitrate = self->average_bitrate;
937 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
938 GST_WARNING_OBJECT (self, " BITRATE_LAYERS SET_CUR error");
939 return;
940 }
941 }
942
943 static void
set_qp(GstUvcH264Src * self,gint type)944 set_qp (GstUvcH264Src * self, gint type)
945 {
946 uvcx_qp_steps_layers_t req;
947
948 req.wLayerID = 0;
949 switch (type) {
950 case QP_I_FRAME:
951 req.bFrameType = UVC_H264_QP_STEPS_I_FRAME_TYPE;
952 break;
953 case QP_P_FRAME:
954 req.bFrameType = UVC_H264_QP_STEPS_P_FRAME_TYPE;
955 break;
956 case QP_B_FRAME:
957 req.bFrameType = UVC_H264_QP_STEPS_B_FRAME_TYPE;
958 break;
959 default:
960 return;
961 }
962 req.bMinQp = 0;
963 req.bMaxQp = 0;
964 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
965 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
966 return;
967 }
968
969 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
970 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
971 return;
972 }
973
974 req.bMinQp = self->min_qp[type];
975 req.bMaxQp = self->max_qp[type];
976 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
977 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
978 return;
979 }
980 }
981
982 static void
set_ltr(GstUvcH264Src * self)983 set_ltr (GstUvcH264Src * self)
984 {
985 uvcx_ltr_buffer_size_control_t req;
986
987 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
988 (guchar *) & req)) {
989 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
990 return;
991 }
992
993 req.bLTRBufferSize = self->ltr_buffer_size;
994 req.bLTREncoderControl = self->ltr_encoder_control;
995 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_SET_CUR,
996 (guchar *) & req)) {
997 GST_WARNING_OBJECT (self, "LTR_BUFFER_SIZE SET_CUR error");
998 return;
999 }
1000 }
1001
1002 /* Get Dynamic controls */
1003
1004 static void
update_rate_control(GstUvcH264Src * self)1005 update_rate_control (GstUvcH264Src * self)
1006 {
1007 uvcx_rate_control_mode_t req;
1008
1009 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR, (guchar *) & req)) {
1010 GST_WARNING_OBJECT (self, " RATE_CONTROL GET_CUR error");
1011 return;
1012 }
1013
1014 if (self->rate_control != (req.bRateControlMode &
1015 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG)) {
1016 self->rate_control = (req.bRateControlMode &
1017 ~UVC_H264_RATECONTROL_FIXED_FRM_FLG);
1018 g_object_notify (G_OBJECT (self), "rate-control");
1019 }
1020 if (self->fixed_framerate != ((req.bRateControlMode &
1021 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0)) {
1022 self->fixed_framerate = ((req.bRateControlMode &
1023 UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1024 g_object_notify (G_OBJECT (self), "fixed-framerate");
1025 }
1026 }
1027
1028
1029 static guint32
update_level_idc_and_get_max_mbps(GstUvcH264Src * self)1030 update_level_idc_and_get_max_mbps (GstUvcH264Src * self)
1031 {
1032 uvcx_video_advance_config_t req;
1033
1034 if (!xu_query (self, UVCX_VIDEO_ADVANCE_CONFIG, UVC_GET_CUR,
1035 (guchar *) & req)) {
1036 GST_WARNING_OBJECT (self, " VIDEO_ADVANCE_CONFIG GET_CUR error");
1037 return 0;
1038 }
1039
1040 if (self->level_idc != req.blevel_idc) {
1041 self->level_idc = req.blevel_idc;
1042 g_object_notify (G_OBJECT (self), "level-idc");
1043 }
1044 return req.dwMb_max;
1045 }
1046
1047 static void
update_bitrate(GstUvcH264Src * self)1048 update_bitrate (GstUvcH264Src * self)
1049 {
1050 uvcx_bitrate_layers_t req;
1051
1052 if (!xu_query (self, UVCX_BITRATE_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1053 GST_WARNING_OBJECT (self, " BITRATE_LAYERS GET_CUR error");
1054 return;
1055 }
1056 if (self->peak_bitrate != req.dwPeakBitrate) {
1057 self->peak_bitrate = req.dwPeakBitrate;
1058 g_object_notify (G_OBJECT (self), "peak-bitrate");
1059 }
1060 if (self->average_bitrate != req.dwAverageBitrate) {
1061 self->average_bitrate = req.dwAverageBitrate;
1062 g_object_notify (G_OBJECT (self), "average-bitrate");
1063 }
1064 }
1065
1066 static gboolean
update_qp(GstUvcH264Src * self,gint type)1067 update_qp (GstUvcH264Src * self, gint type)
1068 {
1069 uvcx_qp_steps_layers_t req;
1070 guint8 frame_type;
1071
1072 req.wLayerID = 0;
1073 switch (type) {
1074 case QP_I_FRAME:
1075 frame_type = UVC_H264_QP_STEPS_I_FRAME_TYPE;
1076 break;
1077 case QP_P_FRAME:
1078 frame_type = UVC_H264_QP_STEPS_P_FRAME_TYPE;
1079 break;
1080 case QP_B_FRAME:
1081 frame_type = UVC_H264_QP_STEPS_B_FRAME_TYPE;
1082 break;
1083 default:
1084 return FALSE;
1085 }
1086 req.bFrameType = frame_type;
1087 req.bMinQp = 0;
1088 req.bMaxQp = 0;
1089 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_SET_CUR, (guchar *) & req)) {
1090 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS SET_CUR error");
1091 return FALSE;
1092 }
1093
1094 if (!xu_query (self, UVCX_QP_STEPS_LAYERS, UVC_GET_CUR, (guchar *) & req)) {
1095 GST_WARNING_OBJECT (self, " QP_STEPS_LAYERS GET_CUR error");
1096 return FALSE;
1097 }
1098
1099 if (req.bFrameType == frame_type) {
1100 if (self->min_qp[type] != req.bMinQp) {
1101 self->min_qp[type] = req.bMinQp;
1102 switch (type) {
1103 case QP_I_FRAME:
1104 g_object_notify (G_OBJECT (self), "min-iframe-qp");
1105 break;
1106 case QP_P_FRAME:
1107 g_object_notify (G_OBJECT (self), "min-pframe-qp");
1108 break;
1109 case QP_B_FRAME:
1110 g_object_notify (G_OBJECT (self), "min-bframe-qp");
1111 break;
1112 default:
1113 break;
1114 }
1115 }
1116 if (self->max_qp[type] != req.bMaxQp) {
1117 self->max_qp[type] = req.bMaxQp;
1118 switch (type) {
1119 case QP_I_FRAME:
1120 g_object_notify (G_OBJECT (self), "max-iframe-qp");
1121 break;
1122 case QP_P_FRAME:
1123 g_object_notify (G_OBJECT (self), "max-pframe-qp");
1124 break;
1125 case QP_B_FRAME:
1126 g_object_notify (G_OBJECT (self), "max-bframe-qp");
1127 break;
1128 default:
1129 break;
1130 }
1131 }
1132 return TRUE;
1133 } else {
1134 self->min_qp[type] = 0xFF;
1135 self->max_qp[type] = 0xFF;
1136 return FALSE;
1137 }
1138 }
1139
1140 static void
update_ltr(GstUvcH264Src * self)1141 update_ltr (GstUvcH264Src * self)
1142 {
1143 uvcx_ltr_buffer_size_control_t req;
1144
1145 if (!xu_query (self, UVCX_LTR_BUFFER_SIZE_CONTROL, UVC_GET_CUR,
1146 (guchar *) & req)) {
1147 GST_WARNING_OBJECT (self, " LTR_BUFFER_SIZE GET_CUR error");
1148 return;
1149 }
1150
1151 if (self->ltr_buffer_size != req.bLTRBufferSize) {
1152 self->ltr_buffer_size = req.bLTRBufferSize;
1153 g_object_notify (G_OBJECT (self), "ltr-buffer-size");
1154 }
1155 if (self->ltr_encoder_control != req.bLTREncoderControl) {
1156 self->ltr_encoder_control = req.bLTREncoderControl;
1157 g_object_notify (G_OBJECT (self), "ltr-encoder-control");
1158 }
1159 }
1160
1161 #define STORE_MIN_DEF_MAX(type) \
1162 *(type *)min = *((type *) (min_p + offset)); \
1163 *(type *)def = *((type *) (def_p + offset)); \
1164 *(type *)max = *((type *) (max_p + offset));
1165
1166 static gboolean
probe_setting(GstUvcH264Src * self,uvcx_control_selector_t selector,guint offset,gint size,gpointer min,gpointer def,gpointer max)1167 probe_setting (GstUvcH264Src * self, uvcx_control_selector_t selector,
1168 guint offset, gint size, gpointer min, gpointer def, gpointer max)
1169 {
1170 guchar *min_p, *def_p, *max_p;
1171 gboolean ret = FALSE;
1172 __u16 len;
1173
1174 if (!xu_query (self, selector, UVC_GET_LEN, (guchar *) & len)) {
1175 GST_WARNING_OBJECT (self, "probe_setting GET_LEN error");
1176 return FALSE;
1177 }
1178 min_p = g_malloc0 (len);
1179 def_p = g_malloc0 (len);
1180 max_p = g_malloc0 (len);
1181
1182 if (!xu_query (self, selector, UVC_GET_MIN, min_p)) {
1183 GST_WARNING_OBJECT (self, "probe_setting GET_MIN error");
1184 goto end;
1185 }
1186 if (!xu_query (self, selector, UVC_GET_DEF, def_p)) {
1187 GST_WARNING_OBJECT (self, "probe_setting GET_DEF error");
1188 goto end;
1189 }
1190 if (!xu_query (self, selector, UVC_GET_MAX, max_p)) {
1191 GST_WARNING_OBJECT (self, "probe_setting GET_MAX error");
1192 goto end;
1193 }
1194
1195 switch (size) {
1196 case -1:
1197 STORE_MIN_DEF_MAX (gint8);
1198 ret = TRUE;
1199 break;
1200 case 1:
1201 STORE_MIN_DEF_MAX (guint8);
1202 ret = TRUE;
1203 break;
1204 case -2:
1205 STORE_MIN_DEF_MAX (gint16);
1206 ret = TRUE;
1207 break;
1208 case 2:
1209 STORE_MIN_DEF_MAX (guint16);
1210 ret = TRUE;
1211 break;
1212 case -4:
1213 STORE_MIN_DEF_MAX (gint32);
1214 ret = TRUE;
1215 break;
1216 case 4:
1217 STORE_MIN_DEF_MAX (guint32);
1218 ret = TRUE;
1219 break;
1220 default:
1221 break;
1222 }
1223
1224 end:
1225 g_free (min_p);
1226 g_free (def_p);
1227 g_free (max_p);
1228
1229 return ret;
1230 }
1231
1232 static gboolean
test_enum_setting(GstUvcH264Src * self,guint offset,guint size,guint16 value)1233 test_enum_setting (GstUvcH264Src * self, guint offset, guint size,
1234 guint16 value)
1235 {
1236 uvcx_video_config_probe_commit_t cur;
1237 uvcx_video_config_probe_commit_t req;
1238 guchar *req_p = (guchar *) & req;
1239
1240 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, (guchar *) & cur)) {
1241 GST_WARNING_OBJECT (self, " GET_CUR error");
1242 return FALSE;
1243 }
1244
1245 req = cur;
1246
1247 if (size == 1)
1248 *((guint8 *) (req_p + offset)) = (guint8) value;
1249 else
1250 *((guint16 *) (req_p + offset)) = value;
1251
1252 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, req_p)) {
1253 GST_WARNING_OBJECT (self, " SET_CUR error");
1254 return FALSE;
1255 }
1256
1257 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR, req_p)) {
1258 GST_WARNING_OBJECT (self, " GET_CUR error");
1259 return FALSE;
1260 }
1261
1262 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR, (guchar *) & cur)) {
1263 GST_WARNING_OBJECT (self, " SET_CUR error");
1264 return FALSE;
1265 }
1266
1267 if (size == 1)
1268 return *((guint8 *) (req_p + offset)) == (guint8) value;
1269 else
1270 return *((guint16 *) (req_p + offset)) == value;
1271 }
1272
1273 static gboolean
gst_uvc_h264_src_get_enum_setting(GstUvcH264Src * self,gchar * property,gint * mask,gint * default_value)1274 gst_uvc_h264_src_get_enum_setting (GstUvcH264Src * self, gchar * property,
1275 gint * mask, gint * default_value)
1276 {
1277 guint8 min, def, max;
1278 guint8 en;
1279 gboolean ret = FALSE;
1280
1281 if (g_strcmp0 (property, "slice-mode") == 0) {
1282 guint16 min16, def16, max16;
1283 guint16 en16;
1284
1285 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1286 offsetof (uvcx_video_config_probe_commit_t, wSliceMode), 2,
1287 &min16, &def16, &max16);
1288 if (ret) {
1289 *default_value = def16;
1290 *mask = 0;
1291 for (en16 = min16; en16 <= max16; en16++) {
1292 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1293 wSliceMode), 2, en16))
1294 *mask |= (1 << en16);
1295 }
1296 }
1297 } else if (g_strcmp0 (property, "usage-type") == 0) {
1298 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1299 offsetof (uvcx_video_config_probe_commit_t, bUsageType), 1,
1300 &min, &def, &max);
1301 if (ret) {
1302 *default_value = def;
1303 *mask = 0;
1304 for (en = min; en <= max; en++) {
1305 if (test_enum_setting (self, offsetof (uvcx_video_config_probe_commit_t,
1306 bUsageType), 1, en))
1307 *mask |= (1 << en);
1308 }
1309 }
1310 } else if (g_strcmp0 (property, "entropy") == 0) {
1311 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1312 offsetof (uvcx_video_config_probe_commit_t, bEntropyCABAC), 1,
1313 &min, &def, &max);
1314 if (ret) {
1315 *mask = (1 << min) | (1 << max);
1316 *default_value = def;
1317 }
1318 } else if (g_strcmp0 (property, "rate-control") == 0) {
1319 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1320 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode), 1,
1321 &min, &def, &max);
1322 if (ret) {
1323 uvcx_rate_control_mode_t cur;
1324
1325 *default_value = def;
1326 *mask = 0;
1327
1328 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR,
1329 (guchar *) & cur)) {
1330 GST_WARNING_OBJECT (self, " CONTROL_MODE GET_CUR error");
1331 return FALSE;
1332 }
1333
1334 for (en = min; en <= max; en++) {
1335 uvcx_rate_control_mode_t req = { 0, en };
1336
1337 if (xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR,
1338 (guchar *) & req) &&
1339 xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_GET_CUR,
1340 (guchar *) & req) && req.bRateControlMode == en)
1341 *mask |= (1 << en);
1342 }
1343 if (!xu_query (self, UVCX_RATE_CONTROL_MODE, UVC_SET_CUR,
1344 (guchar *) & cur)) {
1345 GST_WARNING_OBJECT (self, " CONTROL_MODE SET_CUR error");
1346 return FALSE;
1347 }
1348 }
1349 }
1350
1351 return ret;
1352 }
1353
1354 static gboolean
gst_uvc_h264_src_get_boolean_setting(GstUvcH264Src * self,gchar * property,gboolean * changeable,gboolean * default_value)1355 gst_uvc_h264_src_get_boolean_setting (GstUvcH264Src * self, gchar * property,
1356 gboolean * changeable, gboolean * default_value)
1357 {
1358 guint8 min, def, max;
1359 gboolean ret = FALSE;
1360
1361 if (g_strcmp0 (property, "enable-sei") == 0) {
1362 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1363 offsetof (uvcx_video_config_probe_commit_t, bTimestamp), 1,
1364 &min, &def, &max))) {
1365 *changeable = (min != max);
1366 *default_value = (def != 0);
1367 }
1368 } else if (g_strcmp0 (property, "preview-flipped") == 0) {
1369 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1370 offsetof (uvcx_video_config_probe_commit_t, bPreviewFlipped), 1,
1371 &min, &def, &max))) {
1372 *changeable = (min != max);
1373 *default_value = (def != 0);
1374 }
1375 } else if (g_strcmp0 (property, "fixed-framerate") == 0) {
1376 if ((ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1377 offsetof (uvcx_video_config_probe_commit_t, bRateControlMode),
1378 1, &min, &def, &max))) {
1379 *changeable = ((max & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1380 *default_value = ((def & UVC_H264_RATECONTROL_FIXED_FRM_FLG) != 0);
1381 }
1382 }
1383
1384 return ret;
1385 }
1386
1387 static gboolean
gst_uvc_h264_src_get_int_setting(GstUvcH264Src * self,gchar * property,gint * min,gint * def,gint * max)1388 gst_uvc_h264_src_get_int_setting (GstUvcH264Src * self, gchar * property,
1389 gint * min, gint * def, gint * max)
1390 {
1391 guint32 min32, def32, max32;
1392 guint16 min16, def16, max16;
1393 guint8 min8, def8, max8;
1394 gint8 smin8, sdef8, smax8;
1395 gboolean ret = FALSE;
1396
1397 GST_DEBUG_OBJECT (self, "Probing int property %s", property);
1398 if (g_strcmp0 (property, "initial-bitrate") == 0) {
1399 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1400 offsetof (uvcx_video_config_probe_commit_t, dwBitRate), 4,
1401 &min32, &def32, &max32);
1402 if (ret) {
1403 *min = min32;
1404 *def = def32;
1405 *max = max32;
1406 }
1407 } else if (g_strcmp0 (property, "slice-units") == 0) {
1408 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1409 offsetof (uvcx_video_config_probe_commit_t, wSliceUnits), 2,
1410 &min16, &def16, &max16);
1411 if (ret) {
1412 *min = min16;
1413 *def = def16;
1414 *max = max16;
1415 }
1416 } else if (g_strcmp0 (property, "iframe-period") == 0) {
1417 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1418 offsetof (uvcx_video_config_probe_commit_t, wIFramePeriod), 2,
1419 &min16, &def16, &max16);
1420 if (ret) {
1421 *min = min16;
1422 *def = def16;
1423 *max = max16;
1424 }
1425 } else if (g_strcmp0 (property, "num-reorder-frames") == 0) {
1426 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1427 offsetof (uvcx_video_config_probe_commit_t, bNumOfReorderFrames), 1,
1428 &min8, &def8, &max8);
1429 if (ret) {
1430 *min = min8;
1431 *def = def8;
1432 *max = max8;
1433 }
1434 } else if (g_strcmp0 (property, "leaky-bucket-size") == 0) {
1435 ret = probe_setting (self, UVCX_VIDEO_CONFIG_PROBE,
1436 offsetof (uvcx_video_config_probe_commit_t, wLeakyBucketSize), 2,
1437 &min16, &def16, &max16);
1438 if (ret) {
1439 *min = min16;
1440 *def = def16;
1441 *max = max16;
1442 }
1443 } else if (g_strcmp0 (property, "level-idc") == 0) {
1444 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1445 offsetof (uvcx_video_advance_config_t, blevel_idc), 1,
1446 &min8, &def8, &max8);
1447 if (ret) {
1448 *min = min8;
1449 *def = def8;
1450 *max = max8;
1451 }
1452 } else if (g_strcmp0 (property, "max-mbps") == 0) {
1453 ret = probe_setting (self, UVCX_VIDEO_ADVANCE_CONFIG,
1454 offsetof (uvcx_video_advance_config_t, dwMb_max), 4,
1455 &min32, &def32, &max32);
1456 if (ret) {
1457 *min = min32;
1458 *def = def32;
1459 *max = max32;
1460 }
1461 } else if (g_strcmp0 (property, "peak-bitrate") == 0) {
1462 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1463 offsetof (uvcx_bitrate_layers_t, dwPeakBitrate), 4,
1464 &min32, &def32, &max32);
1465 if (ret) {
1466 *min = min32;
1467 *def = def32;
1468 *max = max32;
1469 }
1470 } else if (g_strcmp0 (property, "average-bitrate") == 0) {
1471 ret = probe_setting (self, UVCX_BITRATE_LAYERS,
1472 offsetof (uvcx_bitrate_layers_t, dwAverageBitrate), 4,
1473 &min32, &def32, &max32);
1474 if (ret) {
1475 *min = min32;
1476 *def = def32;
1477 *max = max32;
1478 }
1479 } else if (g_strcmp0 (property, "min-iframe-qp") == 0) {
1480 if (update_qp (self, QP_I_FRAME))
1481 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1482 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1483 if (ret) {
1484 *min = smin8;
1485 *def = sdef8;
1486 *max = smax8;
1487 }
1488 } else if (g_strcmp0 (property, "max-iframe-qp") == 0) {
1489 if (update_qp (self, QP_I_FRAME))
1490 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1491 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1492 if (ret) {
1493 *min = smin8;
1494 *def = sdef8;
1495 *max = smax8;
1496 }
1497 } else if (g_strcmp0 (property, "min-pframe-qp") == 0) {
1498 if (update_qp (self, QP_P_FRAME))
1499 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1500 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1501 if (ret) {
1502 *min = smin8;
1503 *def = sdef8;
1504 *max = smax8;
1505 }
1506 } else if (g_strcmp0 (property, "max-pframe-qp") == 0) {
1507 if (update_qp (self, QP_P_FRAME))
1508 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1509 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1510 if (ret) {
1511 *min = smin8;
1512 *def = sdef8;
1513 *max = smax8;
1514 }
1515 } else if (g_strcmp0 (property, "min-bframe-qp") == 0) {
1516 if (update_qp (self, QP_B_FRAME))
1517 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1518 offsetof (uvcx_qp_steps_layers_t, bMinQp), 1, &smin8, &sdef8, &smax8);
1519 if (ret) {
1520 *min = smin8;
1521 *def = sdef8;
1522 *max = smax8;
1523 }
1524 } else if (g_strcmp0 (property, "max-bframe-qp") == 0) {
1525 if (update_qp (self, QP_B_FRAME))
1526 ret = probe_setting (self, UVCX_QP_STEPS_LAYERS,
1527 offsetof (uvcx_qp_steps_layers_t, bMaxQp), 1, &smin8, &sdef8, &smax8);
1528 if (ret) {
1529 *min = smin8;
1530 *def = sdef8;
1531 *max = smax8;
1532 }
1533 } else if (g_strcmp0 (property, "ltr-buffer-size") == 0) {
1534 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1535 offsetof (uvcx_ltr_buffer_size_control_t, bLTRBufferSize), 1,
1536 &min8, &def8, &max8);
1537 if (ret) {
1538 *min = min8;
1539 *def = def8;
1540 *max = max8;
1541 }
1542 } else if (g_strcmp0 (property, "ltr-encoder-control") == 0) {
1543 ret = probe_setting (self, UVCX_LTR_BUFFER_SIZE_CONTROL,
1544 offsetof (uvcx_ltr_buffer_size_control_t, bLTREncoderControl), 1,
1545 &min8, &def8, &max8);
1546 if (ret) {
1547 *min = min8;
1548 *def = def8;
1549 *max = max8;
1550 }
1551 } else {
1552 g_return_val_if_reached (FALSE);
1553 }
1554
1555 return ret;
1556 }
1557
1558 static GstPadProbeReturn
gst_uvc_h264_src_event_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)1559 gst_uvc_h264_src_event_probe (GstPad * pad, GstPadProbeInfo * info,
1560 gpointer user_data)
1561 {
1562 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1563 GstPadProbeReturn ret = GST_PAD_PROBE_OK;
1564 GstEvent *event = info->data;
1565
1566 switch (GST_EVENT_TYPE (event)) {
1567 case GST_EVENT_SEGMENT:
1568 if (pad == self->vidsrc) {
1569 const GstSegment *s;
1570
1571 gst_event_parse_segment (event, &s);
1572 gst_segment_copy_into (s, &self->segment);
1573 }
1574 break;
1575 case GST_EVENT_EOS:
1576 ret = self->reconfiguring ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK;
1577 break;
1578 default:
1579 break;
1580 }
1581
1582 return ret;
1583 }
1584
1585 static GstPadProbeReturn
gst_uvc_h264_src_buffer_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)1586 gst_uvc_h264_src_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
1587 gpointer user_data)
1588 {
1589 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
1590 GstBuffer *buffer = info->data;
1591
1592 /* TODO: Check the NALU type and make sure it is a keyframe */
1593 if (self->key_unit_event) {
1594 GstClockTime ts, running_time, stream_time;
1595 gboolean all_headers;
1596 guint count;
1597 GstEvent *downstream;
1598
1599 if (gst_video_event_parse_upstream_force_key_unit (self->key_unit_event,
1600 &ts, &all_headers, &count)) {
1601 if (!GST_CLOCK_TIME_IS_VALID (ts)) {
1602 ts = GST_BUFFER_TIMESTAMP (buffer);
1603 }
1604 running_time = gst_segment_to_running_time (&self->segment,
1605 GST_FORMAT_TIME, ts);
1606
1607 stream_time = gst_segment_to_stream_time (&self->segment,
1608 GST_FORMAT_TIME, ts);
1609
1610 GST_DEBUG_OBJECT (self, "Sending downstream force-key-unit : %d - %d ts=%"
1611 GST_TIME_FORMAT " running time =%" GST_TIME_FORMAT " stream=%"
1612 GST_TIME_FORMAT, all_headers, count, GST_TIME_ARGS (ts),
1613 GST_TIME_ARGS (running_time), GST_TIME_ARGS (stream_time));
1614 downstream = gst_video_event_new_downstream_force_key_unit (ts,
1615 stream_time, running_time, all_headers, count);
1616 gst_pad_push_event (self->vidsrc, downstream);
1617 gst_event_replace (&self->key_unit_event, NULL);
1618 }
1619 }
1620 return TRUE;
1621 }
1622
1623 static gboolean
gst_uvc_h264_src_parse_event(GstUvcH264Src * self,GstPad * pad,GstEvent * event)1624 gst_uvc_h264_src_parse_event (GstUvcH264Src * self, GstPad * pad,
1625 GstEvent * event)
1626 {
1627 const GstStructure *s = gst_event_get_structure (event);
1628
1629 switch (GST_EVENT_TYPE (event)) {
1630 case GST_EVENT_CUSTOM_UPSTREAM:
1631 if (pad == self->vidsrc && self->main_format == UVC_H264_SRC_FORMAT_H264) {
1632 if (gst_video_event_is_force_key_unit (event)) {
1633 uvcx_picture_type_control_t req = { 0, 0 };
1634 GstClockTime ts;
1635 gboolean all_headers;
1636
1637 if (gst_video_event_parse_upstream_force_key_unit (event,
1638 &ts, &all_headers, NULL)) {
1639 GST_INFO_OBJECT (self, "Received upstream force-key-unit : %d %"
1640 GST_TIME_FORMAT, all_headers, GST_TIME_ARGS (ts));
1641 /* TODO: wait until 'ts' time is reached */
1642 if (all_headers)
1643 req.wPicType = UVC_H264_PICTYPE_IDR_WITH_PPS_SPS;
1644 else
1645 req.wPicType = UVC_H264_PICTYPE_IDR;
1646
1647 if (!xu_query (self, UVCX_PICTURE_TYPE_CONTROL, UVC_SET_CUR,
1648 (guchar *) & req)) {
1649 GST_WARNING_OBJECT (self, " PICTURE_TYPE_CONTROL SET_CUR error");
1650 } else {
1651 gst_event_replace (&self->key_unit_event, event);
1652 gst_event_unref (event);
1653
1654 return TRUE;
1655 }
1656 }
1657 } else if (s &&
1658 gst_structure_has_name (s, "uvc-h264-ltr-picture-control")) {
1659 guint put_at, encode_using;
1660
1661 if (gst_structure_get_uint (s, "put-at", &put_at) &&
1662 gst_structure_get_uint (s, "encode-using", &encode_using)) {
1663 uvcx_ltr_picture_control req = { 0, put_at, encode_using };
1664
1665 if (!xu_query (self, UVCX_LTR_PICTURE_CONTROL, UVC_SET_CUR,
1666 (guchar *) & req)) {
1667 GST_WARNING_OBJECT (self, " LTR PICTURE_CONTROL SET_CUR error");
1668 } else {
1669 gst_event_unref (event);
1670
1671 return TRUE;
1672 }
1673 }
1674 return TRUE;
1675 } else if (s && gst_structure_has_name (s, "uvc-h264-bitrate-control")) {
1676 guint average, peak;
1677
1678 if (gst_structure_get_uint (s, "average-bitrate", &average) &&
1679 gst_structure_get_uint (s, "peak-bitrate", &peak)) {
1680 self->average_bitrate = average;
1681 self->peak_bitrate = peak;
1682 set_bitrate (self);
1683 update_bitrate (self);
1684
1685 gst_event_unref (event);
1686
1687 return TRUE;
1688 }
1689 } else if (s && gst_structure_has_name (s, "uvc-h264-qp-control")) {
1690 gint min_qp, max_qp;
1691 gboolean valid_event = FALSE;
1692
1693 if (gst_structure_get_int (s, "min-iframe-qp", &min_qp) &&
1694 gst_structure_get_int (s, "max-iframe-qp", &max_qp)) {
1695 self->min_qp[QP_I_FRAME] = min_qp;
1696 self->max_qp[QP_I_FRAME] = max_qp;
1697 set_qp (self, QP_I_FRAME);
1698 update_qp (self, QP_I_FRAME);
1699 valid_event = TRUE;
1700 }
1701 if (gst_structure_get_int (s, "min-pframe-qp", &min_qp) &&
1702 gst_structure_get_int (s, "max-pframe-qp", &max_qp)) {
1703 self->min_qp[QP_P_FRAME] = min_qp;
1704 self->max_qp[QP_P_FRAME] = max_qp;
1705 set_qp (self, QP_P_FRAME);
1706 update_qp (self, QP_P_FRAME);
1707 valid_event = TRUE;
1708 }
1709 if (gst_structure_get_int (s, "min-bframe-qp", &min_qp) &&
1710 gst_structure_get_int (s, "max-bframe-qp", &max_qp)) {
1711 self->min_qp[QP_B_FRAME] = min_qp;
1712 self->max_qp[QP_B_FRAME] = max_qp;
1713 set_qp (self, QP_B_FRAME);
1714 update_qp (self, QP_B_FRAME);
1715 valid_event = TRUE;
1716 }
1717
1718 if (valid_event) {
1719 gst_event_unref (event);
1720
1721 return TRUE;
1722 }
1723 } else if (s && gst_structure_has_name (s, "uvc-h264-rate-control")) {
1724 UvcH264RateControl rate;
1725 gboolean fixed_framerate;
1726
1727 if (gst_structure_get_enum (s, "rate-control",
1728 UVC_H264_RATECONTROL_TYPE, (gint *) & rate) &&
1729 gst_structure_get_boolean (s, "fixed-framerate",
1730 &fixed_framerate)) {
1731 self->rate_control = rate;
1732 self->fixed_framerate = fixed_framerate;
1733 set_rate_control (self);
1734 update_rate_control (self);
1735
1736 gst_event_unref (event);
1737
1738 return TRUE;
1739 }
1740 } else if (s && gst_structure_has_name (s, "uvc-h264-level-idc")) {
1741 guint level_idc;
1742
1743 if (gst_structure_get_uint (s, "level-idc", &level_idc)) {
1744 self->level_idc = level_idc;
1745 set_level_idc (self);
1746 update_level_idc_and_get_max_mbps (self);
1747
1748 gst_event_unref (event);
1749 }
1750 }
1751 }
1752 break;
1753 default:
1754 break;
1755 }
1756
1757 return FALSE;
1758 }
1759
1760 static gboolean
gst_uvc_h264_src_send_event(GstElement * element,GstEvent * event)1761 gst_uvc_h264_src_send_event (GstElement * element, GstEvent * event)
1762 {
1763 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
1764
1765 if (gst_uvc_h264_src_parse_event (self, self->vidsrc, event))
1766 return TRUE;
1767
1768 return GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
1769 }
1770
1771 static gboolean
gst_uvc_h264_src_event(GstPad * pad,GstObject * parent,GstEvent * event)1772 gst_uvc_h264_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
1773 {
1774 GstUvcH264Src *self = GST_UVC_H264_SRC (GST_PAD_PARENT (pad));
1775
1776 switch (GST_EVENT_TYPE (event)) {
1777 case GST_EVENT_SEGMENT:
1778 if (pad == self->vidsrc) {
1779 const GstSegment *s;
1780
1781 gst_event_parse_segment (event, &s);
1782 gst_segment_copy_into (s, &self->segment);
1783 }
1784 break;
1785 case GST_EVENT_FLUSH_STOP:
1786 if (pad == self->vidsrc)
1787 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
1788 break;
1789 default:
1790 if (gst_uvc_h264_src_parse_event (self, pad, event))
1791 return TRUE;
1792 break;
1793 }
1794 return self->srcpad_event_func (pad, parent, event);
1795 }
1796
1797 static guint8
xu_get_id(GstUvcH264Src * self)1798 xu_get_id (GstUvcH264Src * self)
1799 {
1800 static const __u8 guid[16] = GUID_UVCX_H264_XU;
1801 GUdevClient *client;
1802 GUdevDevice *udevice;
1803 GUdevDevice *parent;
1804 guint64 busnum;
1805 guint64 devnum;
1806 libusb_device **device_list = NULL;
1807 libusb_device *device = NULL;
1808 ssize_t cnt;
1809 int i, j, k;
1810
1811
1812 if (self->usb_ctx == NULL)
1813 libusb_init (&self->usb_ctx);
1814
1815 client = g_udev_client_new (NULL);
1816 if (client) {
1817 udevice = g_udev_client_query_by_device_file (client, self->device);
1818 if (udevice) {
1819 parent = g_udev_device_get_parent_with_subsystem (udevice, "usb",
1820 "usb_device");
1821 if (parent) {
1822 busnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "busnum");
1823 devnum = g_udev_device_get_sysfs_attr_as_uint64 (parent, "devnum");
1824
1825 cnt = libusb_get_device_list (self->usb_ctx, &device_list);
1826 for (i = 0; i < cnt; i++) {
1827 if (busnum == libusb_get_bus_number (device_list[i]) &&
1828 devnum == libusb_get_device_address (device_list[i])) {
1829 device = libusb_ref_device (device_list[i]);
1830 break;
1831 }
1832 }
1833 libusb_free_device_list (device_list, 1);
1834 g_object_unref (parent);
1835 }
1836 g_object_unref (udevice);
1837 }
1838 g_object_unref (client);
1839 }
1840
1841 if (device) {
1842 struct libusb_device_descriptor desc;
1843
1844 if (libusb_get_device_descriptor (device, &desc) == 0) {
1845 for (i = 0; i < desc.bNumConfigurations; ++i) {
1846 struct libusb_config_descriptor *config = NULL;
1847
1848 if (libusb_get_config_descriptor (device, i, &config) == 0) {
1849 for (j = 0; j < config->bNumInterfaces; j++) {
1850 for (k = 0; k < config->interface[j].num_altsetting; k++) {
1851 const struct libusb_interface_descriptor *interface;
1852 const guint8 *ptr = NULL;
1853
1854 interface = &config->interface[j].altsetting[k];
1855 if (interface->bInterfaceClass != LIBUSB_CLASS_VIDEO ||
1856 interface->bInterfaceSubClass != USB_VIDEO_CONTROL)
1857 continue;
1858 ptr = interface->extra;
1859 while (ptr - interface->extra +
1860 sizeof (xu_descriptor) < interface->extra_length) {
1861 xu_descriptor *desc = (xu_descriptor *) ptr;
1862
1863 GST_DEBUG_OBJECT (self, "Found VideoControl interface with "
1864 "unit id %d : %" GUID_FORMAT, desc->bUnitID,
1865 GUID_ARGS (desc->guidExtensionCode));
1866 if (desc->bDescriptorType == USB_VIDEO_CONTROL_INTERFACE &&
1867 desc->bDescriptorSubType == USB_VIDEO_CONTROL_XU_TYPE &&
1868 memcmp (desc->guidExtensionCode, guid, 16) == 0) {
1869 guint8 unit_id = desc->bUnitID;
1870
1871 GST_DEBUG_OBJECT (self, "Found H264 XU unit : %d", unit_id);
1872
1873 libusb_free_config_descriptor (config);
1874 libusb_unref_device (device);
1875 return unit_id;
1876 }
1877 ptr += desc->bLength;
1878 }
1879 }
1880 }
1881 libusb_free_config_descriptor (config);
1882 }
1883 }
1884 }
1885 libusb_unref_device (device);
1886 }
1887
1888 return 0;
1889 }
1890
1891 static gboolean
xu_query(GstUvcH264Src * self,guint selector,guint query,guchar * data)1892 xu_query (GstUvcH264Src * self, guint selector, guint query, guchar * data)
1893 {
1894 struct uvc_xu_control_query xu;
1895 __u16 len;
1896
1897 if (self->v4l2_fd == -1) {
1898 GST_WARNING_OBJECT (self, "Can't query XU with fd = -1");
1899 return FALSE;
1900 }
1901
1902 xu.unit = self->h264_unit_id;
1903 xu.selector = selector;
1904
1905 xu.query = UVC_GET_LEN;
1906 xu.size = sizeof (len);
1907 xu.data = (unsigned char *) &len;
1908 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1909 GST_WARNING_OBJECT (self, "PROBE GET_LEN error");
1910 return FALSE;
1911 }
1912
1913 if (query == UVC_GET_LEN) {
1914 *((__u16 *) data) = len;
1915 } else {
1916 xu.query = query;
1917 xu.size = len;
1918 xu.data = data;
1919 if (-1 == ioctl (self->v4l2_fd, UVCIOC_CTRL_QUERY, &xu)) {
1920 return FALSE;
1921 }
1922 }
1923
1924 return TRUE;
1925 }
1926
1927 static void
fill_probe_commit(GstUvcH264Src * self,uvcx_video_config_probe_commit_t * probe,guint32 frame_interval,guint32 width,guint32 height,guint32 profile,UvcH264StreamFormat stream_format)1928 fill_probe_commit (GstUvcH264Src * self,
1929 uvcx_video_config_probe_commit_t * probe, guint32 frame_interval,
1930 guint32 width, guint32 height, guint32 profile,
1931 UvcH264StreamFormat stream_format)
1932 {
1933 probe->dwFrameInterval = frame_interval;
1934 probe->dwBitRate = self->initial_bitrate;
1935 probe->wWidth = width;
1936 probe->wHeight = height;
1937 probe->wSliceUnits = self->slice_units;
1938 probe->wSliceMode = self->slice_mode;
1939 probe->wProfile = profile;
1940 probe->wIFramePeriod = self->iframe_period;
1941 probe->bUsageType = self->usage_type;
1942 probe->bRateControlMode = self->rate_control;
1943 if (self->fixed_framerate)
1944 probe->bRateControlMode |= UVC_H264_RATECONTROL_FIXED_FRM_FLG;
1945 probe->bStreamFormat = stream_format;
1946 probe->bEntropyCABAC = self->entropy;
1947 probe->bTimestamp = self->enable_sei ?
1948 UVC_H264_TIMESTAMP_SEI_ENABLE : UVC_H264_TIMESTAMP_SEI_DISABLE;
1949 probe->bNumOfReorderFrames = self->num_reorder_frames;
1950 probe->bPreviewFlipped = self->preview_flipped ?
1951 UVC_H264_PREFLIPPED_HORIZONTAL : UVC_H264_PREFLIPPED_DISABLE;
1952 probe->wLeakyBucketSize = self->leaky_bucket_size;
1953 }
1954
1955 static void
print_probe_commit(GstUvcH264Src * self,uvcx_video_config_probe_commit_t * probe)1956 print_probe_commit (GstUvcH264Src * self,
1957 uvcx_video_config_probe_commit_t * probe)
1958 {
1959 GST_DEBUG_OBJECT (self, " Frame interval : %d *100ns",
1960 probe->dwFrameInterval);
1961 GST_DEBUG_OBJECT (self, " Bit rate : %d", probe->dwBitRate);
1962 GST_DEBUG_OBJECT (self, " Hints : %X", probe->bmHints);
1963 GST_DEBUG_OBJECT (self, " Configuration index : %d",
1964 probe->wConfigurationIndex);
1965 GST_DEBUG_OBJECT (self, " Width : %d", probe->wWidth);
1966 GST_DEBUG_OBJECT (self, " Height : %d", probe->wHeight);
1967 GST_DEBUG_OBJECT (self, " Slice units : %d", probe->wSliceUnits);
1968 GST_DEBUG_OBJECT (self, " Slice mode : %X", probe->wSliceMode);
1969 GST_DEBUG_OBJECT (self, " Profile : %X", probe->wProfile);
1970 GST_DEBUG_OBJECT (self, " IFrame Period : %d ms", probe->wIFramePeriod);
1971 GST_DEBUG_OBJECT (self, " Estimated video delay : %d ms",
1972 probe->wEstimatedVideoDelay);
1973 GST_DEBUG_OBJECT (self, " Estimated max config delay : %d ms",
1974 probe->wEstimatedMaxConfigDelay);
1975 GST_DEBUG_OBJECT (self, " Usage type : %X", probe->bUsageType);
1976 GST_DEBUG_OBJECT (self, " Rate control mode : %X", probe->bRateControlMode);
1977 GST_DEBUG_OBJECT (self, " Temporal scale mode : %X",
1978 probe->bTemporalScaleMode);
1979 GST_DEBUG_OBJECT (self, " Spatial scale mode : %X",
1980 probe->bSpatialScaleMode);
1981 GST_DEBUG_OBJECT (self, " SNR scale mode : %X", probe->bSNRScaleMode);
1982 GST_DEBUG_OBJECT (self, " Stream mux option : %X", probe->bStreamMuxOption);
1983 GST_DEBUG_OBJECT (self, " Stream Format : %X", probe->bStreamFormat);
1984 GST_DEBUG_OBJECT (self, " Entropy CABAC : %X", probe->bEntropyCABAC);
1985 GST_DEBUG_OBJECT (self, " Timestamp : %X", probe->bTimestamp);
1986 GST_DEBUG_OBJECT (self, " Num of reorder frames : %d",
1987 probe->bNumOfReorderFrames);
1988 GST_DEBUG_OBJECT (self, " Preview flipped : %X", probe->bPreviewFlipped);
1989 GST_DEBUG_OBJECT (self, " View : %d", probe->bView);
1990 GST_DEBUG_OBJECT (self, " Stream ID : %X", probe->bStreamID);
1991 GST_DEBUG_OBJECT (self, " Spatial layer ratio : %f",
1992 ((probe->bSpatialLayerRatio & 0xF0) >> 4) +
1993 ((float) (probe->bSpatialLayerRatio & 0x0F)) / 16);
1994 GST_DEBUG_OBJECT (self, " Leaky bucket size : %d ms",
1995 probe->wLeakyBucketSize);
1996 }
1997
1998 static void
configure_h264(GstUvcH264Src * self,gint fd)1999 configure_h264 (GstUvcH264Src * self, gint fd)
2000 {
2001 uvcx_video_config_probe_commit_t probe;
2002
2003 /* Set the secondary format first, so the last SET_CUR will be for the
2004 * H264 format. This way, we can still get the static control values with
2005 * a GET_CUR. Otherwise all static properties will return 0 because that's
2006 * what the GET_CUR of the raw format returns.
2007 */
2008 if (self->secondary_format == UVC_H264_SRC_FORMAT_RAW) {
2009 memset (&probe, 0, sizeof (probe));
2010 probe.dwFrameInterval = self->secondary_frame_interval;
2011 probe.wWidth = self->secondary_width;
2012 probe.wHeight = self->secondary_height;
2013 probe.bStreamMuxOption = 5;
2014
2015 GST_DEBUG_OBJECT (self, "RAW PROBE SET_CUR : ");
2016 print_probe_commit (self, &probe);
2017
2018 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2019 (guchar *) & probe)) {
2020 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2021 return;
2022 }
2023
2024 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2025 (guchar *) & probe)) {
2026 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2027 return;
2028 }
2029 GST_DEBUG_OBJECT (self, "RAW PROBE GET_CUR : ");
2030 print_probe_commit (self, &probe);
2031
2032 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
2033 (guchar *) & probe)) {
2034 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
2035 return;
2036 }
2037 }
2038 /* Print MIN/MAX/DEF probe values for debugging purposes */
2039 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MIN,
2040 (guchar *) & probe)) {
2041 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2042 return;
2043 }
2044 GST_DEBUG_OBJECT (self, "PROBE GET_MIN : ");
2045 print_probe_commit (self, &probe);
2046
2047 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_MAX,
2048 (guchar *) & probe)) {
2049 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2050 return;
2051 }
2052 GST_DEBUG_OBJECT (self, "PROBE GET_MAX : ");
2053 print_probe_commit (self, &probe);
2054
2055 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_DEF,
2056 (guchar *) & probe)) {
2057 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2058 return;
2059 }
2060 GST_DEBUG_OBJECT (self, "PROBE GET_DEF : ");
2061 print_probe_commit (self, &probe);
2062
2063 fill_probe_commit (self, &probe, self->main_frame_interval,
2064 self->main_width, self->main_height, self->main_profile,
2065 self->main_stream_format);
2066 if (self->secondary_format != UVC_H264_SRC_FORMAT_NONE)
2067 probe.bStreamMuxOption = 3;
2068 else
2069 probe.bStreamMuxOption = 0;
2070 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION | UVC_H264_BMHINTS_PROFILE |
2071 UVC_H264_BMHINTS_FRAME_INTERVAL;
2072
2073 GST_DEBUG_OBJECT (self, "PROBE SET_CUR : ");
2074 print_probe_commit (self, &probe);
2075
2076 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2077 (guchar *) & probe)) {
2078 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2079 return;
2080 }
2081
2082 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2083 (guchar *) & probe)) {
2084 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2085 return;
2086 }
2087 GST_DEBUG_OBJECT (self, "PROBE GET_CUR : ");
2088 print_probe_commit (self, &probe);
2089
2090 /* Must validate the settings accepted by the encoder */
2091 if (!xu_query (self, UVCX_VIDEO_CONFIG_COMMIT, UVC_SET_CUR,
2092 (guchar *) & probe)) {
2093 GST_WARNING_OBJECT (self, "COMMIT SET_CUR error");
2094 return;
2095 }
2096 }
2097
2098 static void
v4l2src_prepare_format(GstElement * v4l2src,gint fd,GstCaps * caps,gpointer user_data)2099 v4l2src_prepare_format (GstElement * v4l2src, gint fd, GstCaps * caps,
2100 gpointer user_data)
2101 {
2102 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
2103
2104 if (self->main_format == UVC_H264_SRC_FORMAT_H264) {
2105 /* TODO: update static controls and g_object_notify those that changed */
2106 configure_h264 (self, fd);
2107
2108 /* TODO: update dynamic controls on READY state */
2109 /* Configure dynamic controls */
2110 set_rate_control (self);
2111 update_rate_control (self);
2112 set_level_idc (self);
2113 update_level_idc_and_get_max_mbps (self);
2114 set_bitrate (self);
2115 update_bitrate (self);
2116 set_qp (self, QP_I_FRAME);
2117 update_qp (self, QP_I_FRAME);
2118 set_qp (self, QP_P_FRAME);
2119 update_qp (self, QP_P_FRAME);
2120 set_qp (self, QP_B_FRAME);
2121 update_qp (self, QP_B_FRAME);
2122 set_ltr (self);
2123 update_ltr (self);
2124 }
2125 }
2126
2127 static gboolean
_extract_caps_info(GstStructure * structure,guint16 * width,guint16 * height,guint32 * frame_interval)2128 _extract_caps_info (GstStructure * structure, guint16 * width, guint16 * height,
2129 guint32 * frame_interval)
2130 {
2131 gint w, h, fps_n, fps_d;
2132 gboolean ret = TRUE;
2133
2134 ret &= gst_structure_get_int (structure, "width", &w);
2135 ret &= gst_structure_get_int (structure, "height", &h);
2136 ret &= gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
2137
2138 if (ret) {
2139 *width = w;
2140 *height = h;
2141 /* Interval is in 100ns */
2142 *frame_interval = GST_TIME_AS_NSECONDS ((fps_d * GST_SECOND) / fps_n) / 100;
2143 }
2144
2145 return ret;
2146 }
2147
2148 static guint16
_extract_profile(GstStructure * structure)2149 _extract_profile (GstStructure * structure)
2150 {
2151 const gchar *profile_str;
2152 guint16 profile;
2153
2154 profile = UVC_H264_PROFILE_HIGH;
2155 profile_str = gst_structure_get_string (structure, "profile");
2156 if (profile_str) {
2157 if (!strcmp (profile_str, "constrained-baseline")) {
2158 profile = UVC_H264_PROFILE_CONSTRAINED_BASELINE;
2159 } else if (!strcmp (profile_str, "baseline")) {
2160 profile = UVC_H264_PROFILE_BASELINE;
2161 } else if (!strcmp (profile_str, "main")) {
2162 profile = UVC_H264_PROFILE_MAIN;
2163 } else if (!strcmp (profile_str, "high")) {
2164 profile = UVC_H264_PROFILE_HIGH;
2165 }
2166 }
2167 return profile;
2168 }
2169
2170 static UvcH264StreamFormat
_extract_stream_format(GstStructure * structure)2171 _extract_stream_format (GstStructure * structure)
2172 {
2173 const gchar *stream_format;
2174
2175 stream_format = gst_structure_get_string (structure, "stream-format");
2176 if (stream_format) {
2177 if (!strcmp (stream_format, "avc"))
2178 return UVC_H264_STREAMFORMAT_NAL;
2179 else if (!strcmp (stream_format, "byte-stream"))
2180 return UVC_H264_STREAMFORMAT_ANNEXB;
2181 }
2182 return UVC_H264_STREAMFORMAT_ANNEXB;
2183 }
2184
2185 static GstCaps *
_transform_caps(GstUvcH264Src * self,GstCaps * caps,const gchar * name)2186 _transform_caps (GstUvcH264Src * self, GstCaps * caps, const gchar * name)
2187 {
2188 GstElement *el = gst_element_factory_make (name, NULL);
2189 GstElement *cf = gst_element_factory_make ("capsfilter", NULL);
2190 GstElement *fs = gst_element_factory_make ("fakesink", NULL);
2191 GstPad *sink;
2192 GstCaps *out_caps = NULL;
2193
2194 if (!el || !cf || !fs) {
2195 if (el)
2196 gst_object_unref (el);
2197 if (cf)
2198 gst_object_unref (cf);
2199 if (fs)
2200 gst_object_unref (fs);
2201 goto done;
2202 }
2203
2204 gst_element_set_locked_state (el, TRUE);
2205 gst_element_set_locked_state (cf, TRUE);
2206 gst_element_set_locked_state (fs, TRUE);
2207
2208 if (!gst_bin_add (GST_BIN (self), el)) {
2209 gst_object_unref (el);
2210 gst_object_unref (cf);
2211 gst_object_unref (fs);
2212 goto done;
2213 }
2214 if (!gst_bin_add (GST_BIN (self), cf)) {
2215 gst_object_unref (cf);
2216 gst_object_unref (fs);
2217 gst_bin_remove (GST_BIN (self), el);
2218 goto done;
2219 }
2220 if (!gst_bin_add (GST_BIN (self), fs)) {
2221 gst_object_unref (fs);
2222 gst_bin_remove (GST_BIN (self), el);
2223 gst_bin_remove (GST_BIN (self), cf);
2224 goto done;
2225 }
2226
2227 g_object_set (cf, "caps", caps, NULL);
2228
2229 if (!gst_element_link (cf, fs))
2230 goto error_remove;
2231 if (!gst_element_link (el, cf))
2232 goto error_remove;
2233
2234 sink = gst_element_get_static_pad (el, "sink");
2235 if (!sink)
2236 goto error_remove;
2237 GST_DEBUG_OBJECT (self, "Transforming: %" GST_PTR_FORMAT, caps);
2238
2239 caps = gst_pad_query_caps (sink, NULL);
2240 gst_object_unref (sink);
2241
2242 GST_DEBUG_OBJECT (self, "Result: %" GST_PTR_FORMAT, out_caps);
2243
2244 error_remove:
2245 gst_bin_remove (GST_BIN (self), cf);
2246 gst_bin_remove (GST_BIN (self), el);
2247 gst_bin_remove (GST_BIN (self), fs);
2248
2249 done:
2250 if (out_caps == NULL)
2251 out_caps = gst_caps_copy (caps);
2252
2253 return out_caps;
2254 }
2255
2256 static GstCaps *
gst_uvc_h264_src_transform_caps(GstUvcH264Src * self,GstCaps * caps)2257 gst_uvc_h264_src_transform_caps (GstUvcH264Src * self, GstCaps * caps)
2258 {
2259 GstCaps *h264 = gst_caps_new_empty_simple ("video/x-h264");
2260 GstCaps *jpg = gst_caps_new_empty_simple ("image/jpeg");
2261 GstCaps *h264_caps = gst_caps_intersect (h264, caps);
2262 GstCaps *jpg_caps = gst_caps_intersect (jpg, caps);
2263
2264 /* TODO: Keep caps order after transformation */
2265 caps = _transform_caps (self, caps, self->colorspace_name);
2266 caps = gst_caps_make_writable (caps);
2267
2268 if (!gst_caps_is_empty (h264_caps)) {
2269 gst_caps_append (caps, h264_caps);
2270 } else {
2271 gst_caps_unref (h264_caps);
2272 }
2273
2274 if (!gst_caps_is_empty (jpg_caps)) {
2275 gst_caps_append (caps, jpg_caps);
2276 } else {
2277 gst_caps_unref (jpg_caps);
2278 }
2279
2280 gst_caps_unref (h264);
2281 gst_caps_unref (jpg);
2282
2283 return caps;
2284 }
2285
2286 static GstCaps *
gst_uvc_h264_src_fixate_caps(GstUvcH264Src * self,GstPad * v4l_pad,GstCaps * v4l_caps,GstCaps * peer_caps,gboolean primary)2287 gst_uvc_h264_src_fixate_caps (GstUvcH264Src * self, GstPad * v4l_pad,
2288 GstCaps * v4l_caps, GstCaps * peer_caps, gboolean primary)
2289 {
2290 GstCaps *caps = NULL;
2291 GstCaps *icaps = NULL;
2292 GstCaps *tcaps = NULL;
2293 int i;
2294
2295 if (v4l_caps == NULL || gst_caps_is_any (v4l_caps)) {
2296 GST_DEBUG_OBJECT (self, "v4l caps are invalid. not fixating");
2297 return NULL;
2298 }
2299
2300 tcaps = gst_caps_intersect_full (peer_caps, v4l_caps,
2301 GST_CAPS_INTERSECT_FIRST);
2302 GST_DEBUG_OBJECT (self, "intersect: %" GST_PTR_FORMAT, tcaps);
2303 icaps = gst_caps_normalize (tcaps);
2304
2305 /* Prefer the first caps we are compatible with that the peer proposed */
2306 for (i = 0; i < gst_caps_get_size (icaps); i++) {
2307 /* get intersection */
2308 GstCaps *ipcaps = gst_caps_copy_nth (icaps, i);
2309 GstStructure *s = gst_caps_get_structure (ipcaps, 0);
2310
2311 GST_DEBUG_OBJECT (self, "Testing %s: %" GST_PTR_FORMAT,
2312 primary ? "primary" : "secondary", ipcaps);
2313 if (primary && gst_structure_has_name (s, "video/x-h264")) {
2314 uvcx_video_config_probe_commit_t probe;
2315 guint16 width;
2316 guint16 height;
2317 guint32 interval;
2318 guint16 profile;
2319 UvcH264StreamFormat stream_format;
2320
2321 if (_extract_caps_info (s, &width, &height, &interval)) {
2322 profile = _extract_profile (s);
2323 stream_format = _extract_stream_format (s);
2324 fill_probe_commit (self, &probe, interval, width, height,
2325 profile, stream_format);
2326 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2327 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2328
2329 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2330 (guchar *) & probe)) {
2331 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2332 return NULL;
2333 }
2334
2335 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2336 (guchar *) & probe)) {
2337 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2338 return NULL;
2339 }
2340 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d==%d",
2341 probe.wWidth, width, probe.wHeight, height,
2342 probe.bStreamFormat, stream_format);
2343 if (probe.wWidth == width && probe.wHeight == height &&
2344 probe.bStreamFormat == stream_format) {
2345 caps = ipcaps;
2346 break;
2347 }
2348 }
2349 } else if (!primary && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2350 uvcx_video_config_probe_commit_t probe;
2351 guint16 width;
2352 guint16 height;
2353 guint32 interval;
2354
2355 if (_extract_caps_info (s, &width, &height, &interval)) {
2356 if (gst_structure_has_name (s, "video/x-raw")) {
2357 guint8 mux = 0;
2358 const gchar *format = gst_structure_get_string (s, "format");
2359
2360 if ((format = gst_structure_get_string (s, "format"))) {
2361 if (g_strcmp0 (format, "YUY2") == 0)
2362 mux = 4;
2363 else if (g_strcmp0 (format, "NV12") == 0)
2364 mux = 8;
2365 }
2366 if (mux != 0) {
2367 memset (&probe, 0, sizeof (probe));
2368 probe.dwFrameInterval = interval;
2369 probe.wWidth = width;
2370 probe.wHeight = height;
2371 probe.bStreamMuxOption = mux | 1;
2372 probe.bmHints = UVC_H264_BMHINTS_RESOLUTION |
2373 UVC_H264_BMHINTS_PROFILE | UVC_H264_BMHINTS_FRAME_INTERVAL;
2374
2375 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_SET_CUR,
2376 (guchar *) & probe)) {
2377 GST_WARNING_OBJECT (self, "PROBE SET_CUR error");
2378 return NULL;
2379 }
2380
2381 if (!xu_query (self, UVCX_VIDEO_CONFIG_PROBE, UVC_GET_CUR,
2382 (guchar *) & probe)) {
2383 GST_WARNING_OBJECT (self, "PROBE GET_CUR error");
2384 return NULL;
2385 }
2386 GST_DEBUG_OBJECT (self, "Probe gives us %d==%d, %d==%d, %d~=%d",
2387 probe.wWidth, width, probe.wHeight, height,
2388 probe.bStreamMuxOption, mux);
2389 if (probe.wWidth == width && probe.wHeight == height &&
2390 (probe.bStreamMuxOption & mux) != 0) {
2391 caps = ipcaps;
2392 break;
2393 }
2394 }
2395 } else if (gst_structure_has_name (s, "image/jpeg")) {
2396 /* HACK ALERT: No way of figuring this one out but it seems the
2397 * camera doesn't allow for h264 muxing and jpeg resolution higher
2398 * than 640x480 so we shouldn't allow it */
2399 if (width <= 640 && height <= 480) {
2400 caps = ipcaps;
2401 break;
2402 }
2403 }
2404 }
2405 } else {
2406 caps = ipcaps;
2407 break;
2408 }
2409 gst_caps_unref (ipcaps);
2410 }
2411
2412 if (caps) {
2413 caps = gst_caps_make_writable (caps);
2414
2415 /* now fixate */
2416 if (!gst_caps_is_empty (caps)) {
2417 caps = gst_caps_fixate (caps);
2418 GST_DEBUG_OBJECT (self, "fixated to: %" GST_PTR_FORMAT, caps);
2419 }
2420
2421 if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
2422 gst_caps_unref (caps);
2423 caps = NULL;
2424 }
2425 }
2426
2427 return caps;
2428 }
2429
2430 static void
gst_uvc_h264_src_destroy_pipeline(GstUvcH264Src * self,gboolean v4l2src)2431 gst_uvc_h264_src_destroy_pipeline (GstUvcH264Src * self, gboolean v4l2src)
2432 {
2433 GstIterator *iter = NULL;
2434 gboolean done;
2435
2436 if (v4l2src && self->v4l2_src) {
2437 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2438 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2439 gst_object_unref (self->v4l2_src);
2440 self->v4l2_src = NULL;
2441 self->v4l2_fd = -1;
2442 self->h264_unit_id = 0;
2443 }
2444 if (self->mjpg_demux) {
2445 gst_bin_remove (GST_BIN (self), self->mjpg_demux);
2446 gst_element_set_state (self->mjpg_demux, GST_STATE_NULL);
2447 gst_object_unref (self->mjpg_demux);
2448 self->mjpg_demux = NULL;
2449 }
2450 if (self->jpeg_dec) {
2451 gst_bin_remove (GST_BIN (self), self->jpeg_dec);
2452 gst_element_set_state (self->jpeg_dec, GST_STATE_NULL);
2453 gst_object_unref (self->jpeg_dec);
2454 self->jpeg_dec = NULL;
2455 }
2456 if (self->vid_colorspace) {
2457 gst_bin_remove (GST_BIN (self), self->vid_colorspace);
2458 gst_element_set_state (self->vid_colorspace, GST_STATE_NULL);
2459 gst_object_unref (self->vid_colorspace);
2460 self->vid_colorspace = NULL;
2461 }
2462 if (self->vf_colorspace) {
2463 gst_bin_remove (GST_BIN (self), self->vf_colorspace);
2464 gst_element_set_state (self->vf_colorspace, GST_STATE_NULL);
2465 gst_object_unref (self->vf_colorspace);
2466 self->vf_colorspace = NULL;
2467 }
2468 iter = gst_bin_iterate_elements (GST_BIN (self));
2469 done = FALSE;
2470 while (!done) {
2471 GValue data = { 0, };
2472
2473 switch (gst_iterator_next (iter, &data)) {
2474 case GST_ITERATOR_OK:
2475 {
2476 GstElement *child = g_value_get_object (&data);
2477 if (child != self->v4l2_src) {
2478 gst_bin_remove (GST_BIN (self), child);
2479 gst_element_set_state (child, GST_STATE_NULL);
2480 }
2481 g_value_reset (&data);
2482 break;
2483 }
2484 case GST_ITERATOR_RESYNC:
2485 gst_iterator_resync (iter);
2486 break;
2487 case GST_ITERATOR_ERROR:
2488 done = TRUE;
2489 break;
2490 case GST_ITERATOR_DONE:
2491 done = TRUE;
2492 break;
2493 }
2494 }
2495 gst_iterator_free (iter);
2496 }
2497
2498 static gboolean
ensure_v4l2src(GstUvcH264Src * self)2499 ensure_v4l2src (GstUvcH264Src * self)
2500 {
2501 gchar *device = NULL;
2502 GstClock *v4l2_clock = NULL;
2503
2504 if (self->v4l2_src == NULL) {
2505 /* Create v4l2 source and set it up */
2506 self->v4l2_src = gst_element_factory_make ("v4l2src", NULL);
2507 if (!self->v4l2_src || !gst_bin_add (GST_BIN (self), self->v4l2_src))
2508 goto error;
2509 gst_object_ref (self->v4l2_src);
2510 g_signal_connect (self->v4l2_src, "prepare-format",
2511 (GCallback) v4l2src_prepare_format, self);
2512 }
2513
2514 g_object_get (self->v4l2_src, "device", &device, NULL);
2515 g_object_set (self->v4l2_src,
2516 "device", self->device, "num-buffers", self->num_buffers, NULL);
2517
2518 v4l2_clock = gst_element_get_clock (self->v4l2_src);
2519
2520 /* Set to NULL if the device changed */
2521 if (g_strcmp0 (device, self->device))
2522 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2523 g_free (device);
2524
2525 if (gst_element_set_state (self->v4l2_src, GST_STATE_READY) !=
2526 GST_STATE_CHANGE_SUCCESS) {
2527 GST_DEBUG_OBJECT (self, "Unable to set v4l2src to READY state");
2528 goto error_remove;
2529 }
2530
2531 /* Set/Update the fd and unit id after we go to READY */
2532 g_object_get (self->v4l2_src, "device-fd", &self->v4l2_fd, NULL);
2533 self->h264_unit_id = xu_get_id (self);
2534
2535 if (self->h264_unit_id == 0) {
2536 GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
2537 ("Device is not a valid UVC H264 camera"), (NULL));
2538 goto error_remove;
2539 }
2540
2541 /* going to state READY makes v4l2src lose its reference to the clock */
2542 if (v4l2_clock) {
2543 gst_element_set_clock (self->v4l2_src, v4l2_clock);
2544 gst_element_set_base_time (self->v4l2_src,
2545 gst_element_get_base_time (GST_ELEMENT (self)));
2546 gst_object_unref (v4l2_clock);
2547 }
2548
2549 return TRUE;
2550
2551 error_remove:
2552 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
2553 gst_bin_remove (GST_BIN (self), self->v4l2_src);
2554
2555 error:
2556 if (v4l2_clock)
2557 gst_object_unref (v4l2_clock);
2558 if (self->v4l2_src)
2559 gst_object_unref (self->v4l2_src);
2560 self->v4l2_src = NULL;
2561 self->v4l2_fd = -1;
2562 self->h264_unit_id = 0;
2563
2564 return FALSE;
2565 }
2566
2567 static gboolean
gst_uvc_h264_src_construct_pipeline(GstBaseCameraSrc * bcamsrc)2568 gst_uvc_h264_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
2569 {
2570 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
2571 GstIterator *iter = NULL;
2572 gboolean iter_done = FALSE;
2573 GstPad *vf_pad = NULL;
2574 GstCaps *vf_caps = NULL;
2575 GstStructure *vf_struct = NULL;
2576 GstPad *vid_pad = NULL;
2577 GstCaps *vid_caps = NULL;
2578 GstStructure *vid_struct = NULL;
2579 GstCaps *src_caps = NULL;
2580 GstPad *v4l_pad = NULL;
2581 GstCaps *v4l_caps = NULL;
2582 gboolean jpg2raw = FALSE;
2583
2584 enum
2585 {
2586 RAW_NONE, ENCODED_NONE, NONE_RAW, NONE_ENCODED,
2587 H264_JPG, H264_RAW, H264_JPG2RAW, NONE_NONE,
2588 RAW_RAW, ENCODED_ENCODED,
2589 } type;
2590
2591 GST_DEBUG_OBJECT (self, "Construct pipeline");
2592 self->reconfiguring = TRUE;
2593
2594 if (self->v4l2_src) {
2595 uvcx_encoder_reset req = { 0 };
2596
2597 if (!xu_query (self, UVCX_ENCODER_RESET, UVC_SET_CUR, (guchar *) & req))
2598 GST_WARNING_OBJECT (self, " UVCX_ENCODER_RESET SET_CUR error");
2599 }
2600
2601 if (!ensure_v4l2src (self))
2602 goto error;
2603
2604 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
2605
2606 /* Potentially unlink v4l2src to the ghost pads */
2607 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), NULL);
2608 gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), NULL);
2609
2610 if (gst_pad_is_linked (self->vfsrc))
2611 vf_caps = gst_pad_peer_query_caps (self->vfsrc, NULL);
2612 if (gst_pad_is_linked (self->vidsrc))
2613 vid_caps = gst_pad_peer_query_caps (self->vidsrc, NULL);
2614
2615 GST_DEBUG_OBJECT (self, "vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2616 GST_DEBUG_OBJECT (self, "vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2617 if (!self->started) {
2618 GST_DEBUG_OBJECT (self, "video not started. Ignoring vidsrc caps");
2619 if (vid_caps)
2620 gst_caps_unref (vid_caps);
2621 vid_caps = NULL;
2622 }
2623
2624 v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2625 v4l_caps = gst_pad_query_caps (v4l_pad, NULL);
2626 GST_DEBUG_OBJECT (self, "v4l2src caps : %" GST_PTR_FORMAT, v4l_caps);
2627 if (vid_caps) {
2628 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vid_caps);
2629
2630 gst_caps_unref (vid_caps);
2631 vid_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2632 trans_caps, TRUE);
2633 gst_caps_unref (trans_caps);
2634
2635 if (vid_caps) {
2636 vid_struct = gst_caps_get_structure (vid_caps, 0);
2637 } else {
2638 GST_WARNING_OBJECT (self, "Could not negotiate vidsrc caps format");
2639 gst_object_unref (v4l_pad);
2640 gst_caps_unref (v4l_caps);
2641 goto error_remove;
2642 }
2643 }
2644 GST_DEBUG_OBJECT (self, "Fixated vidsrc caps : %" GST_PTR_FORMAT, vid_caps);
2645
2646 if (vid_caps && gst_structure_has_name (vid_struct, "video/x-h264")) {
2647 self->main_format = UVC_H264_SRC_FORMAT_H264;
2648 if (!_extract_caps_info (vid_struct, &self->main_width,
2649 &self->main_height, &self->main_frame_interval)) {
2650 gst_object_unref (v4l_pad);
2651 gst_caps_unref (v4l_caps);
2652 goto error_remove;
2653 }
2654
2655 self->main_stream_format = _extract_stream_format (vid_struct);
2656 self->main_profile = _extract_profile (vid_struct);
2657 } else {
2658 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2659 }
2660
2661 if (vf_caps) {
2662 GstCaps *trans_caps = gst_uvc_h264_src_transform_caps (self, vf_caps);
2663
2664 gst_caps_unref (vf_caps);
2665 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2666 trans_caps, FALSE);
2667
2668 /* If we couldn't find a suitable vf cap, try the jpeg2raw pipeline */
2669 if (!vf_caps && self->main_format == UVC_H264_SRC_FORMAT_H264) {
2670 GstCaps *jpg_caps;
2671
2672 jpg2raw = TRUE;
2673 jpg_caps = _transform_caps (self, trans_caps, self->jpeg_decoder_name);
2674
2675 vf_caps = gst_uvc_h264_src_fixate_caps (self, v4l_pad, v4l_caps,
2676 jpg_caps, FALSE);
2677 gst_caps_unref (jpg_caps);
2678 }
2679 gst_caps_unref (trans_caps);
2680 if (vf_caps) {
2681 vf_struct = gst_caps_get_structure (vf_caps, 0);
2682 } else {
2683 GST_WARNING_OBJECT (self, "Could not negotiate vfsrc caps format");
2684 gst_object_unref (v4l_pad);
2685 gst_caps_unref (v4l_caps);
2686 goto error_remove;
2687 }
2688 }
2689 GST_DEBUG_OBJECT (self, "Fixated vfsrc caps : %" GST_PTR_FORMAT, vf_caps);
2690 gst_object_unref (v4l_pad);
2691 gst_caps_unref (v4l_caps);
2692
2693 if (vf_caps && vid_caps &&
2694 !gst_structure_has_name (vid_struct, "video/x-h264")) {
2695 /* Allow for vfsrc+vidsrc to both be raw or jpeg */
2696 if (gst_structure_has_name (vid_struct, "image/jpeg") &&
2697 gst_structure_has_name (vf_struct, "image/jpeg")) {
2698 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2699 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2700 type = ENCODED_ENCODED;
2701 } else if (!gst_structure_has_name (vid_struct, "image/jpeg") &&
2702 !gst_structure_has_name (vf_struct, "image/jpeg")) {
2703 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2704 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2705 type = RAW_RAW;
2706 } else {
2707 goto error_remove;
2708 }
2709 } else if (vf_caps && vid_caps) {
2710 guint32 smallest_frame_interval;
2711
2712 if (!_extract_caps_info (vf_struct, &self->secondary_width,
2713 &self->secondary_height, &self->secondary_frame_interval))
2714 goto error_remove;
2715
2716 if (jpg2raw == FALSE && gst_structure_has_name (vf_struct, "image/jpeg")) {
2717 type = H264_JPG;
2718 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2719 } else {
2720 if (jpg2raw) {
2721 type = H264_JPG2RAW;
2722 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2723 } else {
2724 type = H264_RAW;
2725 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2726 }
2727 }
2728 smallest_frame_interval = MIN (self->main_frame_interval,
2729 self->secondary_frame_interval);
2730 /* Just to avoid a potential division by zero, set interval to 30 fps */
2731 if (smallest_frame_interval == 0)
2732 smallest_frame_interval = 333333;
2733
2734 /* Frame interval is in 100ns units */
2735 src_caps = gst_caps_new_simple ("image/jpeg",
2736 "width", G_TYPE_INT, self->secondary_width,
2737 "height", G_TYPE_INT, self->secondary_height,
2738 "framerate", GST_TYPE_FRACTION,
2739 NSEC_PER_SEC / smallest_frame_interval, 100, NULL);
2740 } else if (vf_caps || vid_caps) {
2741 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2742 if (vid_struct && gst_structure_has_name (vid_struct, "video/x-h264")) {
2743 type = ENCODED_NONE;
2744 } else if (vid_struct && gst_structure_has_name (vid_struct, "image/jpeg")) {
2745 type = ENCODED_NONE;
2746 self->main_format = UVC_H264_SRC_FORMAT_JPG;
2747 } else if (vf_struct && gst_structure_has_name (vf_struct, "image/jpeg")) {
2748 type = NONE_ENCODED;
2749 self->secondary_format = UVC_H264_SRC_FORMAT_JPG;
2750 } else if (vid_struct) {
2751 type = RAW_NONE;
2752 self->main_format = UVC_H264_SRC_FORMAT_RAW;
2753 } else if (vf_struct) {
2754 type = NONE_RAW;
2755 self->secondary_format = UVC_H264_SRC_FORMAT_RAW;
2756 } else {
2757 g_assert_not_reached ();
2758 type = NONE_NONE;
2759 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2760 }
2761 } else {
2762 type = NONE_NONE;
2763 self->main_format = UVC_H264_SRC_FORMAT_NONE;
2764 self->secondary_format = UVC_H264_SRC_FORMAT_NONE;
2765 }
2766
2767 switch (type) {
2768 case NONE_NONE:
2769 GST_DEBUG_OBJECT (self, "None+None");
2770 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2771 break;
2772 case RAW_NONE:
2773 GST_DEBUG_OBJECT (self, "Raw+None");
2774 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2775 NULL);
2776 if (!self->vid_colorspace ||
2777 !gst_bin_add (GST_BIN (self), self->vid_colorspace))
2778 goto error_remove;
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");
2783 break;
2784 case NONE_RAW:
2785 GST_DEBUG_OBJECT (self, "None+Raw");
2786 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2787 NULL);
2788 if (!self->vf_colorspace ||
2789 !gst_bin_add (GST_BIN (self), self->vf_colorspace))
2790 goto error_remove;
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");
2795 break;
2796 case ENCODED_NONE:
2797 GST_DEBUG_OBJECT (self, "Encoded+None");
2798 vid_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2799 break;
2800 case NONE_ENCODED:
2801 GST_DEBUG_OBJECT (self, "None+Encoded");
2802 vf_pad = gst_element_get_static_pad (self->v4l2_src, "src");
2803 break;
2804 case H264_JPG:
2805 GST_DEBUG_OBJECT (self, "H264+JPG");
2806 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
2807 if (!self->mjpg_demux || !gst_bin_add (GST_BIN (self), self->mjpg_demux))
2808 goto error_remove;
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,
2813 src_caps))
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");
2817 break;
2818 case H264_RAW:
2819 GST_DEBUG_OBJECT (self, "H264+Raw");
2820 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
2821 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2822 NULL);
2823 if (!self->mjpg_demux || !self->vf_colorspace)
2824 goto error_remove;
2825 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2826 goto error_remove;
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;
2834 }
2835 gst_object_ref (self->vf_colorspace);
2836 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2837 src_caps))
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");
2844 break;
2845 case H264_JPG2RAW:
2846 GST_DEBUG_OBJECT (self, "H264+Raw(jpegdec)");
2847 self->mjpg_demux = gst_element_factory_make ("uvch264mjpgdemux", 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,
2850 NULL);
2851 if (!self->mjpg_demux || !self->jpeg_dec || !self->vf_colorspace)
2852 goto error_remove;
2853 if (!gst_bin_add (GST_BIN (self), self->mjpg_demux))
2854 goto error_remove;
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;
2864 }
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;
2870 }
2871 gst_object_ref (self->vf_colorspace);
2872 if (!gst_element_link_filtered (self->v4l2_src, self->mjpg_demux,
2873 src_caps))
2874 goto error_remove_all;
2875 if (!gst_element_link_pads (self->mjpg_demux, "jpeg", self->jpeg_dec,
2876 "sink"))
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");
2882 break;
2883 case RAW_RAW:
2884 {
2885 GstElement *tee = NULL;
2886
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)) {
2890 if (tee)
2891 gst_object_unref (tee);
2892 goto error_remove;
2893 }
2894 self->vf_colorspace = gst_element_factory_make (self->colorspace_name,
2895 NULL);
2896 self->vid_colorspace = gst_element_factory_make (self->colorspace_name,
2897 NULL);
2898 if (!self->vf_colorspace || !self->vid_colorspace)
2899 goto error_remove;
2900 if (!gst_bin_add (GST_BIN (self), self->vf_colorspace))
2901 goto error_remove;
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;
2907 }
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");
2917 }
2918 break;
2919 case ENCODED_ENCODED:
2920 {
2921 GstElement *tee = NULL;
2922
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)) {
2926 if (tee)
2927 gst_object_unref (tee);
2928 goto error_remove;
2929 }
2930 if (!gst_element_link (self->v4l2_src, tee))
2931 goto error_remove_all;
2932 vf_pad = gst_element_get_request_pad (tee, "src_%u");
2933 vid_pad = gst_element_get_request_pad (tee, "src_%u");
2934 }
2935 break;
2936 }
2937
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;
2941 if (vid_pad)
2942 gst_object_unref (vid_pad);
2943 if (vf_pad)
2944 gst_object_unref (vf_pad);
2945 vid_pad = vf_pad = NULL;
2946
2947 if (vf_caps)
2948 gst_caps_unref (vf_caps);
2949 if (vid_caps)
2950 gst_caps_unref (vid_caps);
2951 if (src_caps)
2952 gst_caps_unref (src_caps);
2953 vf_caps = vid_caps = src_caps = NULL;
2954
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;
2969
2970 /* Sync any remaining children states with bin's state */
2971 iter = gst_bin_iterate_elements (GST_BIN (self));
2972 iter_done = FALSE;
2973 while (!iter_done) {
2974 GstElement *child = NULL;
2975 GValue data = { 0, };
2976
2977 switch (gst_iterator_next (iter, &data)) {
2978 case GST_ITERATOR_OK:
2979 child = g_value_get_object (&data);
2980 if (!gst_element_sync_state_with_parent (child)) {
2981 g_value_reset (&data);
2982 gst_iterator_free (iter);
2983 goto error_remove_all;
2984 }
2985 g_value_reset (&data);
2986 break;
2987 case GST_ITERATOR_RESYNC:
2988 gst_iterator_resync (iter);
2989 break;
2990 case GST_ITERATOR_ERROR:
2991 iter_done = TRUE;
2992 break;
2993 case GST_ITERATOR_DONE:
2994 iter_done = TRUE;
2995 break;
2996 }
2997 }
2998 gst_iterator_free (iter);
2999
3000 self->reconfiguring = FALSE;
3001 return TRUE;
3002
3003 error_remove_all:
3004 gst_uvc_h264_src_destroy_pipeline (self, FALSE);
3005 error_remove:
3006 gst_element_set_state (self->v4l2_src, GST_STATE_NULL);
3007 gst_bin_remove (GST_BIN (self), self->v4l2_src);
3008
3009 error:
3010 if (self->v4l2_src)
3011 gst_object_unref (self->v4l2_src);
3012 self->v4l2_src = NULL;
3013 self->v4l2_fd = -1;
3014 self->h264_unit_id = 0;
3015
3016 if (self->mjpg_demux)
3017 gst_object_unref (self->mjpg_demux);
3018 self->mjpg_demux = NULL;
3019 if (self->jpeg_dec)
3020 gst_object_unref (self->jpeg_dec);
3021 self->jpeg_dec = NULL;
3022 if (self->vid_colorspace)
3023 gst_object_unref (self->vid_colorspace);
3024 self->vid_colorspace = NULL;
3025 if (self->vf_colorspace)
3026 gst_object_unref (self->vf_colorspace);
3027 self->vf_colorspace = NULL;
3028
3029 if (src_caps)
3030 gst_caps_unref (src_caps);
3031
3032 if (vf_caps)
3033 gst_caps_unref (vf_caps);
3034 if (vid_caps)
3035 gst_caps_unref (vid_caps);
3036
3037 if (vid_pad)
3038 gst_object_unref (vid_pad);
3039 if (vf_pad)
3040 gst_object_unref (vf_pad);
3041
3042 self->reconfiguring = FALSE;
3043 return FALSE;
3044 }
3045
3046 static GstCaps *
gst_uvc_h264_src_getcaps(GstPad * pad,GstObject * parent,GstQuery * query)3047 gst_uvc_h264_src_getcaps (GstPad * pad, GstObject * parent, GstQuery * query)
3048 {
3049 GstUvcH264Src *self = GST_UVC_H264_SRC (parent);
3050 GstCaps *template = NULL;
3051 GstCaps *result = NULL;
3052
3053 if (pad == self->vfsrc)
3054 template = gst_static_pad_template_get_caps (&vfsrc_template);
3055 else if (pad == self->vidsrc)
3056 template = gst_static_pad_template_get_caps (&vidsrc_template);
3057 else
3058 template = gst_caps_new_empty ();
3059
3060 if (self->v4l2_src) {
3061 GstCaps *filter;
3062 GstPad *v4l_pad = gst_element_get_static_pad (self->v4l2_src, "src");
3063 GstCaps *v4l_caps = NULL;
3064 GstCaps *new_caps = NULL;
3065
3066 gst_query_parse_caps (query, &filter);
3067 v4l_caps = gst_pad_query_caps (v4l_pad, filter);
3068 new_caps = gst_uvc_h264_src_transform_caps (self, v4l_caps);
3069
3070 result = gst_caps_intersect (new_caps, template);
3071 gst_object_unref (v4l_pad);
3072 gst_caps_unref (v4l_caps);
3073 gst_caps_unref (new_caps);
3074 gst_caps_unref (template);
3075 } else {
3076 result = template;
3077 }
3078
3079 return result;
3080 }
3081
3082 static gboolean
gst_uvc_h264_src_query(GstPad * pad,GstObject * parent,GstQuery * query)3083 gst_uvc_h264_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
3084 {
3085 gboolean ret;
3086
3087 switch (GST_QUERY_TYPE (query)) {
3088 case GST_QUERY_CAPS:{
3089 GstCaps *caps;
3090
3091 caps = gst_uvc_h264_src_getcaps (pad, parent, query);
3092 gst_query_set_caps_result (query, caps);
3093 gst_caps_unref (caps);
3094 ret = TRUE;
3095 break;
3096 }
3097 default:
3098 ret = gst_pad_query_default (pad, parent, query);
3099 break;
3100 }
3101 return ret;
3102 }
3103
3104
3105 static gboolean
gst_uvc_h264_src_set_mode(GstBaseCameraSrc * bcamsrc,GstCameraBinMode mode)3106 gst_uvc_h264_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode)
3107 {
3108 GstUvcH264Src *self = GST_UVC_H264_SRC (bcamsrc);
3109
3110 GST_DEBUG_OBJECT (self, "set mode to %d", mode);
3111
3112 return (mode == MODE_VIDEO);
3113 }
3114
3115 static gboolean
gst_uvc_h264_src_start_capture(GstBaseCameraSrc * camerasrc)3116 gst_uvc_h264_src_start_capture (GstBaseCameraSrc * camerasrc)
3117 {
3118 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
3119 gboolean ret = TRUE;
3120
3121 GST_DEBUG_OBJECT (self, "start capture");
3122
3123 if (!self->started) {
3124 self->started = TRUE;
3125 if (GST_STATE (self) >= GST_STATE_READY) {
3126 ret = gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3127 if (!ret) {
3128 GST_DEBUG_OBJECT (self, "Could not start capture");
3129 self->started = FALSE;
3130 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3131 }
3132 }
3133 }
3134
3135 return ret;
3136 }
3137
3138 static void
gst_uvc_h264_src_stop_capture(GstBaseCameraSrc * camerasrc)3139 gst_uvc_h264_src_stop_capture (GstBaseCameraSrc * camerasrc)
3140 {
3141 GstUvcH264Src *self = GST_UVC_H264_SRC (camerasrc);
3142
3143 GST_DEBUG_OBJECT (self, "stop capture");
3144
3145 if (self->started) {
3146 self->started = FALSE;
3147 if (GST_STATE (self) >= GST_STATE_READY)
3148 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3149 gst_base_camera_src_finish_capture (camerasrc);
3150 }
3151 }
3152
3153 static void
gst_uvc_h264_src_pad_linking_cb(GstPad * pad,GstPad * peer,gpointer user_data)3154 gst_uvc_h264_src_pad_linking_cb (GstPad * pad,
3155 GstPad * peer, gpointer user_data)
3156 {
3157 GstUvcH264Src *self = GST_UVC_H264_SRC (user_data);
3158 gchar *pad_name = gst_pad_get_name (pad);
3159
3160 GST_DEBUG_OBJECT (self, "Pad %s was (un)linked. Renegotiating", pad_name);
3161 g_free (pad_name);
3162 if (GST_STATE (self) >= GST_STATE_READY)
3163 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3164 }
3165
3166
3167 static GstStateChangeReturn
gst_uvc_h264_src_change_state(GstElement * element,GstStateChange trans)3168 gst_uvc_h264_src_change_state (GstElement * element, GstStateChange trans)
3169 {
3170 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3171 GstUvcH264Src *self = GST_UVC_H264_SRC (element);
3172
3173 switch (trans) {
3174 case GST_STATE_CHANGE_NULL_TO_READY:
3175 if (!ensure_v4l2src (self)) {
3176 ret = GST_STATE_CHANGE_FAILURE;
3177 goto end;
3178 }
3179 gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
3180 break;
3181 case GST_STATE_CHANGE_READY_TO_PAUSED:
3182 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3183 if (!self->v4l2_src)
3184 gst_uvc_h264_src_construct_pipeline (GST_BASE_CAMERA_SRC (self));
3185 break;
3186 default:
3187 break;
3188 }
3189
3190 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans);
3191
3192 if (ret == GST_STATE_CHANGE_FAILURE)
3193 goto end;
3194
3195 switch (trans) {
3196 case GST_STATE_CHANGE_READY_TO_NULL:
3197 gst_uvc_h264_src_destroy_pipeline (self, TRUE);
3198 break;
3199 default:
3200 break;
3201 }
3202
3203
3204 end:
3205 return ret;
3206 }
3207