smpte: Add property for inverting the transition mask

This converts a left-to-right transition to right-to-left or
clock-wise to counter-clock-wise.
This commit is contained in:
Sebastian Dröge 2010-04-15 22:28:58 +02:00
parent e17954aa6b
commit 04a1b1dc48
6 changed files with 75 additions and 16 deletions

View file

@ -69,7 +69,8 @@ gst_mask_find_definition (gint type)
} }
GstMask * GstMask *
gst_mask_factory_new (gint type, gint bpp, gint width, gint height) gst_mask_factory_new (gint type, gboolean invert, gint bpp, gint width,
gint height)
{ {
GstMaskDefinition *definition; GstMaskDefinition *definition;
GstMask *mask = NULL; GstMask *mask = NULL;
@ -86,8 +87,20 @@ gst_mask_factory_new (gint type, gint bpp, gint width, gint height)
mask->user_data = definition->user_data; mask->user_data = definition->user_data;
mask->data = g_malloc (width * height * sizeof (guint32)); mask->data = g_malloc (width * height * sizeof (guint32));
if (definition->draw_func)
definition->draw_func (mask); definition->draw_func (mask);
if (invert) {
gint i, j;
guint32 *datap = mask->data;
guint32 max = (1 << bpp);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
*datap = max - *datap;
datap++;
}
}
}
} }
return mask; return mask;

View file

