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