mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 20:51:13 +00:00
audiodecoder: Add transform_meta() vfunc with default implementation
The default implementation copies all metadata without tags, and metadata with only the audio tag. Same behaviour as in GstAudioFilter. https://bugzilla.gnome.org/show_bug.cgi?id=742385
This commit is contained in:
parent
cc1719130b
commit
844fa28c67
2 changed files with 96 additions and 2 deletions
|
@ -388,6 +388,9 @@ static gboolean gst_audio_decoder_sink_query_default (GstAudioDecoder * dec,
|
||||||
static gboolean gst_audio_decoder_src_query_default (GstAudioDecoder * dec,
|
static gboolean gst_audio_decoder_src_query_default (GstAudioDecoder * dec,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
|
||||||
|
static gboolean gst_audio_decoder_transform_meta_default (GstAudioDecoder *
|
||||||
|
decoder, GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf);
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
static GstElementClass *parent_class = NULL;
|
||||||
|
|
||||||
static void gst_audio_decoder_class_init (GstAudioDecoderClass * klass);
|
static void gst_audio_decoder_class_init (GstAudioDecoderClass * klass);
|
||||||
|
@ -478,6 +481,8 @@ gst_audio_decoder_class_init (GstAudioDecoderClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_query_default);
|
GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_query_default);
|
||||||
audiodecoder_class->src_query =
|
audiodecoder_class->src_query =
|
||||||
GST_DEBUG_FUNCPTR (gst_audio_decoder_src_query_default);
|
GST_DEBUG_FUNCPTR (gst_audio_decoder_src_query_default);
|
||||||
|
audiodecoder_class->transform_meta =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_audio_decoder_transform_meta_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1155,6 +1160,66 @@ check_pending_reconfigure (GstAudioDecoder * dec)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_audio_decoder_transform_meta_default (GstAudioDecoder *
|
||||||
|
decoder, GstBuffer * outbuf, GstMeta * meta, GstBuffer * inbuf)
|
||||||
|
{
|
||||||
|
const GstMetaInfo *info = meta->info;
|
||||||
|
const gchar *const *tags;
|
||||||
|
|
||||||
|
tags = gst_meta_api_type_get_tags (info->api);
|
||||||
|
|
||||||
|
if (!tags || (g_strv_length ((gchar **) tags) == 1
|
||||||
|
&& gst_meta_api_type_has_tag (info->api,
|
||||||
|
g_quark_from_string (GST_META_TAG_AUDIO_STR))))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GstAudioDecoder *decoder;
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
} CopyMetaData;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
|
||||||
|
{
|
||||||
|
CopyMetaData *data = user_data;
|
||||||
|
GstAudioDecoder *decoder = data->decoder;
|
||||||
|
GstAudioDecoderClass *klass = GST_AUDIO_DECODER_GET_CLASS (decoder);
|
||||||
|
GstBuffer *outbuf = data->outbuf;
|
||||||
|
const GstMetaInfo *info = (*meta)->info;
|
||||||
|
gboolean do_copy = FALSE;
|
||||||
|
|
||||||
|
if (GST_META_FLAG_IS_SET (*meta, GST_META_FLAG_POOLED)) {
|
||||||
|
/* never call the transform_meta with pool private metadata */
|
||||||
|
GST_DEBUG_OBJECT (decoder, "not copying pooled metadata %s",
|
||||||
|
g_type_name (info->api));
|
||||||
|
do_copy = FALSE;
|
||||||
|
} else if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) {
|
||||||
|
/* never call the transform_meta with memory specific metadata */
|
||||||
|
GST_DEBUG_OBJECT (decoder, "not copying memory specific metadata %s",
|
||||||
|
g_type_name (info->api));
|
||||||
|
do_copy = FALSE;
|
||||||
|
} else if (klass->transform_meta) {
|
||||||
|
do_copy = klass->transform_meta (decoder, outbuf, *meta, inbuf);
|
||||||
|
GST_DEBUG_OBJECT (decoder, "transformed metadata %s: copy: %d",
|
||||||
|
g_type_name (info->api), do_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we only copy metadata when the subclass implemented a transform_meta
|
||||||
|
* function and when it returns %TRUE */
|
||||||
|
if (do_copy) {
|
||||||
|
GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
|
||||||
|
GST_DEBUG_OBJECT (decoder, "copy metadata %s", g_type_name (info->api));
|
||||||
|
/* simply copy then */
|
||||||
|
info->transform_func (outbuf, *meta, inbuf,
|
||||||
|
_gst_meta_transform_copy, ©_data);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_audio_decoder_finish_frame:
|
* gst_audio_decoder_finish_frame:
|
||||||
|
@ -1181,10 +1246,12 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
|
||||||
{
|
{
|
||||||
GstAudioDecoderPrivate *priv;
|
GstAudioDecoderPrivate *priv;
|
||||||
GstAudioDecoderContext *ctx;
|
GstAudioDecoderContext *ctx;
|
||||||
|
GstAudioDecoderClass *klass = GST_AUDIO_DECODER_GET_CLASS (dec);
|
||||||
gint samples = 0;
|
gint samples = 0;
|
||||||
GstClockTime ts, next_ts;
|
GstClockTime ts, next_ts;
|
||||||
gsize size;
|
gsize size;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
GQueue inbufs = G_QUEUE_INIT;
|
||||||
|
|
||||||
/* subclass should not hand us no data */
|
/* subclass should not hand us no data */
|
||||||
g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
|
g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
|
||||||
|
@ -1252,7 +1319,7 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
|
||||||
GST_TIME_ARGS (ts));
|
GST_TIME_ARGS (ts));
|
||||||
|
|
||||||
while (priv->frames.length && frames) {
|
while (priv->frames.length && frames) {
|
||||||
gst_buffer_unref (g_queue_pop_head (&priv->frames));
|
g_queue_push_tail (&inbufs, g_queue_pop_head (&priv->frames));
|
||||||
dec->priv->ctx.delay = dec->priv->frames.length;
|
dec->priv->ctx.delay = dec->priv->frames.length;
|
||||||
frames--;
|
frames--;
|
||||||
}
|
}
|
||||||
|
@ -1324,6 +1391,23 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
|
||||||
GST_BUFFER_DURATION (buf) =
|
GST_BUFFER_DURATION (buf) =
|
||||||
GST_FRAMES_TO_CLOCK_TIME (samples, ctx->info.rate);
|
GST_FRAMES_TO_CLOCK_TIME (samples, ctx->info.rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (klass->transform_meta) {
|
||||||
|
if (inbufs.length) {
|
||||||
|
GList *l;
|
||||||
|
for (l = inbufs.head; l; l = l->next) {
|
||||||
|
CopyMetaData data;
|
||||||
|
|
||||||
|
data.decoder = dec;
|
||||||
|
data.outbuf = buf;
|
||||||
|
gst_buffer_foreach_meta (l->data, foreach_metadata, &data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (dec,
|
||||||
|
"Can't copy metadata because input buffers disappeared");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
priv->samples += samples;
|
priv->samples += samples;
|
||||||
priv->samples_out += samples;
|
priv->samples_out += samples;
|
||||||
|
|
||||||
|
@ -1334,6 +1418,8 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
|
||||||
ret = gst_audio_decoder_output (dec, buf);
|
ret = gst_audio_decoder_output (dec, buf);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
g_queue_foreach (&inbufs, (GFunc) gst_buffer_unref, NULL);
|
||||||
|
g_queue_clear (&inbufs);
|
||||||
|
|
||||||
GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
|
GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,11 @@ struct _GstAudioDecoder
|
||||||
* If not implemented,
|
* If not implemented,
|
||||||
* default returns gst_audio_decoder_proxy_getcaps
|
* default returns gst_audio_decoder_proxy_getcaps
|
||||||
* applied to sink template caps.
|
* applied to sink template caps.
|
||||||
|
* @transform_meta: Optional. Transform the metadata on the input buffer to the
|
||||||
|
* output buffer. By default this method copies all meta without
|
||||||
|
* tags and meta with only the "audio" tag. subclasses can
|
||||||
|
* implement this method and return %TRUE if the metadata is to be
|
||||||
|
* copied. Since 1.6
|
||||||
*
|
*
|
||||||
* Subclasses can override any of the available virtual methods or not, as
|
* Subclasses can override any of the available virtual methods or not, as
|
||||||
* needed. At minimum @handle_frame (and likely @set_format) needs to be
|
* needed. At minimum @handle_frame (and likely @set_format) needs to be
|
||||||
|
@ -300,8 +305,11 @@ struct _GstAudioDecoderClass
|
||||||
GstCaps * (*getcaps) (GstAudioDecoder * dec,
|
GstCaps * (*getcaps) (GstAudioDecoder * dec,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
|
||||||
|
gboolean (*transform_meta) (GstAudioDecoder *enc, GstBuffer *outbuf,
|
||||||
|
GstMeta *meta, GstBuffer *inbuf);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _gst_reserved[GST_PADDING_LARGE - 3];
|
gpointer _gst_reserved[GST_PADDING_LARGE - 4];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_audio_decoder_get_type (void);
|
GType gst_audio_decoder_get_type (void);
|
||||||
|
|
Loading…
Reference in a new issue