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