summaryrefslogtreecommitdiffstats
path: root/gst/smpte/gstsmpte.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/smpte/gstsmpte.c')
-rw-r--r--gst/smpte/gstsmpte.c168
1 files changed, 116 insertions, 52 deletions
diff --git a/gst/smpte/gstsmpte.c b/gst/smpte/gstsmpte.c
index 536be8d4..47de304f 100644
--- a/gst/smpte/gstsmpte.c
+++ b/gst/smpte/gstsmpte.c
@@ -79,6 +79,9 @@ enum {
enum {
ARG_0,
ARG_TYPE,
+ ARG_BORDER,
+ ARG_DEPTH,
+ ARG_FPS,
};
#define GST_TYPE_SMPTE_TRANSITION_TYPE (gst_smpte_transition_type_get_type())
@@ -106,7 +109,8 @@ gst_smpte_transition_type_get_type (void)
i++;
}
- smpte_transition_type = g_enum_register_static ("GstSMPTETransitionType", smpte_transitions);
+ smpte_transition_type =
+ g_enum_register_static ("GstSMPTETransitionType", smpte_transitions);
}
return smpte_transition_type;
}
@@ -166,7 +170,15 @@ gst_smpte_class_init (GstSMPTEClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TYPE,
g_param_spec_enum ("type", "Type", "The type of transition to use",
GST_TYPE_SMPTE_TRANSITION_TYPE, 1, G_PARAM_READWRITE));
-
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
+ g_param_spec_int ("fps", "FPS", "Frames per second if no input files are given",
+ 1, 255, 1, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BORDER,
+ g_param_spec_int ("border", "Border", "The border width of the transition",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEPTH,
+ g_param_spec_int ("depth", "Depth", "Depth of the mask in bits",
+ 1, 24, 16, G_PARAM_READWRITE));
}
/* wht yel cya grn mag red blu blk -I Q */
@@ -177,13 +189,35 @@ static int v_colors[] = { 128, 155, 0, 21, 235, 255, 107, 128, 128, 255 };
static void
fill_i420 (guint8 *data, gint width, gint height, gint color)
{
+ gint size = width * height, size4 = size >> 2;
guint8 *yp = data;
- guint8 *up = data + width * height;
- guint8 *vp = data + width * height + (width * height) / 4;
+ guint8 *up = data + size;
+ guint8 *vp = data + size + size4;
- gst_smpte_paint_rect (yp, width, 0, 0, width, height, y_colors[color]);
- gst_smpte_paint_rect (up, width/2, 0, 0, width/2, height/2, u_colors[color]);
- gst_smpte_paint_rect (vp, width/2, 0, 0, width/2, height/2, v_colors[color]);
+ memset (yp, y_colors[color], size);
+ memset (up, u_colors[color], size4);
+ memset (vp, v_colors[color], size4);
+}
+
+static gboolean
+gst_smpte_update_mask (GstSMPTE *smpte, gint type, gint depth, gint width, gint height)
+{
+ GstMask *newmask;
+
+ newmask = gst_mask_factory_new (type, depth, width, height);
+ if (newmask) {
+ if (smpte->mask) {
+ gst_mask_destroy (smpte->mask);
+ }
+ smpte->mask = newmask;
+ smpte->type = type;
+ smpte->depth = depth;
+ smpte->width = width;
+ smpte->height = height;
+
+ return TRUE;
+ }
+ return FALSE;
}
static gboolean
@@ -199,7 +233,7 @@ gst_smpte_sinkconnect (GstPad *pad, GstCaps *caps)
gst_caps_get_int (caps, "width", &smpte->width);
gst_caps_get_int (caps, "height", &smpte->height);
- smpte->mask = gst_mask_factory_new (smpte->type, 8, smpte->width, smpte->height);
+ gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width, smpte->height);
/* forward to the next plugin */
return gst_pad_try_set_caps(smpte->srcpad, gst_caps_copy_1(caps));
@@ -229,35 +263,43 @@ gst_smpte_init (GstSMPTE *smpte)
smpte->duration = 64;
smpte->position = 0;
smpte->type = 1;
- smpte->mask = gst_mask_factory_new (smpte->type, 8, smpte->width, smpte->height);
+ smpte->fps = 1;
+ smpte->border = 0;
+ smpte->depth = 16;
+ gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width, smpte->height);
}
static void
gst_smpte_blend_i420 (guint8 *in1, guint8 *in2, guint8 *out, GstMask *mask,
- gint width, gint height)
+ gint width, gint height, gint border, gint pos)
{
- gint i, j;
- guint8 *maskporig, *maskp;
+ guint32 *maskp;
+ gint value;
+ gint i;
+ gint min, max;
guint8 *in1u, *in1v, *in2u, *in2v, *outu, *outv;
- guint8 value;
- gint chromsize = (width * height) >> 2;
+ gint lumsize = width * height;
+ gint chromsize = lumsize >> 2;
+
+ if (border == 0) border++;
- maskp = maskporig = mask->data;
+ min = pos - border;
+ max = pos;
+
+ in1u = in1 + lumsize; in1v = in1 + chromsize;
+ in2u = in2 + lumsize; in2v = in2 + chromsize;
+ outu = out + lumsize; outv = out + chromsize;
- for (i = width * height; i; i--) {
+ maskp = mask->data;
+
+ for (i = lumsize; i; i--) {
value = *maskp++;
- *out++ = ((*in2++ * value) + (*in1++ * (255 - value))) >> 8;
- }
- in1u = in1; in1v = in1 + chromsize;
- in2u = in2; in2v = in2 + chromsize;
- outu = out; outv = out + chromsize;
-
- maskp = maskporig;
- for (i = height/2; i; i--, maskp += width) {
- for (j = width/2; j; j--, maskp += 2) {
- value = *maskp;
- *outu++ = ((*in2u++ * value) + (*in1u++ * (255 - value))) >> 8;
- *outv++ = ((*in2v++ * value) + (*in1v++ * (255 - value))) >> 8;
+ value = ((CLAMP (value, min, max) - min) << 8) / border;
+
+ *out++ = ((*in1++ * value) + (*in2++ * (255 - value))) >> 8;
+ if (i % 4) {
+ *outu++ = ((*in1u++ * value) + (*in2u++ * (255 - value))) >> 8;
+ *outv++ = ((*in1v++ * value) + (*in2v++ * (255 - value))) >> 8;
}
}
}
@@ -272,7 +314,7 @@ gst_smpte_loop (GstElement *element)
smpte = GST_SMPTE (element);
- ts = smpte->position * GST_SECOND;
+ ts = smpte->position * GST_SECOND / smpte->fps;
if (GST_PAD_IS_USABLE (smpte->sinkpad1)) {
in1 = gst_pad_pull (smpte->sinkpad1);
@@ -297,23 +339,26 @@ gst_smpte_loop (GstElement *element)
if (!GST_PAD_CAPS (smpte->srcpad)) {
if (!gst_pad_try_set_caps (smpte->srcpad,
- GST_CAPS_NEW (
- "smpte_srccaps",
- "video/raw",
- "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
- "width", GST_PROPS_INT (smpte->width),
- "height", GST_PROPS_INT (smpte->height)
- )))
+ GST_CAPS_NEW (
+ "smpte_srccaps",
+ "video/raw",
+ "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
+ "width", GST_PROPS_INT (smpte->width),
+ "height", GST_PROPS_INT (smpte->height)
+ )))
{
gst_element_error (element, "cannot set caps");
return;
}
}
- gst_mask_update (smpte->mask, smpte->position, smpte->duration);
-
- gst_smpte_blend_i420 (GST_BUFFER_DATA (in1), GST_BUFFER_DATA (in2), GST_BUFFER_DATA (outbuf),
- smpte->mask, smpte->width, smpte->height);
+ gst_smpte_blend_i420 (GST_BUFFER_DATA (in1),
+ GST_BUFFER_DATA (in2),
+ GST_BUFFER_DATA (outbuf),
+ smpte->mask, smpte->width, smpte->height,
+ smpte->border,
+ ((1 << smpte->depth) + smpte->border) *
+ smpte->position / smpte->duration);
}
else {
outbuf = in2;
@@ -342,17 +387,24 @@ gst_smpte_set_property (GObject *object, guint prop_id,
switch (prop_id) {
case ARG_TYPE:
{
- GstMask *newmask;
gint type = g_value_get_enum (value);
- newmask = gst_mask_factory_new (type, 8, smpte->width, smpte->height);
- if (newmask) {
- if (smpte->mask) {
- gst_mask_destroy (smpte->mask);
- }
- smpte->mask = newmask;
- smpte->type = type;
- }
+ gst_smpte_update_mask (smpte, type, smpte->depth,
+ smpte->width, smpte->height);
+ break;
+ }
+ case ARG_FPS:
+ smpte->fps = g_value_get_int (value);
+ break;
+ case ARG_BORDER:
+ smpte->border = g_value_get_int (value);
+ break;
+ case ARG_DEPTH:
+ {
+ gint depth = g_value_get_int (value);
+
+ gst_smpte_update_mask (smpte, smpte->type, depth,
+ smpte->width, smpte->height);
break;
}
default:
@@ -375,6 +427,15 @@ gst_smpte_get_property (GObject *object, guint prop_id,
g_value_set_enum (value, smpte->mask->type);
}
break;
+ case ARG_FPS:
+ g_value_set_int (value, smpte->fps);
+ break;
+ case ARG_BORDER:
+ g_value_set_int (value, smpte->border);
+ break;
+ case ARG_DEPTH:
+ g_value_set_int (value, smpte->depth);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -391,9 +452,12 @@ plugin_init (GModule *module, GstPlugin *plugin)
&smpte_details);
g_return_val_if_fail(factory != NULL, FALSE);
- gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_sink1_factory));
- gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_sink2_factory));
- gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_src_factory));
+ gst_element_factory_add_pad_template (factory,
+ GST_PAD_TEMPLATE_GET (smpte_sink1_factory));
+ gst_element_factory_add_pad_template (factory,
+ GST_PAD_TEMPLATE_GET (smpte_sink2_factory));
+ gst_element_factory_add_pad_template (factory,
+ GST_PAD_TEMPLATE_GET (smpte_src_factory));
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));