mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 14:06:23 +00:00
videoencoder: 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. https://bugzilla.gnome.org/show_bug.cgi?id=742385
This commit is contained in:
parent
353fb82ea1
commit
ceef2cc12d
2 changed files with 89 additions and 1 deletions
|
@ -244,6 +244,9 @@ static gboolean gst_video_encoder_sink_query_default (GstVideoEncoder * encoder,
|
|||
static gboolean gst_video_encoder_src_query_default (GstVideoEncoder * encoder,
|
||||
GstQuery * query);
|
||||
|
||||
static gboolean gst_video_encoder_transform_meta_default (GstVideoEncoder *
|
||||
encoder, 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
|
||||
|
@ -307,6 +310,7 @@ gst_video_encoder_class_init (GstVideoEncoderClass * klass)
|
|||
klass->negotiate = gst_video_encoder_negotiate_default;
|
||||
klass->sink_query = gst_video_encoder_sink_query_default;
|
||||
klass->src_query = gst_video_encoder_src_query_default;
|
||||
klass->transform_meta = gst_video_encoder_transform_meta_default;
|
||||
}
|
||||
|
||||
static GList *
|
||||
|
@ -1800,6 +1804,67 @@ gst_video_encoder_release_frame (GstVideoEncoder * enc,
|
|||
gst_video_codec_frame_unref (frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_video_encoder_transform_meta_default (GstVideoEncoder *
|
||||
encoder, 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
|
||||
{
|
||||
GstVideoEncoder *encoder;
|
||||
GstVideoCodecFrame *frame;
|
||||
} CopyMetaData;
|
||||
|
||||
static gboolean
|
||||
foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
|
||||
{
|
||||
CopyMetaData *data = user_data;
|
||||
GstVideoEncoder *encoder = data->encoder;
|
||||
GstVideoEncoderClass *klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
|
||||
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 (encoder, "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 (encoder, "not copying memory specific metadata %s",
|
||||
g_type_name (info->api));
|
||||
do_copy = FALSE;
|
||||
} else if (klass->transform_meta) {
|
||||
do_copy = klass->transform_meta (encoder, frame, *meta);
|
||||
GST_DEBUG_OBJECT (encoder, "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 (encoder, "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_encoder_finish_frame:
|
||||
* @encoder: a #GstVideoEncoder
|
||||
|
@ -2046,6 +2111,19 @@ gst_video_encoder_finish_frame (GstVideoEncoder * encoder,
|
|||
if (encoder_class->pre_push)
|
||||
ret = encoder_class->pre_push (encoder, frame);
|
||||
|
||||
if (encoder_class->transform_meta) {
|
||||
if (G_LIKELY (frame->input_buffer)) {
|
||||
CopyMetaData data;
|
||||
|
||||
data.encoder = encoder;
|
||||
data.frame = frame;
|
||||
gst_buffer_foreach_meta (frame->input_buffer, foreach_metadata, &data);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (encoder,
|
||||
"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 */
|
||||
buffer = gst_buffer_ref (frame->output_buffer);
|
||||
|
|
|
@ -225,6 +225,12 @@ struct _GstVideoEncoder
|
|||
* should chain up to the parent implementation to invoke the
|
||||
* default handler. Since 1.4
|
||||
*
|
||||
* @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
|
||||
* and @get_caps are likely needed as well.
|
||||
|
@ -281,8 +287,12 @@ struct _GstVideoEncoderClass
|
|||
gboolean (*src_query) (GstVideoEncoder *encoder,
|
||||
GstQuery *query);
|
||||
|
||||
gboolean (*transform_meta) (GstVideoEncoder *encoder,
|
||||
GstVideoCodecFrame *frame,
|
||||
GstMeta * meta);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE-3];
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE-4];
|
||||
};
|
||||
|
||||
GType gst_video_encoder_get_type (void);
|
||||
|
|
Loading…
Reference in a new issue