summaryrefslogtreecommitdiff
path: root/sys/androidmedia
diff options
context:
space:
mode:
Diffstat (limited to 'sys/androidmedia')
-rw-r--r--sys/androidmedia/Makefile.am2
-rw-r--r--sys/androidmedia/gstamc.c68
-rw-r--r--sys/androidmedia/gstamc.h8
-rw-r--r--sys/androidmedia/gstamcaudiodec.c230
-rw-r--r--sys/androidmedia/gstamcaudiodec.h10
-rw-r--r--sys/androidmedia/gstamcvideodec.c307
-rw-r--r--sys/androidmedia/gstamcvideodec.h3
7 files changed, 345 insertions, 283 deletions
diff --git a/sys/androidmedia/Makefile.am b/sys/androidmedia/Makefile.am
index 283488f95..fba8777ce 100644
--- a/sys/androidmedia/Makefile.am
+++ b/sys/androidmedia/Makefile.am
@@ -25,7 +25,7 @@ libgstandroidmedia_la_LIBADD = \
$(GST_LIBS) \
$(ORC_LIBS)
libgstandroidmedia_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstandroidmedia_la_LIBTOOLFLAGS = --tag=disable-static
+libgstandroidmedia_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \
diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c
index 205b8502f..a1153b5a6 100644
--- a/sys/androidmedia/gstamc.c
+++ b/sys/androidmedia/gstamc.c
@@ -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
diff --git a/sys/androidmedia/gstamc.h b/sys/androidmedia/gstamc.h
index 9568b4939..b48a3ee7c 100644
--- a/sys/androidmedia/gstamc.h
+++ b/sys/androidmedia/gstamc.h
@@ -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
diff --git a/sys/androidmedia/gstamcaudiodec.c b/sys/androidmedia/gstamcaudiodec.c
index 31a8bf5f2..886556ae2 100644
--- a/sys/androidmedia/gstamcaudiodec.c
+++ b/sys/androidmedia/gstamcaudiodec.c
@@ -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;
}
}
diff --git a/sys/androidmedia/gstamcaudiodec.h b/sys/androidmedia/gstamcaudiodec.h
index 5941a0114..0e0c6e10b 100644
--- a/sys/androidmedia/gstamcaudiodec.h
+++ b/sys/androidmedia/gstamcaudiodec.h
@@ -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;
diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c
index dc3d7b2db..e316b34c3 100644
--- a/sys/androidmedia/gstamcvideodec.c
+++ b/sys/androidmedia/gstamcvideodec.c
@@ -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;
+}
diff --git a/sys/androidmedia/gstamcvideodec.h b/sys/androidmedia/gstamcvideodec.h
index 4a33e4830..8709d1169 100644
--- a/sys/androidmedia/gstamcvideodec.h
+++ b/sys/androidmedia/gstamcvideodec.h
@@ -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;