androidmedia: Port to 1.0
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 18 Oct 2012 14:41:07 +0000 (16:41 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 16 Apr 2013 10:57:09 +0000 (12:57 +0200)
configure.ac
sys/androidmedia/gstamc.c
sys/androidmedia/gstamc.h
sys/androidmedia/gstamcaudiodec.c
sys/androidmedia/gstamcaudiodec.h
sys/androidmedia/gstamcvideodec.c
sys/androidmedia/gstamcvideodec.h

index bc2be1b9e509b29836cf559f1da4bc3e6e21be78..6c7c5c0c199434d9c5bbacaf975c28383e27b737 100644 (file)
@@ -487,7 +487,7 @@ AG_GST_DEFAULT_ELEMENTS
 dnl *** plug-ins to include ***
 dnl Non ported plugins (non-dependant, then dependant)
 dnl Make sure you have a space before and after all plugins
-GST_PLUGINS_NONPORTED=" androidmedia aiff \
+GST_PLUGINS_NONPORTED=" aiff \
  cdxaparse \
  dccp faceoverlay \
  freeverb \
index 205b8502f175d0a60b710f1baf65359cbcefef0a..a1153b5a6850ab39ea44d64faea396057d989839 100644 (file)
@@ -28,6 +28,7 @@
 #include "gstamcvideodec.h"
 #include "gstamcaudiodec.h"
 
+#include <gmodule.h>
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <gst/audio/audio.h>
@@ -1169,20 +1170,20 @@ done:
 
 gboolean
 gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
-    GstBuffer ** value)
+    guint8 ** data, gsize * size)
 {
   JNIEnv *env;
   gboolean ret = FALSE;
   jstring key_str = NULL;
   jobject v = NULL;
-  guint8 *data;
-  gsize size;
 
   g_return_val_if_fail (format != NULL, FALSE);
   g_return_val_if_fail (key != NULL, FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+  g_return_val_if_fail (size != NULL, FALSE);
 
-  *value = 0;
+  *data = NULL;
+  *size = 0;
   env = gst_amc_get_jni_env ();
 
   key_str = (*env)->NewStringUTF (env, key);
@@ -1197,15 +1198,14 @@ gst_amc_format_get_buffer (GstAmcFormat * format, const gchar * key,
     goto done;
   }
 
-  data = (*env)->GetDirectBufferAddress (env, v);
+  *data = (*env)->GetDirectBufferAddress (env, v);
   if (!data) {
     (*env)->ExceptionClear (env);
     GST_ERROR ("Failed to get buffer address");
     goto done;
   }
-  size = (*env)->GetDirectBufferCapacity (env, v);
-  *value = gst_buffer_new_and_alloc (size);
-  memcpy (GST_BUFFER_DATA (*value), data, size);
+  *size = (*env)->GetDirectBufferCapacity (env, v);
+  *data = g_memdup (*data, *size);
 
   ret = TRUE;
 
@@ -1220,7 +1220,7 @@ done:
 
 void
 gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
-    GstBuffer * value)
+    guint8 * data, gsize size)
 {
   JNIEnv *env;
   jstring key_str = NULL;
@@ -1228,7 +1228,7 @@ gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
 
   g_return_if_fail (format != NULL);
   g_return_if_fail (key != NULL);
-  g_return_if_fail (value != NULL);
+  g_return_if_fail (data != NULL);
 
   env = gst_amc_get_jni_env ();
 
@@ -1236,9 +1236,8 @@ gst_amc_format_set_buffer (GstAmcFormat * format, const gchar * key,
   if (!key_str)
     goto done;
 
-  /* FIXME: The buffer must remain valid until the codec is stopped */
-  v = (*env)->NewDirectByteBuffer (env, GST_BUFFER_DATA (value),
-      GST_BUFFER_SIZE (value));
+  /* FIXME: The memory must remain valid until the codec is stopped */
+  v = (*env)->NewDirectByteBuffer (env, data, size);
   if (!v)
     goto done;
 
@@ -2016,7 +2015,7 @@ scan_codecs (GstPlugin * plugin)
    * number is limited by 64 in Android).
    */
   if (ret) {
-    GstStructure *new_cache_data = gst_structure_empty_new ("gst-amc-cache");
+    GstStructure *new_cache_data = gst_structure_new_empty ("gst-amc-cache");
     GList *l;
     GValue arr = { 0, };
 
@@ -2025,7 +2024,7 @@ scan_codecs (GstPlugin * plugin)
     for (l = codec_infos; l; l = l->next) {
       GstAmcCodecInfo *gst_codec_info = l->data;
       GValue cv = { 0, };
-      GstStructure *cs = gst_structure_empty_new ("gst-amc-codec");
+      GstStructure *cs = gst_structure_new_empty ("gst-amc-codec");
       GValue starr = { 0, };
       gint i;
 
@@ -2036,7 +2035,7 @@ scan_codecs (GstPlugin * plugin)
 
       for (i = 0; i < gst_codec_info->n_supported_types; i++) {
         GstAmcCodecType *gst_codec_type = &gst_codec_info->supported_types[i];
-        GstStructure *sts = gst_structure_empty_new ("gst-amc-supported-type");
+        GstStructure *sts = gst_structure_new_empty ("gst-amc-supported-type");
         GValue stv = { 0, };
         GValue tmparr = { 0, };
         gint j;
@@ -2497,7 +2496,7 @@ static const struct
   CHANNEL_OUT_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
   CHANNEL_OUT_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
   CHANNEL_OUT_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
-  CHANNEL_OUT_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, {
+  CHANNEL_OUT_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1}, {
   CHANNEL_OUT_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
   CHANNEL_OUT_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
   CHANNEL_OUT_FRONT_LEFT_OF_CENTER,
@@ -2516,21 +2515,21 @@ static const struct
   CHANNEL_OUT_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_INVALID}
 };
 
-GstAudioChannelPosition *
-gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels)
+gboolean
+gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels,
+    GstAudioChannelPosition * pos)
 {
-  GstAudioChannelPosition *pos = g_new0 (GstAudioChannelPosition, channels);
   gint i, j;
 
   if (channel_mask == 0) {
     if (channels == 1) {
-      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
-      return pos;
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+      return TRUE;
     }
     if (channels == 2) {
       pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
       pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
-      return pos;
+      return TRUE;
     }
 
     /* Now let the guesswork begin, these are the
@@ -2567,10 +2566,10 @@ gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels)
     if ((channel_mask & channel_mapping_table[i].mask)) {
       pos[j++] = channel_mapping_table[i].pos;
       if (channel_mapping_table[i].pos == GST_AUDIO_CHANNEL_POSITION_INVALID) {
-        g_free (pos);
+        memset (pos, 0, sizeof (GstAudioChannelPosition) * channels);
         GST_ERROR ("Unable to map channel mask 0x%08x",
             channel_mapping_table[i].mask);
-        return NULL;
+        return FALSE;
       }
       if (j == channels)
         break;
@@ -2578,13 +2577,13 @@ gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels)
   }
 
   if (j != channels) {
-    g_free (pos);
+    memset (pos, 0, sizeof (GstAudioChannelPosition) * channels);
     GST_ERROR ("Unable to map all channel positions in mask 0x%08x",
         channel_mask);
-    return NULL;
+    return FALSE;
   }
 
-  return pos;
+  return TRUE;
 }
 
 guint32
@@ -2813,18 +2812,9 @@ plugin_init (GstPlugin * plugin)
   return TRUE;
 }
 
-#ifdef GST_PLUGIN_DEFINE2
-GST_PLUGIN_DEFINE2 (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    androidmedia,
-    "Android Media plugin",
-    plugin_init,
-    PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
-#else
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
-    "androidmedia",
+    androidmedia,
     "Android Media plugin",
     plugin_init,
     PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
-#endif
index 9568b4939e28fcd427a8c6998b5dc6433ca5807b..b48a3ee7cc79f6d429a7928209ea6ca5b459c2f1 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <gst/gst.h>
 #include <gst/video/video.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 #include <jni.h>
 
 G_BEGIN_DECLS
@@ -116,8 +116,8 @@ gboolean gst_amc_format_get_int (GstAmcFormat *format, const gchar *key, gint *v
 void gst_amc_format_set_int (GstAmcFormat *format, const gchar *key, gint value);
 gboolean gst_amc_format_get_string (GstAmcFormat *format, const gchar *key, gchar **value);
 void gst_amc_format_set_string (GstAmcFormat *format, const gchar *key, const gchar *value);
-gboolean gst_amc_format_get_buffer (GstAmcFormat *format, const gchar *key, GstBuffer **value);
-void gst_amc_format_set_buffer (GstAmcFormat *format, const gchar *key, GstBuffer *value);
+gboolean gst_amc_format_get_buffer (GstAmcFormat *format, const gchar *key, guint8 **data, gsize *size);
+void gst_amc_format_set_buffer (GstAmcFormat *format, const gchar *key, guint8 *data, gsize size);
 
 GstVideoFormat gst_amc_color_format_to_video_format (gint color_format);
 gint gst_amc_video_format_to_color_format (GstVideoFormat video_format);
@@ -137,7 +137,7 @@ gint gst_amc_mpeg4_level_from_string (const gchar *level);
 const gchar * gst_amc_aac_profile_to_string (gint profile);
 gint gst_amc_aac_profile_from_string (const gchar *profile);
 
-GstAudioChannelPosition* gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels);
+gboolean gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels, GstAudioChannelPosition *pos);
 guint32 gst_amc_audio_channel_mask_from_positions (GstAudioChannelPosition *positions, gint channels);
 
 G_END_DECLS
index 31a8bf5f22764943daf1afad0e5e765f07c15474..886556ae20a21ae8cf9280623890ccc48fc19e94 100644 (file)
@@ -28,7 +28,7 @@
 #endif
 
 #include <gst/gst.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 #include <string.h>
 
 #ifdef HAVE_ORC
@@ -69,11 +69,12 @@ enum
 
 /* class initialization */
 
-#define DEBUG_INIT(bla) \
+#define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_amc_audio_dec_debug_category, "amcaudiodec", 0, \
       "Android MediaCodec audio decoder");
+#define parent_class gst_amc_audio_dec_parent_class
 
-GST_BOILERPLATE_FULL (GstAmcAudioDec, gst_amc_audio_dec, GstAudioDecoder,
+G_DEFINE_TYPE_WITH_CODE (GstAmcAudioDec, gst_amc_audio_dec,
     GST_TYPE_AUDIO_DECODER, DEBUG_INIT);
 
 static GstCaps *
@@ -95,21 +96,21 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/3gpp") == 0) {
       GstStructure *tmp;
 
       tmp = gst_structure_new ("audio/AMR",
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/amr-wb") == 0) {
       GstStructure *tmp;
 
       tmp = gst_structure_new ("audio/AMR-WB",
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/mp4a-latm") == 0) {
       gint j;
       GstStructure *tmp, *tmp2;
@@ -147,13 +148,13 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
 
         tmp2 = gst_structure_copy (tmp);
         gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL);
-        gst_caps_merge_structure (ret, tmp2);
+        ret = gst_caps_merge_structure (ret, tmp2);
 
         have_profile = TRUE;
       }
 
       if (!have_profile) {
-        gst_caps_merge_structure (ret, tmp);
+        ret = gst_caps_merge_structure (ret, tmp);
       } else {
         gst_structure_free (tmp);
       }
@@ -163,21 +164,21 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
       tmp = gst_structure_new ("audio/x-alaw",
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/g711-mlaw") == 0) {
       GstStructure *tmp;
 
       tmp = gst_structure_new ("audio/x-mulaw",
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/vorbis") == 0) {
       GstStructure *tmp;
 
       tmp = gst_structure_new ("audio/x-vorbis",
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/flac") == 0) {
       GstStructure *tmp;
 
@@ -185,7 +186,7 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "audio/mpeg-L2") == 0) {
       GstStructure *tmp;
 
@@ -195,7 +196,7 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
           "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else {
       GST_WARNING ("Unsupported mimetype '%s'", type->mime);
     }
@@ -264,22 +265,38 @@ create_src_caps (const GstAmcCodecInfo * codec_info)
 }
 
 static void
-gst_amc_audio_dec_base_init (gpointer g_class)
+gst_amc_audio_dec_class_init (GstAmcAudioDecClass * klass)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  GstAmcAudioDecClass *audiodec_class = GST_AMC_AUDIO_DEC_CLASS (g_class);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstAudioDecoderClass *audiodec_class = GST_AUDIO_DECODER_CLASS (klass);
+  GstAmcAudioDecClass *amcaudiodec_class = GST_AMC_AUDIO_DEC_CLASS (klass);
   const GstAmcCodecInfo *codec_info;
   GstPadTemplate *templ;
   GstCaps *caps;
   gchar *longname;
 
+  gobject_class->finalize = gst_amc_audio_dec_finalize;
+
+  element_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_amc_audio_dec_change_state);
+
+  audiodec_class->start = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_start);
+  audiodec_class->stop = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_stop);
+  audiodec_class->open = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_open);
+  audiodec_class->close = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_close);
+  audiodec_class->flush = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_flush);
+  audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_set_format);
+  audiodec_class->handle_frame =
+      GST_DEBUG_FUNCPTR (gst_amc_audio_dec_handle_frame);
+
   codec_info =
