#endif
#include <string.h>
#include "gstsmpte.h"
-#include <gst/video/video.h>
#include "paint.h"
GST_DEBUG_CATEGORY_STATIC (gst_smpte_debug);
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420")
)
);
GST_STATIC_PAD_TEMPLATE ("sink1",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420")
)
);
GST_STATIC_PAD_TEMPLATE ("sink2",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420")
)
);
static void gst_smpte_class_init (GstSMPTEClass * klass);
-static void gst_smpte_base_init (GstSMPTEClass * klass);
static void gst_smpte_init (GstSMPTE * smpte);
static void gst_smpte_finalize (GstSMPTE * smpte);
if (!smpte_type) {
static const GTypeInfo smpte_info = {
sizeof (GstSMPTEClass),
- (GBaseInitFunc) gst_smpte_base_init,
+ NULL,
NULL,
(GClassInitFunc) gst_smpte_class_init,
NULL,
}
static void
-gst_smpte_base_init (GstSMPTEClass * klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_smpte_sink1_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_smpte_sink2_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_smpte_src_template));
- gst_element_class_set_details_simple (element_class, "SMPTE transitions",
- "Filter/Editor/Video",
- "Apply the standard SMPTE transitions on video images",
- "Wim Taymans <wim.taymans@chello.be>");
-}
-
-static void
gst_smpte_class_init (GstSMPTEClass * klass)
{
GObjectClass *gobject_class;
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_smpte_change_state);
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_smpte_sink1_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_smpte_sink2_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_smpte_src_template));
+ gst_element_class_set_details_simple (gstelement_class, "SMPTE transitions",
+ "Filter/Editor/Video",
+ "Apply the standard SMPTE transitions on video images",
+ "Wim Taymans <wim.taymans@chello.be>");
}
/* wht yel cya grn mag red blu blk -I Q */
gst_smpte_setcaps (GstPad * pad, GstCaps * caps)
{
GstSMPTE *smpte;
- GstStructure *structure;
gboolean ret;
+ GstVideoInfo vinfo;
smpte = GST_SMPTE (GST_PAD_PARENT (pad));
- structure = gst_caps_get_structure (caps, 0);
-
- ret = gst_structure_get_int (structure, "width", &smpte->width);
- ret &= gst_structure_get_int (structure, "height", &smpte->height);
- ret &= gst_structure_get_fraction (structure, "framerate",
- &smpte->fps_num, &smpte->fps_denom);
- if (!ret)
+ gst_video_info_init (&vinfo);
+ if (!gst_video_info_from_caps (&vinfo, caps))
return FALSE;
+ smpte->width = GST_VIDEO_INFO_WIDTH (&vinfo);
+ smpte->height = GST_VIDEO_INFO_HEIGHT (&vinfo);
+ smpte->fps_num = GST_VIDEO_INFO_FPS_N (&vinfo);
+ smpte->fps_denom = GST_VIDEO_INFO_FPS_D (&vinfo);
+
/* for backward compat, we store these here */
smpte->fps = ((gdouble) smpte->fps_num) / smpte->fps_denom;
gst_smpte_update_mask (smpte, smpte->type, smpte->invert, smpte->depth,
smpte->width, smpte->height);
+ if (pad == smpte->sinkpad1) {
+ GST_DEBUG_OBJECT (smpte, "setting pad1 info");
+ smpte->vinfo1 = vinfo;
+ } else {
+ GST_DEBUG_OBJECT (smpte, "setting pad2 info");
+ smpte->vinfo2 = vinfo;
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_smpte_sink_event (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data)
+{
+ GstPad *pad;
+ gboolean ret = FALSE;
+
+ pad = data->pad;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_event_parse_caps (event, &caps);
+ ret = gst_smpte_setcaps (pad, caps);
+ gst_event_unref (event);
+ event = NULL;
+ break;
+ }
+ default:
+ ret = gst_pad_event_default (pad,
+ GST_OBJECT_CAST (GST_PAD_PARENT (pad)), event);
+ }
+
return ret;
}
{
smpte->sinkpad1 =
gst_pad_new_from_static_template (&gst_smpte_sink1_template, "sink1");
- gst_pad_set_setcaps_function (smpte->sinkpad1,
- GST_DEBUG_FUNCPTR (gst_smpte_setcaps));
- gst_pad_set_getcaps_function (smpte->sinkpad1,
- GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+ GST_PAD_SET_PROXY_CAPS (smpte->sinkpad1);
gst_element_add_pad (GST_ELEMENT (smpte), smpte->sinkpad1);
smpte->sinkpad2 =
gst_pad_new_from_static_template (&gst_smpte_sink2_template, "sink2");
- gst_pad_set_setcaps_function (smpte->sinkpad2,
- GST_DEBUG_FUNCPTR (gst_smpte_setcaps));
- gst_pad_set_getcaps_function (smpte->sinkpad2,
- GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+ GST_PAD_SET_PROXY_CAPS (smpte->sinkpad2);
gst_element_add_pad (GST_ELEMENT (smpte), smpte->sinkpad2);
smpte->srcpad =
smpte->collect = gst_collect_pads2_new ();
gst_collect_pads2_set_function (smpte->collect,
(GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
+ gst_collect_pads2_set_event_function (smpte->collect,
+ GST_DEBUG_FUNCPTR (gst_smpte_sink_event), smpte);
gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad1,
sizeof (GstCollectData2));
}
static void
-gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
- gint width, gint height, gint border, gint pos)
+gst_smpte_blend_i420 (GstVideoFrame * frame1, GstVideoFrame * frame2,
+ GstVideoFrame * oframe, GstMask * mask, gint border, gint pos)
{
guint32 *maskp;
gint value;
gint i, j;
gint min, max;
- guint8 *in1u, *in1v, *in2u, *in2v, *outu, *outv;
- gint uoffset, voffset, ystr, ustr, vstr;
+ guint8 *in1, *in2, *out, *in1u, *in1v, *in2u, *in2v, *outu, *outv;
+ gint width, height;
if (border == 0)
border++;
min = pos - border;
max = pos;
- uoffset = I420_U_OFFSET (width, height);
- voffset = I420_V_OFFSET (width, height);
+ width = GST_VIDEO_FRAME_WIDTH (frame1);
+ height = GST_VIDEO_FRAME_HEIGHT (frame1);
- ystr = I420_Y_ROWSTRIDE (width);
- ustr = I420_U_ROWSTRIDE (width);
- vstr = I420_V_ROWSTRIDE (width);
+ in1 = GST_VIDEO_FRAME_COMP_DATA (frame1, 0);
+ in2 = GST_VIDEO_FRAME_COMP_DATA (frame2, 0);
+ out = GST_VIDEO_FRAME_COMP_DATA (oframe, 0);
- in1u = in1 + uoffset;
- in1v = in1 + voffset;
- in2u = in2 + uoffset;
- in2v = in2 + voffset;
- outu = out + uoffset;
- outv = out + voffset;
+ in1u = GST_VIDEO_FRAME_COMP_DATA (frame1, 1);
+ in1v = GST_VIDEO_FRAME_COMP_DATA (frame1, 2);
+ in2u = GST_VIDEO_FRAME_COMP_DATA (frame2, 1);
+ in2v = GST_VIDEO_FRAME_COMP_DATA (frame2, 2);
+ outu = GST_VIDEO_FRAME_COMP_DATA (oframe, 1);
+ outv = GST_VIDEO_FRAME_COMP_DATA (oframe, 2);
maskp = mask->data;
((in1v[j / 2] * value) + (in2v[j / 2] * (256 - value))) >> 8;
}
}
- out += ystr;
- in1 += ystr;
- in2 += ystr;
+
+ in1 += GST_VIDEO_FRAME_COMP_STRIDE (frame1, 0);
+ in2 += GST_VIDEO_FRAME_COMP_STRIDE (frame2, 0);
+ out += GST_VIDEO_FRAME_COMP_STRIDE (oframe, 0);
+
if (!(i & 1)) {
- outu += ustr;
- in1u += ustr;
- in2u += ustr;
- outv += vstr;
- in1v += vstr;
- in2v += vstr;
+ in1u += GST_VIDEO_FRAME_COMP_STRIDE (frame1, 1);
+ in2u += GST_VIDEO_FRAME_COMP_STRIDE (frame2, 1);
+ in1v += GST_VIDEO_FRAME_COMP_STRIDE (frame1, 2);
+ in2v += GST_VIDEO_FRAME_COMP_STRIDE (frame1, 2);
+ outu += GST_VIDEO_FRAME_COMP_STRIDE (oframe, 1);
+ outv += GST_VIDEO_FRAME_COMP_STRIDE (oframe, 2);
}
}
}
GstClockTime ts;
GstBuffer *in1 = NULL, *in2 = NULL;
GSList *collected;
+ GstMapInfo map;
+ GstVideoFrame frame1, frame2, oframe;
if (G_UNLIKELY (smpte->fps_num == 0))
goto not_negotiated;
- if (!GST_PAD_CAPS (smpte->sinkpad1) || !GST_PAD_CAPS (smpte->sinkpad2))
+ if (!gst_pad_has_current_caps (smpte->sinkpad1) ||
+ !gst_pad_has_current_caps (smpte->sinkpad2))
goto not_negotiated;
ts = gst_util_uint64_scale_int (smpte->position * GST_SECOND,
if (in1 == NULL) {
/* if no input, make picture black */
in1 = gst_buffer_new_and_alloc (I420_SIZE (smpte->width, smpte->height));
- fill_i420 (GST_BUFFER_DATA (in1), smpte->width, smpte->height, 7);
+ gst_buffer_map (in1, &map, GST_MAP_WRITE);
+ fill_i420 (map.data, smpte->width, smpte->height, 7);
+ gst_buffer_unmap (in1, &map);
}
if (in2 == NULL) {
/* if no input, make picture white */
in2 = gst_buffer_new_and_alloc (I420_SIZE (smpte->width, smpte->height));
- fill_i420 (GST_BUFFER_DATA (in2), smpte->width, smpte->height, 0);
+ gst_buffer_map (in2, &map, GST_MAP_WRITE);
+ fill_i420 (map.data, smpte->width, smpte->height, 0);
+ gst_buffer_unmap (in1, &map);
}
- if (GST_BUFFER_SIZE (in1) != GST_BUFFER_SIZE (in2))
+ if (GST_VIDEO_INFO_WIDTH (&smpte->vinfo1) !=
+ GST_VIDEO_INFO_WIDTH (&smpte->vinfo2) ||
+ GST_VIDEO_INFO_HEIGHT (&smpte->vinfo1) !=
+ GST_VIDEO_INFO_HEIGHT (&smpte->vinfo2))
goto input_formats_do_not_match;
if (smpte->position < smpte->end_position) {
outbuf = gst_buffer_new_and_alloc (I420_SIZE (smpte->width, smpte->height));
/* set caps if not done yet */
- if (!GST_PAD_CAPS (smpte->srcpad)) {
+ if (!gst_pad_has_current_caps (smpte->srcpad)) {
GstCaps *caps;
+ GstSegment segment;
caps =
gst_caps_copy (gst_static_caps_get
gst_pad_set_caps (smpte->srcpad, caps);
- gst_pad_push_event (smpte->srcpad,
- gst_event_new_new_segment_full (FALSE,
- 1.0, 1.0, GST_FORMAT_TIME, 0, -1, 0));
-
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ gst_pad_push_event (smpte->srcpad, gst_event_new_segment (&segment));
}
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smpte->srcpad));
- gst_smpte_blend_i420 (GST_BUFFER_DATA (in1),
- GST_BUFFER_DATA (in2),
- GST_BUFFER_DATA (outbuf),
- smpte->mask, smpte->width, smpte->height,
- smpte->border,
+ gst_video_frame_map (&frame1, &smpte->vinfo1, in1, GST_MAP_READ);
+ gst_video_frame_map (&frame2, &smpte->vinfo2, in2, GST_MAP_READ);
+ /* re-use either info, now know they are essentially identical */
+ gst_video_frame_map (&oframe, &smpte->vinfo1, outbuf, GST_MAP_WRITE);
+ gst_smpte_blend_i420 (&frame1, &frame2, &oframe, smpte->mask, smpte->border,
((1 << smpte->depth) + smpte->border) *
smpte->position / smpte->end_position);
-
+ gst_video_frame_unmap (&frame1);
+ gst_video_frame_unmap (&frame2);
+ gst_video_frame_unmap (&oframe);
} else {
outbuf = in2;
gst_buffer_ref (in2);
}
input_formats_do_not_match:
{
+ GstCaps *caps1, *caps2;
+
+ caps1 = gst_pad_get_current_caps (smpte->sinkpad1);
+ caps2 = gst_pad_get_current_caps (smpte->sinkpad2);
GST_ELEMENT_ERROR (smpte, CORE, NEGOTIATION, (NULL),
("input formats don't match: %" GST_PTR_FORMAT " vs. %" GST_PTR_FORMAT,
- GST_PAD_CAPS (smpte->sinkpad1), GST_PAD_CAPS (smpte->sinkpad2)));
+ caps1, caps2));
+ gst_caps_unref (caps1);
+ gst_caps_unref (caps2);
return GST_FLOW_ERROR;
}
}
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";"
- GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";"
- GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_ARGB)
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("AYUV") ";"
+ GST_VIDEO_CAPS_MAKE ("ARGB") ";" GST_VIDEO_CAPS_MAKE ("BGRA") ";"
+ GST_VIDEO_CAPS_MAKE ("RGBA") ";" GST_VIDEO_CAPS_MAKE ("ARGB"))
);
static GstStaticPadTemplate gst_smpte_alpha_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("YV12")
- ";" GST_VIDEO_CAPS_YUV ("AYUV")
- ";" GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_RGBA
- ";" GST_VIDEO_CAPS_ARGB)
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420") ";"
+ GST_VIDEO_CAPS_MAKE ("YV12")
+ ";" GST_VIDEO_CAPS_MAKE ("AYUV")
+ ";" GST_VIDEO_CAPS_MAKE ("ARGB") ";" GST_VIDEO_CAPS_MAKE ("BGRA")
+ ";" GST_VIDEO_CAPS_MAKE ("RGBA") ";" GST_VIDEO_CAPS_MAKE ("ARGB"))
);
/* SMPTE signals and properties */
static void gst_smpte_alpha_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static gboolean gst_smpte_alpha_setcaps (GstBaseTransform * btrans,
- GstCaps * incaps, GstCaps * outcaps);
-static gboolean gst_smpte_alpha_get_unit_size (GstBaseTransform * btrans,
- GstCaps * caps, guint * size);
-static GstFlowReturn gst_smpte_alpha_transform (GstBaseTransform * trans,
- GstBuffer * in, GstBuffer * out);
+static gboolean gst_smpte_alpha_set_info (GstVideoFilter * vfilter,
+ GstCaps * incaps, GstVideoInfo * in_info,
+ GstCaps * outcaps, GstVideoInfo * out_info);
+static GstFlowReturn gst_smpte_alpha_transform_frame (GstVideoFilter * vfilter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame);
static void gst_smpte_alpha_before_transform (GstBaseTransform * trans,
GstBuffer * buf);
static GstCaps *gst_smpte_alpha_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * from);
+ GstPadDirection direction, GstCaps * from, GstCaps * filter);
-GST_BOILERPLATE (GstSMPTEAlpha, gst_smpte_alpha, GstVideoFilter,
- GST_TYPE_VIDEO_FILTER);
-
-static void
-gst_smpte_alpha_base_init (gpointer klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_smpte_alpha_sink_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_smpte_alpha_src_template));
- gst_element_class_set_details_simple (element_class, "SMPTE transitions",
- "Filter/Editor/Video",
- "Apply the standard SMPTE transitions as alpha on video images",
- "Wim Taymans <wim.taymans@gmail.com>");
-}
+#define gst_smpte_alpha_parent_class parent_class
+G_DEFINE_TYPE (GstSMPTEAlpha, gst_smpte_alpha, GST_TYPE_VIDEO_FILTER);
static void
gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *element_class = (GstElementClass *) (klass);
GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+ GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
gobject_class->set_property = gst_smpte_alpha_set_property;
gobject_class->get_property = gst_smpte_alpha_get_property;
"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->get_unit_size =
- GST_DEBUG_FUNCPTR (gst_smpte_alpha_get_unit_size);
- trans_class->transform = GST_DEBUG_FUNCPTR (gst_smpte_alpha_transform);
trans_class->before_transform =
GST_DEBUG_FUNCPTR (gst_smpte_alpha_before_transform);
trans_class->transform_caps =
GST_DEBUG_FUNCPTR (gst_smpte_alpha_transform_caps);
+
+ vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_smpte_alpha_set_info);
+ vfilter_class->transform_frame =
+ GST_DEBUG_FUNCPTR (gst_smpte_alpha_transform_frame);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_smpte_alpha_sink_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_smpte_alpha_src_template));
+ gst_element_class_set_details_simple (element_class, "SMPTE transitions",
+ "Filter/Editor/Video",
+ "Apply the standard SMPTE transitions as alpha on video images",
+ "Wim Taymans <wim.taymans@gmail.com>");
}
static gboolean
}
static void
-gst_smpte_alpha_init (GstSMPTEAlpha * smpte, GstSMPTEAlphaClass * klass)
+gst_smpte_alpha_init (GstSMPTEAlpha * smpte)
{
smpte->type = DEFAULT_PROP_TYPE;
smpte->border = DEFAULT_PROP_BORDER;
#define CREATE_ARGB_FUNC(name, A, R, G, B) \
static void \
-gst_smpte_alpha_process_##name##_##name (GstSMPTEAlpha * smpte, const guint8 * in, \
- guint8 * out, GstMask * mask, gint width, gint height, gint border, \
- gint pos) \
+gst_smpte_alpha_process_##name##_##name (GstSMPTEAlpha * smpte, \
+ const GstVideoFrame * in_frame, GstVideoFrame * out_frame, GstMask * mask, \
+ gint border, gint pos) \
{ \
gint i, j; \
const guint32 *maskp; \
gint value; \
gint min, max; \
+ gint width, height; \
+ guint8 *in, *out; \
+ gint src_wrap, dest_wrap; \
\
if (border == 0) \
border++; \
\
maskp = mask->data; \
\
+ width = GST_VIDEO_FRAME_WIDTH (out_frame); \
+ height = GST_VIDEO_FRAME_HEIGHT (out_frame); \
+ \
+ in = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0); \
+ out = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0); \
+ src_wrap = GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0) - (width << 2); \
+ dest_wrap = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0) - (width << 2); \
+ \
/* we basically copy the source to dest but we scale the alpha channel with \
* the mask */ \
for (i = 0; i < height; i++) { \
out += 4; \
in += 4; \
} \
+ in += src_wrap; \
+ out += dest_wrap; \
} \
}
CREATE_ARGB_FUNC (rgba, 3, 0, 1, 2);
static void
-gst_smpte_alpha_process_ayuv_ayuv (GstSMPTEAlpha * smpte, const guint8 * in,
- guint8 * out, GstMask * mask, gint width, gint height, gint border,
- gint pos)
+gst_smpte_alpha_process_ayuv_ayuv (GstSMPTEAlpha * smpte,
+ const GstVideoFrame * in_frame, GstVideoFrame * out_frame, GstMask * mask,
+ gint border, gint pos)
{
gint i, j;
const guint32 *maskp;
gint value;
gint min, max;
+ gint width, height;
+ guint8 *in, *out;
+ gint src_wrap, dest_wrap;
if (border == 0)
border++;
maskp = mask->data;
+ width = GST_VIDEO_FRAME_WIDTH (out_frame);
+ height = GST_VIDEO_FRAME_HEIGHT (out_frame);
+
+ in = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
+ out = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
+ src_wrap = GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0) - (width << 2);
+ dest_wrap = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0) - (width << 2);
+
/* we basically copy the source to dest but we scale the alpha channel with
* the mask */
for (i = 0; i < height; i++) {
*out++ = *in++;
*out++ = *in++;
}
+ in += src_wrap;
+ out += dest_wrap;
}
}
static void
-gst_smpte_alpha_process_i420_ayuv (GstSMPTEAlpha * smpte, const guint8 * in,
- guint8 * out, GstMask * mask, gint width, gint height, gint border,
- gint pos)
+gst_smpte_alpha_process_i420_ayuv (GstSMPTEAlpha * smpte,
+ const GstVideoFrame * in_frame, GstVideoFrame * out_frame, GstMask * mask,
+ gint border, gint pos)
{
const guint8 *srcY;
const guint8 *srcU;
const guint8 *srcV;
+ guint8 *out;
gint i, j;
- gint src_wrap, src_uv_wrap;
- gint y_stride, uv_stride;
+ gint src_wrap, src_u_wrap, src_v_wrap, dest_wrap;
+ gint y_stride, u_stride, v_stride;
gboolean odd_width;
const guint32 *maskp;
gint value;
gint min, max;
+ gint width, height;
if (border == 0)
border++;
maskp = mask->data;
- y_stride = gst_video_format_get_row_stride (smpte->in_format, 0, width);
- uv_stride = gst_video_format_get_row_stride (smpte->in_format, 1, width);
+ width = GST_VIDEO_FRAME_WIDTH (out_frame);
+ height = GST_VIDEO_FRAME_HEIGHT (out_frame);
+
+ y_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 0);
+ u_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 1);
+ v_stride = GST_VIDEO_FRAME_COMP_STRIDE (in_frame, 2);
src_wrap = y_stride - width;
- src_uv_wrap = uv_stride - (width / 2);
+ src_u_wrap = u_stride - (width / 2);
+ src_v_wrap = v_stride - (width / 2);
- srcY = in;
- srcU = in + gst_video_format_get_component_offset (smpte->in_format,
- 1, width, height);
- srcV = in + gst_video_format_get_component_offset (smpte->in_format,
- 2, width, height);
+ srcY = GST_VIDEO_FRAME_COMP_DATA (in_frame, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (in_frame, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (in_frame, 2);
+
+ out = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);
+ dest_wrap = GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0) - (width << 2);
odd_width = (width % 2 != 0);
srcU -= width / 2;
srcV -= width / 2;
} else {
- srcU += src_uv_wrap;
- srcV += src_uv_wrap;
+ srcU += src_u_wrap;
+ srcV += src_v_wrap;
}
srcY += src_wrap;
+ out += dest_wrap;
}
}
}
static GstFlowReturn
-gst_smpte_alpha_transform (GstBaseTransform * trans, GstBuffer * in,
- GstBuffer * out)
+gst_smpte_alpha_transform_frame (GstVideoFilter * vfilter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame)
{
- GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (trans);
+ GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (vfilter);
gdouble position;
gint border;
if (G_UNLIKELY (!smpte->process))
goto not_negotiated;
- /* these are the propertis we update with only the object lock, others are
- * only updated with the TRANSFORM_LOCK. */
GST_OBJECT_LOCK (smpte);
position = smpte->position;
border = smpte->border;
- GST_OBJECT_UNLOCK (smpte);
/* run the type specific filter code */
- smpte->process (smpte, GST_BUFFER_DATA (in), GST_BUFFER_DATA (out),
- smpte->mask, smpte->width, smpte->height, border,
- ((1 << smpte->depth) + border) * position);
+ smpte->process (smpte, in_frame, out_frame,
+ smpte->mask, border, ((1 << smpte->depth) + border) * position);
+ GST_OBJECT_UNLOCK (smpte);
return GST_FLOW_OK;
static GstCaps *
gst_smpte_alpha_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * from)
+ GstPadDirection direction, GstCaps * from, GstCaps * filter)
{
- GstCaps *to = gst_caps_copy (from);
- GstStructure *s;
+ GstCaps *result, *tmp_caps, *tmpl_caps = NULL;
+ gint i, j;
- gst_caps_truncate (to);
- s = gst_caps_get_structure (to, 0);
+ tmp_caps = gst_caps_new_empty ();
- if (gst_structure_has_name (s, "video/x-raw-yuv")) {
+ for (i = 0; i < gst_caps_get_size (from); i++) {
+ GstStructure *structure;
+ const GValue *val, *lval;
GValue list = { 0, };
- GValue val = { 0, };
-
- gst_structure_remove_field (s, "format");
-
- g_value_init (&list, GST_TYPE_LIST);
- g_value_init (&val, GST_TYPE_FOURCC);
- gst_value_set_fourcc (&val, GST_STR_FOURCC ("AYUV"));
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- gst_value_set_fourcc (&val, GST_STR_FOURCC ("I420"));
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- gst_value_set_fourcc (&val, GST_STR_FOURCC ("YV12"));
- gst_value_list_append_value (&list, &val);
- g_value_unset (&val);
- gst_structure_set_value (s, "format", &list);
- g_value_unset (&list);
- } else if (!gst_structure_has_name (s, "video/x-raw-rgb")) {
- gst_caps_unref (to);
- to = gst_caps_new_empty ();
+ GValue aval = { 0, };
+ const gchar *str;
+
+ structure = gst_structure_copy (gst_caps_get_structure (from, i));
+ /* we can transform I420 to AYUV,
+ * so need to locate and substitute AYUV for the both of them */
+ val = gst_structure_get_value (structure, "format");
+ if (val && GST_VALUE_HOLDS_LIST (val)) {
+ gboolean seen_ayuv = FALSE, seen_i420 = FALSE;
+
+ g_value_init (&list, GST_TYPE_LIST);
+ for (j = 0; j < gst_value_list_get_size (val); j++) {
+ lval = gst_value_list_get_value (val, j);
+ if ((str = g_value_get_string (lval))) {
+ if (strcmp (str, "AYUV") == 0) {
+ seen_ayuv = TRUE;
+ } else if (strcmp (str, "I420") == 0) {
+ seen_i420 = TRUE;
+ }
+ }
+ }
+ if (seen_ayuv && !seen_i420) {
+ str = "I420";
+ } else if (seen_i420 && !seen_ayuv) {
+ str = "AYUV";
+ } else
+ str = NULL;
+ if (str) {
+ g_value_copy (val, &list);
+ g_value_init (&aval, G_TYPE_STRING);
+ g_value_set_string (&aval, str);
+ gst_value_list_append_value (&list, &aval);
+ g_value_reset (&aval);
+ gst_structure_set_value (structure, "format", &list);
+ g_value_unset (&list);
+ }
+ } else if (val && G_VALUE_HOLDS_STRING (val)) {
+ if ((str = g_value_get_string (val)) &&
+ ((strcmp (str, "AYUV") == 0) || (strcmp (str, "I420") == 0))) {
+ g_value_init (&list, GST_TYPE_LIST);
+ g_value_init (&aval, G_TYPE_STRING);
+ g_value_set_string (&aval, "AYUV");
+ gst_value_list_append_value (&list, &aval);
+ g_value_reset (&aval);
+ g_value_set_string (&aval, "I420");
+ gst_value_list_append_value (&list, &aval);
+ g_value_reset (&aval);
+ gst_structure_set_value (structure, "format", &list);
+ g_value_unset (&list);
+ }
+ } else {
+ gst_structure_remove_field (structure, "format");
+ }
+
+ gst_structure_remove_field (structure, "color-matrix");
+ gst_structure_remove_field (structure, "chroma-site");
+
+ gst_caps_append_structure (tmp_caps, structure);
+ }
+
+ /* Get the appropriate template */
+ if (direction == GST_PAD_SINK) {
+ tmpl_caps =
+ gst_static_pad_template_get_caps (&gst_smpte_alpha_src_template);
+ } else if (direction == GST_PAD_SRC) {
+ tmpl_caps =
+ gst_static_pad_template_get_caps (&gst_smpte_alpha_sink_template);
+ } else {
+ g_assert_not_reached ();
}
- return to;
+ /* Intersect with our template caps */
+ result = gst_caps_intersect (tmp_caps, tmpl_caps);
+ gst_caps_unref (tmpl_caps);
+ gst_caps_unref (tmp_caps);
+
+ result = gst_caps_simplify (result);
+
+ GST_LOG_OBJECT (trans, "transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT,
+ from, result);
+
+ if (filter) {
+ GstCaps *intersection;
+
+ GST_DEBUG_OBJECT (trans, "Using filter caps %" GST_PTR_FORMAT, filter);
+ intersection =
+ gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (result);
+ result = intersection;
+ GST_DEBUG_OBJECT (trans, "Intersection %" GST_PTR_FORMAT, result);
+ }
+
+ return result;
}
static gboolean
-gst_smpte_alpha_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
- GstCaps * outcaps)
+gst_smpte_alpha_set_info (GstVideoFilter * vfilter, GstCaps * incaps,
+ GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
{
- GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (btrans);
+ GstSMPTEAlpha *smpte = GST_SMPTE_ALPHA (vfilter);
gboolean ret;
gint width, height;
smpte->process = NULL;
- if (!gst_video_format_parse_caps (incaps, &smpte->in_format, &width, &height))
- goto invalid_caps;
- if (!gst_video_format_parse_caps (outcaps, &smpte->out_format, &width,
- &height))
- goto invalid_caps;
+ smpte->in_format = GST_VIDEO_INFO_FORMAT (in_info);
+ smpte->out_format = GST_VIDEO_INFO_FORMAT (out_info);
+ smpte->width = width = GST_VIDEO_INFO_WIDTH (out_info);
+ smpte->height = height = GST_VIDEO_INFO_HEIGHT (out_info);
/* try to update the mask now, this will also adjust the width/height on
* success */
return ret;
/* ERRORS */
-invalid_caps:
- {
- GST_ERROR_OBJECT (smpte, "Invalid caps: %" GST_PTR_FORMAT, incaps);
- return FALSE;
- }
mask_failed:
{
GST_ERROR_OBJECT (smpte, "failed creating the mask");
}
}
-static gboolean
-gst_smpte_alpha_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
- guint * size)
-{
- gint width, height;
- GstVideoFormat format;
-
- if (!gst_video_format_parse_caps (caps, &format, &width, &height))
- return FALSE;
-
- *size = gst_video_format_get_size (format, width, height);
-
- return TRUE;
-}
-
static void
gst_smpte_alpha_finalize (GstSMPTEAlpha * smpte)
{
type = g_value_get_enum (value);
- GST_BASE_TRANSFORM_LOCK (smpte);
GST_OBJECT_LOCK (smpte);
gst_smpte_alpha_update_mask (smpte, type, smpte->invert,
smpte->depth, smpte->width, smpte->height);
GST_OBJECT_UNLOCK (smpte);
- GST_BASE_TRANSFORM_UNLOCK (smpte);
break;
}
case PROP_BORDER:
depth = g_value_get_int (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_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert,
depth, smpte->width, smpte->height);
GST_OBJECT_UNLOCK (smpte);
- GST_BASE_TRANSFORM_UNLOCK (smpte);
break;
}
case PROP_POSITION:
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_smpte_alpha_update_mask (smpte, smpte->type, invert,
smpte->depth, smpte->width, smpte->height);
GST_OBJECT_UNLOCK (smpte);
- GST_BASE_TRANSFORM_UNLOCK (smpte);
break;
}
default: