diff options
Diffstat (limited to 'gst/smpte/gstsmpte.c')
-rw-r--r-- | gst/smpte/gstsmpte.c | 168 |
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)); |