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