rtsp-server: fix memory leak
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / sys / v4l2 / gstv4l2videoenc.c
1 /*
2  * Copyright (C) 2014-2017 SUMOMO Computer Association
3  *     Authors Ayaka <ayaka@soulik.info>
4  * Copyright (C) 2017 Collabora Ltd.
5  *     Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <string.h>
33
34 #include "gstv4l2object.h"
35 #include "gstv4l2videoenc.h"
36
37 #include <string.h>
38 #include <glib/gi18n-lib.h>
39
40 GST_DEBUG_CATEGORY_STATIC (gst_v4l2_video_enc_debug);
41 #define GST_CAT_DEFAULT gst_v4l2_video_enc_debug
42
43 typedef struct
44 {
45   gchar *device;
46   GstCaps *sink_caps;
47   GstCaps *src_caps;
48   const GstV4l2Codec *codec;
49 } GstV4l2VideoEncCData;
50
51 enum
52 {
53   PROP_0,
54   V4L2_STD_OBJECT_PROPS,
55 };
56
57 #define gst_v4l2_video_enc_parent_class parent_class
58 G_DEFINE_ABSTRACT_TYPE (GstV4l2VideoEnc, gst_v4l2_video_enc,
59     GST_TYPE_VIDEO_ENCODER);
60
61 static void
62 gst_v4l2_video_enc_set_property (GObject * object,
63     guint prop_id, const GValue * value, GParamSpec * pspec)
64 {
65   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
66
67   switch (prop_id) {
68     case PROP_CAPTURE_IO_MODE:
69       if (!gst_v4l2_object_set_property_helper (self->v4l2capture,
70               prop_id, value, pspec)) {
71         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
72       }
73       break;
74
75       /* By default, only set on output */
76     default:
77       if (!gst_v4l2_object_set_property_helper (self->v4l2output,
78               prop_id, value, pspec)) {
79         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
80       }
81       break;
82   }
83 }
84
85 static void
86 gst_v4l2_video_enc_get_property (GObject * object,
87     guint prop_id, GValue * value, GParamSpec * pspec)
88 {
89   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
90
91   switch (prop_id) {
92     case PROP_CAPTURE_IO_MODE:
93       if (!gst_v4l2_object_get_property_helper (self->v4l2capture,
94               prop_id, value, pspec)) {
95         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
96       }
97       break;
98
99       /* By default read from output */
100     default:
101       if (!gst_v4l2_object_get_property_helper (self->v4l2output,
102               prop_id, value, pspec)) {
103         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
104       }
105       break;
106   }
107 }
108
109 static gboolean
110 gst_v4l2_video_enc_open (GstVideoEncoder * encoder)
111 {
112   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
113   GstV4l2Error error = GST_V4L2_ERROR_INIT;
114   GstCaps *codec_caps;
115
116   GST_DEBUG_OBJECT (self, "Opening");
117
118   if (!gst_v4l2_object_open (self->v4l2output, &error))
119     goto failure;
120
121   if (!gst_v4l2_object_open_shared (self->v4l2capture, self->v4l2output))
122     goto failure;
123
124   self->probed_sinkcaps = gst_v4l2_object_probe_caps (self->v4l2output,
125       gst_v4l2_object_get_raw_caps ());
126
127   if (gst_caps_is_empty (self->probed_sinkcaps))
128     goto no_raw_format;
129
130   codec_caps = gst_pad_get_pad_template_caps (encoder->srcpad);
131   self->probed_srccaps = gst_v4l2_object_probe_caps (self->v4l2capture,
132       codec_caps);
133   gst_caps_unref (codec_caps);
134
135   if (gst_caps_is_empty (self->probed_srccaps))
136     goto no_encoded_format;
137
138   return TRUE;
139
140 no_encoded_format:
141   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
142       (_("Encoder on device %s has no supported output format"),
143           self->v4l2output->videodev), (NULL));
144   goto failure;
145
146
147 no_raw_format:
148   GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
149       (_("Encoder on device %s has no supported input format"),
150           self->v4l2output->videodev), (NULL));
151   goto failure;
152
153 failure:
154   if (GST_V4L2_IS_OPEN (self->v4l2output))
155     gst_v4l2_object_close (self->v4l2output);
156
157   if (GST_V4L2_IS_OPEN (self->v4l2capture))
158     gst_v4l2_object_close (self->v4l2capture);
159
160   gst_caps_replace (&self->probed_srccaps, NULL);
161   gst_caps_replace (&self->probed_sinkcaps, NULL);
162
163   gst_v4l2_error (self, &error);
164
165   return FALSE;
166 }
167
168 static gboolean
169 gst_v4l2_video_enc_close (GstVideoEncoder * encoder)
170 {
171   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
172
173   GST_DEBUG_OBJECT (self, "Closing");
174
175   gst_v4l2_object_close (self->v4l2output);
176   gst_v4l2_object_close (self->v4l2capture);
177   gst_caps_replace (&self->probed_srccaps, NULL);
178   gst_caps_replace (&self->probed_sinkcaps, NULL);
179
180   return TRUE;
181 }
182
183 static gboolean
184 gst_v4l2_video_enc_start (GstVideoEncoder * encoder)
185 {
186   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
187
188   GST_DEBUG_OBJECT (self, "Starting");
189
190   gst_v4l2_object_unlock (self->v4l2output);
191   g_atomic_int_set (&self->active, TRUE);
192   self->output_flow = GST_FLOW_OK;
193
194   return TRUE;
195 }
196
197 static gboolean
198 gst_v4l2_video_enc_stop (GstVideoEncoder * encoder)
199 {
200   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
201
202   GST_DEBUG_OBJECT (self, "Stopping");
203
204   gst_v4l2_object_unlock (self->v4l2output);
205   gst_v4l2_object_unlock (self->v4l2capture);
206
207   /* Wait for capture thread to stop */
208   gst_pad_stop_task (encoder->srcpad);
209
210   GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
211   self->output_flow = GST_FLOW_OK;
212   GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
213
214   /* Should have been flushed already */
215   g_assert (g_atomic_int_get (&self->active) == FALSE);
216   g_assert (g_atomic_int_get (&self->processing) == FALSE);
217
218   gst_v4l2_object_stop (self->v4l2output);
219   gst_v4l2_object_stop (self->v4l2capture);
220
221   if (self->input_state) {
222     gst_video_codec_state_unref (self->input_state);
223     self->input_state = NULL;
224   }
225
226   GST_DEBUG_OBJECT (self, "Stopped");
227
228   return TRUE;
229 }
230
231 static gboolean
232 gst_v4l2_encoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags)
233 {
234   struct v4l2_encoder_cmd ecmd = { 0, };
235
236   GST_DEBUG_OBJECT (v4l2object->element,
237       "sending v4l2 encoder command %u with flags %u", cmd, flags);
238
239   if (!GST_V4L2_IS_OPEN (v4l2object))
240     return FALSE;
241
242   ecmd.cmd = cmd;
243   ecmd.flags = flags;
244   if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENCODER_CMD, &ecmd) < 0)
245     goto ecmd_failed;
246
247   return TRUE;
248
249 ecmd_failed:
250   if (errno == ENOTTY) {
251     GST_INFO_OBJECT (v4l2object->element,
252         "Failed to send encoder command %u with flags %u for '%s'. (%s)",
253         cmd, flags, v4l2object->videodev, g_strerror (errno));
254   } else {
255     GST_ERROR_OBJECT (v4l2object->element,
256         "Failed to send encoder command %u with flags %u for '%s'. (%s)",
257         cmd, flags, v4l2object->videodev, g_strerror (errno));
258   }
259   return FALSE;
260 }
261
262 static GstFlowReturn
263 gst_v4l2_video_enc_finish (GstVideoEncoder * encoder)
264 {
265   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
266   GstFlowReturn ret = GST_FLOW_OK;
267
268   if (gst_pad_get_task_state (encoder->srcpad) != GST_TASK_STARTED)
269     goto done;
270
271   GST_DEBUG_OBJECT (self, "Finishing encoding");
272
273   /* drop the stream lock while draining, so remaining buffers can be
274    * pushed from the src pad task thread */
275   GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
276
277   if (gst_v4l2_encoder_cmd (self->v4l2capture, V4L2_ENC_CMD_STOP, 0)) {
278     GstTask *task = encoder->srcpad->task;
279
280     /* Wait for the task to be drained */
281     GST_DEBUG_OBJECT (self, "Waiting for encoder stop");
282     GST_OBJECT_LOCK (task);
283     while (GST_TASK_STATE (task) == GST_TASK_STARTED)
284       GST_TASK_WAIT (task);
285     GST_OBJECT_UNLOCK (task);
286     ret = GST_FLOW_FLUSHING;
287   }
288
289   /* and ensure the processing thread has stopped in case another error
290    * occurred. */
291   gst_v4l2_object_unlock (self->v4l2capture);
292   gst_pad_stop_task (encoder->srcpad);
293   GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
294
295   if (ret == GST_FLOW_FLUSHING)
296     ret = self->output_flow;
297
298   GST_DEBUG_OBJECT (encoder, "Done draining buffers");
299
300 done:
301   return ret;
302 }
303
304 static gboolean
305 gst_v4l2_video_enc_set_format (GstVideoEncoder * encoder,
306     GstVideoCodecState * state)
307 {
308   gboolean ret = TRUE;
309   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
310   GstV4l2Error error = GST_V4L2_ERROR_INIT;
311   GstCaps *outcaps;
312   GstVideoCodecState *output;
313
314   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
315
316   if (self->input_state) {
317     if (gst_v4l2_object_caps_equal (self->v4l2output, state->caps)) {
318       GST_DEBUG_OBJECT (self, "Compatible caps");
319       return TRUE;
320     }
321
322     if (gst_v4l2_video_enc_finish (encoder) != GST_FLOW_OK)
323       return FALSE;
324
325     gst_v4l2_object_stop (self->v4l2output);
326     gst_v4l2_object_stop (self->v4l2capture);
327
328     gst_video_codec_state_unref (self->input_state);
329     self->input_state = NULL;
330   }
331
332   outcaps = gst_pad_get_pad_template_caps (encoder->srcpad);
333   outcaps = gst_caps_make_writable (outcaps);
334   output = gst_video_encoder_set_output_state (encoder, outcaps, state);
335   gst_video_codec_state_unref (output);
336
337   if (!gst_video_encoder_negotiate (encoder))
338     return FALSE;
339
340   if (!gst_v4l2_object_set_format (self->v4l2output, state->caps, &error)) {
341     gst_v4l2_error (self, &error);
342     return FALSE;
343   }
344
345   /* best effort */
346   gst_v4l2_object_setup_padding (self->v4l2output);
347
348   self->input_state = gst_video_codec_state_ref (state);
349
350   GST_DEBUG_OBJECT (self, "output caps: %" GST_PTR_FORMAT, state->caps);
351
352   return ret;
353 }
354
355 static gboolean
356 gst_v4l2_video_enc_flush (GstVideoEncoder * encoder)
357 {
358   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
359
360   GST_DEBUG_OBJECT (self, "Flushing");
361
362   /* Ensure the processing thread has stopped for the reverse playback
363    * iscount case */
364   if (g_atomic_int_get (&self->processing)) {
365     GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
366
367     gst_v4l2_object_unlock_stop (self->v4l2output);
368     gst_v4l2_object_unlock_stop (self->v4l2capture);
369     gst_pad_stop_task (encoder->srcpad);
370
371     GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
372
373   }
374
375   self->output_flow = GST_FLOW_OK;
376
377   gst_v4l2_object_unlock_stop (self->v4l2output);
378   gst_v4l2_object_unlock_stop (self->v4l2capture);
379
380   return TRUE;
381 }
382
383 struct ProfileLevelCtx
384 {
385   GstV4l2VideoEnc *self;
386   const gchar *profile;
387   const gchar *level;
388 };
389
390 static gboolean
391 get_string_list (GstStructure * s, const gchar * field, GQueue * queue)
392 {
393   const GValue *value;
394
395   value = gst_structure_get_value (s, field);
396
397   if (!value)
398     return FALSE;
399
400   if (GST_VALUE_HOLDS_LIST (value)) {
401     guint i;
402
403     if (gst_value_list_get_size (value) == 0)
404       return FALSE;
405
406     for (i = 0; i < gst_value_list_get_size (value); i++) {
407       const GValue *item = gst_value_list_get_value (value, i);
408
409       if (G_VALUE_HOLDS_STRING (item))
410         g_queue_push_tail (queue, g_value_dup_string (item));
411     }
412   } else if (G_VALUE_HOLDS_STRING (value)) {
413     g_queue_push_tail (queue, g_value_dup_string (value));
414   }
415
416   return TRUE;
417 }
418
419 static gboolean
420 negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
421     gpointer user_data)
422 {
423   struct ProfileLevelCtx *ctx = user_data;
424   GstV4l2VideoEncClass *klass = GST_V4L2_VIDEO_ENC_GET_CLASS (ctx->self);
425   GstV4l2Object *v4l2object = GST_V4L2_VIDEO_ENC (ctx->self)->v4l2output;
426   GQueue profiles = G_QUEUE_INIT;
427   GQueue levels = G_QUEUE_INIT;
428   gboolean failed = FALSE;
429   const GstV4l2Codec *codec = klass->codec;
430
431   if (codec->profile_cid && get_string_list (s, "profile", &profiles)) {
432     GList *l;
433
434     for (l = profiles.head; l; l = l->next) {
435       struct v4l2_control control = { 0, };
436       gint v4l2_profile;
437       const gchar *profile = l->data;
438
439       GST_TRACE_OBJECT (ctx->self, "Trying profile %s", profile);
440
441       control.id = codec->profile_cid;
442
443       control.value = v4l2_profile = codec->profile_from_string (profile);
444
445       if (control.value < 0)
446         continue;
447
448       if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
449         GST_WARNING_OBJECT (ctx->self, "Failed to set %s profile: '%s'",
450             klass->codec_name, g_strerror (errno));
451         break;
452       }
453
454       profile = codec->profile_to_string (control.value);
455
456       if (control.value == v4l2_profile) {
457         ctx->profile = profile;
458         break;
459       }
460
461       if (g_list_find_custom (l, profile, g_str_equal)) {
462         ctx->profile = profile;
463         break;
464       }
465     }
466
467     if (profiles.length && !ctx->profile)
468       failed = TRUE;
469
470     g_queue_foreach (&profiles, (GFunc) g_free, NULL);
471     g_queue_clear (&profiles);
472   }
473
474   if (!failed && codec->level_cid && get_string_list (s, "level", &levels)) {
475     GList *l;
476 #ifdef TIZEN_FEATURE_V4L2_ENCODER_SET_MAX_LEVEL
477     gint max_level = -1;
478 #endif
479
480     for (l = levels.head; l; l = l->next) {
481       struct v4l2_control control = { 0, };
482       gint v4l2_level;
483       const gchar *level = l->data;
484
485       GST_TRACE_OBJECT (ctx->self, "Trying level %s", level);
486
487       control.id = codec->level_cid;
488       control.value = v4l2_level = codec->level_from_string (level);
489
490       if (control.value < 0)
491         continue;
492
493       if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
494         GST_WARNING_OBJECT (ctx->self, "Failed to set %s level: '%s'",
495             klass->codec_name, g_strerror (errno));
496         break;
497       }
498
499       level = codec->level_to_string (control.value);
500
501 #ifdef TIZEN_FEATURE_V4L2_ENCODER_SET_MAX_LEVEL
502       if (v4l2_level > max_level &&
503         (control.value == v4l2_level ||
504           g_list_find_custom (l, level, g_str_equal))) {
505         ctx->level = level;
506         max_level = v4l2_level;
507         GST_WARNING_OBJECT (ctx->self, "max level -> %d", max_level);
508       }
509 #else
510       if (control.value == v4l2_level) {
511         ctx->level = level;
512         break;
513       }
514
515       if (g_list_find_custom (l, level, g_str_equal)) {
516         ctx->level = level;
517         break;
518       }
519 #endif
520     }
521
522     if (levels.length && !ctx->level)
523       failed = TRUE;
524
525     g_queue_foreach (&levels, (GFunc) g_free, NULL);
526     g_queue_clear (&levels);
527   }
528
529   /* If it failed, we continue */
530   return failed;
531 }
532
533 static GstCaps *
534 gst_v4l2_video_enc_sink_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
535 {
536   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
537   GstCaps *probed_caps = NULL;
538   GstCaps *caps;
539
540   if (self->probed_sinkcaps)
541     probed_caps = gst_caps_ref (self->probed_sinkcaps);
542
543   caps = gst_video_encoder_proxy_getcaps (encoder, probed_caps, filter);
544
545   if (probed_caps)
546     gst_caps_unref (probed_caps);
547
548   GST_DEBUG_OBJECT (self, "Returning sink caps %" GST_PTR_FORMAT, caps);
549
550   return caps;
551 }
552
553 static gboolean
554 gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
555 {
556   GstV4l2VideoEncClass *klass = GST_V4L2_VIDEO_ENC_GET_CLASS (encoder);
557   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
558   GstV4l2Object *v4l2object = self->v4l2output;
559   GstCaps *allowed_caps;
560   struct ProfileLevelCtx ctx = { self, NULL, NULL };
561   GstVideoCodecState *state;
562   GstStructure *s;
563   const GstV4l2Codec *codec = klass->codec;
564
565   GST_DEBUG_OBJECT (self, "Negotiating %s profile and level.",
566       klass->codec_name);
567
568   /* Only renegotiate on upstream changes */
569   if (self->input_state)
570     return TRUE;
571
572   if (!codec)
573     goto done;
574
575   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
576
577   if (allowed_caps) {
578
579     if (gst_caps_is_empty (allowed_caps))
580       goto not_negotiated;
581
582     allowed_caps = gst_caps_make_writable (allowed_caps);
583
584     /* negotiate_profile_and_level() will return TRUE on failure to keep
585      * iterating, if gst_caps_foreach() returns TRUE it means there was no
586      * compatible profile and level in any of the structure */
587     if (gst_caps_foreach (allowed_caps, negotiate_profile_and_level, &ctx)) {
588       goto no_profile_level;
589     }
590
591     gst_caps_unref (allowed_caps);
592     allowed_caps = NULL;
593   }
594
595   if (codec->profile_cid && !ctx.profile) {
596     struct v4l2_control control = { 0, };
597
598     control.id = codec->profile_cid;
599
600     if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
601       goto g_ctrl_failed;
602
603     ctx.profile = codec->profile_to_string (control.value);
604   }
605
606   if (codec->level_cid && !ctx.level) {
607     struct v4l2_control control = { 0, };
608
609     control.id = codec->level_cid;
610
611     if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
612       goto g_ctrl_failed;
613
614     ctx.level = codec->level_to_string (control.value);
615   }
616
617   GST_DEBUG_OBJECT (self, "Selected %s profile %s at level %s",
618       klass->codec_name, ctx.profile, ctx.level);
619
620   state = gst_video_encoder_get_output_state (encoder);
621   s = gst_caps_get_structure (state->caps, 0);
622
623   if (codec->profile_cid)
624     gst_structure_set (s, "profile", G_TYPE_STRING, ctx.profile, NULL);
625
626   if (codec->level_cid)
627     gst_structure_set (s, "level", G_TYPE_STRING, ctx.level, NULL);
628
629 done:
630   if (!GST_VIDEO_ENCODER_CLASS (parent_class)->negotiate (encoder))
631     return FALSE;
632
633   return TRUE;
634
635 g_ctrl_failed:
636   GST_WARNING_OBJECT (self, "Failed to get %s profile and level: '%s'",
637       klass->codec_name, g_strerror (errno));
638   goto not_negotiated;
639
640 no_profile_level:
641   GST_WARNING_OBJECT (self, "No compatible level and profile in caps: %"
642       GST_PTR_FORMAT, allowed_caps);
643   goto not_negotiated;
644
645 not_negotiated:
646   if (allowed_caps)
647     gst_caps_unref (allowed_caps);
648   return FALSE;
649 }
650
651 static gboolean
652 check_system_frame_number_too_old (guint32 current, guint32 old)
653 {
654   guint32 absdiff = current > old ? current - old : old - current;
655
656   /* More than 100 frames in the past, or current wrapped around */
657   if (absdiff > 100) {
658     /* Wraparound and difference is actually smaller than 100 */
659     if (absdiff > G_MAXUINT32 - 100)
660       return FALSE;
661     return TRUE;
662   }
663
664   return FALSE;
665 }
666
667 static void
668 gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
669 {
670   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
671   GstVideoCodecFrame *frame;
672   GstBuffer *buffer = NULL;
673   GstFlowReturn ret;
674
675   GST_LOG_OBJECT (encoder, "Allocate output buffer");
676
677   buffer = gst_video_encoder_allocate_output_buffer (encoder,
678       self->v4l2capture->info.size);
679
680   if (NULL == buffer) {
681     ret = GST_FLOW_FLUSHING;
682     goto beach;
683   }
684
685   /* FIXME Check if buffer isn't the last one here */
686
687   GST_LOG_OBJECT (encoder, "Process output buffer");
688   {
689     GstV4l2BufferPool *cpool =
690         GST_V4L2_BUFFER_POOL (gst_v4l2_object_get_buffer_pool
691         (self->v4l2capture));
692     ret = gst_v4l2_buffer_pool_process (cpool, &buffer, NULL);
693     if (cpool)
694       gst_object_unref (cpool);
695   }
696   if (ret != GST_FLOW_OK)
697     goto beach;
698
699   if (GST_BUFFER_TIMESTAMP (buffer) % GST_SECOND != 0)
700     GST_ERROR_OBJECT (encoder,
701         "Driver bug detected - check driver with v4l2-compliance from http://git.linuxtv.org/v4l-utils.git");
702   GST_LOG_OBJECT (encoder, "Got buffer for frame number %u",
703       (guint32) (GST_BUFFER_PTS (buffer) / GST_SECOND));
704   frame =
705       gst_video_encoder_get_frame (encoder,
706       GST_BUFFER_TIMESTAMP (buffer) / GST_SECOND);
707
708   if (frame) {
709     GstVideoCodecFrame *oldest_frame;
710     gboolean warned = FALSE;
711
712     /* Garbage collect old frames in case of codec bugs */
713     while ((oldest_frame = gst_video_encoder_get_oldest_frame (encoder)) &&
714         check_system_frame_number_too_old (frame->system_frame_number,
715             oldest_frame->system_frame_number)) {
716       gst_video_encoder_finish_frame (encoder, oldest_frame);
717       oldest_frame = NULL;
718
719       if (!warned) {
720         g_warning ("%s: Too old frames, bug in encoder -- please file a bug",
721             GST_ELEMENT_NAME (encoder));
722         warned = TRUE;
723       }
724     }
725     if (oldest_frame)
726       gst_video_codec_frame_unref (oldest_frame);
727
728     /* At this point, the delta unit buffer flag is already correctly set by
729      * gst_v4l2_buffer_pool_process. Since gst_video_encoder_finish_frame
730      * will overwrite it from GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame),
731      * set that here.
732      */
733     if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
734       GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
735     else
736       GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
737     frame->output_buffer = buffer;
738     buffer = NULL;
739     ret = gst_video_encoder_finish_frame (encoder, frame);
740
741     if (ret != GST_FLOW_OK)
742       goto beach;
743   } else {
744     GST_WARNING_OBJECT (encoder, "Encoder is producing too many buffers");
745     gst_buffer_unref (buffer);
746   }
747
748   return;
749
750 beach:
751   GST_DEBUG_OBJECT (encoder, "Leaving output thread");
752
753   gst_buffer_replace (&buffer, NULL);
754   self->output_flow = ret;
755   g_atomic_int_set (&self->processing, FALSE);
756   gst_v4l2_object_unlock (self->v4l2output);
757   gst_pad_pause_task (encoder->srcpad);
758 }
759
760 static void
761 gst_v4l2_video_enc_loop_stopped (GstV4l2VideoEnc * self)
762 {
763   if (g_atomic_int_get (&self->processing)) {
764     GST_DEBUG_OBJECT (self, "Early stop of encoding thread");
765     self->output_flow = GST_FLOW_FLUSHING;
766     g_atomic_int_set (&self->processing, FALSE);
767   }
768
769   GST_DEBUG_OBJECT (self, "Encoding task destroyed: %s",
770       gst_flow_get_name (self->output_flow));
771
772 }
773
774 static GstFlowReturn
775 gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
776     GstVideoCodecFrame * frame)
777 {
778   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
779   GstFlowReturn ret = GST_FLOW_OK;
780   GstTaskState task_state;
781   gboolean active;
782
783   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
784
785   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
786     goto flushing;
787
788   task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
789   if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
790     GstBufferPool *pool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
791
792     /* It is possible that the processing thread stopped due to an error or
793      * when the last buffer has been met during the draining process. */
794     if (self->output_flow != GST_FLOW_OK &&
795         self->output_flow != GST_FLOW_FLUSHING &&
796         self->output_flow != GST_V4L2_FLOW_LAST_BUFFER) {
797       GST_DEBUG_OBJECT (self, "Processing loop stopped with error: %s, leaving",
798           gst_flow_get_name (self->output_flow));
799       ret = self->output_flow;
800       if (pool)
801         gst_object_unref (pool);
802       goto drop;
803     }
804
805     /* Ensure input internal pool is active */
806     if (!gst_buffer_pool_is_active (pool)) {
807       GstStructure *config = gst_buffer_pool_get_config (pool);
808       guint min = MAX (self->v4l2output->min_buffers,
809           GST_V4L2_MIN_BUFFERS (self->v4l2output));
810
811       gst_buffer_pool_config_set_params (config, self->input_state->caps,
812           self->v4l2output->info.size, min, min);
813
814       /* There is no reason to refuse this config */
815       if (!gst_buffer_pool_set_config (pool, config)) {
816         if (pool)
817           gst_object_unref (pool);
818         goto activate_failed;
819       }
820
821       if (!gst_buffer_pool_set_active (pool, TRUE)) {
822         if (pool)
823           gst_object_unref (pool);
824         goto activate_failed;
825       }
826       if (pool)
827         gst_object_unref (pool);
828     }
829
830     {
831       GstBufferPool *cpool =
832           gst_v4l2_object_get_buffer_pool (self->v4l2capture);
833       active = gst_buffer_pool_set_active (cpool, TRUE);
834       if (cpool)
835         gst_object_unref (cpool);
836     }
837     if (!active) {
838       GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
839       goto activate_failed;
840     }
841
842     GST_DEBUG_OBJECT (self, "Starting encoding thread");
843
844     /* Start the processing task, when it quits, the task will disable input
845      * processing to unlock input if draining, or prevent potential block */
846     if (!gst_pad_start_task (encoder->srcpad,
847             (GstTaskFunction) gst_v4l2_video_enc_loop, self,
848             (GDestroyNotify) gst_v4l2_video_enc_loop_stopped))
849       goto start_task_failed;
850   }
851
852   if (frame->input_buffer) {
853     /* Process force keyframe event if it was passed */
854     if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
855       struct v4l2_control ctrl = { V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, 1 };
856       if (self->v4l2output->ioctl (self->v4l2output->video_fd, VIDIOC_S_CTRL,
857               &ctrl) < 0)
858         GST_ELEMENT_WARNING (self, RESOURCE, FAILED,
859             (_("Failed to force keyframe.")),
860             ("VIDIOC_S_CTRL (V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME) failed: %s (%d)",
861                 g_strerror (errno), errno));
862     }
863
864     GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
865     GST_LOG_OBJECT (encoder, "Passing buffer with frame number %u",
866         frame->system_frame_number);
867
868     {
869       GstBufferPool *opool = gst_v4l2_object_get_buffer_pool (self->v4l2output);
870       ret = gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (opool),
871           &frame->input_buffer, &frame->system_frame_number);
872       if (opool)
873         gst_object_unref (opool);
874     }
875
876     GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
877
878     if (ret == GST_FLOW_FLUSHING) {
879       if (gst_pad_get_task_state (encoder->srcpad) != GST_TASK_STARTED)
880         ret = self->output_flow;
881       goto drop;
882     } else if (ret != GST_FLOW_OK) {
883       goto process_failed;
884     }
885   }
886
887   gst_video_codec_frame_unref (frame);
888   return ret;
889
890   /* ERRORS */
891 activate_failed:
892   {
893     GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
894         (_("Failed to allocate required memory.")),
895         ("Buffer pool activation failed"));
896     return GST_FLOW_ERROR;
897
898   }
899 flushing:
900   {
901     ret = GST_FLOW_FLUSHING;
902     goto drop;
903   }
904 start_task_failed:
905   {
906     GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
907         (_("Failed to start encoding thread.")), (NULL));
908     g_atomic_int_set (&self->processing, FALSE);
909     ret = GST_FLOW_ERROR;
910     goto drop;
911   }
912 process_failed:
913   {
914     GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
915         (_("Failed to process frame.")),
916         ("Maybe be due to not enough memory or failing driver"));
917     ret = GST_FLOW_ERROR;
918     goto drop;
919   }
920 drop:
921   {
922     gst_video_encoder_finish_frame (encoder, frame);
923     return ret;
924   }
925 }
926
927 static gboolean
928 gst_v4l2_video_enc_decide_allocation (GstVideoEncoder *
929     encoder, GstQuery * query)
930 {
931   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
932   GstVideoCodecState *state = gst_video_encoder_get_output_state (encoder);
933   GstCaps *caps;
934   GstV4l2Error error = GST_V4L2_ERROR_INIT;
935   GstClockTime latency;
936   gboolean ret = FALSE;
937
938   /* We need to set the format here, since this is called right after
939    * GstVideoEncoder have set the width, height and framerate into the state
940    * caps. These are needed by the driver to calculate the buffer size and to
941    * implement bitrate adaptation. */
942   caps = gst_caps_copy (state->caps);
943   gst_structure_remove_field (gst_caps_get_structure (caps, 0), "colorimetry");
944   if (!gst_v4l2_object_set_format (self->v4l2capture, caps, &error)) {
945     gst_v4l2_error (self, &error);
946     gst_caps_unref (caps);
947     ret = FALSE;
948     goto done;
949   }
950   gst_caps_unref (caps);
951
952   /* best effort */
953   gst_v4l2_object_setup_padding (self->v4l2capture);
954
955   if (gst_v4l2_object_decide_allocation (self->v4l2capture, query)) {
956     GstVideoEncoderClass *enc_class = GST_VIDEO_ENCODER_CLASS (parent_class);
957     ret = enc_class->decide_allocation (encoder, query);
958   }
959
960   /* FIXME This may not be entirely correct, as encoder may keep some
961    * observation without delaying the encoding. Linux Media API need some
962    * more work to explicitly expressed the decoder / encoder latency. This
963    * value will then become max latency, and the reported driver latency would
964    * become the min latency. */
965   if (!GST_CLOCK_TIME_IS_VALID (self->v4l2capture->duration))
966     self->v4l2capture->duration = gst_util_uint64_scale_int (GST_SECOND, 1, 25);
967   latency = self->v4l2capture->min_buffers * self->v4l2capture->duration;
968   gst_video_encoder_set_latency (encoder, latency, latency);
969   GST_DEBUG_OBJECT (self, "Setting latency: %" GST_TIME_FORMAT,
970       GST_TIME_ARGS (latency));
971
972 done:
973   gst_video_codec_state_unref (state);
974   return ret;
975 }
976
977 static gboolean
978 gst_v4l2_video_enc_propose_allocation (GstVideoEncoder *
979     encoder, GstQuery * query)
980 {
981   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
982   gboolean ret = FALSE;
983
984   GST_DEBUG_OBJECT (self, "called");
985
986   if (query == NULL)
987     ret = TRUE;
988   else
989     ret = gst_v4l2_object_propose_allocation (self->v4l2output, query);
990
991   if (ret)
992     ret = GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
993         query);
994
995   return ret;
996 }
997
998 static gboolean
999 gst_v4l2_video_enc_src_query (GstVideoEncoder * encoder, GstQuery * query)
1000 {
1001   gboolean ret = TRUE;
1002   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
1003   switch (GST_QUERY_TYPE (query)) {
1004     case GST_QUERY_CAPS:{
1005       GstCaps *filter, *result = NULL;
1006       GstPad *pad = GST_VIDEO_ENCODER_SRC_PAD (encoder);
1007
1008       gst_query_parse_caps (query, &filter);
1009
1010       /* FIXME Try and not probe the entire encoder, but only the implement
1011        * subclass format */
1012       if (self->probed_srccaps) {
1013         GstCaps *tmpl = gst_pad_get_pad_template_caps (pad);
1014         result = gst_caps_intersect (tmpl, self->probed_srccaps);
1015         gst_caps_unref (tmpl);
1016       } else
1017         result = gst_pad_get_pad_template_caps (pad);
1018
1019       if (filter) {
1020         GstCaps *tmp = result;
1021         result =
1022             gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
1023         gst_caps_unref (tmp);
1024       }
1025
1026       GST_DEBUG_OBJECT (self, "Returning src caps %" GST_PTR_FORMAT, result);
1027
1028       gst_query_set_caps_result (query, result);
1029       gst_caps_unref (result);
1030       break;
1031     }
1032
1033     default:
1034       ret = GST_VIDEO_ENCODER_CLASS (parent_class)->src_query (encoder, query);
1035       break;
1036   }
1037
1038   return ret;
1039 }
1040
1041 static gboolean
1042 gst_v4l2_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event)
1043 {
1044   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
1045   gboolean ret;
1046   GstEventType type = GST_EVENT_TYPE (event);
1047
1048   switch (type) {
1049     case GST_EVENT_FLUSH_START:
1050       GST_DEBUG_OBJECT (self, "flush start");
1051       gst_v4l2_object_unlock (self->v4l2output);
1052       gst_v4l2_object_unlock (self->v4l2capture);
1053       break;
1054     default:
1055       break;
1056   }
1057
1058   ret = GST_VIDEO_ENCODER_CLASS (parent_class)->sink_event (encoder, event);
1059
1060   switch (type) {
1061     case GST_EVENT_FLUSH_START:
1062       gst_pad_stop_task (encoder->srcpad);
1063       GST_DEBUG_OBJECT (self, "flush start done");
1064     default:
1065       break;
1066   }
1067
1068   return ret;
1069 }
1070
1071 static GstStateChangeReturn
1072 gst_v4l2_video_enc_change_state (GstElement * element,
1073     GstStateChange transition)
1074 {
1075   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (element);
1076
1077   if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
1078     g_atomic_int_set (&self->active, FALSE);
1079     gst_v4l2_object_unlock (self->v4l2output);
1080     gst_v4l2_object_unlock (self->v4l2capture);
1081   }
1082
1083   return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1084 }
1085
1086
1087 static void
1088 gst_v4l2_video_enc_dispose (GObject * object)
1089 {
1090   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
1091
1092   gst_caps_replace (&self->probed_sinkcaps, NULL);
1093   gst_caps_replace (&self->probed_srccaps, NULL);
1094
1095   G_OBJECT_CLASS (parent_class)->dispose (object);
1096 }
1097
1098 static void
1099 gst_v4l2_video_enc_finalize (GObject * object)
1100 {
1101   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
1102
1103   gst_v4l2_object_destroy (self->v4l2capture);
1104   gst_v4l2_object_destroy (self->v4l2output);
1105
1106   G_OBJECT_CLASS (parent_class)->finalize (object);
1107 }
1108
1109
1110 static void
1111 gst_v4l2_video_enc_init (GstV4l2VideoEnc * self)
1112 {
1113   /* V4L2 object are created in subinstance_init */
1114 }
1115
1116 static void
1117 gst_v4l2_video_enc_subinstance_init (GTypeInstance * instance, gpointer g_class)
1118 {
1119   GstV4l2VideoEncClass *klass = GST_V4L2_VIDEO_ENC_CLASS (g_class);
1120   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (instance);
1121
1122   self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
1123       GST_OBJECT (GST_VIDEO_ENCODER_SINK_PAD (self)),
1124       V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
1125       gst_v4l2_get_output, gst_v4l2_set_output, NULL);
1126   self->v4l2output->no_initial_format = TRUE;
1127   self->v4l2output->keep_aspect = FALSE;
1128
1129   self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
1130       GST_OBJECT (GST_VIDEO_ENCODER_SRC_PAD (self)),
1131       V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
1132       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
1133 }
1134
1135 static void
1136 gst_v4l2_video_enc_class_init (GstV4l2VideoEncClass * klass)
1137 {
1138   GstElementClass *element_class;
1139   GObjectClass *gobject_class;
1140   GstVideoEncoderClass *video_encoder_class;
1141
1142   parent_class = g_type_class_peek_parent (klass);
1143
1144   element_class = (GstElementClass *) klass;
1145   gobject_class = (GObjectClass *) klass;
1146   video_encoder_class = (GstVideoEncoderClass *) klass;
1147
1148   GST_DEBUG_CATEGORY_INIT (gst_v4l2_video_enc_debug, "v4l2videoenc", 0,
1149       "V4L2 Video Encoder");
1150
1151   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_dispose);
1152   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_finalize);
1153   gobject_class->set_property =
1154       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_set_property);
1155   gobject_class->get_property =
1156       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_get_property);
1157
1158   video_encoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_open);
1159   video_encoder_class->close = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_close);
1160   video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_start);
1161   video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_stop);
1162   video_encoder_class->finish = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_finish);
1163   video_encoder_class->flush = GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_flush);
1164   video_encoder_class->set_format =
1165       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_set_format);
1166   video_encoder_class->getcaps =
1167       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_sink_getcaps);
1168   video_encoder_class->negotiate =
1169       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_negotiate);
1170   video_encoder_class->decide_allocation =
1171       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_decide_allocation);
1172   video_encoder_class->propose_allocation =
1173       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_propose_allocation);
1174   video_encoder_class->src_query =
1175       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_src_query);
1176   video_encoder_class->sink_event =
1177       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_sink_event);
1178   video_encoder_class->handle_frame =
1179       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_handle_frame);
1180
1181   element_class->change_state =
1182       GST_DEBUG_FUNCPTR (gst_v4l2_video_enc_change_state);
1183
1184   gst_v4l2_object_install_m2m_properties_helper (gobject_class);
1185 }
1186
1187 static void
1188 gst_v4l2_video_enc_subclass_init (gpointer g_class, gpointer data)
1189 {
1190   GstV4l2VideoEncClass *klass = GST_V4L2_VIDEO_ENC_CLASS (g_class);
1191   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1192   GstV4l2VideoEncCData *cdata = data;
1193
1194   klass->default_device = cdata->device;
1195   klass->codec = cdata->codec;
1196
1197   gst_element_class_add_pad_template (element_class,
1198       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
1199           cdata->sink_caps));
1200   gst_element_class_add_pad_template (element_class,
1201       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
1202           cdata->src_caps));
1203
1204   gst_caps_unref (cdata->sink_caps);
1205   gst_caps_unref (cdata->src_caps);
1206   g_free (cdata);
1207 }
1208
1209 /* Probing functions */
1210 gboolean
1211 gst_v4l2_is_video_enc (GstCaps * sink_caps, GstCaps * src_caps,
1212     GstCaps * codec_caps)
1213 {
1214   gboolean ret = FALSE;
1215   gboolean (*check_caps) (const GstCaps *, const GstCaps *);
1216
1217   if (codec_caps) {
1218     check_caps = gst_caps_can_intersect;
1219   } else {
1220     codec_caps = gst_v4l2_object_get_codec_caps ();
1221     check_caps = gst_caps_is_subset;
1222   }
1223
1224   if (gst_caps_is_subset (sink_caps, gst_v4l2_object_get_raw_caps ())
1225       && check_caps (src_caps, codec_caps))
1226     ret = TRUE;
1227
1228   return ret;
1229 }
1230
1231 void
1232 gst_v4l2_video_enc_register (GstPlugin * plugin, GType type,
1233     const char *codec_name, const gchar * basename, const gchar * device_path,
1234     const GstV4l2Codec * codec, gint video_fd, GstCaps * sink_caps,
1235     GstCaps * codec_caps, GstCaps * src_caps)
1236 {
1237   GstCaps *filtered_caps;
1238   GTypeQuery type_query;
1239   GTypeInfo type_info = { 0, };
1240   GType subtype;
1241   gchar *type_name;
1242   GstV4l2VideoEncCData *cdata;
1243   GValue value = G_VALUE_INIT;
1244
1245   filtered_caps = gst_caps_intersect (src_caps, codec_caps);
1246
1247   if (codec != NULL && video_fd != -1) {
1248     if (gst_v4l2_codec_probe_levels (codec, video_fd, &value)) {
1249       gst_caps_set_value (filtered_caps, "level", &value);
1250       g_value_unset (&value);
1251     }
1252
1253     if (gst_v4l2_codec_probe_profiles (codec, video_fd, &value)) {
1254       gst_caps_set_value (filtered_caps, "profile", &value);
1255       g_value_unset (&value);
1256     }
1257   }
1258
1259   cdata = g_new0 (GstV4l2VideoEncCData, 1);
1260   cdata->device = g_strdup (device_path);
1261   cdata->sink_caps = gst_caps_ref (sink_caps);
1262   cdata->src_caps = gst_caps_ref (filtered_caps);
1263   cdata->codec = codec;
1264
1265   g_type_query (type, &type_query);
1266   memset (&type_info, 0, sizeof (type_info));
1267   type_info.class_size = type_query.class_size;
1268   type_info.instance_size = type_query.instance_size;
1269   type_info.class_init = gst_v4l2_video_enc_subclass_init;
1270   type_info.class_data = cdata;
1271   type_info.instance_init = gst_v4l2_video_enc_subinstance_init;
1272
1273   /* The first encoder to be registered should use a constant name, like
1274    * v4l2h264enc, for any additional encoders, we create unique names. Encoder
1275    * names may change between boots, so this should help gain stable names for
1276    * the most common use cases. */
1277   type_name = g_strdup_printf ("v4l2%senc", codec_name);
1278
1279   if (g_type_from_name (type_name) != 0) {
1280     g_free (type_name);
1281     type_name = g_strdup_printf ("v4l2%s%senc", basename, codec_name);
1282   }
1283
1284   subtype = g_type_register_static (type, type_name, &type_info, 0);
1285
1286 #ifdef TIZEN_FEATURE_V4L2VIDEO_ADJ_RANK
1287   if (!gst_element_register (plugin, type_name, GST_RANK_SECONDARY, subtype))
1288     GST_WARNING ("Failed to register plugin '%s'", type_name);
1289 #else
1290   if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY + 1, subtype))
1291     GST_WARNING ("Failed to register plugin '%s'", type_name);
1292 #endif
1293
1294   g_free (type_name);
1295 }