-      g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), gst_amc_codec_info_quark);
+      g_type_get_qdata (G_TYPE_FROM_CLASS (klass), gst_amc_codec_info_quark);
   /* This happens for the base class and abstract subclasses */
   if (!codec_info)
     return;
 
-  audiodec_class->codec_info = codec_info;
+  amcaudiodec_class->codec_info = codec_info;
 
   /* Add pad templates */
   caps = create_sink_caps (codec_info);
@@ -293,7 +310,7 @@ gst_amc_audio_dec_base_init (gpointer g_class)
   gst_object_unref (templ);
 
   longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name);
-  gst_element_class_set_details_simple (element_class,
+  gst_element_class_set_metadata (element_class,
       codec_info->name,
       "Codec/Decoder/Audio",
       longname, "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
@@ -301,31 +318,7 @@ gst_amc_audio_dec_base_init (gpointer g_class)
 }
 
 static void
-gst_amc_audio_dec_class_init (GstAmcAudioDecClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstAudioDecoderClass *audiodec_class = GST_AUDIO_DECODER_CLASS (klass);
-
-  gobject_class->finalize = gst_amc_audio_dec_finalize;
-
-  element_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_amc_audio_dec_change_state);
-
-  audiodec_class->start = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_start);
-  audiodec_class->stop = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_stop);
-#if 0
-  audiodec_class->open = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_open);
-  audiodec_class->close = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_close);
-#endif
-  audiodec_class->flush = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_flush);
-  audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_amc_audio_dec_set_format);
-  audiodec_class->handle_frame =
-      GST_DEBUG_FUNCPTR (gst_amc_audio_dec_handle_frame);
-}
-
-static void
-gst_amc_audio_dec_init (GstAmcAudioDec * self, GstAmcAudioDecClass * klass)
+gst_amc_audio_dec_init (GstAmcAudioDec * self)
 {
   gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (self), TRUE);
   gst_audio_decoder_set_drainable (GST_AUDIO_DECODER (self), TRUE);
