b5c2cb06b8bb63c1923f76e7f9281237206305e4
[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 "gstv4l2videodec.h"
27 #include "v4l2_calls.h"
28
29 #include <string.h>
30 #include <gst/gst-i18n-plugin.h>
31
32 #define DEFAULT_PROP_DEVICE "/dev/video8"
33
34 GST_DEBUG_CATEGORY_STATIC (gst_v4l2_video_dec_debug);
35 #define GST_CAT_DEFAULT gst_v4l2_video_dec_debug
36
37 #define parent_class gst_v4l2_video_dec_parent_class
38 G_DEFINE_TYPE (GstV4l2VideoDec, gst_v4l2_video_dec, GST_TYPE_VIDEO_DECODER);
39
40 static gboolean gst_v4l2_video_dec_flush (GstVideoDecoder * decoder);
41
42 enum
43 {
44   PROP_0,
45   V4L2_STD_OBJECT_PROPS,
46   PROP_CAPTURE_IO_MODE,
47 };
48
49 static void
50 gst_v4l2_video_dec_set_property (GObject * object,
51     guint prop_id, const GValue * value, GParamSpec * pspec)
52 {
53   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
54
55   switch (prop_id) {
56       /* Split IO mode so output is configure through 'io-mode' and capture
57        * through 'capture-io-mode' */
58     case PROP_IO_MODE:
59       gst_v4l2_object_set_property_helper (self->v4l2output, prop_id, value,
60           pspec);
61       break;
62     case PROP_CAPTURE_IO_MODE:
63       gst_v4l2_object_set_property_helper (self->v4l2capture, prop_id, value,
64           pspec);
65       break;
66
67     case PROP_DEVICE:
68       gst_v4l2_object_set_property_helper (self->v4l2output, prop_id, value,
69           pspec);
70       gst_v4l2_object_set_property_helper (self->v4l2capture, prop_id, value,
71           pspec);
72       break;
73
74       /* By default, only set on output */
75     default:
76       if (!gst_v4l2_object_set_property_helper (self->v4l2output,
77               prop_id, value, pspec)) {
78         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
79       }
80       break;
81   }
82 }
83
84 static void
85 gst_v4l2_video_dec_get_property (GObject * object,
86     guint prop_id, GValue * value, GParamSpec * pspec)
87 {
88   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
89
90   switch (prop_id) {
91     case PROP_IO_MODE:
92       gst_v4l2_object_get_property_helper (self->v4l2output, prop_id, value,
93           pspec);
94       break;
95     case PROP_CAPTURE_IO_MODE:
96       gst_v4l2_object_get_property_helper (self->v4l2output, PROP_IO_MODE,
97           value, pspec);
98       break;
99
100       /* By default read from output */
101     default:
102       if (!gst_v4l2_object_get_property_helper (self->v4l2output,
103               prop_id, value, pspec)) {
104         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105       }
106       break;
107   }
108 }
109
110 static gboolean
111 gst_v4l2_video_dec_open (GstVideoDecoder * decoder)
112 {
113   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
114
115   GST_DEBUG_OBJECT (self, "Opening");
116
117   if (!gst_v4l2_object_open (self->v4l2output))
118     goto failure;
119
120   if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
121     goto failure;
122
123   self->probed_sinkcaps = gst_v4l2_object_get_caps (self->v4l2output,
124       gst_v4l2_object_get_codec_caps ());
125
126   if (gst_caps_is_empty (self->probed_sinkcaps))
127     goto no_encoded_format;
128
129   self->probed_srccaps = gst_v4l2_object_get_caps (self->v4l2capture,
130       gst_v4l2_object_get_raw_caps ());
131
132   if (gst_caps_is_empty (self->probed_srccaps))
133     goto no_raw_format;
134
135   return TRUE;
136
137 no_encoded_format:
138   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
139       (_("Encoder on device %s has no supported input format"),
140           self->v4l2output->videodev), (NULL));
141   goto failure;
142
143
144 no_raw_format:
145   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
146       (_("Encoder on device %s has no supported output format"),
147           self->v4l2output->videodev), (NULL));
148   goto failure;
149
150 failure:
151   if (GST_V4L2_IS_OPEN (self->v4l2output))
152     gst_v4l2_object_close (self->v4l2output);
153
154   if (GST_V4L2_IS_OPEN (self->v4l2capture))
155     gst_v4l2_object_close (self->v4l2capture);
156
157   gst_caps_replace (&self->probed_srccaps, NULL);
158   gst_caps_replace (&self->probed_sinkcaps, NULL);
159
160   return FALSE;
161 }
162
163 static gboolean
164 gst_v4l2_video_dec_close (GstVideoDecoder * decoder)
165 {
166   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
167
168   GST_DEBUG_OBJECT (self, "Closing");
169
170   gst_v4l2_object_close (self->v4l2output);
171   gst_v4l2_object_close (self->v4l2capture);
172   gst_caps_replace (&self->probed_srccaps, NULL);
173   gst_caps_replace (&self->probed_sinkcaps, NULL);
174
175   return TRUE;
176 }
177
178 static gboolean
179 gst_v4l2_video_dec_start (GstVideoDecoder * decoder)
180 {
181   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
182
183   GST_DEBUG_OBJECT (self, "Starting");
184
185   gst_v4l2_object_unlock (self->v4l2output);
186   g_atomic_int_set (&self->active, TRUE);
187   self->output_flow = GST_FLOW_OK;
188
189   return TRUE;
190 }
191
192 static gboolean
193 gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
194 {
195   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
196
197   GST_DEBUG_OBJECT (self, "Stopping");
198
199   /* Should have been flushed already */
200   g_assert (g_atomic_int_get (&self->active) == FALSE);
201   g_assert (g_atomic_int_get (&self->processing) == FALSE);
202
203   gst_v4l2_object_stop (self->v4l2output);
204   gst_v4l2_object_stop (self->v4l2capture);
205
206   if (self->input_state) {
207     gst_video_codec_state_unref (self->input_state);
208     self->input_state = NULL;
209   }
210
211   GST_DEBUG_OBJECT (self, "Stopped");
212
213   return TRUE;
214 }
215
216 static gboolean
217 gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
218     GstVideoCodecState * state)
219 {
220   gboolean ret = TRUE;
221   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
222
223   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
224
225   if (self->input_state) {
226     if (gst_v4l2_object_caps_equal (self->v4l2output, state->caps)) {
227       GST_DEBUG_OBJECT (self, "Compatible caps");
228       goto done;
229     }
230     gst_video_codec_state_unref (self->input_state);
231
232     /* FIXME we probably need to do more work if pools are active */
233   }
234
235   ret = gst_v4l2_object_set_format (self->v4l2output, state->caps);
236
237   if (ret)
238     self->input_state = gst_video_codec_state_ref (state);
239
240 done:
241   return ret;
242 }
243
244 static gboolean
245 gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
246 {
247   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
248
249   GST_DEBUG_OBJECT (self, "Flushing");
250
251   /* Wait for capture thread to stop */
252   gst_pad_stop_task (decoder->srcpad);
253   self->output_flow = GST_FLOW_OK;
254
255   gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output->pool));
256   gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture->pool));
257
258   /* Output will remain flushing until new frame comes in */
259   gst_v4l2_object_unlock_stop (self->v4l2capture);
260
261   return TRUE;
262 }
263
264 static gboolean
265 gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
266 {
267   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
268 }
269
270 static GstFlowReturn
271 gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
272 {
273   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
274   GstFlowReturn ret = GST_FLOW_OK;
275   GstBuffer *buffer;
276
277   if (!self->input_state)
278     goto done;
279
280   GST_DEBUG_OBJECT (self, "Finishing decoding");
281
282   /* Keep queuing empty buffers until the processing thread has stopped,
283    * _pool_process() will return FLUSHING when that happened */
284   GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
285   while (ret == GST_FLOW_OK) {
286     buffer = gst_buffer_new ();
287     ret =
288         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
289             v4l2output->pool), buffer);
290     gst_buffer_unref (buffer);
291   }
292   GST_VIDEO_DECODER_STREAM_LOCK (decoder);
293
294   g_assert (g_atomic_int_get (&self->processing) == FALSE);
295
296   if (ret == GST_FLOW_FLUSHING)
297     ret = self->output_flow;
298
299   GST_DEBUG_OBJECT (decoder, "Done draining buffers");
300
301 done:
302   return ret;
303 }
304
305 static GstVideoCodecFrame *
306 gst_v4l2_video_dec_get_oldest_frame (GstVideoDecoder * decoder)
307 {
308   GstVideoCodecFrame *frame = NULL;
309   GList *frames, *l;
310   gint count = 0;
311
312   frames = gst_video_decoder_get_frames (decoder);
313
314   for (l = frames; l != NULL; l = l->next) {
315     GstVideoCodecFrame *f = l->data;
316
317     if (!frame || frame->pts > f->pts)
318       frame = f;
319
320     count++;
321   }
322
323   if (frame) {
324     GST_LOG_OBJECT (decoder,
325         "Oldest frame is %d %" GST_TIME_FORMAT " and %d frames left",
326         frame->system_frame_number, GST_TIME_ARGS (frame->pts), count - 1);
327     gst_video_codec_frame_ref (frame);
328   }
329
330   g_list_free_full (frames, (GDestroyNotify) gst_video_codec_frame_unref);
331
332   return frame;
333 }
334
335 static void
336 gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
337 {
338   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
339   GstBufferPool *pool;
340   GstVideoCodecFrame *frame;
341   GstBuffer *buffer = NULL;
342   GstFlowReturn ret;
343
344   GST_LOG_OBJECT (decoder, "Allocate output buffer");
345
346   /* We cannot use the base class allotate helper since it taking the internal
347    * stream lock. we know that the acquire may need to poll until more frames
348    * comes in and holding this lock would prevent that.
349    */
350   pool = gst_video_decoder_get_buffer_pool (decoder);
351   ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
352   g_object_unref (pool);
353
354   if (ret != GST_FLOW_OK)
355     goto beach;
356
357   /* Check if buffer isn't the last one */
358   if (gst_buffer_get_size (buffer) == 0)
359     goto beach;
360
361   GST_LOG_OBJECT (decoder, "Process output buffer");
362   ret =
363       gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
364           v4l2capture->pool), buffer);
365
366   if (ret != GST_FLOW_OK)
367     goto beach;
368
369   frame = gst_v4l2_video_dec_get_oldest_frame (decoder);
370
371   if (frame) {
372     frame->output_buffer = buffer;
373     buffer = NULL;
374     ret = gst_video_decoder_finish_frame (decoder, frame);
375
376     if (ret != GST_FLOW_OK)
377       goto beach;
378   } else {
379     GST_WARNING_OBJECT (decoder, "Decoder is producing too many buffers");
380     gst_buffer_unref (buffer);
381   }
382
383   return;
384
385 beach:
386   GST_DEBUG_OBJECT (decoder, "Leaving output thread");
387
388   gst_buffer_replace (&buffer, NULL);
389   self->output_flow = ret;
390   g_atomic_int_set (&self->processing, FALSE);
391   gst_v4l2_object_unlock (self->v4l2output);
392   gst_pad_pause_task (decoder->srcpad);
393 }
394
395 static GstFlowReturn
396 gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
397     GstVideoCodecFrame * frame)
398 {
399   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
400   GstFlowReturn ret = GST_FLOW_OK;
401
402   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
403
404   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
405     goto flushing;
406
407   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2output))) {
408     if (!gst_v4l2_object_set_format (self->v4l2output, self->input_state->caps))
409       goto not_negotiated;
410   }
411
412   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
413     GstVideoInfo info;
414     GstVideoCodecState *output_state;
415     GstBuffer *codec_data;
416
417     GST_DEBUG_OBJECT (self, "Sending header");
418
419     codec_data = self->input_state->codec_data;
420
421     /* We are running in byte-stream mode, so we don't know the headers, but
422      * we need to send something, otherwise the decoder will refuse to
423      * intialize.
424      */
425     if (codec_data) {
426       gst_buffer_ref (codec_data);
427     } else {
428       codec_data = frame->input_buffer;
429       frame->input_buffer = NULL;
430     }
431
432     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
433     gst_v4l2_object_unlock_stop (self->v4l2output);
434     ret =
435         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
436             pool), codec_data);
437     gst_v4l2_object_unlock (self->v4l2output);
438     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
439
440     gst_buffer_unref (codec_data);
441
442     if (!gst_v4l2_object_setup_format (self->v4l2capture, &info, &self->align))
443       goto not_negotiated;
444
445     output_state = gst_video_decoder_set_output_state (decoder,
446         info.finfo->format, info.width, info.height, self->input_state);
447
448     /* Copy the rest of the information, there might be more in the future */
449     output_state->info.interlace_mode = info.interlace_mode;
450     gst_video_codec_state_unref (output_state);
451
452     if (!gst_video_decoder_negotiate (decoder)) {
453       if (GST_PAD_IS_FLUSHING (decoder->srcpad))
454         goto flushing;
455       else
456         goto not_negotiated;
457     }
458   }
459
460   if (g_atomic_int_get (&self->processing) == FALSE) {
461     /* It possible that the processing thread stopped due to an error */
462     if (self->output_flow != GST_FLOW_OK) {
463       GST_DEBUG_OBJECT (self, "Processing loop stopped with error, leaving");
464       ret = self->output_flow;
465       goto drop;
466     }
467
468     GST_DEBUG_OBJECT (self, "Starting decoding thread");
469
470     /* Enable processing input */
471     gst_v4l2_object_unlock_stop (self->v4l2output);
472
473     /* Start the processing task, when it quits, the task will disable input
474      * processing to unlock input if draining, or prevent potential block */
475     g_atomic_int_set (&self->processing, TRUE);
476     gst_pad_start_task (decoder->srcpad,
477         (GstTaskFunction) gst_v4l2_video_dec_loop, self, NULL);
478   }
479
480   if (frame->input_buffer) {
481     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
482     ret =
483         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
484             pool), frame->input_buffer);
485     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
486
487     if (ret == GST_FLOW_FLUSHING) {
488       if (g_atomic_int_get (&self->processing) == FALSE)
489         ret = self->output_flow;
490     }
491
492     /* No need to keep input arround */
493     gst_buffer_replace (&frame->input_buffer, NULL);
494   }
495
496   gst_video_codec_frame_unref (frame);
497   return ret;
498
499   /* ERRORS */
500 not_negotiated:
501   {
502     GST_ERROR_OBJECT (self, "not negotiated");
503     ret = GST_FLOW_NOT_NEGOTIATED;
504     goto drop;
505   }
506 flushing:
507   {
508     ret = GST_FLOW_FLUSHING;
509     goto drop;
510   }
511 drop:
512   {
513     gst_video_decoder_drop_frame (decoder, frame);
514     return ret;
515   }
516 }
517
518 static gboolean
519 gst_v4l2_video_dec_decide_allocation (GstVideoDecoder * decoder,
520     GstQuery * query)
521 {
522   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
523   GstClockTime latency;
524   gboolean ret = FALSE;
525
526   if (gst_v4l2_object_decide_allocation (self->v4l2capture, query))
527     ret = GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
528         query);
529
530   latency = self->v4l2capture->min_buffers_for_capture *
531       self->v4l2capture->duration;
532   gst_video_decoder_set_latency (decoder, latency, latency);
533
534   return ret;
535 }
536
537 static gboolean
538 gst_v4l2_video_dec_src_query (GstVideoDecoder * decoder, GstQuery * query)
539 {
540   gboolean ret = TRUE;
541   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
542
543   switch (GST_QUERY_TYPE (query)) {
544     case GST_QUERY_CAPS:{
545       GstCaps *filter, *result = NULL;
546       gst_query_parse_caps (query, &filter);
547
548       if (self->probed_srccaps)
549         result = gst_caps_ref (self->probed_srccaps);
550       else
551         result = gst_v4l2_object_get_raw_caps ();
552
553       if (filter) {
554         GstCaps *tmp = result;
555         result =
556             gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
557         gst_caps_unref (tmp);
558       }
559
560       GST_DEBUG_OBJECT (self, "Returning src caps %" GST_PTR_FORMAT, result);
561
562       gst_query_set_caps_result (query, result);
563       gst_caps_unref (result);
564       break;
565     }
566
567     default:
568       ret = GST_VIDEO_DECODER_CLASS (parent_class)->src_query (decoder, query);
569       break;
570   }
571
572   return ret;
573 }
574
575 static gboolean
576 gst_v4l2_video_dec_sink_query (GstVideoDecoder * decoder, GstQuery * query)
577 {
578   gboolean ret = TRUE;
579   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
580
581   switch (GST_QUERY_TYPE (query)) {
582     case GST_QUERY_CAPS:{
583       GstCaps *filter, *result = NULL;
584       gst_query_parse_caps (query, &filter);
585
586       if (self->probed_sinkcaps)
587         result = gst_caps_ref (self->probed_sinkcaps);
588       else
589         result = gst_v4l2_object_get_codec_caps ();
590
591       if (filter) {
592         GstCaps *tmp = result;
593         result =
594             gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
595         gst_caps_unref (tmp);
596       }
597
598       GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, result);
599
600       gst_query_set_caps_result (query, result);
601       gst_caps_unref (result);
602       break;
603     }
604
605     default:
606       ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_query (decoder, query);
607       break;
608   }
609
610   return ret;
611 }
612
613 static gboolean
614 gst_v4l2_video_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
615 {
616   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
617
618   switch (GST_EVENT_TYPE (event)) {
619     case GST_EVENT_FLUSH_START:
620       gst_v4l2_object_unlock (self->v4l2output);
621       gst_v4l2_object_unlock (self->v4l2capture);
622     default:
623       break;
624   }
625
626   return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
627 }
628
629 static GstStateChangeReturn
630 gst_v4l2_video_dec_change_state (GstElement * element,
631     GstStateChange transition)
632 {
633   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (element);
634
635   if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
636     g_atomic_int_set (&self->active, FALSE);
637     gst_v4l2_object_unlock (self->v4l2output);
638     gst_v4l2_object_unlock (self->v4l2capture);
639   }
640
641   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
642 }
643
644 static void
645 gst_v4l2_video_dec_dispose (GObject * object)
646 {
647   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
648
649   gst_caps_replace (&self->probed_sinkcaps, NULL);
650   gst_caps_replace (&self->probed_srccaps, NULL);
651
652   G_OBJECT_CLASS (parent_class)->dispose (object);
653 }
654
655 static void
656 gst_v4l2_video_dec_finalize (GObject * object)
657 {
658   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (object);
659
660   gst_v4l2_object_destroy (self->v4l2capture);
661   gst_v4l2_object_destroy (self->v4l2output);
662
663   G_OBJECT_CLASS (parent_class)->finalize (object);
664 }
665
666 static void
667 gst_v4l2_video_dec_init (GstV4l2VideoDec * self)
668 {
669   GstVideoDecoder *decoder = (GstVideoDecoder *) self;
670
671   gst_video_decoder_set_packetized (decoder, TRUE);
672
673   self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
674       V4L2_BUF_TYPE_VIDEO_OUTPUT, DEFAULT_PROP_DEVICE,
675       gst_v4l2_get_output, gst_v4l2_set_output, NULL);
676   self->v4l2output->no_initial_format = TRUE;
677   self->v4l2output->keep_aspect = FALSE;
678
679   self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
680       V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
681       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
682   self->v4l2capture->no_initial_format = TRUE;
683   self->v4l2output->keep_aspect = FALSE;
684
685   g_object_set (self, "device", DEFAULT_PROP_DEVICE, NULL);
686 }
687
688 static void
689 gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
690 {
691   GstElementClass *element_class;
692   GObjectClass *gobject_class;
693   GstVideoDecoderClass *video_decoder_class;
694
695   element_class = (GstElementClass *) klass;
696   gobject_class = (GObjectClass *) klass;
697   video_decoder_class = (GstVideoDecoderClass *) klass;
698
699   gst_element_class_add_pad_template (element_class,
700       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
701           gst_v4l2_object_get_codec_caps ()));
702
703   gst_element_class_add_pad_template (element_class,
704       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
705           gst_v4l2_object_get_raw_caps ()));
706
707   gst_element_class_set_static_metadata (element_class,
708       "V4L2 Video Decoder",
709       "Codec/Decoder/Video",
710       "Decode video streams via V4L2 API",
711       "Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>");
712
713   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_dispose);
714   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_finalize);
715   gobject_class->set_property =
716       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_set_property);
717   gobject_class->get_property =
718       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_get_property);
719
720   video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_open);
721   video_decoder_class->close = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_close);
722   video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_start);
723   video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_stop);
724   video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_finish);
725   video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_flush);
726   video_decoder_class->set_format =
727       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_set_format);
728   video_decoder_class->negotiate =
729       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_negotiate);
730   video_decoder_class->decide_allocation =
731       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_decide_allocation);
732   /* FIXME propose_allocation or not ? */
733   video_decoder_class->handle_frame =
734       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_handle_frame);
735   video_decoder_class->sink_query =
736       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_sink_query);
737   video_decoder_class->src_query =
738       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_src_query);
739   video_decoder_class->sink_event =
740       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_sink_event);
741
742   element_class->change_state =
743       GST_DEBUG_FUNCPTR (gst_v4l2_video_dec_change_state);
744
745
746   gst_v4l2_object_install_properties_helper (gobject_class,
747       DEFAULT_PROP_DEVICE);
748
749   /**
750    * GstV4l2VideoDec:capture-io-mode
751    *
752    * Capture IO Mode
753    */
754   g_object_class_install_property (gobject_class, PROP_IO_MODE,
755       g_param_spec_enum ("capture-io-mode", "Capture IO mode",
756           "Capture I/O mode",
757           GST_TYPE_V4L2_IO_MODE, GST_V4L2_IO_AUTO,
758           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
759
760   GST_DEBUG_CATEGORY_INIT (gst_v4l2_video_dec_debug, "v4l2videodec", 0,
761       "V4L2 Video Decoder");
762 }