mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
videodecoder: Add transform_meta() vfunc with default implementation
The default implementation copies all metadata without tags, and metadata with only the video tag. Same behaviour as in GstVideoFilter. This currently does not work if the ::parse() vfunc is implemented as all metas are getting lost inside GstAdapter. https://bugzilla.gnome.org/show_bug.cgi?id=742385
This commit is contained in:
parent
ceef2cc12d
commit
d2cc76b228
2 changed files with 89 additions and 2 deletions
|
@ -468,6 +468,9 @@ static gboolean gst_video_decoder_sink_query_default (GstVideoDecoder * decoder,
|
|||
static gboolean gst_video_decoder_src_query_default (GstVideoDecoder * decoder,
|
||||
GstQuery * query);
|
||||
|
||||
static gboolean gst_video_decoder_transform_meta_default (GstVideoDecoder *
|
||||
decoder, GstVideoCodecFrame * frame, GstMeta * meta);
|
||||
|
||||
/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
|
||||
* method to get to the padtemplates */
|
||||
GType
|
||||
|
@ -523,6 +526,7 @@ gst_video_decoder_class_init (GstVideoDecoderClass * klass)
|
|||
klass->negotiate = gst_video_decoder_negotiate_default;
|
||||
klass->sink_query = gst_video_decoder_sink_query_default;
|
||||
klass->src_query = gst_video_decoder_src_query_default;
|
||||
klass->transform_meta = gst_video_decoder_transform_meta_default;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2834,6 +2838,67 @@ gst_video_decoder_drop_frame (GstVideoDecoder * dec, GstVideoCodecFrame * frame)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_video_decoder_transform_meta_default (GstVideoDecoder *
|
||||
decoder, GstVideoCodecFrame * frame, GstMeta * meta)
|
||||
{
|
||||
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_VIDEO_STR))))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstVideoDecoder *decoder;
|
||||
GstVideoCodecFrame *frame;
|
||||
} CopyMetaData;
|
||||
|
||||
static gboolean
|
||||
foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
|
||||
{
|
||||
CopyMetaData *data = user_data;
|
||||
GstVideoDecoder *decoder = data->decoder;
|
||||
GstVideoDecoderClass *klass = GST_VIDEO_DECODER_GET_CLASS (decoder);
|
||||
GstVideoCodecFrame *frame = data->frame;
|
||||
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, frame, *meta);
|
||||
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 (frame->output_buffer, *meta, inbuf,
|
||||
_gst_meta_transform_copy, ©_data);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_decoder_finish_frame:
|
||||
* @decoder: a #GstVideoDecoder
|
||||
|
@ -2855,6 +2920,7 @@ gst_video_decoder_finish_frame (GstVideoDecoder * decoder,
|
|||
GstVideoCodecFrame * frame)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_GET_CLASS (decoder);
|
||||
GstVideoDecoderPrivate *priv = decoder->priv;
|
||||
GstBuffer *output_buffer;
|
||||
gboolean needs_reconfigure = FALSE;
|
||||
|
@ -2908,6 +2974,19 @@ gst_video_decoder_finish_frame (GstVideoDecoder * decoder,
|
|||
priv->discont = FALSE;
|
||||
}
|
||||
|
||||
if (decoder_class->transform_meta) {
|
||||
if (G_LIKELY (frame->input_buffer)) {
|
||||
CopyMetaData data;
|
||||
|
||||
data.decoder = decoder;
|
||||
data.frame = frame;
|
||||
gst_buffer_foreach_meta (frame->input_buffer, foreach_metadata, &data);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (decoder,
|
||||
"Can't copy metadata because input frame disappeared");
|
||||
}
|
||||
}
|
||||
|
||||
/* Get an additional ref to the buffer, which is going to be pushed
|
||||
* downstream, the original ref is owned by the frame
|
||||
*
|
||||
|
@ -2936,7 +3015,6 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* With stream lock, takes the frame reference */
|
||||
static GstFlowReturn
|
||||
gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
|
||||
|
|
|
@ -265,6 +265,11 @@ struct _GstVideoDecoder
|
|||
* If not implemented, default returns
|
||||
* gst_video_decoder_proxy_getcaps
|
||||
* applied to sink template caps.
|
||||
* @transform_meta: Optional. Transform the metadata on the input buffer to the
|
||||
* output buffer. By default this method is copies all meta without
|
||||
* tags and meta with only the "video" 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
|
||||
* needed. At minimum @handle_frame needs to be overridden, and @set_format
|
||||
|
@ -326,8 +331,12 @@ struct _GstVideoDecoderClass
|
|||
|
||||
GstFlowReturn (*drain) (GstVideoDecoder *decoder);
|
||||
|
||||
gboolean (*transform_meta) (GstVideoDecoder *decoder,
|
||||
GstVideoCodecFrame *frame,
|
||||
GstMeta * meta);
|
||||
|
||||
/*< private >*/
|
||||
void *padding[GST_PADDING_LARGE-5];
|
||||
void *padding[GST_PADDING_LARGE-6];
|
||||
};
|
||||
|
||||
GType gst_video_decoder_get_type (void);
|
||||
|
|
Loading…
Reference in a new issue