@@ -400,8 +393,6 @@ gst_amc_audio_dec_change_state (GstElement * element, GstStateChange transition)
       self->downstream_flow_ret = GST_FLOW_OK;
       self->draining = FALSE;
       self->started = FALSE;
-      if (!gst_amc_audio_dec_open (GST_AUDIO_DECODER (self)))
-        return GST_STATE_CHANGE_FAILURE;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
@@ -429,9 +420,7 @@ gst_amc_audio_dec_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      if (!gst_amc_audio_dec_close (GST_AUDIO_DECODER (self)))
-        return GST_STATE_CHANGE_FAILURE;
-      self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+      self->downstream_flow_ret = GST_FLOW_FLUSHING;
       self->started = FALSE;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -449,6 +438,7 @@ gst_amc_audio_dec_set_src_caps (GstAmcAudioDec * self, GstAmcFormat * format)
   GstCaps *caps;
   gint rate, channels;
   guint32 channel_mask = 0;
+  GstAudioChannelPosition to[64];
 
   if (!gst_amc_format_get_int (format, "sample-rate", &rate) ||
       !gst_amc_format_get_int (format, "channel-count", &channels)) {
@@ -465,26 +455,23 @@ gst_amc_audio_dec_set_src_caps (GstAmcAudioDec * self, GstAmcFormat * format)
   if (gst_amc_format_contains_key (format, "channel-mask"))
     gst_amc_format_get_int (format, "channel-mask", (gint *) & channel_mask);
 
-  if (self->positions)
-    g_free (self->positions);
-  self->positions =
-      gst_amc_audio_channel_mask_to_positions (channel_mask, channels);
+  gst_amc_audio_channel_mask_to_positions (channel_mask, channels,
+      self->positions);
+  memcpy (to, self->positions, sizeof (to));
+  gst_audio_channel_positions_to_valid_order (to, channels);
+  self->needs_reorder =
+      (memcmp (self->positions, to,
+          sizeof (GstAudioChannelPosition) * channels) != 0);
+  if (self->needs_reorder)
+    gst_audio_get_channel_reorder_map (channels, self->positions, to,
+        self->reorder_map);
 
+  gst_audio_info_init (&self->info);
+  gst_audio_info_set_format (&self->info, GST_AUDIO_FORMAT_S16, rate, channels,
+      to);
 
-  caps = gst_caps_new_simple ("audio/x-raw-int",
-      "rate", G_TYPE_INT, rate,
-      "channels", G_TYPE_INT, channels,
-      "width", G_TYPE_INT, 16,
-      "depth", G_TYPE_INT, 16,
-      "signed", G_TYPE_BOOLEAN, TRUE,
-      "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
+  caps = gst_audio_info_to_caps (&self->info);
 
-  if (self->positions)
-    gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0),
-        self->positions);
-
-  self->channels = channels;
-  self->rate = rate;
   gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (self), caps);
   gst_caps_unref (caps);
 
@@ -592,6 +579,7 @@ retry:
     GstAmcAudioDecClass *klass = GST_AMC_AUDIO_DEC_GET_CLASS (self);
     GstBuffer *outbuf;
     GstAmcBuffer *buf;
+    GstMapInfo minfo;
 
     /* This sometimes happens at EOS or if the input is not properly framed,
      * let's handle it gracefully by allocating a new buffer for the current
@@ -610,13 +598,33 @@ retry:
       }
     }
 
-    outbuf = gst_buffer_try_new_and_alloc (buffer_info.size);
+    outbuf =
+        gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (self),
+        buffer_info.size);
     if (!outbuf)
       goto failed_allocate;
 
+    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
     buf = &self->output_buffers[idx];
-    orc_memcpy (GST_BUFFER_DATA (outbuf), buf->data + buffer_info.offset,
-        buffer_info.size);
+    if (self->needs_reorder) {
+      gint i, n_samples, c, n_channels;
+      gint *reorder_map = self->reorder_map;
+      gint16 *dest, *source;
+
+      dest = (gint16 *) minfo.data;
+      source = (gint16 *) (buf->data + buffer_info.offset);
+      n_samples = buffer_info.size / self->info.bpf;
+      n_channels = self->info.channels;
+
+      for (i = 0; i < n_samples; i++) {
+        for (c = 0; c < n_channels; c++) {
+          dest[i * n_channels + reorder_map[c]] = source[i * n_channels + c];
+        }
+      }
+    } else {
+      orc_memcpy (minfo.data, buf->data + buffer_info.offset, buffer_info.size);
+    }
+    gst_buffer_unmap (outbuf, &minfo);
 
     /* FIXME: We should get one decoded input frame here for
      * every buffer. If this is not the case somewhere, we will
@@ -630,7 +638,7 @@ done:
   if (!gst_amc_codec_release_output_buffer (self->codec, idx))
     goto failed_release;
 
-  if (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
+  if (is_eos || flow_ret == GST_FLOW_EOS) {
     GST_AUDIO_DECODER_STREAM_UNLOCK (self);
     g_mutex_lock (self->drain_lock);
     if (self->draining) {
@@ -639,7 +647,7 @@ done:
       g_cond_broadcast (self->drain_cond);
     } else if (flow_ret == GST_FLOW_OK) {
       GST_DEBUG_OBJECT (self, "Component signalled EOS");
-      flow_ret = GST_FLOW_UNEXPECTED;
+      flow_ret = GST_FLOW_EOS;
     }
     g_mutex_unlock (self->drain_lock);
     GST_AUDIO_DECODER_STREAM_LOCK (self);
@@ -702,20 +710,19 @@ flushing:
   {
     GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
     gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
-    self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+    self->downstream_flow_ret = GST_FLOW_FLUSHING;
     GST_AUDIO_DECODER_STREAM_UNLOCK (self);
     return;
   }
 
 flow_error:
   {
-    if (flow_ret == GST_FLOW_UNEXPECTED) {
+    if (flow_ret == GST_FLOW_EOS) {
       GST_DEBUG_OBJECT (self, "EOS");
       gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_AUDIO_DECODER_SRC_PAD (self));
-    } else
-        if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_UNEXPECTED) {
+    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (self, STREAM, FAILED,
           ("Internal data stream error."), ("stream stopped, reason %s",
               gst_flow_get_name (flow_ret)));
@@ -786,20 +793,19 @@ gst_amc_audio_dec_stop (GstAudioDecoder * decoder)
   }
   gst_pad_stop_task (GST_AUDIO_DECODER_SRC_PAD (decoder));
 
-  g_free (self->positions);
-  self->positions = NULL;
+  memset (self->positions, 0, sizeof (self->positions));
 
-  g_list_foreach (self->codec_datas, (GFunc) gst_buffer_unref, NULL);
+  g_list_foreach (self->codec_datas, (GFunc) g_free, NULL);
   g_list_free (self->codec_datas);
   self->codec_datas = NULL;
 
-  self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+  self->downstream_flow_ret = GST_FLOW_FLUSHING;
   self->eos = FALSE;
   g_mutex_lock (self->drain_lock);
   self->draining = FALSE;
   g_cond_broadcast (self->drain_cond);
   g_mutex_unlock (self->drain_lock);
-  gst_buffer_replace (&self->codec_data, NULL);
+
   GST_DEBUG_OBJECT (self, "Stopped decoder");
   return TRUE;
 }
@@ -883,10 +889,14 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
   if (gst_structure_has_field (s, "codec_data")) {
     const GValue *h = gst_structure_get_value (s, "codec_data");
     GstBuffer *codec_data = gst_value_get_buffer (h);
-
-    self->codec_datas =
-        g_list_prepend (self->codec_datas, gst_buffer_ref (codec_data));
-    gst_amc_format_set_buffer (format, "csd-0", codec_data);
+    GstMapInfo minfo;
+    guint8 *data;
+
+    gst_buffer_map (codec_data, &minfo, GST_MAP_READ);
+    data = g_memdup (minfo.data, minfo.size);
+    self->codec_datas = g_list_prepend (self->codec_datas, data);
+    gst_amc_format_set_buffer (format, "csd-0", data, minfo.size);
+    gst_buffer_unmap (codec_data, &minfo);
   } else if (gst_structure_has_field (s, "streamheader")) {
     const GValue *sh = gst_structure_get_value (s, "streamheader");
     gint nsheaders = gst_value_array_get_size (sh);
@@ -894,13 +904,17 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
     const GValue *h;
     gint i, j;
     gchar *fname;
+    GstMapInfo minfo;
+    guint8 *data;
 
     for (i = 0, j = 0; i < nsheaders; i++) {
       h = gst_value_array_get_value (sh, i);
       buf = gst_value_get_buffer (h);
 
       if (strcmp (mime, "audio/vorbis") == 0) {
-        guint8 header_type = GST_BUFFER_DATA (buf)[0];
+        guint8 header_type;
+
+        gst_buffer_extract (buf, 0, &header_type, 1);
 
         /* Only use the identification and setup packets */
         if (header_type != 0x01 && header_type != 0x05)
