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