glvideomixer: don't upload if alpha <= 0

Implemented using a upload_buffer vfunc within GstGLMixer allowing
NULL uploaded buffers.
This commit is contained in:
Matthew Waters 2015-01-15 09:47:45 +11:00 committed by Tim-Philipp Müller
parent aedfadd972
commit 02fdc64844
3 changed files with 116 additions and 77 deletions

View file

@ -54,6 +54,8 @@ static void gst_gl_mixer_pad_get_property (GObject * object, guint prop_id,
static void gst_gl_mixer_pad_set_property (GObject * object, guint prop_id, static void gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_gl_mixer_pad_finalize (GObject * object); static void gst_gl_mixer_pad_finalize (GObject * object);
static GstBuffer *_default_pad_upload_buffer (GstGLMixer * mix,
GstGLMixerFrameData * frame, GstBuffer * buffer);
static void gst_gl_mixer_set_context (GstElement * element, static void gst_gl_mixer_set_context (GstElement * element,
GstContext * context); GstContext * context);
@ -98,6 +100,8 @@ gst_gl_mixer_pad_class_init (GstGLMixerPadClass * klass)
vaggpad_class->set_info = NULL; vaggpad_class->set_info = NULL;
vaggpad_class->prepare_frame = NULL; vaggpad_class->prepare_frame = NULL;
vaggpad_class->clean_frame = NULL; vaggpad_class->clean_frame = NULL;
klass->upload_buffer = _default_pad_upload_buffer;
} }
static void static void
@ -1043,6 +1047,81 @@ no_decide_allocation:
} }
} }
static GstBuffer *
_default_pad_upload_buffer (GstGLMixer * mix, GstGLMixerFrameData * frame,
GstBuffer * buffer)
{
GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (frame->pad);
GstGLMixerPad *pad = frame->pad;
GstBuffer *uploaded_buf, *gl_buffer;
GstCaps *gl_caps;
GstCapsFeatures *gl_features;
GstVideoInfo gl_info;
GstVideoFrame gl_frame;
GstGLSyncMeta *sync_meta;
gst_video_info_set_format (&gl_info,
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_INFO_WIDTH (&vaggpad->info),
GST_VIDEO_INFO_HEIGHT (&vaggpad->info));
gl_features =
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
gl_caps = gst_video_info_to_caps (&gl_info);
gst_caps_set_features (gl_caps, 0, gst_caps_features_copy (gl_features));
if (!pad->upload) {
GstCaps *in_caps = gst_pad_get_current_caps (GST_PAD (pad));
GstCaps *upload_caps = gst_caps_copy (in_caps);
pad->upload = gst_gl_upload_new (mix->context);
gst_caps_set_features (upload_caps, 0,
gst_caps_features_copy (gl_features));
gst_gl_upload_set_caps (pad->upload, in_caps, upload_caps);
if (!pad->convert) {
pad->convert = gst_gl_color_convert_new (mix->context);
gst_gl_color_convert_set_caps (pad->convert, upload_caps, gl_caps);
}
gst_caps_unref (upload_caps);
gst_caps_unref (in_caps);
}
gst_caps_features_free (gl_features);
gst_caps_unref (gl_caps);
sync_meta = gst_buffer_get_gl_sync_meta (vaggpad->buffer);
if (sync_meta)
gst_gl_sync_meta_wait (sync_meta);
if (gst_gl_upload_perform_with_buffer (pad->upload,
vaggpad->buffer, &uploaded_buf) != GST_GL_UPLOAD_DONE) {
return NULL;
}
if (!(gl_buffer = gst_gl_color_convert_perform (pad->convert, uploaded_buf))) {
gst_buffer_unref (uploaded_buf);
return NULL;
}
if (!gst_video_frame_map (&gl_frame, &gl_info, gl_buffer,
GST_MAP_READ | GST_MAP_GL)) {
gst_buffer_unref (uploaded_buf);
gst_buffer_unref (gl_buffer);
return NULL;
}
frame->texture = *(guint *) gl_frame.data[0];
gst_buffer_unref (uploaded_buf);
gst_video_frame_unmap (&gl_frame);
return gl_buffer;
}
gboolean gboolean
gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf) gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
{ {
@ -1094,6 +1173,7 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData); mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData);
while (walk) { while (walk) {
GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data); GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data);
GstGLMixerPadClass *pad_class = GST_GL_MIXER_PAD_GET_CLASS (pad);
GstVideoAggregatorPad *vaggpad = walk->data; GstVideoAggregatorPad *vaggpad = walk->data;
GstGLMixerFrameData *frame; GstGLMixerFrameData *frame;
@ -1104,84 +1184,17 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
walk = g_list_next (walk); walk = g_list_next (walk);
if (vaggpad->buffer != NULL) { if (vaggpad->buffer != NULL) {
GstBuffer *uploaded_buf; g_assert (pad_class->upload_buffer);
GstCaps *gl_caps;
GstCapsFeatures *gl_features;
GstVideoInfo gl_info;
GstVideoFrame gl_frame;
GstGLSyncMeta *sync_meta;
gst_video_info_set_format (&gl_info,
GST_VIDEO_FORMAT_RGBA,
GST_VIDEO_INFO_WIDTH (&vaggpad->info),
GST_VIDEO_INFO_HEIGHT (&vaggpad->info));
gl_features =
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);
gl_caps = gst_video_info_to_caps (&gl_info);
gst_caps_set_features (gl_caps, 0, gst_caps_features_copy (gl_features));
if (!pad->upload) {
GstCaps *in_caps = gst_pad_get_current_caps (GST_PAD (pad));
GstCaps *upload_caps = gst_caps_copy (in_caps);
pad->upload = gst_gl_upload_new (mix->context);
gst_caps_set_features (upload_caps, 0,
gst_caps_features_copy (gl_features));
gst_gl_upload_set_caps (pad->upload, in_caps, upload_caps);
if (!pad->convert) {
pad->convert = gst_gl_color_convert_new (mix->context);
gst_gl_color_convert_set_caps (pad->convert, upload_caps, gl_caps);
}
gst_caps_unref (upload_caps);
gst_caps_unref (in_caps);
}
gst_caps_features_free (gl_features);
gst_caps_unref (gl_caps);
sync_meta = gst_buffer_get_gl_sync_meta (vaggpad->buffer);
if (sync_meta)
gst_gl_sync_meta_wait (sync_meta);
if (gst_gl_upload_perform_with_buffer (pad->upload,
vaggpad->buffer, &uploaded_buf) != GST_GL_UPLOAD_DONE) {
++array_index;
pad->mapped = FALSE;
continue;
}
if (pad->gl_buffer) if (pad->gl_buffer)
gst_buffer_unref (pad->gl_buffer); gst_buffer_unref (pad->gl_buffer);
pad->gl_buffer = pad_class->upload_buffer (mix, frame, vaggpad->buffer);
if (!(pad->gl_buffer = GST_DEBUG_OBJECT (pad,
gst_gl_color_convert_perform (pad->convert, uploaded_buf))) { "uploaded buffer %" GST_PTR_FORMAT " from buffer %" GST_PTR_FORMAT,
++array_index; pad->gl_buffer, vaggpad->buffer);
pad->mapped = FALSE;
gst_buffer_unref (uploaded_buf);
continue;
}
if (!gst_video_frame_map (&gl_frame, &gl_info, pad->gl_buffer,
GST_MAP_READ | GST_MAP_GL)) {
++array_index;
pad->mapped = FALSE;
gst_buffer_unref (uploaded_buf);
gst_buffer_unref (pad->gl_buffer);
pad->gl_buffer = NULL;
continue;
}
pad->mapped = TRUE;
frame->texture = *(guint *) gl_frame.data[0];
gst_buffer_unref (uploaded_buf);
gst_video_frame_unmap (&gl_frame);
} }
++array_index; ++array_index;
} }
@ -1217,10 +1230,9 @@ out:
while (walk) { while (walk) {
GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data); GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data);
if (pad->mapped) if (pad->upload)
gst_gl_upload_release_buffer (pad->upload); gst_gl_upload_release_buffer (pad->upload);
pad->mapped = FALSE;
walk = g_list_next (walk); walk = g_list_next (walk);
i++; i++;
} }