@@ -908,9 +922,11 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
       }
 
       fname = g_strdup_printf ("csd-%d", j);
-      self->codec_datas =
-          g_list_prepend (self->codec_datas, gst_buffer_ref (buf));
-      gst_amc_format_set_buffer (format, fname, buf);
+      gst_buffer_map (buf, &minfo, GST_MAP_READ);
+      data = g_memdup (minfo.data, minfo.size);
+      self->codec_datas = g_list_prepend (self->codec_datas, data);
+      gst_amc_format_set_buffer (format, fname, data, minfo.size);
+      gst_buffer_unmap (buf, &minfo);
       g_free (fname);
       j++;
     }
@@ -949,7 +965,7 @@ gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
   self->flushing = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
   gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_amc_audio_dec_loop, decoder);
+      (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL);
 
   return TRUE;
 }
@@ -985,7 +1001,7 @@ gst_amc_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard)
   self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
   gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_amc_audio_dec_loop, decoder);
+      (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL);
 
   GST_DEBUG_OBJECT (self, "Reset decoder");
 }
@@ -999,6 +1015,9 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
   GstAmcBufferInfo buffer_info;
   guint offset = 0;
   GstClockTime timestamp, duration, timestamp_offset = 0;
+  GstMapInfo minfo;
+
+  memset (&minfo, 0, sizeof (minfo));
 
   self = GST_AMC_AUDIO_DEC (decoder);
 
@@ -1021,7 +1040,7 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
     GST_WARNING_OBJECT (self, "Got frame after EOS");
     if (inbuf)
       gst_buffer_unref (inbuf);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 
   if (self->flushing)
@@ -1033,10 +1052,12 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
   if (!inbuf)
     return gst_amc_audio_dec_drain (self);
 
-  timestamp = GST_BUFFER_TIMESTAMP (inbuf);
+  timestamp = GST_BUFFER_PTS (inbuf);
   duration = GST_BUFFER_DURATION (inbuf);
 
-  while (offset < GST_BUFFER_SIZE (inbuf)) {
+  gst_buffer_map (inbuf, &minfo, GST_MAP_READ);
+
+  while (offset < minfo.size) {
     /* Make sure to release the base class stream lock, otherwise
      * _loop() can't call _finish_frame() and we might block forever
      * because no input buffers are released */
@@ -1085,15 +1106,14 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
 
     memset (&buffer_info, 0, sizeof (buffer_info));
     buffer_info.offset = 0;
-    buffer_info.size = MIN (GST_BUFFER_SIZE (inbuf) - offset, buf->size);
+    buffer_info.size = MIN (minfo.size - offset, buf->size);
 
-    orc_memcpy (buf->data, GST_BUFFER_DATA (inbuf) + offset, buffer_info.size);
+    orc_memcpy (buf->data, minfo.data + offset, buffer_info.size);
 
     /* Interpolate timestamps if we're passing the buffer
      * in multiple chunks */
     if (offset != 0 && duration != GST_CLOCK_TIME_NONE) {
-      timestamp_offset =
-          gst_util_uint64_scale (offset, duration, GST_BUFFER_SIZE (inbuf));
+      timestamp_offset = gst_util_uint64_scale (offset, duration, minfo.size);
     }
 
     if (timestamp != GST_CLOCK_TIME_NONE) {
@@ -1117,7 +1137,7 @@ gst_amc_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
     if (!gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info))
       goto queue_error;
   }
-
+  gst_buffer_unmap (inbuf, &minfo);
   gst_buffer_unref (inbuf);
 
   return self->downstream_flow_ret;
@@ -1126,6 +1146,8 @@ downstream_error:
   {
     GST_ERROR_OBJECT (self, "Downstream returned %s",
         gst_flow_get_name (self->downstream_flow_ret));
+    if (minfo.data)
+      gst_buffer_unmap (inbuf, &minfo);
     if (inbuf)
       gst_buffer_unref (inbuf);
     return self->downstream_flow_ret;
@@ -1134,6 +1156,8 @@ invalid_buffer_index:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
+    if (minfo.data)
+      gst_buffer_unmap (inbuf, &minfo);
     if (inbuf)
       gst_buffer_unref (inbuf);
     return GST_FLOW_ERROR;
@@ -1142,6 +1166,8 @@ dequeue_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Failed to dequeue input buffer"));
+    if (minfo.data)
+      gst_buffer_unmap (inbuf, &minfo);
     if (inbuf)
       gst_buffer_unref (inbuf);
     return GST_FLOW_ERROR;
@@ -1150,16 +1176,20 @@ queue_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Failed to queue input buffer"));
+    if (minfo.data)
+      gst_buffer_unmap (inbuf, &minfo);
     if (inbuf)
       gst_buffer_unref (inbuf);
     return GST_FLOW_ERROR;
   }
 flushing:
   {
-    GST_DEBUG_OBJECT (self, "Flushing -- returning WRONG_STATE");
+    GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+    if (minfo.data)
+      gst_buffer_unmap (inbuf, &minfo);
     if (inbuf)
       gst_buffer_unref (inbuf);
-    return GST_FLOW_WRONG_STATE;
+    return GST_FLOW_FLUSHING;
   }
 }
 
index 5941a0114cc830bb69b36f99f3f57008d08c8ae7..0e0c6e10bd789437cae4014777e8c16471c839bb 100644 (file)
@@ -22,7 +22,7 @@
 #define __GST_AMC_AUDIO_DEC_H__
 
 #include <gst/gst.h>
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 #include <gst/audio/gstaudiodecoder.h>
 
 #include "gstamc.h"