@ -56,7 +56,7 @@ void _gst_mask_register (const GstMaskDefinition
void _gst_mask_default_destroy (GstMask *mask); void _gst_mask_default_destroy (GstMask *mask);
const GList* gst_mask_get_definitions (void); const GList* gst_mask_get_definitions (void);
GstMask* gst_mask_factory_new (gint type, gint bpp, gint width, gint height); GstMask* gst_mask_factory_new (gint type, gboolean invert, gint bpp, gint width, gint height);
void gst_mask_destroy (GstMask *mask); void gst_mask_destroy (GstMask *mask);
void _gst_barboxwipes_register (void); void _gst_barboxwipes_register (void);

View file

@ -87,6 +87,7 @@ enum
#define DEFAULT_PROP_DEPTH 16 #define DEFAULT_PROP_DEPTH 16
#define DEFAULT_PROP_FPS 0. #define DEFAULT_PROP_FPS 0.
#define DEFAULT_PROP_DURATION GST_SECOND #define DEFAULT_PROP_DURATION GST_SECOND
#define DEFAULT_PROP_INVERT FALSE
enum enum
{ {
@ -96,6 +97,7 @@ enum
PROP_DEPTH, PROP_DEPTH,
PROP_FPS, PROP_FPS,
PROP_DURATION, PROP_DURATION,
PROP_INVERT,
PROP_LAST, PROP_LAST,
}; };
@ -242,6 +244,9 @@ gst_smpte_class_init (GstSMPTEClass * klass)
g_param_spec_uint64 ("duration", "Duration", g_param_spec_uint64 ("duration", "Duration",
"Duration of the transition effect in nanoseconds", 0, G_MAXUINT64, "Duration of the transition effect in nanoseconds", 0, G_MAXUINT64,
DEFAULT_PROP_DURATION, G_PARAM_READWRITE)); DEFAULT_PROP_DURATION, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
g_param_spec_boolean ("invert", "Invert",
"Invert transition mask", DEFAULT_PROP_INVERT, G_PARAM_READWRITE));
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_smpte_change_state); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_smpte_change_state);
} }
@ -266,25 +271,27 @@ fill_i420 (guint8 * data, gint width, gint height, gint color)
} }
static gboolean static gboolean
gst_smpte_update_mask (GstSMPTE * smpte, gint type, gint depth, gint width, gst_smpte_update_mask (GstSMPTE * smpte, gint type, gboolean invert,
gint height) gint depth, gint width, gint height)
{ {
GstMask *newmask; GstMask *newmask;
if (smpte->mask) { if (smpte->mask) {
if (smpte->type == type && if (smpte->type == type &&
smpte->invert == invert &&
smpte->depth == depth && smpte->depth == depth &&
smpte->width == width && smpte->height == height) smpte->width == width && smpte->height == height)
return TRUE; return TRUE;
} }
newmask = gst_mask_factory_new (type, depth, width, height); newmask = gst_mask_factory_new (type, invert, depth, width, height);
if (newmask) { if (newmask) {
if (smpte->mask) { if (smpte->mask) {
gst_mask_destroy (smpte->mask); gst_mask_destroy (smpte->mask);
} }
smpte->mask = newmask; smpte->mask = newmask;
smpte->type = type; smpte->type = type;
smpte->invert = invert;
smpte->depth = depth; smpte->depth = depth;
smpte->width = width; smpte->width = width;
smpte->height = height; smpte->height = height;
@ -321,8 +328,9 @@ gst_smpte_setcaps (GstPad * pad, GstCaps * caps)
GST_DEBUG_OBJECT (smpte, "duration: %d frames", smpte->end_position); GST_DEBUG_OBJECT (smpte, "duration: %d frames", smpte->end_position);
ret = gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width, ret =
smpte->height); gst_smpte_update_mask (smpte, smpte->type, smpte->invert, smpte->depth,
smpte->width, smpte->height);
return ret; return ret;
} }
@ -365,6 +373,7 @@ gst_smpte_init (GstSMPTE * smpte)
smpte->border = DEFAULT_PROP_BORDER; smpte->border = DEFAULT_PROP_BORDER;
smpte->depth = DEFAULT_PROP_DEPTH; smpte->depth = DEFAULT_PROP_DEPTH;
smpte->duration = DEFAULT_PROP_DURATION; smpte->duration = DEFAULT_PROP_DURATION;
smpte->invert = DEFAULT_PROP_INVERT;
smpte->fps_num = 0; smpte->fps_num = 0;
smpte->fps_denom = 1; smpte->fps_denom = 1;
} }
@ -558,6 +567,9 @@ gst_smpte_set_property (GObject * object, guint prop_id,
case PROP_DURATION: case PROP_DURATION:
smpte->duration = g_value_get_uint64 (value); smpte->duration = g_value_get_uint64 (value);
break; break;
case PROP_INVERT:
smpte->invert = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -588,6 +600,9 @@ gst_smpte_get_property (GObject * object, guint prop_id,
case PROP_DURATION: case PROP_DURATION:
g_value_set_uint64 (value, smpte->duration); g_value_set_uint64 (value, smpte->duration);
break; break;
case PROP_INVERT:
g_value_set_boolean (value, smpte->invert);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View file

@ -56,6 +56,7 @@ struct _GstSMPTE {
gint border; gint border;
gint depth; gint depth;
guint64 duration; guint64 duration;
gboolean invert;
/* negotiated format */ /* negotiated format */
gint format; gint format;

View file

@ -88,6 +88,7 @@ enum
#define DEFAULT_PROP_BORDER 0 #define DEFAULT_PROP_BORDER 0
#define DEFAULT_PROP_DEPTH 16 #define DEFAULT_PROP_DEPTH 16
#define DEFAULT_PROP_POSITION 0.0 #define DEFAULT_PROP_POSITION 0.0
#define DEFAULT_PROP_INVERT FALSE
enum enum
{ {
@ -96,6 +97,7 @@ enum
PROP_BORDER, PROP_BORDER,
PROP_DEPTH, PROP_DEPTH,
PROP_POSITION, PROP_POSITION,
PROP_INVERT,
PROP_LAST, PROP_LAST,
}; };
@ -231,6 +233,10 @@ gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass)
g_param_spec_double ("position", "Position", g_param_spec_double ("position", "Position",
"Position of the transition effect", 0.0, 1.0, DEFAULT_PROP_POSITION, "Position of the transition effect", 0.0, 1.0, DEFAULT_PROP_POSITION,
GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
g_param_spec_boolean ("invert", "Invert",
"Invert transition mask", DEFAULT_PROP_POSITION,
GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_smpte_alpha_setcaps); trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_smpte_alpha_setcaps);
trans_class->get_unit_size = trans_class->get_unit_size =
@ -239,8 +245,8 @@ gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass)
} }
static gboolean static gboolean
gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth, gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type,
gint width, gint height) gboolean invert, gint depth, gint width, gint height)
{ {
GstMask *newmask; GstMask *newmask;
@ -248,12 +254,14 @@ gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth,
* correct */ * correct */
if (smpte->mask) { if (smpte->mask) {
if (smpte->type == type && if (smpte->type == type &&
smpte->invert == invert &&
smpte->depth == depth && smpte->depth == depth &&
smpte->width == width && smpte->height == height) smpte->width == width && smpte->height == height)
return TRUE; return TRUE;
} }
smpte->type = type; smpte->type = type;
smpte->invert = invert;
smpte->depth = depth; smpte->depth = depth;
smpte->width = width; smpte->width = width;
smpte->height = height; smpte->height = height;
@ -263,7 +271,7 @@ gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth,
return TRUE; return TRUE;
} }
newmask = gst_mask_factory_new (type, depth, width, height); newmask = gst_mask_factory_new (type, invert, depth, width, height);
if (!newmask) if (!newmask)
goto mask_failed; goto mask_failed;
@ -306,8 +314,9 @@ gst_smpte_alpha_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
/* try to update the mask now, this will also adjust the width/height on /* try to update the mask now, this will also adjust the width/height on
* success */ * success */
GST_OBJECT_LOCK (smpte); GST_OBJECT_LOCK (smpte);
ret = gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->depth, ret =
width, height); gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert,
smpte->depth, width, height);
GST_OBJECT_UNLOCK (smpte); GST_OBJECT_UNLOCK (smpte);
if (!ret) if (!ret)
goto mask_failed; goto mask_failed;
@ -383,6 +392,7 @@ gst_smpte_alpha_init (GstSMPTEAlpha * smpte)
smpte->border = DEFAULT_PROP_BORDER; smpte->border = DEFAULT_PROP_BORDER;
smpte->depth = DEFAULT_PROP_DEPTH; smpte->depth = DEFAULT_PROP_DEPTH;
smpte->position = DEFAULT_PROP_POSITION; smpte->position = DEFAULT_PROP_POSITION;
smpte->invert = DEFAULT_PROP_INVERT;
} }
static void static void
@ -574,7 +584,7 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
* have to wait for the transform lock */ * have to wait for the transform lock */
GST_OBJECT_LOCK (smpte); GST_OBJECT_LOCK (smpte);
GST_OBJECT_UNLOCK (smpte); GST_OBJECT_UNLOCK (smpte);
gst_smpte_alpha_update_mask (smpte, type, gst_smpte_alpha_update_mask (smpte, type, smpte->invert,
smpte->depth, smpte->width, smpte->height); smpte->depth, smpte->width, smpte->height);
GST_BASE_TRANSFORM_UNLOCK (smpte); GST_BASE_TRANSFORM_UNLOCK (smpte);
break; break;
@ -594,7 +604,7 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
* have to wait for the transform lock */ * have to wait for the transform lock */
GST_OBJECT_LOCK (smpte); GST_OBJECT_LOCK (smpte);
GST_OBJECT_UNLOCK (smpte); GST_OBJECT_UNLOCK (smpte);
gst_smpte_alpha_update_mask (smpte, smpte->type, gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert,
depth, smpte->width, smpte->height); depth, smpte->width, smpte->height);
GST_BASE_TRANSFORM_UNLOCK (smpte); GST_BASE_TRANSFORM_UNLOCK (smpte);
break; break;
@ -604,6 +614,20 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
smpte->position = g_value_get_double (value); smpte->position = g_value_get_double (value);
GST_OBJECT_UNLOCK (smpte); GST_OBJECT_UNLOCK (smpte);
break; break;
case PROP_INVERT:{
gboolean invert;
invert = g_value_get_boolean (value);
GST_BASE_TRANSFORM_LOCK (smpte);
/* also lock with the object lock so that reading the property doesn't
* have to wait for the transform lock */
GST_OBJECT_LOCK (smpte);
GST_OBJECT_UNLOCK (smpte);
gst_smpte_alpha_update_mask (smpte, smpte->type, invert,
smpte->depth, smpte->width, smpte->height);
GST_BASE_TRANSFORM_UNLOCK (smpte);
break;
}
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -639,6 +663,11 @@ gst_smpte_alpha_get_property (GObject * object, guint prop_id,
g_value_set_double (value, smpte->position); g_value_set_double (value, smpte->position);
GST_OBJECT_UNLOCK (smpte); GST_OBJECT_UNLOCK (smpte);
break; break;
case PROP_INVERT:
GST_OBJECT_LOCK (smpte);
g_value_set_boolean (value, smpte->invert);
GST_OBJECT_UNLOCK (smpte);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View file

@ -52,6 +52,7 @@ struct _GstSMPTEAlpha {
gint border; gint border;
gint depth; gint depth;
gdouble position; gdouble position;
gboolean invert;
/* negotiated format */ /* negotiated format */
GstVideoFormat format; GstVideoFormat format;