View file

@ -29,15 +29,20 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _GstGLMixer GstGLMixer;
typedef struct _GstGLMixerFrameData GstGLMixerFrameData;
#define GST_TYPE_GL_MIXER_PAD (gst_gl_mixer_pad_get_type()) #define GST_TYPE_GL_MIXER_PAD (gst_gl_mixer_pad_get_type())
#define GST_GL_MIXER_PAD(obj) \ #define GST_GL_MIXER_PAD(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_MIXER_PAD, GstGLMixerPad)) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_MIXER_PAD, GstGLMixerPad))
#define GST_GL_MIXER_PAD_CLASS(klass) \ #define GST_GL_MIXER_PAD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_MIXER_PAD, GstGLMixerPadiClass)) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_MIXER_PAD, GstGLMixerPadClass))
#define GST_IS_GL_MIXER_PAD(obj) \ #define GST_IS_GL_MIXER_PAD(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_MIXER_PAD)) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_MIXER_PAD))
#define GST_IS_GL_MIXER_PAD_CLASS(klass) \ #define GST_IS_GL_MIXER_PAD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_MIXER_PAD)) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_MIXER_PAD))
#define GST_GL_MIXER_PAD_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_GL_MIXER_PAD,GstGLMixerPadClass))
typedef struct _GstGLMixerPad GstGLMixerPad; typedef struct _GstGLMixerPad GstGLMixerPad;
typedef struct _GstGLMixerPadClass GstGLMixerPadClass; typedef struct _GstGLMixerPadClass GstGLMixerPadClass;
@ -51,12 +56,13 @@ struct _GstGLMixerPad
GstGLUpload *upload; GstGLUpload *upload;
GstGLColorConvert *convert; GstGLColorConvert *convert;
GstBuffer *gl_buffer; GstBuffer *gl_buffer;
gboolean mapped;
}; };
struct _GstGLMixerPadClass struct _GstGLMixerPadClass
{ {
GstVideoAggregatorPadClass parent_class; GstVideoAggregatorPadClass parent_class;
GstBuffer * (*upload_buffer) (GstGLMixer * mix, GstGLMixerFrameData * frame, GstBuffer * buffer);
}; };
GType gst_gl_mixer_pad_get_type (void); GType gst_gl_mixer_pad_get_type (void);