@@ -59,10 +59,12 @@ struct _GstAmcAudioDec
   gboolean input_caps_changed;
 
   /* Output format of the codec */
-  gint channels, rate;
-  GstAudioChannelPosition *positions;
+  GstAudioInfo info;
+  /* AMC positions, might need reordering */
+  GstAudioChannelPosition positions[64];
+  gboolean needs_reorder;
+  gint reorder_map[64];
 
-  GstBuffer *codec_data;
   /* TRUE if the component is configured and saw
    * the first buffer */
   gboolean started;
index dc3d7b2db6416011737fde9cf8226ba62e9a006e..e316b34c33bd71a805fdeee281aaad6ae43a80c1 100644 (file)
@@ -28,6 +28,8 @@
 #endif
 
 #include <gst/gst.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
 #include <string.h>
 
 #ifdef HAVE_ORC
@@ -82,8 +84,11 @@ static gboolean gst_amc_video_dec_reset (GstVideoDecoder * decoder,
 static GstFlowReturn gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
     GstVideoCodecFrame * frame);
 static GstFlowReturn gst_amc_video_dec_finish (GstVideoDecoder * decoder);
+static gboolean gst_amc_video_dec_decide_allocation (GstVideoDecoder * bdec,
+    GstQuery * query);
 
-static GstFlowReturn gst_amc_video_dec_drain (GstAmcVideoDec * self);
+static GstFlowReturn gst_amc_video_dec_drain (GstAmcVideoDec * self,
+    gboolean at_eos);
 
 enum
 {
@@ -92,11 +97,11 @@ enum
 
 /* class initialization */
 
-#define DEBUG_INIT(bla) \
+#define DEBUG_INIT \
   GST_DEBUG_CATEGORY_INIT (gst_amc_video_dec_debug_category, "amcvideodec", 0, \
       "Android MediaCodec video decoder");
-
-GST_BOILERPLATE_FULL (GstAmcVideoDec, gst_amc_video_dec, GstVideoDecoder,
+#define parent_class gst_amc_video_dec_parent_class
+G_DEFINE_TYPE_WITH_CODE (GstAmcVideoDec, gst_amc_video_dec,
     GST_TYPE_VIDEO_DECODER, DEBUG_INIT);
 
 static GstCaps *
@@ -157,13 +162,13 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           gst_structure_set_value (tmp2, "level", &va);
           g_value_unset (&va);
           g_value_unset (&v);
-          gst_caps_merge_structure (ret, tmp2);
+          ret = gst_caps_merge_structure (ret, tmp2);
           have_profile_level = TRUE;
         }
       }
 
       if (!have_profile_level) {
-        gst_caps_merge_structure (ret, tmp);
+        ret = gst_caps_merge_structure (ret, tmp);
       } else {
         gst_structure_free (tmp);
       }
@@ -213,13 +218,13 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           gst_structure_set_value (tmp2, "level", &va);
           g_value_unset (&va);
           g_value_unset (&v);
-          gst_caps_merge_structure (ret, tmp2);
+          ret = gst_caps_merge_structure (ret, tmp2);
           have_profile_level = TRUE;
         }
       }
 
       if (!have_profile_level) {
-        gst_caps_merge_structure (ret, tmp);
+        ret = gst_caps_merge_structure (ret, tmp);
       } else {
         gst_structure_free (tmp);
       }
@@ -272,7 +277,7 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           if (!alternative)
             g_value_unset (&va);
           g_value_unset (&v);
-          gst_caps_merge_structure (ret, tmp2);
+          ret = gst_caps_merge_structure (ret, tmp2);
 
           if (alternative) {
             tmp2 = gst_structure_copy (tmp);
@@ -280,14 +285,14 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
                 NULL);
             gst_structure_set_value (tmp2, "level", &va);
             g_value_unset (&va);
-            gst_caps_merge_structure (ret, tmp2);
+            ret = gst_caps_merge_structure (ret, tmp2);
           }
           have_profile_level = TRUE;
         }
       }
 
       if (!have_profile_level) {
-        gst_caps_merge_structure (ret, tmp);
+        ret = gst_caps_merge_structure (ret, tmp);
       } else {
         gst_structure_free (tmp);
       }
@@ -299,7 +304,7 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           "height", GST_TYPE_INT_RANGE, 16, 4096,
           "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
 
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else if (strcmp (type->mime, "video/mpeg2") == 0) {
       GstStructure *tmp;
 
@@ -312,7 +317,7 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
           "systemstream", G_TYPE_BOOLEAN, FALSE,
           "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
 
-      gst_caps_merge_structure (ret, tmp);
+      ret = gst_caps_merge_structure (ret, tmp);
     } else {
       GST_WARNING ("Unsupported mimetype '%s'", type->mime);
     }
@@ -375,8 +380,13 @@ create_src_caps (const GstAmcCodecInfo * codec_info)
         GST_WARNING ("Unknown color format 0x%08x", type->color_formats[j]);
         continue;
       }
-      tmp = gst_video_format_new_template_caps (format);
-      gst_caps_merge (ret, tmp);
+
+      tmp = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, gst_video_format_to_string (format),
+          "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+          "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+          "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+      ret = gst_caps_merge (ret, tmp);
     }
   }
 
@@ -384,22 +394,41 @@ create_src_caps (const GstAmcCodecInfo * codec_info)
 }
 
 static void
-gst_amc_video_dec_base_init (gpointer g_class)
+gst_amc_video_dec_class_init (GstAmcVideoDecClass * klass)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-  GstAmcVideoDecClass *videodec_class = GST_AMC_VIDEO_DEC_CLASS (g_class);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstVideoDecoderClass *videodec_class = GST_VIDEO_DECODER_CLASS (klass);
+  GstAmcVideoDecClass *amcvideodec_class = GST_AMC_VIDEO_DEC_CLASS (klass);
   const GstAmcCodecInfo *codec_info;
   GstPadTemplate *templ;
   GstCaps *caps;
   gchar *longname;
 
+  gobject_class->finalize = gst_amc_video_dec_finalize;
+
+  element_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_amc_video_dec_change_state);
+
+  videodec_class->start = GST_DEBUG_FUNCPTR (gst_amc_video_dec_start);
+  videodec_class->stop = GST_DEBUG_FUNCPTR (gst_amc_video_dec_stop);
+  videodec_class->open = GST_DEBUG_FUNCPTR (gst_amc_video_dec_open);
+  videodec_class->close = GST_DEBUG_FUNCPTR (gst_amc_video_dec_close);
+  videodec_class->reset = GST_DEBUG_FUNCPTR (gst_amc_video_dec_reset);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_amc_video_dec_set_format);
+  videodec_class->handle_frame =
+      GST_DEBUG_FUNCPTR (gst_amc_video_dec_handle_frame);
+  videodec_class->finish = GST_DEBUG_FUNCPTR (gst_amc_video_dec_finish);
+  videodec_class->decide_allocation =
+      GST_DEBUG_FUNCPTR (gst_amc_video_dec_decide_allocation);
+
   codec_info =
-      g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), gst_amc_codec_info_quark);
+      g_type_get_qdata (G_TYPE_FROM_CLASS (klass), gst_amc_codec_info_quark);
   /* This happens for the base class and abstract subclasses */
   if (!codec_info)
     return;
 
-  videodec_class->codec_info = codec_info;
+  amcvideodec_class->codec_info = codec_info;
 
   /* Add pad templates */
   caps = create_sink_caps (codec_info);
