Move files from gst-plugins-bad into the "subprojects/gst-plugins-bad/" subdir
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / androidmedia / gstamcvideoenc.c
1 /*
2  * Initially based on gst-plugins-bad/sys/androidmedia/gstamcvideodec.c
3  *
4  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
5  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
6  *
7  * Copyright (C) 2012, Collabora Ltd.
8  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
9  *
10  * Copyright (C) 2013, Lemote Ltd.
11  *   Author: Chen Jie <chenj@lemote.com>
12  *
13  * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation
18  * version 2.1 of the License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
28  *
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <gst/gst.h>
36 #include <string.h>
37
38 #ifdef HAVE_ORC
39 #include <orc/orc.h>
40 #else
41 #define orc_memcpy memcpy
42 #endif
43
44 #ifdef HAVE_JNI_H
45 #include "gstjniutils.h"
46 #endif
47
48 #include "gstamcvideoenc.h"
49 #include "gstamc-constants.h"
50
51 GST_DEBUG_CATEGORY_STATIC (gst_amc_video_enc_debug_category);
52 #define GST_CAT_DEFAULT gst_amc_video_enc_debug_category
53
54 typedef struct _BufferIdentification BufferIdentification;
55 struct _BufferIdentification
56 {
57   guint64 timestamp;
58 };
59
60 static BufferIdentification *
61 buffer_identification_new (GstClockTime timestamp)
62 {
63   BufferIdentification *id = g_slice_new (BufferIdentification);
64
65   id->timestamp = timestamp;
66
67   return id;
68 }
69
70 static void
71 buffer_identification_free (BufferIdentification * id)
72 {
73   g_slice_free (BufferIdentification, id);
74 }
75
76 /* prototypes */
77 static void gst_amc_video_enc_finalize (GObject * object);
78
79 static GstStateChangeReturn
80 gst_amc_video_enc_change_state (GstElement * element,
81     GstStateChange transition);
82
83 static gboolean gst_amc_video_enc_open (GstVideoEncoder * encoder);
84 static gboolean gst_amc_video_enc_close (GstVideoEncoder * encoder);
85 static gboolean gst_amc_video_enc_start (GstVideoEncoder * encoder);
86 static gboolean gst_amc_video_enc_stop (GstVideoEncoder * encoder);
87 static gboolean gst_amc_video_enc_set_format (GstVideoEncoder * encoder,
88     GstVideoCodecState * state);
89 static gboolean gst_amc_video_enc_flush (GstVideoEncoder * encoder);
90 static GstFlowReturn gst_amc_video_enc_handle_frame (GstVideoEncoder * encoder,
91     GstVideoCodecFrame * frame);
92 static GstFlowReturn gst_amc_video_enc_finish (GstVideoEncoder * encoder);
93
94 static GstFlowReturn gst_amc_video_enc_drain (GstAmcVideoEnc * self);
95
96 #define BIT_RATE_DEFAULT (2 * 1024 * 1024)
97 #define I_FRAME_INTERVAL_DEFAULT 0
98 enum
99 {
100   PROP_0,
101   PROP_BIT_RATE,
102   PROP_I_FRAME_INTERVAL,
103   PROP_I_FRAME_INTERVAL_FLOAT
104 };
105
106 /* class initialization */
107
108 static void gst_amc_video_enc_class_init (GstAmcVideoEncClass * klass);
109 static void gst_amc_video_enc_init (GstAmcVideoEnc * self);
110 static void gst_amc_video_enc_base_init (gpointer g_class);
111
112 static GstVideoEncoderClass *parent_class = NULL;
113
114 GType
115 gst_amc_video_enc_get_type (void)
116 {
117   static gsize type = 0;
118
119   if (g_once_init_enter (&type)) {
120     GType _type;
121     static const GTypeInfo info = {
122       sizeof (GstAmcVideoEncClass),
123       gst_amc_video_enc_base_init,
124       NULL,
125       (GClassInitFunc) gst_amc_video_enc_class_init,
126       NULL,
127       NULL,
128       sizeof (GstAmcVideoEnc),
129       0,
130       (GInstanceInitFunc) gst_amc_video_enc_init,
131       NULL
132     };
133
134     _type = g_type_register_static (GST_TYPE_VIDEO_ENCODER, "GstAmcVideoEnc",
135         &info, 0);
136
137     GST_DEBUG_CATEGORY_INIT (gst_amc_video_enc_debug_category, "amcvideoenc", 0,
138         "Android MediaCodec video encoder");
139
140     g_once_init_leave (&type, _type);
141   }
142   return type;
143 }
144
145 static GstAmcFormat *
146 create_amc_format (GstAmcVideoEnc * encoder, GstVideoCodecState * input_state,
147     GstCaps * src_caps)
148 {
149   GstAmcVideoEncClass *klass;
150   GstStructure *s;
151   const gchar *name;
152   const gchar *mime = NULL;
153   const gchar *profile_string = NULL;
154   const gchar *level_string = NULL;
155   struct
156   {
157     const gchar *key;
158     gint id;
159   } amc_profile = {
160   NULL, -1};
161   struct
162   {
163     const gchar *key;
164     gint id;
165   } amc_level = {
166   NULL, -1};
167   gint color_format;
168   gint stride, slice_height;
169   GstAmcFormat *format = NULL;
170   GstVideoInfo *info = &input_state->info;
171   GError *err = NULL;
172
173   klass = GST_AMC_VIDEO_ENC_GET_CLASS (encoder);
174   s = gst_caps_get_structure (src_caps, 0);
175   if (!s)
176     return NULL;
177
178   name = gst_structure_get_name (s);
179   profile_string = gst_structure_get_string (s, "profile");
180   level_string = gst_structure_get_string (s, "level");
181
182   if (strcmp (name, "video/mpeg") == 0) {
183     gint mpegversion;
184
185     if (!gst_structure_get_int (s, "mpegversion", &mpegversion))
186       return NULL;
187
188     if (mpegversion == 4) {
189       mime = "video/mp4v-es";
190
191       if (profile_string) {
192         amc_profile.key = "profile";    /* named profile ? */
193         amc_profile.id = gst_amc_mpeg4_profile_from_string (profile_string);
194       }
195
196       if (level_string) {
197         amc_level.key = "level";        /* named level ? */
198         amc_level.id = gst_amc_mpeg4_level_from_string (level_string);
199       }
200     } else if ( /* mpegversion == 1 || */ mpegversion == 2)
201       mime = "video/mpeg2";
202   } else if (strcmp (name, "video/x-h263") == 0) {
203     mime = "video/3gpp";
204   } else if (strcmp (name, "video/x-h264") == 0) {
205     mime = "video/avc";
206
207     if (profile_string) {
208       amc_profile.key = "profile";      /* named profile ? */
209       amc_profile.id = gst_amc_avc_profile_from_string (profile_string);
210     }
211
212     if (level_string) {
213       amc_level.key = "level";  /* named level ? */
214       amc_level.id = gst_amc_avc_level_from_string (level_string);
215     }
216   } else if (strcmp (name, "video/x-vp8") == 0) {
217     mime = "video/x-vnd.on2.vp8";
218   } else if (strcmp (name, "video/x-vp9") == 0) {
219     mime = "video/x-vnd.on2.vp9";
220   } else {
221     GST_ERROR_OBJECT (encoder, "Failed to convert caps(%s/...) to any mime",
222         name);
223     return NULL;
224   }
225
226   format = gst_amc_format_new_video (mime, info->width, info->height, &err);
227   if (!format) {
228     GST_ERROR_OBJECT (encoder, "Failed to create a \"%s,%dx%d\" MediaFormat",
229         mime, info->width, info->height);
230     GST_ELEMENT_ERROR_FROM_ERROR (encoder, err);
231     return NULL;
232   }
233
234   color_format =
235       gst_amc_video_format_to_color_format (klass->codec_info,
236       mime, info->finfo->format);
237   if (color_format == -1)
238     goto video_format_failed_to_convert;
239
240   gst_amc_format_set_int (format, "bitrate", encoder->bitrate, &err);
241   if (err)
242     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
243   gst_amc_format_set_int (format, "color-format", color_format, &err);
244   if (err)
245     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
246   stride = GST_ROUND_UP_4 (info->width);        /* safe (?) */
247   gst_amc_format_set_int (format, "stride", stride, &err);
248   if (err)
249     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
250   slice_height = info->height;
251   gst_amc_format_set_int (format, "slice-height", slice_height, &err);
252   if (err)
253     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
254
255   if (profile_string) {
256     if (amc_profile.id == -1)
257       goto unsupported_profile;
258
259     /* FIXME: Set to any value in AVCProfile* leads to
260      * codec configuration fail */
261     /* gst_amc_format_set_int (format, amc_profile.key, 0x40); */
262   }
263
264   if (level_string) {
265     if (amc_level.id == -1)
266       goto unsupported_level;
267
268     /* gst_amc_format_set_int (format, amc_level.key, amc_level.id); */
269   }
270
271   /* On Android N_MR1 and higher, i-frame-interval can be a float value */
272 #ifdef HAVE_JNI_H
273   if (gst_amc_jni_get_android_level () >= 25) {
274     GST_LOG_OBJECT (encoder, "Setting i-frame-interval to %f",
275         encoder->i_frame_int);
276     gst_amc_format_set_float (format, "i-frame-interval", encoder->i_frame_int,
277         &err);
278   } else
279 #endif
280   {
281     int i_frame_int = encoder->i_frame_int;
282     /* Round a fractional interval to 1 per sec on older Android */
283     if (encoder->i_frame_int > 0 && encoder->i_frame_int < 1.0)
284       i_frame_int = 1;
285     gst_amc_format_set_int (format, "i-frame-interval", i_frame_int, &err);
286   }
287   if (err)
288     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
289
290   if (info->fps_d)
291     gst_amc_format_set_float (format, "frame-rate",
292         ((gfloat) info->fps_n) / info->fps_d, &err);
293   if (err)
294     GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
295
296   encoder->format = info->finfo->format;
297   if (!gst_amc_color_format_info_set (&encoder->color_format_info,
298           klass->codec_info, mime, color_format, info->width, info->height,
299           stride, slice_height, 0, 0, 0, 0))
300     goto color_format_info_failed_to_set;
301
302   GST_DEBUG_OBJECT (encoder,
303       "Color format info: {color_format=%d, width=%d, height=%d, "
304       "stride=%d, slice-height=%d, crop-left=%d, crop-top=%d, "
305       "crop-right=%d, crop-bottom=%d, frame-size=%d}",
306       encoder->color_format_info.color_format, encoder->color_format_info.width,
307       encoder->color_format_info.height, encoder->color_format_info.stride,
308       encoder->color_format_info.slice_height,
309       encoder->color_format_info.crop_left, encoder->color_format_info.crop_top,
310       encoder->color_format_info.crop_right,
311       encoder->color_format_info.crop_bottom,
312       encoder->color_format_info.frame_size);
313
314   return format;
315
316 video_format_failed_to_convert:
317   GST_ERROR_OBJECT (encoder, "Failed to convert video format");
318   gst_amc_format_free (format);
319   return NULL;
320
321 color_format_info_failed_to_set:
322   GST_ERROR_OBJECT (encoder, "Failed to set up GstAmcColorFormatInfo");
323   gst_amc_format_free (format);
324   return NULL;
325
326 unsupported_profile:
327   GST_ERROR_OBJECT (encoder, "Unsupported profile '%s'", profile_string);
328   gst_amc_format_free (format);
329   return NULL;
330
331 unsupported_level:
332   GST_ERROR_OBJECT (encoder, "Unsupported level '%s'", level_string);
333   gst_amc_format_free (format);
334   return NULL;
335 }
336
337 static GstCaps *
338 caps_from_amc_format (GstAmcFormat * amc_format)
339 {
340   GstCaps *caps = NULL;
341   gchar *mime = NULL;
342   gint width, height;
343   gint amc_profile, amc_level;
344   gfloat frame_rate = 0.0;
345   gint fraction_n, fraction_d;
346   GError *err = NULL;
347
348   if (!gst_amc_format_get_string (amc_format, "mime", &mime, &err)) {
349     GST_ERROR ("Failed to get 'mime': %s", err->message);
350     g_clear_error (&err);
351     return NULL;
352   }
353
354   if (!gst_amc_format_get_int (amc_format, "width", &width, &err) ||
355       !gst_amc_format_get_int (amc_format, "height", &height, &err)) {
356     GST_ERROR ("Failed to get size: %s", err->message);
357     g_clear_error (&err);
358
359     g_free (mime);
360     return NULL;
361   }
362
363   gst_amc_format_get_float (amc_format, "frame-rate", &frame_rate, NULL);
364   gst_util_double_to_fraction (frame_rate, &fraction_n, &fraction_d);
365
366   if (strcmp (mime, "video/mp4v-es") == 0) {
367     const gchar *profile_string, *level_string;
368
369     caps =
370         gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
371         "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
372
373     if (gst_amc_format_get_int (amc_format, "profile", &amc_profile, NULL)) {
374       profile_string = gst_amc_mpeg4_profile_to_string (amc_profile);
375       if (!profile_string)
376         goto unsupported_profile;
377
378       gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_string,
379           NULL);
380     }
381
382     if (gst_amc_format_get_int (amc_format, "level", &amc_level, NULL)) {
383       level_string = gst_amc_mpeg4_level_to_string (amc_profile);
384       if (!level_string)
385         goto unsupported_level;
386
387       gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_string, NULL);
388     }
389
390   } else if (strcmp (mime, "video/mpeg2") == 0) {
391     caps = gst_caps_new_simple ("video/mpeg", "mpegversion", 2, NULL);
392   } else if (strcmp (mime, "video/3gpp") == 0) {
393     caps = gst_caps_new_empty_simple ("video/x-h263");
394   } else if (strcmp (mime, "video/avc") == 0) {
395     const gchar *profile_string, *level_string;
396
397     caps =
398         gst_caps_new_simple ("video/x-h264",
399         "stream-format", G_TYPE_STRING, "byte-stream", NULL);
400
401     if (gst_amc_format_get_int (amc_format, "profile", &amc_profile, NULL)) {
402       profile_string = gst_amc_avc_profile_to_string (amc_profile, NULL);
403       if (!profile_string)
404         goto unsupported_profile;
405
406       gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_string,
407           NULL);
408     }
409
410     if (gst_amc_format_get_int (amc_format, "level", &amc_level, NULL)) {
411       level_string = gst_amc_avc_level_to_string (amc_profile);
412       if (!level_string)
413         goto unsupported_level;
414
415       gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_string, NULL);
416     }
417   } else if (strcmp (mime, "video/x-vnd.on2.vp8") == 0) {
418     caps = gst_caps_new_empty_simple ("video/x-vp8");
419   } else if (strcmp (mime, "video/x-vnd.on2.vp9") == 0) {
420     caps = gst_caps_new_empty_simple ("video/x-vp9");
421   }
422
423   gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
424       "height", G_TYPE_INT, height,
425       "framerate", GST_TYPE_FRACTION, fraction_n, fraction_d, NULL);
426
427   g_free (mime);
428   return caps;
429
430 unsupported_profile:
431   GST_ERROR ("Unsupported amc profile id %d", amc_profile);
432   g_free (mime);
433   gst_caps_unref (caps);
434
435   return NULL;
436
437 unsupported_level:
438   GST_ERROR ("Unsupported amc level id %d", amc_level);
439   g_free (mime);
440   gst_caps_unref (caps);
441
442   return NULL;
443 }
444
445 static void
446 gst_amc_video_enc_base_init (gpointer g_class)
447 {
448   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
449   GstAmcVideoEncClass *videoenc_class = GST_AMC_VIDEO_ENC_CLASS (g_class);
450   const GstAmcCodecInfo *codec_info;
451   GstPadTemplate *templ;
452   GstCaps *sink_caps, *src_caps;
453   gchar *longname;
454
455   codec_info =
456       g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), gst_amc_codec_info_quark);
457   /* This happens for the base class and abstract subclasses */
458   if (!codec_info)
459     return;
460
461   videoenc_class->codec_info = codec_info;
462
463   gst_amc_codec_info_to_caps (codec_info, &sink_caps, &src_caps);
464   /* Add pad templates */
465   templ =
466       gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps);
467   gst_element_class_add_pad_template (element_class, templ);
468   gst_caps_unref (sink_caps);
469
470   templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps);
471   gst_element_class_add_pad_template (element_class, templ);
472   gst_caps_unref (src_caps);
473
474   longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name);
475   gst_element_class_set_metadata (element_class,
476       codec_info->name,
477       "Codec/Encoder/Video/Hardware",
478       longname, "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
479   g_free (longname);
480 }
481
482 static void
483 gst_amc_video_enc_set_property (GObject * object, guint prop_id,
484     const GValue * value, GParamSpec * pspec)
485 {
486   GstAmcVideoEnc *encoder;
487   GstState state;
488   gboolean codec_active;
489   GError *err = NULL;
490
491   encoder = GST_AMC_VIDEO_ENC (object);
492
493   GST_OBJECT_LOCK (encoder);
494
495   state = GST_STATE (encoder);
496   codec_active = (encoder->codec && state != GST_STATE_READY
497       && state != GST_STATE_NULL);
498
499   switch (prop_id) {
500     case PROP_BIT_RATE:
501       encoder->bitrate = g_value_get_uint (value);
502
503       g_mutex_lock (&encoder->codec_lock);
504       if (encoder->codec) {
505         if (!gst_amc_codec_set_dynamic_bitrate (encoder->codec, &err,
506                 encoder->bitrate)) {
507           g_mutex_unlock (&encoder->codec_lock);
508           goto wrong_state;
509         }
510       }
511       g_mutex_unlock (&encoder->codec_lock);
512       if (err) {
513         GST_ELEMENT_WARNING_FROM_ERROR (encoder, err);
514         g_clear_error (&err);
515       }
516
517       break;
518     case PROP_I_FRAME_INTERVAL:
519       encoder->i_frame_int = g_value_get_uint (value);
520       if (codec_active)
521         goto wrong_state;
522       break;
523     case PROP_I_FRAME_INTERVAL_FLOAT:
524       encoder->i_frame_int = g_value_get_float (value);
525       if (codec_active)
526         goto wrong_state;
527       break;
528     default:
529       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
530       break;
531   }
532   GST_OBJECT_UNLOCK (encoder);
533   return;
534
535   /* ERROR */
536 wrong_state:
537   {
538     GST_WARNING_OBJECT (encoder, "setting property in wrong state");
539     GST_OBJECT_UNLOCK (encoder);
540   }
541 }
542
543 static void
544 gst_amc_video_enc_get_property (GObject * object, guint prop_id,
545     GValue * value, GParamSpec * pspec)
546 {
547   GstAmcVideoEnc *encoder;
548
549   encoder = GST_AMC_VIDEO_ENC (object);
550
551   GST_OBJECT_LOCK (encoder);
552   switch (prop_id) {
553     case PROP_BIT_RATE:
554       g_value_set_uint (value, encoder->bitrate);
555       break;
556     case PROP_I_FRAME_INTERVAL:
557       g_value_set_uint (value, encoder->i_frame_int);
558       break;
559     case PROP_I_FRAME_INTERVAL_FLOAT:
560       g_value_set_float (value, encoder->i_frame_int);
561       break;
562     default:
563       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
564       break;
565   }
566   GST_OBJECT_UNLOCK (encoder);
567 }
568
569
570 static void
571 gst_amc_video_enc_class_init (GstAmcVideoEncClass * klass)
572 {
573   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
574   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
575   GstVideoEncoderClass *videoenc_class = GST_VIDEO_ENCODER_CLASS (klass);
576   GParamFlags dynamic_flag = 0;
577
578   parent_class = g_type_class_peek_parent (klass);
579
580   gobject_class->set_property = gst_amc_video_enc_set_property;
581   gobject_class->get_property = gst_amc_video_enc_get_property;
582   gobject_class->finalize = gst_amc_video_enc_finalize;
583
584   element_class->change_state =
585       GST_DEBUG_FUNCPTR (gst_amc_video_enc_change_state);
586
587   videoenc_class->start = GST_DEBUG_FUNCPTR (gst_amc_video_enc_start);
588   videoenc_class->stop = GST_DEBUG_FUNCPTR (gst_amc_video_enc_stop);
589   videoenc_class->open = GST_DEBUG_FUNCPTR (gst_amc_video_enc_open);
590   videoenc_class->close = GST_DEBUG_FUNCPTR (gst_amc_video_enc_close);
591   videoenc_class->flush = GST_DEBUG_FUNCPTR (gst_amc_video_enc_flush);
592   videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_amc_video_enc_set_format);
593   videoenc_class->handle_frame =
594       GST_DEBUG_FUNCPTR (gst_amc_video_enc_handle_frame);
595   videoenc_class->finish = GST_DEBUG_FUNCPTR (gst_amc_video_enc_finish);
596
597   // On Android >= 19, we can set bitrate dynamically
598   // so add the flag so apps can detect it.
599   if (gst_amc_codec_have_dynamic_bitrate ())
600     dynamic_flag = GST_PARAM_MUTABLE_PLAYING;
601
602   g_object_class_install_property (gobject_class, PROP_BIT_RATE,
603       g_param_spec_uint ("bitrate", "Bitrate", "Bitrate in bit/sec", 1,
604           G_MAXINT, BIT_RATE_DEFAULT,
605           dynamic_flag | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
606
607   g_object_class_install_property (gobject_class, PROP_I_FRAME_INTERVAL,
608       g_param_spec_uint ("i-frame-interval", "I-frame interval",
609           "The frequency of I frames expressed in seconds between I frames (0 for automatic)",
610           0, G_MAXINT, I_FRAME_INTERVAL_DEFAULT,
611           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
612
613   g_object_class_install_property (gobject_class, PROP_I_FRAME_INTERVAL_FLOAT,
614       g_param_spec_float ("i-frame-interval-float", "I-frame interval",
615           "The frequency of I frames expressed in seconds between I frames (0 for automatic). "
616           "Fractional intervals work on Android >= 25",
617           0, G_MAXFLOAT, I_FRAME_INTERVAL_DEFAULT,
618           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
619 }
620
621 static void
622 gst_amc_video_enc_init (GstAmcVideoEnc * self)
623 {
624   g_mutex_init (&self->codec_lock);
625   g_mutex_init (&self->drain_lock);
626   g_cond_init (&self->drain_cond);
627
628   self->bitrate = BIT_RATE_DEFAULT;
629   self->i_frame_int = I_FRAME_INTERVAL_DEFAULT;
630 }
631
632 static gboolean
633 gst_amc_video_enc_open (GstVideoEncoder * encoder)
634 {
635   GstAmcVideoEnc *self = GST_AMC_VIDEO_ENC (encoder);
636   GstAmcVideoEncClass *klass = GST_AMC_VIDEO_ENC_GET_CLASS (self);
637   GError *err = NULL;
638
639   GST_DEBUG_OBJECT (self, "Opening encoder");
640
641   g_mutex_lock (&self->codec_lock);
642   self->codec = gst_amc_codec_new (klass->codec_info->name, TRUE, &err);
643   if (!self->codec) {
644     g_mutex_unlock (&self->codec_lock);
645     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
646     return FALSE;
647   }
648   g_mutex_unlock (&self->codec_lock);
649   self->started = FALSE;
650   self->flushing = TRUE;
651
652   GST_DEBUG_OBJECT (self, "Opened encoder");
653
654   return TRUE;
655 }
656
657 static gboolean
658 gst_amc_video_enc_close (GstVideoEncoder * encoder)
659 {
660   GstAmcVideoEnc *self = GST_AMC_VIDEO_ENC (encoder);
661
662   GST_DEBUG_OBJECT (self, "Closing encoder");
663
664   g_mutex_lock (&self->codec_lock);
665   if (self->codec) {
666     GError *err = NULL;
667
668     gst_amc_codec_release (self->codec, &err);
669     if (err)
670       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
671
672     gst_amc_codec_free (self->codec);
673   }
674   self->codec = NULL;
675   g_mutex_unlock (&self->codec_lock);
676
677   self->started = FALSE;
678   self->flushing = TRUE;
679
680   GST_DEBUG_OBJECT (self, "Closed encoder");
681
682   return TRUE;
683 }
684
685 static void
686 gst_amc_video_enc_finalize (GObject * object)
687 {
688   GstAmcVideoEnc *self = GST_AMC_VIDEO_ENC (object);
689
690   g_mutex_clear (&self->codec_lock);
691   g_mutex_clear (&self->drain_lock);
692   g_cond_clear (&self->drain_cond);
693
694   G_OBJECT_CLASS (parent_class)->finalize (object);
695 }
696
697 static GstStateChangeReturn
698 gst_amc_video_enc_change_state (GstElement * element, GstStateChange transition)
699 {
700   GstAmcVideoEnc *self;
701   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
702   GError *err = NULL;
703
704   g_return_val_if_fail (GST_IS_AMC_VIDEO_ENC (element),
705       GST_STATE_CHANGE_FAILURE);
706   self = GST_AMC_VIDEO_ENC (element);
707
708   switch (transition) {
709     case GST_STATE_CHANGE_NULL_TO_READY:
710       break;
711     case GST_STATE_CHANGE_READY_TO_PAUSED:
712       self->downstream_flow_ret = GST_FLOW_OK;
713       self->draining = FALSE;
714       self->started = FALSE;
715       break;
716     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
717       break;
718     case GST_STATE_CHANGE_PAUSED_TO_READY:
719       self->flushing = TRUE;
720       gst_amc_codec_flush (self->codec, &err);
721       if (err)
722         GST_ELEMENT_WARNING_FROM_ERROR (self, err);
723       g_mutex_lock (&self->drain_lock);
724       self->draining = FALSE;
725       g_cond_broadcast (&self->drain_cond);
726       g_mutex_unlock (&self->drain_lock);
727       break;
728     default:
729       break;
730   }
731
732   if (ret == GST_STATE_CHANGE_FAILURE)
733     return ret;
734
735   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
736
737   if (ret == GST_STATE_CHANGE_FAILURE)
738     return ret;
739
740   switch (transition) {
741     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
742       break;
743     case GST_STATE_CHANGE_PAUSED_TO_READY:
744       self->downstream_flow_ret = GST_FLOW_FLUSHING;
745       self->started = FALSE;
746       break;
747     case GST_STATE_CHANGE_READY_TO_NULL:
748       break;
749     default:
750       break;
751   }
752
753   return ret;
754 }
755
756 #define MAX_FRAME_DIST_TIME  (5 * GST_SECOND)
757 #define MAX_FRAME_DIST_FRAMES (100)
758
759 static GstVideoCodecFrame *
760 _find_nearest_frame (GstAmcVideoEnc * self, GstClockTime reference_timestamp)
761 {
762   GList *l, *best_l = NULL;
763   GList *finish_frames = NULL;
764   GstVideoCodecFrame *best = NULL;
765   guint64 best_timestamp = 0;
766   guint64 best_diff = G_MAXUINT64;
767   BufferIdentification *best_id = NULL;
768   GList *frames;
769
770   frames = gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self));
771
772   for (l = frames; l; l = l->next) {
773     GstVideoCodecFrame *tmp = l->data;
774     BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
775     guint64 timestamp, diff;
776
777     /* This happens for frames that were just added but
778      * which were not passed to the component yet. Ignore
779      * them here!
780      */
781     if (!id)
782       continue;
783
784     timestamp = id->timestamp;
785
786     if (timestamp > reference_timestamp)
787       diff = timestamp - reference_timestamp;
788     else
789       diff = reference_timestamp - timestamp;
790
791     if (best == NULL || diff < best_diff) {
792       best = tmp;
793       best_timestamp = timestamp;
794       best_diff = diff;
795       best_l = l;
796       best_id = id;
797
798       /* For frames without timestamp we simply take the first frame */
799       if ((reference_timestamp == 0 && !GST_CLOCK_TIME_IS_VALID (timestamp))
800           || diff == 0)
801         break;
802     }
803   }
804
805   if (best_id) {
806     for (l = frames; l && l != best_l; l = l->next) {
807       GstVideoCodecFrame *tmp = l->data;
808       BufferIdentification *id = gst_video_codec_frame_get_user_data (tmp);
809       guint64 diff_time, diff_frames;
810
811       if (id->timestamp > best_timestamp)
812         break;
813
814       if (id->timestamp == 0 || best_timestamp == 0)
815         diff_time = 0;
816       else
817         diff_time = best_timestamp - id->timestamp;
818       diff_frames = best->system_frame_number - tmp->system_frame_number;
819
820       if (diff_time > MAX_FRAME_DIST_TIME
821           || diff_frames > MAX_FRAME_DIST_FRAMES) {
822         finish_frames =
823             g_list_prepend (finish_frames, gst_video_codec_frame_ref (tmp));
824       }
825     }
826   }
827
828   if (finish_frames) {
829     g_warning ("%s: Too old frames, bug in encoder -- please file a bug",
830         GST_ELEMENT_NAME (self));
831     for (l = finish_frames; l; l = l->next) {
832       gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (self), l->data);
833     }
834   }
835
836   if (best)
837     gst_video_codec_frame_ref (best);
838
839   g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
840   g_list_free (frames);
841
842   return best;
843 }
844
845 static gboolean
846 gst_amc_video_enc_set_src_caps (GstAmcVideoEnc * self, GstAmcFormat * format)
847 {
848   GstCaps *caps;
849   GstVideoCodecState *output_state;
850
851   caps = caps_from_amc_format (format);
852   if (!caps) {
853     GST_ERROR_OBJECT (self, "Failed to create output caps");
854     return FALSE;
855   }
856
857   /* It may not be proper to reference self->input_state here,
858    * because MediaCodec is an async model -- input_state may change multiple times,
859    * the passed-in MediaFormat may not be the one matched to the current input_state.
860    *
861    * Though, currently, the final src caps only calculate
862    * width/height/pixel-aspect-ratio/framerate/codec_data from self->input_state.
863    *
864    * If input width/height/codec_data change(is_format_change), it will restart
865    * MediaCodec, which means in these cases, self->input_state is matched.
866    */
867   output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
868       caps, self->input_state);
869   gst_video_codec_state_unref (output_state);
870
871   if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self)))
872     return FALSE;
873
874   return TRUE;
875 }
876
877 /* The weird handling of cropping, alignment and everything is taken from
878  * platform/frameworks/media/libstagefright/colorconversion/ColorConversion.cpp
879  */
880 static gboolean
881 gst_amc_video_enc_fill_buffer (GstAmcVideoEnc * self, GstBuffer * inbuf,
882     GstAmcBuffer * outbuf, const GstAmcBufferInfo * buffer_info)
883 {
884   GstVideoCodecState *input_state = self->input_state;
885   /* The fill_buffer runs in the same thread as set_format?
886    * then we can use state->info safely */
887   GstVideoInfo *info = &input_state->info;
888
889   if (buffer_info->size < self->color_format_info.frame_size)
890     return FALSE;
891
892   return gst_amc_color_format_copy (&self->color_format_info, outbuf,
893       buffer_info, info, inbuf, COLOR_FORMAT_COPY_IN);
894 }
895
896 static GstFlowReturn
897 gst_amc_video_enc_handle_output_frame (GstAmcVideoEnc * self,
898     GstAmcBuffer * buf, const GstAmcBufferInfo * buffer_info,
899     GstVideoCodecFrame * frame)
900 {
901   GstFlowReturn flow_ret = GST_FLOW_OK;
902   GstVideoEncoder *encoder = GST_VIDEO_ENCODER_CAST (self);
903
904   /* The BUFFER_FLAG_CODEC_CONFIG logic is borrowed from
905    * gst-omx. see *_handle_output_frame in
906    * gstomxvideoenc.c and gstomxh264enc.c */
907   if ((buffer_info->flags & BUFFER_FLAG_CODEC_CONFIG)
908       && buffer_info->size > 0) {
909     GstStructure *s;
910     GstVideoCodecState *state;
911
912     state = gst_video_encoder_get_output_state (encoder);
913     s = gst_caps_get_structure (state->caps, 0);
914     if (!strcmp (gst_structure_get_name (s), "video/x-h264")) {
915       gst_video_codec_state_unref (state);
916
917       if (buffer_info->size > 4 &&
918           GST_READ_UINT32_BE (buf->data + buffer_info->offset) == 0x00000001) {
919         GList *l = NULL;
920         GstBuffer *hdrs;
921
922         GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format");
923
924         hdrs = gst_buffer_new_and_alloc (buffer_info->size);
925         gst_buffer_fill (hdrs, 0, buf->data + buffer_info->offset,
926             buffer_info->size);
927         GST_BUFFER_PTS (hdrs) =
928             gst_util_uint64_scale (buffer_info->presentation_time_us,
929             GST_USECOND, 1);
930
931         l = g_list_append (l, hdrs);
932         gst_video_encoder_set_headers (encoder, l);
933       }
934     } else {
935       GstBuffer *codec_data;
936
937       GST_DEBUG_OBJECT (self, "Handling codec data");
938
939       codec_data = gst_buffer_new_and_alloc (buffer_info->size);
940       gst_buffer_fill (codec_data, 0, buf->data + buffer_info->offset,
941           buffer_info->size);
942       state->codec_data = codec_data;
943       gst_video_codec_state_unref (state);
944
945       if (!gst_video_encoder_negotiate (encoder)) {
946         gst_video_codec_frame_unref (frame);
947         return GST_FLOW_NOT_NEGOTIATED;
948       }
949
950       return GST_FLOW_OK;
951     }
952   }
953
954   if (buffer_info->size > 0) {
955     GstBuffer *out_buf;
956     GstPad *srcpad;
957
958     srcpad = GST_VIDEO_ENCODER_SRC_PAD (encoder);
959     out_buf =
960         gst_video_encoder_allocate_output_buffer (encoder, buffer_info->size);
961     gst_buffer_fill (out_buf, 0, buf->data + buffer_info->offset,
962         buffer_info->size);
963
964     GST_BUFFER_PTS (out_buf) =
965         gst_util_uint64_scale (buffer_info->presentation_time_us, GST_USECOND,
966         1);
967
968     if (frame) {
969       frame->output_buffer = out_buf;
970       flow_ret = gst_video_encoder_finish_frame (encoder, frame);
971     } else {
972       /* This sometimes happens at EOS or if the input is not properly framed,
973        * let's handle it gracefully by allocating a new buffer for the current
974        * caps and filling it
975        */
976
977       GST_ERROR_OBJECT (self, "No corresponding frame found");
978       flow_ret = gst_pad_push (srcpad, out_buf);
979     }
980   } else if (frame) {
981     flow_ret = gst_video_encoder_finish_frame (encoder, frame);
982   }
983
984   return flow_ret;
985 }
986
987 static void
988 gst_amc_video_enc_loop (GstAmcVideoEnc * self)
989 {
990   GstVideoCodecFrame *frame;
991   GstFlowReturn flow_ret = GST_FLOW_OK;
992   gboolean is_eos;
993   GstAmcBufferInfo buffer_info;
994   GstAmcBuffer *buf;
995   gint idx;
996   GError *err = NULL;
997
998   GST_VIDEO_ENCODER_STREAM_LOCK (self);
999
1000 retry:
1001   GST_DEBUG_OBJECT (self, "Waiting for available output buffer");
1002   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1003   /* Wait at most 100ms here, some codecs don't fail dequeueing if
1004    * the codec is flushing, causing deadlocks during shutdown */
1005   idx =
1006       gst_amc_codec_dequeue_output_buffer (self->codec, &buffer_info, 100000,
1007       &err);
1008   GST_VIDEO_ENCODER_STREAM_LOCK (self);
1009   /*} */
1010
1011   if (idx < 0 || self->amc_format) {
1012     if (self->flushing) {
1013       g_clear_error (&err);
1014       goto flushing;
1015     }
1016
1017     /* The comments from https://android.googlesource.com/platform/cts/+/android-4.3_r3.1/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
1018      * line 539 says INFO_OUTPUT_FORMAT_CHANGED is not expected for an encoder
1019      */
1020     if (self->amc_format || idx == INFO_OUTPUT_FORMAT_CHANGED) {
1021       GstAmcFormat *format;
1022       gchar *format_string;
1023
1024       GST_DEBUG_OBJECT (self, "Output format has changed");
1025
1026       format = (idx == INFO_OUTPUT_FORMAT_CHANGED) ?
1027           gst_amc_codec_get_output_format (self->codec,
1028           &err) : self->amc_format;
1029       if (err) {
1030         format = self->amc_format;
1031         GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1032       }
1033
1034       if (self->amc_format) {
1035         if (format != self->amc_format)
1036           gst_amc_format_free (self->amc_format);
1037         self->amc_format = NULL;
1038       }
1039
1040       if (!format)
1041         goto format_error;
1042
1043       format_string = gst_amc_format_to_string (format, &err);
1044       if (err) {
1045         gst_amc_format_free (format);
1046         goto format_error;
1047       }
1048       GST_DEBUG_OBJECT (self, "Got new output format: %s", format_string);
1049       g_free (format_string);
1050
1051       if (!gst_amc_video_enc_set_src_caps (self, format)) {
1052         gst_amc_format_free (format);
1053         goto format_error;
1054       }
1055
1056       gst_amc_format_free (format);
1057
1058       if (idx >= 0)
1059         goto process_buffer;
1060
1061       goto retry;
1062     }
1063
1064     switch (idx) {
1065       case INFO_OUTPUT_BUFFERS_CHANGED:
1066         /* Handled internally */
1067         g_assert_not_reached ();
1068         break;
1069       case INFO_TRY_AGAIN_LATER:
1070         GST_DEBUG_OBJECT (self, "Dequeueing output buffer timed out");
1071         goto retry;
1072         break;
1073       case G_MININT:
1074         GST_ERROR_OBJECT (self, "Failure dequeueing input buffer");
1075         goto dequeue_error;
1076         break;
1077       default:
1078         g_assert_not_reached ();
1079         break;
1080     }
1081
1082     goto retry;
1083   }
1084
1085 process_buffer:
1086   GST_DEBUG_OBJECT (self,
1087       "Got output buffer at index %d: size %d time %" G_GINT64_FORMAT
1088       " flags 0x%08x", idx, buffer_info.size, buffer_info.presentation_time_us,
1089       buffer_info.flags);
1090
1091   buf = gst_amc_codec_get_output_buffer (self->codec, idx, &err);
1092   if (err) {
1093     if (self->flushing) {
1094       g_clear_error (&err);
1095       goto flushing;
1096     }
1097     goto failed_to_get_output_buffer;
1098   } else if (!buf) {
1099     goto got_null_output_buffer;
1100   }
1101
1102   frame =
1103       _find_nearest_frame (self,
1104       gst_util_uint64_scale (buffer_info.presentation_time_us, GST_USECOND, 1));
1105
1106   is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM);
1107
1108   flow_ret =
1109       gst_amc_video_enc_handle_output_frame (self, buf, &buffer_info, frame);
1110
1111   gst_amc_buffer_free (buf);
1112   buf = NULL;
1113
1114   if (!gst_amc_codec_release_output_buffer (self->codec, idx, FALSE, &err)) {
1115     if (self->flushing) {
1116       g_clear_error (&err);
1117       goto flushing;
1118     }
1119     goto failed_release;
1120   }
1121
1122   if (is_eos || flow_ret == GST_FLOW_EOS) {
1123     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1124     g_mutex_lock (&self->drain_lock);
1125     if (self->draining) {
1126       GST_DEBUG_OBJECT (self, "Drained");
1127       self->draining = FALSE;
1128       g_cond_broadcast (&self->drain_cond);
1129     } else if (flow_ret == GST_FLOW_OK) {
1130       GST_DEBUG_OBJECT (self, "Component signalled EOS");
1131       flow_ret = GST_FLOW_EOS;
1132     }
1133     g_mutex_unlock (&self->drain_lock);
1134     GST_VIDEO_ENCODER_STREAM_LOCK (self);
1135   } else {
1136     GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
1137   }
1138
1139   self->downstream_flow_ret = flow_ret;
1140
1141   if (flow_ret != GST_FLOW_OK)
1142     goto flow_error;
1143
1144   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1145
1146   return;
1147
1148 dequeue_error:
1149   {
1150     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1151     gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
1152     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1153     self->downstream_flow_ret = GST_FLOW_ERROR;
1154     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1155     g_mutex_lock (&self->drain_lock);
1156     self->draining = FALSE;
1157     g_cond_broadcast (&self->drain_cond);
1158     g_mutex_unlock (&self->drain_lock);
1159     return;
1160   }
1161
1162 format_error:
1163   {
1164     if (err)
1165       GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1166     else
1167       GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
1168           ("Failed to handle format"));
1169     gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
1170     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1171     self->downstream_flow_ret = GST_FLOW_ERROR;
1172     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1173     g_mutex_lock (&self->drain_lock);
1174     self->draining = FALSE;
1175     g_cond_broadcast (&self->drain_cond);
1176     g_mutex_unlock (&self->drain_lock);
1177     return;
1178   }
1179 failed_release:
1180   {
1181     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1182     gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
1183     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1184     self->downstream_flow_ret = GST_FLOW_ERROR;
1185     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1186     g_mutex_lock (&self->drain_lock);
1187     self->draining = FALSE;
1188     g_cond_broadcast (&self->drain_cond);
1189     g_mutex_unlock (&self->drain_lock);
1190     return;
1191   }
1192 flushing:
1193   {
1194     GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
1195     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1196     self->downstream_flow_ret = GST_FLOW_FLUSHING;
1197     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1198     return;
1199   }
1200
1201 flow_error:
1202   {
1203     if (flow_ret == GST_FLOW_EOS) {
1204       GST_DEBUG_OBJECT (self, "EOS");
1205       gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
1206           gst_event_new_eos ());
1207       gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1208     } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
1209       GST_ELEMENT_FLOW_ERROR (self, flow_ret);
1210       gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self),
1211           gst_event_new_eos ());
1212       gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1213     }
1214     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1215     g_mutex_lock (&self->drain_lock);
1216     self->draining = FALSE;
1217     g_cond_broadcast (&self->drain_cond);
1218     g_mutex_unlock (&self->drain_lock);
1219     return;
1220   }
1221
1222 failed_to_get_output_buffer:
1223   {
1224     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1225     gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
1226     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1227     self->downstream_flow_ret = GST_FLOW_ERROR;
1228     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1229     g_mutex_lock (&self->drain_lock);
1230     self->draining = FALSE;
1231     g_cond_broadcast (&self->drain_cond);
1232     g_mutex_unlock (&self->drain_lock);
1233     return;
1234   }
1235
1236 got_null_output_buffer:
1237   {
1238     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1239         ("Got no output buffer"));
1240     gst_pad_push_event (GST_VIDEO_ENCODER_SRC_PAD (self), gst_event_new_eos ());
1241     gst_pad_pause_task (GST_VIDEO_ENCODER_SRC_PAD (self));
1242     self->downstream_flow_ret = GST_FLOW_ERROR;
1243     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1244     g_mutex_lock (&self->drain_lock);
1245     self->draining = FALSE;
1246     g_cond_broadcast (&self->drain_cond);
1247     g_mutex_unlock (&self->drain_lock);
1248     return;
1249   }
1250 }
1251
1252 static gboolean
1253 gst_amc_video_enc_start (GstVideoEncoder * encoder)
1254 {
1255   GstAmcVideoEnc *self;
1256
1257   self = GST_AMC_VIDEO_ENC (encoder);
1258   self->last_upstream_ts = 0;
1259   self->drained = TRUE;
1260   self->downstream_flow_ret = GST_FLOW_OK;
1261   self->started = FALSE;
1262   self->flushing = TRUE;
1263
1264   return TRUE;
1265 }
1266
1267 static gboolean
1268 gst_amc_video_enc_stop (GstVideoEncoder * encoder)
1269 {
1270   GstAmcVideoEnc *self;
1271   GError *err = NULL;
1272
1273   self = GST_AMC_VIDEO_ENC (encoder);
1274   GST_DEBUG_OBJECT (self, "Stopping encoder");
1275   self->flushing = TRUE;
1276   if (self->started) {
1277     gst_amc_codec_flush (self->codec, &err);
1278     if (err)
1279       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1280     gst_amc_codec_stop (self->codec, &err);
1281     if (err)
1282       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1283     self->started = FALSE;
1284   }
1285   gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1286
1287   self->downstream_flow_ret = GST_FLOW_FLUSHING;
1288   self->drained = TRUE;
1289   g_mutex_lock (&self->drain_lock);
1290   self->draining = FALSE;
1291   g_cond_broadcast (&self->drain_cond);
1292   g_mutex_unlock (&self->drain_lock);
1293   if (self->input_state)
1294     gst_video_codec_state_unref (self->input_state);
1295   self->input_state = NULL;
1296
1297   if (self->amc_format) {
1298     gst_amc_format_free (self->amc_format);
1299     self->amc_format = NULL;
1300   }
1301
1302   GST_DEBUG_OBJECT (self, "Stopped encoder");
1303   return TRUE;
1304 }
1305
1306 static gboolean
1307 gst_amc_video_enc_set_format (GstVideoEncoder * encoder,
1308     GstVideoCodecState * state)
1309 {
1310   GstAmcVideoEnc *self;
1311   GstAmcFormat *format = NULL;
1312   GstCaps *allowed_caps = NULL;
1313   gboolean is_format_change = FALSE;
1314   gboolean needs_disable = FALSE;
1315   gchar *format_string;
1316   gboolean r = FALSE;
1317   GError *err = NULL;
1318
1319   self = GST_AMC_VIDEO_ENC (encoder);
1320
1321   GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, state->caps);
1322
1323   /* Check if the caps change is a real format change or if only irrelevant
1324    * parts of the caps have changed or nothing at all.
1325    */
1326   is_format_change |= self->color_format_info.width != state->info.width;
1327   is_format_change |= self->color_format_info.height != state->info.height;
1328   needs_disable = self->started;
1329
1330   /* If the component is not started and a real format change happens
1331    * we have to restart the component. If no real format change
1332    * happened we can just exit here.
1333    */
1334   if (needs_disable && !is_format_change) {
1335
1336     /* Framerate or something minor changed */
1337     if (self->input_state)
1338       gst_video_codec_state_unref (self->input_state);
1339     self->input_state = gst_video_codec_state_ref (state);
1340     GST_DEBUG_OBJECT (self,
1341         "Already running and caps did not change the format");
1342     return TRUE;
1343   }
1344
1345   if (needs_disable && is_format_change) {
1346     gst_amc_video_enc_drain (self);
1347     GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1348     gst_amc_video_enc_stop (GST_VIDEO_ENCODER (self));
1349     GST_VIDEO_ENCODER_STREAM_LOCK (self);
1350     gst_amc_video_enc_close (GST_VIDEO_ENCODER (self));
1351     if (!gst_amc_video_enc_open (GST_VIDEO_ENCODER (self))) {
1352       GST_ERROR_OBJECT (self, "Failed to open codec again");
1353       return FALSE;
1354     }
1355
1356     if (!gst_amc_video_enc_start (GST_VIDEO_ENCODER (self))) {
1357       GST_ERROR_OBJECT (self, "Failed to start codec again");
1358     }
1359   }
1360   /* srcpad task is not running at this point */
1361   if (self->input_state)
1362     gst_video_codec_state_unref (self->input_state);
1363   self->input_state = NULL;
1364
1365   GST_DEBUG_OBJECT (self, "picking an output format ...");
1366   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1367   if (!allowed_caps) {
1368     GST_DEBUG_OBJECT (self, "... but no peer, using template caps");
1369     allowed_caps =
1370         gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
1371   }
1372   GST_DEBUG_OBJECT (self, "chose caps %" GST_PTR_FORMAT, allowed_caps);
1373   allowed_caps = gst_caps_truncate (allowed_caps);
1374
1375   format = create_amc_format (self, state, allowed_caps);
1376   if (!format)
1377     goto quit;
1378
1379   format_string = gst_amc_format_to_string (format, &err);
1380   if (err)
1381     GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1382   GST_DEBUG_OBJECT (self, "Configuring codec with format: %s",
1383       GST_STR_NULL (format_string));
1384   g_free (format_string);
1385
1386   if (!gst_amc_codec_configure (self->codec, format, NULL, &err)) {
1387     GST_ERROR_OBJECT (self, "Failed to configure codec");
1388     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1389     goto quit;
1390   }
1391
1392   if (!gst_amc_codec_start (self->codec, &err)) {
1393     GST_ERROR_OBJECT (self, "Failed to start codec");
1394     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1395     goto quit;
1396   }
1397
1398   self->amc_format = format;
1399   format = NULL;
1400
1401   self->input_state = gst_video_codec_state_ref (state);
1402
1403   self->started = TRUE;
1404
1405   /* Start the srcpad loop again */
1406   self->flushing = FALSE;
1407   self->downstream_flow_ret = GST_FLOW_OK;
1408   gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
1409       (GstTaskFunction) gst_amc_video_enc_loop, encoder, NULL);
1410
1411   r = TRUE;
1412
1413 quit:
1414   if (allowed_caps)
1415     gst_caps_unref (allowed_caps);
1416
1417   if (format)
1418     gst_amc_format_free (format);
1419
1420   return r;
1421 }
1422
1423 static gboolean
1424 gst_amc_video_enc_flush (GstVideoEncoder * encoder)
1425 {
1426   GstAmcVideoEnc *self;
1427   GError *err = NULL;
1428
1429   self = GST_AMC_VIDEO_ENC (encoder);
1430
1431   GST_DEBUG_OBJECT (self, "Flushing encoder");
1432
1433   if (!self->started) {
1434     GST_DEBUG_OBJECT (self, "Codec not started yet");
1435     return TRUE;
1436   }
1437
1438   self->flushing = TRUE;
1439   gst_amc_codec_flush (self->codec, &err);
1440   if (err)
1441     GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1442
1443   /* Wait until the srcpad loop is finished,
1444    * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks
1445    * caused by using this lock from inside the loop function */
1446   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1447   GST_PAD_STREAM_LOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
1448   GST_PAD_STREAM_UNLOCK (GST_VIDEO_ENCODER_SRC_PAD (self));
1449   GST_VIDEO_ENCODER_STREAM_LOCK (self);
1450   self->flushing = FALSE;
1451
1452   /* Start the srcpad loop again */
1453   self->last_upstream_ts = 0;
1454   self->drained = TRUE;
1455   self->downstream_flow_ret = GST_FLOW_OK;
1456   gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
1457       (GstTaskFunction) gst_amc_video_enc_loop, encoder, NULL);
1458
1459   GST_DEBUG_OBJECT (self, "Flush encoder");
1460
1461   return TRUE;
1462 }
1463
1464 static GstFlowReturn
1465 gst_amc_video_enc_handle_frame (GstVideoEncoder * encoder,
1466     GstVideoCodecFrame * frame)
1467 {
1468   GstAmcVideoEnc *self;
1469   gint idx;
1470   GstAmcBuffer *buf;
1471   GstAmcBufferInfo buffer_info;
1472   GstClockTime timestamp, duration, timestamp_offset = 0;
1473   BufferIdentification *id;
1474   GError *err = NULL;
1475
1476   self = GST_AMC_VIDEO_ENC (encoder);
1477
1478   GST_DEBUG_OBJECT (self, "Handling frame");
1479
1480   if (!self->started) {
1481     GST_ERROR_OBJECT (self, "Codec not started yet");
1482     gst_video_codec_frame_unref (frame);
1483     return GST_FLOW_NOT_NEGOTIATED;
1484   }
1485
1486   if (self->flushing)
1487     goto flushing;
1488
1489   if (self->downstream_flow_ret != GST_FLOW_OK)
1490     goto downstream_error;
1491
1492   timestamp = frame->pts;
1493   duration = frame->duration;
1494
1495   if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
1496     if (gst_amc_codec_request_key_frame (self->codec, &err)) {
1497       GST_DEBUG_OBJECT (self, "Passed keyframe request to MediaCodec");
1498     }
1499     if (err) {
1500       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1501       g_clear_error (&err);
1502     }
1503   }
1504
1505 again:
1506   /* Make sure to release the base class stream lock, otherwise
1507    * _loop() can't call _finish_frame() and we might block forever
1508    * because no input buffers are released */
1509   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1510   /* Wait at most 100ms here, some codecs don't fail dequeueing if
1511    * the codec is flushing, causing deadlocks during shutdown */
1512   idx = gst_amc_codec_dequeue_input_buffer (self->codec, 100000, &err);
1513   GST_VIDEO_ENCODER_STREAM_LOCK (self);
1514
1515   if (idx < 0) {
1516     if (self->flushing || self->downstream_flow_ret == GST_FLOW_FLUSHING) {
1517       g_clear_error (&err);
1518       goto flushing;
1519     }
1520
1521     switch (idx) {
1522       case INFO_TRY_AGAIN_LATER:
1523         GST_DEBUG_OBJECT (self, "Dequeueing input buffer timed out");
1524         goto again;             /* next try */
1525         break;
1526       case G_MININT:
1527         GST_ERROR_OBJECT (self, "Failed to dequeue input buffer");
1528         goto dequeue_error;
1529       default:
1530         g_assert_not_reached ();
1531         break;
1532     }
1533
1534     goto again;
1535   }
1536
1537   if (self->flushing) {
1538     memset (&buffer_info, 0, sizeof (buffer_info));
1539     gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, NULL);
1540     goto flushing;
1541   }
1542
1543   if (self->downstream_flow_ret != GST_FLOW_OK) {
1544     memset (&buffer_info, 0, sizeof (buffer_info));
1545     gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err);
1546     if (err && !self->flushing)
1547       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1548     g_clear_error (&err);
1549     goto downstream_error;
1550   }
1551
1552   /* Now handle the frame */
1553
1554   /* Copy the buffer content in chunks of size as requested
1555    * by the port */
1556   buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
1557   if (err)
1558     goto failed_to_get_input_buffer;
1559   else if (!buf)
1560     goto got_null_input_buffer;
1561
1562   memset (&buffer_info, 0, sizeof (buffer_info));
1563   buffer_info.offset = 0;
1564   buffer_info.size = MIN (self->color_format_info.frame_size, buf->size);
1565   gst_amc_buffer_set_position_and_limit (buf, NULL, buffer_info.offset,
1566       buffer_info.size);
1567
1568   if (!gst_amc_video_enc_fill_buffer (self, frame->input_buffer, buf,
1569           &buffer_info)) {
1570     memset (&buffer_info, 0, sizeof (buffer_info));
1571     gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err);
1572     if (err && !self->flushing)
1573       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1574     g_clear_error (&err);
1575     gst_amc_buffer_free (buf);
1576     buf = NULL;
1577     goto buffer_fill_error;
1578   }
1579
1580   gst_amc_buffer_free (buf);
1581   buf = NULL;
1582
1583   if (timestamp != GST_CLOCK_TIME_NONE) {
1584     buffer_info.presentation_time_us =
1585         gst_util_uint64_scale (timestamp + timestamp_offset, 1, GST_USECOND);
1586     self->last_upstream_ts = timestamp + timestamp_offset;
1587   }
1588   if (duration != GST_CLOCK_TIME_NONE)
1589     self->last_upstream_ts += duration;
1590
1591   id = buffer_identification_new (timestamp + timestamp_offset);
1592   if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
1593     buffer_info.flags |= BUFFER_FLAG_SYNC_FRAME;
1594   gst_video_codec_frame_set_user_data (frame, id,
1595       (GDestroyNotify) buffer_identification_free);
1596
1597   GST_DEBUG_OBJECT (self,
1598       "Queueing buffer %d: size %d time %" G_GINT64_FORMAT " flags 0x%08x",
1599       idx, buffer_info.size, buffer_info.presentation_time_us,
1600       buffer_info.flags);
1601   if (!gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) {
1602     if (self->flushing) {
1603       g_clear_error (&err);
1604       goto flushing;
1605     }
1606     goto queue_error;
1607   }
1608
1609   self->drained = FALSE;
1610
1611   gst_video_codec_frame_unref (frame);
1612
1613   return self->downstream_flow_ret;
1614
1615 downstream_error:
1616   {
1617     GST_ERROR_OBJECT (self, "Downstream returned %s",
1618         gst_flow_get_name (self->downstream_flow_ret));
1619
1620     gst_video_codec_frame_unref (frame);
1621     return self->downstream_flow_ret;
1622   }
1623 failed_to_get_input_buffer:
1624   {
1625     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1626     gst_video_codec_frame_unref (frame);
1627     return GST_FLOW_ERROR;
1628   }
1629 got_null_input_buffer:
1630   {
1631     GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
1632         ("Got no input buffer"));
1633     gst_video_codec_frame_unref (frame);
1634     return GST_FLOW_ERROR;
1635   }
1636 buffer_fill_error:
1637   {
1638     GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL),
1639         ("Failed to write input into the amc buffer(write %dB to a %"
1640             G_GSIZE_FORMAT "B buffer)", self->color_format_info.frame_size,
1641             buf->size));
1642     gst_video_codec_frame_unref (frame);
1643     return GST_FLOW_ERROR;
1644   }
1645 dequeue_error:
1646   {
1647     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1648     gst_video_codec_frame_unref (frame);
1649     return GST_FLOW_ERROR;
1650   }
1651 queue_error:
1652   {
1653     GST_ELEMENT_ERROR_FROM_ERROR (self, err);
1654     gst_video_codec_frame_unref (frame);
1655     return GST_FLOW_ERROR;
1656   }
1657 flushing:
1658   {
1659     GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
1660     gst_video_codec_frame_unref (frame);
1661     return GST_FLOW_FLUSHING;
1662   }
1663 }
1664
1665 static GstFlowReturn
1666 gst_amc_video_enc_finish (GstVideoEncoder * encoder)
1667 {
1668   GstAmcVideoEnc *self;
1669
1670   self = GST_AMC_VIDEO_ENC (encoder);
1671
1672   return gst_amc_video_enc_drain (self);
1673 }
1674
1675 static GstFlowReturn
1676 gst_amc_video_enc_drain (GstAmcVideoEnc * self)
1677 {
1678   GstFlowReturn ret;
1679   gint idx;
1680   GError *err = NULL;
1681
1682   GST_DEBUG_OBJECT (self, "Draining codec");
1683   if (!self->started) {
1684     GST_DEBUG_OBJECT (self, "Codec not started yet");
1685     return GST_FLOW_OK;
1686   }
1687
1688   /* Don't send drain buffer twice, this doesn't work */
1689   if (self->drained) {
1690     GST_DEBUG_OBJECT (self, "Codec is drained already");
1691     return GST_FLOW_OK;
1692   }
1693
1694   /* Make sure to release the base class stream lock, otherwise
1695    * _loop() can't call _finish_frame() and we might block forever
1696    * because no input buffers are released */
1697   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1698   /* Send an EOS buffer to the component and let the base
1699    * class drop the EOS event. We will send it later when
1700    * the EOS buffer arrives on the output port.
1701    * Wait at most 0.5s here. */
1702   idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000, &err);
1703   GST_VIDEO_ENCODER_STREAM_LOCK (self);
1704
1705   if (idx >= 0) {
1706     GstAmcBuffer *buf;
1707     GstAmcBufferInfo buffer_info;
1708
1709     buf = gst_amc_codec_get_input_buffer (self->codec, idx, &err);
1710     if (buf) {
1711       GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
1712       g_mutex_lock (&self->drain_lock);
1713       self->draining = TRUE;
1714
1715       memset (&buffer_info, 0, sizeof (buffer_info));
1716       buffer_info.size = 0;
1717       buffer_info.presentation_time_us =
1718           gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
1719       buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
1720
1721       gst_amc_buffer_set_position_and_limit (buf, NULL, 0, 0);
1722       gst_amc_buffer_free (buf);
1723       buf = NULL;
1724
1725       if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info,
1726               &err)) {
1727         GST_DEBUG_OBJECT (self, "Waiting until codec is drained");
1728         g_cond_wait (&self->drain_cond, &self->drain_lock);
1729         GST_DEBUG_OBJECT (self, "Drained codec");
1730         ret = GST_FLOW_OK;
1731       } else {
1732         GST_ERROR_OBJECT (self, "Failed to queue input buffer");
1733         if (self->flushing) {
1734           g_clear_error (&err);
1735           ret = GST_FLOW_FLUSHING;
1736         } else {
1737           GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1738           ret = GST_FLOW_ERROR;
1739         }
1740       }
1741
1742       self->drained = TRUE;
1743       self->draining = FALSE;
1744       g_mutex_unlock (&self->drain_lock);
1745       GST_VIDEO_ENCODER_STREAM_LOCK (self);
1746     } else {
1747       GST_ERROR_OBJECT (self, "Failed to get buffer for EOS: %d", idx);
1748       if (err)
1749         GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1750       ret = GST_FLOW_ERROR;
1751     }
1752   } else {
1753     GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", idx);
1754     if (err)
1755       GST_ELEMENT_WARNING_FROM_ERROR (self, err);
1756     ret = GST_FLOW_ERROR;
1757   }
1758
1759   return ret;
1760 }