1 /* GStreamer
2  * Copyright (C) <2006> Eric Jonas <jonas@mit.edu>
3  * Copyright (C) <2006> Antoine Tremblay <hexa00@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  * SECTION:element-dc1394src
23  * @title: dc1394src
24  *
25  * Source for IIDC (Instrumentation & Industrial Digital Camera) firewire
26  * cameras. If several cameras are connected to the system, the desired one
27  * can be selected by its GUID and an optional unit number (most cameras are
28  * single unit and do not require it). The frame size, rate and format are set
29  * from capabilities. Although the IIDC specification includes a raw video
30  * mode, many cameras use mono video modes to capture in Bayer format.
31  * Thus, for each mono video mode supported by a camera, both gray raw and Bayer
32  * corresponding video formats are exposed in the capabilities.
33  * The Bayer pattern is left unspecified.
34  *
35  * ## Example launch lines
36  * |[
37  * gst-launch-1.0 -v dc1394src ! videoconvert ! autovideosink
38  * ]| Capture and display frames from the first camera available in the system.
39  * |[
40  * gst-launch-1.0 dc1394src guid=00074813004DF937 \
41  *     ! "video/x-bayer,format=gbrg,width=1280,height=960,framerate=15/2" \
42  *     ! bayer2rgb ! videoconvert ! autovideosink
43  * ]| Capture and display frames from a specific camera in the desired format.
44  *
45  */
46 
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50 #include "gstdc1394src.h"
51 #include <gst/video/video.h>
52 
53 GST_DEBUG_CATEGORY_STATIC (dc1394_debug);
54 #define GST_CAT_DEFAULT dc1394_debug
55 
56 
57 enum
58 {
59   PROP_0,
60   PROP_CAMERA_GUID,
61   PROP_CAMERA_UNIT,
62   PROP_ISO_SPEED,
63   PROP_DMA_BUFFER_SIZE
64 };
65 
66 
67 #define GST_TYPE_DC1394_ISO_SPEED (gst_dc1394_iso_speed_get_type ())
68 static GType
gst_dc1394_iso_speed_get_type(void)69 gst_dc1394_iso_speed_get_type (void)
70 {
71   static const GEnumValue iso_speeds[] = {
72     {100, "DC1394 ISO speed 100", "100"},
73     {200, "DC1394 ISO speed 200", "200"},
74     {400, "DC1394 ISO speed 400", "400"},
75     {800, "DC1394 ISO speed 800", "800"},
76     {1600, "DC1394 ISO speed 1600", "1600"},
77     {3200, "DC1394 ISO speed 3200", "3200"},
78     {0, NULL, NULL}
79   };
80   static GType type = 0;
81 
82   if (!type) {
83     type = g_enum_register_static ("GstDC1394ISOSpeed", iso_speeds);
84   }
85   return type;
86 }
87 
88 
89 #define gst_dc1394_src_parent_class parent_class
90 G_DEFINE_TYPE (GstDC1394Src, gst_dc1394_src, GST_TYPE_PUSH_SRC);
91 
92 static void gst_dc1394_src_set_property (GObject * object, guint prop_id,
93     const GValue * value, GParamSpec * pspec);
94 static void gst_dc1394_src_get_property (GObject * object, guint prop_id,
95     GValue * value, GParamSpec * pspec);
96 static gboolean gst_dc1394_src_start (GstBaseSrc * bsrc);
97 static gboolean gst_dc1394_src_stop (GstBaseSrc * bsrc);
98 static gboolean gst_dc1394_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps);
99 static GstCaps *gst_dc1394_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter);
100 static GstFlowReturn gst_dc1394_src_create (GstPushSrc * psrc,
101     GstBuffer ** buffer);
102 
103 static void gst_dc1394_src_set_prop_camera_guid (GstDC1394Src * src,
104     const gchar * guid);
105 static gchar *gst_dc1394_src_get_prop_camera_guid (GstDC1394Src * src);
106 static void gst_dc1394_src_set_prop_camera_unit (GstDC1394Src * src, gint unit);
107 static gint gst_dc1394_src_get_prop_camera_unit (GstDC1394Src * src);
108 static void gst_dc1394_src_set_prop_iso_speed (GstDC1394Src * src, guint speed);
109 static guint gst_dc1394_src_get_prop_iso_speed (GstDC1394Src * src);
110 static void gst_dc1394_src_set_prop_dma_buffer_size (GstDC1394Src * src,
111     guint size);
112 static guint gst_dc1394_src_get_prop_dma_buffer_size (GstDC1394Src * src);
113 static gboolean gst_dc1394_src_open_cam (GstDC1394Src * src);
114 static void gst_dc1394_src_close_cam (GstDC1394Src * src);
115 static gboolean gst_dc1394_src_start_cam (GstDC1394Src * src);
116 static gboolean gst_dc1394_src_stop_cam (GstDC1394Src * src);
117 static gboolean gst_dc1394_src_set_cam_caps (GstDC1394Src * src,
118     GstCaps * caps);
119 static GstCaps *gst_dc1394_src_get_cam_caps (GstDC1394Src * src);
120 static GstCaps *gst_dc1394_src_get_all_caps (void);
121 
122 static GstCaps *gst_dc1394_src_build_caps (const dc1394color_codings_t *
123     supported_codings, const dc1394framerates_t * supported_rates,
124     guint width_min, guint width_max, guint width_step, guint height_min,
125     guint height_max, guint height_step);
126 static gboolean gst_dc1394_src_parse_caps (const GstCaps * caps,
127     dc1394color_codings_t * color_codings, dc1394framerate_t * rate,
128     gdouble * rate_decimal, guint * width, guint * height);
129 
130 static void
gst_dc1394_src_class_init(GstDC1394SrcClass * klass)131 gst_dc1394_src_class_init (GstDC1394SrcClass * klass)
132 {
133   GObjectClass *gobject_class;
134   GstElementClass *element_class;
135   GstBaseSrcClass *basesrc_class;
136   GstPushSrcClass *pushsrc_class;
137 
138   gobject_class = G_OBJECT_CLASS (klass);
139   element_class = GST_ELEMENT_CLASS (klass);
140   basesrc_class = GST_BASE_SRC_CLASS (klass);
141   pushsrc_class = GST_PUSH_SRC_CLASS (klass);
142 
143   gobject_class->set_property = gst_dc1394_src_set_property;
144   gobject_class->get_property = gst_dc1394_src_get_property;
145   g_object_class_install_property (gobject_class, PROP_CAMERA_GUID,
146       g_param_spec_string ("guid", "Camera GUID",
147           "The hexadecimal representation of the GUID of the camera"
148           " (use first camera available if null)",
149           NULL,
150           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
151           GST_PARAM_MUTABLE_READY));
152   g_object_class_install_property (gobject_class, PROP_CAMERA_UNIT,
153       g_param_spec_int ("unit", "Camera unit",
154           "The unit number of the camera (-1 if no unit number is used)",
155           -1, G_MAXINT, -1,
156           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
157           GST_PARAM_MUTABLE_READY));
158   g_object_class_install_property (gobject_class, PROP_ISO_SPEED,
159       g_param_spec_enum ("iso", "ISO bandwidth",
160           "The ISO bandwidth in Mbps",
161           GST_TYPE_DC1394_ISO_SPEED, 400,
162           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
163           GST_PARAM_MUTABLE_READY));
164   g_object_class_install_property (gobject_class, PROP_DMA_BUFFER_SIZE,
165       g_param_spec_uint ("dma", "DMA ring buffer size",
166           "The number of frames in the Direct Memory Access ring buffer",
167           1, G_MAXUINT, 10,
168           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
169           GST_PARAM_MUTABLE_READY));
170 
171   gst_element_class_set_static_metadata (element_class,
172       "1394 IIDC Video Source", "Source/Video",
173       "libdc1394 based source for IIDC cameras",
174       "Antoine Tremblay <hexa00@gmail.com>");
175   gst_element_class_add_pad_template (element_class,
176       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
177           gst_dc1394_src_get_all_caps ()));
178 
179   basesrc_class->start = GST_DEBUG_FUNCPTR (gst_dc1394_src_start);
180   basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_dc1394_src_stop);
181   basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_dc1394_src_set_caps);
182   basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_dc1394_src_get_caps);
183 
184   pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_dc1394_src_create);
185 }
186 
187 
188 static void
gst_dc1394_src_init(GstDC1394Src * src)189 gst_dc1394_src_init (GstDC1394Src * src)
190 {
191   src->guid = -1;
192   src->unit = -1;
193   src->iso_speed = DC1394_ISO_SPEED_400;
194   src->dma_buffer_size = 10;
195   src->dc1394 = NULL;
196   src->camera = NULL;
197   src->caps = NULL;
198 
199   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
200   gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
201   gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
202 }
203 
204 
205 static void
gst_dc1394_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)206 gst_dc1394_src_get_property (GObject * object, guint prop_id, GValue * value,
207     GParamSpec * pspec)
208 {
209   GstDC1394Src *src;
210 
211   src = GST_DC1394_SRC (object);
212   switch (prop_id) {
213     case PROP_CAMERA_GUID:
214       g_value_take_string (value, gst_dc1394_src_get_prop_camera_guid (src));
215       break;
216     case PROP_CAMERA_UNIT:
217       g_value_set_int (value, gst_dc1394_src_get_prop_camera_unit (src));
218       break;
219     case PROP_ISO_SPEED:
220       g_value_set_enum (value, gst_dc1394_src_get_prop_iso_speed (src));
221       break;
222     case PROP_DMA_BUFFER_SIZE:
223       g_value_set_uint (value, gst_dc1394_src_get_prop_dma_buffer_size (src));
224       break;
225     default:
226       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
227       break;
228   }
229 }
230 
231 
232 static void
gst_dc1394_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)233 gst_dc1394_src_set_property (GObject * object,
234     guint prop_id, const GValue * value, GParamSpec * pspec)
235 {
236   GstDC1394Src *src;
237 
238   src = GST_DC1394_SRC (object);
239   switch (prop_id) {
240     case PROP_CAMERA_GUID:
241       gst_dc1394_src_set_prop_camera_guid (src, g_value_get_string (value));
242       break;
243     case PROP_CAMERA_UNIT:
244       gst_dc1394_src_set_prop_camera_unit (src, g_value_get_int (value));
245       break;
246     case PROP_ISO_SPEED:
247       gst_dc1394_src_set_prop_iso_speed (src, g_value_get_enum (value));
248       break;
249     case PROP_DMA_BUFFER_SIZE:
250       gst_dc1394_src_set_prop_dma_buffer_size (src, g_value_get_uint (value));
251       break;
252     default:
253       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
254       break;
255   }
256 }
257 
258 
259 static gboolean
gst_dc1394_src_start(GstBaseSrc * bsrc)260 gst_dc1394_src_start (GstBaseSrc * bsrc)
261 {
262   GstDC1394Src *src;
263 
264   src = GST_DC1394_SRC (bsrc);
265   return gst_dc1394_src_open_cam (src);
266 }
267 
268 
269 static gboolean
gst_dc1394_src_stop(GstBaseSrc * bsrc)270 gst_dc1394_src_stop (GstBaseSrc * bsrc)
271 {
272   GstDC1394Src *src;
273 
274   src = GST_DC1394_SRC (bsrc);
275   if (!gst_dc1394_src_stop_cam (src))
276     return FALSE;
277   gst_dc1394_src_close_cam (src);
278   return TRUE;
279 }
280 
281 
282 static GstCaps *
gst_dc1394_src_get_caps(GstBaseSrc * bsrc,GstCaps * filter)283 gst_dc1394_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
284 {
285   GstDC1394Src *src;
286   GstCaps *caps, *ret;
287 
288   src = GST_DC1394_SRC (bsrc);
289   if (src->camera) {
290     caps = gst_dc1394_src_get_cam_caps (src);
291   } else {
292     caps = gst_dc1394_src_get_all_caps ();
293   }
294   if (caps && filter) {
295     ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
296     gst_caps_unref (caps);
297   } else {
298     ret = caps;
299   }
300   return ret;
301 }
302 
303 
304 static gboolean
gst_dc1394_src_set_caps(GstBaseSrc * bsrc,GstCaps * caps)305 gst_dc1394_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
306 {
307   GstDC1394Src *src;
308 
309   src = GST_DC1394_SRC (bsrc);
310   return gst_dc1394_src_stop_cam (src)
311       && gst_dc1394_src_set_cam_caps (src, caps)
312       && gst_dc1394_src_start_cam (src);
313 }
314 
315 
316 static GstFlowReturn
gst_dc1394_src_create(GstPushSrc * psrc,GstBuffer ** obuf)317 gst_dc1394_src_create (GstPushSrc * psrc, GstBuffer ** obuf)
318 {
319   GstDC1394Src *src;
320   GstBuffer *buffer = NULL;
321   dc1394video_frame_t *frame;
322   dc1394error_t ret;
323 
324   src = GST_DC1394_SRC (psrc);
325   ret = dc1394_capture_dequeue (src->camera, DC1394_CAPTURE_POLICY_WAIT,
326       &frame);
327   if (ret != DC1394_SUCCESS) {
328     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
329         ("Could not dequeue frame: %s.", dc1394_error_get_string (ret)));
330     return GST_FLOW_ERROR;
331   }
332   /*
333    * TODO: We could create the buffer by wrapping the image bytes in the frame
334    * (enqueing the frame in the notify function) to save the copy operation.
335    * It will only work if all the buffers are disposed before closing the camera
336    * when state changes from PAUSED to READY.
337    */
338   buffer = gst_buffer_new_allocate (NULL, frame->image_bytes, NULL);
339   gst_buffer_fill (buffer, 0, frame->image, frame->image_bytes);
340   /*
341    * TODO: There is a field timestamp in the frame structure,
342    * It is not sure if it could be used as PTS or DTS:
343    * we are not sure if it comes from a monotonic clock,
344    * and it seems to be left undefined under MS Windows.
345    */
346   ret = dc1394_capture_enqueue (src->camera, frame);
347   if (ret != DC1394_SUCCESS) {
348     GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
349         ("Could not enqueue frame: %s.", dc1394_error_get_string (ret)));
350   }
351   *obuf = buffer;
352   return GST_FLOW_OK;
353 }
354 
355 
356 static void
gst_dc1394_src_set_prop_camera_guid(GstDC1394Src * src,const gchar * guid)357 gst_dc1394_src_set_prop_camera_guid (GstDC1394Src * src, const gchar * guid)
358 {
359   gchar *end;
360 
361   if (!guid) {
362     GST_DEBUG_OBJECT (src, "Null camera GUID value: %s.",
363         "first camera available will be used");
364     src->guid = -1;
365     return;
366   }
367   errno = 0;
368   src->guid = g_ascii_strtoull (guid, &end, 16);
369   if (errno == ERANGE || end == guid || *end != '\0') {
370     GST_ERROR_OBJECT (src, "Invalid camera GUID value: %s.", guid);
371     return;
372   }
373 }
374 
375 
376 static gchar *
gst_dc1394_src_get_prop_camera_guid(GstDC1394Src * src)377 gst_dc1394_src_get_prop_camera_guid (GstDC1394Src * src)
378 {
379   if (src->guid == -1) {
380     return NULL;
381   }
382   return g_strdup_printf ("%016" G_GINT64_MODIFIER "X", src->guid);
383 }
384 
385 
386 static void
gst_dc1394_src_set_prop_camera_unit(GstDC1394Src * src,gint unit)387 gst_dc1394_src_set_prop_camera_unit (GstDC1394Src * src, gint unit)
388 {
389   src->unit = unit;
390 }
391 
392 
393 static gint
gst_dc1394_src_get_prop_camera_unit(GstDC1394Src * src)394 gst_dc1394_src_get_prop_camera_unit (GstDC1394Src * src)
395 {
396   return src->unit;
397 }
398 
399 
400 static void
gst_dc1394_src_set_prop_iso_speed(GstDC1394Src * src,guint speed)401 gst_dc1394_src_set_prop_iso_speed (GstDC1394Src * src, guint speed)
402 {
403   switch (speed) {
404     case 100:
405       src->iso_speed = DC1394_ISO_SPEED_100;
406       break;
407     case 200:
408       src->iso_speed = DC1394_ISO_SPEED_200;
409       break;
410     case 400:
411       src->iso_speed = DC1394_ISO_SPEED_400;
412       break;
413     case 800:
414       src->iso_speed = DC1394_ISO_SPEED_800;
415       break;
416     case 1600:
417       src->iso_speed = DC1394_ISO_SPEED_1600;
418       break;
419     case 3200:
420       src->iso_speed = DC1394_ISO_SPEED_3200;
421       break;
422     default:
423       GST_ERROR_OBJECT (src, "Invalid ISO speed value: %d.", speed);
424   }
425 }
426 
427 
428 static guint
gst_dc1394_src_get_prop_iso_speed(GstDC1394Src * src)429 gst_dc1394_src_get_prop_iso_speed (GstDC1394Src * src)
430 {
431   switch (src->iso_speed) {
432     case DC1394_ISO_SPEED_100:
433       return 100;
434     case DC1394_ISO_SPEED_200:
435       return 200;
436     case DC1394_ISO_SPEED_400:
437       return 400;
438     case DC1394_ISO_SPEED_800:
439       return 800;
440     case DC1394_ISO_SPEED_1600:
441       return 1600;
442     case DC1394_ISO_SPEED_3200:
443       return 3200;
444     default:                   /* never reached */
445       return DC1394_ISO_SPEED_MIN - 1;
446   }
447 }
448 
449 
450 static void
gst_dc1394_src_set_prop_dma_buffer_size(GstDC1394Src * src,guint size)451 gst_dc1394_src_set_prop_dma_buffer_size (GstDC1394Src * src, guint size)
452 {
453   src->dma_buffer_size = size;
454 }
455 
456 
457 static guint
gst_dc1394_src_get_prop_dma_buffer_size(GstDC1394Src * src)458 gst_dc1394_src_get_prop_dma_buffer_size (GstDC1394Src * src)
459 {
460   return src->dma_buffer_size;
461 }
462 
463 
464 static gboolean
gst_dc1394_src_open_cam(GstDC1394Src * src)465 gst_dc1394_src_open_cam (GstDC1394Src * src)
466 {
467   dc1394camera_list_t *cameras;
468   dc1394error_t ret;
469   int number;
470   uint64_t guid;
471   int unit, i;
472 
473   src->dc1394 = dc1394_new ();
474   if (!src->dc1394) {
475     GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
476         ("Could not initialize dc1394 library."));
477     goto error;
478   }
479 
480   number = -1;
481   guid = -1;
482   unit = -1;
483   ret = dc1394_camera_enumerate (src->dc1394, &cameras);
484   if (ret != DC1394_SUCCESS) {
485     GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL),
486         ("Could not enumerate cameras: %s.", dc1394_error_get_string (ret)));
487     goto error;
488   }
489   for (i = 0; i < cameras->num; i++) {
490     GST_DEBUG_OBJECT (src, "Camera %2d is %016" G_GINT64_MODIFIER "X %d.",
491         i, cameras->ids[i].guid, cameras->ids[i].unit);
492     if ((src->guid == -1 || src->guid == cameras->ids[i].guid) &&
493         (src->unit == -1 || src->unit == cameras->ids[i].unit)) {
494       number = i;
495       guid = cameras->ids[i].guid;
496       unit = cameras->ids[i].unit;
497     }
498   }
499   dc1394_camera_free_list (cameras);
500   if (number < 0) {
501     if (src->guid == -1) {
502       GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
503           ("No cameras found."));
504     } else {
505       GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
506           ("Camera %016" G_GINT64_MODIFIER "X %d not found.",
507               src->guid, src->unit));
508     }
509     goto error;
510   }
511 
512   GST_DEBUG_OBJECT (src, "Open camera %016" G_GINT64_MODIFIER "X %d.",
513       guid, unit);
514   src->camera = dc1394_camera_new_unit (src->dc1394, guid, unit);
515   if (!src->camera) {
516     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
517         ("Could not open camera %016" G_GINT64_MODIFIER "X %d.", guid, unit));
518     goto error;
519   }
520   GST_DEBUG_OBJECT (src,
521       "Camera %016" G_GINT64_MODIFIER "X %d opened: \"%s %s\".",
522       src->camera->guid, src->camera->unit,
523       src->camera->vendor, src->camera->model);
524 
525   if (src->iso_speed > DC1394_ISO_SPEED_400) {
526     ret = dc1394_video_set_operation_mode (src->camera,
527         DC1394_OPERATION_MODE_1394B);
528     if (ret != DC1394_SUCCESS) {
529       GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
530           ("Could not set 1394B operation mode: %s.",
531               dc1394_error_get_string (ret)));
532       goto error;
533     }
534   }
535   ret = dc1394_video_set_iso_speed (src->camera, src->iso_speed);
536   if (ret != DC1394_SUCCESS) {
537     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
538         ("Could not set ISO speed %d: %s.", src->iso_speed,
539             dc1394_error_get_string (ret)));
540     goto error;
541   }
542 
543   return TRUE;
544 
545 error:
546   if (src->camera) {
547     dc1394_camera_free (src->camera);
548     src->camera = NULL;
549   }
550   if (src->dc1394) {
551     dc1394_free (src->dc1394);
552     src->dc1394 = NULL;
553   }
554   return FALSE;
555 }
556 
557 
558 static void
gst_dc1394_src_close_cam(GstDC1394Src * src)559 gst_dc1394_src_close_cam (GstDC1394Src * src)
560 {
561   GST_DEBUG_OBJECT (src,
562       "Close camera %016" G_GINT64_MODIFIER "X %d: \"%s %s\".",
563       src->camera->guid, src->camera->unit,
564       src->camera->vendor, src->camera->model);
565   if (src->caps) {
566     gst_caps_unref (src->caps);
567     src->caps = NULL;
568   }
569   dc1394_camera_free (src->camera);
570   src->camera = NULL;
571   dc1394_free (src->dc1394);
572   src->dc1394 = NULL;
573   GST_DEBUG_OBJECT (src, "Camera closed.");
574 }
575 
576 
577 static gboolean
gst_dc1394_src_start_cam(GstDC1394Src * src)578 gst_dc1394_src_start_cam (GstDC1394Src * src)
579 {
580   dc1394error_t ret;
581   dc1394switch_t status;
582   guint trials;
583 
584   GST_DEBUG_OBJECT (src, "Setup capture with a DMA buffer of %d frames",
585       src->dma_buffer_size);
586   ret = dc1394_capture_setup (src->camera, src->dma_buffer_size,
587       DC1394_CAPTURE_FLAGS_DEFAULT);
588   if (ret == DC1394_NO_BANDWIDTH) {
589     GST_DEBUG_OBJECT (src,
590         "Could not setup capture with available ISO bandwidth,"
591         "releasing channels and bandwidth and retrying...");
592     ret = dc1394_iso_release_all (src->camera);
593     if (ret != DC1394_SUCCESS) {
594       GST_ELEMENT_WARNING (src, RESOURCE, FAILED, (NULL),
595           ("Could not release ISO channels and bandwidth: %s",
596               dc1394_error_get_string (ret)));
597     }
598     ret = dc1394_capture_setup (src->camera, src->dma_buffer_size,
599         DC1394_CAPTURE_FLAGS_DEFAULT);
600   }
601   if (ret != DC1394_SUCCESS) {
602     GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
603         ("Could not setup capture: %s", dc1394_error_get_string (ret)));
604     goto error_capture;
605   }
606 
607   /*
608    * TODO: dc1394_capture_setup/stop can start/stop the transmission
609    * when called with DC1394_CAPTURE_FLAGS_AUTO_ISO in the flags.
610    * The repeated trials check is a leftover of the original code,
611    * and might not be needed.
612    */
613   GST_DEBUG_OBJECT (src, "Enable camera transmission.");
614   ret = dc1394_video_set_transmission (src->camera, DC1394_ON);
615   if (ret != DC1394_SUCCESS) {
616     GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
617         ("Could not set transmission status: %s.",
618             dc1394_error_get_string (ret)));
619     goto error_transmission;
620   }
621   ret = dc1394_video_get_transmission (src->camera, &status);
622   for (trials = 10;
623       (trials > 0) && !(ret == DC1394_SUCCESS && status == DC1394_ON);
624       trials--) {
625     GST_DEBUG_OBJECT (src,
626         "Wait for camera to start transmission (%d trials left).", trials);
627     g_usleep (50000);
628     ret = dc1394_video_get_transmission (src->camera, &status);
629   }
630   if (!(ret == DC1394_SUCCESS && status == DC1394_ON)) {
631     GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
632         ("Could not get positive transmission status: %s.",
633             dc1394_error_get_string (ret)));
634     goto error_transmission;
635   }
636 
637   GST_DEBUG_OBJECT (src, "Capture successfully started.");
638   return TRUE;
639 
640 error_transmission:
641   ret = dc1394_capture_stop (src->camera);
642   if (ret != DC1394_SUCCESS) {
643     GST_ELEMENT_WARNING (src, RESOURCE, FAILED, (NULL),
644         ("Could not stop capture: %s.", dc1394_error_get_string (ret)));
645   }
646 error_capture:
647   return FALSE;
648 }
649 
650 
651 static gboolean
gst_dc1394_src_stop_cam(GstDC1394Src * src)652 gst_dc1394_src_stop_cam (GstDC1394Src * src)
653 {
654   dc1394error_t ret;
655   dc1394switch_t status;
656   guint trials;
657 
658   /*
659    * TODO: dc1394_capture_setup/stop can start/stop the transmission
660    * when called with DC1394_CAPTURE_FLAGS_AUTO_ISO in the flags.
661    * The repeated trials check is a leftover of the original code,
662    * and might not be needed.
663    */
664   GST_DEBUG_OBJECT (src, "Disable camera transmission.");
665   ret = dc1394_video_set_transmission (src->camera, DC1394_OFF);
666   if (ret != DC1394_SUCCESS) {
667     GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
668         ("Could not set transmission status: %s.",
669             dc1394_error_get_string (ret)));
670     return FALSE;
671   }
672   ret = dc1394_video_get_transmission (src->camera, &status);
673   for (trials = 10;
674       (trials > 0) && !(ret == DC1394_SUCCESS && status == DC1394_OFF);
675       trials--) {
676     GST_DEBUG_OBJECT (src,
677         "Wait for camera to stop transmission (%d trials left).", trials);
678     g_usleep (50000);
679     ret = dc1394_video_get_transmission (src->camera, &status);
680   }
681   if (!(ret == DC1394_SUCCESS && status == DC1394_OFF)) {
682     GST_WARNING_OBJECT (src,
683         "Could not get negative transmission status: %s.",
684         dc1394_error_get_string (ret));
685   }
686 
687   GST_DEBUG_OBJECT (src, "Clear capture resources.");
688   ret = dc1394_capture_stop (src->camera);
689   if (ret != DC1394_SUCCESS && ret != DC1394_CAPTURE_IS_NOT_SET) {
690     GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
691         ("Could not clear capture: %s.", dc1394_error_get_string (ret)));
692     return FALSE;
693   }
694 
695   switch (ret) {
696     case DC1394_CAPTURE_IS_NOT_SET:
697       GST_DEBUG_OBJECT (src, "Capture was not set up.");
698       break;
699     case DC1394_SUCCESS:
700       GST_DEBUG_OBJECT (src, "Capture successfully stopped.");
701       break;
702     default:
703       break;
704   }
705 
706   return TRUE;
707 }
708 
709 
710 static gboolean
gst_dc1394_src_set_cam_caps(GstDC1394Src * src,GstCaps * caps)711 gst_dc1394_src_set_cam_caps (GstDC1394Src * src, GstCaps * caps)
712 {
713   GstCaps *mode_caps;
714   gboolean ok, supported;
715   dc1394video_modes_t supported_modes;
716   dc1394video_mode_t mode;
717   dc1394color_codings_t supported_codings;
718   dc1394color_coding_t coding;
719   dc1394framerates_t supported_rates;
720   dc1394framerate_t rate;
721   double rate_decimal;
722   uint64_t total_bytes;
723   uint32_t width, width_step, height, height_step;
724   guint m, c;
725 
726   ok = dc1394_video_get_supported_modes (src->camera,
727       &supported_modes) == DC1394_SUCCESS;
728   if (!ok) {
729     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
730         ("Could not get supported modes."));
731     goto error;
732   }
733   supported = FALSE;
734   for (m = 0; m < supported_modes.num && !supported; m++) {
735     mode = supported_modes.modes[m];
736     mode_caps = gst_caps_new_empty ();
737     if (dc1394_is_video_mode_scalable (mode)) {
738       ok &= dc1394_format7_get_color_codings (src->camera, mode,
739           &supported_codings) == DC1394_SUCCESS;
740       ok &= dc1394_format7_get_max_image_size (src->camera, mode,
741           &width, &height) == DC1394_SUCCESS;
742       ok &= dc1394_format7_get_unit_size (src->camera, mode,
743           &width_step, &height_step) == DC1394_SUCCESS;
744     } else {
745       ok &= dc1394_get_color_coding_from_video_mode (src->camera, mode,
746           &coding) == DC1394_SUCCESS;
747       ok &= dc1394_get_image_size_from_video_mode (src->camera, mode,
748           &width, &height) == DC1394_SUCCESS;
749       ok &= dc1394_video_get_supported_framerates (src->camera, mode,
750           &supported_rates) == DC1394_SUCCESS;
751     }
752     if (!ok) {
753       GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
754           ("Could not get video mode %d parameters.", mode));
755     } else if (dc1394_is_video_mode_scalable (mode)) {
756       gst_caps_append (mode_caps,
757           gst_dc1394_src_build_caps (&supported_codings, NULL,
758               width_step, width, width_step, height_step, height, height_step));
759     } else {
760       supported_codings.num = 1;
761       supported_codings.codings[0] = coding;
762       gst_caps_append (mode_caps,
763           gst_dc1394_src_build_caps (&supported_codings, &supported_rates,
764               width, width, 1, height, height, 1));
765     }
766     supported = gst_caps_can_intersect (caps, mode_caps);
767     gst_caps_unref (mode_caps);
768   }
769   ok = supported && gst_dc1394_src_parse_caps (caps, &supported_codings, &rate,
770       &rate_decimal, &width, &height);
771   if (!ok) {
772     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
773         ("Unsupported caps %" GST_PTR_FORMAT, caps));
774     goto error;
775   }
776   GST_DEBUG_OBJECT (src, "Set video mode %d.", mode);
777   ok = dc1394_video_set_mode (src->camera, mode) == DC1394_SUCCESS;
778   if (!ok) {
779     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
780         ("Could not set video mode %d.", mode));
781     goto error;
782   }
783   if (dc1394_is_video_mode_scalable (mode)) {
784     ok = FALSE;
785     for (c = 0; c < supported_codings.num && !ok; c++) {
786       coding = supported_codings.codings[c];
787       GST_DEBUG_OBJECT (src,
788           "Try format7 video mode %d with coding %d, size %d %d, and rate %.4f Hz.",
789           mode, coding, width, height, rate_decimal);
790       ok = (dc1394_format7_set_color_coding (src->camera, mode,
791               coding) == DC1394_SUCCESS)
792           && (dc1394_format7_set_image_size (src->camera, mode,
793               width, height) == DC1394_SUCCESS)
794           && (dc1394_format7_get_total_bytes (src->camera, mode,
795               &total_bytes) == DC1394_SUCCESS)
796           && (dc1394_format7_set_packet_size (src->camera, mode,
797               total_bytes * rate_decimal * 0.000125) == DC1394_SUCCESS);
798     }
799   } else {
800     GST_DEBUG_OBJECT (src, "Set fixed video mode %d rate %.4f Hz (%d).",
801         mode, rate_decimal, rate);
802     ok = dc1394_video_set_framerate (src->camera, rate) == DC1394_SUCCESS;
803   }
804   /* TODO: check feature framerate */
805   if (!ok) {
806     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
807         ("Could not set video mode %d parameters.", mode));
808     goto error;
809   }
810   return TRUE;
811 
812 error:
813   return FALSE;
814 }
815 
816 
817 GstCaps *
gst_dc1394_src_get_cam_caps(GstDC1394Src * src)818 gst_dc1394_src_get_cam_caps (GstDC1394Src * src)
819 {
820   gboolean ok;
821   dc1394video_modes_t supported_modes;
822   dc1394video_mode_t mode;
823   dc1394color_codings_t supported_codings;
824   dc1394color_coding_t coding;
825   dc1394framerates_t supported_rates;
826   uint32_t width, width_step, height, height_step;
827   guint m;
828 
829   if (src->caps)
830     return gst_caps_ref (src->caps);
831 
832   ok = dc1394_video_get_supported_modes (src->camera,
833       &supported_modes) == DC1394_SUCCESS;
834   if (!ok) {
835     GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
836         ("Could not get supported modes."));
837     return NULL;
838   }
839 
840   src->caps = gst_caps_new_empty ();
841   for (m = 0; m < supported_modes.num; m++) {
842     mode = supported_modes.modes[m];
843     if (dc1394_is_video_mode_scalable (mode)) {
844       ok &= dc1394_format7_get_color_codings (src->camera, mode,
845           &supported_codings) == DC1394_SUCCESS;
846       ok &= dc1394_format7_get_max_image_size (src->camera, mode,
847           &width, &height) == DC1394_SUCCESS;
848       ok &= dc1394_format7_get_unit_size (src->camera, mode,
849           &width_step, &height_step) == DC1394_SUCCESS;
850       if (!ok) {
851         GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
852             ("Could not get format7 video mode %d parameters.", mode));
853       } else {
854         gst_caps_append (src->caps,
855             gst_dc1394_src_build_caps (&supported_codings, NULL,
856                 width_step, width, width_step, height_step, height,
857                 height_step));
858       }
859     } else {
860       ok &= dc1394_get_image_size_from_video_mode (src->camera, mode,
861           &width, &height) == DC1394_SUCCESS;
862       ok &= dc1394_video_get_supported_framerates (src->camera, mode,
863           &supported_rates) == DC1394_SUCCESS;
864       ok &= dc1394_get_color_coding_from_video_mode (src->camera, mode,
865           &coding) == DC1394_SUCCESS;
866       if (!ok) {
867         GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
868             ("Could not get fixed video mode %d parameters.", mode));
869       } else {
870         supported_codings.num = 1;
871         supported_codings.codings[0] = coding;
872         gst_caps_append (src->caps,
873             gst_dc1394_src_build_caps (&supported_codings, &supported_rates,
874                 width, width, 1, height, height, 1));
875       }
876     }
877   }
878   GST_DEBUG_OBJECT (src, "Camera capabilities: \"%" GST_PTR_FORMAT "\".",
879       src->caps);
880   return gst_caps_ref (src->caps);
881 }
882 
883 
884 static GstCaps *
gst_dc1394_src_get_all_caps(void)885 gst_dc1394_src_get_all_caps (void)
886 {
887   GstCaps *caps;
888   dc1394color_coding_t coding;
889   dc1394color_codings_t video_codings;
890   uint32_t width, height;
891 
892   const dc1394color_codings_t supported_codings = { 7, {
893           /* DC1394_COLOR_CODING_RGB16S, DC1394_COLOR_CODING_RGB16, */
894           DC1394_COLOR_CODING_RGB8, DC1394_COLOR_CODING_YUV444,
895           DC1394_COLOR_CODING_YUV422, DC1394_COLOR_CODING_YUV411,
896           /* DC1394_COLOR_CODING_RAW16, DC1394_COLOR_CODING_MONO16S */
897           DC1394_COLOR_CODING_MONO16, DC1394_COLOR_CODING_RAW8,
898       DC1394_COLOR_CODING_MONO8}
899   };
900   const dc1394framerates_t all_rates = { 8, {
901           DC1394_FRAMERATE_1_875, DC1394_FRAMERATE_3_75, DC1394_FRAMERATE_7_5,
902           DC1394_FRAMERATE_15, DC1394_FRAMERATE_30, DC1394_FRAMERATE_60,
903       DC1394_FRAMERATE_120, DC1394_FRAMERATE_240}
904   };
905   dc1394video_mode_t mode;
906 
907   caps = gst_caps_new_empty ();
908   /* First caps for fixed video modes */
909   for (mode = DC1394_VIDEO_MODE_MIN; mode < DC1394_VIDEO_MODE_EXIF; mode++) {
910     dc1394_get_image_size_from_video_mode (NULL, mode, &width, &height);
911     dc1394_get_color_coding_from_video_mode (NULL, mode, &coding);
912     video_codings.codings[0] = coding;
913     video_codings.num = 1;
914     gst_caps_append (caps,
915         gst_dc1394_src_build_caps (&video_codings, &all_rates,
916             width, width, 1, height, height, 1));
917   }
918   /* Then caps for Format 7 modes */
919   gst_caps_append (caps,
920       gst_dc1394_src_build_caps (&supported_codings, NULL,
921           1, G_MAXINT, 1, 1, G_MAXINT, 1));
922   return caps;
923 }
924 
925 
926 static GstCaps *
gst_dc1394_src_build_caps(const dc1394color_codings_t * supported_codings,const dc1394framerates_t * supported_rates,uint32_t width_min,uint32_t width_max,uint32_t width_step,uint32_t height_min,uint32_t height_max,uint32_t height_step)927 gst_dc1394_src_build_caps (const dc1394color_codings_t * supported_codings,
928     const dc1394framerates_t * supported_rates,
929     uint32_t width_min, uint32_t width_max, uint32_t width_step,
930     uint32_t height_min, uint32_t height_max, uint32_t height_step)
931 {
932   GstCaps *caps;
933   GstStructure *structure;
934   GstVideoFormat video_format;
935   dc1394color_coding_t coding;
936   dc1394framerate_t rate;
937   GValue format = { 0 };
938   GValue formats = { 0 };
939   GValue width = { 0 };
940   GValue widths = { 0 };
941   GValue height = { 0 };
942   GValue heights = { 0 };
943   GValue framerate = { 0 };
944   GValue framerates = { 0 };
945   guint c, w, h, r;
946 
947   caps = gst_caps_new_empty ();
948   for (c = 0; c < supported_codings->num; c++) {
949     coding = supported_codings->codings[c];
950     switch (coding) {
951       case DC1394_COLOR_CODING_MONO8:
952         video_format = GST_VIDEO_FORMAT_GRAY8;
953         break;
954       case DC1394_COLOR_CODING_YUV411:
955         video_format = GST_VIDEO_FORMAT_IYU1;
956         break;
957       case DC1394_COLOR_CODING_YUV422:
958         video_format = GST_VIDEO_FORMAT_UYVY;
959         break;
960       case DC1394_COLOR_CODING_YUV444:
961         video_format = GST_VIDEO_FORMAT_IYU2;
962         break;
963       case DC1394_COLOR_CODING_RGB8:
964         video_format = GST_VIDEO_FORMAT_RGB;
965         break;
966       case DC1394_COLOR_CODING_RAW8:
967         video_format = GST_VIDEO_FORMAT_UNKNOWN;        /* GST_BAYER_FORMAT_XXXX8 */
968         break;
969       case DC1394_COLOR_CODING_MONO16:
970         video_format = GST_VIDEO_FORMAT_GRAY16_BE;
971         break;
972         /*
973          * The following formats do not exist in Gstreamer:
974          *case DC1394_COLOR_CODING_RGB16: // Unsigned RGB 16 bits per channel
975          *  video_format = GST_VIDEO_FORMAT_RGB48;
976          *  break;
977          *case DC1394_COLOR_CODING_MONO16S: // Signed grayscale 16 bits
978          *  video_format = GST_VIDEO_FORMAT_GRAY16_BE_SIGNED;
979          *  break;
980          *case DC1394_COLOR_CODING_RGB16S: // Signed RGB 16 bits per channel
981          *  video_format = GST_VIDEO_FORMAT_RGB48_SIGNED;
982          *  break;
983          *case DC1394_COLOR_CODING_RAW16: // Raw sensor output (bayer) 16 bits
984          *  video_format = GST_VIDEO_FORMAT_UNKNOWN; // GST_BAYER_FORMAT_XXXX16_BE
985          *  break;
986          */
987       default:
988         video_format = GST_VIDEO_FORMAT_UNKNOWN;
989         GST_DEBUG ("unsupported dc1394 video coding %d", coding);
990     }
991     if (video_format != GST_VIDEO_FORMAT_UNKNOWN) {
992       g_value_init (&formats, G_TYPE_STRING);
993       g_value_set_string (&formats, gst_video_format_to_string (video_format));
994       structure = gst_structure_new_empty ("video/x-raw");
995       gst_structure_set_value (structure, "format", &formats);
996       gst_caps_append_structure (caps, structure);
997       g_value_unset (&formats);
998     }
999     if (coding == DC1394_COLOR_CODING_MONO8 ||
1000         coding == DC1394_COLOR_CODING_RAW8) {
1001       g_value_init (&formats, GST_TYPE_LIST);
1002       g_value_init (&format, G_TYPE_STRING);
1003       g_value_set_static_string (&format, "bggr");
1004       gst_value_list_append_value (&formats, &format);
1005       g_value_set_static_string (&format, "rggb");
1006       gst_value_list_append_value (&formats, &format);
1007       g_value_set_static_string (&format, "grbg");
1008       gst_value_list_append_value (&formats, &format);
1009       g_value_set_static_string (&format, "gbrg");
1010       gst_value_list_append_value (&formats, &format);
1011       structure = gst_structure_new_empty ("video/x-bayer");
1012       gst_structure_set_value (structure, "format", &formats);
1013       gst_caps_append_structure (caps, structure);
1014       g_value_unset (&format);
1015       g_value_unset (&formats);
1016     }
1017   }
1018 
1019   if (width_min == width_max) {
1020     g_value_init (&widths, G_TYPE_INT);
1021     g_value_set_int (&widths, width_min);
1022   } else if (width_step == 1) {
1023     g_value_init (&widths, GST_TYPE_INT_RANGE);
1024     gst_value_set_int_range (&widths, width_min, width_max);
1025   } else {
1026     g_value_init (&widths, GST_TYPE_LIST);
1027     g_value_init (&width, G_TYPE_INT);
1028     for (w = width_min; w <= width_max; w += width_step) {
1029       g_value_set_int (&width, w);
1030       gst_value_list_append_value (&widths, &width);
1031     }
1032     g_value_unset (&width);
1033   }
1034   if (height_min == height_max) {
1035     g_value_init (&heights, G_TYPE_INT);
1036     g_value_set_int (&heights, height_min);
1037   } else if (height_step == 1) {
1038     g_value_init (&heights, GST_TYPE_INT_RANGE);
1039     gst_value_set_int_range (&heights, height_min, height_max);
1040   } else {
1041     g_value_init (&heights, GST_TYPE_LIST);
1042     g_value_init (&height, G_TYPE_INT);
1043     for (h = height_min; h <= height_max; h += height_step) {
1044       g_value_set_int (&height, h);
1045       gst_value_list_append_value (&heights, &height);
1046     }
1047     g_value_unset (&height);
1048   }
1049   gst_caps_set_value (caps, "width", &widths);
1050   gst_caps_set_value (caps, "height", &heights);
1051   g_value_unset (&widths);
1052   g_value_unset (&heights);
1053 
1054   if (supported_rates) {
1055     g_value_init (&framerates, GST_TYPE_LIST);
1056     g_value_init (&framerate, GST_TYPE_FRACTION);
1057     for (r = 0; r < supported_rates->num; r++) {
1058       rate = supported_rates->framerates[r];
1059       switch (rate) {
1060         case DC1394_FRAMERATE_1_875:
1061           gst_value_set_fraction (&framerate, 240, 128);
1062           break;
1063         case DC1394_FRAMERATE_3_75:
1064           gst_value_set_fraction (&framerate, 240, 64);
1065           break;
1066         case DC1394_FRAMERATE_7_5:
1067           gst_value_set_fraction (&framerate, 240, 32);
1068           break;
1069         case DC1394_FRAMERATE_15:
1070           gst_value_set_fraction (&framerate, 240, 16);
1071           break;
1072         case DC1394_FRAMERATE_30:
1073           gst_value_set_fraction (&framerate, 240, 8);
1074           break;
1075         case DC1394_FRAMERATE_60:
1076           gst_value_set_fraction (&framerate, 240, 4);
1077           break;
1078         case DC1394_FRAMERATE_120:
1079           gst_value_set_fraction (&framerate, 240, 2);
1080           break;
1081         case DC1394_FRAMERATE_240:
1082           gst_value_set_fraction (&framerate, 240, 1);
1083           break;
1084       }
1085       gst_value_list_append_value (&framerates, &framerate);
1086     }
1087     g_value_unset (&framerate);
1088   } else {
1089     g_value_init (&framerates, GST_TYPE_FRACTION_RANGE);
1090     gst_value_set_fraction_range_full (&framerates, 1, G_MAXINT, G_MAXINT, 1);
1091   }
1092   gst_caps_set_value (caps, "framerate", &framerates);
1093   g_value_unset (&framerates);
1094   return caps;
1095 }
1096 
1097 
1098 static gboolean
gst_dc1394_src_parse_caps(const GstCaps * caps,dc1394color_codings_t * color_codings,dc1394framerate_t * rate,double * rate_decimal,uint32_t * width,uint32_t * height)1099 gst_dc1394_src_parse_caps (const GstCaps * caps,
1100     dc1394color_codings_t * color_codings,
1101     dc1394framerate_t * rate, double *rate_decimal,
1102     uint32_t * width, uint32_t * height)
1103 {
1104   const GstStructure *structure;
1105   const gchar *format;
1106   gint w, h, num, den;
1107   gdouble dec;
1108 
1109   structure = gst_caps_get_structure (caps, 0);
1110   if (!structure)
1111     goto error;
1112 
1113   if (!gst_structure_get_int (structure, "width", &w)
1114       || !gst_structure_get_int (structure, "height", &h))
1115     goto error;
1116 
1117   *width = w;
1118   *height = h;
1119 
1120   if (!gst_structure_get_fraction (structure, "framerate", &num, &den))
1121     goto error;
1122 
1123   if (gst_util_fraction_compare (num, den, 240, 128) <= 0) {
1124     *rate = DC1394_FRAMERATE_1_875;
1125   } else if (gst_util_fraction_compare (num, den, 240, 64) <= 0) {
1126     *rate = DC1394_FRAMERATE_3_75;
1127   } else if (gst_util_fraction_compare (num, den, 240, 32) <= 0) {
1128     *rate = DC1394_FRAMERATE_7_5;
1129   } else if (gst_util_fraction_compare (num, den, 240, 16) <= 0) {
1130     *rate = DC1394_FRAMERATE_15;
1131   } else if (gst_util_fraction_compare (num, den, 240, 8) <= 0) {
1132     *rate = DC1394_FRAMERATE_30;
1133   } else if (gst_util_fraction_compare (num, den, 240, 4) <= 0) {
1134     *rate = DC1394_FRAMERATE_60;
1135   } else if (gst_util_fraction_compare (num, den, 240, 2) <= 0) {
1136     *rate = DC1394_FRAMERATE_120;
1137   } else if (gst_util_fraction_compare (num, den, 240, 1) <= 0) {
1138     *rate = DC1394_FRAMERATE_240;
1139   } else {
1140     *rate = DC1394_FRAMERATE_240;
1141   }
1142 
1143   gst_util_fraction_to_double (num, den, &dec);
1144   *rate_decimal = dec;
1145 
1146   if (gst_structure_has_name (structure, "video/x-raw")) {
1147     format = gst_structure_get_string (structure, "format");
1148     switch (gst_video_format_from_string (format)) {
1149       case GST_VIDEO_FORMAT_GRAY8:
1150         color_codings->num = 1;
1151         color_codings->codings[0] = DC1394_COLOR_CODING_MONO8;
1152         break;
1153       case GST_VIDEO_FORMAT_IYU1:
1154         color_codings->num = 1;
1155         color_codings->codings[0] = DC1394_COLOR_CODING_YUV411;
1156         break;
1157       case GST_VIDEO_FORMAT_UYVY:
1158         color_codings->num = 1;
1159         color_codings->codings[0] = DC1394_COLOR_CODING_YUV422;
1160         break;
1161       case GST_VIDEO_FORMAT_IYU2:
1162         color_codings->num = 1;
1163         color_codings->codings[0] = DC1394_COLOR_CODING_YUV444;
1164         break;
1165       case GST_VIDEO_FORMAT_RGB:
1166         color_codings->num = 1;
1167         color_codings->codings[0] = DC1394_COLOR_CODING_RGB8;
1168         break;
1169       case GST_VIDEO_FORMAT_GRAY16_BE:
1170         color_codings->num = 1;
1171         color_codings->codings[0] = DC1394_COLOR_CODING_MONO16;
1172         break;
1173         /*
1174          * The following formats do not exist in Gstreamer:
1175          *case GST_VIDEO_FORMAT_RGB48: // Unsigned RGB format 16 bits per channel
1176          *  color_codings->num = 1
1177          *  color_codings->codings[0] = DC1394_COLOR_CODING_RGB16;
1178          *  break;
1179          *case GST_VIDEO_FORMAT_GRAY16_BE_SIGNED: // Signed grayscale format 16 bits
1180          *  color_codings->num = 1
1181          *  color_codings->codings[0] = DC1394_COLOR_CODING_MONO16S;
1182          *  break;
1183          *case GST_VIDEO_FORMAT_RGB48_SIGNED: // Signed RGB format 16 bits per channel
1184          *  color_codings->num = 1
1185          *  color_codings->codings[0] = DC1394_COLOR_CODING_RGB16S;
1186          *  break;
1187          */
1188       default:
1189         GST_ERROR ("unsupported raw video format %s", format);
1190         goto error;
1191     }
1192   } else if (gst_structure_has_name (structure, "video/x-bayer")) {
1193     /*
1194      * The following formats do not exist in Gstreamer:
1195      *switch (gst_bayer_format_from_string(format)) {
1196      *  case GST_BAYER_FORMAT_BGGR8:
1197      *  case GST_BAYER_FORMAT_GBRG8:
1198      *  case GST_BAYER_FORMAT_GRBG8:
1199      *  case GST_BAYER_FORMAT_BGGR8:
1200      *    *coding = DC1394_COLOR_CODING_RAW8;
1201      *    break;
1202      *  case GST_BAYER_FORMAT_BGGR16_BE:
1203      *  case GST_BAYER_FORMAT_GBRG16_BE:
1204      *  case GST_BAYER_FORMAT_GRBG16_BE:
1205      *  case GST_BAYER_FORMAT_BGGR16_BE:
1206      *    *coding = DC1394_COLOR_CODING_RAW16;
1207      *    break;
1208      *  default:
1209      *    GST_ERROR("unsupported raw video format %s", format);
1210      *    goto error;
1211      *}
1212      */
1213     color_codings->num = 2;
1214     color_codings->codings[0] = DC1394_COLOR_CODING_RAW8;
1215     color_codings->codings[1] = DC1394_COLOR_CODING_MONO8;
1216   } else {
1217     goto error;
1218   }
1219 
1220   return TRUE;
1221 
1222 error:
1223   return FALSE;
1224 }
1225 
1226 
1227 static gboolean
plugin_init(GstPlugin * plugin)1228 plugin_init (GstPlugin * plugin)
1229 {
1230   GST_DEBUG_CATEGORY_INIT (dc1394_debug, "dc1394", 0, "DC1394 interface");
1231 
1232   return gst_element_register (plugin, "dc1394src", GST_RANK_NONE,
1233       GST_TYPE_DC1394_SRC);
1234 }
1235 
1236 
1237 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1238     GST_VERSION_MINOR,
1239     dc1394,
1240     "1394 IIDC video source",
1241     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
1242