@@ -413,7 +442,7 @@ gst_amc_video_dec_base_init (gpointer g_class)
   gst_object_unref (templ);
 
   longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name);
-  gst_element_class_set_details_simple (element_class,
+  gst_element_class_set_metadata (element_class,
       codec_info->name,
       "Codec/Decoder/Video",
       longname, "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
@@ -421,30 +450,7 @@ gst_amc_video_dec_base_init (gpointer g_class)
 }
 
 static void
-gst_amc_video_dec_class_init (GstAmcVideoDecClass * klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-  GstVideoDecoderClass *videodec_class = GST_VIDEO_DECODER_CLASS (klass);
-
-  gobject_class->finalize = gst_amc_video_dec_finalize;
-
-  element_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_amc_video_dec_change_state);
-
-  videodec_class->start = GST_DEBUG_FUNCPTR (gst_amc_video_dec_start);
-  videodec_class->stop = GST_DEBUG_FUNCPTR (gst_amc_video_dec_stop);
-  videodec_class->open = GST_DEBUG_FUNCPTR (gst_amc_video_dec_open);
-  videodec_class->close = GST_DEBUG_FUNCPTR (gst_amc_video_dec_close);
-  videodec_class->reset = GST_DEBUG_FUNCPTR (gst_amc_video_dec_reset);
-  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_amc_video_dec_set_format);
-  videodec_class->handle_frame =
-      GST_DEBUG_FUNCPTR (gst_amc_video_dec_handle_frame);
-  videodec_class->finish = GST_DEBUG_FUNCPTR (gst_amc_video_dec_finish);
-}
-
-static void
-gst_amc_video_dec_init (GstAmcVideoDec * self, GstAmcVideoDecClass * klass)
+gst_amc_video_dec_init (GstAmcVideoDec * self)
 {
   gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
 
@@ -545,7 +551,7 @@ gst_amc_video_dec_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+      self->downstream_flow_ret = GST_FLOW_FLUSHING;
       self->started = FALSE;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
@@ -710,6 +716,7 @@ gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format)
   self->crop_top = crop_top;
   self->crop_bottom = crop_bottom;
 
+  gst_video_decoder_negotiate (GST_VIDEO_DECODER (self));
   gst_video_codec_state_unref (output_state);
   self->input_state_changed = FALSE;
 
@@ -737,21 +744,25 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
   }
 
   /* Same video format */
-  if (buffer_info->size == GST_BUFFER_SIZE (outbuf)) {
+  if (buffer_info->size == gst_buffer_get_size (outbuf)) {
+    GstMapInfo minfo;
+
     GST_DEBUG_OBJECT (self, "Buffer sizes equal, doing fast copy");
-    orc_memcpy (GST_BUFFER_DATA (outbuf), buf->data + buffer_info->offset,
-        buffer_info->size);
+    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
+    orc_memcpy (minfo.data, buf->data + buffer_info->offset, buffer_info->size);
+    gst_buffer_unmap (outbuf, &minfo);
     ret = TRUE;
     goto done;
   }
 
   GST_DEBUG_OBJECT (self,
       "Sizes not equal (%d vs %d), doing slow line-by-line copying",
-      buffer_info->size, GST_BUFFER_SIZE (outbuf));
+      buffer_info->size, gst_buffer_get_size (outbuf));
 
   /* Different video format, try to convert */
   switch (self->color_format) {
     case COLOR_FormatYUV420Planar:{
+      GstVideoFrame vframe;
       gint i, j, height;
       guint8 *src, *dest;
       gint stride, slice_height;
@@ -775,13 +786,14 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
         }
       }
 
+      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
       for (i = 0; i < 3; i++) {
         if (i == 0) {
           src_stride = stride;
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         } else {
           src_stride = (stride + 1) / 2;
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         }
 
         src = buf->data + buffer_info->offset;
@@ -799,8 +811,8 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
         if (i == 2)
           src += ((slice_height + 1) / 2) * ((stride + 1) / 2);
 
-        dest = GST_BUFFER_DATA (outbuf) + GST_VIDEO_INFO_COMP_OFFSET (info, i);
-        height = GST_VIDEO_INFO_COMP_HEIGHT (info, i);
+        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
+        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
         for (j = 0; j < height; j++) {
           orc_memcpy (dest, src, row_length);
@@ -808,6 +820,7 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
           dest += dest_stride;
         }
       }
+      gst_video_frame_unmap (&vframe);
       ret = TRUE;
       break;
     }
@@ -817,6 +830,7 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
       guint8 *src, *dest;
       gint src_stride, dest_stride;
       gint row_length;
+      GstVideoFrame vframe;
 
       /* This should always be set */
       if (self->stride == 0 || self->slice_height == 0) {
@@ -826,13 +840,14 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
 
       /* FIXME: This does not work for odd widths or heights
        * but might as well be a bug in the codec */
+      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
       for (i = 0; i < 2; i++) {
         if (i == 0) {
           src_stride = self->stride;
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         } else {
           src_stride = GST_ROUND_UP_2 (self->stride);
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         }
 
         src = buf->data + buffer_info->offset;
@@ -843,8 +858,8 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
           row_length = GST_ROUND_UP_2 (self->width);
         }
 
-        dest = GST_BUFFER_DATA (outbuf) + GST_VIDEO_INFO_COMP_OFFSET (info, i);
-        height = GST_VIDEO_INFO_COMP_HEIGHT (info, i);
+        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
+        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
         for (j = 0; j < height; j++) {
           orc_memcpy (dest, src, row_length);
@@ -852,6 +867,7 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
           dest += dest_stride;
         }
       }
+      gst_video_frame_unmap (&vframe);
       ret = TRUE;
       break;
     }
@@ -861,6 +877,7 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
       guint8 *src, *dest;
       gint src_stride, dest_stride;
       gint row_length;
+      GstVideoFrame vframe;
 
       /* This should always be set */
       if (self->stride == 0 || self->slice_height == 0) {
@@ -869,14 +886,14 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
       }
 
       /* FIXME: This is untested! */
-
+      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
       for (i = 0; i < 2; i++) {
         if (i == 0) {
           src_stride = self->stride;
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         } else {
           src_stride = self->stride;
-          dest_stride = GST_VIDEO_INFO_COMP_STRIDE (info, i);
+          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
         }
 
         src = buf->data + buffer_info->offset;
@@ -891,8 +908,8 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
           row_length = self->width;
         }
 
-        dest = GST_BUFFER_DATA (outbuf) + GST_VIDEO_INFO_COMP_OFFSET (info, i);
-        height = GST_VIDEO_INFO_COMP_HEIGHT (info, i);
+        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
+        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
         for (j = 0; j < height; j++) {
           orc_memcpy (dest, src, row_length);
@@ -900,6 +917,7 @@ gst_amc_video_dec_fill_buffer (GstAmcVideoDec * self, gint idx,
           dest += dest_stride;
         }
       }
+      gst_video_frame_unmap (&vframe);
       ret = TRUE;
       break;
     }