View file

@ -178,6 +178,8 @@ static void gst_gl_video_mixer_pad_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec); guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_gl_video_mixer_pad_get_property (GObject * object, static void gst_gl_video_mixer_pad_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static GstBuffer *gst_gl_video_mixer_pad_upload_buffer (GstGLMixer * mix,
GstGLMixerFrameData * frame, GstBuffer * buffer);
#define DEFAULT_PAD_XPOS 0 #define DEFAULT_PAD_XPOS 0
#define DEFAULT_PAD_YPOS 0 #define DEFAULT_PAD_YPOS 0
@ -204,6 +206,7 @@ static void
gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass) gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass)
{ {
GObjectClass *gobject_class = (GObjectClass *) klass; GObjectClass *gobject_class = (GObjectClass *) klass;
GstGLMixerPadClass *mix_pad_class = (GstGLMixerPadClass *) klass;
gobject_class->set_property = gst_gl_video_mixer_pad_set_property; gobject_class->set_property = gst_gl_video_mixer_pad_set_property;
gobject_class->get_property = gst_gl_video_mixer_pad_get_property; gobject_class->get_property = gst_gl_video_mixer_pad_get_property;
@ -228,6 +231,8 @@ gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass)
g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0, g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
DEFAULT_PAD_ALPHA, DEFAULT_PAD_ALPHA,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
mix_pad_class->upload_buffer = gst_gl_video_mixer_pad_upload_buffer;
} }
static void static void
@ -293,6 +298,22 @@ gst_gl_video_mixer_pad_set_property (GObject * object, guint prop_id,
gst_object_unref (mix); gst_object_unref (mix);
} }
static GstBuffer *
gst_gl_video_mixer_pad_upload_buffer (GstGLMixer * mix,
GstGLMixerFrameData * frame, GstBuffer * buffer)
{
GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (frame->pad);
if (pad->alpha > 0.0) {
return
GST_GL_MIXER_PAD_CLASS
(gst_gl_video_mixer_pad_parent_class)->upload_buffer (mix, frame,
buffer);
}
return NULL;
}
#define GST_GL_TYPE_VIDEO_MIXER_BACKGROUND (gst_gl_video_mixer_background_get_type()) #define GST_GL_TYPE_VIDEO_MIXER_BACKGROUND (gst_gl_video_mixer_background_get_type())
static GType static GType
gst_gl_video_mixer_background_get_type (void) gst_gl_video_mixer_background_get_type (void)