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