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