mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
Move GstVideoAggregator, compositor and OpenGL mixers from -bad
Merge branch 'videoaggregator-compositor-glmixers-move' Fixes #137 and #138.
This commit is contained in:
commit
f11571f398
21 changed files with 13059 additions and 178 deletions
|
@ -28,10 +28,6 @@
|
|||
|
||||
#include "gstglbasemixer.h"
|
||||
|
||||
#define gst_gl_base_mixer_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE (GstGLBaseMixer, gst_gl_base_mixer,
|
||||
GST_TYPE_VIDEO_AGGREGATOR);
|
||||
|
||||
#define GST_CAT_DEFAULT gst_gl_base_mixer_debug
|
||||
GST_DEBUG_CATEGORY (gst_gl_base_mixer_debug);
|
||||
|
||||
|
@ -45,14 +41,6 @@ static void gst_gl_base_mixer_set_context (GstElement * element,
|
|||
static GstStateChangeReturn gst_gl_base_mixer_change_state (GstElement *
|
||||
element, GstStateChange transition);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_PAD_0
|
||||
};
|
||||
|
||||
#define GST_GL_BASE_MIXER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_GL_BASE_MIXER, GstGLBaseMixerPrivate))
|
||||
|
||||
struct _GstGLBaseMixerPrivate
|
||||
{
|
||||
gboolean negotiated;
|
||||
|
@ -60,6 +48,10 @@ struct _GstGLBaseMixerPrivate
|
|||
GstGLContext *other_context;
|
||||
};
|
||||
|
||||
#define gst_gl_base_mixer_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstGLBaseMixer, gst_gl_base_mixer,
|
||||
GST_TYPE_VIDEO_AGGREGATOR);
|
||||
|
||||
G_DEFINE_TYPE (GstGLBaseMixerPad, gst_gl_base_mixer_pad,
|
||||
GST_TYPE_VIDEO_AGGREGATOR_PAD);
|
||||
|
||||
|
@ -73,7 +65,6 @@ gst_gl_base_mixer_pad_class_init (GstGLBaseMixerPadClass * klass)
|
|||
gobject_class->set_property = gst_gl_base_mixer_pad_set_property;
|
||||
gobject_class->get_property = gst_gl_base_mixer_pad_get_property;
|
||||
|
||||
vaggpad_class->set_info = NULL;
|
||||
vaggpad_class->prepare_frame = NULL;
|
||||
vaggpad_class->clean_frame = NULL;
|
||||
}
|
||||
|
@ -261,8 +252,6 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
|
|||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstGLBaseMixerPrivate));
|
||||
|
||||
gobject_class->get_property = gst_gl_base_mixer_get_property;
|
||||
gobject_class->set_property = gst_gl_base_mixer_set_property;
|
||||
|
||||
|
@ -293,7 +282,7 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
|
|||
static void
|
||||
gst_gl_base_mixer_init (GstGLBaseMixer * mix)
|
||||
{
|
||||
mix->priv = GST_GL_BASE_MIXER_GET_PRIVATE (mix);
|
||||
mix->priv = gst_gl_base_mixer_get_instance_private (mix);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -26,10 +26,9 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include "gstglmixer.h"
|
||||
#include <string.h>
|
||||
|
||||
#define gst_gl_mixer_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE (GstGLMixer, gst_gl_mixer, GST_TYPE_GL_BASE_MIXER);
|
||||
#include "gstglmixer.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_gl_mixer_debug
|
||||
GST_DEBUG_CATEGORY (gst_gl_mixer_debug);
|
||||
|
@ -38,15 +37,17 @@ static void gst_gl_mixer_pad_get_property (GObject * object, guint prop_id,
|
|||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static gboolean gst_gl_mixer_pad_prepare_frame (GstVideoAggregatorPad * vpad,
|
||||
GstVideoAggregator * vagg, GstBuffer * buffer,
|
||||
GstVideoFrame * prepared_frame);
|
||||
static void gst_gl_mixer_pad_clean_frame (GstVideoAggregatorPad * vpad,
|
||||
GstVideoAggregator * vagg, GstVideoFrame * prepared_frame);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_PAD_0
|
||||
};
|
||||
|
||||
#define GST_GL_MIXER_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_GL_MIXER, GstGLMixerPrivate))
|
||||
|
||||
struct _GstGLMixerPrivate
|
||||
{
|
||||
gboolean negotiated;
|
||||
|
@ -56,6 +57,10 @@ struct _GstGLMixerPrivate
|
|||
GCond gl_resource_cond;
|
||||
};
|
||||
|
||||
#define gst_gl_mixer_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstGLMixer, gst_gl_mixer,
|
||||
GST_TYPE_GL_BASE_MIXER);
|
||||
|
||||
G_DEFINE_TYPE (GstGLMixerPad, gst_gl_mixer_pad, GST_TYPE_GL_BASE_MIXER_PAD);
|
||||
|
||||
static void
|
||||
|
@ -68,9 +73,8 @@ gst_gl_mixer_pad_class_init (GstGLMixerPadClass * klass)
|
|||
gobject_class->set_property = gst_gl_mixer_pad_set_property;
|
||||
gobject_class->get_property = gst_gl_mixer_pad_get_property;
|
||||
|
||||
vaggpad_class->set_info = NULL;
|
||||
vaggpad_class->prepare_frame = NULL;
|
||||
vaggpad_class->clean_frame = NULL;
|
||||
vaggpad_class->prepare_frame = gst_gl_mixer_pad_prepare_frame;
|
||||
vaggpad_class->clean_frame = gst_gl_mixer_pad_clean_frame;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -95,6 +99,50 @@ gst_gl_mixer_pad_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_mixer_pad_prepare_frame (GstVideoAggregatorPad * vpad,
|
||||
GstVideoAggregator * vagg, GstBuffer * buffer,
|
||||
GstVideoFrame * prepared_frame)
|
||||
{
|
||||
GstGLMixerPad *pad = GST_GL_MIXER_PAD (vpad);
|
||||
GstGLMixer *mix = GST_GL_MIXER (vagg);
|
||||
GstVideoInfo gl_info;
|
||||
GstGLSyncMeta *sync_meta;
|
||||
|
||||
pad->current_texture = 0;
|
||||
|
||||
gst_video_info_set_format (&gl_info,
|
||||
GST_VIDEO_FORMAT_RGBA,
|
||||
GST_VIDEO_INFO_WIDTH (&vpad->info), GST_VIDEO_INFO_HEIGHT (&vpad->info));
|
||||
|
||||
sync_meta = gst_buffer_get_gl_sync_meta (buffer);
|
||||
if (sync_meta)
|
||||
gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context);
|
||||
|
||||
if (!gst_video_frame_map (prepared_frame, &gl_info, buffer,
|
||||
GST_MAP_READ | GST_MAP_GL)) {
|
||||
GST_ERROR_OBJECT (pad, "Failed to map input frame");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pad->current_texture = *(guint *) prepared_frame->data[0];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mixer_pad_clean_frame (GstVideoAggregatorPad * vpad,
|
||||
GstVideoAggregator * vagg, GstVideoFrame * prepared_frame)
|
||||
{
|
||||
GstGLMixerPad *pad = GST_GL_MIXER_PAD (vpad);
|
||||
|
||||
pad->current_texture = 0;
|
||||
if (prepared_frame->buffer) {
|
||||
gst_video_frame_unmap (prepared_frame);
|
||||
memset (prepared_frame, 0, sizeof (GstVideoFrame));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_negotiated_caps (GstAggregator * agg, GstCaps * caps)
|
||||
{
|
||||
|
@ -357,8 +405,6 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass)
|
|||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glmixer", 0, "OpenGL mixer");
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstGLMixerPrivate));
|
||||
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gl_mixer_finalize);
|
||||
|
||||
gobject_class->get_property = gst_gl_mixer_get_property;
|
||||
|
@ -396,7 +442,7 @@ gst_gl_mixer_reset (GstGLMixer * mix)
|
|||
static void
|
||||
gst_gl_mixer_init (GstGLMixer * mix)
|
||||
{
|
||||
mix->priv = GST_GL_MIXER_GET_PRIVATE (mix);
|
||||
mix->priv = gst_gl_mixer_get_instance_private (mix);
|
||||
|
||||
mix->priv->gl_resource_ready = FALSE;
|
||||
g_mutex_init (&mix->priv->gl_resource_lock);
|
||||
|
@ -561,42 +607,6 @@ context_error:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_mixer_upload_frames (GstElement * element, GstPad * sink_pad,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (sink_pad);
|
||||
GstGLMixerPad *pad = GST_GL_MIXER_PAD (sink_pad);
|
||||
GstGLMixer *mix = GST_GL_MIXER (element);
|
||||
|
||||
pad->current_texture = 0;
|
||||
if (vaggpad->buffer != NULL) {
|
||||
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));
|
||||
|
||||
sync_meta = gst_buffer_get_gl_sync_meta (vaggpad->buffer);
|
||||
if (sync_meta)
|
||||
gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context);
|
||||
|
||||
if (!gst_video_frame_map (&gl_frame, &gl_info, vaggpad->buffer,
|
||||
GST_MAP_READ | GST_MAP_GL)) {
|
||||
GST_ERROR_OBJECT (pad, "Failed to map input frame");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pad->current_texture = *(guint *) gl_frame.data[0];
|
||||
gst_video_frame_unmap (&gl_frame);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
|
||||
{
|
||||
|
@ -616,12 +626,6 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
|
|||
|
||||
out_tex = (GstGLMemory *) out_frame.map[0].memory;
|
||||
|
||||
if (!gst_element_foreach_sink_pad (GST_ELEMENT_CAST (mix),
|
||||
gst_gl_mixer_upload_frames, NULL)) {
|
||||
res = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_mutex_lock (&priv->gl_resource_lock);
|
||||
if (!priv->gl_resource_ready)
|
||||
g_cond_wait (&priv->gl_resource_cond, &priv->gl_resource_lock);
|
||||
|
|
|
@ -68,6 +68,7 @@ struct input_chain
|
|||
GstGhostPad *ghost_pad;
|
||||
GstElement *upload;
|
||||
GstElement *in_convert;
|
||||
GstElement *in_overlay;
|
||||
GstPad *mixer_pad;
|
||||
};
|
||||
|
||||
|
@ -91,6 +92,12 @@ _free_input_chain (struct input_chain *chain)
|
|||
chain->in_convert = NULL;
|
||||
}
|
||||
|
||||
if (chain->in_overlay) {
|
||||
gst_element_set_state (chain->in_overlay, GST_STATE_NULL);
|
||||
gst_bin_remove (GST_BIN (chain->self), chain->in_overlay);
|
||||
chain->in_overlay = NULL;
|
||||
}
|
||||
|
||||
if (chain->mixer_pad) {
|
||||
gst_element_release_request_pad (chain->self->mixer, chain->mixer_pad);
|
||||
gst_object_unref (chain->mixer_pad);
|
||||
|
@ -126,9 +133,8 @@ enum
|
|||
static void gst_gl_mixer_bin_child_proxy_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
#define GST_GL_MIXER_BIN_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_TYPE_GL_MIXER_BIN, GstGLMixerBinPrivate))
|
||||
G_DEFINE_TYPE_WITH_CODE (GstGLMixerBin, gst_gl_mixer_bin, GST_TYPE_BIN,
|
||||
G_ADD_PRIVATE (GstGLMixerBin)
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
|
||||
gst_gl_mixer_bin_child_proxy_init));
|
||||
|
||||
|
@ -145,7 +151,6 @@ static void gst_gl_mixer_bin_set_property (GObject * object, guint prop_id,
|
|||
static void gst_gl_mixer_bin_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_gl_mixer_bin_dispose (GObject * object);
|
||||
static void gst_gl_mixer_bin_finalize (GObject * object);
|
||||
|
||||
static GstPad *gst_gl_mixer_bin_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps);
|
||||
|
@ -160,8 +165,6 @@ gst_gl_mixer_bin_class_init (GstGLMixerBinClass * klass)
|
|||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstCaps *upload_caps;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstGLMixerBinPrivate));
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glmixerbin", 0,
|
||||
"opengl mixer bin");
|
||||
|
||||
|
@ -172,7 +175,6 @@ gst_gl_mixer_bin_class_init (GstGLMixerBinClass * klass)
|
|||
gobject_class->get_property = gst_gl_mixer_bin_get_property;
|
||||
gobject_class->set_property = gst_gl_mixer_bin_set_property;
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_gl_mixer_bin_dispose);
|
||||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gl_mixer_bin_finalize);
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_MIXER,
|
||||
g_param_spec_object ("mixer",
|
||||
|
@ -183,11 +185,10 @@ gst_gl_mixer_bin_class_init (GstGLMixerBinClass * klass)
|
|||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_LATENCY,
|
||||
g_param_spec_int64 ("latency", "Buffer latency",
|
||||
g_param_spec_uint64 ("latency", "Buffer latency",
|
||||
"Additional latency in live mode to allow upstream "
|
||||
"to take longer to produce buffers for the current "
|
||||
"position", 0,
|
||||
(G_MAXLONG == G_MAXINT64) ? G_MAXINT64 : (G_MAXLONG * GST_SECOND - 1),
|
||||
"position (in nanoseconds)", 0, G_MAXUINT64,
|
||||
DEFAULT_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_START_TIME_SELECTION,
|
||||
|
@ -235,7 +236,7 @@ gst_gl_mixer_bin_init (GstGLMixerBin * self)
|
|||
gboolean res = TRUE;
|
||||
GstPad *pad;
|
||||
|
||||
self->priv = GST_GL_MIXER_BIN_GET_PRIVATE (self);
|
||||
self->priv = gst_gl_mixer_bin_get_instance_private (self);
|
||||
|
||||
self->out_convert = gst_element_factory_make ("glcolorconvert", NULL);
|
||||
self->download = gst_element_factory_make ("gldownload", NULL);
|
||||
|
@ -259,17 +260,6 @@ gst_gl_mixer_bin_init (GstGLMixerBin * self)
|
|||
GST_ERROR_OBJECT (self, "failed to create output chain");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mixer_bin_finalize (GObject * object)
|
||||
{
|
||||
GstGLMixerBin *self = GST_GL_MIXER_BIN (object);
|
||||
|
||||
if (self->mixer)
|
||||
gst_object_unref (self->mixer);
|
||||
|
||||
G_OBJECT_CLASS (gst_gl_mixer_bin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mixer_bin_dispose (GObject * object)
|
||||
{
|
||||
|
@ -308,16 +298,21 @@ _create_input_chain (GstGLMixerBin * self, struct input_chain *chain,
|
|||
|
||||
chain->upload = gst_element_factory_make ("glupload", NULL);
|
||||
chain->in_convert = gst_element_factory_make ("glcolorconvert", NULL);
|
||||
chain->in_overlay = gst_element_factory_make ("gloverlaycompositor", NULL);
|
||||
|
||||
res &= gst_bin_add (GST_BIN (self), chain->in_convert);
|
||||
res &= gst_bin_add (GST_BIN (self), chain->in_overlay);
|
||||
res &= gst_bin_add (GST_BIN (self), chain->upload);
|
||||
|
||||
pad = gst_element_get_static_pad (chain->in_convert, "src");
|
||||
pad = gst_element_get_static_pad (chain->in_overlay, "src");
|
||||
if (gst_pad_link (pad, mixer_pad) != GST_PAD_LINK_OK) {
|
||||
gst_object_unref (pad);
|
||||
return FALSE;
|
||||
}
|
||||
gst_object_unref (pad);
|
||||
res &=
|
||||
gst_element_link_pads (chain->in_convert, "src", chain->in_overlay,
|
||||
"sink");
|
||||
res &=
|
||||
gst_element_link_pads (chain->upload, "src", chain->in_convert, "sink");
|
||||
|
||||
|
@ -349,6 +344,7 @@ _create_input_chain (GstGLMixerBin * self, struct input_chain *chain,
|
|||
|
||||
gst_element_sync_state_with_parent (chain->upload);
|
||||
gst_element_sync_state_with_parent (chain->in_convert);
|
||||
gst_element_sync_state_with_parent (chain->in_overlay);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -398,39 +394,18 @@ _connect_mixer_element (GstGLMixerBin * self)
|
|||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* @mixer: (transfer floating):
|
||||
*/
|
||||
static gboolean
|
||||
gst_gl_mixer_bin_set_mixer (GstGLMixerBin * self, GstElement * mixer)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (mixer), FALSE);
|
||||
|
||||
if (self->mixer) {
|
||||
gst_element_set_locked_state (self->mixer, TRUE);
|
||||
gst_bin_remove (GST_BIN (self), self->mixer);
|
||||
gst_element_set_state (self->mixer, GST_STATE_NULL);
|
||||
gst_object_unref (self->mixer);
|
||||
self->mixer = NULL;
|
||||
}
|
||||
self->mixer = mixer;
|
||||
|
||||
gst_object_ref_sink (mixer);
|
||||
|
||||
if (mixer && !_connect_mixer_element (self)) {
|
||||
gst_object_unref (self->mixer);
|
||||
self->mixer = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_gl_mixer_bin_finish_init_with_element (GstGLMixerBin * self,
|
||||
GstElement * element)
|
||||
{
|
||||
gst_gl_mixer_bin_set_mixer (self, element);
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
||||
self->mixer = element;
|
||||
|
||||
if (!_connect_mixer_element (self)) {
|
||||
gst_object_unref (self->mixer);
|
||||
self->mixer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -475,7 +450,11 @@ gst_gl_mixer_bin_set_property (GObject * object,
|
|||
GstElement *mixer = g_value_get_object (value);
|
||||
/* FIXME: deal with replacing a mixer */
|
||||
g_return_if_fail (!self->mixer || (self->mixer == mixer));
|
||||
gst_gl_mixer_bin_set_mixer (self, mixer);
|
||||
self->mixer = mixer;
|
||||
if (mixer) {
|
||||
gst_object_ref_sink (mixer);
|
||||
_connect_mixer_element (self);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -560,12 +539,9 @@ gst_gl_mixer_bin_change_state (GstElement * element, GstStateChange transition)
|
|||
if (klass->create_element)
|
||||
self->mixer = klass->create_element ();
|
||||
|
||||
if (!self->mixer) {
|
||||
if (!self->mixer)
|
||||
g_signal_emit (element,
|
||||
gst_gl_mixer_bin_signals[SIGNAL_CREATE_ELEMENT], 0, &self->mixer);
|
||||
if (self->mixer && g_object_is_floating (self->mixer))
|
||||
gst_object_ref_sink (self->mixer);
|
||||
}
|
||||
|
||||
if (!self->mixer) {
|
||||
GST_ERROR_OBJECT (element, "Failed to retrieve element");
|
||||
|
|
|
@ -55,10 +55,15 @@ enum
|
|||
PROP_0,
|
||||
};
|
||||
|
||||
static void gst_gl_mosaic_child_proxy_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
#define DEBUG_INIT \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_gl_mosaic_debug, "glmosaic", 0, "glmosaic element");
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstGLMosaic, gst_gl_mosaic, GST_TYPE_GL_MIXER,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
|
||||
gst_gl_mosaic_child_proxy_init);
|
||||
DEBUG_INIT);
|
||||
|
||||
static void gst_gl_mosaic_set_property (GObject * object, guint prop_id,
|
||||
|
@ -66,6 +71,10 @@ static void gst_gl_mosaic_set_property (GObject * object, guint prop_id,
|
|||
static void gst_gl_mosaic_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstPad *gst_gl_mosaic_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * temp, const gchar * req_name, const GstCaps * caps);
|
||||
static void gst_gl_mosaic_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
static void gst_gl_mosaic_reset (GstGLMixer * mixer);
|
||||
static gboolean gst_gl_mosaic_init_shader (GstGLMixer * mixer,
|
||||
GstCaps * outcaps);
|
||||
|
@ -128,6 +137,10 @@ gst_gl_mosaic_class_init (GstGLMosaicClass * klass)
|
|||
gobject_class->set_property = gst_gl_mosaic_set_property;
|
||||
gobject_class->get_property = gst_gl_mosaic_get_property;
|
||||
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_gl_mosaic_request_new_pad);
|
||||
element_class->release_pad = GST_DEBUG_FUNCPTR (gst_gl_mosaic_release_pad);
|
||||
|
||||
gst_element_class_set_metadata (element_class, "OpenGL mosaic",
|
||||
"Filter/Effect/Video", "OpenGL mosaic",
|
||||
"Julien Isorce <julien.isorce@gmail.com>");
|
||||
|
@ -171,6 +184,44 @@ gst_gl_mosaic_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_gl_mosaic_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * req_name, const GstCaps * caps)
|
||||
{
|
||||
GstPad *newpad;
|
||||
|
||||
newpad = (GstPad *)
|
||||
GST_ELEMENT_CLASS (gst_gl_mosaic_parent_class)->request_new_pad (element,
|
||||
templ, req_name, caps);
|
||||
|
||||
if (newpad == NULL)
|
||||
goto could_not_create;
|
||||
|
||||
gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (newpad),
|
||||
GST_OBJECT_NAME (newpad));
|
||||
|
||||
return newpad;
|
||||
|
||||
could_not_create:
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "could not create/add pad");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mosaic_release_pad (GstElement * element, GstPad * pad)
|
||||
{
|
||||
GstGLMosaic *gl_mosaic = GST_GL_MOSAIC (element);
|
||||
|
||||
GST_DEBUG_OBJECT (gl_mosaic, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
gst_child_proxy_child_removed (GST_CHILD_PROXY (gl_mosaic), G_OBJECT (pad),
|
||||
GST_OBJECT_NAME (pad));
|
||||
|
||||
GST_ELEMENT_CLASS (gst_gl_mosaic_parent_class)->release_pad (element, pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mosaic_reset (GstGLMixer * mixer)
|
||||
{
|
||||
|
@ -356,3 +407,43 @@ gst_gl_mosaic_callback (gpointer stuff)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* GstChildProxy implementation */
|
||||
static GObject *
|
||||
gst_gl_mosaic_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
|
||||
guint index)
|
||||
{
|
||||
GstGLMosaic *gl_mosaic = GST_GL_MOSAIC (child_proxy);
|
||||
GObject *obj = NULL;
|
||||
|
||||
GST_OBJECT_LOCK (gl_mosaic);
|
||||
obj = g_list_nth_data (GST_ELEMENT_CAST (gl_mosaic)->sinkpads, index);
|
||||
if (obj)
|
||||
gst_object_ref (obj);
|
||||
GST_OBJECT_UNLOCK (gl_mosaic);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static guint
|
||||
gst_gl_mosaic_child_proxy_get_children_count (GstChildProxy * child_proxy)
|
||||
{
|
||||
guint count = 0;
|
||||
GstGLMosaic *gl_mosaic = GST_GL_MOSAIC (child_proxy);
|
||||
|
||||
GST_OBJECT_LOCK (gl_mosaic);
|
||||
count = GST_ELEMENT_CAST (gl_mosaic)->numsinkpads;
|
||||
GST_OBJECT_UNLOCK (gl_mosaic);
|
||||
GST_INFO_OBJECT (gl_mosaic, "Children Count: %d", count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_mosaic_child_proxy_init (gpointer g_iface, gpointer iface_data)
|
||||
{
|
||||
GstChildProxyInterface *iface = g_iface;
|
||||
|
||||
iface->get_child_by_index = gst_gl_mosaic_child_proxy_get_child_by_index;
|
||||
iface->get_children_count = gst_gl_mosaic_child_proxy_get_children_count;
|
||||
}
|
||||
|
|
|
@ -78,12 +78,17 @@ gst_gl_stereo_mix_pad_init (GstGLStereoMixPad * pad)
|
|||
{
|
||||
}
|
||||
|
||||
static void gst_gl_stereo_mix_child_proxy_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
#define gst_gl_stereo_mix_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstGLStereoMix, gst_gl_stereo_mix, GST_TYPE_GL_MIXER);
|
||||
G_DEFINE_TYPE_WITH_CODE (GstGLStereoMix, gst_gl_stereo_mix, GST_TYPE_GL_MIXER,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
|
||||
gst_gl_stereo_mix_child_proxy_init));
|
||||
|
||||
static GstCaps *_update_caps (GstVideoAggregator * vagg, GstCaps * caps);
|
||||
static gboolean _negotiated_caps (GstAggregator * aggregator, GstCaps * caps);
|
||||
gboolean gst_gl_stereo_mix_make_output (GstGLStereoMix * mix);
|
||||
static gboolean gst_gl_stereo_mix_make_output (GstGLStereoMix * mix);
|
||||
static gboolean gst_gl_stereo_mix_process_frames (GstGLStereoMix * mixer);
|
||||
|
||||
#define DEFAULT_DOWNMIX GST_GL_STEREO_DOWNMIX_ANAGLYPH_GREEN_MAGENTA_DUBOIS
|
||||
|
@ -133,8 +138,12 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
|
|||
"; " GST_VIDEO_CAPS_MAKE (GST_GL_COLOR_CONVERT_FORMATS))
|
||||
);
|
||||
|
||||
static GstFlowReturn gst_gl_stereo_mix_get_output_buffer (GstVideoAggregator *
|
||||
videoaggregator, GstBuffer ** outbuf);
|
||||
static GstPad *gst_gl_stereo_mix_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * temp, const gchar * req_name, const GstCaps * caps);
|
||||
static void gst_gl_stereo_mix_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
static GstFlowReturn gst_gl_stereo_mix_create_output_buffer (GstVideoAggregator
|
||||
* videoaggregator, GstBuffer ** outbuf);
|
||||
static gboolean gst_gl_stereo_mix_stop (GstAggregator * agg);
|
||||
static gboolean gst_gl_stereo_mix_start (GstAggregator * agg);
|
||||
static gboolean gst_gl_stereo_mix_src_query (GstAggregator * agg,
|
||||
|
@ -184,6 +193,11 @@ gst_gl_stereo_mix_class_init (GstGLStereoMixClass * klass)
|
|||
gst_element_class_add_static_pad_template_with_gtype (element_class,
|
||||
&sink_factory, GST_TYPE_GL_STEREO_MIX_PAD);
|
||||
|
||||
element_class->request_new_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_gl_stereo_mix_request_new_pad);
|
||||
element_class->release_pad =
|
||||
GST_DEBUG_FUNCPTR (gst_gl_stereo_mix_release_pad);
|
||||
|
||||
agg_class->stop = gst_gl_stereo_mix_stop;
|
||||
agg_class->start = gst_gl_stereo_mix_start;
|
||||
agg_class->src_query = gst_gl_stereo_mix_src_query;
|
||||
|
@ -191,8 +205,8 @@ gst_gl_stereo_mix_class_init (GstGLStereoMixClass * klass)
|
|||
|
||||
videoaggregator_class->aggregate_frames = gst_gl_stereo_mix_aggregate_frames;
|
||||
videoaggregator_class->update_caps = _update_caps;
|
||||
videoaggregator_class->get_output_buffer =
|
||||
gst_gl_stereo_mix_get_output_buffer;
|
||||
videoaggregator_class->create_output_buffer =
|
||||
gst_gl_stereo_mix_create_output_buffer;
|
||||
|
||||
base_mix_class->supported_gl_api =
|
||||
GST_GL_API_GLES2 | GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
|
||||
|
@ -249,7 +263,7 @@ gst_gl_stereo_mix_src_query (GstAggregator * agg, GstQuery * query)
|
|||
|
||||
|
||||
static GstFlowReturn
|
||||
gst_gl_stereo_mix_get_output_buffer (GstVideoAggregator * videoaggregator,
|
||||
gst_gl_stereo_mix_create_output_buffer (GstVideoAggregator * videoaggregator,
|
||||
GstBuffer ** outbuf)
|
||||
{
|
||||
GstGLStereoMix *mix = GST_GL_STEREO_MIX (videoaggregator);
|
||||
|
@ -287,7 +301,7 @@ gst_gl_stereo_mix_get_output_buffer (GstVideoAggregator * videoaggregator,
|
|||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
gst_gl_stereo_mix_make_output (GstGLStereoMix * mix)
|
||||
{
|
||||
GList *walk;
|
||||
|
@ -302,11 +316,12 @@ gst_gl_stereo_mix_make_output (GstGLStereoMix * mix)
|
|||
while (walk) {
|
||||
GstVideoAggregatorPad *vaggpad = walk->data;
|
||||
GstGLStereoMixPad *pad = walk->data;
|
||||
GstBuffer *buffer = gst_video_aggregator_pad_get_current_buffer (vaggpad);
|
||||
|
||||
GST_LOG_OBJECT (mix, "Checking pad %" GST_PTR_FORMAT, vaggpad);
|
||||
|
||||
if (vaggpad->buffer != NULL) {
|
||||
pad->current_buffer = vaggpad->buffer;
|
||||
if (buffer != NULL) {
|
||||
pad->current_buffer = buffer;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "Got buffer %" GST_PTR_FORMAT,
|
||||
pad->current_buffer);
|
||||
|
@ -399,6 +414,42 @@ gst_gl_stereo_mix_set_property (GObject * object,
|
|||
}
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_gl_stereo_mix_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
||||
const gchar * req_name, const GstCaps * caps)
|
||||
{
|
||||
GstPad *newpad;
|
||||
|
||||
newpad = (GstPad *)
|
||||
GST_ELEMENT_CLASS (parent_class)->request_new_pad (element,
|
||||
templ, req_name, caps);
|
||||
|
||||
if (newpad == NULL)
|
||||
goto could_not_create;
|
||||
|
||||
gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (newpad),
|
||||
GST_OBJECT_NAME (newpad));
|
||||
|
||||
return GST_PAD_CAST (newpad);
|
||||
|
||||
could_not_create:
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "could not create/add pad");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_stereo_mix_release_pad (GstElement * element, GstPad * pad)
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
gst_child_proxy_child_removed (GST_CHILD_PROXY (element), G_OBJECT (pad),
|
||||
GST_OBJECT_NAME (pad));
|
||||
|
||||
GST_ELEMENT_CLASS (parent_class)->release_pad (element, pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_gl_stereo_mix_start (GstAggregator * agg)
|
||||
{
|
||||
|
@ -696,3 +747,43 @@ gst_gl_stereo_mix_process_frames (GstGLStereoMix * mixer)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* GstChildProxy implementation */
|
||||
static GObject *
|
||||
gst_gl_stereo_mix_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
|
||||
guint index)
|
||||
{
|
||||
GstGLStereoMix *gl_stereo_mix = GST_GL_STEREO_MIX (child_proxy);
|
||||
GObject *obj = NULL;
|
||||
|
||||
GST_OBJECT_LOCK (gl_stereo_mix);
|
||||
obj = g_list_nth_data (GST_ELEMENT_CAST (gl_stereo_mix)->sinkpads, index);
|
||||
if (obj)
|
||||
gst_object_ref (obj);
|
||||
GST_OBJECT_UNLOCK (gl_stereo_mix);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static guint
|
||||
gst_gl_stereo_mix_child_proxy_get_children_count (GstChildProxy * child_proxy)
|
||||
{
|
||||
guint count = 0;
|
||||
GstGLStereoMix *gl_stereo_mix = GST_GL_STEREO_MIX (child_proxy);
|
||||
|
||||
GST_OBJECT_LOCK (gl_stereo_mix);
|
||||
count = GST_ELEMENT_CAST (gl_stereo_mix)->numsinkpads;
|
||||
GST_OBJECT_UNLOCK (gl_stereo_mix);
|
||||
GST_INFO_OBJECT (gl_stereo_mix, "Children Count: %d", count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_stereo_mix_child_proxy_init (gpointer g_iface, gpointer iface_data)
|
||||
{
|
||||
GstChildProxyInterface *iface = g_iface;
|
||||
|
||||
iface->get_child_by_index = gst_gl_stereo_mix_child_proxy_get_child_by_index;
|
||||
iface->get_children_count = gst_gl_stereo_mix_child_proxy_get_children_count;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/controller/gstproxycontrolbinding.h>
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
#include <gst/video/gstvideoaffinetransformationmeta.h>
|
||||
|
@ -136,7 +137,7 @@ gst_gl_video_mixer_blend_function_get_type (void)
|
|||
"One Minus Constant Color", "one-minus-contant-color"},
|
||||
{GST_GL_VIDEO_MIXER_BLEND_FUNCTION_CONSTANT_ALPHA, "Constant Alpha",
|
||||
"constant-alpha"},
|
||||
{GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_COLOR,
|
||||
{GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_CONSTANT_ALPHA,
|
||||
"One Minus Constant Alpha", "one-minus-contant-alpha"},
|
||||
{GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA_SATURATE,
|
||||
"Source Alpha Saturate", "src-alpha-saturate"},
|
||||
|
@ -157,11 +158,11 @@ gst_gl_video_mixer_blend_function_get_type (void)
|
|||
#define DEFAULT_PAD_HEIGHT 0
|
||||
#define DEFAULT_PAD_ALPHA 1.0
|
||||
#define DEFAULT_PAD_ZORDER 0
|
||||
#define DEFAULT_PAD_IGNORE_EOS FALSE
|
||||
#define DEFAULT_PAD_REPEAT_AFTER_EOS FALSE
|
||||
#define DEFAULT_PAD_BLEND_EQUATION_RGB GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD
|
||||
#define DEFAULT_PAD_BLEND_EQUATION_ALPHA GST_GL_VIDEO_MIXER_BLEND_EQUATION_ADD
|
||||
#define DEFAULT_PAD_BLEND_FUNCTION_SRC_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA
|
||||
#define DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_SRC_ALPHA
|
||||
#define DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE
|
||||
#define DEFAULT_PAD_BLEND_FUNCTION_DST_RGB GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA
|
||||
#define DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA GST_GL_VIDEO_MIXER_BLEND_FUNCTION_ONE_MINUS_SRC_ALPHA
|
||||
|
||||
|
@ -184,7 +185,7 @@ enum
|
|||
PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_BLUE,
|
||||
PROP_INPUT_BLEND_FUNCTION_CONSTANT_COLOR_ALPHA,
|
||||
PROP_INPUT_ZORDER,
|
||||
PROP_INPUT_IGNORE_EOS,
|
||||
PROP_INPUT_REPEAT_AFTER_EOS,
|
||||
};
|
||||
|
||||
static void gst_gl_video_mixer_input_get_property (GObject * object,
|
||||
|
@ -225,10 +226,11 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
|
|||
g_param_spec_uint ("zorder", "Z-Order", "Z Order of the picture",
|
||||
0, 10000, DEFAULT_PAD_ZORDER,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_IGNORE_EOS,
|
||||
g_param_spec_boolean ("ignore-eos", "Ignore EOS", "Aggregate the last "
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_REPEAT_AFTER_EOS,
|
||||
g_param_spec_boolean ("repeat-after-eos", "Repeat After EOS",
|
||||
"Aggregate the last "
|
||||
"frame on pads that are EOS till they are released",
|
||||
DEFAULT_PAD_IGNORE_EOS,
|
||||
DEFAULT_PAD_REPEAT_AFTER_EOS,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_XPOS,
|
||||
g_param_spec_int ("xpos", "X Position", "X Position of the picture",
|
||||
|
@ -239,12 +241,12 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
|
|||
G_MININT, G_MAXINT, DEFAULT_PAD_YPOS,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_WIDTH,
|
||||
g_param_spec_int ("width", "Width", "Width of the picture",
|
||||
G_MININT, G_MAXINT, DEFAULT_PAD_WIDTH,
|
||||
g_param_spec_int ("width", "Width", "Width of the picture", G_MININT,
|
||||
G_MAXINT, DEFAULT_PAD_WIDTH,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_HEIGHT,
|
||||
g_param_spec_int ("height", "Height", "Height of the picture",
|
||||
G_MININT, G_MAXINT, DEFAULT_PAD_HEIGHT,
|
||||
g_param_spec_int ("height", "Height", "Height of the picture", G_MININT,
|
||||
G_MAXINT, DEFAULT_PAD_HEIGHT,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_ALPHA,
|
||||
g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
|
||||
|
@ -252,8 +254,7 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
|
|||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, PROP_INPUT_BLEND_EQUATION_RGB,
|
||||
g_param_spec_enum ("blend-equation-rgb", "Blend Equation RGB",
|
||||
"Blend Equation for RGB",
|
||||
GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
|
||||
"Blend Equation for RGB", GST_TYPE_GL_VIDEO_MIXER_BLEND_EQUATION,
|
||||
DEFAULT_PAD_BLEND_EQUATION_RGB,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class,
|
||||
|
@ -288,7 +289,7 @@ gst_gl_video_mixer_input_class_init (GstGLVideoMixerInputClass * klass)
|
|||
PROP_INPUT_BLEND_FUNCTION_DST_ALPHA,
|
||||
g_param_spec_enum ("blend-function-dst-alpha",
|
||||
"Blend Function Destination Alpha",
|
||||
"Blend Function for Destiniation Alpha",
|
||||
"Blend Function for Destination Alpha",
|
||||
GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
|
||||
DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
@ -451,12 +452,16 @@ enum
|
|||
PROP_BACKGROUND,
|
||||
};
|
||||
|
||||
static void gst_gl_video_mixer_child_proxy_init (gpointer g_iface,
|
||||
gpointer iface_data);
|
||||
|
||||
#define DEBUG_INIT \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_gl_video_mixer_debug, "glvideomixer", 0, "glvideomixer element");
|
||||
|
||||
#define gst_gl_video_mixer_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstGLVideoMixer, gst_gl_video_mixer, GST_TYPE_GL_MIXER,
|
||||
DEBUG_INIT);
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY,
|
||||
gst_gl_video_mixer_child_proxy_init); DEBUG_INIT);
|
||||
|
||||
static void gst_gl_video_mixer_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
@ -565,6 +570,7 @@ struct _GstGLVideoMixerPad
|
|||
|
||||
gboolean geometry_change;
|
||||
GLuint vertex_buffer;
|
||||
gfloat m_matrix[16];
|
||||
};
|
||||
|
||||
struct _GstGLVideoMixerPadClass
|
||||
|
@ -611,6 +617,11 @@ gst_gl_video_mixer_pad_init (GstGLVideoMixerPad * pad)
|
|||
pad->blend_function_src_alpha = DEFAULT_PAD_BLEND_FUNCTION_SRC_ALPHA;
|
||||
pad->blend_function_dst_rgb = DEFAULT_PAD_BLEND_FUNCTION_DST_RGB;
|
||||
pad->blend_function_dst_alpha = DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA;
|
||||
memset (pad->m_matrix, 0, sizeof (gfloat) * 4 * 4);
|
||||
pad->m_matrix[0] = 1.0;
|
||||
pad->m_matrix[5] = 1.0;
|
||||
pad->m_matrix[10] = 1.0;
|
||||
pad->m_matrix[15] = 1.0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -679,7 +690,7 @@ gst_gl_video_mixer_pad_class_init (GstGLVideoMixerPadClass * klass)
|
|||
PROP_INPUT_BLEND_FUNCTION_DST_ALPHA,
|
||||
g_param_spec_enum ("blend-function-dst-alpha",
|
||||
"Blend Function Destination Alpha",
|
||||
"Blend Function for Destiniation Alpha",
|
||||
"Blend Function for Destination Alpha",
|
||||
GST_TYPE_GL_VIDEO_MIXER_BLEND_FUNCTION,
|
||||
DEFAULT_PAD_BLEND_FUNCTION_DST_ALPHA,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
@ -837,18 +848,52 @@ _del_buffer (GstGLContext * context, GLuint * pBuffer)
|
|||
context->gl_vtable->DeleteBuffers (1, pBuffer);
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_gl_video_mixer_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
|
||||
{
|
||||
GstPad *newpad;
|
||||
|
||||
newpad = (GstPad *)
|
||||
GST_ELEMENT_CLASS (parent_class)->request_new_pad (element,
|
||||
templ, req_name, caps);
|
||||
|
||||
if (newpad == NULL)
|
||||
goto could_not_create;
|
||||
|
||||
gst_child_proxy_child_added (GST_CHILD_PROXY (element), G_OBJECT (newpad),
|
||||
GST_OBJECT_NAME (newpad));
|
||||
|
||||
return newpad;
|
||||
|
||||
could_not_create:
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "could not create/add pad");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_video_mixer_release_pad (GstElement * element, GstPad * p)
|
||||
{
|
||||
GstGLVideoMixerPad *pad = GST_GL_VIDEO_MIXER_PAD (p);
|
||||
|
||||
gst_child_proxy_child_removed (GST_CHILD_PROXY (element), G_OBJECT (pad),
|
||||
GST_OBJECT_NAME (pad));
|
||||
|
||||
/* we call the base class first as this will remove the pad from
|
||||
* the aggregator, thus stopping misc callbacks from being called,
|
||||
* one of which (process_textures) will recreate the vertex_buffer
|
||||
* if it is destroyed */
|
||||
GST_ELEMENT_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS (element)))
|
||||
->release_pad (element, p);
|
||||
|
||||
if (pad->vertex_buffer) {
|
||||
GstGLBaseMixer *mix = GST_GL_BASE_MIXER (element);
|
||||
gst_gl_context_thread_add (mix->context, (GstGLContextThreadFunc)
|
||||
_del_buffer, &pad->vertex_buffer);
|
||||
pad->vertex_buffer = 0;
|
||||
}
|
||||
GST_ELEMENT_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS (element)))
|
||||
->release_pad (element, p);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -861,6 +906,7 @@ gst_gl_video_mixer_class_init (GstGLVideoMixerClass * klass)
|
|||
|
||||
gobject_class = (GObjectClass *) klass;
|
||||
element_class = GST_ELEMENT_CLASS (klass);
|
||||
element_class->request_new_pad = gst_gl_video_mixer_request_new_pad;
|
||||
element_class->release_pad = gst_gl_video_mixer_release_pad;
|
||||
|
||||
gobject_class->set_property = gst_gl_video_mixer_set_property;
|
||||
|
@ -1225,10 +1271,10 @@ _draw_checker_background (GstGLVideoMixer * video_mixer)
|
|||
|
||||
/* *INDENT-OFF* */
|
||||
gfloat v_vertices[] = {
|
||||
-1.0,-1.0,-1.0f,
|
||||
1.0,-1.0,-1.0f,
|
||||
1.0, 1.0,-1.0f,
|
||||
-1.0, 1.0,-1.0f,
|
||||
-1.0,-1.0, 0.0f,
|
||||
1.0,-1.0, 0.0f,
|
||||
1.0, 1.0, 0.0f,
|
||||
-1.0, 1.0, 0.0f,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -1466,10 +1512,10 @@ gst_gl_video_mixer_callback (gpointer stuff)
|
|||
|
||||
/* *INDENT-OFF* */
|
||||
gfloat v_vertices[] = {
|
||||
-1.0,-1.0,-1.0f, 0.0f, 0.0f,
|
||||
1.0,-1.0,-1.0f, 1.0f, 0.0f,
|
||||
1.0, 1.0,-1.0f, 1.0f, 1.0f,
|
||||
-1.0, 1.0,-1.0f, 0.0f, 1.0f,
|
||||
-1.0,-1.0, 0.0f, 0.0f, 0.0f,
|
||||
1.0,-1.0, 0.0f, 1.0f, 0.0f,
|
||||
1.0, 1.0, 0.0f, 1.0f, 1.0f,
|
||||
-1.0, 1.0, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -1507,25 +1553,21 @@ gst_gl_video_mixer_callback (gpointer stuff)
|
|||
w = ((gfloat) pad_width / (gfloat) out_width);
|
||||
h = ((gfloat) pad_height / (gfloat) out_height);
|
||||
|
||||
/* top-left */
|
||||
v_vertices[0] = v_vertices[15] =
|
||||
2.0f * (gfloat) pad->xpos / (gfloat) out_width - 1.0f;
|
||||
/* bottom-left */
|
||||
v_vertices[1] = v_vertices[6] =
|
||||
2.0f * (gfloat) pad->ypos / (gfloat) out_height - 1.0f;
|
||||
/* top-right */
|
||||
v_vertices[5] = v_vertices[10] = v_vertices[0] + 2.0f * w;
|
||||
/* bottom-right */
|
||||
v_vertices[11] = v_vertices[16] = v_vertices[1] + 2.0f * h;
|
||||
pad->m_matrix[0] = w;
|
||||
pad->m_matrix[5] = h;
|
||||
pad->m_matrix[12] =
|
||||
2. * (gfloat) pad->xpos / (gfloat) out_width - (1. - w);
|
||||
pad->m_matrix[13] =
|
||||
2. * (gfloat) pad->ypos / (gfloat) out_height - (1. - h);
|
||||
|
||||
GST_TRACE ("processing texture:%u dimensions:%ux%u, at %f,%f %fx%f with "
|
||||
"alpha:%f", in_tex, in_width, in_height, v_vertices[0], v_vertices[1],
|
||||
v_vertices[5], v_vertices[11], pad->alpha);
|
||||
"alpha:%f", in_tex, in_width, in_height, pad->m_matrix[12],
|
||||
pad->m_matrix[13], pad->m_matrix[0], pad->m_matrix[5], pad->alpha);
|
||||
|
||||
if (!pad->vertex_buffer)
|
||||
gl->GenBuffers (1, &pad->vertex_buffer);
|
||||
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, pad->vertex_buffer);
|
||||
|
||||
gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), v_vertices,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
|
@ -1543,10 +1585,13 @@ gst_gl_video_mixer_callback (gpointer stuff)
|
|||
{
|
||||
GstVideoAffineTransformationMeta *af_meta;
|
||||
gfloat matrix[16];
|
||||
gfloat af_matrix[16];
|
||||
GstBuffer *buffer =
|
||||
gst_video_aggregator_pad_get_current_buffer (vagg_pad);
|
||||
|
||||
af_meta =
|
||||
gst_buffer_get_video_affine_transformation_meta (vagg_pad->buffer);
|
||||
gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, matrix);
|
||||
af_meta = gst_buffer_get_video_affine_transformation_meta (buffer);
|
||||
gst_gl_get_affine_transformation_meta_as_ndc_ext (af_meta, af_matrix);
|
||||
gst_gl_multiply_matrix4 (af_matrix, pad->m_matrix, matrix);
|
||||
gst_gl_shader_set_uniform_matrix_4fv (video_mixer->shader,
|
||||
"u_transformation", 1, FALSE, matrix);
|
||||
}
|
||||
|
@ -1584,3 +1629,43 @@ gst_gl_video_mixer_callback (gpointer stuff)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* GstChildProxy implementation */
|
||||
static GObject *
|
||||
gst_gl_video_mixer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
|
||||
guint index)
|
||||
{
|
||||
GstGLVideoMixer *gl_video_mixer = GST_GL_VIDEO_MIXER (child_proxy);
|
||||
GObject *obj = NULL;
|
||||
|
||||
GST_OBJECT_LOCK (gl_video_mixer);
|
||||
obj = g_list_nth_data (GST_ELEMENT_CAST (gl_video_mixer)->sinkpads, index);
|
||||
if (obj)
|
||||
gst_object_ref (obj);
|
||||
GST_OBJECT_UNLOCK (gl_video_mixer);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static guint
|
||||
gst_gl_video_mixer_child_proxy_get_children_count (GstChildProxy * child_proxy)
|
||||
{
|
||||
guint count = 0;
|
||||
GstGLVideoMixer *gl_video_mixer = GST_GL_VIDEO_MIXER (child_proxy);
|
||||
|
||||
GST_OBJECT_LOCK (gl_video_mixer);
|
||||
count = GST_ELEMENT_CAST (gl_video_mixer)->numsinkpads;
|
||||
GST_OBJECT_UNLOCK (gl_video_mixer);
|
||||
GST_INFO_OBJECT (gl_video_mixer, "Children Count: %d", count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_video_mixer_child_proxy_init (gpointer g_iface, gpointer iface_data)
|
||||
{
|
||||
GstChildProxyInterface *iface = g_iface;
|
||||
|
||||
iface->get_child_by_index = gst_gl_video_mixer_child_proxy_get_child_by_index;
|
||||
iface->get_children_count = gst_gl_video_mixer_child_proxy_get_children_count;
|
||||
}
|
||||
|
|
2582
gst-libs/gst/video/gstvideoaggregator.c
Normal file
2582
gst-libs/gst/video/gstvideoaggregator.c
Normal file
File diff suppressed because it is too large
Load diff
248
gst-libs/gst/video/gstvideoaggregator.h
Normal file
248
gst-libs/gst/video/gstvideoaggregator.h
Normal file
|
@ -0,0 +1,248 @@
|
|||
/* Generic video aggregator plugin
|
||||
* Copyright (C) 2008 Wim Taymans <wim@fluendo.com>
|
||||
* Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_VIDEO_AGGREGATOR_H__
|
||||
#define __GST_VIDEO_AGGREGATOR_H__
|
||||
|
||||
#ifndef GST_USE_UNSTABLE_API
|
||||
#warning "The Video library from gst-plugins-bad is unstable API and may change in future."
|
||||
#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/base/gstaggregator.h>
|
||||
#include <gst/video/video-bad-prelude.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstVideoAggregator GstVideoAggregator;
|
||||
typedef struct _GstVideoAggregatorClass GstVideoAggregatorClass;
|
||||
typedef struct _GstVideoAggregatorPrivate GstVideoAggregatorPrivate;
|
||||
|
||||
/*************************
|
||||
* GstVideoAggregatorPad *
|
||||
*************************/
|
||||
|
||||
#define GST_TYPE_VIDEO_AGGREGATOR_PAD (gst_video_aggregator_pad_get_type())
|
||||
#define GST_VIDEO_AGGREGATOR_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_AGGREGATOR_PAD, GstVideoAggregatorPad))
|
||||
#define GST_VIDEO_AGGREGATOR_PAD_CAST(obj) ((GstVideoAggregatorPad *)(obj))
|
||||
#define GST_VIDEO_AGGREGATOR_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_AGGREGATOR_PAD, GstVideoAggregatorPadClass))
|
||||
#define GST_IS_VIDEO_AGGREGATOR_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_AGGREGATOR_PAD))
|
||||
#define GST_IS_VIDEO_AGGREGATOR_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_AGGREGATOR_PAD))
|
||||
#define GST_VIDEO_AGGREGATOR_PAD_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_VIDEO_AGGREGATOR_PAD,GstVideoAggregatorPadClass))
|
||||
|
||||
typedef struct _GstVideoAggregatorPad GstVideoAggregatorPad;
|
||||
typedef struct _GstVideoAggregatorPadClass GstVideoAggregatorPadClass;
|
||||
typedef struct _GstVideoAggregatorPadPrivate GstVideoAggregatorPadPrivate;
|
||||
|
||||
/**
|
||||
* GstVideoAggregatorPad:
|
||||
* @info: The #GstVideoInfo currently set on the pad
|
||||
*/
|
||||
struct _GstVideoAggregatorPad
|
||||
{
|
||||
GstAggregatorPad parent;
|
||||
|
||||
/*< public >*/
|
||||
/* read-only, with OBJECT_LOCK */
|
||||
GstVideoInfo info;
|
||||
|
||||
/* < private > */
|
||||
GstVideoAggregatorPadPrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
/**
|
||||
* GstVideoAggregatorPadClass:
|
||||
*
|
||||
* @update_conversion_info: Called when either the input or output formats
|
||||
* have changed.
|
||||
* @prepare_frame: Prepare the frame from the pad buffer and sets it to prepared_frame
|
||||
* @clean_frame: clean the frame previously prepared in prepare_frame
|
||||
*/
|
||||
struct _GstVideoAggregatorPadClass
|
||||
{
|
||||
GstAggregatorPadClass parent_class;
|
||||
void (*update_conversion_info) (GstVideoAggregatorPad * pad);
|
||||
|
||||
gboolean (*prepare_frame) (GstVideoAggregatorPad * pad,
|
||||
GstVideoAggregator * videoaggregator,
|
||||
GstBuffer * buffer,
|
||||
GstVideoFrame * prepared_frame);
|
||||
|
||||
void (*clean_frame) (GstVideoAggregatorPad * pad,
|
||||
GstVideoAggregator * videoaggregator,
|
||||
GstVideoFrame * prepared_frame);
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
};
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
GType gst_video_aggregator_pad_get_type (void);
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
gboolean gst_video_aggregator_pad_has_current_buffer (GstVideoAggregatorPad *pad);
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
GstBuffer * gst_video_aggregator_pad_get_current_buffer (GstVideoAggregatorPad *pad);
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
GstVideoFrame * gst_video_aggregator_pad_get_prepared_frame (GstVideoAggregatorPad *pad);
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
void gst_video_aggregator_pad_set_needs_alpha (GstVideoAggregatorPad *pad, gboolean needs_alpha);
|
||||
|
||||
/********************************
|
||||
* GstVideoAggregatorConvertPad *
|
||||
*******************************/
|
||||
|
||||
#define GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD (gst_video_aggregator_convert_pad_get_type())
|
||||
#define GST_VIDEO_AGGREGATOR_CONVERT_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD, GstVideoAggregatorConvertPad))
|
||||
#define GST_VIDEO_AGGREGATOR_CONVERT_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD, GstVideoAggregatorConvertPadClass))
|
||||
#define GST_VIDEO_AGGREGATOR_CONVERT_PAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD, GstVideoAggregatorConvertPadClass))
|
||||
#define GST_IS_VIDEO_AGGREGATOR_CONVERT_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD))
|
||||
#define GST_IS_VIDEO_AGGREGATOR_CONVERT_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_AGGREGATOR_CONVERT_PAD))
|
||||
|
||||
typedef struct _GstVideoAggregatorConvertPad GstVideoAggregatorConvertPad;
|
||||
typedef struct _GstVideoAggregatorConvertPadClass GstVideoAggregatorConvertPadClass;
|
||||
typedef struct _GstVideoAggregatorConvertPadPrivate GstVideoAggregatorConvertPadPrivate;
|
||||
|
||||
/**
|
||||
* GstVideoAggregatorConvertPad:
|
||||
*
|
||||
* An implementation of GstPad that can be used with #GstVideoAggregator.
|
||||
*
|
||||
* See #GstVideoAggregator for more details.
|
||||
*/
|
||||
struct _GstVideoAggregatorConvertPad
|
||||
{
|
||||
/*< private >*/
|
||||
GstVideoAggregatorPad parent;
|
||||
|
||||
GstVideoAggregatorConvertPadPrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
/**
|
||||
* GstVideoAggregatorConvertPadClass:
|
||||
*
|
||||
*/
|
||||
struct _GstVideoAggregatorConvertPadClass
|
||||
{
|
||||
GstVideoAggregatorPadClass parent_class;
|
||||
|
||||
void (*create_conversion_info) (GstVideoAggregatorConvertPad *pad, GstVideoAggregator *agg, GstVideoInfo *conversion_info);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
GType gst_video_aggregator_convert_pad_get_type (void);
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
void gst_video_aggregator_convert_pad_update_conversion_info (GstVideoAggregatorConvertPad * pad);
|
||||
|
||||
/**********************
|
||||
* GstVideoAggregator *
|
||||
*********************/
|
||||
|
||||
#define GST_TYPE_VIDEO_AGGREGATOR (gst_video_aggregator_get_type())
|
||||
#define GST_VIDEO_AGGREGATOR(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_AGGREGATOR, GstVideoAggregator))
|
||||
#define GST_VIDEO_AGGREGATOR_CAST(obj) ((GstVideoAggregator *)(obj))
|
||||
#define GST_VIDEO_AGGREGATOR_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_AGGREGATOR, GstVideoAggregatorClass))
|
||||
#define GST_IS_VIDEO_AGGREGATOR(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_AGGREGATOR))
|
||||
#define GST_IS_VIDEO_AGGREGATOR_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_AGGREGATOR))
|
||||
#define GST_VIDEO_AGGREGATOR_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_VIDEO_AGGREGATOR,GstVideoAggregatorClass))
|
||||
|
||||
/**
|
||||
* GstVideoAggregator:
|
||||
* @info: The #GstVideoInfo representing the currently set
|
||||
* srcpad caps.
|
||||
*/
|
||||
struct _GstVideoAggregator
|
||||
{
|
||||
GstAggregator aggregator;
|
||||
|
||||
/*< public >*/
|
||||
/* Output caps */
|
||||
GstVideoInfo info;
|
||||
|
||||
/* < private > */
|
||||
GstVideoAggregatorPrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
};
|
||||
|
||||
/**
|
||||
* GstVideoAggregatorClass:
|
||||
* @update_caps: Optional.
|
||||
* Lets subclasses update the #GstCaps representing
|
||||
* the src pad caps before usage. Return %NULL to indicate failure.
|
||||
* @aggregate_frames: Lets subclasses aggregate frames that are ready. Subclasses
|
||||
* should iterate the GstElement.sinkpads and use the already
|
||||
* mapped #GstVideoFrame from gst_video_aggregator_pad_get_prepared_frame()
|
||||
* or directly use the #GstBuffer from gst_video_aggregator_pad_get_current_buffer()
|
||||
* if it needs to map the buffer in a special way. The result of the
|
||||
* aggregation should land in @outbuffer.
|
||||
* @create_output_buffer: Optional.
|
||||
* Lets subclasses provide a #GstBuffer to be used as @outbuffer of
|
||||
* the #aggregate_frames vmethod.
|
||||
* @find_best_format: Optional.
|
||||
* Lets subclasses decide of the best common format to use.
|
||||
**/
|
||||
struct _GstVideoAggregatorClass
|
||||
{
|
||||
/*< private >*/
|
||||
GstAggregatorClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
GstCaps * (*update_caps) (GstVideoAggregator * videoaggregator,
|
||||
GstCaps * caps);
|
||||
GstFlowReturn (*aggregate_frames) (GstVideoAggregator * videoaggregator,
|
||||
GstBuffer * outbuffer);
|
||||
GstFlowReturn (*create_output_buffer) (GstVideoAggregator * videoaggregator,
|
||||
GstBuffer ** outbuffer);
|
||||
void (*find_best_format) (GstVideoAggregator * vagg,
|
||||
GstCaps * downstream_caps,
|
||||
GstVideoInfo * best_info,
|
||||
gboolean * at_least_one_alpha);
|
||||
|
||||
/* < private > */
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
};
|
||||
|
||||
GST_VIDEO_BAD_API
|
||||
GType gst_video_aggregator_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_VIDEO_AGGREGATOR_H__ */
|
1
gst/compositor/.gitignore
vendored
Normal file
1
gst/compositor/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
compositororc.h
|
28
gst/compositor/Makefile.am
Normal file
28
gst/compositor/Makefile.am
Normal file
|
@ -0,0 +1,28 @@
|
|||
plugin_LTLIBRARIES = libgstcompositor.la
|
||||
|
||||
ORC_SOURCE=compositororc
|
||||
|
||||
include $(top_srcdir)/common/orc.mak
|
||||
|
||||
libgstcompositor_la_SOURCES = \
|
||||
blend.c \
|
||||
compositor.c
|
||||
|
||||
|
||||
nodist_libgstcompositor_la_SOURCES = $(ORC_NODIST_SOURCES)
|
||||
libgstcompositor_la_CFLAGS = \
|
||||
-I$(top_srcdir)/gst-libs \
|
||||
-I$(top_builddir)/gst-libs \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS)
|
||||
libgstcompositor_la_LIBADD = \
|
||||
$(top_builddir)/gst-libs/gst/video/libgstbadvideo-$(GST_API_VERSION).la \
|
||||
$(GST_PLUGINS_BASE_LIBS) \
|
||||
-lgstvideo-@GST_API_VERSION@ \
|
||||
$(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM)
|
||||
libgstcompositor_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
# headers we need but don't want installed
|
||||
noinst_HEADERS = \
|
||||
blend.h \
|
||||
compositor.h
|
1116
gst/compositor/blend.c
Normal file
1116
gst/compositor/blend.c
Normal file
File diff suppressed because it is too large
Load diff
120
gst/compositor/blend.h
Normal file
120
gst/compositor/blend.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __BLEND_H__
|
||||
#define __BLEND_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
/**
|
||||
* GstCompositorBlendMode:
|
||||
* @COMPOSITOR_BLEND_MODE_SOURCE: Copy source
|
||||
* @COMPOSITOR_BLEND_MODE_OVER: Normal blending
|
||||
* @COMPOSITOR_BLEND_MODE_ADD: Alphas are simply added,
|
||||
*
|
||||
* The different modes compositor can use for blending.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
COMPOSITOR_BLEND_MODE_SOURCE,
|
||||
COMPOSITOR_BLEND_MODE_OVER,
|
||||
COMPOSITOR_BLEND_MODE_ADD,
|
||||
} GstCompositorBlendMode;
|
||||
|
||||
typedef void (*BlendFunction) (GstVideoFrame *srcframe, gint xpos, gint ypos, gdouble src_alpha, GstVideoFrame * destframe,
|
||||
GstCompositorBlendMode mode);
|
||||
typedef void (*FillCheckerFunction) (GstVideoFrame * frame);
|
||||
typedef void (*FillColorFunction) (GstVideoFrame * frame, gint c1, gint c2, gint c3);
|
||||
|
||||
extern BlendFunction gst_compositor_blend_argb;
|
||||
extern BlendFunction gst_compositor_blend_bgra;
|
||||
#define gst_compositor_blend_ayuv gst_compositor_blend_argb
|
||||
#define gst_compositor_blend_abgr gst_compositor_blend_argb
|
||||
#define gst_compositor_blend_rgba gst_compositor_blend_bgra
|
||||
|
||||
extern BlendFunction gst_compositor_overlay_argb;
|
||||
extern BlendFunction gst_compositor_overlay_bgra;
|
||||
#define gst_compositor_overlay_ayuv gst_compositor_overlay_argb
|
||||
#define gst_compositor_overlay_abgr gst_compositor_overlay_argb
|
||||
#define gst_compositor_overlay_rgba gst_compositor_overlay_bgra
|
||||
extern BlendFunction gst_compositor_blend_i420;
|
||||
#define gst_compositor_blend_yv12 gst_compositor_blend_i420
|
||||
extern BlendFunction gst_compositor_blend_nv12;
|
||||
extern BlendFunction gst_compositor_blend_nv21;
|
||||
extern BlendFunction gst_compositor_blend_y41b;
|
||||
extern BlendFunction gst_compositor_blend_y42b;
|
||||
extern BlendFunction gst_compositor_blend_y444;
|
||||
extern BlendFunction gst_compositor_blend_rgb;
|
||||
#define gst_compositor_blend_bgr gst_compositor_blend_rgb
|
||||
extern BlendFunction gst_compositor_blend_rgbx;
|
||||
#define gst_compositor_blend_bgrx gst_compositor_blend_rgbx
|
||||
#define gst_compositor_blend_xrgb gst_compositor_blend_rgbx
|
||||
#define gst_compositor_blend_xbgr gst_compositor_blend_rgbx
|
||||
extern BlendFunction gst_compositor_blend_yuy2;
|
||||
#define gst_compositor_blend_uyvy gst_compositor_blend_yuy2;
|
||||
#define gst_compositor_blend_yvyu gst_compositor_blend_yuy2;
|
||||
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_argb;
|
||||
#define gst_compositor_fill_checker_abgr gst_compositor_fill_checker_argb
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_bgra;
|
||||
#define gst_compositor_fill_checker_rgba gst_compositor_fill_checker_bgra
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_ayuv;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_i420;
|
||||
#define gst_compositor_fill_checker_yv12 gst_compositor_fill_checker_i420
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_nv12;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_nv21;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_y41b;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_y42b;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_y444;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_rgb;
|
||||
#define gst_compositor_fill_checker_bgr gst_compositor_fill_checker_rgb
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_rgbx;
|
||||
#define gst_compositor_fill_checker_bgrx gst_compositor_fill_checker_rgbx
|
||||
#define gst_compositor_fill_checker_xrgb gst_compositor_fill_checker_rgbx
|
||||
#define gst_compositor_fill_checker_xbgr gst_compositor_fill_checker_rgbx
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_yuy2;
|
||||
#define gst_compositor_fill_checker_yvyu gst_compositor_fill_checker_yuy2;
|
||||
extern FillCheckerFunction gst_compositor_fill_checker_uyvy;
|
||||
|
||||
extern FillColorFunction gst_compositor_fill_color_argb;
|
||||
extern FillColorFunction gst_compositor_fill_color_abgr;
|
||||
extern FillColorFunction gst_compositor_fill_color_bgra;
|
||||
extern FillColorFunction gst_compositor_fill_color_rgba;
|
||||
extern FillColorFunction gst_compositor_fill_color_ayuv;
|
||||
extern FillColorFunction gst_compositor_fill_color_i420;
|
||||
extern FillColorFunction gst_compositor_fill_color_yv12;
|
||||
extern FillColorFunction gst_compositor_fill_color_nv12;
|
||||
#define gst_compositor_fill_color_nv21 gst_compositor_fill_color_nv12;
|
||||
extern FillColorFunction gst_compositor_fill_color_y41b;
|
||||
extern FillColorFunction gst_compositor_fill_color_y42b;
|
||||
extern FillColorFunction gst_compositor_fill_color_y444;
|
||||
extern FillColorFunction gst_compositor_fill_color_rgb;
|
||||
extern FillColorFunction gst_compositor_fill_color_bgr;
|
||||
extern FillColorFunction gst_compositor_fill_color_xrgb;
|
||||
extern FillColorFunction gst_compositor_fill_color_xbgr;
|
||||
extern FillColorFunction gst_compositor_fill_color_rgbx;
|
||||
extern FillColorFunction gst_compositor_fill_color_bgrx;
|
||||
extern FillColorFunction gst_compositor_fill_color_yuy2;
|
||||
extern FillColorFunction gst_compositor_fill_color_yvyu;
|
||||
extern FillColorFunction gst_compositor_fill_color_uyvy;
|
||||
|
||||
void gst_compositor_init_blend (void);
|
||||
|
||||
#endif /* __BLEND_H__ */
|
96
gst/compositor/blendorc.h
Normal file
96
gst/compositor/blendorc.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
|
||||
/* autogenerated from blendorc.orc */
|
||||
|
||||
#ifndef _BLENDORC_H_
|
||||
#define _BLENDORC_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef _ORC_INTEGER_TYPEDEFS_
|
||||
#define _ORC_INTEGER_TYPEDEFS_
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#include <stdint.h>
|
||||
typedef int8_t orc_int8;
|
||||
typedef int16_t orc_int16;
|
||||
typedef int32_t orc_int32;
|
||||
typedef int64_t orc_int64;
|
||||
typedef uint8_t orc_uint8;
|
||||
typedef uint16_t orc_uint16;
|
||||
typedef uint32_t orc_uint32;
|
||||
typedef uint64_t orc_uint64;
|
||||
#define ORC_UINT64_C(x) UINT64_C(x)
|
||||
#elif defined(_MSC_VER)
|
||||
typedef signed __int8 orc_int8;
|
||||
typedef signed __int16 orc_int16;
|
||||
typedef signed __int32 orc_int32;
|
||||
typedef signed __int64 orc_int64;
|
||||
typedef unsigned __int8 orc_uint8;
|
||||
typedef unsigned __int16 orc_uint16;
|
||||
typedef unsigned __int32 orc_uint32;
|
||||
typedef unsigned __int64 orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##Ui64)
|
||||
#define inline __inline
|
||||
#else
|
||||
#include <limits.h>
|
||||
typedef signed char orc_int8;
|
||||
typedef short orc_int16;
|
||||
typedef int orc_int32;
|
||||
typedef unsigned char orc_uint8;
|
||||
typedef unsigned short orc_uint16;
|
||||
typedef unsigned int orc_uint32;
|
||||
#if INT_MAX == LONG_MAX
|
||||
typedef long long orc_int64;
|
||||
typedef unsigned long long orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##ULL)
|
||||
#else
|
||||
typedef long orc_int64;
|
||||
typedef unsigned long orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##UL)
|
||||
#endif
|
||||
#endif
|
||||
typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
|
||||
typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
|
||||
typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
|
||||
#endif
|
||||
#ifndef ORC_RESTRICT
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#define ORC_RESTRICT restrict
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define ORC_RESTRICT __restrict__
|
||||
#else
|
||||
#define ORC_RESTRICT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ORC_INTERNAL
|
||||
#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
||||
#define ORC_INTERNAL __attribute__((visibility("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define ORC_INTERNAL __hidden
|
||||
#elif defined (__GNUC__)
|
||||
#define ORC_INTERNAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define ORC_INTERNAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
|
||||
void compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n);
|
||||
void compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1104
gst/compositor/compositor.c
Normal file
1104
gst/compositor/compositor.c
Normal file
File diff suppressed because it is too large
Load diff
143
gst/compositor/compositor.h
Normal file
143
gst/compositor/compositor.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/* Generic video compositor plugin
|
||||
* Copyright (C) 2008 Wim Taymans <wim@fluendo.com>
|
||||
* Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_COMPOSITOR_H__
|
||||
#define __GST_COMPOSITOR_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideoaggregator.h>
|
||||
|
||||
#include "blend.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_COMPOSITOR (gst_compositor_get_type())
|
||||
#define GST_COMPOSITOR(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COMPOSITOR, GstCompositor))
|
||||
#define GST_COMPOSITOR_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COMPOSITOR, GstCompositorClass))
|
||||
#define GST_IS_COMPOSITOR(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COMPOSITOR))
|
||||
#define GST_IS_COMPOSITOR_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COMPOSITOR))
|
||||
|
||||
#define GST_TYPE_COMPOSITOR_PAD (gst_compositor_pad_get_type())
|
||||
#define GST_COMPOSITOR_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COMPOSITOR_PAD, GstCompositorPad))
|
||||
#define GST_COMPOSITOR_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COMPOSITOR_PAD, GstCompositorPadClass))
|
||||
#define GST_IS_COMPOSITOR_PAD(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COMPOSITOR_PAD))
|
||||
#define GST_IS_COMPOSITOR_PAD_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COMPOSITOR_PAD))
|
||||
|
||||
typedef struct _GstCompositor GstCompositor;
|
||||
typedef struct _GstCompositorClass GstCompositorClass;
|
||||
|
||||
typedef struct _GstCompositorPad GstCompositorPad;
|
||||
typedef struct _GstCompositorPadClass GstCompositorPadClass;
|
||||
|
||||
/**
|
||||
* GstCompositorBackground:
|
||||
* @COMPOSITOR_BACKGROUND_CHECKER: checker pattern background
|
||||
* @COMPOSITOR_BACKGROUND_BLACK: solid color black background
|
||||
* @COMPOSITOR_BACKGROUND_WHITE: solid color white background
|
||||
* @COMPOSITOR_BACKGROUND_TRANSPARENT: background is left transparent and layers are composited using "A OVER B" composition rules. This is only applicable to AYUV and ARGB (and variants) as it preserves the alpha channel and allows for further mixing.
|
||||
*
|
||||
* The different backgrounds compositor can blend over.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
COMPOSITOR_BACKGROUND_CHECKER,
|
||||
COMPOSITOR_BACKGROUND_BLACK,
|
||||
COMPOSITOR_BACKGROUND_WHITE,
|
||||
COMPOSITOR_BACKGROUND_TRANSPARENT,
|
||||
} GstCompositorBackground;
|
||||
|
||||
/**
|
||||
* GstCompositorOperator:
|
||||
* @COMPOSITOR_OPERATOR_SOURCE: Copy the source over the destination,
|
||||
* without the destination pixels.
|
||||
* @COMPOSITOR_OPERATOR_OVER: Blend the source over the destination.
|
||||
* @COMPOSITOR_OPERATOR_ADD: Similar to over but add the source and
|
||||
* destination alpha. Requires output with alpha
|
||||
* channel.
|
||||
*
|
||||
* The different blending operators that can be used by compositor.
|
||||
*
|
||||
* See https://www.cairographics.org/operators/ for some explanation and
|
||||
* visualizations.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
COMPOSITOR_OPERATOR_SOURCE,
|
||||
COMPOSITOR_OPERATOR_OVER,
|
||||
COMPOSITOR_OPERATOR_ADD,
|
||||
} GstCompositorOperator;
|
||||
|
||||
/**
|
||||
* GstCompositor:
|
||||
*
|
||||
* The opaque #GstCompositor structure.
|
||||
*/
|
||||
struct _GstCompositor
|
||||
{
|
||||
GstVideoAggregator videoaggregator;
|
||||
GstCompositorBackground background;
|
||||
|
||||
BlendFunction blend, overlay;
|
||||
FillCheckerFunction fill_checker;
|
||||
FillColorFunction fill_color;
|
||||
};
|
||||
|
||||
struct _GstCompositorClass
|
||||
{
|
||||
GstVideoAggregatorClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstCompositorPad:
|
||||
*
|
||||
* The opaque #GstCompositorPad structure.
|
||||
*/
|
||||
struct _GstCompositorPad
|
||||
{
|
||||
GstVideoAggregatorConvertPad parent;
|
||||
|
||||
/* properties */
|
||||
gint xpos, ypos;
|
||||
gint width, height;
|
||||
gdouble alpha;
|
||||
|
||||
GstCompositorOperator op;
|
||||
};
|
||||
|
||||
struct _GstCompositorPadClass
|
||||
{
|
||||
GstVideoAggregatorConvertPadClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_compositor_get_type (void);
|
||||
GType gst_compositor_pad_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_COMPOSITOR_H__ */
|
4401
gst/compositor/compositororc-dist.c
Normal file
4401
gst/compositor/compositororc-dist.c
Normal file
File diff suppressed because it is too large
Load diff
100
gst/compositor/compositororc-dist.h
Normal file
100
gst/compositor/compositororc-dist.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
|
||||
/* autogenerated from compositororc.orc */
|
||||
|
||||
#ifndef _COMPOSITORORC_H_
|
||||
#define _COMPOSITORORC_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef _ORC_INTEGER_TYPEDEFS_
|
||||
#define _ORC_INTEGER_TYPEDEFS_
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#include <stdint.h>
|
||||
typedef int8_t orc_int8;
|
||||
typedef int16_t orc_int16;
|
||||
typedef int32_t orc_int32;
|
||||
typedef int64_t orc_int64;
|
||||
typedef uint8_t orc_uint8;
|
||||
typedef uint16_t orc_uint16;
|
||||
typedef uint32_t orc_uint32;
|
||||
typedef uint64_t orc_uint64;
|
||||
#define ORC_UINT64_C(x) UINT64_C(x)
|
||||
#elif defined(_MSC_VER)
|
||||
typedef signed __int8 orc_int8;
|
||||
typedef signed __int16 orc_int16;
|
||||
typedef signed __int32 orc_int32;
|
||||
typedef signed __int64 orc_int64;
|
||||
typedef unsigned __int8 orc_uint8;
|
||||
typedef unsigned __int16 orc_uint16;
|
||||
typedef unsigned __int32 orc_uint32;
|
||||
typedef unsigned __int64 orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##Ui64)
|
||||
#define inline __inline
|
||||
#else
|
||||
#include <limits.h>
|
||||
typedef signed char orc_int8;
|
||||
typedef short orc_int16;
|
||||
typedef int orc_int32;
|
||||
typedef unsigned char orc_uint8;
|
||||
typedef unsigned short orc_uint16;
|
||||
typedef unsigned int orc_uint32;
|
||||
#if INT_MAX == LONG_MAX
|
||||
typedef long long orc_int64;
|
||||
typedef unsigned long long orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##ULL)
|
||||
#else
|
||||
typedef long orc_int64;
|
||||
typedef unsigned long orc_uint64;
|
||||
#define ORC_UINT64_C(x) (x##UL)
|
||||
#endif
|
||||
#endif
|
||||
typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
|
||||
typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
|
||||
typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
|
||||
#endif
|
||||
#ifndef ORC_RESTRICT
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#define ORC_RESTRICT restrict
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define ORC_RESTRICT __restrict__
|
||||
#else
|
||||
#define ORC_RESTRICT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ORC_INTERNAL
|
||||
#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
|
||||
#define ORC_INTERNAL __attribute__((visibility("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define ORC_INTERNAL __hidden
|
||||
#elif defined (__GNUC__)
|
||||
#define ORC_INTERNAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define ORC_INTERNAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
|
||||
void compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n);
|
||||
void compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_source_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_source_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_argb_addition (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
void compositor_orc_overlay_bgra_addition (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
425
gst/compositor/compositororc.orc
Normal file
425
gst/compositor/compositororc.orc
Normal file
|
@ -0,0 +1,425 @@
|
|||
.function compositor_orc_splat_u32
|
||||
.dest 4 d1 guint32
|
||||
.param 4 p1 guint32
|
||||
|
||||
copyl d1, p1
|
||||
|
||||
.function compositor_orc_memcpy_u32
|
||||
.dest 4 d1 guint32
|
||||
.source 4 s1 guint32
|
||||
|
||||
copyl d1, s1
|
||||
|
||||
.function compositor_orc_blend_u8
|
||||
.flags 2d
|
||||
.dest 1 d1 guint8
|
||||
.source 1 s1 guint8
|
||||
.param 2 p1
|
||||
.temp 2 t1
|
||||
.temp 2 t2
|
||||
.const 1 c1 8
|
||||
|
||||
convubw t1, d1
|
||||
convubw t2, s1
|
||||
subw t2, t2, t1
|
||||
mullw t2, t2, p1
|
||||
shlw t1, t1, c1
|
||||
addw t2, t1, t2
|
||||
shruw t2, t2, c1
|
||||
convsuswb d1, t2
|
||||
|
||||
|
||||
.function compositor_orc_blend_argb
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.temp 8 a_wide
|
||||
.const 4 a_alpha 0x000000ff
|
||||
|
||||
loadl t, s
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw a_wide, a
|
||||
x4 mullw a_wide, a_wide, alpha
|
||||
x4 div255w a_wide, a_wide
|
||||
x4 convubw s_wide, t
|
||||
loadl t, d
|
||||
x4 convubw d_wide, t
|
||||
x4 subw s_wide, s_wide, d_wide
|
||||
x4 mullw s_wide, s_wide, a_wide
|
||||
|
||||
x4 div255w s_wide, s_wide
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
x4 convwb t, d_wide
|
||||
orl t, t, a_alpha
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_source_argb
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 4 t2
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 4 a
|
||||
.temp 8 a_wide
|
||||
.const 4 a_alpha 0x000000ff
|
||||
.const 4 a_not_alpha 0xffffff00
|
||||
|
||||
loadl t, s
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw a_wide, a
|
||||
x4 mullw a_wide, a_wide, alpha
|
||||
x4 div255w a_wide, a_wide
|
||||
|
||||
andl t, t, a_not_alpha
|
||||
x4 convwb t2, a_wide
|
||||
andl t2, t2, a_alpha
|
||||
orl t, t, t2
|
||||
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_blend_bgra
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 4 t2
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.temp 8 a_wide
|
||||
.const 4 a_alpha 0xff000000
|
||||
|
||||
loadl t, s
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw a_wide, a
|
||||
x4 mullw a_wide, a_wide, alpha
|
||||
x4 div255w a_wide, a_wide
|
||||
|
||||
x4 convubw s_wide, t
|
||||
loadl t, d
|
||||
x4 convubw d_wide, t
|
||||
x4 subw s_wide, s_wide, d_wide
|
||||
x4 mullw s_wide, s_wide, a_wide
|
||||
x4 div255w s_wide, s_wide
|
||||
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
x4 convwb t, d_wide
|
||||
orl t, t, a_alpha
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_source_bgra
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 4 t2
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 4 a
|
||||
.temp 8 a_wide
|
||||
.const 4 a_alpha 0xff000000
|
||||
.const 4 a_not_alpha 0x00ffffff
|
||||
|
||||
loadl t, s
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw a_wide, a
|
||||
x4 mullw a_wide, a_wide, alpha
|
||||
x4 div255w a_wide, a_wide
|
||||
|
||||
andl t, t, a_not_alpha
|
||||
x4 convwb t2, a_wide
|
||||
andl t2, t2, a_alpha
|
||||
orl t, t, t2
|
||||
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_overlay_argb
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 8 alpha_s
|
||||
.temp 8 alpha_s_inv
|
||||
.temp 8 alpha_d
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.const 4 xfs 0xffffffff
|
||||
.const 4 a_alpha 0x000000ff
|
||||
.const 4 a_alpha_inv 0xffffff00
|
||||
|
||||
# calc source alpha as alpha_s = alpha_s * alpha / 255
|
||||
loadl t, s
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_s, a
|
||||
x4 mullw alpha_s, alpha_s, alpha
|
||||
x4 div255w alpha_s, alpha_s
|
||||
x4 convubw s_wide, t
|
||||
x4 mullw s_wide, s_wide, alpha_s
|
||||
|
||||
# calc destination alpha as alpha_d = (255-alpha_s) * alpha_d / 255
|
||||
loadpl a, xfs
|
||||
x4 convubw alpha_s_inv, a
|
||||
x4 subw alpha_s_inv, alpha_s_inv, alpha_s
|
||||
loadl t, d
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_d, a
|
||||
x4 mullw alpha_d, alpha_d, alpha_s_inv
|
||||
x4 div255w alpha_d, alpha_d
|
||||
x4 convubw d_wide, t
|
||||
x4 mullw d_wide, d_wide, alpha_d
|
||||
|
||||
# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_d*(255-alpha_s)/255
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
|
||||
# calc the final destination alpha_d = alpha_s + alpha_d * (255-alpha_s)/255
|
||||
x4 addw alpha_d, alpha_d, alpha_s
|
||||
|
||||
# now normalize the pix_d by the final alpha to make it associative
|
||||
x4 divluw, d_wide, d_wide, alpha_d
|
||||
|
||||
# pack the new alpha into the correct spot
|
||||
x4 convwb t, d_wide
|
||||
andl t, t, a_alpha_inv
|
||||
x4 convwb a, alpha_d
|
||||
andl a, a, a_alpha
|
||||
orl t, t, a
|
||||
storel d, t
|
||||
|
||||
|
||||
.function compositor_orc_overlay_argb_addition
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 8 alpha_s
|
||||
.temp 8 alpha_s_inv
|
||||
.temp 8 alpha_factor
|
||||
.temp 8 alpha_d
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.const 4 xfs 0xffffffff
|
||||
.const 4 a_alpha 0x000000ff
|
||||
.const 4 a_alpha_inv 0xffffff00
|
||||
|
||||
# calc source alpha as alpha_s = alpha_s * alpha / 255
|
||||
loadl t, s
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_s, a
|
||||
x4 mullw alpha_s, alpha_s, alpha
|
||||
x4 div255w alpha_s, alpha_s
|
||||
x4 convubw s_wide, t
|
||||
x4 mullw s_wide, s_wide, alpha_s
|
||||
|
||||
# calc destination alpha as alpha_factor = (255-alpha_s) * alpha_factor / factor
|
||||
loadpl a, xfs
|
||||
x4 convubw alpha_s_inv, a
|
||||
x4 subw alpha_s_inv, alpha_s_inv, alpha_s
|
||||
loadl t, d
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_factor, a
|
||||
x4 mullw alpha_factor, alpha_factor, alpha_s_inv
|
||||
x4 div255w alpha_factor, alpha_factor
|
||||
x4 convubw d_wide, t
|
||||
x4 mullw d_wide, d_wide, alpha_factor
|
||||
|
||||
# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_factor*(255-alpha_s)/255
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
|
||||
# calc the alpha factor alpha_factor = alpha_s + alpha_factor * (255-alpha_s)/255
|
||||
x4 addw alpha_factor, alpha_factor, alpha_s
|
||||
|
||||
# now normalize the pix_d by the final alpha to make it associative
|
||||
x4 divluw, d_wide, d_wide, alpha_factor
|
||||
|
||||
# calc the final global alpha_d = alpha_d + (alpha_s * (alpha / 255))
|
||||
loadl t, d
|
||||
convlw tw, t
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_d, a
|
||||
x4 addw alpha_d, alpha_d, alpha_s
|
||||
|
||||
# pack the new alpha into the correct spot
|
||||
x4 convwb t, d_wide
|
||||
andl t, t, a_alpha_inv
|
||||
x4 convwb a, alpha_d
|
||||
andl a, a, a_alpha
|
||||
orl t, t, a
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_overlay_bgra
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 4 t2
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 8 alpha_s
|
||||
.temp 8 alpha_s_inv
|
||||
.temp 8 alpha_d
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.const 4 xfs 0xffffffff
|
||||
.const 4 a_alpha 0xff000000
|
||||
.const 4 a_alpha_inv 0x00ffffff
|
||||
|
||||
# calc source alpha as alpha_s = alpha_s * alpha / 255
|
||||
loadl t, s
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_s, a
|
||||
x4 mullw alpha_s, alpha_s, alpha
|
||||
x4 div255w alpha_s, alpha_s
|
||||
x4 convubw s_wide, t
|
||||
x4 mullw s_wide, s_wide, alpha_s
|
||||
|
||||
# calc destination alpha as alpha_d = (255-alpha_s) * alpha_d / 255
|
||||
loadpl a, xfs
|
||||
x4 convubw alpha_s_inv, a
|
||||
x4 subw alpha_s_inv, alpha_s_inv, alpha_s
|
||||
loadl t, d
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_d, a
|
||||
x4 mullw alpha_d, alpha_d, alpha_s_inv
|
||||
x4 div255w alpha_d, alpha_d
|
||||
x4 convubw d_wide, t
|
||||
x4 mullw d_wide, d_wide, alpha_d
|
||||
|
||||
# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_d*(255-alpha_s)/255
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
|
||||
# calc the final destination alpha_d = alpha_s + alpha_d * (255-alpha_s)/255
|
||||
x4 addw alpha_d, alpha_d, alpha_s
|
||||
|
||||
# now normalize the pix_d by the final alpha to make it associative
|
||||
x4 divluw, d_wide, d_wide, alpha_d
|
||||
|
||||
# pack the new alpha into the correct spot
|
||||
x4 convwb t, d_wide
|
||||
andl t, t, a_alpha_inv
|
||||
x4 convwb a, alpha_d
|
||||
andl a, a, a_alpha
|
||||
orl t, t, a
|
||||
storel d, t
|
||||
|
||||
.function compositor_orc_overlay_bgra_addition
|
||||
.flags 2d
|
||||
.dest 4 d guint8
|
||||
.source 4 s guint8
|
||||
.param 2 alpha
|
||||
.temp 4 t
|
||||
.temp 4 t2
|
||||
.temp 2 tw
|
||||
.temp 1 tb
|
||||
.temp 8 alpha_s
|
||||
.temp 8 alpha_s_inv
|
||||
.temp 8 alpha_factor
|
||||
.temp 8 alpha_d
|
||||
.temp 4 a
|
||||
.temp 8 d_wide
|
||||
.temp 8 s_wide
|
||||
.const 4 xfs 0xffffffff
|
||||
.const 4 a_alpha 0xff000000
|
||||
.const 4 a_alpha_inv 0x00ffffff
|
||||
|
||||
# calc source alpha as alpha_s = alpha_s * alpha / 255
|
||||
loadl t, s
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_s, a
|
||||
x4 mullw alpha_s, alpha_s, alpha
|
||||
x4 div255w alpha_s, alpha_s
|
||||
x4 convubw s_wide, t
|
||||
x4 mullw s_wide, s_wide, alpha_s
|
||||
|
||||
# calc destination alpha as alpha_factor = (255-alpha_s) * alpha_factor / 255
|
||||
loadpl a, xfs
|
||||
x4 convubw alpha_s_inv, a
|
||||
x4 subw alpha_s_inv, alpha_s_inv, alpha_s
|
||||
loadl t, d
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_factor, a
|
||||
x4 mullw alpha_factor, alpha_factor, alpha_s_inv
|
||||
x4 div255w alpha_factor, alpha_factor
|
||||
x4 convubw d_wide, t
|
||||
x4 mullw d_wide, d_wide, alpha_factor
|
||||
|
||||
# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_factor*(255-alpha_s)/255
|
||||
x4 addw d_wide, d_wide, s_wide
|
||||
|
||||
# calc the final destination alpha_factor = alpha_s + alpha_factor * (255-alpha_s)/255
|
||||
x4 addw alpha_factor, alpha_factor, alpha_s
|
||||
|
||||
# now normalize the pix_d by the final alpha to make it associative
|
||||
x4 divluw, d_wide, d_wide, alpha_factor
|
||||
|
||||
# calc the final global alpha_d = alpha_d + (alpha_s * (alpha / 255))
|
||||
loadl t, d
|
||||
shrul t2, t, 24
|
||||
convlw tw, t2
|
||||
convwb tb, tw
|
||||
splatbl a, tb
|
||||
x4 convubw alpha_d, a
|
||||
x4 addw alpha_d, alpha_d, alpha_s
|
||||
|
||||
# pack the new alpha into the correct spot
|
||||
x4 convwb t, d_wide
|
||||
andl t, t, a_alpha_inv
|
||||
x4 convwb a, alpha_d
|
||||
andl a, a, a_alpha
|
||||
orl t, t, a
|
||||
storel d, t
|
33
gst/compositor/meson.build
Normal file
33
gst/compositor/meson.build
Normal file
|
@ -0,0 +1,33 @@
|
|||
compositor_sources = [
|
||||
'blend.c',
|
||||
'compositor.c',
|
||||
]
|
||||
|
||||
orcsrc = 'compositororc'
|
||||
if have_orcc
|
||||
orc_h = custom_target(orcsrc + '.h',
|
||||
input : orcsrc + '.orc',
|
||||
output : orcsrc + '.h',
|
||||
command : orcc_args + ['--header', '-o', '@OUTPUT@', '@INPUT@'])
|
||||
orc_c = custom_target(orcsrc + '.c',
|
||||
input : orcsrc + '.orc',
|
||||
output : orcsrc + '.c',
|
||||
command : orcc_args + ['--implementation', '-o', '@OUTPUT@', '@INPUT@'])
|
||||
else
|
||||
orc_h = configure_file(input : orcsrc + '-dist.h',
|
||||
output : orcsrc + '.h',
|
||||
copy : true)
|
||||
orc_c = configure_file(input : orcsrc + '-dist.c',
|
||||
output : orcsrc + '.c',
|
||||
copy : true)
|
||||
endif
|
||||
|
||||
gstcompositor = library('gstcompositor',
|
||||
compositor_sources, orc_c, orc_h,
|
||||
c_args : gst_plugins_bad_args + ['-DGST_USE_UNSTABLE_API'],
|
||||
include_directories : [configinc],
|
||||
dependencies : [gstbadvideo_dep, gstvideo_dep, gstbase_dep, orc_dep, libm],
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
pkgconfig.generate(gstcompositor, install_dir : plugins_pkgconfig_install_dir)
|
2115
tests/check/elements/compositor.c
Normal file
2115
tests/check/elements/compositor.c
Normal file
File diff suppressed because it is too large
Load diff
133
tests/examples/compositor/crossfade.c
Normal file
133
tests/examples/compositor/crossfade.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2017 Thibault Saunier <thibault.saunier@osg-samsung.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Simple crossfade example using the compositor element.
|
||||
*
|
||||
* Takes two video files and crossfades them for 10 seconds and returns.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/controller/gstdirectcontrolbinding.h>
|
||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstElement *compositor;
|
||||
guint z_order;
|
||||
} VideoInfo;
|
||||
|
||||
static gchar *
|
||||
ensure_uri (const gchar * location)
|
||||
{
|
||||
if (gst_uri_is_valid (location))
|
||||
return g_strdup (location);
|
||||
else
|
||||
return gst_filename_to_uri (location, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_pad_added_cb (GstElement * decodebin, GstPad * pad, VideoInfo * info)
|
||||
{
|
||||
GstPad *sinkpad =
|
||||
gst_element_get_request_pad (GST_ELEMENT (info->compositor), "sink_%u");
|
||||
GstControlSource *control_source;
|
||||
gboolean is_last = info->z_order == 1;
|
||||
|
||||
control_source = gst_interpolation_control_source_new ();
|
||||
|
||||
gst_util_set_object_arg (G_OBJECT (sinkpad), "operator",
|
||||
info->z_order == 0 ? "source" : "add");
|
||||
gst_object_add_control_binding (GST_OBJECT (sinkpad),
|
||||
gst_direct_control_binding_new_absolute (GST_OBJECT (sinkpad), "alpha",
|
||||
control_source));
|
||||
|
||||
g_object_set (control_source, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
|
||||
|
||||
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
|
||||
(control_source), 0, is_last ? 0.0 : 1.0);
|
||||
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
|
||||
(control_source), 10 * GST_SECOND, is_last ? 1.0 : 0.0);
|
||||
g_object_set (sinkpad, "zorder", info->z_order, NULL);
|
||||
|
||||
gst_pad_link (pad, sinkpad);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
gint i;
|
||||
GstMessage *message;
|
||||
GstElement *compositor, *sink, *pipeline;
|
||||
GstBus *bus;
|
||||
|
||||
if (argc != 3) {
|
||||
g_error ("Need to provide 2 input videos");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
pipeline = gst_element_factory_make ("pipeline", NULL);
|
||||
compositor = gst_element_factory_make ("compositor", NULL);
|
||||
sink =
|
||||
gst_parse_bin_from_description ("videoconvert ! autovideosink", TRUE,
|
||||
NULL);
|
||||
|
||||
gst_util_set_object_arg (G_OBJECT (compositor), "background", "black");
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), compositor, sink, NULL);
|
||||
g_assert (gst_element_link (compositor, sink));
|
||||
|
||||
for (i = 1; i < 3; i++) {
|
||||
gchar *uri = ensure_uri (argv[i]);
|
||||
VideoInfo *info = g_malloc0 (sizeof (VideoInfo));
|
||||
GstElement *uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
|
||||
|
||||
g_object_set (uridecodebin, "uri", uri, "expose-all-streams", FALSE,
|
||||
"caps", gst_caps_from_string ("video/x-raw(ANY)"), NULL);
|
||||
|
||||
info->compositor = compositor;
|
||||
info->z_order = i - 1;
|
||||
g_signal_connect (uridecodebin, "pad-added", (GCallback) _pad_added_cb,
|
||||
info);
|
||||
|
||||
gst_bin_add (GST_BIN (pipeline), uridecodebin);
|
||||
}
|
||||
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
message =
|
||||
gst_bus_timed_pop_filtered (bus, 11 * GST_SECOND,
|
||||
GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
|
||||
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "go");
|
||||
if (message)
|
||||
gst_print ("%" GST_PTR_FORMAT "\n", message);
|
||||
else
|
||||
gst_print ("Timeout\n");
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue