v4l2videodec: Create one element per device
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2videodec.c
1 /*
2  * Copyright (C) 2014 Collabora Ltd.
3  *     Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <string.h>
31
32 #include "gstv4l2videodec.h"
33 #include "v4l2_calls.h"
34
35 #include <string.h>
36 #include <gst/gst-i18n-plugin.h>
37
38 #define DEFAULT_PROP_DEVICE "/dev/video0"
39
40 #define V4L2_VIDEO_DEC_QUARK \
41         g_quark_from_static_string("gst-v4l2-video-dec-info")
42
43 GST_DEBUG_CATEGORY_STATIC (gst_v4l2_video_dec_debug);
44 #define GST_CAT_DEFAULT gst_v4l2_video_dec_debug
45
46 static gboolean gst_v4l2_video_dec_flush (GstVideoDecoder * decoder);
47
48 typedef struct
49 {
50   gchar *device;
51   GstCaps *sink_caps;
52   GstCaps *src_caps;
53 } Gstv4l2VideoDecQData;
54
55 enum
56 {
57   PROP_0,
58   V4L2_STD_OBJECT_PROPS,
59   PROP_CAPTURE_IO_MODE,
60 };
61
62 static void gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass);
63 static void gst_v4l2_video_dec_init (GstV4l2VideoDec * self, gpointer g_class);
64 static void gst_v4l2_video_dec_base_init (gpointer g_class);
65
66 static GstVideoDecoderClass *parent_class = NULL;
67
68 GType
69 gst_v4l2_video_dec_get_type (void)
70 {
71   static volatile gsize type = 0;
72
73   if (g_once_init_enter (&type)) {
74     GType _type;
75     static const GTypeInfo info = {
76       sizeof (GstV4l2VideoDecClass),
77       gst_v4l2_video_dec_base_init,
78       NULL,
79       (GClassInitFunc) gst_v4l2_video_dec_class_init,
80       NULL,
81       NULL,
82       sizeof (GstV4l2VideoDec),
83       0,
84       (GInstanceInitFunc) gst_v4l2_video_dec_init,
85       NULL
86     };
87
88     _type = g_type_register_static (GST_TYPE_VIDEO_DECODER, "GstV4l2VideoDec",
89         &info, 0);
90
91     g_once_init_leave (&type, _type);
92   }
93   return type;
94 }
95
96 static void
97 gst_v4l2_video_dec_set_property (GObject * object,
98     guint prop_id, const GValue * value, GParamSpec * pspec)
99 {
100   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
101
102   switch (prop_id) {
103       /* Split IO mode so output is configure through 'io-mode' and capture
104        * through 'capture-io-mode' */
105     case PROP_IO_MODE:
106       gst_v4l2_object_set_property_helper (self->v4l2output, prop_id, value,
107           pspec);
108       break;
109     case PROP_CAPTURE_IO_MODE:
110       gst_v4l2_object_set_property_helper (self->v4l2capture, prop_id, value,
111           pspec);
112       break;
113
114     case PROP_DEVICE:
115       gst_v4l2_object_set_property_helper (self->v4l2output, prop_id, value,
116           pspec);
117       gst_v4l2_object_set_property_helper (self->v4l2capture, prop_id, value,
118           pspec);
119       break;
120
121       /* By default, only set on output */
122     default:
123       if (!gst_v4l2_object_set_property_helper (self->v4l2output,
124               prop_id, value, pspec)) {
125         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
126       }
127       break;
128   }
129 }
130
131 static void
132 gst_v4l2_video_dec_get_property (GObject * object,
133     guint prop_id, GValue * value, GParamSpec * pspec)
134 {
135   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
136
137   switch (prop_id) {
138     case PROP_IO_MODE:
139       gst_v4l2_object_get_property_helper (self->v4l2output, prop_id, value,
140           pspec);
141       break;
142     case PROP_CAPTURE_IO_MODE:
143       gst_v4l2_object_get_property_helper (self->v4l2output, PROP_IO_MODE,
144           value, pspec);
145       break;
146
147       /* By default read from output */
148     default:
149       if (!gst_v4l2_object_get_property_helper (self->v4l2output,
150               prop_id, value, pspec)) {
151         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
152       }
153       break;
154   }
155 }
156
157 static gboolean
158 gst_v4l2_video_dec_open (GstVideoDecoder * decoder)
159 {
160   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
161
162   GST_DEBUG_OBJECT (self, "Opening");
163
164   if (!gst_v4l2_object_open (self->v4l2output))
165     goto failure;
166
167   if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
168     goto failure;
169
170   self->probed_sinkcaps = gst_v4l2_object_get_caps (self->v4l2output,
171       gst_v4l2_object_get_codec_caps ());
172
173   if (gst_caps_is_empty (self->probed_sinkcaps))
174     goto no_encoded_format;
175
176   self->probed_srccaps = gst_v4l2_object_get_caps (self->v4l2capture,
177       gst_v4l2_object_get_raw_caps ());
178
179   if (gst_caps_is_empty (self->probed_srccaps))
180     goto no_raw_format;
181
182   return TRUE;
183
184 no_encoded_format:
185   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
186       (_("Encoder on device %s has no supported input format"),
187           self->v4l2output->videodev), (NULL));
188   goto failure;
189
190
191 no_raw_format:
192   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
193       (_("Encoder on device %s has no supported output format"),
194           self->v4l2output->videodev), (NULL));
195   goto failure;
196
197 failure:
198   if (GST_V4L2_IS_OPEN (self->v4l2output))
199     gst_v4l2_object_close (self->v4l2output);
200
201   if (GST_V4L2_IS_OPEN (self->v4l2capture))
202     gst_v4l2_object_close (self->v4l2capture);
203
204   gst_caps_replace (&self->probed_srccaps, NULL);
205   gst_caps_replace (&self->probed_sinkcaps, NULL);
206
207   return FALSE;
208 }
209
210 static gboolean
211 gst_v4l2_video_dec_close (GstVideoDecoder * decoder)
212 {
213   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
214
215   GST_DEBUG_OBJECT (self, "Closing");
216
217   gst_v4l2_object_close (self->v4l2output);
218   gst_v4l2_object_close (self->v4l2capture);
219   gst_caps_replace (&self->probed_srccaps, NULL);
220   gst_caps_replace (&self->probed_sinkcaps, NULL);
221
222   return TRUE;
223 }
224
225 static gboolean
226 gst_v4l2_video_dec_start (GstVideoDecoder * decoder)
227 {
228   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
229
230   GST_DEBUG_OBJECT (self, "Starting");
231
232   gst_v4l2_object_unlock (self->v4l2output);
233   g_atomic_int_set (&self->active, TRUE);
234   self->output_flow = GST_FLOW_OK;
235
236   return TRUE;
237 }
238
239 static gboolean
240 gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
241 {
242   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
243
244   GST_DEBUG_OBJECT (self, "Stopping");
245
246   /* Should have been flushed already */
247   g_assert (g_atomic_int_get (&self->active) == FALSE);
248   g_assert (g_atomic_int_get (&self->processing) == FALSE);
249
250   gst_v4l2_object_stop (self->v4l2output);
251   gst_v4l2_object_stop (self->v4l2capture);
252
253   if (self->input_state) {
254     gst_video_codec_state_unref (self->input_state);
255     self->input_state = NULL;
256   }
257
258   GST_DEBUG_OBJECT (self, "Stopped");
259
260   return TRUE;
261 }
262
263 static gboolean
264 gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
265     GstVideoCodecState * state)
266 {
267   gboolean ret = TRUE;
268   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
269
270   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
271
272   if (self->input_state) {
273     if (gst_v4l2_object_caps_equal (self->v4l2output, state->caps)) {
274       GST_DEBUG_OBJECT (self, "Compatible caps");
275       goto done;
276     }
277     gst_video_codec_state_unref (self->input_state);
278
279     /* FIXME we probably need to do more work if pools are active */
280   }
281
282   ret = gst_v4l2_object_set_format (self->v4l2output, state->caps);
283
284   if (ret)
285     self->input_state = gst_video_codec_state_ref (state);
286
287 done:
288   return ret;
289 }
290
291 static gboolean
292 gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
293 {
294   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
295
296   GST_DEBUG_OBJECT (self, "Flushing");
297
298   /* Wait for capture thread to stop */
299   gst_pad_stop_task (decoder->srcpad);
300   self->output_flow = GST_FLOW_OK;
301
302   gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output->pool));
303   gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture->pool));
304
305   /* Output will remain flushing until new frame comes in */
306   gst_v4l2_object_unlock_stop (self->v4l2capture);
307
308   return TRUE;
309 }
310
311 static gboolean
312 gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
313 {
314   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
315 }
316
317 static GstFlowReturn
318 gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
319 {
320   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
321   GstFlowReturn ret = GST_FLOW_OK;
322   GstBuffer *buffer;
323
324   if (!self->input_state)
325     goto done;
326
327   GST_DEBUG_OBJECT (self, "Finishing decoding");
328
329   /* Keep queuing empty buffers until the processing thread has stopped,
330    * _pool_process() will return FLUSHING when that happened */
331   GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
332   while (ret == GST_FLOW_OK) {
333     buffer = gst_buffer_new ();
334     ret =
335         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
336             v4l2output->pool), buffer);
337     gst_buffer_unref (buffer);
338   }
339   GST_VIDEO_DECODER_STREAM_LOCK (decoder);
340
341   g_assert (g_atomic_int_get (&self->processing) == FALSE);
342
343   if (ret == GST_FLOW_FLUSHING)
344     ret = self->output_flow;
345
346   GST_DEBUG_OBJECT (decoder, "Done draining buffers");
347
348 done:
349   return ret;
350 }
351
352 static GstVideoCodecFrame *
353 gst_v4l2_video_dec_get_oldest_frame (GstVideoDecoder * decoder)
354 {
355   GstVideoCodecFrame *frame = NULL;
356   GList *frames, *l;
357   gint count = 0;
358
359   frames = gst_video_decoder_get_frames (decoder);
360
361   for (l = frames; l != NULL; l = l->next) {
362     GstVideoCodecFrame *f = l->data;
363
364     if (!frame || frame->pts > f->pts)
365       frame = f;
366
367     count++;
368   }
369
370   if (frame) {
371     GST_LOG_OBJECT (decoder,
372         "Oldest frame is %d %" GST_TIME_FORMAT " and %d frames left",
373         frame->system_frame_number, GST_TIME_ARGS (frame->pts), count - 1);
374     gst_video_codec_frame_ref (frame);
375   }
376
377   g_list_free_full (frames, (GDestroyNotify) gst_video_codec_frame_unref);
378
379   return frame;
380 }
381
382 static void
383 gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
384 {
385   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
386   GstBufferPool *pool;
387   GstVideoCodecFrame *frame;
388   GstBuffer *buffer = NULL;
389   GstFlowReturn ret;
390
391   GST_LOG_OBJECT (decoder, "Allocate output buffer");
392
393   /* We cannot use the base class allotate helper since it taking the internal
394    * stream lock. we know that the acquire may need to poll until more frames
395    * comes in and holding this lock would prevent that.
396    */
397   pool = gst_video_decoder_get_buffer_pool (decoder);
398   ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
399   g_object_unref (pool);
400
401   if (ret != GST_FLOW_OK)
402     goto beach;
403
404   /* Check if buffer isn't the last one */
405   if (gst_buffer_get_size (buffer) == 0)
406     goto beach;
407
408   GST_LOG_OBJECT (decoder, "Process output buffer");
409   ret =
410       gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
411           v4l2capture->pool), buffer);
412
413   if (ret != GST_FLOW_OK)
414     goto beach;
415
416   frame = gst_v4l2_video_dec_get_oldest_frame (decoder);
417
418   if (frame) {
419     frame->output_buffer = buffer;
420     buffer = NULL;
421     ret = gst_video_decoder_finish_frame (decoder, frame);
422
423     if (ret != GST_FLOW_OK)
424       goto beach;
425   } else {
426     GST_WARNING_OBJECT (decoder, "Decoder is producing too many buffers");
427     gst_buffer_unref (buffer);
428   }
429
430   return;
431
432 beach:
433   GST_DEBUG_OBJECT (decoder, "Leaving output thread");
434
435   gst_buffer_replace (&buffer, NULL);
436   self->output_flow = ret;
437   g_atomic_int_set (&self->processing, FALSE);
438   gst_v4l2_object_unlock (self->v4l2output);
439   gst_pad_pause_task (decoder->srcpad);
440 }
441
442 static GstFlowReturn
443 gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
444     GstVideoCodecFrame * frame)
445 {
446   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
447   GstFlowReturn ret = GST_FLOW_OK;
448
449   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
450
451   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
452     goto flushing;
453
454   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2output))) {
455     if (!gst_v4l2_object_set_format (self->v4l2output, self->input_state->caps))
456       goto not_negotiated;
457   }
458
459   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
460     GstVideoInfo info;
461     GstVideoCodecState *output_state;
462     GstBuffer *codec_data;
463
464     GST_DEBUG_OBJECT (self, "Sending header");
465
466     codec_data = self->input_state->codec_data;
467
468     /* We are running in byte-stream mode, so we don't know the headers, but
469      * we need to send something, otherwise the decoder will refuse to
470      * intialize.
471      */
472     if (codec_data) {
473       gst_buffer_ref (codec_data);
474     } else {
475       codec_data = frame->input_buffer;
476       frame->input_buffer = NULL;
477     }
478
479     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
480     gst_v4l2_object_unlock_stop (self->v4l2output);
481     ret =
482         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
483             v4l2output->pool), codec_data);
484     gst_v4l2_object_unlock (self->v4l2output);
485     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
486
487     gst_buffer_unref (codec_data);
488
489     if (!gst_v4l2_object_setup_format (self->v4l2capture, &info, &self->align))
490       goto not_negotiated;
491
492     output_state = gst_video_decoder_set_output_state (decoder,
493         info.finfo->format, info.width, info.height, self->input_state);
494
495     /* Copy the rest of the information, there might be more in the future */
496     output_state->info.interlace_mode = info.interlace_mode;
497     gst_video_codec_state_unref (output_state);
498
499     if (!gst_video_decoder_negotiate (decoder)) {
500       if (GST_PAD_IS_FLUSHING (decoder->srcpad))
501         goto flushing;
502       else
503         goto not_negotiated;
504     }
505   }
506
507   if (g_atomic_int_get (&self->processing) == FALSE) {
508     /* It possible that the processing thread stopped due to an error */
509     if (self->output_flow != GST_FLOW_OK) {
510       GST_DEBUG_OBJECT (self, "Processing loop stopped with error, leaving");
511       ret = self->output_flow;
512       goto drop;
513     }
514
515     GST_DEBUG_OBJECT (self, "Starting decoding thread");
516
517     /* Enable processing input */
518     gst_v4l2_object_unlock_stop (self->v4l2output);
519
520     /* Start the processing task, when it quits, the task will disable input
521      * processing to unlock input if draining, or prevent potential block */
522     g_atomic_int_set (&self->processing, TRUE);
523     gst_pad_start_task (decoder->srcpad,
524         (GstTaskFunction) gst_v4l2_video_dec_loop, self, NULL);
525   }
526
527   if (frame->input_buffer) {
528     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
529     ret =
530         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
531             pool), frame->input_buffer);
532     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
533
534     if (ret == GST_FLOW_FLUSHING) {
535       if (g_atomic_int_get (&self->processing) == FALSE)
536         ret = self->output_flow;
537     }
538
539     /* No need to keep input arround */
540     gst_buffer_replace (&frame->input_buffer, NULL);
541   }
542
543   gst_video_codec_frame_unref (frame);
544   return ret;
545
546   /* ERRORS */
547 not_negotiated:
548   {
549     GST_ERROR_OBJECT (self, "not negotiated");
550     ret = GST_FLOW_NOT_NEGOTIATED;
551     goto drop;
552   }
553 flushing:
554   {
555     ret = GST_FLOW_FLUSHING;
556     goto drop;
557   }
558 drop:
559   {
560     gst_video_decoder_drop_frame (decoder, frame);
561     return ret;
562   }
563 }
564
565 static gboolean
566 gst_v4l2_video_dec_decide_allocation (GstVideoDecoder * decoder,
567     GstQuery * query)
568 {
569   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
570   GstClockTime latency;
571   gboolean ret = FALSE;
572
573   if (gst_v4l2_object_decide_allocation (self->v4l2capture, query))
574     ret = GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
575         query);
576
577   latency = self->v4l2capture->min_buffers_for_capture *
578       self->v4l2capture->duration;
579   gst_video_decoder_set_latency (decoder, latency, latency);
580
581   return ret;
582 }
583
584 static gboolean
585 gst_v4l2_video_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
586 {
587   gboolean ret = TRUE;
588   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
589
590   switch (GST_QUERY_TYPE (query)) {
591     case GST_QUERY_CAPS:{
592       GstCaps *filter, *result = NULL;
593       gst_query_parse_caps (query, &filter);
594
595       if (self->probed_srccaps)
596         result = gst_caps_ref (self->probed_srccaps);
597       else
598         result = gst_v4l2_object_get_raw_caps ();
599
600       if (filter) {
601         GstCaps *tmp = result;
602         result =
603             gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
604         gst_caps_unref (tmp);
605       }
606
607       GST_DEBUG_OBJECT (self, "Returning src caps %" GST_PTR_FORMAT, result);
608
609       gst_query_set_caps_result (query, result);
610       gst_caps_unref (result);
611       break;
612     }
613
614     default:
615       ret = GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
616       break;
617   }
618
619   return ret;
620 }
621
622 static gboolean
623 gst_v4l2_video_dec_sink_query (GstVideoDecoder * decoder, GstQuery * query)
624 {
625   gboolean ret = TRUE;
626   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
627
628   switch (GST_QUERY_TYPE (query)) {
629     case GST_QUERY_CAPS:{
630       GstCaps *filter, *result = NULL;
631       gst_query_parse_caps (query, &filter);
632
633       if (self->probed_sinkcaps)
634         result = gst_caps_ref (self->probed_sinkcaps);
635       else
636         result = gst_v4l2_object_get_codec_caps ();
637
638       if (filter) {
639         GstCaps *tmp = result;
640         result =
641             gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
642         gst_caps_unref (tmp);
643       }
644
645       GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, result);
646
647       gst_query_set_caps_result (query, result);
648       gst_caps_unref (result);
649       break;
650     }
651
652     default:
653       ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_query (decoder, query);
654       break;
655   }
656
657   return ret;
658 }
659
660 static gboolean
661 gst_v4l2_video_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
662 {
663   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
664
665   switch (GST_EVENT_TYPE (event)) {
666     case GST_EVENT_FLUSH_START:
667       gst_v4l2_object_unlock (self->v4l2output);
668       gst_v4l2_object_unlock (self->v4l2capture);
669     default:
670       break;
671   }
672
673   return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
674 }
675
676 static GstStateChangeReturn
677 gst_v4l2_video_dec_change_state (GstElement * element,
678     GstStateChange transition)
679 {
680   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (element);
681
682   if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
683     g_atomic_int_set (&self->active, FALSE);
684     gst_v4l2_object_unlock (self->v4l2output);
685     gst_v4l2_object_unlock (self->v4l2capture);
686   }
687
688   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
689 }
690
691 static void
692 gst_v4l2_video_dec_dispose (GObject * object)
693 {
694   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
695
696   gst_caps_replace (&self->probed_sinkcaps, NULL);
697   gst_caps_replace (&self->probed_srccaps, NULL);
698
699   G_OBJECT_CLASS (parent_class)->dispose (object);
700 }
701
702 static void
703 gst_v4l2_video_dec_finalize (GObject * object)
704 {
705   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
706
707   gst_v4l2_object_destroy (self->v4l2capture);
708   gst_v4l2_object_destroy (self->v4l2output);
709
710   G_OBJECT_CLASS (parent_class)->finalize (object);
711 }
712
713 static void
714 gst_v4l2_video_dec_base_init (gpointer g_class)
715 {
716   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
717   Gstv4l2VideoDecQData *qdata;
718   GstPadTemplate *templ;
719
720   qdata = g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), V4L2_VIDEO_DEC_QUARK);
721   if (!qdata)
722     return;
723
724   templ =
725       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
726       qdata->sink_caps);
727   gst_element_class_add_pad_template (element_class, templ);
728
729   templ =
730       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
731       qdata->src_caps);
732   gst_element_class_add_pad_template (element_class, templ);
733 }
734
735 static void
736 gst_v4l2_video_dec_init (GstV4l2VideoDec * self, gpointer g_class)
737 {
738   GstVideoDecoder *decoder = (GstVideoDecoder *) self;
739   Gstv4l2VideoDecQData *qdata;
740
741   qdata = g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), V4L2_VIDEO_DEC_QUARK);
742   if (!qdata)
743     return;
744
745   gst_video_decoder_set_packetized (decoder, TRUE);
746
747   self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
748       V4L2_BUF_TYPE_VIDEO_OUTPUT, qdata->device,
749       gst_v4l2_get_output, gst_v4l2_set_output, NULL);
750   self->v4l2output->no_initial_format = TRUE;
751   self->v4l2output->keep_aspect = FALSE;
752
753   self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
754       V4L2_BUF_TYPE_VIDEO_CAPTURE, qdata->device,
755       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
756   self->v4l2capture->no_initial_format = TRUE;
757   self->v4l2output->keep_aspect = FALSE;
758
759   g_object_set (self, "device", qdata->device, NULL);
760 }
761
762 static void
763 gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
764 {
765   GstElementClass *element_class;
766   GObjectClass *gobject_class;
767   GstVideoDecoderClass *video_decoder_class;
768
769   parent_class = g_type_class_peek_parent (klass);
770
771   element_class = (GstElementClass *) klass;
772   gobject_class = (GObjectClass *) klass;
773   video_decoder_class = (GstVideoDecoderClass *) klass;
774
775   gst_element_class_set_static_metadata (element_class,
776       "V4L2 Video Decoder",
777       "Codec/Decoder/Video",
778       "Decode video streams via V4L2 API",
779       "Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>");
780
781   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_dispose);
782   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_finalize);
783   gobject_class->set_property =
784       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_set_property);
785   gobject_class->get_property =
786       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_get_property);
787
788   video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_open);
789   video_decoder_class->close = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_close);
790   video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_start);
791   video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_stop);
792   video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_finish);
793   video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_flush);
794   video_decoder_class->set_format =
795       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_set_format);
796   video_decoder_class->negotiate =
797       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_negotiate);
798   video_decoder_class->decide_allocation =
799       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_decide_allocation);
800   /* FIXME propose_allocation or not ? */
801   video_decoder_class->handle_frame =
802       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_handle_frame);
803   video_decoder_class->sink_query =
804       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_sink_query);
805   video_decoder_class->src_query =
806       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_src_query);
807   video_decoder_class->sink_event =
808       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_sink_event);
809
810   element_class->change_state =
811       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_change_state);
812
813   gst_v4l2_object_install_properties_helper (gobject_class,
814       DEFAULT_PROP_DEVICE);
815
816   /**
817    * GstV4l2VideoDec:capture-io-mode
818    *
819    * Capture IO Mode
820    */
821   g_object_class_install_property (gobject_class, PROP_IO_MODE,
822       g_param_spec_enum ("capture-io-mode", "Capture IO mode",
823           "Capture I/O mode",
824           GST_TYPE_V4L2_IO_MODE, GST_V4L2_IO_AUTO,
825           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
826 }
827
828 /* Probing functions */
829 static GstCaps *
830 gst_v4l2_video_dec_probe_caps (gchar * device, gint video_fd,
831     enum v4l2_buf_type type, GstCaps * filter)
832 {
833   gint n;
834   struct v4l2_fmtdesc format;
835   GstCaps *ret, *caps;
836
837   GST_DEBUG ("Getting %s format enumerations", device);
838   caps = gst_caps_new_empty ();
839
840   for (n = 0;; n++) {
841     GstStructure *template;
842
843     format.index = n;
844     format.type = type;
845
846     if (v4l2_ioctl (video_fd, VIDIOC_ENUM_FMT, &format) < 0)
847       break;                    /* end of enumeration */
848
849     GST_LOG ("index:       %u", format.index);
850     GST_LOG ("type:        %d", format.type);
851     GST_LOG ("flags:       %08x", format.flags);
852     GST_LOG ("description: '%s'", format.description);
853     GST_LOG ("pixelformat: %" GST_FOURCC_FORMAT,
854         GST_FOURCC_ARGS (format.pixelformat));
855
856     template = gst_v4l2_object_v4l2fourcc_to_structure (format.pixelformat);
857
858     if (template)
859       gst_caps_append_structure (caps, template);
860   }
861
862   caps = gst_caps_simplify (caps);
863
864   ret = gst_caps_intersect (filter, caps);
865   gst_caps_unref (filter);
866   gst_caps_unref (caps);
867
868   return ret;
869 }
870
871 gboolean
872 gst_v4l2_video_dec_register (GstPlugin * plugin)
873 {
874   gint i = -1;
875   gchar *device = NULL;
876
877   GST_DEBUG_CATEGORY_INIT (gst_v4l2_video_dec_debug, "v4l2videodec", 0,
878       "V4L2 Video Decoder");
879
880   while (TRUE) {
881     GstCaps *src_caps, *sink_caps;
882     gint video_fd;
883
884     g_free (device);
885     device = g_strdup_printf ("/dev/video%d", ++i);
886
887     if (!g_file_test (device, G_FILE_TEST_EXISTS))
888       break;
889
890     video_fd = open (device, O_RDWR);
891     if (video_fd == -1) {
892       GST_WARNING ("Failed to open %s", device);
893       continue;
894     }
895
896     /* get sink supported format (no MPLANE for codec) */
897     sink_caps = gst_v4l2_video_dec_probe_caps (device, video_fd,
898         V4L2_BUF_TYPE_VIDEO_OUTPUT, gst_v4l2_object_get_codec_caps ());
899
900     /* get src supported format */
901     src_caps = gst_caps_merge (gst_v4l2_video_dec_probe_caps (device, video_fd,
902             V4L2_BUF_TYPE_VIDEO_CAPTURE, gst_v4l2_object_get_raw_caps ()),
903         gst_v4l2_video_dec_probe_caps (device, video_fd,
904             V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
905             gst_v4l2_object_get_raw_caps ()));
906
907     if (!gst_caps_is_empty (sink_caps) && !gst_caps_is_empty (src_caps)) {
908       GTypeQuery type_query;
909       GTypeInfo type_info = { 0, };
910       GType type, subtype;
911       gchar *type_name;
912       Gstv4l2VideoDecQData *qdata;
913
914       type = gst_v4l2_video_dec_get_type ();
915       g_type_query (type, &type_query);
916       memset (&type_info, 0, sizeof (type_info));
917       type_info.class_size = type_query.class_size;
918       type_info.instance_size = type_query.instance_size;
919
920       type_name = g_strdup_printf ("v4l2video%ddec", i);
921       subtype = g_type_register_static (type, type_name, &type_info, 0);
922
923       qdata = g_new0 (Gstv4l2VideoDecQData, 1);
924       qdata->device = g_strdup (device);
925       qdata->sink_caps = gst_caps_ref (sink_caps);
926       qdata->src_caps = gst_caps_ref (src_caps);
927
928       g_type_set_qdata (subtype, V4L2_VIDEO_DEC_QUARK, qdata);
929
930       gst_element_register (plugin, type_name, GST_RANK_PRIMARY + 1, subtype);
931
932       g_free (type_name);
933     }
934
935     close (video_fd);
936     gst_caps_unref (src_caps);
937     gst_caps_unref (sink_caps);
938   }
939
940   g_free (device);
941
942   return TRUE;
943 }