summaryrefslogtreecommitdiffstats
path: root/gst/videobox
diff options
context:
space:
mode:
authorDejan Sakelšak <sakdean@gmail.com>2007-05-28 15:01:33 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-05-28 15:01:33 +0000
commit82a509fdfd79dd72f33dd25b02f969e281c5667d (patch)
tree7d58cf3b965cc700387db5694c8b0fe791df97d6 /gst/videobox
parente81c80a481eef774ec3cc3d10b04181efc27db10 (diff)
gst/videobox/gstvideobox.c: Add AYUV->AYUV and AYUV->I420 formats.
Original commit message from CVS: Based on patch by: Dejan Sakelšak <sakdean at gmail dot com> * gst/videobox/gstvideobox.c: (gst_video_box_class_init), (gst_video_box_set_property), (gst_video_box_transform_caps), (video_box_recalc_transform), (gst_video_box_set_caps), (gst_video_box_get_unit_size), (gst_video_box_apply_alpha), (gst_video_box_ayuv_ayuv), (gst_video_box_clear), (UVfloor), (UVceil), (gst_video_box_ayuv_i420), (gst_video_box_i420_ayuv), (gst_video_box_i420_i420), (gst_video_box_transform), (plugin_init): Add AYUV->AYUV and AYUV->I420 formats. Fix negotiation and I420->AYUV conversion. Fixes #429329.
Diffstat (limited to 'gst/videobox')
-rw-r--r--gst/videobox/gstvideobox.c707
1 files changed, 588 insertions, 119 deletions
diff --git a/gst/videobox/gstvideobox.c b/gst/videobox/gstvideobox.c
index 966569b2..5fa3d59e 100644
--- a/gst/videobox/gstvideobox.c
+++ b/gst/videobox/gstvideobox.c
@@ -23,7 +23,7 @@
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
#include <gst/video/video.h>
-
+#include <math.h>
#include <liboil/liboil.h>
#include <string.h>
@@ -58,7 +58,9 @@ struct _GstVideoBox
GstBaseTransform element;
/* caps */
+ guint32 in_fourcc;
gint in_width, in_height;
+ guint32 out_fourcc;
gint out_width, out_height;
gint box_left, box_right, box_top, box_bottom;
@@ -66,7 +68,6 @@ struct _GstVideoBox
gint border_left, border_right, border_top, border_bottom;
gint crop_left, crop_right, crop_top, crop_bottom;
- gboolean use_alpha;
gdouble alpha;
gdouble border_alpha;
@@ -108,17 +109,19 @@ enum
};
static GstStaticPadTemplate gst_video_box_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
+ GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ AYUV, I420 }"))
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";"
+ GST_VIDEO_CAPS_YUV ("I420"))
);
static GstStaticPadTemplate gst_video_box_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";"
+ GST_VIDEO_CAPS_YUV ("I420"))
);
@@ -130,6 +133,7 @@ static void gst_video_box_set_property (GObject * object, guint prop_id,
static void gst_video_box_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
+static gboolean video_box_recalc_transform (GstVideoBox * video_box);
static GstCaps *gst_video_box_transform_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * from);
static gboolean gst_video_box_set_caps (GstBaseTransform * trans,
@@ -213,16 +217,14 @@ gst_video_box_class_init (GstVideoBoxClass * klass)
"Alpha value of the border", 0.0, 1.0, DEFAULT_BORDER_ALPHA,
G_PARAM_READWRITE));
+ trans_class->transform = GST_DEBUG_FUNCPTR (gst_video_box_transform);
trans_class->transform_caps =
GST_DEBUG_FUNCPTR (gst_video_box_transform_caps);
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_box_set_caps);
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_video_box_get_unit_size);
- trans_class->transform = GST_DEBUG_FUNCPTR (gst_video_box_transform);
GST_DEBUG_CATEGORY_INIT (videobox_debug, "videobox", 0,
"Resizes a video by adding borders or cropping");
-
- oil_init ();
}
static void
@@ -247,6 +249,7 @@ gst_video_box_set_property (GObject * object, guint prop_id,
{
GstVideoBox *video_box = GST_VIDEO_BOX (object);
+ GST_BASE_TRANSFORM_LOCK (GST_BASE_TRANSFORM_CAST (video_box));
switch (prop_id) {
case PROP_LEFT:
video_box->box_left = g_value_get_int (value);
@@ -301,6 +304,8 @@ gst_video_box_set_property (GObject * object, guint prop_id,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+ video_box_recalc_transform (video_box);
+ GST_BASE_TRANSFORM_UNLOCK (GST_BASE_TRANSFORM_CAST (video_box));
}
static void
@@ -342,48 +347,83 @@ gst_video_box_transform_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * from)
{
GstVideoBox *video_box;
- GstCaps *to;
+ GstCaps *to, *ret;
+ const GstCaps *templ;
GstStructure *structure;
- GValue list_value = { 0 }, value = {
- 0};
- gint dir, i, tmp;
+ GstPad *other;
+ gint width, height;
video_box = GST_VIDEO_BOX (trans);
- g_value_init (&list_value, GST_TYPE_LIST);
- g_value_init (&value, GST_TYPE_FOURCC);
- gst_value_set_fourcc (&value, GST_MAKE_FOURCC ('I', '4', '2', '0'));
- gst_value_list_append_value (&list_value, &value);
- g_value_unset (&value);
-
to = gst_caps_copy (from);
- dir = (direction == GST_PAD_SINK) ? -1 : 1;
-
- for (i = 0; i < gst_caps_get_size (to); i++) {
- structure = gst_caps_get_structure (to, i);
- if (direction == GST_PAD_SINK) { /* I420 to { I420, AYUV } */
- g_value_init (&value, GST_TYPE_FOURCC);
- gst_value_set_fourcc (&value, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'));
- gst_value_list_append_value (&list_value, &value);
- g_value_unset (&value);
- gst_structure_set_value (structure, "format", &list_value);
- } else if (direction == GST_PAD_SRC) {
- gst_structure_set_value (structure, "format", &list_value);
+ structure = gst_caps_get_structure (to, 0);
+
+ /* get rid of format */
+ gst_structure_remove_field (structure, "format");
+
+ /* calculate width and height */
+ if (gst_structure_get_int (structure, "width", &width)) {
+ if (direction == GST_PAD_SINK) {
+ width -= video_box->box_left;
+ width -= video_box->box_right;
+ } else {
+ width += video_box->box_left;
+ width += video_box->box_right;
+ }
+ if (width <= 0)
+ width = 1;
+
+ GST_DEBUG ("New caps width: %d", width);
+ gst_structure_set (structure, "width", G_TYPE_INT, width, NULL);
+ }
+
+ if (gst_structure_get_int (structure, "height", &height)) {
+ if (direction == GST_PAD_SINK) {
+ height -= video_box->box_top;
+ height -= video_box->box_bottom;
+ } else {
+ height += video_box->box_top;
+ height += video_box->box_bottom;
}
- if (gst_structure_get_int (structure, "width", &tmp))
- gst_structure_set (structure, "width", G_TYPE_INT,
- tmp + dir * (video_box->box_left + video_box->box_right), NULL);
- if (gst_structure_get_int (structure, "height", &tmp))
- gst_structure_set (structure, "height", G_TYPE_INT,
- tmp + dir * (video_box->box_top + video_box->box_bottom), NULL);
+
+ if (height <= 0)
+ height = 1;
+
+ GST_DEBUG ("New caps height: %d", height);
+ gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
}
- g_value_unset (&list_value);
+ /* filter against set allowed caps on the pad */
+ other = (direction == GST_PAD_SINK) ? trans->srcpad : trans->sinkpad;
+
+ templ = gst_pad_get_pad_template_caps (other);
+ ret = gst_caps_intersect (to, templ);
+ gst_caps_unref (to);
GST_DEBUG_OBJECT (video_box, "direction %d, transformed %" GST_PTR_FORMAT
- " to %" GST_PTR_FORMAT, direction, from, to);
+ " to %" GST_PTR_FORMAT, direction, from, ret);
+
+ return ret;
+}
+
+static gboolean
+video_box_recalc_transform (GstVideoBox * video_box)
+{
+ gboolean res = TRUE;
- return to;
+ /* if we have the same format in and out and we don't need to perform and
+ * cropping at all, we can just operate in passthorugh mode */
+ if (video_box->in_fourcc == video_box->out_fourcc &&
+ video_box->box_left == 0 && video_box->box_right == 0 &&
+ video_box->box_top == 0 && video_box->box_bottom == 0) {
+
+ GST_LOG_OBJECT (video_box, "we are using passthrough");
+ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box), TRUE);
+ } else {
+ GST_LOG_OBJECT (video_box, "we are not using passthrough");
+ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box), FALSE);
+ }
+ return res;
}
static gboolean
@@ -392,34 +432,37 @@ gst_video_box_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
GstVideoBox *video_box;
GstStructure *structure;
gboolean ret;
- guint32 fourcc = 0;
video_box = GST_VIDEO_BOX (trans);
structure = gst_caps_get_structure (in, 0);
ret = gst_structure_get_int (structure, "width", &video_box->in_width);
ret &= gst_structure_get_int (structure, "height", &video_box->in_height);
+ ret &= gst_structure_get_fourcc (structure, "format", &video_box->in_fourcc);
structure = gst_caps_get_structure (out, 0);
ret &= gst_structure_get_int (structure, "width", &video_box->out_width);
ret &= gst_structure_get_int (structure, "height", &video_box->out_height);
- ret &= gst_structure_get_fourcc (structure, "format", &fourcc);
+ ret &= gst_structure_get_fourcc (structure, "format", &video_box->out_fourcc);
- if (fourcc == GST_STR_FOURCC ("AYUV")) {
- video_box->use_alpha = TRUE;
- } else {
- if (video_box->box_left == 0 && video_box->box_right == 0 &&
- video_box->box_top == 0 && video_box->box_bottom == 0) {
- gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box), TRUE);
- GST_LOG ("we are using passthrough");
- } else {
- gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box),
- FALSE);
- GST_LOG ("we are not using passthrough");
- }
- }
+ /* something wrong getting the caps */
+ if (!ret)
+ goto no_caps;
+
+ GST_DEBUG ("Input w: %d h: %d", video_box->in_width, video_box->in_height);
+ GST_DEBUG ("Output w: %d h: %d", video_box->out_width, video_box->out_height);
+
+ /* recalc the transformation strategy */
+ ret = video_box_recalc_transform (video_box);
return ret;
+
+ /* ERRORS */
+no_caps:
+ {
+ GST_DEBUG_OBJECT (video_box, "Could not get all caps fields");
+ return FALSE;
+ }
}
/* see gst-plugins/gst/games/gstvideoimage.c, paint_setup_I420() */
@@ -437,6 +480,7 @@ static gboolean
gst_video_box_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
guint * size)
{
+
GstVideoBox *video_box;
GstStructure *structure = NULL;
guint32 fourcc;
@@ -463,6 +507,8 @@ gst_video_box_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
break;
}
+ GST_LOG_OBJECT (video_box, "Returning from _unit_size %d", *size);
+
return TRUE;
}
@@ -501,74 +547,397 @@ gst_video_box_copy_plane_i420 (GstVideoBox * video_box, guint8 * src,
}
static void
-gst_video_box_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
+gst_video_box_apply_alpha (guint8 * dest, guint8 alpha)
{
- guint8 *srcY, *srcU, *srcV;
- guint8 *destY, *destU, *destV;
- gint crop_width, crop_height;
- gint out_width, out_height;
- gint src_width, src_height;
- gint src_stride, dest_stride;
- gint br, bl, bt, bb;
+ if (dest[0] != 0)
+ dest[0] = alpha;
+}
- br = video_box->border_right;
- bl = video_box->border_left;
- bt = video_box->border_top;
- bb = video_box->border_bottom;
+static void
+gst_video_box_ayuv_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
+{
+ gint dblen = video_box->out_height * video_box->out_width;
+ guint32 *destb = (guint32 *) dest;
+ guint32 *srcb = (guint32 *) src;
+ guint8 b_alpha = (guint8) (video_box->border_alpha * 255);
+ guint8 i_alpha = (guint8) (video_box->alpha * 255);
+ gint br, bl, bt, bb, crop_w, crop_h;
+ gint i;
+ guint32 *loc = destb;
+ guint32 empty_pixel;
+
+ GST_LOG ("Processing AYUV -> AYUV data");
+
+ crop_h = 0;
+ crop_w = 0;
+ empty_pixel = GUINT32_FROM_BE ((b_alpha << 24) |
+ (yuv_colors_Y[video_box->fill_type] << 16) |
+ (yuv_colors_U[video_box->fill_type] << 8) |
+ yuv_colors_V[video_box->fill_type]);
+
+ br = video_box->box_right;
+ bl = video_box->box_left;
+ bt = video_box->box_top;
+ bb = video_box->box_bottom;
+
+ if (br >= 0 && bl >= 0) {
+ crop_w = video_box->in_width - (br + bl);
+ } else if (br >= 0 && bl < 0) {
+ crop_w = video_box->in_width - (br);
+ } else if (br < 0 && bl >= 0) {
+ crop_w = video_box->in_width - (bl);
+ } else if (br < 0 && bl < 0) {
+ crop_w = video_box->in_width;
+ }
- out_width = video_box->out_width;
- out_height = video_box->out_height;
+ if (bb >= 0 && bt >= 0) {
+ crop_h = video_box->in_height - (bb + bt);
+ } else if (bb >= 0 && bt < 0) {
+ crop_h = video_box->in_height - (bb);
+ } else if (bb < 0 && bt >= 0) {
+ crop_h = video_box->in_height - (bt);
+ } else if (bb < 0 && bt < 0) {
+ crop_h = video_box->in_height;
+ }
- src_width = video_box->in_width;
- src_height = video_box->in_height;
+ GST_DEBUG ("Borders are: L:%d, R:%d, T:%d, B:%d", bl, br, bt, bb);
+ GST_DEBUG ("Alpha value is: %d", i_alpha);
- crop_width = src_width - (video_box->crop_left + video_box->crop_right);
- crop_height = src_height - (video_box->crop_top + video_box->crop_bottom);
+ if (crop_h <= 0 || crop_w <= 0) {
- /* Y plane */
- src_stride = GST_VIDEO_I420_Y_ROWSTRIDE (src_width);
- dest_stride = GST_VIDEO_I420_Y_ROWSTRIDE (out_width);
+ oil_splat_u32_ns (destb, &empty_pixel, dblen);
- destY = dest + GST_VIDEO_I420_Y_OFFSET (out_width, out_height);
+ } else {
- srcY = src + GST_VIDEO_I420_Y_OFFSET (src_width, src_height);
- srcY += src_stride * video_box->crop_top + video_box->crop_left;
+ guint32 *src_loc = srcb;
- gst_video_box_copy_plane_i420 (video_box, srcY, destY, br, bl, bt, bb,
- crop_width, crop_height, src_stride, out_width, dest_stride,
- yuv_colors_Y[video_box->fill_type]);
+ /* Top border */
+ if (bt < 0) {
+ oil_splat_u32_ns (loc, &empty_pixel, (-bt) * video_box->out_width);
+ loc = loc + ((-bt) * video_box->out_width);
+ } else {
+ src_loc = src_loc + (bt * video_box->in_width);
+ }
- /* U plane */
- src_stride = GST_VIDEO_I420_U_ROWSTRIDE (src_width);
- dest_stride = GST_VIDEO_I420_U_ROWSTRIDE (out_width);
+ if (bl >= 0)
+ src_loc += bl;
- destU = dest + GST_VIDEO_I420_U_OFFSET (out_width, out_height);
+ for (i = 0; i < crop_h; i++) {
+ gint j;
- srcU = src + GST_VIDEO_I420_U_OFFSET (src_width, src_height);
- srcU += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+ /* Left border */
+ if (bl < 0) {
+ oil_splat_u32_ns (loc, &empty_pixel, -bl);
+ loc += (-bl);
+ }
- gst_video_box_copy_plane_i420 (video_box, srcU, destU, br / 2, bl / 2, bt / 2,
- bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
- dest_stride, yuv_colors_U[video_box->fill_type]);
+ /* Cropped area */
+ oil_copy_u8 ((guint8 *) loc, (guint8 *) src_loc, crop_w * 4);
- /* V plane */
- src_stride = GST_VIDEO_I420_V_ROWSTRIDE (src_width);
- dest_stride = GST_VIDEO_I420_V_ROWSTRIDE (out_width);
+ for (j = 0; j < crop_w; j++)
+ gst_video_box_apply_alpha ((guint8 *) & loc[j], i_alpha);
- destV = dest + GST_VIDEO_I420_V_OFFSET (out_width, out_height);
+ src_loc += video_box->in_width;
+ loc += crop_w;
- srcV = src + GST_VIDEO_I420_V_OFFSET (src_width, src_height);
- srcV += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+ /* Right border */
+ if (br < 0) {
+ oil_splat_u32_ns (loc, &empty_pixel, -br);
+ loc += (-br);
+ }
+ }
- gst_video_box_copy_plane_i420 (video_box, srcV, destV, br / 2, bl / 2, bt / 2,
- bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
- dest_stride, yuv_colors_V[video_box->fill_type]);
+ /* Bottom border */
+ if (bb < 0) {
+ oil_splat_u32_ns (loc, &empty_pixel, (-bb) * video_box->out_width);
+ }
+ }
+
+ GST_LOG ("image created");
+
+}
+
+static gpointer
+gst_video_box_clear (gpointer dest, gint size)
+{
+ guint8 nil = 255;
+
+ oil_splat_u8_ns (dest, &nil, size);
+
+ return dest;
+}
+
+static gint
+UVfloor (gint j)
+{
+ return floor (((float) j) / 2);
+}
+
+static gint
+UVceil (gint j)
+{
+ return ceil (((float) j) / 2);
+}
+
+static void
+gst_video_box_ayuv_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
+{
+ gint br, bl, bt, bb, crop_w, crop_h, rest;
+ gint Ysize, Usize, Vsize;
+ guint8 *Ydest, *Udest, *Vdest;
+ guint8 *Utemp, *Vtemp;
+ guint32 empty_px_values[3];
+ gint i, j;
+ guint Ywidth, Uwidth, Vwidth;
+
+ GST_DEBUG ("AYUV to I420 conversion");
+
+ crop_h = 0;
+ crop_w = 0;
+ rest = 0;
+
+ empty_px_values[0] = yuv_colors_Y[video_box->fill_type];
+ empty_px_values[1] = yuv_colors_U[video_box->fill_type];
+ empty_px_values[2] = yuv_colors_V[video_box->fill_type];
+
+ Ywidth = GST_VIDEO_I420_Y_ROWSTRIDE (video_box->out_width);
+ Uwidth = GST_VIDEO_I420_U_ROWSTRIDE (video_box->out_width);
+ Vwidth = GST_VIDEO_I420_V_ROWSTRIDE (video_box->out_width);
+
+ Ydest = dest + GST_VIDEO_I420_Y_OFFSET (video_box->out_width,
+ video_box->out_height);
+ Udest = Ydest + GST_VIDEO_I420_U_OFFSET (video_box->out_width,
+ video_box->out_height);
+ Vdest = Ydest + GST_VIDEO_I420_V_OFFSET (video_box->out_width,
+ video_box->out_height);
+
+ Ysize = Ywidth * video_box->out_height;
+ Usize = Uwidth * UVceil (video_box->out_height);
+ Vsize = Vwidth * UVceil (video_box->out_height);
+
+ br = video_box->box_right;
+ bl = video_box->box_left;
+ bt = video_box->box_top;
+ bb = video_box->box_bottom;
+
+ if (br >= 0 && bl >= 0) {
+ rest = Ywidth - video_box->out_width;
+ crop_w = video_box->in_width - (bl + br);
+ } else if (br >= 0 && bl < 0) {
+ rest = Ywidth - video_box->out_width;
+ crop_w = video_box->in_width - (br);
+ } else if (br < 0 && bl >= 0) {
+ rest = Ywidth - video_box->out_width;
+ crop_w = video_box->in_width - (bl);
+ } else if (br < 0 && bl < 0) {
+ rest = Ywidth - video_box->out_width;
+ crop_w = video_box->in_width;
+ }
+
+ if (bb >= 0 && bt >= 0) {
+ crop_h = video_box->in_height - (bb + bt);
+ } else if (bb >= 0 && bt < 0) {
+ crop_h = video_box->in_height - (bb);
+ } else if (bb < 0 && bt >= 0) {
+ crop_h = video_box->in_height - (bt);
+ } else if (bb < 0 && bt < 0) {
+ crop_h = video_box->in_height;
+ }
+
+ Utemp = g_try_malloc0 (Uwidth);
+ Vtemp = g_try_malloc0 (Vwidth);
+
+ GST_DEBUG ("Borders are: L:%d, R:%d, T:%d, B:%d", bl, br, bt, bb);
+
+ GST_DEBUG ("Starting conversion");
+
+ if (crop_h <= 0 || crop_w <= 0) {
+
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], Ysize);
+ oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1], Usize);
+ oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2], Vsize);
+
+ } else {
+
+ gboolean sumbuff = FALSE;
+ guint32 *src_loc1;
+ gint a = 0;
+
+ src_loc1 = (guint32 *) src;
+
+ if (bt < 0) {
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], (-bt) * Ywidth);
+
+ oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1],
+ (UVfloor (-bt) * Uwidth) + 7);
+ oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2],
+ UVfloor (-bt) * Vwidth);
+
+ if ((-bt) % 2 > 0) {
+ oil_splat_u8_ns (Utemp, (guint8 *) & empty_px_values[1], Uwidth);
+ oil_splat_u8_ns (Vtemp, (guint8 *) & empty_px_values[2], Vwidth);
+ sumbuff = TRUE;
+ }
+
+ Ydest += ((-bt) * Ywidth);
+ Udest += (UVfloor (-bt) * Uwidth);
+ Vdest += (UVfloor (-bt) * Vwidth);
+
+ } else {
+ src_loc1 = src_loc1 + (bt * video_box->in_width);
+ }
+
+ if (bl >= 0)
+ src_loc1 += bl;
+
+ GST_DEBUG ("Cropped area");
+ GST_DEBUG ("Ydest value: %d Ywidth: %d", Ydest, Ywidth);
+ GST_DEBUG ("Udest value: %d Uwidth: %d", Udest, Uwidth);
+ GST_DEBUG ("Vdest value: %d Vwidth: %d", Vdest, Vwidth);
+ GST_DEBUG ("Rest: %d", rest);
+ for (i = 0; i < crop_h; i++) {
+
+ a = 0;
+ if (sumbuff) {
+ // left border
+ if (bl < 0) {
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -bl);
+
+ for (j = 0; j < -bl; j++) {
+ Utemp[UVfloor (j)] = (Utemp[UVfloor (j)] + empty_px_values[1]) / 2;
+ Vtemp[UVfloor (j)] = (Vtemp[UVfloor (j)] + empty_px_values[2]) / 2;
+ }
+ Ydest += -bl;
+ a = -bl;
+ }
+
+ for (j = 0; j < crop_w; j++) {
+ // check ARCH
+ Ydest[j] = ((guint8 *) & src_loc1[j])[1];
+ Utemp[UVfloor (a + j)] =
+ (Utemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[2]) / 2;
+ Vtemp[UVfloor (a + j)] =
+ (Vtemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[3]) / 2;
+ }
+ Ydest += crop_w;
+
+ // right border
+ if (br < 0) {
+ a = 0;
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -br);
+ for (j = 0; j < -br; j++) {
+ Utemp[UVfloor (a + crop_w + j)] =
+ (Utemp[UVfloor (a + crop_w + j)] + empty_px_values[1]) / 2;
+ Vtemp[UVfloor (a + crop_w + j)] =
+ (Vtemp[UVfloor (a + crop_w + j)] + empty_px_values[2]) / 2;
+ }
+ Ydest += -br;
+ }
+ oil_copy_u8 (Udest, Utemp, Uwidth);
+ oil_copy_u8 (Vdest, Vtemp, Vwidth);
+ Udest += Uwidth;
+ Vdest += Vwidth;
+ Ydest += rest;
+ gst_video_box_clear (Utemp, Uwidth);
+ gst_video_box_clear (Vtemp, Vwidth);
+ src_loc1 += video_box->in_width;
+ sumbuff = FALSE;
+
+ } else {
+
+ // left border
+ a = 0;
+ if (bl < 0) {
+ //GST_DEBUG("Left border");
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -bl);
+ oil_splat_u8_ns (Vtemp, (guint8 *) & empty_px_values[1],
+ UVceil (-bl));
+ oil_splat_u8_ns (Utemp, (guint8 *) & empty_px_values[2],
+ UVceil (-bl));
+ Ydest += -bl;
+ a = -bl;
+ }
+
+ for (j = 0; j < crop_w; j++) {
+
+ // check ARCH
+ Ydest[j] = ((guint8 *) & src_loc1[j])[1];
+
+ if ((a + j) % 2 > 0) {
+ Utemp[UVfloor (a + j)] =
+ (Utemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[2]) / 2;
+ Vtemp[UVfloor (a + j)] =
+ (Vtemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[3]) / 2;
+ } else {
+ Utemp[UVfloor (a + j)] = ((guint8 *) & src_loc1[j])[2] / 2;
+ Vtemp[UVfloor (a + j)] = ((guint8 *) & src_loc1[j])[3] / 2;
+ }
+ }
+ Ydest += crop_w;
+
+ // right border
+ if (br < 0) {
+ j = 0;
+ if ((a + crop_w) % 2 > 0) {
+ Utemp[UVfloor (a + crop_w)] =
+ (Utemp[UVfloor (a + crop_w)] + empty_px_values[1]) / 2;
+ Vtemp[UVfloor (a + crop_w)] =
+ (Vtemp[UVfloor (a + crop_w)] + empty_px_values[2]) / 2;
+ a++;
+ j = -1;
+ }
+
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -br);
+ oil_splat_u8_ns (&Utemp[UVfloor (a + crop_w)],
+ (guint8 *) & empty_px_values[1], UVceil ((-br) + j));
+ oil_splat_u8_ns (&Vtemp[UVfloor (a + crop_w)],
+ (guint8 *) & empty_px_values[2], UVceil ((-br) + j));
+ Ydest += -br;
+ }
+ Ydest += rest;
+ src_loc1 += video_box->in_width;
+ sumbuff = TRUE;
+
+ }
+ }
+
+ // bottom border
+ if (bb < 0) {
+ a = 0;
+ oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], (-bb) * Ywidth);
+ if (sumbuff) {
+ for (i = 0; i < Uwidth; i++) {
+ Utemp[i] = (Utemp[i] + empty_px_values[1]) / 2;
+ }
+ for (i = 0; i < Vwidth; i++) {
+ Vtemp[i] = (Vtemp[i] + empty_px_values[2]) / 2;
+ }
+
+ oil_copy_u8 (Udest, Utemp, Uwidth);
+ oil_copy_u8 (Vdest, Vtemp, Vwidth);
+ Udest += Uwidth;
+ Vdest += Vwidth;
+ sumbuff = FALSE;
+ a = -1;
+ }
+ oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1],
+ (UVfloor ((-bb))) * Uwidth);
+ oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2],
+ (UVfloor ((-bb))) * Vwidth);
+ }
+ if (sumbuff) {
+ oil_copy_u8 (Udest, Utemp, Uwidth);
+ oil_copy_u8 (Vdest, Vtemp, Vwidth);
+ }
+ }
+
+ GST_LOG ("image created");
+ g_free (Utemp);
+ g_free (Vtemp);
}
-/* Note the source image is always I420, we
- * are converting to AYUV on the fly here */
static void
-gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
+gst_video_box_i420_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
{
guint8 *srcY, *srcU, *srcV;
gint crop_width, crop_width2, crop_height;
@@ -579,7 +948,8 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
gint i, j;
guint8 b_alpha = (guint8) (video_box->border_alpha * 255);
guint8 i_alpha = (guint8) (video_box->alpha * 255);
- guint32 *destp = (guint32 *) dest;
+ guint32 *destp;
+ guint32 *destb = (guint32 *) dest;
guint32 ayuv;
br = video_box->border_right;
@@ -594,11 +964,11 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
src_strideu = GST_VIDEO_I420_U_ROWSTRIDE (video_box->in_width);
src_stridev = GST_VIDEO_I420_V_ROWSTRIDE (video_box->in_width);
- crop_width =
- video_box->in_width - (video_box->crop_left + video_box->crop_right);
+ crop_width = video_box->in_width;
+ crop_width -= (video_box->crop_left + video_box->crop_right);
crop_width2 = crop_width / 2;
- crop_height =
- video_box->in_height - (video_box->crop_top + video_box->crop_bottom);
+ crop_height = video_box->in_height;
+ crop_height -= (video_box->crop_top + video_box->crop_bottom);
srcY =
src + GST_VIDEO_I420_Y_OFFSET (video_box->in_width, video_box->in_height);
@@ -622,10 +992,11 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
if (bt) {
size_t nb_pixels = bt * out_width;
- oil_splat_u32_ns (destp, &ayuv, nb_pixels);
- destp += nb_pixels;
+ oil_splat_u32_ns (destb, &ayuv, nb_pixels);
+ destb += nb_pixels;
}
for (i = 0; i < crop_height; i++) {
+ destp = destb;
/* left border */
if (bl) {
oil_splat_u32_ns (destp, &ayuv, bl);
@@ -652,7 +1023,7 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
srcU += src_strideu - crop_width2;
srcV += src_stridev - crop_width2;
}
- srcY += src_stridey - crop_width;
+ srcY += src_stridey - (crop_width2 * 2);
destp = (guint32 *) dest;
/* right border */
@@ -660,37 +1031,135 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
oil_splat_u32_ns (destp, &ayuv, br);
destp += br;
}
+ destb += out_width;
}
/* bottom border */
if (bb) {
size_t nb_pixels = bb * out_width;
- oil_splat_u32_ns (destp, &ayuv, nb_pixels);
- destp += nb_pixels;
+ oil_splat_u32_ns (destb, &ayuv, nb_pixels);
+ destb += nb_pixels;
}
}
+
+static void
+gst_video_box_i420_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
+{
+ guint8 *srcY, *srcU, *srcV;
+ guint8 *destY, *destU, *destV;
+ gint crop_width, crop_height;
+ gint out_width, out_height;
+ gint src_width, src_height;
+ gint src_stride, dest_stride;
+ gint br, bl, bt, bb;
+
+ br = video_box->border_right;
+ bl = video_box->border_left;
+ bt = video_box->border_top;
+ bb = video_box->border_bottom;
+
+ out_width = video_box->out_width;
+ out_height = video_box->out_height;
+
+ src_width = video_box->in_width;
+ src_height = video_box->in_height;
+
+ crop_width = src_width - (video_box->crop_left + video_box->crop_right);
+ crop_height = src_height - (video_box->crop_top + video_box->crop_bottom);
+
+ /* Y plane */
+ src_stride = GST_VIDEO_I420_Y_ROWSTRIDE (src_width);
+ dest_stride = GST_VIDEO_I420_Y_ROWSTRIDE (out_width);
+
+ destY = dest + GST_VIDEO_I420_Y_OFFSET (out_width, out_height);
+
+ srcY = src + GST_VIDEO_I420_Y_OFFSET (src_width, src_height);
+ srcY += src_stride * video_box->crop_top + video_box->crop_left;
+
+ gst_video_box_copy_plane_i420 (video_box, srcY, destY, br, bl, bt, bb,
+ crop_width, crop_height, src_stride, out_width, dest_stride,
+ yuv_colors_Y[video_box->fill_type]);
+
+ /* U plane */
+ src_stride = GST_VIDEO_I420_U_ROWSTRIDE (src_width);
+ dest_stride = GST_VIDEO_I420_U_ROWSTRIDE (out_width);
+
+ destU = dest + GST_VIDEO_I420_U_OFFSET (out_width, out_height);
+
+ srcU = src + GST_VIDEO_I420_U_OFFSET (src_width, src_height);
+ srcU += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+
+ gst_video_box_copy_plane_i420 (video_box, srcU, destU, br / 2, bl / 2, bt / 2,
+ bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
+ dest_stride, yuv_colors_U[video_box->fill_type]);
+
+ /* V plane */
+ src_stride = GST_VIDEO_I420_V_ROWSTRIDE (src_width);
+ dest_stride = GST_VIDEO_I420_V_ROWSTRIDE (out_width);
+
+ destV = dest + GST_VIDEO_I420_V_OFFSET (out_width, out_height);
+
+ srcV = src + GST_VIDEO_I420_V_OFFSET (src_width, src_height);
+ srcV += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+
+ gst_video_box_copy_plane_i420 (video_box, srcV, destV, br / 2, bl / 2, bt / 2,
+ bb / 2, crop_width / 2, crop_height / 2, src_stride, out_width / 2,
+ dest_stride, yuv_colors_V[video_box->fill_type]);
+}
+
static GstFlowReturn
gst_video_box_transform (GstBaseTransform * trans, GstBuffer * in,
GstBuffer * out)
{
GstVideoBox *video_box;
+ guint8 *indata, *outdata;
video_box = GST_VIDEO_BOX (trans);
- if (video_box->use_alpha) {
- gst_video_box_ayuv (video_box, GST_BUFFER_DATA (in), GST_BUFFER_DATA (out));
- } else {
- gst_video_box_i420 (video_box, GST_BUFFER_DATA (in), GST_BUFFER_DATA (out));
- }
+ indata = GST_BUFFER_DATA (in);
+ outdata = GST_BUFFER_DATA (out);
+ switch (video_box->in_fourcc) {
+ case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
+ switch (video_box->out_fourcc) {
+ case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
+ gst_video_box_ayuv_ayuv (video_box, indata, outdata);
+ break;
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ gst_video_box_ayuv_i420 (video_box, indata, outdata);
+ break;
+ default:
+ goto invalid_format;
+ }
+ break;
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ switch (video_box->out_fourcc) {
+ case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
+ gst_video_box_i420_ayuv (video_box, indata, outdata);
+ break;
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ gst_video_box_i420_i420 (video_box, indata, outdata);
+ break;
+ default:
+ goto invalid_format;
+ }
+ break;
+ default:
+ goto invalid_format;
+ }
return GST_FLOW_OK;
+
+ /* ERRORS */
+invalid_format:
+ {
+ return GST_FLOW_ERROR;
+ }
}
static gboolean
plugin_init (GstPlugin * plugin)
{
-
return gst_element_register (plugin, "videobox", GST_RANK_NONE,
GST_TYPE_VIDEO_BOX);
}