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
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
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
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;
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
*
return ret;
}
-
/* With stream lock, takes the frame reference */
static GstFlowReturn
gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
* 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
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);