@@ -940,7 +958,7 @@ retry:
   /*} */
 
   if (idx < 0) {
-    if (self->flushing || self->downstream_flow_ret == GST_FLOW_WRONG_STATE)
+    if (self->flushing || self->downstream_flow_ret == GST_FLOW_FLUSHING)
       goto flushing;
 
     switch (idx) {
@@ -1032,7 +1050,8 @@ retry:
      */
     GST_ERROR_OBJECT (self, "No corresponding frame found");
 
-    outbuf = gst_video_decoder_alloc_output_buffer (GST_VIDEO_DECODER (self));
+    outbuf =
+        gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
 
     if (!gst_amc_video_dec_fill_buffer (self, idx, &buffer_info, outbuf)) {
       gst_buffer_unref (outbuf);
@@ -1042,12 +1061,12 @@ retry:
       goto invalid_buffer;
     }
 
-    GST_BUFFER_TIMESTAMP (outbuf) =
+    GST_BUFFER_PTS (outbuf) =
         gst_util_uint64_scale (buffer_info.presentation_time_us, GST_USECOND,
         1);
     flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
   } else if (buffer_info.size > 0) {
-    if ((flow_ret = gst_video_decoder_alloc_output_frame (GST_VIDEO_DECODER
+    if ((flow_ret = gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER
                 (self), frame)) != GST_FLOW_OK) {
       GST_ERROR_OBJECT (self, "Failed to allocate buffer");
       goto flow_error;
@@ -1071,7 +1090,7 @@ retry:
   if (!gst_amc_codec_release_output_buffer (self->codec, idx))
     goto failed_release;
 
-  if (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
+  if (is_eos || flow_ret == GST_FLOW_EOS) {
     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     g_mutex_lock (self->drain_lock);
     if (self->draining) {
@@ -1080,7 +1099,7 @@ retry:
       g_cond_broadcast (self->drain_cond);
     } else if (flow_ret == GST_FLOW_OK) {
       GST_DEBUG_OBJECT (self, "Component signalled EOS");
-      flow_ret = GST_FLOW_UNEXPECTED;
+      flow_ret = GST_FLOW_EOS;
     }
     g_mutex_unlock (self->drain_lock);
     GST_VIDEO_DECODER_STREAM_LOCK (self);
@@ -1143,20 +1162,19 @@ flushing:
   {
     GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
     gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
-    self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+    self->downstream_flow_ret = GST_FLOW_FLUSHING;
     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     return;
   }
 
 flow_error:
   {
-    if (flow_ret == GST_FLOW_UNEXPECTED) {
+    if (flow_ret == GST_FLOW_EOS) {
       GST_DEBUG_OBJECT (self, "EOS");
       gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
           gst_event_new_eos ());
       gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
-    } else
-        if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_UNEXPECTED) {
+    } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (self, STREAM, FAILED,
           ("Internal data stream error."), ("stream stopped, reason %s",
               gst_flow_get_name (flow_ret)));
@@ -1216,13 +1234,14 @@ gst_amc_video_dec_stop (GstVideoDecoder * decoder)
   }
   gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
 
-  self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
+  self->downstream_flow_ret = GST_FLOW_FLUSHING;
   self->eos = FALSE;
   g_mutex_lock (self->drain_lock);
   self->draining = FALSE;
   g_cond_broadcast (self->drain_cond);
   g_mutex_unlock (self->drain_lock);
-  gst_buffer_replace (&self->codec_data, NULL);
+  g_free (self->codec_data);
+  self->codec_data_size = 0;
   GST_DEBUG_OBJECT (self, "Stopped decoder");
   return TRUE;
 }
@@ -1237,6 +1256,8 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
   gboolean is_format_change = FALSE;
   gboolean needs_disable = FALSE;
   gchar *format_string;
+  guint8 *codec_data = NULL;
+  gsize codec_data_size = 0;
 
   self = GST_AMC_VIDEO_DEC (decoder);
 
@@ -1247,7 +1268,20 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
    */
   is_format_change |= self->width != state->info.width;
   is_format_change |= self->height != state->info.height;
-  is_format_change |= (self->codec_data != state->codec_data);
+  if (state->codec_data) {
+    GstMapInfo cminfo;
+
+    gst_buffer_map (state->codec_data, &cminfo, GST_MAP_READ);
+    codec_data = g_memdup (cminfo.data, cminfo.size);
+    codec_data_size = cminfo.size;
+
+    is_format_change |= (!self->codec_data
+        || self->codec_data_size != codec_data_size
+        || memcmp (self->codec_data, codec_data, codec_data_size) != 0);
+    gst_buffer_unmap (state->codec_data, &cminfo);
+  } else if (self->codec_data) {
+    is_format_change |= TRUE;
+  }
 
   needs_disable = self->started;
 
@@ -1256,6 +1290,10 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
    * happened we can just exit here.
    */
   if (needs_disable && !is_format_change) {
+    g_free (codec_data);
+    codec_data = NULL;
+    codec_data_size = 0;
+
     /* Framerate or something minor changed */
     self->input_state_changed = TRUE;
     GST_DEBUG_OBJECT (self,
@@ -1264,7 +1302,7 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
   }
 
   if (needs_disable && is_format_change) {
-    gst_amc_video_dec_drain (self);
+    gst_amc_video_dec_drain (self, FALSE);
     GST_VIDEO_DECODER_STREAM_UNLOCK (self);
     gst_amc_video_dec_stop (GST_VIDEO_DECODER (self));
     GST_VIDEO_DECODER_STREAM_LOCK (self);
@@ -1280,7 +1318,9 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
   }
   /* srcpad task is not running at this point */
 
-  gst_buffer_replace (&self->codec_data, state->codec_data);
+  g_free (self->codec_data);
+  self->codec_data = codec_data;
+  self->codec_data_size = codec_data_size;
 
   mime = caps_to_mime (state->caps);
   if (!mime) {
@@ -1297,7 +1337,8 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
 
   /* FIXME: This buffer needs to be valid until the codec is stopped again */
   if (self->codec_data)
-    gst_amc_format_set_buffer (format, "csd-0", self->codec_data);
+    gst_amc_format_set_buffer (format, "csd-0", self->codec_data,
+        self->codec_data_size);
 
   format_string = gst_amc_format_to_string (format);
   GST_DEBUG_OBJECT (self, "Configuring codec with format: %s", format_string);
@@ -1331,7 +1372,7 @@ gst_amc_video_dec_set_format (GstVideoDecoder * decoder,
   self->flushing = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
   gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_amc_video_dec_loop, decoder);
+      (GstTaskFunction) gst_amc_video_dec_loop, decoder, NULL);
 
   return TRUE;
 }
@@ -1367,7 +1408,7 @@ gst_amc_video_dec_reset (GstVideoDecoder * decoder, gboolean hard)
   self->eos = FALSE;
   self->downstream_flow_ret = GST_FLOW_OK;
   gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
-      (GstTaskFunction) gst_amc_video_dec_loop, decoder);
+      (GstTaskFunction) gst_amc_video_dec_loop, decoder, NULL);
 
   GST_DEBUG_OBJECT (self, "Reset decoder");
 
@@ -1384,6 +1425,9 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
   GstAmcBufferInfo buffer_info;
   guint offset = 0;
   GstClockTime timestamp, duration, timestamp_offset = 0;
+  GstMapInfo minfo;
+
+  memset (&minfo, 0, sizeof (minfo));
 
   self = GST_AMC_VIDEO_DEC (decoder);
 
@@ -1398,7 +1442,7 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
   if (self->eos) {
     GST_WARNING_OBJECT (self, "Got frame after EOS");
     gst_video_codec_frame_unref (frame);
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 
   if (self->flushing)
@@ -1410,7 +1454,9 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
   timestamp = frame->pts;
   duration = frame->duration;
 
-  while (offset < GST_BUFFER_SIZE (frame->input_buffer)) {
+  gst_buffer_map (frame->input_buffer, &minfo, GST_MAP_READ);
+
+  while (offset < minfo.size) {
     /* Make sure to release the base class stream lock, otherwise
      * _loop() can't call _finish_frame() and we might block forever
      * because no input buffers are released */
@@ -1459,18 +1505,14 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
 
     memset (&buffer_info, 0, sizeof (buffer_info));
     buffer_info.offset = 0;
-    buffer_info.size =
-        MIN (GST_BUFFER_SIZE (frame->input_buffer) - offset, buf->size);
+    buffer_info.size = MIN (minfo.size - offset, buf->size);
 
-    orc_memcpy (buf->data, GST_BUFFER_DATA (frame->input_buffer) + offset,
-        buffer_info.size);
+    orc_memcpy (buf->data, minfo.data + offset, buffer_info.size);
 
     /* Interpolate timestamps if we're passing the buffer
      * in multiple chunks */
     if (offset != 0 && duration != GST_CLOCK_TIME_NONE) {
-      timestamp_offset =
-          gst_util_uint64_scale (offset, duration,
-          GST_BUFFER_SIZE (frame->input_buffer));
+      timestamp_offset = gst_util_uint64_scale (offset, duration, minfo.size);
     }
 
     if (timestamp != GST_CLOCK_TIME_NONE) {
@@ -1499,6 +1541,7 @@ gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder,
       goto queue_error;
   }
 
+  gst_buffer_unmap (frame->input_buffer, &minfo);
   gst_video_codec_frame_unref (frame);
 
   return self->downstream_flow_ret;
@@ -1507,6 +1550,8 @@ downstream_error:
   {
     GST_ERROR_OBJECT (self, "Downstream returned %s",
         gst_flow_get_name (self->downstream_flow_ret));
+    if (minfo.data)
+      gst_buffer_unmap (frame->input_buffer, &minfo);
     gst_video_codec_frame_unref (frame);
     return self->downstream_flow_ret;
   }
@@ -1514,6 +1559,8 @@ invalid_buffer_index:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Invalid input buffer index %d of %d", idx, self->n_input_buffers));
+    if (minfo.data)
+      gst_buffer_unmap (frame->input_buffer, &minfo);
     gst_video_codec_frame_unref (frame);
     return GST_FLOW_ERROR;
   }
@@ -1521,6 +1568,8 @@ dequeue_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Failed to dequeue input buffer"));
+    if (minfo.data)
+      gst_buffer_unmap (frame->input_buffer, &minfo);
     gst_video_codec_frame_unref (frame);
     return GST_FLOW_ERROR;
   }
@@ -1528,14 +1577,18 @@ queue_error:
   {
     GST_ELEMENT_ERROR (self, LIBRARY, FAILED, (NULL),
         ("Failed to queue input buffer"));
+    if (minfo.data)
+      gst_buffer_unmap (frame->input_buffer, &minfo);
     gst_video_codec_frame_unref (frame);
     return GST_FLOW_ERROR;
   }
 flushing:
   {
-    GST_DEBUG_OBJECT (self, "Flushing -- returning WRONG_STATE");
+    GST_DEBUG_OBJECT (self, "Flushing -- returning FLUSHING");
+    if (minfo.data)
+      gst_buffer_unmap (frame->input_buffer, &minfo);
     gst_video_codec_frame_unref (frame);
-    return GST_FLOW_WRONG_STATE;
+    return GST_FLOW_FLUSHING;
   }
 }
 
@@ -1543,54 +1596,14 @@ static GstFlowReturn
 gst_amc_video_dec_finish (GstVideoDecoder * decoder)
 {
   GstAmcVideoDec *self;
-  gint idx;
 
   self = GST_AMC_VIDEO_DEC (decoder);
-  GST_DEBUG_OBJECT (self, "Sending EOS to the component");
-
-  /* Don't send EOS buffer twice, this doesn't work */
-  if (self->eos) {
-    GST_DEBUG_OBJECT (self, "Component is already EOS");
-    return GST_VIDEO_DECODER_FLOW_DROPPED;
-  }
-  self->eos = TRUE;
-
-  /* Make sure to release the base class stream lock, otherwise
-   * _loop() can't call _finish_frame() and we might block forever
-   * because no input buffers are released */
-  GST_VIDEO_DECODER_STREAM_UNLOCK (self);
-  /* Send an EOS buffer to the component and let the base
-   * class drop the EOS event. We will send it later when
-   * the EOS buffer arrives on the output port.
-   * Wait at most 0.5s here. */
-  idx = gst_amc_codec_dequeue_input_buffer (self->codec, 500000);
-  GST_VIDEO_DECODER_STREAM_LOCK (self);
-
-  if (idx >= 0 && idx < self->n_input_buffers) {
-    GstAmcBufferInfo buffer_info;
 
-    memset (&buffer_info, 0, sizeof (buffer_info));
-    buffer_info.size = 0;
-    buffer_info.presentation_time_us =
-        gst_util_uint64_scale (self->last_upstream_ts, 1, GST_USECOND);
-    buffer_info.flags |= BUFFER_FLAG_END_OF_STREAM;
-
-    if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info))
-      GST_DEBUG_OBJECT (self, "Sent EOS to the codec");
-    else
-      GST_ERROR_OBJECT (self, "Failed to send EOS to the codec");
-  } else if (idx >= self->n_input_buffers) {
-    GST_ERROR_OBJECT (self, "Invalid input buffer index %d of %d",
-        idx, self->n_input_buffers);
-  } else {
-    GST_ERROR_OBJECT (self, "Failed to dequeue input buffer for EOS: %d", idx);
-  }
-
-  return GST_VIDEO_DECODER_FLOW_DROPPED;
+  return gst_amc_video_dec_drain (self, TRUE);
 }
 
 static GstFlowReturn
-gst_amc_video_dec_drain (GstAmcVideoDec * self)
+gst_amc_video_dec_drain (GstAmcVideoDec * self, gboolean at_eos)
 {
   GstFlowReturn ret;
   gint idx;
@@ -1606,6 +1619,8 @@ gst_amc_video_dec_drain (GstAmcVideoDec * self)
     GST_DEBUG_OBJECT (self, "Codec is EOS already");
     return GST_FLOW_OK;
   }
+  if (at_eos)
+    self->eos = TRUE;
 
   /* Make sure to release the base class stream lock, otherwise
    * _loop() can't call _finish_frame() and we might block forever
@@ -1654,3 +1669,27 @@ gst_amc_video_dec_drain (GstAmcVideoDec * self)
 
   return ret;
 }
+
+static gboolean
+gst_amc_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
+{
+  GstBufferPool *pool;
+  GstStructure *config;
+
+  if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
+    return FALSE;
+
+  g_assert (gst_query_get_n_allocation_pools (query) > 0);
+  gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
+  g_assert (pool != NULL);
+
+  config = gst_buffer_pool_get_config (pool);
+  if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
+    gst_buffer_pool_config_add_option (config,
+        GST_BUFFER_POOL_OPTION_VIDEO_META);
+  }
+  gst_buffer_pool_set_config (pool, config);
+  gst_object_unref (pool);
+
+  return TRUE;
+}
index 4a33e483054099689c4508f5448709ccfd7120ed..8709d11697e9104e8ee3f8ac599f8902983c7901 100644 (file)
@@ -64,7 +64,8 @@ struct _GstAmcVideoDec
   gint crop_left, crop_right;
   gint crop_top, crop_bottom;
 
-  GstBuffer *codec_data;
+  guint8 *codec_data;
+  gsize codec_data_size;
   /* TRUE if the component is configured and saw
    * the first buffer */
   gboolean started;