summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu.duponchelle@opencreed.com>2014-05-22 19:46:02 +0200
committerThibault Saunier <tsaunier@gnome.org>2014-06-20 19:53:33 +0200
commit11fa711c34028b816702a748456f97de326b1e91 (patch)
treefc97949ffc385f561aea63da893a4fa85f276879
parent4ce8b409cc30d80c5d6ce949965789036e2269d6 (diff)
downloadgstreamer-plugins-bad-11fa711c34028b816702a748456f97de326b1e91.tar.gz
compositor: Add a new compositor based on the new GstVideoAggregator base class
It is a replacement for videomixer with a similare API Co-Authored by: Thibault Saunier <tsaunier@gnome.org> https://bugzilla.gnome.org/show_bug.cgi?id=731919
-rw-r--r--configure.ac2
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-docs.sgml1
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-sections.txt20
-rw-r--r--gst/compositor/Makefile.am29
-rw-r--r--gst/compositor/blend.c1059
-rw-r--r--gst/compositor/blend.h103
-rw-r--r--gst/compositor/blendorc.h96
-rw-r--r--gst/compositor/compositor.c604
-rw-r--r--gst/compositor/compositor.h86
-rw-r--r--gst/compositor/compositororc-dist.c2400
-rw-r--r--gst/compositor/compositororc-dist.h96
-rw-r--r--gst/compositor/compositororc.orc220
-rw-r--r--gst/compositor/compositorpad.h65
-rw-r--r--tests/check/Makefile.am16
-rw-r--r--tests/check/elements/compositor.c1071
15 files changed, 5867 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 6230f3463..059c85d5c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -430,6 +430,7 @@ AG_GST_CHECK_PLUGIN(aiff)
AG_GST_CHECK_PLUGIN(asfmux)
AG_GST_CHECK_PLUGIN(audiofxbad)
AG_GST_CHECK_PLUGIN(audiomixer)
+AG_GST_CHECK_PLUGIN(compositor)
AG_GST_CHECK_PLUGIN(audiovisualizers)
AG_GST_CHECK_PLUGIN(autoconvert)
AG_GST_CHECK_PLUGIN(bayer)
@@ -3202,6 +3203,7 @@ gst/videosignal/Makefile
gst/vmnc/Makefile
gst/y4m/Makefile
gst/yadif/Makefile
+gst/compositor/Makefile
gst-libs/Makefile
gst-libs/gst/Makefile
gst-libs/gst/basecamerabinsrc/Makefile
diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml
index 72b45083b..2ef594115 100644
--- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml
+++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml
@@ -26,6 +26,7 @@
<xi:include href="xml/element-chromium.xml" />
<xi:include href="xml/element-circle.xml" />
<xi:include href="xml/element-coloreffects.xml" />
+ <xi:include href="xml/element-compositor.xml" />
<xi:include href="xml/element-cvdilate.xml" />
<xi:include href="xml/element-cverode.xml" />
<xi:include href="xml/element-cvequalizehist.xml" />
diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt
index 62b75970c..e42f1b391 100644
--- a/docs/plugins/gst-plugins-bad-plugins-sections.txt
+++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt
@@ -1624,6 +1624,26 @@ GST_IS_GL_TRANSFORMATION_CLASS
GST_TYPE_GL_TRANSFORMATION
</SECTION>
+<SECTION>
+<FILE>element-compositor</FILE>
+<TITLE>compositor</TITLE>
+<SUBSECTION Standard>
+GstCompositorClass
+GstCompositor
+GST_COMPOSITOR
+GST_COMPOSITOR_CLASS
+GST_IS_COMPOSITOR
+GST_IS_COMPOSITOR_CLASS
+GST_TYPE_COMPOSITOR
+GstCompositorPad
+GstCompositorPadClass
+GST_COMPOSITOR_PAD
+GST_COMPOSITOR_PAD_CLASS
+GST_IS_COMPOSITOR_PAD
+GST_IS_COMPOSITOR_PAD_CLASS
+GST_TYPE_COMPOSITOR_PAD
+</SECTION>
+
# gst-libs
<SECTION>
diff --git a/gst/compositor/Makefile.am b/gst/compositor/Makefile.am
new file mode 100644
index 000000000..a91f0fa4f
--- /dev/null
+++ b/gst/compositor/Makefile.am
@@ -0,0 +1,29 @@
+plugin_LTLIBRARIES = libgstcompositor.la
+
+ORC_SOURCE=compositororc
+
+include $(top_srcdir)/common/orc.mak
+
+libgstcompositor_la_SOURCES = \
+ blend.c \
+ compositor.c
+
+
+nodist_libgstcompositor_la_SOURCES = $(ORC_NODIST_SOURCES)
+libgstcompositor_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
+ -I$(top_srcdir)/gst-libs \
+ -I$(top_builddir)/gst-libs \
+ $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS)
+libgstcompositor_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
+ -lgstvideo-@GST_API_VERSION@ \
+ $(top_builddir)/gst-libs/gst/base/libgstbadbase-$(GST_API_VERSION).la \
+ $(top_builddir)/gst-libs/gst/video/libgstbadvideo-$(GST_API_VERSION).la \
+ $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM)
+libgstcompositor_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstcompositor_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
+
+# headers we need but don't want installed
+noinst_HEADERS = \
+ blend.h \
+ compositor.h \
+ compositorpad.h
diff --git a/gst/compositor/blend.c b/gst/compositor/blend.c
new file mode 100644
index 000000000..7fe8e53fd
--- /dev/null
+++ b/gst/compositor/blend.c
@@ -0,0 +1,1059 @@
+/*
+ * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2006 Mindfruit Bv.
+ * Author: Sjoerd Simons <sjoerd@luon.net>
+ * Author: Alex Ugarte <alexugarte@gmail.com>
+ * Copyright (C) 2009 Alex Ugarte <augarte@vicomtech.org>
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "blend.h"
+#include "compositororc.h"
+
+#include <string.h>
+
+#include <gst/video/video.h>
+
+#define BLEND(D,S,alpha) (((D) * (256 - (alpha)) + (S) * (alpha)) >> 8)
+
+GST_DEBUG_CATEGORY_STATIC (gst_compositor_blend_debug);
+#define GST_CAT_DEFAULT gst_compositor_blend_debug
+
+/* Below are the implementations of everything */
+
+/* A32 is for AYUV, ARGB and BGRA */
+#define BLEND_A32(name, method, LOOP) \
+static void \
+method##_ ##name (GstVideoFrame * srcframe, gint xpos, gint ypos, \
+ gdouble src_alpha, GstVideoFrame * destframe) \
+{ \
+ guint s_alpha; \
+ gint src_stride, dest_stride; \
+ gint dest_width, dest_height; \
+ guint8 *src, *dest; \
+ gint src_width, src_height; \
+ \
+ src_width = GST_VIDEO_FRAME_WIDTH (srcframe); \
+ src_height = GST_VIDEO_FRAME_HEIGHT (srcframe); \
+ src = GST_VIDEO_FRAME_PLANE_DATA (srcframe, 0); \
+ src_stride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 0); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (destframe, 0); \
+ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 0); \
+ dest_width = GST_VIDEO_FRAME_COMP_WIDTH (destframe, 0); \
+ dest_height = GST_VIDEO_FRAME_COMP_HEIGHT (destframe, 0); \
+ \
+ s_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+ \
+ /* If it's completely transparent... we just return */ \
+ if (G_UNLIKELY (s_alpha == 0)) \
+ return; \
+ \
+ /* adjust src pointers for negative sizes */ \
+ if (xpos < 0) { \
+ src += -xpos * 4; \
+ src_width -= -xpos; \
+ xpos = 0; \
+ } \
+ if (ypos < 0) { \
+ src += -ypos * src_stride; \
+ src_height -= -ypos; \
+ ypos = 0; \
+ } \
+ /* adjust width/height if the src is bigger than dest */ \
+ if (xpos + src_width > dest_width) { \
+ src_width = dest_width - xpos; \
+ } \
+ if (ypos + src_height > dest_height) { \
+ src_height = dest_height - ypos; \
+ } \
+ \
+ dest = dest + 4 * xpos + (ypos * dest_stride); \
+ \
+ LOOP (dest, src, src_height, src_width, src_stride, dest_stride, s_alpha); \
+}
+
+#define BLEND_A32_LOOP(name, method) \
+static inline void \
+_##method##_loop_##name (guint8 * dest, const guint8 * src, gint src_height, \
+ gint src_width, gint src_stride, gint dest_stride, guint s_alpha) \
+{ \
+ s_alpha = MIN (255, s_alpha); \
+ compositor_orc_##method##_##name (dest, dest_stride, src, src_stride, \
+ s_alpha, src_width, src_height); \
+}
+
+BLEND_A32_LOOP (argb, blend);
+BLEND_A32_LOOP (bgra, blend);
+BLEND_A32_LOOP (argb, overlay);
+BLEND_A32_LOOP (bgra, overlay);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+BLEND_A32 (argb, blend, _blend_loop_argb);
+BLEND_A32 (bgra, blend, _blend_loop_bgra);
+BLEND_A32 (argb, overlay, _overlay_loop_argb);
+BLEND_A32 (bgra, overlay, _overlay_loop_bgra);
+#else
+BLEND_A32 (argb, blend, _blend_loop_bgra);
+BLEND_A32 (bgra, blend, _blend_loop_argb);
+BLEND_A32 (argb, overlay, _overlay_loop_bgra);
+BLEND_A32 (bgra, overlay, _overlay_loop_argb);
+#endif
+
+#define A32_CHECKER_C(name, RGB, A, C1, C2, C3) \
+static void \
+fill_checker_##name##_c (GstVideoFrame * frame) \
+{ \
+ gint i, j; \
+ gint val; \
+ static const gint tab[] = { 80, 160, 80, 160 }; \
+ gint width, height; \
+ guint8 *dest; \
+ \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ \
+ if (!RGB) { \
+ for (i = 0; i < height; i++) { \
+ for (j = 0; j < width; j++) { \
+ dest[A] = 0xff; \
+ dest[C1] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ dest[C2] = 128; \
+ dest[C3] = 128; \
+ dest += 4; \
+ } \
+ } \
+ } else { \
+ for (i = 0; i < height; i++) { \
+ for (j = 0; j < width; j++) { \
+ val = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ dest[A] = 0xFF; \
+ dest[C1] = val; \
+ dest[C2] = val; \
+ dest[C3] = val; \
+ dest += 4; \
+ } \
+ } \
+ } \
+}
+
+A32_CHECKER_C (argb, TRUE, 0, 1, 2, 3);
+A32_CHECKER_C (bgra, TRUE, 3, 2, 1, 0);
+A32_CHECKER_C (ayuv, FALSE, 0, 1, 2, 3);
+
+#define YUV_TO_R(Y,U,V) (CLAMP (1.164 * (Y - 16) + 1.596 * (V - 128), 0, 255))
+#define YUV_TO_G(Y,U,V) (CLAMP (1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128), 0, 255))
+#define YUV_TO_B(Y,U,V) (CLAMP (1.164 * (Y - 16) + 2.018 * (U - 128), 0, 255))
+
+#define A32_COLOR(name, RGB, A, C1, C2, C3) \
+static void \
+fill_color_##name (GstVideoFrame * frame, gint Y, gint U, gint V) \
+{ \
+ gint c1, c2, c3; \
+ guint32 val; \
+ gint width, height; \
+ guint8 *dest; \
+ \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ \
+ if (RGB) { \
+ c1 = YUV_TO_R (Y, U, V); \
+ c2 = YUV_TO_G (Y, U, V); \
+ c3 = YUV_TO_B (Y, U, V); \
+ } else { \
+ c1 = Y; \
+ c2 = U; \
+ c3 = V; \
+ } \
+ val = GUINT32_FROM_BE ((0xff << A) | (c1 << C1) | (c2 << C2) | (c3 << C3)); \
+ \
+ compositor_orc_splat_u32 ((guint32 *) dest, val, height * width); \
+}
+
+A32_COLOR (argb, TRUE, 24, 16, 8, 0);
+A32_COLOR (bgra, TRUE, 0, 8, 16, 24);
+A32_COLOR (abgr, TRUE, 24, 0, 8, 16);
+A32_COLOR (rgba, TRUE, 0, 24, 16, 8);
+A32_COLOR (ayuv, FALSE, 24, 16, 8, 0);
+
+/* Y444, Y42B, I420, YV12, Y41B */
+#define PLANAR_YUV_BLEND(format_name,format_enum,x_round,y_round,MEMCPY,BLENDLOOP) \
+inline static void \
+_blend_##format_name (const guint8 * src, guint8 * dest, \
+ gint src_stride, gint dest_stride, gint src_width, gint src_height, \
+ gdouble src_alpha) \
+{ \
+ gint i; \
+ gint b_alpha; \
+ \
+ /* If it's completely transparent... we just return */ \
+ if (G_UNLIKELY (src_alpha == 0.0)) { \
+ GST_INFO ("Fast copy (alpha == 0.0)"); \
+ return; \
+ } \
+ \
+ /* If it's completely opaque, we do a fast copy */ \
+ if (G_UNLIKELY (src_alpha == 1.0)) { \
+ GST_INFO ("Fast copy (alpha == 1.0)"); \
+ for (i = 0; i < src_height; i++) { \
+ MEMCPY (dest, src, src_width); \
+ src += src_stride; \
+ dest += dest_stride; \
+ } \
+ return; \
+ } \
+ \
+ b_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+ \
+ BLENDLOOP(dest, dest_stride, src, src_stride, b_alpha, src_width, src_height); \
+} \
+\
+static void \
+blend_##format_name (GstVideoFrame * srcframe, gint xpos, gint ypos, \
+ gdouble src_alpha, GstVideoFrame * destframe) \
+{ \
+ const guint8 *b_src; \
+ guint8 *b_dest; \
+ gint b_src_width; \
+ gint b_src_height; \
+ gint xoffset = 0; \
+ gint yoffset = 0; \
+ gint src_comp_rowstride, dest_comp_rowstride; \
+ gint src_comp_height; \
+ gint src_comp_width; \
+ gint comp_ypos, comp_xpos; \
+ gint comp_yoffset, comp_xoffset; \
+ gint dest_width, dest_height; \
+ const GstVideoFormatInfo *info; \
+ gint src_width, src_height; \
+ \
+ src_width = GST_VIDEO_FRAME_WIDTH (srcframe); \
+ src_height = GST_VIDEO_FRAME_HEIGHT (srcframe); \
+ \
+ info = srcframe->info.finfo; \
+ dest_width = GST_VIDEO_FRAME_WIDTH (destframe); \
+ dest_height = GST_VIDEO_FRAME_HEIGHT (destframe); \
+ \
+ xpos = x_round (xpos); \
+ ypos = y_round (ypos); \
+ \
+ b_src_width = src_width; \
+ b_src_height = src_height; \
+ \
+ /* adjust src pointers for negative sizes */ \
+ if (xpos < 0) { \
+ xoffset = -xpos; \
+ b_src_width -= -xpos; \
+ xpos = 0; \
+ } \
+ if (ypos < 0) { \
+ yoffset += -ypos; \
+ b_src_height -= -ypos; \
+ ypos = 0; \
+ } \
+ /* If x or y offset are larger then the source it's outside of the picture */ \
+ if (xoffset > src_width || yoffset > src_height) { \
+ return; \
+ } \
+ \
+ /* adjust width/height if the src is bigger than dest */ \
+ if (xpos + src_width > dest_width) { \
+ b_src_width = dest_width - xpos; \
+ } \
+ if (ypos + src_height > dest_height) { \
+ b_src_height = dest_height - ypos; \
+ } \
+ if (b_src_width < 0 || b_src_height < 0) { \
+ return; \
+ } \
+ \
+ /* First mix Y, then U, then V */ \
+ b_src = GST_VIDEO_FRAME_COMP_DATA (srcframe, 0); \
+ b_dest = GST_VIDEO_FRAME_COMP_DATA (destframe, 0); \
+ src_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 0); \
+ dest_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 0); \
+ src_comp_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info, 0, b_src_width); \
+ src_comp_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info, 0, b_src_height); \
+ comp_xpos = (xpos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 0, xpos); \
+ comp_ypos = (ypos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 0, ypos); \
+ comp_xoffset = (xoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 0, xoffset); \
+ comp_yoffset = (yoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 0, yoffset); \
+ _blend_##format_name (b_src + comp_xoffset + comp_yoffset * src_comp_rowstride, \
+ b_dest + comp_xpos + comp_ypos * dest_comp_rowstride, \
+ src_comp_rowstride, \
+ dest_comp_rowstride, src_comp_width, src_comp_height, \
+ src_alpha); \
+ \
+ b_src = GST_VIDEO_FRAME_COMP_DATA (srcframe, 1); \
+ b_dest = GST_VIDEO_FRAME_COMP_DATA (destframe, 1); \
+ src_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 1); \
+ dest_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 1); \
+ src_comp_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info, 1, b_src_width); \
+ src_comp_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info, 1, b_src_height); \
+ comp_xpos = (xpos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 1, xpos); \
+ comp_ypos = (ypos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 1, ypos); \
+ comp_xoffset = (xoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 1, xoffset); \
+ comp_yoffset = (yoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 1, yoffset); \
+ _blend_##format_name (b_src + comp_xoffset + comp_yoffset * src_comp_rowstride, \
+ b_dest + comp_xpos + comp_ypos * dest_comp_rowstride, \
+ src_comp_rowstride, \
+ dest_comp_rowstride, src_comp_width, src_comp_height, \
+ src_alpha); \
+ \
+ b_src = GST_VIDEO_FRAME_COMP_DATA (srcframe, 2); \
+ b_dest = GST_VIDEO_FRAME_COMP_DATA (destframe, 2); \
+ src_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 2); \
+ dest_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 2); \
+ src_comp_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info, 2, b_src_width); \
+ src_comp_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info, 2, b_src_height); \
+ comp_xpos = (xpos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 2, xpos); \
+ comp_ypos = (ypos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 2, ypos); \
+ comp_xoffset = (xoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 2, xoffset); \
+ comp_yoffset = (yoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 2, yoffset); \
+ _blend_##format_name (b_src + comp_xoffset + comp_yoffset * src_comp_rowstride, \
+ b_dest + comp_xpos + comp_ypos * dest_comp_rowstride, \
+ src_comp_rowstride, \
+ dest_comp_rowstride, src_comp_width, src_comp_height, \
+ src_alpha); \
+}
+
+#define PLANAR_YUV_FILL_CHECKER(format_name, format_enum, MEMSET) \
+static void \
+fill_checker_##format_name (GstVideoFrame * frame) \
+{ \
+ gint i, j; \
+ static const int tab[] = { 80, 160, 80, 160 }; \
+ guint8 *p; \
+ gint comp_width, comp_height; \
+ gint rowstride; \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 0); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ for (j = 0; j < comp_width; j++) { \
+ *p++ = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ } \
+ p += rowstride - comp_width; \
+ } \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 1); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 1); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 1); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, 0x80, comp_width); \
+ p += rowstride; \
+ } \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 2); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 2); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 2); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, 0x80, comp_width); \
+ p += rowstride; \
+ } \
+}
+
+#define PLANAR_YUV_FILL_COLOR(format_name,format_enum,MEMSET) \
+static void \
+fill_color_##format_name (GstVideoFrame * frame, \
+ gint colY, gint colU, gint colV) \
+{ \
+ guint8 *p; \
+ gint comp_width, comp_height; \
+ gint rowstride; \
+ gint i; \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 0); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, colY, comp_width); \
+ p += rowstride; \
+ } \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 1); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 1); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 1); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, colU, comp_width); \
+ p += rowstride; \
+ } \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 2); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 2); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 2); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, colV, comp_width); \
+ p += rowstride; \
+ } \
+}
+
+#define GST_ROUND_UP_1(x) (x)
+
+PLANAR_YUV_BLEND (i420, GST_VIDEO_FORMAT_I420, GST_ROUND_UP_2,
+ GST_ROUND_UP_2, memcpy, compositor_orc_blend_u8);
+PLANAR_YUV_FILL_CHECKER (i420, GST_VIDEO_FORMAT_I420, memset);
+PLANAR_YUV_FILL_COLOR (i420, GST_VIDEO_FORMAT_I420, memset);
+PLANAR_YUV_FILL_COLOR (yv12, GST_VIDEO_FORMAT_YV12, memset);
+PLANAR_YUV_BLEND (y444, GST_VIDEO_FORMAT_Y444, GST_ROUND_UP_1,
+ GST_ROUND_UP_1, memcpy, compositor_orc_blend_u8);
+PLANAR_YUV_FILL_CHECKER (y444, GST_VIDEO_FORMAT_Y444, memset);
+PLANAR_YUV_FILL_COLOR (y444, GST_VIDEO_FORMAT_Y444, memset);
+PLANAR_YUV_BLEND (y42b, GST_VIDEO_FORMAT_Y42B, GST_ROUND_UP_2,
+ GST_ROUND_UP_1, memcpy, compositor_orc_blend_u8);
+PLANAR_YUV_FILL_CHECKER (y42b, GST_VIDEO_FORMAT_Y42B, memset);
+PLANAR_YUV_FILL_COLOR (y42b, GST_VIDEO_FORMAT_Y42B, memset);
+PLANAR_YUV_BLEND (y41b, GST_VIDEO_FORMAT_Y41B, GST_ROUND_UP_4,
+ GST_ROUND_UP_1, memcpy, compositor_orc_blend_u8);
+PLANAR_YUV_FILL_CHECKER (y41b, GST_VIDEO_FORMAT_Y41B, memset);
+PLANAR_YUV_FILL_COLOR (y41b, GST_VIDEO_FORMAT_Y41B, memset);
+
+/* NV12, NV21 */
+#define NV_YUV_BLEND(format_name,MEMCPY,BLENDLOOP) \
+inline static void \
+_blend_##format_name (const guint8 * src, guint8 * dest, \
+ gint src_stride, gint dest_stride, gint src_width, gint src_height, \
+ gdouble src_alpha) \
+{ \
+ gint i; \
+ gint b_alpha; \
+ \
+ /* If it's completely transparent... we just return */ \
+ if (G_UNLIKELY (src_alpha == 0.0)) { \
+ GST_INFO ("Fast copy (alpha == 0.0)"); \
+ return; \
+ } \
+ \
+ /* If it's completely opaque, we do a fast copy */ \
+ if (G_UNLIKELY (src_alpha == 1.0)) { \
+ GST_INFO ("Fast copy (alpha == 1.0)"); \
+ for (i = 0; i < src_height; i++) { \
+ MEMCPY (dest, src, src_width); \
+ src += src_stride; \
+ dest += dest_stride; \
+ } \
+ return; \
+ } \
+ \
+ b_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+ \
+ BLENDLOOP(dest, dest_stride, src, src_stride, b_alpha, src_width, src_height); \
+} \
+\
+static void \
+blend_##format_name (GstVideoFrame * srcframe, gint xpos, gint ypos, \
+ gdouble src_alpha, GstVideoFrame * destframe) \
+{ \
+ const guint8 *b_src; \
+ guint8 *b_dest; \
+ gint b_src_width; \
+ gint b_src_height; \
+ gint xoffset = 0; \
+ gint yoffset = 0; \
+ gint src_comp_rowstride, dest_comp_rowstride; \
+ gint src_comp_height; \
+ gint src_comp_width; \
+ gint comp_ypos, comp_xpos; \
+ gint comp_yoffset, comp_xoffset; \
+ gint dest_width, dest_height; \
+ const GstVideoFormatInfo *info; \
+ gint src_width, src_height; \
+ \
+ src_width = GST_VIDEO_FRAME_WIDTH (srcframe); \
+ src_height = GST_VIDEO_FRAME_HEIGHT (srcframe); \
+ \
+ info = srcframe->info.finfo; \
+ dest_width = GST_VIDEO_FRAME_WIDTH (destframe); \
+ dest_height = GST_VIDEO_FRAME_HEIGHT (destframe); \
+ \
+ xpos = GST_ROUND_UP_2 (xpos); \
+ ypos = GST_ROUND_UP_2 (ypos); \
+ \
+ b_src_width = src_width; \
+ b_src_height = src_height; \
+ \
+ /* adjust src pointers for negative sizes */ \
+ if (xpos < 0) { \
+ xoffset = -xpos; \
+ b_src_width -= -xpos; \
+ xpos = 0; \
+ } \
+ if (ypos < 0) { \
+ yoffset += -ypos; \
+ b_src_height -= -ypos; \
+ ypos = 0; \
+ } \
+ /* If x or y offset are larger then the source it's outside of the picture */ \
+ if (xoffset > src_width || yoffset > src_height) { \
+ return; \
+ } \
+ \
+ /* adjust width/height if the src is bigger than dest */ \
+ if (xpos + src_width > dest_width) { \
+ b_src_width = dest_width - xpos; \
+ } \
+ if (ypos + src_height > dest_height) { \
+ b_src_height = dest_height - ypos; \
+ } \
+ if (b_src_width < 0 || b_src_height < 0) { \
+ return; \
+ } \
+ \
+ /* First mix Y, then UV */ \
+ b_src = GST_VIDEO_FRAME_COMP_DATA (srcframe, 0); \
+ b_dest = GST_VIDEO_FRAME_COMP_DATA (destframe, 0); \
+ src_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 0); \
+ dest_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 0); \
+ src_comp_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info, 0, b_src_width); \
+ src_comp_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info, 0, b_src_height); \
+ comp_xpos = (xpos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 0, xpos); \
+ comp_ypos = (ypos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 0, ypos); \
+ comp_xoffset = (xoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 0, xoffset); \
+ comp_yoffset = (yoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 0, yoffset); \
+ _blend_##format_name (b_src + comp_xoffset + comp_yoffset * src_comp_rowstride, \
+ b_dest + comp_xpos + comp_ypos * dest_comp_rowstride, \
+ src_comp_rowstride, \
+ dest_comp_rowstride, src_comp_width, src_comp_height, \
+ src_alpha); \
+ \
+ b_src = GST_VIDEO_FRAME_PLANE_DATA (srcframe, 1); \
+ b_dest = GST_VIDEO_FRAME_PLANE_DATA (destframe, 1); \
+ src_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 1); \
+ dest_comp_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 1); \
+ src_comp_width = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info, 1, b_src_width); \
+ src_comp_height = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info, 1, b_src_height); \
+ comp_xpos = (xpos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 1, xpos); \
+ comp_ypos = (ypos == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 1, ypos); \
+ comp_xoffset = (xoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (info, 1, xoffset); \
+ comp_yoffset = (yoffset == 0) ? 0 : GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info, 1, yoffset); \
+ _blend_##format_name (b_src + comp_xoffset * 2 + comp_yoffset * src_comp_rowstride, \
+ b_dest + comp_xpos * 2 + comp_ypos * dest_comp_rowstride, \
+ src_comp_rowstride, \
+ dest_comp_rowstride, 2 * src_comp_width, src_comp_height, \
+ src_alpha); \
+}
+
+#define NV_YUV_FILL_CHECKER(format_name, MEMSET) \
+static void \
+fill_checker_##format_name (GstVideoFrame * frame) \
+{ \
+ gint i, j; \
+ static const int tab[] = { 80, 160, 80, 160 }; \
+ guint8 *p; \
+ gint comp_width, comp_height; \
+ gint rowstride; \
+ \
+ p = GST_VIDEO_FRAME_COMP_DATA (frame, 0); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ for (j = 0; j < comp_width; j++) { \
+ *p++ = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ } \
+ p += rowstride - comp_width; \
+ } \
+ \
+ p = GST_VIDEO_FRAME_PLANE_DATA (frame, 1); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 1); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 1); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (p, 0x80, comp_width * 2); \
+ p += rowstride; \
+ } \
+}
+
+#define NV_YUV_FILL_COLOR(format_name,MEMSET) \
+static void \
+fill_color_##format_name (GstVideoFrame * frame, \
+ gint colY, gint colU, gint colV) \
+{ \
+ guint8 *y, *u, *v; \
+ gint comp_width, comp_height; \
+ gint rowstride; \
+ gint i, j; \
+ \
+ y = GST_VIDEO_FRAME_COMP_DATA (frame, 0); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ MEMSET (y, colY, comp_width); \
+ y += rowstride; \
+ } \
+ \
+ u = GST_VIDEO_FRAME_COMP_DATA (frame, 1); \
+ v = GST_VIDEO_FRAME_COMP_DATA (frame, 2); \
+ comp_width = GST_VIDEO_FRAME_COMP_WIDTH (frame, 1); \
+ comp_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 1); \
+ rowstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1); \
+ \
+ for (i = 0; i < comp_height; i++) { \
+ for (j = 0; j < comp_width; j++) { \
+ u[j*2] = colU; \
+ v[j*2] = colV; \
+ } \
+ u += rowstride; \
+ v += rowstride; \
+ } \
+}
+
+NV_YUV_BLEND (nv12, memcpy, compositor_orc_blend_u8);
+NV_YUV_FILL_CHECKER (nv12, memset);
+NV_YUV_FILL_COLOR (nv12, memset);
+NV_YUV_BLEND (nv21, memcpy, compositor_orc_blend_u8);
+NV_YUV_FILL_CHECKER (nv21, memset);
+
+/* RGB, BGR, xRGB, xBGR, RGBx, BGRx */
+
+#define RGB_BLEND(name, bpp, MEMCPY, BLENDLOOP) \
+static void \
+blend_##name (GstVideoFrame * srcframe, gint xpos, gint ypos, \
+ gdouble src_alpha, GstVideoFrame * destframe) \
+{ \
+ gint b_alpha; \
+ gint i; \
+ gint src_stride, dest_stride; \
+ gint dest_width, dest_height; \
+ guint8 *dest, *src; \
+ gint src_width, src_height; \
+ \
+ src_width = GST_VIDEO_FRAME_WIDTH (srcframe); \
+ src_height = GST_VIDEO_FRAME_HEIGHT (srcframe); \
+ \
+ src = GST_VIDEO_FRAME_PLANE_DATA (srcframe, 0); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (destframe, 0); \
+ \
+ dest_width = GST_VIDEO_FRAME_WIDTH (destframe); \
+ dest_height = GST_VIDEO_FRAME_HEIGHT (destframe); \
+ \
+ src_stride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 0); \
+ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 0); \
+ \
+ b_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+ \
+ /* adjust src pointers for negative sizes */ \
+ if (xpos < 0) { \
+ src += -xpos * bpp; \
+ src_width -= -xpos; \
+ xpos = 0; \
+ } \
+ if (ypos < 0) { \
+ src += -ypos * src_stride; \
+ src_height -= -ypos; \
+ ypos = 0; \
+ } \
+ /* adjust width/height if the src is bigger than dest */ \
+ if (xpos + src_width > dest_width) { \
+ src_width = dest_width - xpos; \
+ } \
+ if (ypos + src_height > dest_height) { \
+ src_height = dest_height - ypos; \
+ } \
+ \
+ dest = dest + bpp * xpos + (ypos * dest_stride); \
+ /* If it's completely transparent... we just return */ \
+ if (G_UNLIKELY (src_alpha == 0.0)) { \
+ GST_INFO ("Fast copy (alpha == 0.0)"); \
+ return; \
+ } \
+ \
+ /* If it's completely opaque, we do a fast copy */ \
+ if (G_UNLIKELY (src_alpha == 1.0)) { \
+ GST_INFO ("Fast copy (alpha == 1.0)"); \
+ for (i = 0; i < src_height; i++) { \
+ MEMCPY (dest, src, bpp * src_width); \
+ src += src_stride; \
+ dest += dest_stride; \
+ } \
+ return; \
+ } \
+ \
+ BLENDLOOP(dest, dest_stride, src, src_stride, b_alpha, src_width * bpp, src_height); \
+}
+
+#define RGB_FILL_CHECKER_C(name, bpp, r, g, b) \
+static void \
+fill_checker_##name##_c (GstVideoFrame * frame) \
+{ \
+ gint i, j; \
+ static const int tab[] = { 80, 160, 80, 160 }; \
+ gint stride, dest_add, width, height; \
+ guint8 *dest; \
+ \
+ width = GST_VIDEO_FRAME_WIDTH (frame); \
+ height = GST_VIDEO_FRAME_HEIGHT (frame); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ dest_add = stride - width * bpp; \
+ \
+ for (i = 0; i < height; i++) { \
+ for (j = 0; j < width; j++) { \
+ dest[r] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; /* red */ \
+ dest[g] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; /* green */ \
+ dest[b] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; /* blue */ \
+ dest += bpp; \
+ } \
+ dest += dest_add; \
+ } \
+}
+
+#define RGB_FILL_COLOR(name, bpp, MEMSET_RGB) \
+static void \
+fill_color_##name (GstVideoFrame * frame, \
+ gint colY, gint colU, gint colV) \
+{ \
+ gint red, green, blue; \
+ gint i; \
+ gint dest_stride; \
+ gint width, height; \
+ guint8 *dest; \
+ \
+ width = GST_VIDEO_FRAME_WIDTH (frame); \
+ height = GST_VIDEO_FRAME_HEIGHT (frame); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ \
+ red = YUV_TO_R (colY, colU, colV); \
+ green = YUV_TO_G (colY, colU, colV); \
+ blue = YUV_TO_B (colY, colU, colV); \
+ \
+ for (i = 0; i < height; i++) { \
+ MEMSET_RGB (dest, red, green, blue, width); \
+ dest += dest_stride; \
+ } \
+}
+
+#define MEMSET_RGB_C(name, r, g, b) \
+static inline void \
+_memset_##name##_c (guint8* dest, gint red, gint green, gint blue, gint width) { \
+ gint j; \
+ \
+ for (j = 0; j < width; j++) { \
+ dest[r] = red; \
+ dest[g] = green; \
+ dest[b] = blue; \
+ dest += 3; \
+ } \
+}
+
+#define MEMSET_XRGB(name, r, g, b) \
+static inline void \
+_memset_##name (guint8* dest, gint red, gint green, gint blue, gint width) { \
+ guint32 val; \
+ \
+ val = GUINT32_FROM_BE ((red << r) | (green << g) | (blue << b)); \
+ compositor_orc_splat_u32 ((guint32 *) dest, val, width); \
+}
+
+#define _orc_memcpy_u32(dest,src,len) compositor_orc_memcpy_u32((guint32 *) dest, (const guint32 *) src, len/4)
+
+RGB_BLEND (rgb, 3, memcpy, compositor_orc_blend_u8);
+RGB_FILL_CHECKER_C (rgb, 3, 0, 1, 2);
+MEMSET_RGB_C (rgb, 0, 1, 2);
+RGB_FILL_COLOR (rgb_c, 3, _memset_rgb_c);
+
+MEMSET_RGB_C (bgr, 2, 1, 0);
+RGB_FILL_COLOR (bgr_c, 3, _memset_bgr_c);
+
+RGB_BLEND (xrgb, 4, _orc_memcpy_u32, compositor_orc_blend_u8);
+RGB_FILL_CHECKER_C (xrgb, 4, 1, 2, 3);
+MEMSET_XRGB (xrgb, 24, 16, 0);
+RGB_FILL_COLOR (xrgb, 4, _memset_xrgb);
+
+MEMSET_XRGB (xbgr, 0, 16, 24);
+RGB_FILL_COLOR (xbgr, 4, _memset_xbgr);
+
+MEMSET_XRGB (rgbx, 24, 16, 8);
+RGB_FILL_COLOR (rgbx, 4, _memset_rgbx);
+
+MEMSET_XRGB (bgrx, 8, 16, 24);
+RGB_FILL_COLOR (bgrx, 4, _memset_bgrx);
+
+/* YUY2, YVYU, UYVY */
+
+#define PACKED_422_BLEND(name, MEMCPY, BLENDLOOP) \
+static void \
+blend_##name (GstVideoFrame * srcframe, gint xpos, gint ypos, \
+ gdouble src_alpha, GstVideoFrame * destframe) \
+{ \
+ gint b_alpha; \
+ gint i; \
+ gint src_stride, dest_stride; \
+ gint dest_width, dest_height; \
+ guint8 *src, *dest; \
+ gint src_width, src_height; \
+ \
+ src_width = GST_VIDEO_FRAME_WIDTH (srcframe); \
+ src_height = GST_VIDEO_FRAME_HEIGHT (srcframe); \
+ \
+ dest_width = GST_VIDEO_FRAME_WIDTH (destframe); \
+ dest_height = GST_VIDEO_FRAME_HEIGHT (destframe); \
+ \
+ src = GST_VIDEO_FRAME_PLANE_DATA (srcframe, 0); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (destframe, 0); \
+ \
+ src_stride = GST_VIDEO_FRAME_COMP_STRIDE (srcframe, 0); \
+ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (destframe, 0); \
+ \
+ b_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+ \
+ xpos = GST_ROUND_UP_2 (xpos); \
+ \
+ /* adjust src pointers for negative sizes */ \
+ if (xpos < 0) { \
+ src += -xpos * 2; \
+ src_width -= -xpos; \
+ xpos = 0; \
+ } \
+ if (ypos < 0) { \
+ src += -ypos * src_stride; \
+ src_height -= -ypos; \
+ ypos = 0; \
+ } \
+ \
+ /* adjust width/height if the src is bigger than dest */ \
+ if (xpos + src_width > dest_width) { \
+ src_width = dest_width - xpos; \
+ } \
+ if (ypos + src_height > dest_height) { \
+ src_height = dest_height - ypos; \
+ } \
+ \
+ dest = dest + 2 * xpos + (ypos * dest_stride); \
+ /* If it's completely transparent... we just return */ \
+ if (G_UNLIKELY (src_alpha == 0.0)) { \
+ GST_INFO ("Fast copy (alpha == 0.0)"); \
+ return; \
+ } \
+ \
+ /* If it's completely opaque, we do a fast copy */ \
+ if (G_UNLIKELY (src_alpha == 1.0)) { \
+ GST_INFO ("Fast copy (alpha == 1.0)"); \
+ for (i = 0; i < src_height; i++) { \
+ MEMCPY (dest, src, 2 * src_width); \
+ src += src_stride; \
+ dest += dest_stride; \
+ } \
+ return; \
+ } \
+ \
+ BLENDLOOP(dest, dest_stride, src, src_stride, b_alpha, 2 * src_width, src_height); \
+}
+
+#define PACKED_422_FILL_CHECKER_C(name, Y1, U, Y2, V) \
+static void \
+fill_checker_##name##_c (GstVideoFrame * frame) \
+{ \
+ gint i, j; \
+ static const int tab[] = { 80, 160, 80, 160 }; \
+ gint dest_add; \
+ gint width, height; \
+ guint8 *dest; \
+ \
+ width = GST_VIDEO_FRAME_WIDTH (frame); \
+ width = GST_ROUND_UP_2 (width); \
+ height = GST_VIDEO_FRAME_HEIGHT (frame); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ dest_add = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0) - width * 2; \
+ width /= 2; \
+ \
+ for (i = 0; i < height; i++) { \
+ for (j = 0; j < width; j++) { \
+ dest[Y1] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ dest[Y2] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+ dest[U] = 128; \
+ dest[V] = 128; \
+ dest += 4; \
+ } \
+ dest += dest_add; \
+ } \
+}
+
+#define PACKED_422_FILL_COLOR(name, Y1, U, Y2, V) \
+static void \
+fill_color_##name (GstVideoFrame * frame, \
+ gint colY, gint colU, gint colV) \
+{ \
+ gint i; \
+ gint dest_stride; \
+ guint32 val; \
+ gint width, height; \
+ guint8 *dest; \
+ \
+ width = GST_VIDEO_FRAME_WIDTH (frame); \
+ width = GST_ROUND_UP_2 (width); \
+ height = GST_VIDEO_FRAME_HEIGHT (frame); \
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \
+ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \
+ width /= 2; \
+ \
+ val = GUINT32_FROM_BE ((colY << Y1) | (colY << Y2) | (colU << U) | (colV << V)); \
+ \
+ for (i = 0; i < height; i++) { \
+ compositor_orc_splat_u32 ((guint32 *) dest, val, width); \
+ dest += dest_stride; \
+ } \
+}
+
+PACKED_422_BLEND (yuy2, memcpy, compositor_orc_blend_u8);
+PACKED_422_FILL_CHECKER_C (yuy2, 0, 1, 2, 3);
+PACKED_422_FILL_CHECKER_C (uyvy, 1, 0, 3, 2);
+PACKED_422_FILL_COLOR (yuy2, 24, 16, 8, 0);
+PACKED_422_FILL_COLOR (yvyu, 24, 0, 8, 16);
+PACKED_422_FILL_COLOR (uyvy, 16, 24, 0, 8);
+
+/* Init function */
+BlendFunction gst_compositor_blend_argb;
+BlendFunction gst_compositor_blend_bgra;
+BlendFunction gst_compositor_overlay_argb;
+BlendFunction gst_compositor_overlay_bgra;
+/* AYUV/ABGR is equal to ARGB, RGBA is equal to BGRA */
+BlendFunction gst_compositor_blend_y444;
+BlendFunction gst_compositor_blend_y42b;
+BlendFunction gst_compositor_blend_i420;
+/* I420 is equal to YV12 */
+BlendFunction gst_compositor_blend_nv12;
+BlendFunction gst_compositor_blend_nv21;
+BlendFunction gst_compositor_blend_y41b;
+BlendFunction gst_compositor_blend_rgb;
+/* BGR is equal to RGB */
+BlendFunction gst_compositor_blend_rgbx;
+/* BGRx, xRGB, xBGR are equal to RGBx */
+BlendFunction gst_compositor_blend_yuy2;
+/* YVYU and UYVY are equal to YUY2 */
+
+FillCheckerFunction gst_compositor_fill_checker_argb;
+FillCheckerFunction gst_compositor_fill_checker_bgra;
+/* ABGR is equal to ARGB, RGBA is equal to BGRA */
+FillCheckerFunction gst_compositor_fill_checker_ayuv;
+FillCheckerFunction gst_compositor_fill_checker_y444;
+FillCheckerFunction gst_compositor_fill_checker_y42b;
+FillCheckerFunction gst_compositor_fill_checker_i420;
+/* I420 is equal to YV12 */
+FillCheckerFunction gst_compositor_fill_checker_nv12;
+FillCheckerFunction gst_compositor_fill_checker_nv21;
+FillCheckerFunction gst_compositor_fill_checker_y41b;
+FillCheckerFunction gst_compositor_fill_checker_rgb;
+/* BGR is equal to RGB */
+FillCheckerFunction gst_compositor_fill_checker_xrgb;
+/* BGRx, xRGB, xBGR are equal to RGBx */
+FillCheckerFunction gst_compositor_fill_checker_yuy2;
+/* YVYU is equal to YUY2 */
+FillCheckerFunction gst_compositor_fill_checker_uyvy;
+
+FillColorFunction gst_compositor_fill_color_argb;
+FillColorFunction gst_compositor_fill_color_bgra;
+FillColorFunction gst_compositor_fill_color_abgr;
+FillColorFunction gst_compositor_fill_color_rgba;
+FillColorFunction gst_compositor_fill_color_ayuv;
+FillColorFunction gst_compositor_fill_color_y444;
+FillColorFunction gst_compositor_fill_color_y42b;
+FillColorFunction gst_compositor_fill_color_i420;
+FillColorFunction gst_compositor_fill_color_yv12;
+FillColorFunction gst_compositor_fill_color_nv12;
+/* NV21 is equal to NV12 */
+FillColorFunction gst_compositor_fill_color_y41b;
+FillColorFunction gst_compositor_fill_color_rgb;
+FillColorFunction gst_compositor_fill_color_bgr;
+FillColorFunction gst_compositor_fill_color_xrgb;
+FillColorFunction gst_compositor_fill_color_xbgr;
+FillColorFunction gst_compositor_fill_color_rgbx;
+FillColorFunction gst_compositor_fill_color_bgrx;
+FillColorFunction gst_compositor_fill_color_yuy2;
+FillColorFunction gst_compositor_fill_color_yvyu;
+FillColorFunction gst_compositor_fill_color_uyvy;
+
+void
+gst_compositor_init_blend (void)
+{
+ GST_DEBUG_CATEGORY_INIT (gst_compositor_blend_debug, "compositor_blend", 0,
+ "video compositor blending functions");
+
+ gst_compositor_blend_argb = blend_argb;
+ gst_compositor_blend_bgra = blend_bgra;
+ gst_compositor_overlay_argb = overlay_argb;
+ gst_compositor_overlay_bgra = overlay_bgra;
+ gst_compositor_blend_i420 = blend_i420;
+ gst_compositor_blend_nv12 = blend_nv12;
+ gst_compositor_blend_nv21 = blend_nv21;
+ gst_compositor_blend_y444 = blend_y444;
+ gst_compositor_blend_y42b = blend_y42b;
+ gst_compositor_blend_y41b = blend_y41b;
+ gst_compositor_blend_rgb = blend_rgb;
+ gst_compositor_blend_xrgb = blend_xrgb;
+ gst_compositor_blend_yuy2 = blend_yuy2;
+
+ gst_compositor_fill_checker_argb = fill_checker_argb_c;
+ gst_compositor_fill_checker_bgra = fill_checker_bgra_c;
+ gst_compositor_fill_checker_ayuv = fill_checker_ayuv_c;
+ gst_compositor_fill_checker_i420 = fill_checker_i420;
+ gst_compositor_fill_checker_nv12 = fill_checker_nv12;
+ gst_compositor_fill_checker_nv21 = fill_checker_nv21;
+ gst_compositor_fill_checker_y444 = fill_checker_y444;
+ gst_compositor_fill_checker_y42b = fill_checker_y42b;
+ gst_compositor_fill_checker_y41b = fill_checker_y41b;
+ gst_compositor_fill_checker_rgb = fill_checker_rgb_c;
+ gst_compositor_fill_checker_xrgb = fill_checker_xrgb_c;
+ gst_compositor_fill_checker_yuy2 = fill_checker_yuy2_c;
+ gst_compositor_fill_checker_uyvy = fill_checker_uyvy_c;
+
+ gst_compositor_fill_color_argb = fill_color_argb;
+ gst_compositor_fill_color_bgra = fill_color_bgra;
+ gst_compositor_fill_color_abgr = fill_color_abgr;
+ gst_compositor_fill_color_rgba = fill_color_rgba;
+ gst_compositor_fill_color_ayuv = fill_color_ayuv;
+ gst_compositor_fill_color_i420 = fill_color_i420;
+ gst_compositor_fill_color_yv12 = fill_color_yv12;
+ gst_compositor_fill_color_nv12 = fill_color_nv12;
+ gst_compositor_fill_color_y444 = fill_color_y444;
+ gst_compositor_fill_color_y42b = fill_color_y42b;
+ gst_compositor_fill_color_y41b = fill_color_y41b;
+ gst_compositor_fill_color_rgb = fill_color_rgb_c;
+ gst_compositor_fill_color_bgr = fill_color_bgr_c;
+ gst_compositor_fill_color_xrgb = fill_color_xrgb;
+ gst_compositor_fill_color_xbgr = fill_color_xbgr;
+ gst_compositor_fill_color_rgbx = fill_color_rgbx;
+ gst_compositor_fill_color_bgrx = fill_color_bgrx;
+ gst_compositor_fill_color_yuy2 = fill_color_yuy2;
+ gst_compositor_fill_color_yvyu = fill_color_yvyu;
+ gst_compositor_fill_color_uyvy = fill_color_uyvy;
+}
diff --git a/gst/compositor/blend.h b/gst/compositor/blend.h
new file mode 100644
index 000000000..1cc127c4c
--- /dev/null
+++ b/gst/compositor/blend.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __BLEND_H__
+#define __BLEND_H__
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+typedef void (*BlendFunction) (GstVideoFrame *srcframe, gint xpos, gint ypos, gdouble src_alpha, GstVideoFrame * destframe);
+typedef void (*FillCheckerFunction) (GstVideoFrame * frame);
+typedef void (*FillColorFunction) (GstVideoFrame * frame, gint c1, gint c2, gint c3);
+
+extern BlendFunction gst_compositor_blend_argb;
+extern BlendFunction gst_compositor_blend_bgra;
+#define gst_compositor_blend_ayuv gst_compositor_blend_argb
+#define gst_compositor_blend_abgr gst_compositor_blend_argb
+#define gst_compositor_blend_rgba gst_compositor_blend_bgra
+extern BlendFunction gst_compositor_overlay_argb;
+extern BlendFunction gst_compositor_overlay_bgra;
+#define gst_compositor_overlay_ayuv gst_compositor_overlay_argb
+#define gst_compositor_overlay_abgr gst_compositor_overlay_argb
+#define gst_compositor_overlay_rgba gst_compositor_overlay_bgra
+extern BlendFunction gst_compositor_blend_i420;
+#define gst_compositor_blend_yv12 gst_compositor_blend_i420
+extern BlendFunction gst_compositor_blend_nv12;
+extern BlendFunction gst_compositor_blend_nv21;
+extern BlendFunction gst_compositor_blend_y41b;
+extern BlendFunction gst_compositor_blend_y42b;
+extern BlendFunction gst_compositor_blend_y444;
+extern BlendFunction gst_compositor_blend_rgb;
+#define gst_compositor_blend_bgr gst_compositor_blend_rgb
+extern BlendFunction gst_compositor_blend_rgbx;
+#define gst_compositor_blend_bgrx gst_compositor_blend_rgbx
+#define gst_compositor_blend_xrgb gst_compositor_blend_rgbx
+#define gst_compositor_blend_xbgr gst_compositor_blend_rgbx
+extern BlendFunction gst_compositor_blend_yuy2;
+#define gst_compositor_blend_uyvy gst_compositor_blend_yuy2;
+#define gst_compositor_blend_yvyu gst_compositor_blend_yuy2;
+
+extern FillCheckerFunction gst_compositor_fill_checker_argb;
+#define gst_compositor_fill_checker_abgr gst_compositor_fill_checker_argb
+extern FillCheckerFunction gst_compositor_fill_checker_bgra;
+#define gst_compositor_fill_checker_rgba gst_compositor_fill_checker_bgra
+extern FillCheckerFunction gst_compositor_fill_checker_ayuv;
+extern FillCheckerFunction gst_compositor_fill_checker_i420;
+#define gst_compositor_fill_checker_yv12 gst_compositor_fill_checker_i420
+extern FillCheckerFunction gst_compositor_fill_checker_nv12;
+extern FillCheckerFunction gst_compositor_fill_checker_nv21;
+extern FillCheckerFunction gst_compositor_fill_checker_y41b;
+extern FillCheckerFunction gst_compositor_fill_checker_y42b;
+extern FillCheckerFunction gst_compositor_fill_checker_y444;
+extern FillCheckerFunction gst_compositor_fill_checker_rgb;
+#define gst_compositor_fill_checker_bgr gst_compositor_fill_checker_rgb
+extern FillCheckerFunction gst_compositor_fill_checker_rgbx;
+#define gst_compositor_fill_checker_bgrx gst_compositor_fill_checker_rgbx
+#define gst_compositor_fill_checker_xrgb gst_compositor_fill_checker_rgbx
+#define gst_compositor_fill_checker_xbgr gst_compositor_fill_checker_rgbx
+extern FillCheckerFunction gst_compositor_fill_checker_yuy2;
+#define gst_compositor_fill_checker_yvyu gst_compositor_fill_checker_yuy2;
+extern FillCheckerFunction gst_compositor_fill_checker_uyvy;
+
+extern FillColorFunction gst_compositor_fill_color_argb;
+extern FillColorFunction gst_compositor_fill_color_abgr;
+extern FillColorFunction gst_compositor_fill_color_bgra;
+extern FillColorFunction gst_compositor_fill_color_rgba;
+extern FillColorFunction gst_compositor_fill_color_ayuv;
+extern FillColorFunction gst_compositor_fill_color_i420;
+extern FillColorFunction gst_compositor_fill_color_yv12;
+extern FillColorFunction gst_compositor_fill_color_nv12;
+#define gst_compositor_fill_color_nv21 gst_compositor_fill_color_nv12;
+extern FillColorFunction gst_compositor_fill_color_y41b;
+extern FillColorFunction gst_compositor_fill_color_y42b;
+extern FillColorFunction gst_compositor_fill_color_y444;
+extern FillColorFunction gst_compositor_fill_color_rgb;
+extern FillColorFunction gst_compositor_fill_color_bgr;
+extern FillColorFunction gst_compositor_fill_color_xrgb;
+extern FillColorFunction gst_compositor_fill_color_xbgr;
+extern FillColorFunction gst_compositor_fill_color_rgbx;
+extern FillColorFunction gst_compositor_fill_color_bgrx;
+extern FillColorFunction gst_compositor_fill_color_yuy2;
+extern FillColorFunction gst_compositor_fill_color_yvyu;
+extern FillColorFunction gst_compositor_fill_color_uyvy;
+
+void gst_compositor_init_blend (void);
+
+#endif /* __BLEND_H__ */
diff --git a/gst/compositor/blendorc.h b/gst/compositor/blendorc.h
new file mode 100644
index 000000000..6a39edc7f
--- /dev/null
+++ b/gst/compositor/blendorc.h
@@ -0,0 +1,96 @@
+
+/* autogenerated from blendorc.orc */
+
+#ifndef _BLENDORC_H_
+#define _BLENDORC_H_
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#ifndef _ORC_INTEGER_TYPEDEFS_
+#define _ORC_INTEGER_TYPEDEFS_
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <stdint.h>
+typedef int8_t orc_int8;
+typedef int16_t orc_int16;
+typedef int32_t orc_int32;
+typedef int64_t orc_int64;
+typedef uint8_t orc_uint8;
+typedef uint16_t orc_uint16;
+typedef uint32_t orc_uint32;
+typedef uint64_t orc_uint64;
+#define ORC_UINT64_C(x) UINT64_C(x)
+#elif defined(_MSC_VER)
+typedef signed __int8 orc_int8;
+typedef signed __int16 orc_int16;
+typedef signed __int32 orc_int32;
+typedef signed __int64 orc_int64;
+typedef unsigned __int8 orc_uint8;
+typedef unsigned __int16 orc_uint16;
+typedef unsigned __int32 orc_uint32;
+typedef unsigned __int64 orc_uint64;
+#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
+#else
+#include <limits.h>
+typedef signed char orc_int8;
+typedef short orc_int16;
+typedef int orc_int32;
+typedef unsigned char orc_uint8;
+typedef unsigned short orc_uint16;
+typedef unsigned int orc_uint32;
+#if INT_MAX == LONG_MAX
+typedef long long orc_int64;
+typedef unsigned long long orc_uint64;
+#define ORC_UINT64_C(x) (x##ULL)
+#else
+typedef long orc_int64;
+typedef unsigned long orc_uint64;
+#define ORC_UINT64_C(x) (x##UL)
+#endif
+#endif
+typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
+typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
+typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
+#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+
+#ifndef ORC_INTERNAL
+#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#define ORC_INTERNAL __hidden
+#elif defined (__GNUC__)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#else
+#define ORC_INTERNAL
+#endif
+#endif
+
+void compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
+void compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n);
+void compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/gst/compositor/compositor.c b/gst/compositor/compositor.c
new file mode 100644
index 000000000..805b67454
--- /dev/null
+++ b/gst/compositor/compositor.c
@@ -0,0 +1,604 @@
+/* Video compositor plugin
+ * Copyright (C) 2004, 2008 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2014 Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
+ * Copyright (C) 2014 Thibault Saunier <tsaunier@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:element-compositor
+ *
+ * Compositor can accept AYUV, ARGB and BGRA video streams. For each of the requested
+ * sink pads it will compare the incoming geometry and framerate to define the
+ * output parameters. Indeed output video frames will have the geometry of the
+ * biggest incoming video stream and the framerate of the fastest incoming one.
+ *
+ * Compositor will do colorspace conversion.
+ *
+ * Individual parameters for each input stream can be configured on the
+ * #GstCompositorPad.
+ *
+ * <refsect2>
+ * <title>Sample pipelines</title>
+ * |[
+ * gst-launch-1.0 \
+ * videotestsrc pattern=1 ! \
+ * video/x-raw,format=AYUV,framerate=\(fraction\)10/1,width=100,height=100 ! \
+ * videobox border-alpha=0 top=-70 bottom=-70 right=-220 ! \
+ * compositor name=comp sink_0::alpha=0.7 sink_1::alpha=0.5 ! \
+ * videoconvert ! xvimagesink \
+ * videotestsrc ! \
+ * video/x-raw,format=AYUV,framerate=\(fraction\)5/1,width=320,height=240 ! comp.
+ * ]| A pipeline to demonstrate compositor used together with videobox.
+ * This should show a 320x240 pixels video test source with some transparency
+ * showing the background checker pattern. Another video test source with just
+ * the snow pattern of 100x100 pixels is overlayed on top of the first one on
+ * the left vertically centered with a small transparency showing the first
+ * video test source behind and the checker pattern under it. Note that the
+ * framerate of the output video is 10 frames per second.
+ * |[
+ * gst-launch-1.0 videotestsrc pattern=1 ! \
+ * video/x-raw, framerate=\(fraction\)10/1, width=100, height=100 ! \
+ * compositor name=comp ! videoconvert ! ximagesink \
+ * videotestsrc ! \
+ * video/x-raw, framerate=\(fraction\)5/1, width=320, height=240 ! comp.
+ * ]| A pipeline to demostrate bgra comping. (This does not demonstrate alpha blending).
+ * |[
+ * gst-launch-1.0 videotestsrc pattern=1 ! \
+ * video/x-raw,format =I420, framerate=\(fraction\)10/1, width=100, height=100 ! \
+ * compositor name=comp ! videoconvert ! ximagesink \
+ * videotestsrc ! \
+ * video/x-raw,format=I420, framerate=\(fraction\)5/1, width=320, height=240 ! comp.
+ * ]| A pipeline to test I420
+ * |[
+ * gst-launch-1.0 compositor name=comp sink_1::alpha=0.5 sink_1::xpos=50 sink_1::ypos=50 ! \
+ * videoconvert ! ximagesink \
+ * videotestsrc pattern=snow timestamp-offset=3000000000 ! \
+ * "video/x-raw,format=AYUV,width=640,height=480,framerate=(fraction)30/1" ! \
+ * timeoverlay ! queue2 ! comp. \
+ * videotestsrc pattern=smpte ! \
+ * "video/x-raw,format=AYUV,width=800,height=600,framerate=(fraction)10/1" ! \
+ * timeoverlay ! queue2 ! comp.
+ * ]| A pipeline to demonstrate synchronized compositing (the second stream starts after 3 seconds)
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "compositor.h"
+#include "compositorpad.h"
+
+#ifdef DISABLE_ORC
+#define orc_memset memset
+#else
+#include <orc/orcfunctions.h>
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (gst_compositor_debug);
+#define GST_CAT_DEFAULT gst_compositor_debug
+
+#define FORMATS " { AYUV, BGRA, ARGB, RGBA, ABGR, Y444, Y42B, YUY2, UYVY, "\
+ " YVYU, I420, YV12, NV12, NV21, Y41B, RGB, BGR, xRGB, xBGR, "\
+ " RGBx, BGRx } "
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (FORMATS))
+ );
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%u",
+ GST_PAD_SINK,
+ GST_PAD_REQUEST,
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (FORMATS))
+ );
+
+#define DEFAULT_PAD_ZORDER 0
+#define DEFAULT_PAD_XPOS 0
+#define DEFAULT_PAD_YPOS 0
+#define DEFAULT_PAD_ALPHA 1.0
+enum
+{
+ PROP_PAD_0,
+ PROP_PAD_ZORDER,
+ PROP_PAD_XPOS,
+ PROP_PAD_YPOS,
+ PROP_PAD_ALPHA
+};
+
+G_DEFINE_TYPE (GstCompositorPad, gst_compositor_pad,
+ GST_TYPE_VIDEO_AGGREGATOR_PAD);
+
+static void
+gst_compositor_pad_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstCompositorPad *pad = GST_COMPOSITOR_PAD (object);
+
+ switch (prop_id) {
+ case PROP_PAD_ZORDER:
+ g_value_set_uint (value, pad->zorder);
+ break;
+ case PROP_PAD_XPOS:
+ g_value_set_int (value, pad->xpos);
+ break;
+ case PROP_PAD_YPOS:
+ g_value_set_int (value, pad->ypos);
+ break;
+ case PROP_PAD_ALPHA:
+ g_value_set_double (value, pad->alpha);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_compositor_pad_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstCompositorPad *pad = GST_COMPOSITOR_PAD (object);
+
+ switch (prop_id) {
+ case PROP_PAD_XPOS:
+ pad->xpos = g_value_get_int (value);
+ break;
+ case PROP_PAD_YPOS:
+ pad->ypos = g_value_get_int (value);
+ break;
+ case PROP_PAD_ALPHA:
+ pad->alpha = g_value_get_double (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_compositor_pad_class_init (GstCompositorPadClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ gobject_class->set_property = gst_compositor_pad_set_property;
+ gobject_class->get_property = gst_compositor_pad_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_PAD_XPOS,
+ g_param_spec_int ("xpos", "X Position", "X Position of the picture",
+ G_MININT, G_MAXINT, DEFAULT_PAD_XPOS,
+ G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PAD_YPOS,
+ g_param_spec_int ("ypos", "Y Position", "Y Position of the picture",
+ G_MININT, G_MAXINT, DEFAULT_PAD_YPOS,
+ G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_PAD_ALPHA,
+ g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
+ DEFAULT_PAD_ALPHA,
+ G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+gst_compositor_pad_init (GstCompositorPad * compo_pad)
+{
+ compo_pad->xpos = DEFAULT_PAD_XPOS;
+ compo_pad->ypos = DEFAULT_PAD_YPOS;
+ compo_pad->alpha = DEFAULT_PAD_ALPHA;
+}
+
+
+/* GstCompositor */
+#define DEFAULT_BACKGROUND COMPOSITOR_BACKGROUND_CHECKER
+enum
+{
+ PROP_0,
+ PROP_BACKGROUND
+};
+
+#define GST_TYPE_COMPOSITOR_BACKGROUND (gst_compositor_background_get_type())
+static GType
+gst_compositor_background_get_type (void)
+{
+ static GType compositor_background_type = 0;
+
+ static const GEnumValue compositor_background[] = {
+ {COMPOSITOR_BACKGROUND_CHECKER, "Checker pattern", "checker"},
+ {COMPOSITOR_BACKGROUND_BLACK, "Black", "black"},
+ {COMPOSITOR_BACKGROUND_WHITE, "White", "white"},
+ {COMPOSITOR_BACKGROUND_TRANSPARENT,
+ "Transparent Background to enable further compositing", "transparent"},
+ {0, NULL, NULL},
+ };
+
+ if (!compositor_background_type) {
+ compositor_background_type =
+ g_enum_register_static ("GstCompositorBackground",
+ compositor_background);
+ }
+ return compositor_background_type;
+}
+
+static void
+gst_compositor_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstCompositor *self = GST_COMPOSITOR (object);
+
+ switch (prop_id) {
+ case PROP_BACKGROUND:
+ g_value_set_enum (value, self->background);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_compositor_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstCompositor *self = GST_COMPOSITOR (object);
+
+ switch (prop_id) {
+ case PROP_BACKGROUND:
+ self->background = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+#define gst_compositor_parent_class parent_class
+G_DEFINE_TYPE (GstCompositor, gst_compositor, GST_TYPE_VIDEO_AGGREGATOR);
+
+static gboolean
+set_functions (GstCompositor * self, GstVideoInfo * info)
+{
+ gboolean ret = FALSE;
+
+ self->blend = NULL;
+ self->overlay = NULL;
+ self->fill_checker = NULL;
+ self->fill_color = NULL;
+
+ switch (GST_VIDEO_INFO_FORMAT (info)) {
+ case GST_VIDEO_FORMAT_AYUV:
+ self->blend = gst_compositor_blend_ayuv;
+ self->overlay = gst_compositor_overlay_ayuv;
+ self->fill_checker = gst_compositor_fill_checker_ayuv;
+ self->fill_color = gst_compositor_fill_color_ayuv;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ self->blend = gst_compositor_blend_argb;
+ self->overlay = gst_compositor_overlay_argb;
+ self->fill_checker = gst_compositor_fill_checker_argb;
+ self->fill_color = gst_compositor_fill_color_argb;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ self->blend = gst_compositor_blend_bgra;
+ self->overlay = gst_compositor_overlay_bgra;
+ self->fill_checker = gst_compositor_fill_checker_bgra;
+ self->fill_color = gst_compositor_fill_color_bgra;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ self->blend = gst_compositor_blend_abgr;
+ self->overlay = gst_compositor_overlay_abgr;
+ self->fill_checker = gst_compositor_fill_checker_abgr;
+ self->fill_color = gst_compositor_fill_color_abgr;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ self->blend = gst_compositor_blend_rgba;
+ self->overlay = gst_compositor_overlay_rgba;
+ self->fill_checker = gst_compositor_fill_checker_rgba;
+ self->fill_color = gst_compositor_fill_color_rgba;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_Y444:
+ self->blend = gst_compositor_blend_y444;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_y444;
+ self->fill_color = gst_compositor_fill_color_y444;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_Y42B:
+ self->blend = gst_compositor_blend_y42b;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_y42b;
+ self->fill_color = gst_compositor_fill_color_y42b;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_YUY2:
+ self->blend = gst_compositor_blend_yuy2;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_yuy2;
+ self->fill_color = gst_compositor_fill_color_yuy2;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_UYVY:
+ self->blend = gst_compositor_blend_uyvy;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_uyvy;
+ self->fill_color = gst_compositor_fill_color_uyvy;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_YVYU:
+ self->blend = gst_compositor_blend_yvyu;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_yvyu;
+ self->fill_color = gst_compositor_fill_color_yvyu;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ self->blend = gst_compositor_blend_i420;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_i420;
+ self->fill_color = gst_compositor_fill_color_i420;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_YV12:
+ self->blend = gst_compositor_blend_yv12;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_yv12;
+ self->fill_color = gst_compositor_fill_color_yv12;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ self->blend = gst_compositor_blend_nv12;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_nv12;
+ self->fill_color = gst_compositor_fill_color_nv12;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_NV21:
+ self->blend = gst_compositor_blend_nv21;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_nv21;
+ self->fill_color = gst_compositor_fill_color_nv21;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_Y41B:
+ self->blend = gst_compositor_blend_y41b;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_y41b;
+ self->fill_color = gst_compositor_fill_color_y41b;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_RGB:
+ self->blend = gst_compositor_blend_rgb;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_rgb;
+ self->fill_color = gst_compositor_fill_color_rgb;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_BGR:
+ self->blend = gst_compositor_blend_bgr;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_bgr;
+ self->fill_color = gst_compositor_fill_color_bgr;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_xRGB:
+ self->blend = gst_compositor_blend_xrgb;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_xrgb;
+ self->fill_color = gst_compositor_fill_color_xrgb;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_xBGR:
+ self->blend = gst_compositor_blend_xbgr;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_xbgr;
+ self->fill_color = gst_compositor_fill_color_xbgr;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_RGBx:
+ self->blend = gst_compositor_blend_rgbx;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_rgbx;
+ self->fill_color = gst_compositor_fill_color_rgbx;
+ ret = TRUE;
+ break;
+ case GST_VIDEO_FORMAT_BGRx:
+ self->blend = gst_compositor_blend_bgrx;
+ self->overlay = self->blend;
+ self->fill_checker = gst_compositor_fill_checker_bgrx;
+ self->fill_color = gst_compositor_fill_color_bgrx;
+ ret = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+_update_info (GstVideoAggregator * vagg, GstVideoInfo * info)
+{
+ GList *l;
+ gint best_width = -1, best_height = -1;
+ gboolean ret = FALSE;
+
+ GST_OBJECT_LOCK (vagg);
+ for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
+ GstVideoAggregatorPad *vaggpad = l->data;
+ GstCompositorPad *compositor_pad = GST_COMPOSITOR_PAD (vaggpad);
+ gint this_width, this_height;
+ gint width, height;
+
+ width = GST_VIDEO_INFO_WIDTH (&vaggpad->info);
+ height = GST_VIDEO_INFO_HEIGHT (&vaggpad->info);
+
+ if (width == 0 || height == 0)
+ continue;
+
+ this_width = width + MAX (compositor_pad->xpos, 0);
+ this_height = height + MAX (compositor_pad->ypos, 0);
+
+ if (best_width < this_width)
+ best_width = this_width;
+ if (best_height < this_height)
+ best_height = this_height;
+ }
+ GST_OBJECT_UNLOCK (vagg);
+
+ if (best_width > 0 && best_height > 0) {
+ gst_video_info_set_format (info, GST_VIDEO_INFO_FORMAT (info),
+ best_width, best_height);
+ ret = set_functions (GST_COMPOSITOR (vagg), info);
+ }
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_compositor_aggregate_frames (GstVideoAggregator * vagg, GstBuffer * outbuf)
+{
+ GList *l;
+ GstCompositor *self = GST_COMPOSITOR (vagg);
+ BlendFunction composite;
+ GstVideoFrame out_frame, *outframe;
+
+ if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, GST_MAP_WRITE)) {
+
+ return GST_FLOW_ERROR;
+ }
+
+ outframe = &out_frame;
+ /* default to blending */
+ composite = self->blend;
+ switch (self->background) {
+ case COMPOSITOR_BACKGROUND_CHECKER:
+ self->fill_checker (outframe);
+ break;
+ case COMPOSITOR_BACKGROUND_BLACK:
+ self->fill_color (outframe, 16, 128, 128);
+ break;
+ case COMPOSITOR_BACKGROUND_WHITE:
+ self->fill_color (outframe, 240, 128, 128);
+ break;
+ case COMPOSITOR_BACKGROUND_TRANSPARENT:
+ {
+ guint i, plane, num_planes, height;
+
+ num_planes = GST_VIDEO_FRAME_N_PLANES (outframe);
+ for (plane = 0; plane < num_planes; ++plane) {
+ guint8 *pdata;
+ gsize rowsize, plane_stride;
+
+ pdata = GST_VIDEO_FRAME_PLANE_DATA (outframe, plane);
+ plane_stride = GST_VIDEO_FRAME_PLANE_STRIDE (outframe, plane);
+ rowsize = GST_VIDEO_FRAME_COMP_WIDTH (outframe, plane)
+ * GST_VIDEO_FRAME_COMP_PSTRIDE (outframe, plane);
+ height = GST_VIDEO_FRAME_COMP_HEIGHT (outframe, plane);
+ for (i = 0; i < height; ++i) {
+ memset (pdata, 0, rowsize);
+ pdata += plane_stride;
+ }
+ }
+
+ /* use overlay to keep background transparent */
+ composite = self->overlay;
+ break;
+ }
+ }
+
+ GST_OBJECT_LOCK (vagg);
+ for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) {
+ GstVideoAggregatorPad *pad = l->data;
+ GstCompositorPad *compo_pad = GST_COMPOSITOR_PAD (pad);
+
+ if (pad->aggregated_frame != NULL) {
+ composite (pad->aggregated_frame, compo_pad->xpos, compo_pad->ypos,
+ compo_pad->alpha, outframe);
+ }
+ }
+ GST_OBJECT_UNLOCK (vagg);
+
+ gst_video_frame_unmap (outframe);
+
+ return GST_FLOW_OK;
+}
+
+/* GObject boilerplate */
+static void
+gst_compositor_class_init (GstCompositorClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *gstelement_class = (GstElementClass *) klass;
+ GstVideoAggregatorClass *videoaggregator_class =
+ (GstVideoAggregatorClass *) klass;
+ GstAggregatorClass *agg_class = (GstAggregatorClass *) klass;
+
+ gobject_class->get_property = gst_compositor_get_property;
+ gobject_class->set_property = gst_compositor_set_property;
+
+ agg_class->sinkpads_type = GST_TYPE_COMPOSITOR_PAD;
+ videoaggregator_class->update_info = _update_info;
+ videoaggregator_class->aggregate_frames = gst_compositor_aggregate_frames;
+
+ g_object_class_install_property (gobject_class, PROP_BACKGROUND,
+ g_param_spec_enum ("background", "Background", "Background type",
+ GST_TYPE_COMPOSITOR_BACKGROUND,
+ DEFAULT_BACKGROUND, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ gst_element_class_set_static_metadata (gstelement_class, "Compositor",
+ "Filter/Editor/Video/Compositor",
+ "Composite multiple video streams", "Wim Taymans <wim@fluendo.com>, "
+ "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_compositor_init (GstCompositor * self)
+{
+ self->background = DEFAULT_BACKGROUND;
+ /* initialize variables */
+}
+
+/* Element registration */
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GST_DEBUG_CATEGORY_INIT (gst_compositor_debug, "compositor", 0, "compositor");
+
+ gst_compositor_init_blend ();
+
+ return gst_element_register (plugin, "compositor", GST_RANK_PRIMARY + 1,
+ GST_TYPE_COMPOSITOR);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ compositor,
+ "Compositor", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
+ GST_PACKAGE_ORIGIN)
diff --git a/gst/compositor/compositor.h b/gst/compositor/compositor.h
new file mode 100644
index 000000000..a6b4d9fce
--- /dev/null
+++ b/gst/compositor/compositor.h
@@ -0,0 +1,86 @@
+/* Generic video compositor plugin
+ * Copyright (C) 2008 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_COMPOSITOR_H__
+#define __GST_COMPOSITOR_H__
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideoaggregator.h>
+
+#include "blend.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_COMPOSITOR (gst_compositor_get_type())
+#define GST_COMPOSITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COMPOSITOR, GstCompositor))
+#define GST_COMPOSITOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COMPOSITOR, GstCompositorClass))
+#define GST_IS_COMPOSITOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COMPOSITOR))
+#define GST_IS_COMPOSITOR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COMPOSITOR))
+
+typedef struct _GstCompositor GstCompositor;
+typedef struct _GstCompositorClass GstCompositorClass;
+
+/**
+ * GstcompositorBackground:
+ * @COMPOSITOR_BACKGROUND_CHECKER: checker pattern background
+ * @COMPOSITOR_BACKGROUND_BLACK: solid color black background
+ * @COMPOSITOR_BACKGROUND_WHITE: solid color white background
+ * @COMPOSITOR_BACKGROUND_TRANSPARENT: background is left transparent and layers are composited using "A OVER B" composition rules. This is only applicable to AYUV and ARGB (and variants) as it preserves the alpha channel and allows for further mixing.
+ *
+ * The different backgrounds compositor can blend over.
+ */
+typedef enum
+{
+ COMPOSITOR_BACKGROUND_CHECKER,
+ COMPOSITOR_BACKGROUND_BLACK,
+ COMPOSITOR_BACKGROUND_WHITE,
+ COMPOSITOR_BACKGROUND_TRANSPARENT,
+}
+GstCompositorBackground;
+
+/**
+ * GstCompositor:
+ *
+ * The opaque #GstCompositor structure.
+ */
+struct _GstCompositor
+{
+ GstVideoAggregator videoaggregator;
+ GstCompositorBackground background;
+
+ BlendFunction blend, overlay;
+ FillCheckerFunction fill_checker;
+ FillColorFunction fill_color;
+};
+
+struct _GstCompositorClass
+{
+ GstVideoAggregatorClass parent_class;
+};
+
+GType gst_compositor_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_COMPOSITOR_H__ */
diff --git a/gst/compositor/compositororc-dist.c b/gst/compositor/compositororc-dist.c
new file mode 100644
index 000000000..04d97dd24
--- /dev/null
+++ b/gst/compositor/compositororc-dist.c
@@ -0,0 +1,2400 @@
+
+/* autogenerated from compositororc.orc */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <glib.h>
+
+#ifndef _ORC_INTEGER_TYPEDEFS_
+#define _ORC_INTEGER_TYPEDEFS_
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <stdint.h>
+typedef int8_t orc_int8;
+typedef int16_t orc_int16;
+typedef int32_t orc_int32;
+typedef int64_t orc_int64;
+typedef uint8_t orc_uint8;
+typedef uint16_t orc_uint16;
+typedef uint32_t orc_uint32;
+typedef uint64_t orc_uint64;
+#define ORC_UINT64_C(x) UINT64_C(x)
+#elif defined(_MSC_VER)
+typedef signed __int8 orc_int8;
+typedef signed __int16 orc_int16;
+typedef signed __int32 orc_int32;
+typedef signed __int64 orc_int64;
+typedef unsigned __int8 orc_uint8;
+typedef unsigned __int16 orc_uint16;
+typedef unsigned __int32 orc_uint32;
+typedef unsigned __int64 orc_uint64;
+#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
+#else
+#include <limits.h>
+typedef signed char orc_int8;
+typedef short orc_int16;
+typedef int orc_int32;
+typedef unsigned char orc_uint8;
+typedef unsigned short orc_uint16;
+typedef unsigned int orc_uint32;
+#if INT_MAX == LONG_MAX
+typedef long long orc_int64;
+typedef unsigned long long orc_uint64;
+#define ORC_UINT64_C(x) (x##ULL)
+#else
+typedef long orc_int64;
+typedef unsigned long orc_uint64;
+#define ORC_UINT64_C(x) (x##UL)
+#endif
+#endif
+typedef union
+{
+ orc_int16 i;
+ orc_int8 x2[2];
+} orc_union16;
+typedef union
+{
+ orc_int32 i;
+ float f;
+ orc_int16 x2[2];
+ orc_int8 x4[4];
+} orc_union32;
+typedef union
+{
+ orc_int64 i;
+ double f;
+ orc_int32 x2[2];
+ float x2f[2];
+ orc_int16 x4[4];
+} orc_union64;
+#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+
+#ifndef ORC_INTERNAL
+#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#define ORC_INTERNAL __hidden
+#elif defined (__GNUC__)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#else
+#define ORC_INTERNAL
+#endif
+#endif
+
+
+#ifndef DISABLE_ORC
+#include <orc/orc.h>
+#endif
+void compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
+void compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1,
+ const guint32 * ORC_RESTRICT s1, int n);
+void compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+
+
+/* begin Orc C target preamble */
+#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x)))
+#define ORC_ABS(a) ((a)<0 ? -(a) : (a))
+#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b))
+#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b))
+#define ORC_SB_MAX 127
+#define ORC_SB_MIN (-1-ORC_SB_MAX)
+#define ORC_UB_MAX 255
+#define ORC_UB_MIN 0
+#define ORC_SW_MAX 32767
+#define ORC_SW_MIN (-1-ORC_SW_MAX)
+#define ORC_UW_MAX 65535
+#define ORC_UW_MIN 0
+#define ORC_SL_MAX 2147483647
+#define ORC_SL_MIN (-1-ORC_SL_MAX)
+#define ORC_UL_MAX 4294967295U
+#define ORC_UL_MIN 0
+#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX)
+#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX)
+#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX)
+#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX)
+#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX)
+#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX)
+#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8))
+#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))
+#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56))
+#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset)))
+#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff))
+#define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0))
+#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == 0) ? ORC_UINT64_C(0xfff0000000000000) : ORC_UINT64_C(0xffffffffffffffff)))
+#define ORC_ISNAN_DOUBLE(x) ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == ORC_UINT64_C(0x7ff0000000000000)) && (((x)&ORC_UINT64_C(0x000fffffffffffff)) != 0))
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+/* end Orc C target preamble */
+
+
+
+/* compositor_orc_splat_u32 */
+#ifdef DISABLE_ORC
+void
+compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
+{
+ int i;
+ orc_union32 *ORC_RESTRICT ptr0;
+ orc_union32 var32;
+ orc_union32 var33;
+
+ ptr0 = (orc_union32 *) d1;
+
+ /* 0: loadpl */
+ var32.i = p1;
+
+ for (i = 0; i < n; i++) {
+ /* 1: copyl */
+ var33.i = var32.i;
+ /* 2: storel */
+ ptr0[i] = var33;
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_splat_u32 (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int n = ex->n;
+ orc_union32 *ORC_RESTRICT ptr0;
+ orc_union32 var32;
+ orc_union32 var33;
+
+ ptr0 = (orc_union32 *) ex->arrays[0];
+
+ /* 0: loadpl */
+ var32.i = ex->params[24];
+
+ for (i = 0; i < n; i++) {
+ /* 1: copyl */
+ var33.i = var32.i;
+ /* 2: storel */
+ ptr0[i] = var33;
+ }
+
+}
+
+void
+compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 9, 24, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111, 114,
+ 99, 95, 115, 112, 108, 97, 116, 95, 117, 51, 50, 11, 4, 4, 16, 4,
+ 112, 0, 24, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_splat_u32);
+#else
+ p = orc_program_new ();
+ orc_program_set_name (p, "compositor_orc_splat_u32");
+ orc_program_set_backup_function (p, _backup_compositor_orc_splat_u32);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_parameter (p, 4, "p1");
+
+ orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_memcpy_u32 */
+#ifdef DISABLE_ORC
+void
+compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1,
+ const guint32 * ORC_RESTRICT s1, int n)
+{
+ int i;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union32 var32;
+ orc_union32 var33;
+
+ ptr0 = (orc_union32 *) d1;
+ ptr4 = (orc_union32 *) s1;
+
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var32 = ptr4[i];
+ /* 1: copyl */
+ var33.i = var32.i;
+ /* 2: storel */
+ ptr0[i] = var33;
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_memcpy_u32 (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int n = ex->n;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union32 var32;
+ orc_union32 var33;
+
+ ptr0 = (orc_union32 *) ex->arrays[0];
+ ptr4 = (orc_union32 *) ex->arrays[4];
+
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var32 = ptr4[i];
+ /* 1: copyl */
+ var33.i = var32.i;
+ /* 2: storel */
+ ptr0[i] = var33;
+ }
+
+}
+
+void
+compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1,
+ const guint32 * ORC_RESTRICT s1, int n)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 9, 25, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111, 114,
+ 99, 95, 109, 101, 109, 99, 112, 121, 95, 117, 51, 50, 11, 4, 4, 12,
+ 4, 4, 112, 0, 4, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_memcpy_u32);
+#else
+ p = orc_program_new ();
+ orc_program_set_name (p, "compositor_orc_memcpy_u32");
+ orc_program_set_backup_function (p, _backup_compositor_orc_memcpy_u32);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_source (p, 4, "s1");
+
+ orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_blend_u8 */
+#ifdef DISABLE_ORC
+void
+compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ int i;
+ int j;
+ orc_int8 *ORC_RESTRICT ptr0;
+ const orc_int8 *ORC_RESTRICT ptr4;
+ orc_int8 var34;
+ orc_int8 var35;
+ orc_union16 var36;
+ orc_int8 var37;
+ orc_union16 var38;
+ orc_union16 var39;
+ orc_union16 var40;
+ orc_union16 var41;
+ orc_union16 var42;
+ orc_union16 var43;
+ orc_union16 var44;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
+ ptr4 = ORC_PTR_OFFSET (s1, s1_stride * j);
+
+ /* 5: loadpw */
+ var36.i = p1;
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadb */
+ var34 = ptr0[i];
+ /* 1: convubw */
+ var38.i = (orc_uint8) var34;
+ /* 2: loadb */
+ var35 = ptr4[i];
+ /* 3: convubw */
+ var39.i = (orc_uint8) var35;
+ /* 4: subw */
+ var40.i = var39.i - var38.i;
+ /* 6: mullw */
+ var41.i = (var40.i * var36.i) & 0xffff;
+ /* 7: shlw */
+ var42.i = var38.i << 8;
+ /* 8: addw */
+ var43.i = var42.i + var41.i;
+ /* 9: shruw */
+ var44.i = ((orc_uint16) var43.i) >> 8;
+ /* 10: convsuswb */
+ var37 = ORC_CLAMP_UB (var44.i);
+ /* 11: storeb */
+ ptr0[i] = var37;
+ }
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_blend_u8 (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int j;
+ int n = ex->n;
+ int m = ex->params[ORC_VAR_A1];
+ orc_int8 *ORC_RESTRICT ptr0;
+ const orc_int8 *ORC_RESTRICT ptr4;
+ orc_int8 var34;
+ orc_int8 var35;
+ orc_union16 var36;
+ orc_int8 var37;
+ orc_union16 var38;
+ orc_union16 var39;
+ orc_union16 var40;
+ orc_union16 var41;
+ orc_union16 var42;
+ orc_union16 var43;
+ orc_union16 var44;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
+ ptr4 = ORC_PTR_OFFSET (ex->arrays[4], ex->params[4] * j);
+
+ /* 5: loadpw */
+ var36.i = ex->params[24];
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadb */
+ var34 = ptr0[i];
+ /* 1: convubw */
+ var38.i = (orc_uint8) var34;
+ /* 2: loadb */
+ var35 = ptr4[i];
+ /* 3: convubw */
+ var39.i = (orc_uint8) var35;
+ /* 4: subw */
+ var40.i = var39.i - var38.i;
+ /* 6: mullw */
+ var41.i = (var40.i * var36.i) & 0xffff;
+ /* 7: shlw */
+ var42.i = var38.i << 8;
+ /* 8: addw */
+ var43.i = var42.i + var41.i;
+ /* 9: shruw */
+ var44.i = ((orc_uint16) var43.i) >> 8;
+ /* 10: convsuswb */
+ var37 = ORC_CLAMP_UB (var44.i);
+ /* 11: storeb */
+ ptr0[i] = var37;
+ }
+ }
+
+}
+
+void
+compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 7, 9, 23, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111,
+ 114, 99, 95, 98, 108, 101, 110, 100, 95, 117, 56, 11, 1, 1, 12, 1,
+ 1, 14, 1, 8, 0, 0, 0, 16, 2, 20, 2, 20, 2, 150, 32, 0,
+ 150, 33, 4, 98, 33, 33, 32, 89, 33, 33, 24, 93, 32, 32, 16, 70,
+ 33, 32, 33, 95, 33, 33, 16, 160, 0, 33, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_u8);
+#else
+ p = orc_program_new ();
+ orc_program_set_2d (p);
+ orc_program_set_name (p, "compositor_orc_blend_u8");
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_u8);
+ orc_program_add_destination (p, 1, "d1");
+ orc_program_add_source (p, 1, "s1");
+ orc_program_add_constant (p, 1, 0x00000008, "c1");
+ orc_program_add_parameter (p, 2, "p1");
+ orc_program_add_temporary (p, 2, "t1");
+ orc_program_add_temporary (p, 2, "t2");
+
+ orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 0, ORC_VAR_T2, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "subw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_T1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shlw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_T2,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shruw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_C1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convsuswb", 0, ORC_VAR_D1, ORC_VAR_T2,
+ ORC_VAR_D1, ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ORC_EXECUTOR_M (ex) = m;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_D1] = d1_stride;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+ ex->params[ORC_VAR_S1] = s1_stride;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_blend_argb */
+#ifdef DISABLE_ORC
+void
+compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ int i;
+ int j;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var39;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var40;
+#else
+ orc_union32 var40;
+#endif
+ orc_union32 var41;
+ orc_union16 var42;
+ orc_int8 var43;
+ orc_union32 var44;
+ orc_union64 var45;
+ orc_union64 var46;
+ orc_union64 var47;
+ orc_union64 var48;
+ orc_union32 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union32 var55;
+ orc_union32 var56;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
+ ptr4 = ORC_PTR_OFFSET (s1, s1_stride * j);
+
+ /* 5: loadpw */
+ var39.x4[0] = p1;
+ var39.x4[1] = p1;
+ var39.x4[2] = p1;
+ var39.x4[3] = p1;
+ /* 16: loadpl */
+ var40.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var41 = ptr4[i];
+ /* 1: convlw */
+ var42.i = var41.i;
+ /* 2: convwb */
+ var43 = var42.i;
+ /* 3: splatbl */
+ var44.i =
+ ((var43 & 0xff) << 24) | ((var43 & 0xff) << 16) | ((var43 & 0xff) <<
+ 8) | (var43 & 0xff);
+ /* 4: convubw */
+ var45.x4[0] = (orc_uint8) var44.x4[0];
+ var45.x4[1] = (orc_uint8) var44.x4[1];
+ var45.x4[2] = (orc_uint8) var44.x4[2];
+ var45.x4[3] = (orc_uint8) var44.x4[3];
+ /* 6: mullw */
+ var46.x4[0] = (var45.x4[0] * var39.x4[0]) & 0xffff;
+ var46.x4[1] = (var45.x4[1] * var39.x4[1]) & 0xffff;
+ var46.x4[2] = (var45.x4[2] * var39.x4[2]) & 0xffff;
+ var46.x4[3] = (var45.x4[3] * var39.x4[3]) & 0xffff;
+ /* 7: shruw */
+ var47.x4[0] = ((orc_uint16) var46.x4[0]) >> 8;
+ var47.x4[1] = ((orc_uint16) var46.x4[1]) >> 8;
+ var47.x4[2] = ((orc_uint16) var46.x4[2]) >> 8;
+ var47.x4[3] = ((orc_uint16) var46.x4[3]) >> 8;
+ /* 8: convubw */
+ var48.x4[0] = (orc_uint8) var41.x4[0];
+ var48.x4[1] = (orc_uint8) var41.x4[1];
+ var48.x4[2] = (orc_uint8) var41.x4[2];
+ var48.x4[3] = (orc_uint8) var41.x4[3];
+ /* 9: loadl */
+ var49 = ptr0[i];
+ /* 10: convubw */
+ var50.x4[0] = (orc_uint8) var49.x4[0];
+ var50.x4[1] = (orc_uint8) var49.x4[1];
+ var50.x4[2] = (orc_uint8) var49.x4[2];
+ var50.x4[3] = (orc_uint8) var49.x4[3];
+ /* 11: subw */
+ var51.x4[0] = var48.x4[0] - var50.x4[0];
+ var51.x4[1] = var48.x4[1] - var50.x4[1];
+ var51.x4[2] = var48.x4[2] - var50.x4[2];
+ var51.x4[3] = var48.x4[3] - var50.x4[3];
+ /* 12: mullw */
+ var52.x4[0] = (var51.x4[0] * var47.x4[0]) & 0xffff;
+ var52.x4[1] = (var51.x4[1] * var47.x4[1]) & 0xffff;
+ var52.x4[2] = (var51.x4[2] * var47.x4[2]) & 0xffff;
+ var52.x4[3] = (var51.x4[3] * var47.x4[3]) & 0xffff;
+ /* 13: div255w */
+ var53.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[0] + 128)) +
+ (((orc_uint16) (var52.x4[0] + 128)) >> 8))) >> 8;
+ var53.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[1] + 128)) +
+ (((orc_uint16) (var52.x4[1] + 128)) >> 8))) >> 8;
+ var53.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[2] + 128)) +
+ (((orc_uint16) (var52.x4[2] + 128)) >> 8))) >> 8;
+ var53.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[3] + 128)) +
+ (((orc_uint16) (var52.x4[3] + 128)) >> 8))) >> 8;
+ /* 14: addw */
+ var54.x4[0] = var50.x4[0] + var53.x4[0];
+ var54.x4[1] = var50.x4[1] + var53.x4[1];
+ var54.x4[2] = var50.x4[2] + var53.x4[2];
+ var54.x4[3] = var50.x4[3] + var53.x4[3];
+ /* 15: convwb */
+ var55.x4[0] = var54.x4[0];
+ var55.x4[1] = var54.x4[1];
+ var55.x4[2] = var54.x4[2];
+ var55.x4[3] = var54.x4[3];
+ /* 17: orl */
+ var56.i = var55.i | var40.i;
+ /* 18: storel */
+ ptr0[i] = var56;
+ }
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_blend_argb (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int j;
+ int n = ex->n;
+ int m = ex->params[ORC_VAR_A1];
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var39;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var40;
+#else
+ orc_union32 var40;
+#endif
+ orc_union32 var41;
+ orc_union16 var42;
+ orc_int8 var43;
+ orc_union32 var44;
+ orc_union64 var45;
+ orc_union64 var46;
+ orc_union64 var47;
+ orc_union64 var48;
+ orc_union32 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union32 var55;
+ orc_union32 var56;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
+ ptr4 = ORC_PTR_OFFSET (ex->arrays[4], ex->params[4] * j);
+
+ /* 5: loadpw */
+ var39.x4[0] = ex->params[24];
+ var39.x4[1] = ex->params[24];
+ var39.x4[2] = ex->params[24];
+ var39.x4[3] = ex->params[24];
+ /* 16: loadpl */
+ var40.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var41 = ptr4[i];
+ /* 1: convlw */
+ var42.i = var41.i;
+ /* 2: convwb */
+ var43 = var42.i;
+ /* 3: splatbl */
+ var44.i =
+ ((var43 & 0xff) << 24) | ((var43 & 0xff) << 16) | ((var43 & 0xff) <<
+ 8) | (var43 & 0xff);
+ /* 4: convubw */
+ var45.x4[0] = (orc_uint8) var44.x4[0];
+ var45.x4[1] = (orc_uint8) var44.x4[1];
+ var45.x4[2] = (orc_uint8) var44.x4[2];
+ var45.x4[3] = (orc_uint8) var44.x4[3];
+ /* 6: mullw */
+ var46.x4[0] = (var45.x4[0] * var39.x4[0]) & 0xffff;
+ var46.x4[1] = (var45.x4[1] * var39.x4[1]) & 0xffff;
+ var46.x4[2] = (var45.x4[2] * var39.x4[2]) & 0xffff;
+ var46.x4[3] = (var45.x4[3] * var39.x4[3]) & 0xffff;
+ /* 7: shruw */
+ var47.x4[0] = ((orc_uint16) var46.x4[0]) >> 8;
+ var47.x4[1] = ((orc_uint16) var46.x4[1]) >> 8;
+ var47.x4[2] = ((orc_uint16) var46.x4[2]) >> 8;
+ var47.x4[3] = ((orc_uint16) var46.x4[3]) >> 8;
+ /* 8: convubw */
+ var48.x4[0] = (orc_uint8) var41.x4[0];
+ var48.x4[1] = (orc_uint8) var41.x4[1];
+ var48.x4[2] = (orc_uint8) var41.x4[2];
+ var48.x4[3] = (orc_uint8) var41.x4[3];
+ /* 9: loadl */
+ var49 = ptr0[i];
+ /* 10: convubw */
+ var50.x4[0] = (orc_uint8) var49.x4[0];
+ var50.x4[1] = (orc_uint8) var49.x4[1];
+ var50.x4[2] = (orc_uint8) var49.x4[2];
+ var50.x4[3] = (orc_uint8) var49.x4[3];
+ /* 11: subw */
+ var51.x4[0] = var48.x4[0] - var50.x4[0];
+ var51.x4[1] = var48.x4[1] - var50.x4[1];
+ var51.x4[2] = var48.x4[2] - var50.x4[2];
+ var51.x4[3] = var48.x4[3] - var50.x4[3];
+ /* 12: mullw */
+ var52.x4[0] = (var51.x4[0] * var47.x4[0]) & 0xffff;
+ var52.x4[1] = (var51.x4[1] * var47.x4[1]) & 0xffff;
+ var52.x4[2] = (var51.x4[2] * var47.x4[2]) & 0xffff;
+ var52.x4[3] = (var51.x4[3] * var47.x4[3]) & 0xffff;
+ /* 13: div255w */
+ var53.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[0] + 128)) +
+ (((orc_uint16) (var52.x4[0] + 128)) >> 8))) >> 8;
+ var53.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[1] + 128)) +
+ (((orc_uint16) (var52.x4[1] + 128)) >> 8))) >> 8;
+ var53.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[2] + 128)) +
+ (((orc_uint16) (var52.x4[2] + 128)) >> 8))) >> 8;
+ var53.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var52.x4[3] + 128)) +
+ (((orc_uint16) (var52.x4[3] + 128)) >> 8))) >> 8;
+ /* 14: addw */
+ var54.x4[0] = var50.x4[0] + var53.x4[0];
+ var54.x4[1] = var50.x4[1] + var53.x4[1];
+ var54.x4[2] = var50.x4[2] + var53.x4[2];
+ var54.x4[3] = var50.x4[3] + var53.x4[3];
+ /* 15: convwb */
+ var55.x4[0] = var54.x4[0];
+ var55.x4[1] = var54.x4[1];
+ var55.x4[2] = var54.x4[2];
+ var55.x4[3] = var54.x4[3];
+ /* 17: orl */
+ var56.i = var55.i | var40.i;
+ /* 18: storel */
+ ptr0[i] = var56;
+ }
+ }
+
+}
+
+void
+compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 7, 9, 25, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111,
+ 114, 99, 95, 98, 108, 101, 110, 100, 95, 97, 114, 103, 98, 11, 4, 4,
+ 12, 4, 4, 14, 4, 255, 0, 0, 0, 14, 4, 8, 0, 0, 0, 16,
+ 2, 20, 4, 20, 2, 20, 1, 20, 4, 20, 8, 20, 8, 20, 8, 113,
+ 32, 4, 163, 33, 32, 157, 34, 33, 152, 35, 34, 21, 2, 150, 38, 35,
+ 21, 2, 89, 38, 38, 24, 21, 2, 95, 38, 38, 17, 21, 2, 150, 37,
+ 32, 113, 32, 0, 21, 2, 150, 36, 32, 21, 2, 98, 37, 37, 36, 21,
+ 2, 89, 37, 37, 38, 21, 2, 80, 37, 37, 21, 2, 70, 36, 36, 37,
+ 21, 2, 157, 32, 36, 123, 32, 32, 16, 128, 0, 32, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_argb);
+#else
+ p = orc_program_new ();
+ orc_program_set_2d (p);
+ orc_program_set_name (p, "compositor_orc_blend_argb");
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_argb);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_source (p, 4, "s1");
+ orc_program_add_constant (p, 4, 0x000000ff, "c1");
+ orc_program_add_constant (p, 4, 0x00000008, "c2");
+ orc_program_add_parameter (p, 2, "p1");
+ orc_program_add_temporary (p, 4, "t1");
+ orc_program_add_temporary (p, 2, "t2");
+ orc_program_add_temporary (p, 1, "t3");
+ orc_program_add_temporary (p, 4, "t4");
+ orc_program_add_temporary (p, 8, "t5");
+ orc_program_add_temporary (p, 8, "t6");
+ orc_program_add_temporary (p, 8, "t7");
+
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T7, ORC_VAR_T4, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_P1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shruw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_C2,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T6, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T5, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "subw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T7,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "div255w", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_T6,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T1, ORC_VAR_T5, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "orl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ORC_EXECUTOR_M (ex) = m;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_D1] = d1_stride;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+ ex->params[ORC_VAR_S1] = s1_stride;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_blend_bgra */
+#ifdef DISABLE_ORC
+void
+compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ int i;
+ int j;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var40;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var41;
+#else
+ orc_union32 var41;
+#endif
+ orc_union32 var42;
+ orc_union32 var43;
+ orc_union16 var44;
+ orc_int8 var45;
+ orc_union32 var46;
+ orc_union64 var47;
+ orc_union64 var48;
+ orc_union64 var49;
+ orc_union64 var50;
+ orc_union32 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union64 var55;
+ orc_union64 var56;
+ orc_union32 var57;
+ orc_union32 var58;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
+ ptr4 = ORC_PTR_OFFSET (s1, s1_stride * j);
+
+ /* 6: loadpw */
+ var40.x4[0] = p1;
+ var40.x4[1] = p1;
+ var40.x4[2] = p1;
+ var40.x4[3] = p1;
+ /* 17: loadpl */
+ var41.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var42 = ptr4[i];
+ /* 1: shrul */
+ var43.i = ((orc_uint32) var42.i) >> 24;
+ /* 2: convlw */
+ var44.i = var43.i;
+ /* 3: convwb */
+ var45 = var44.i;
+ /* 4: splatbl */
+ var46.i =
+ ((var45 & 0xff) << 24) | ((var45 & 0xff) << 16) | ((var45 & 0xff) <<
+ 8) | (var45 & 0xff);
+ /* 5: convubw */
+ var47.x4[0] = (orc_uint8) var46.x4[0];
+ var47.x4[1] = (orc_uint8) var46.x4[1];
+ var47.x4[2] = (orc_uint8) var46.x4[2];
+ var47.x4[3] = (orc_uint8) var46.x4[3];
+ /* 7: mullw */
+ var48.x4[0] = (var47.x4[0] * var40.x4[0]) & 0xffff;
+ var48.x4[1] = (var47.x4[1] * var40.x4[1]) & 0xffff;
+ var48.x4[2] = (var47.x4[2] * var40.x4[2]) & 0xffff;
+ var48.x4[3] = (var47.x4[3] * var40.x4[3]) & 0xffff;
+ /* 8: shruw */
+ var49.x4[0] = ((orc_uint16) var48.x4[0]) >> 8;
+ var49.x4[1] = ((orc_uint16) var48.x4[1]) >> 8;
+ var49.x4[2] = ((orc_uint16) var48.x4[2]) >> 8;
+ var49.x4[3] = ((orc_uint16) var48.x4[3]) >> 8;
+ /* 9: convubw */
+ var50.x4[0] = (orc_uint8) var42.x4[0];
+ var50.x4[1] = (orc_uint8) var42.x4[1];
+ var50.x4[2] = (orc_uint8) var42.x4[2];
+ var50.x4[3] = (orc_uint8) var42.x4[3];
+ /* 10: loadl */
+ var51 = ptr0[i];
+ /* 11: convubw */
+ var52.x4[0] = (orc_uint8) var51.x4[0];
+ var52.x4[1] = (orc_uint8) var51.x4[1];
+ var52.x4[2] = (orc_uint8) var51.x4[2];
+ var52.x4[3] = (orc_uint8) var51.x4[3];
+ /* 12: subw */
+ var53.x4[0] = var50.x4[0] - var52.x4[0];
+ var53.x4[1] = var50.x4[1] - var52.x4[1];
+ var53.x4[2] = var50.x4[2] - var52.x4[2];
+ var53.x4[3] = var50.x4[3] - var52.x4[3];
+ /* 13: mullw */
+ var54.x4[0] = (var53.x4[0] * var49.x4[0]) & 0xffff;
+ var54.x4[1] = (var53.x4[1] * var49.x4[1]) & 0xffff;
+ var54.x4[2] = (var53.x4[2] * var49.x4[2]) & 0xffff;
+ var54.x4[3] = (var53.x4[3] * var49.x4[3]) & 0xffff;
+ /* 14: div255w */
+ var55.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[0] + 128)) +
+ (((orc_uint16) (var54.x4[0] + 128)) >> 8))) >> 8;
+ var55.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[1] + 128)) +
+ (((orc_uint16) (var54.x4[1] + 128)) >> 8))) >> 8;
+ var55.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[2] + 128)) +
+ (((orc_uint16) (var54.x4[2] + 128)) >> 8))) >> 8;
+ var55.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[3] + 128)) +
+ (((orc_uint16) (var54.x4[3] + 128)) >> 8))) >> 8;
+ /* 15: addw */
+ var56.x4[0] = var52.x4[0] + var55.x4[0];
+ var56.x4[1] = var52.x4[1] + var55.x4[1];
+ var56.x4[2] = var52.x4[2] + var55.x4[2];
+ var56.x4[3] = var52.x4[3] + var55.x4[3];
+ /* 16: convwb */
+ var57.x4[0] = var56.x4[0];
+ var57.x4[1] = var56.x4[1];
+ var57.x4[2] = var56.x4[2];
+ var57.x4[3] = var56.x4[3];
+ /* 18: orl */
+ var58.i = var57.i | var41.i;
+ /* 19: storel */
+ ptr0[i] = var58;
+ }
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_blend_bgra (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int j;
+ int n = ex->n;
+ int m = ex->params[ORC_VAR_A1];
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var40;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var41;
+#else
+ orc_union32 var41;
+#endif
+ orc_union32 var42;
+ orc_union32 var43;
+ orc_union16 var44;
+ orc_int8 var45;
+ orc_union32 var46;
+ orc_union64 var47;
+ orc_union64 var48;
+ orc_union64 var49;
+ orc_union64 var50;
+ orc_union32 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union64 var55;
+ orc_union64 var56;
+ orc_union32 var57;
+ orc_union32 var58;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
+ ptr4 = ORC_PTR_OFFSET (ex->arrays[4], ex->params[4] * j);
+
+ /* 6: loadpw */
+ var40.x4[0] = ex->params[24];
+ var40.x4[1] = ex->params[24];
+ var40.x4[2] = ex->params[24];
+ var40.x4[3] = ex->params[24];
+ /* 17: loadpl */
+ var41.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var42 = ptr4[i];
+ /* 1: shrul */
+ var43.i = ((orc_uint32) var42.i) >> 24;
+ /* 2: convlw */
+ var44.i = var43.i;
+ /* 3: convwb */
+ var45 = var44.i;
+ /* 4: splatbl */
+ var46.i =
+ ((var45 & 0xff) << 24) | ((var45 & 0xff) << 16) | ((var45 & 0xff) <<
+ 8) | (var45 & 0xff);
+ /* 5: convubw */
+ var47.x4[0] = (orc_uint8) var46.x4[0];
+ var47.x4[1] = (orc_uint8) var46.x4[1];
+ var47.x4[2] = (orc_uint8) var46.x4[2];
+ var47.x4[3] = (orc_uint8) var46.x4[3];
+ /* 7: mullw */
+ var48.x4[0] = (var47.x4[0] * var40.x4[0]) & 0xffff;
+ var48.x4[1] = (var47.x4[1] * var40.x4[1]) & 0xffff;
+ var48.x4[2] = (var47.x4[2] * var40.x4[2]) & 0xffff;
+ var48.x4[3] = (var47.x4[3] * var40.x4[3]) & 0xffff;
+ /* 8: shruw */
+ var49.x4[0] = ((orc_uint16) var48.x4[0]) >> 8;
+ var49.x4[1] = ((orc_uint16) var48.x4[1]) >> 8;
+ var49.x4[2] = ((orc_uint16) var48.x4[2]) >> 8;
+ var49.x4[3] = ((orc_uint16) var48.x4[3]) >> 8;
+ /* 9: convubw */
+ var50.x4[0] = (orc_uint8) var42.x4[0];
+ var50.x4[1] = (orc_uint8) var42.x4[1];
+ var50.x4[2] = (orc_uint8) var42.x4[2];
+ var50.x4[3] = (orc_uint8) var42.x4[3];
+ /* 10: loadl */
+ var51 = ptr0[i];
+ /* 11: convubw */
+ var52.x4[0] = (orc_uint8) var51.x4[0];
+ var52.x4[1] = (orc_uint8) var51.x4[1];
+ var52.x4[2] = (orc_uint8) var51.x4[2];
+ var52.x4[3] = (orc_uint8) var51.x4[3];
+ /* 12: subw */
+ var53.x4[0] = var50.x4[0] - var52.x4[0];
+ var53.x4[1] = var50.x4[1] - var52.x4[1];
+ var53.x4[2] = var50.x4[2] - var52.x4[2];
+ var53.x4[3] = var50.x4[3] - var52.x4[3];
+ /* 13: mullw */
+ var54.x4[0] = (var53.x4[0] * var49.x4[0]) & 0xffff;
+ var54.x4[1] = (var53.x4[1] * var49.x4[1]) & 0xffff;
+ var54.x4[2] = (var53.x4[2] * var49.x4[2]) & 0xffff;
+ var54.x4[3] = (var53.x4[3] * var49.x4[3]) & 0xffff;
+ /* 14: div255w */
+ var55.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[0] + 128)) +
+ (((orc_uint16) (var54.x4[0] + 128)) >> 8))) >> 8;
+ var55.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[1] + 128)) +
+ (((orc_uint16) (var54.x4[1] + 128)) >> 8))) >> 8;
+ var55.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[2] + 128)) +
+ (((orc_uint16) (var54.x4[2] + 128)) >> 8))) >> 8;
+ var55.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var54.x4[3] + 128)) +
+ (((orc_uint16) (var54.x4[3] + 128)) >> 8))) >> 8;
+ /* 15: addw */
+ var56.x4[0] = var52.x4[0] + var55.x4[0];
+ var56.x4[1] = var52.x4[1] + var55.x4[1];
+ var56.x4[2] = var52.x4[2] + var55.x4[2];
+ var56.x4[3] = var52.x4[3] + var55.x4[3];
+ /* 16: convwb */
+ var57.x4[0] = var56.x4[0];
+ var57.x4[1] = var56.x4[1];
+ var57.x4[2] = var56.x4[2];
+ var57.x4[3] = var56.x4[3];
+ /* 18: orl */
+ var58.i = var57.i | var41.i;
+ /* 19: storel */
+ ptr0[i] = var58;
+ }
+ }
+
+}
+
+void
+compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 7, 9, 25, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111,
+ 114, 99, 95, 98, 108, 101, 110, 100, 95, 98, 103, 114, 97, 11, 4, 4,
+ 12, 4, 4, 14, 4, 0, 0, 0, 255, 14, 4, 24, 0, 0, 0, 14,
+ 4, 8, 0, 0, 0, 16, 2, 20, 4, 20, 4, 20, 2, 20, 1, 20,
+ 4, 20, 8, 20, 8, 20, 8, 113, 32, 4, 126, 33, 32, 17, 163, 34,
+ 33, 157, 35, 34, 152, 36, 35, 21, 2, 150, 39, 36, 21, 2, 89, 39,
+ 39, 24, 21, 2, 95, 39, 39, 18, 21, 2, 150, 38, 32, 113, 32, 0,
+ 21, 2, 150, 37, 32, 21, 2, 98, 38, 38, 37, 21, 2, 89, 38, 38,
+ 39, 21, 2, 80, 38, 38, 21, 2, 70, 37, 37, 38, 21, 2, 157, 32,
+ 37, 123, 32, 32, 16, 128, 0, 32, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_bgra);
+#else
+ p = orc_program_new ();
+ orc_program_set_2d (p);
+ orc_program_set_name (p, "compositor_orc_blend_bgra");
+ orc_program_set_backup_function (p, _backup_compositor_orc_blend_bgra);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_source (p, 4, "s1");
+ orc_program_add_constant (p, 4, 0xff000000, "c1");
+ orc_program_add_constant (p, 4, 0x00000018, "c2");
+ orc_program_add_constant (p, 4, 0x00000008, "c3");
+ orc_program_add_parameter (p, 2, "p1");
+ orc_program_add_temporary (p, 4, "t1");
+ orc_program_add_temporary (p, 4, "t2");
+ orc_program_add_temporary (p, 2, "t3");
+ orc_program_add_temporary (p, 1, "t4");
+ orc_program_add_temporary (p, 4, "t5");
+ orc_program_add_temporary (p, 8, "t6");
+ orc_program_add_temporary (p, 8, "t7");
+ orc_program_add_temporary (p, 8, "t8");
+
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shrul", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_C2,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T5, ORC_VAR_T4, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T8, ORC_VAR_T5, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_P1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shruw", 2, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_C3,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T7, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T6, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "subw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_T6,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_T8,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "div255w", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T7,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T1, ORC_VAR_T6, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "orl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ORC_EXECUTOR_M (ex) = m;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_D1] = d1_stride;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+ ex->params[ORC_VAR_S1] = s1_stride;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_overlay_argb */
+#ifdef DISABLE_ORC
+void
+compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ int i;
+ int j;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var41;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var42;
+#else
+ orc_union32 var42;
+#endif
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var43;
+#else
+ orc_union32 var43;
+#endif
+ orc_union32 var44;
+ orc_union16 var45;
+ orc_int8 var46;
+ orc_union32 var47;
+ orc_union64 var48;
+ orc_union64 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union32 var53;
+ orc_union64 var54;
+ orc_union64 var55;
+ orc_union32 var56;
+ orc_union16 var57;
+ orc_int8 var58;
+ orc_union32 var59;
+ orc_union64 var60;
+ orc_union64 var61;
+ orc_union64 var62;
+ orc_union64 var63;
+ orc_union64 var64;
+ orc_union64 var65;
+ orc_union64 var66;
+ orc_union64 var67;
+ orc_union32 var68;
+ orc_union32 var69;
+ orc_union32 var70;
+ orc_union32 var71;
+ orc_union32 var72;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
+ ptr4 = ORC_PTR_OFFSET (s1, s1_stride * j);
+
+ /* 5: loadpw */
+ var41.x4[0] = p1;
+ var41.x4[1] = p1;
+ var41.x4[2] = p1;
+ var41.x4[3] = p1;
+ /* 10: loadpl */
+ var53.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
+ /* 26: loadpl */
+ var42.i = (int) 0xffffff00; /* -256 or 2.122e-314f */
+ /* 29: loadpl */
+ var43.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var44 = ptr4[i];
+ /* 1: convlw */
+ var45.i = var44.i;
+ /* 2: convwb */
+ var46 = var45.i;
+ /* 3: splatbl */
+ var47.i =
+ ((var46 & 0xff) << 24) | ((var46 & 0xff) << 16) | ((var46 & 0xff) <<
+ 8) | (var46 & 0xff);
+ /* 4: convubw */
+ var48.x4[0] = (orc_uint8) var47.x4[0];
+ var48.x4[1] = (orc_uint8) var47.x4[1];
+ var48.x4[2] = (orc_uint8) var47.x4[2];
+ var48.x4[3] = (orc_uint8) var47.x4[3];
+ /* 6: mullw */
+ var49.x4[0] = (var48.x4[0] * var41.x4[0]) & 0xffff;
+ var49.x4[1] = (var48.x4[1] * var41.x4[1]) & 0xffff;
+ var49.x4[2] = (var48.x4[2] * var41.x4[2]) & 0xffff;
+ var49.x4[3] = (var48.x4[3] * var41.x4[3]) & 0xffff;
+ /* 7: shruw */
+ var50.x4[0] = ((orc_uint16) var49.x4[0]) >> 8;
+ var50.x4[1] = ((orc_uint16) var49.x4[1]) >> 8;
+ var50.x4[2] = ((orc_uint16) var49.x4[2]) >> 8;
+ var50.x4[3] = ((orc_uint16) var49.x4[3]) >> 8;
+ /* 8: convubw */
+ var51.x4[0] = (orc_uint8) var44.x4[0];
+ var51.x4[1] = (orc_uint8) var44.x4[1];
+ var51.x4[2] = (orc_uint8) var44.x4[2];
+ var51.x4[3] = (orc_uint8) var44.x4[3];
+ /* 9: mullw */
+ var52.x4[0] = (var51.x4[0] * var50.x4[0]) & 0xffff;
+ var52.x4[1] = (var51.x4[1] * var50.x4[1]) & 0xffff;
+ var52.x4[2] = (var51.x4[2] * var50.x4[2]) & 0xffff;
+ var52.x4[3] = (var51.x4[3] * var50.x4[3]) & 0xffff;
+ /* 11: convubw */
+ var54.x4[0] = (orc_uint8) var53.x4[0];
+ var54.x4[1] = (orc_uint8) var53.x4[1];
+ var54.x4[2] = (orc_uint8) var53.x4[2];
+ var54.x4[3] = (orc_uint8) var53.x4[3];
+ /* 12: subw */
+ var55.x4[0] = var54.x4[0] - var50.x4[0];
+ var55.x4[1] = var54.x4[1] - var50.x4[1];
+ var55.x4[2] = var54.x4[2] - var50.x4[2];
+ var55.x4[3] = var54.x4[3] - var50.x4[3];
+ /* 13: loadl */
+ var56 = ptr0[i];
+ /* 14: convlw */
+ var57.i = var56.i;
+ /* 15: convwb */
+ var58 = var57.i;
+ /* 16: splatbl */
+ var59.i =
+ ((var58 & 0xff) << 24) | ((var58 & 0xff) << 16) | ((var58 & 0xff) <<
+ 8) | (var58 & 0xff);
+ /* 17: convubw */
+ var60.x4[0] = (orc_uint8) var59.x4[0];
+ var60.x4[1] = (orc_uint8) var59.x4[1];
+ var60.x4[2] = (orc_uint8) var59.x4[2];
+ var60.x4[3] = (orc_uint8) var59.x4[3];
+ /* 18: mullw */
+ var61.x4[0] = (var60.x4[0] * var55.x4[0]) & 0xffff;
+ var61.x4[1] = (var60.x4[1] * var55.x4[1]) & 0xffff;
+ var61.x4[2] = (var60.x4[2] * var55.x4[2]) & 0xffff;
+ var61.x4[3] = (var60.x4[3] * var55.x4[3]) & 0xffff;
+ /* 19: div255w */
+ var62.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[0] + 128)) +
+ (((orc_uint16) (var61.x4[0] + 128)) >> 8))) >> 8;
+ var62.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[1] + 128)) +
+ (((orc_uint16) (var61.x4[1] + 128)) >> 8))) >> 8;
+ var62.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[2] + 128)) +
+ (((orc_uint16) (var61.x4[2] + 128)) >> 8))) >> 8;
+ var62.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[3] + 128)) +
+ (((orc_uint16) (var61.x4[3] + 128)) >> 8))) >> 8;
+ /* 20: convubw */
+ var63.x4[0] = (orc_uint8) var56.x4[0];
+ var63.x4[1] = (orc_uint8) var56.x4[1];
+ var63.x4[2] = (orc_uint8) var56.x4[2];
+ var63.x4[3] = (orc_uint8) var56.x4[3];
+ /* 21: mullw */
+ var64.x4[0] = (var63.x4[0] * var62.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var62.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var62.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var62.x4[3]) & 0xffff;
+ /* 22: addw */
+ var65.x4[0] = var64.x4[0] + var52.x4[0];
+ var65.x4[1] = var64.x4[1] + var52.x4[1];
+ var65.x4[2] = var64.x4[2] + var52.x4[2];
+ var65.x4[3] = var64.x4[3] + var52.x4[3];
+ /* 23: addw */
+ var66.x4[0] = var62.x4[0] + var50.x4[0];
+ var66.x4[1] = var62.x4[1] + var50.x4[1];
+ var66.x4[2] = var62.x4[2] + var50.x4[2];
+ var66.x4[3] = var62.x4[3] + var50.x4[3];
+ /* 24: divluw */
+ var67.x4[0] =
+ ((var66.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[0]) /
+ ((orc_uint16) var66.x4[0] & 0xff));
+ var67.x4[1] =
+ ((var66.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[1]) /
+ ((orc_uint16) var66.x4[1] & 0xff));
+ var67.x4[2] =
+ ((var66.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[2]) /
+ ((orc_uint16) var66.x4[2] & 0xff));
+ var67.x4[3] =
+ ((var66.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[3]) /
+ ((orc_uint16) var66.x4[3] & 0xff));
+ /* 25: convwb */
+ var68.x4[0] = var67.x4[0];
+ var68.x4[1] = var67.x4[1];
+ var68.x4[2] = var67.x4[2];
+ var68.x4[3] = var67.x4[3];
+ /* 27: andl */
+ var69.i = var68.i & var42.i;
+ /* 28: convwb */
+ var70.x4[0] = var66.x4[0];
+ var70.x4[1] = var66.x4[1];
+ var70.x4[2] = var66.x4[2];
+ var70.x4[3] = var66.x4[3];
+ /* 30: andl */
+ var71.i = var70.i & var43.i;
+ /* 31: orl */
+ var72.i = var69.i | var71.i;
+ /* 32: storel */
+ ptr0[i] = var72;
+ }
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_overlay_argb (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int j;
+ int n = ex->n;
+ int m = ex->params[ORC_VAR_A1];
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var41;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var42;
+#else
+ orc_union32 var42;
+#endif
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var43;
+#else
+ orc_union32 var43;
+#endif
+ orc_union32 var44;
+ orc_union16 var45;
+ orc_int8 var46;
+ orc_union32 var47;
+ orc_union64 var48;
+ orc_union64 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union32 var53;
+ orc_union64 var54;
+ orc_union64 var55;
+ orc_union32 var56;
+ orc_union16 var57;
+ orc_int8 var58;
+ orc_union32 var59;
+ orc_union64 var60;
+ orc_union64 var61;
+ orc_union64 var62;
+ orc_union64 var63;
+ orc_union64 var64;
+ orc_union64 var65;
+ orc_union64 var66;
+ orc_union64 var67;
+ orc_union32 var68;
+ orc_union32 var69;
+ orc_union32 var70;
+ orc_union32 var71;
+ orc_union32 var72;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
+ ptr4 = ORC_PTR_OFFSET (ex->arrays[4], ex->params[4] * j);
+
+ /* 5: loadpw */
+ var41.x4[0] = ex->params[24];
+ var41.x4[1] = ex->params[24];
+ var41.x4[2] = ex->params[24];
+ var41.x4[3] = ex->params[24];
+ /* 10: loadpl */
+ var53.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
+ /* 26: loadpl */
+ var42.i = (int) 0xffffff00; /* -256 or 2.122e-314f */
+ /* 29: loadpl */
+ var43.i = (int) 0x000000ff; /* 255 or 1.25987e-321f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var44 = ptr4[i];
+ /* 1: convlw */
+ var45.i = var44.i;
+ /* 2: convwb */
+ var46 = var45.i;
+ /* 3: splatbl */
+ var47.i =
+ ((var46 & 0xff) << 24) | ((var46 & 0xff) << 16) | ((var46 & 0xff) <<
+ 8) | (var46 & 0xff);
+ /* 4: convubw */
+ var48.x4[0] = (orc_uint8) var47.x4[0];
+ var48.x4[1] = (orc_uint8) var47.x4[1];
+ var48.x4[2] = (orc_uint8) var47.x4[2];
+ var48.x4[3] = (orc_uint8) var47.x4[3];
+ /* 6: mullw */
+ var49.x4[0] = (var48.x4[0] * var41.x4[0]) & 0xffff;
+ var49.x4[1] = (var48.x4[1] * var41.x4[1]) & 0xffff;
+ var49.x4[2] = (var48.x4[2] * var41.x4[2]) & 0xffff;
+ var49.x4[3] = (var48.x4[3] * var41.x4[3]) & 0xffff;
+ /* 7: shruw */
+ var50.x4[0] = ((orc_uint16) var49.x4[0]) >> 8;
+ var50.x4[1] = ((orc_uint16) var49.x4[1]) >> 8;
+ var50.x4[2] = ((orc_uint16) var49.x4[2]) >> 8;
+ var50.x4[3] = ((orc_uint16) var49.x4[3]) >> 8;
+ /* 8: convubw */
+ var51.x4[0] = (orc_uint8) var44.x4[0];
+ var51.x4[1] = (orc_uint8) var44.x4[1];
+ var51.x4[2] = (orc_uint8) var44.x4[2];
+ var51.x4[3] = (orc_uint8) var44.x4[3];
+ /* 9: mullw */
+ var52.x4[0] = (var51.x4[0] * var50.x4[0]) & 0xffff;
+ var52.x4[1] = (var51.x4[1] * var50.x4[1]) & 0xffff;
+ var52.x4[2] = (var51.x4[2] * var50.x4[2]) & 0xffff;
+ var52.x4[3] = (var51.x4[3] * var50.x4[3]) & 0xffff;
+ /* 11: convubw */
+ var54.x4[0] = (orc_uint8) var53.x4[0];
+ var54.x4[1] = (orc_uint8) var53.x4[1];
+ var54.x4[2] = (orc_uint8) var53.x4[2];
+ var54.x4[3] = (orc_uint8) var53.x4[3];
+ /* 12: subw */
+ var55.x4[0] = var54.x4[0] - var50.x4[0];
+ var55.x4[1] = var54.x4[1] - var50.x4[1];
+ var55.x4[2] = var54.x4[2] - var50.x4[2];
+ var55.x4[3] = var54.x4[3] - var50.x4[3];
+ /* 13: loadl */
+ var56 = ptr0[i];
+ /* 14: convlw */
+ var57.i = var56.i;
+ /* 15: convwb */
+ var58 = var57.i;
+ /* 16: splatbl */
+ var59.i =
+ ((var58 & 0xff) << 24) | ((var58 & 0xff) << 16) | ((var58 & 0xff) <<
+ 8) | (var58 & 0xff);
+ /* 17: convubw */
+ var60.x4[0] = (orc_uint8) var59.x4[0];
+ var60.x4[1] = (orc_uint8) var59.x4[1];
+ var60.x4[2] = (orc_uint8) var59.x4[2];
+ var60.x4[3] = (orc_uint8) var59.x4[3];
+ /* 18: mullw */
+ var61.x4[0] = (var60.x4[0] * var55.x4[0]) & 0xffff;
+ var61.x4[1] = (var60.x4[1] * var55.x4[1]) & 0xffff;
+ var61.x4[2] = (var60.x4[2] * var55.x4[2]) & 0xffff;
+ var61.x4[3] = (var60.x4[3] * var55.x4[3]) & 0xffff;
+ /* 19: div255w */
+ var62.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[0] + 128)) +
+ (((orc_uint16) (var61.x4[0] + 128)) >> 8))) >> 8;
+ var62.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[1] + 128)) +
+ (((orc_uint16) (var61.x4[1] + 128)) >> 8))) >> 8;
+ var62.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[2] + 128)) +
+ (((orc_uint16) (var61.x4[2] + 128)) >> 8))) >> 8;
+ var62.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var61.x4[3] + 128)) +
+ (((orc_uint16) (var61.x4[3] + 128)) >> 8))) >> 8;
+ /* 20: convubw */
+ var63.x4[0] = (orc_uint8) var56.x4[0];
+ var63.x4[1] = (orc_uint8) var56.x4[1];
+ var63.x4[2] = (orc_uint8) var56.x4[2];
+ var63.x4[3] = (orc_uint8) var56.x4[3];
+ /* 21: mullw */
+ var64.x4[0] = (var63.x4[0] * var62.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var62.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var62.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var62.x4[3]) & 0xffff;
+ /* 22: addw */
+ var65.x4[0] = var64.x4[0] + var52.x4[0];
+ var65.x4[1] = var64.x4[1] + var52.x4[1];
+ var65.x4[2] = var64.x4[2] + var52.x4[2];
+ var65.x4[3] = var64.x4[3] + var52.x4[3];
+ /* 23: addw */
+ var66.x4[0] = var62.x4[0] + var50.x4[0];
+ var66.x4[1] = var62.x4[1] + var50.x4[1];
+ var66.x4[2] = var62.x4[2] + var50.x4[2];
+ var66.x4[3] = var62.x4[3] + var50.x4[3];
+ /* 24: divluw */
+ var67.x4[0] =
+ ((var66.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[0]) /
+ ((orc_uint16) var66.x4[0] & 0xff));
+ var67.x4[1] =
+ ((var66.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[1]) /
+ ((orc_uint16) var66.x4[1] & 0xff));
+ var67.x4[2] =
+ ((var66.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[2]) /
+ ((orc_uint16) var66.x4[2] & 0xff));
+ var67.x4[3] =
+ ((var66.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var65.x4[3]) /
+ ((orc_uint16) var66.x4[3] & 0xff));
+ /* 25: convwb */
+ var68.x4[0] = var67.x4[0];
+ var68.x4[1] = var67.x4[1];
+ var68.x4[2] = var67.x4[2];
+ var68.x4[3] = var67.x4[3];
+ /* 27: andl */
+ var69.i = var68.i & var42.i;
+ /* 28: convwb */
+ var70.x4[0] = var66.x4[0];
+ var70.x4[1] = var66.x4[1];
+ var70.x4[2] = var66.x4[2];
+ var70.x4[3] = var66.x4[3];
+ /* 30: andl */
+ var71.i = var70.i & var43.i;
+ /* 31: orl */
+ var72.i = var69.i | var71.i;
+ /* 32: storel */
+ ptr0[i] = var72;
+ }
+ }
+
+}
+
+void
+compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 7, 9, 27, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111,
+ 114, 99, 95, 111, 118, 101, 114, 108, 97, 121, 95, 97, 114, 103, 98, 11,
+ 4, 4, 12, 4, 4, 14, 4, 255, 255, 255, 255, 14, 4, 255, 0, 0,
+ 0, 14, 4, 0, 255, 255, 255, 14, 4, 8, 0, 0, 0, 16, 2, 20,
+ 4, 20, 2, 20, 1, 20, 8, 20, 8, 20, 8, 20, 4, 20, 8, 20,
+ 8, 113, 32, 4, 163, 33, 32, 157, 34, 33, 152, 38, 34, 21, 2, 150,
+ 35, 38, 21, 2, 89, 35, 35, 24, 21, 2, 95, 35, 35, 19, 21, 2,
+ 150, 40, 32, 21, 2, 89, 40, 40, 35, 115, 38, 16, 21, 2, 150, 36,
+ 38, 21, 2, 98, 36, 36, 35, 113, 32, 0, 163, 33, 32, 157, 34, 33,
+ 152, 38, 34, 21, 2, 150, 37, 38, 21, 2, 89, 37, 37, 36, 21, 2,
+ 80, 37, 37, 21, 2, 150, 39, 32, 21, 2, 89, 39, 39, 37, 21, 2,
+ 70, 39, 39, 40, 21, 2, 70, 37, 37, 35, 21, 2, 81, 39, 39, 37,
+ 21, 2, 157, 32, 39, 106, 32, 32, 18, 21, 2, 157, 38, 37, 106, 38,
+ 38, 17, 123, 32, 32, 38, 128, 0, 32, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_overlay_argb);
+#else
+ p = orc_program_new ();
+ orc_program_set_2d (p);
+ orc_program_set_name (p, "compositor_orc_overlay_argb");
+ orc_program_set_backup_function (p, _backup_compositor_orc_overlay_argb);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_source (p, 4, "s1");
+ orc_program_add_constant (p, 4, 0xffffffff, "c1");
+ orc_program_add_constant (p, 4, 0x000000ff, "c2");
+ orc_program_add_constant (p, 4, 0xffffff00, "c3");
+ orc_program_add_constant (p, 4, 0x00000008, "c4");
+ orc_program_add_parameter (p, 2, "p1");
+ orc_program_add_temporary (p, 4, "t1");
+ orc_program_add_temporary (p, 2, "t2");
+ orc_program_add_temporary (p, 1, "t3");
+ orc_program_add_temporary (p, 8, "t4");
+ orc_program_add_temporary (p, 8, "t5");
+ orc_program_add_temporary (p, 8, "t6");
+ orc_program_add_temporary (p, 4, "t7");
+ orc_program_add_temporary (p, 8, "t8");
+ orc_program_add_temporary (p, 8, "t9");
+
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T7, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T4, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T4, ORC_VAR_T4, ORC_VAR_P1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shruw", 2, ORC_VAR_T4, ORC_VAR_T4, ORC_VAR_C4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T9, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T9, ORC_VAR_T9, ORC_VAR_T4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadpl", 0, ORC_VAR_T7, ORC_VAR_C1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T5, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "subw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_T4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T7, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T6, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "div255w", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T8, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_T6,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_T9,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "divluw", 2, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_T6,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T1, ORC_VAR_T8, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "andl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C3,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T7, ORC_VAR_T6, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "andl", 0, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_C2,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "orl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T7,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ORC_EXECUTOR_M (ex) = m;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_D1] = d1_stride;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+ ex->params[ORC_VAR_S1] = s1_stride;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
+
+
+/* compositor_orc_overlay_bgra */
+#ifdef DISABLE_ORC
+void
+compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ int i;
+ int j;
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var42;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var43;
+#else
+ orc_union32 var43;
+#endif
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var44;
+#else
+ orc_union32 var44;
+#endif
+ orc_union32 var45;
+ orc_union32 var46;
+ orc_union16 var47;
+ orc_int8 var48;
+ orc_union32 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union32 var55;
+ orc_union64 var56;
+ orc_union64 var57;
+ orc_union32 var58;
+ orc_union32 var59;
+ orc_union16 var60;
+ orc_int8 var61;
+ orc_union32 var62;
+ orc_union64 var63;
+ orc_union64 var64;
+ orc_union64 var65;
+ orc_union64 var66;
+ orc_union64 var67;
+ orc_union64 var68;
+ orc_union64 var69;
+ orc_union64 var70;
+ orc_union32 var71;
+ orc_union32 var72;
+ orc_union32 var73;
+ orc_union32 var74;
+ orc_union32 var75;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (d1, d1_stride * j);
+ ptr4 = ORC_PTR_OFFSET (s1, s1_stride * j);
+
+ /* 6: loadpw */
+ var42.x4[0] = p1;
+ var42.x4[1] = p1;
+ var42.x4[2] = p1;
+ var42.x4[3] = p1;
+ /* 11: loadpl */
+ var55.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
+ /* 28: loadpl */
+ var43.i = (int) 0x00ffffff; /* 16777215 or 8.28905e-317f */
+ /* 31: loadpl */
+ var44.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var45 = ptr4[i];
+ /* 1: shrul */
+ var46.i = ((orc_uint32) var45.i) >> 24;
+ /* 2: convlw */
+ var47.i = var46.i;
+ /* 3: convwb */
+ var48 = var47.i;
+ /* 4: splatbl */
+ var49.i =
+ ((var48 & 0xff) << 24) | ((var48 & 0xff) << 16) | ((var48 & 0xff) <<
+ 8) | (var48 & 0xff);
+ /* 5: convubw */
+ var50.x4[0] = (orc_uint8) var49.x4[0];
+ var50.x4[1] = (orc_uint8) var49.x4[1];
+ var50.x4[2] = (orc_uint8) var49.x4[2];
+ var50.x4[3] = (orc_uint8) var49.x4[3];
+ /* 7: mullw */
+ var51.x4[0] = (var50.x4[0] * var42.x4[0]) & 0xffff;
+ var51.x4[1] = (var50.x4[1] * var42.x4[1]) & 0xffff;
+ var51.x4[2] = (var50.x4[2] * var42.x4[2]) & 0xffff;
+ var51.x4[3] = (var50.x4[3] * var42.x4[3]) & 0xffff;
+ /* 8: shruw */
+ var52.x4[0] = ((orc_uint16) var51.x4[0]) >> 8;
+ var52.x4[1] = ((orc_uint16) var51.x4[1]) >> 8;
+ var52.x4[2] = ((orc_uint16) var51.x4[2]) >> 8;
+ var52.x4[3] = ((orc_uint16) var51.x4[3]) >> 8;
+ /* 9: convubw */
+ var53.x4[0] = (orc_uint8) var45.x4[0];
+ var53.x4[1] = (orc_uint8) var45.x4[1];
+ var53.x4[2] = (orc_uint8) var45.x4[2];
+ var53.x4[3] = (orc_uint8) var45.x4[3];
+ /* 10: mullw */
+ var54.x4[0] = (var53.x4[0] * var52.x4[0]) & 0xffff;
+ var54.x4[1] = (var53.x4[1] * var52.x4[1]) & 0xffff;
+ var54.x4[2] = (var53.x4[2] * var52.x4[2]) & 0xffff;
+ var54.x4[3] = (var53.x4[3] * var52.x4[3]) & 0xffff;
+ /* 12: convubw */
+ var56.x4[0] = (orc_uint8) var55.x4[0];
+ var56.x4[1] = (orc_uint8) var55.x4[1];
+ var56.x4[2] = (orc_uint8) var55.x4[2];
+ var56.x4[3] = (orc_uint8) var55.x4[3];
+ /* 13: subw */
+ var57.x4[0] = var56.x4[0] - var52.x4[0];
+ var57.x4[1] = var56.x4[1] - var52.x4[1];
+ var57.x4[2] = var56.x4[2] - var52.x4[2];
+ var57.x4[3] = var56.x4[3] - var52.x4[3];
+ /* 14: loadl */
+ var58 = ptr0[i];
+ /* 15: shrul */
+ var59.i = ((orc_uint32) var58.i) >> 24;
+ /* 16: convlw */
+ var60.i = var59.i;
+ /* 17: convwb */
+ var61 = var60.i;
+ /* 18: splatbl */
+ var62.i =
+ ((var61 & 0xff) << 24) | ((var61 & 0xff) << 16) | ((var61 & 0xff) <<
+ 8) | (var61 & 0xff);
+ /* 19: convubw */
+ var63.x4[0] = (orc_uint8) var62.x4[0];
+ var63.x4[1] = (orc_uint8) var62.x4[1];
+ var63.x4[2] = (orc_uint8) var62.x4[2];
+ var63.x4[3] = (orc_uint8) var62.x4[3];
+ /* 20: mullw */
+ var64.x4[0] = (var63.x4[0] * var57.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var57.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var57.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var57.x4[3]) & 0xffff;
+ /* 21: div255w */
+ var65.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[0] + 128)) +
+ (((orc_uint16) (var64.x4[0] + 128)) >> 8))) >> 8;
+ var65.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[1] + 128)) +
+ (((orc_uint16) (var64.x4[1] + 128)) >> 8))) >> 8;
+ var65.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[2] + 128)) +
+ (((orc_uint16) (var64.x4[2] + 128)) >> 8))) >> 8;
+ var65.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[3] + 128)) +
+ (((orc_uint16) (var64.x4[3] + 128)) >> 8))) >> 8;
+ /* 22: convubw */
+ var66.x4[0] = (orc_uint8) var58.x4[0];
+ var66.x4[1] = (orc_uint8) var58.x4[1];
+ var66.x4[2] = (orc_uint8) var58.x4[2];
+ var66.x4[3] = (orc_uint8) var58.x4[3];
+ /* 23: mullw */
+ var67.x4[0] = (var66.x4[0] * var65.x4[0]) & 0xffff;
+ var67.x4[1] = (var66.x4[1] * var65.x4[1]) & 0xffff;
+ var67.x4[2] = (var66.x4[2] * var65.x4[2]) & 0xffff;
+ var67.x4[3] = (var66.x4[3] * var65.x4[3]) & 0xffff;
+ /* 24: addw */
+ var68.x4[0] = var67.x4[0] + var54.x4[0];
+ var68.x4[1] = var67.x4[1] + var54.x4[1];
+ var68.x4[2] = var67.x4[2] + var54.x4[2];
+ var68.x4[3] = var67.x4[3] + var54.x4[3];
+ /* 25: addw */
+ var69.x4[0] = var65.x4[0] + var52.x4[0];
+ var69.x4[1] = var65.x4[1] + var52.x4[1];
+ var69.x4[2] = var65.x4[2] + var52.x4[2];
+ var69.x4[3] = var65.x4[3] + var52.x4[3];
+ /* 26: divluw */
+ var70.x4[0] =
+ ((var69.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[0]) /
+ ((orc_uint16) var69.x4[0] & 0xff));
+ var70.x4[1] =
+ ((var69.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[1]) /
+ ((orc_uint16) var69.x4[1] & 0xff));
+ var70.x4[2] =
+ ((var69.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[2]) /
+ ((orc_uint16) var69.x4[2] & 0xff));
+ var70.x4[3] =
+ ((var69.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[3]) /
+ ((orc_uint16) var69.x4[3] & 0xff));
+ /* 27: convwb */
+ var71.x4[0] = var70.x4[0];
+ var71.x4[1] = var70.x4[1];
+ var71.x4[2] = var70.x4[2];
+ var71.x4[3] = var70.x4[3];
+ /* 29: andl */
+ var72.i = var71.i & var43.i;
+ /* 30: convwb */
+ var73.x4[0] = var69.x4[0];
+ var73.x4[1] = var69.x4[1];
+ var73.x4[2] = var69.x4[2];
+ var73.x4[3] = var69.x4[3];
+ /* 32: andl */
+ var74.i = var73.i & var44.i;
+ /* 33: orl */
+ var75.i = var72.i | var74.i;
+ /* 34: storel */
+ ptr0[i] = var75;
+ }
+ }
+
+}
+
+#else
+static void
+_backup_compositor_orc_overlay_bgra (OrcExecutor * ORC_RESTRICT ex)
+{
+ int i;
+ int j;
+ int n = ex->n;
+ int m = ex->params[ORC_VAR_A1];
+ orc_union32 *ORC_RESTRICT ptr0;
+ const orc_union32 *ORC_RESTRICT ptr4;
+ orc_union64 var42;
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var43;
+#else
+ orc_union32 var43;
+#endif
+#if defined(__APPLE__) && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && defined (__i386__)
+ volatile orc_union32 var44;
+#else
+ orc_union32 var44;
+#endif
+ orc_union32 var45;
+ orc_union32 var46;
+ orc_union16 var47;
+ orc_int8 var48;
+ orc_union32 var49;
+ orc_union64 var50;
+ orc_union64 var51;
+ orc_union64 var52;
+ orc_union64 var53;
+ orc_union64 var54;
+ orc_union32 var55;
+ orc_union64 var56;
+ orc_union64 var57;
+ orc_union32 var58;
+ orc_union32 var59;
+ orc_union16 var60;
+ orc_int8 var61;
+ orc_union32 var62;
+ orc_union64 var63;
+ orc_union64 var64;
+ orc_union64 var65;
+ orc_union64 var66;
+ orc_union64 var67;
+ orc_union64 var68;
+ orc_union64 var69;
+ orc_union64 var70;
+ orc_union32 var71;
+ orc_union32 var72;
+ orc_union32 var73;
+ orc_union32 var74;
+ orc_union32 var75;
+
+ for (j = 0; j < m; j++) {
+ ptr0 = ORC_PTR_OFFSET (ex->arrays[0], ex->params[0] * j);
+ ptr4 = ORC_PTR_OFFSET (ex->arrays[4], ex->params[4] * j);
+
+ /* 6: loadpw */
+ var42.x4[0] = ex->params[24];
+ var42.x4[1] = ex->params[24];
+ var42.x4[2] = ex->params[24];
+ var42.x4[3] = ex->params[24];
+ /* 11: loadpl */
+ var55.i = (int) 0xffffffff; /* -1 or 2.122e-314f */
+ /* 28: loadpl */
+ var43.i = (int) 0x00ffffff; /* 16777215 or 8.28905e-317f */
+ /* 31: loadpl */
+ var44.i = (int) 0xff000000; /* -16777216 or 2.11371e-314f */
+
+ for (i = 0; i < n; i++) {
+ /* 0: loadl */
+ var45 = ptr4[i];
+ /* 1: shrul */
+ var46.i = ((orc_uint32) var45.i) >> 24;
+ /* 2: convlw */
+ var47.i = var46.i;
+ /* 3: convwb */
+ var48 = var47.i;
+ /* 4: splatbl */
+ var49.i =
+ ((var48 & 0xff) << 24) | ((var48 & 0xff) << 16) | ((var48 & 0xff) <<
+ 8) | (var48 & 0xff);
+ /* 5: convubw */
+ var50.x4[0] = (orc_uint8) var49.x4[0];
+ var50.x4[1] = (orc_uint8) var49.x4[1];
+ var50.x4[2] = (orc_uint8) var49.x4[2];
+ var50.x4[3] = (orc_uint8) var49.x4[3];
+ /* 7: mullw */
+ var51.x4[0] = (var50.x4[0] * var42.x4[0]) & 0xffff;
+ var51.x4[1] = (var50.x4[1] * var42.x4[1]) & 0xffff;
+ var51.x4[2] = (var50.x4[2] * var42.x4[2]) & 0xffff;
+ var51.x4[3] = (var50.x4[3] * var42.x4[3]) & 0xffff;
+ /* 8: shruw */
+ var52.x4[0] = ((orc_uint16) var51.x4[0]) >> 8;
+ var52.x4[1] = ((orc_uint16) var51.x4[1]) >> 8;
+ var52.x4[2] = ((orc_uint16) var51.x4[2]) >> 8;
+ var52.x4[3] = ((orc_uint16) var51.x4[3]) >> 8;
+ /* 9: convubw */
+ var53.x4[0] = (orc_uint8) var45.x4[0];
+ var53.x4[1] = (orc_uint8) var45.x4[1];
+ var53.x4[2] = (orc_uint8) var45.x4[2];
+ var53.x4[3] = (orc_uint8) var45.x4[3];
+ /* 10: mullw */
+ var54.x4[0] = (var53.x4[0] * var52.x4[0]) & 0xffff;
+ var54.x4[1] = (var53.x4[1] * var52.x4[1]) & 0xffff;
+ var54.x4[2] = (var53.x4[2] * var52.x4[2]) & 0xffff;
+ var54.x4[3] = (var53.x4[3] * var52.x4[3]) & 0xffff;
+ /* 12: convubw */
+ var56.x4[0] = (orc_uint8) var55.x4[0];
+ var56.x4[1] = (orc_uint8) var55.x4[1];
+ var56.x4[2] = (orc_uint8) var55.x4[2];
+ var56.x4[3] = (orc_uint8) var55.x4[3];
+ /* 13: subw */
+ var57.x4[0] = var56.x4[0] - var52.x4[0];
+ var57.x4[1] = var56.x4[1] - var52.x4[1];
+ var57.x4[2] = var56.x4[2] - var52.x4[2];
+ var57.x4[3] = var56.x4[3] - var52.x4[3];
+ /* 14: loadl */
+ var58 = ptr0[i];
+ /* 15: shrul */
+ var59.i = ((orc_uint32) var58.i) >> 24;
+ /* 16: convlw */
+ var60.i = var59.i;
+ /* 17: convwb */
+ var61 = var60.i;
+ /* 18: splatbl */
+ var62.i =
+ ((var61 & 0xff) << 24) | ((var61 & 0xff) << 16) | ((var61 & 0xff) <<
+ 8) | (var61 & 0xff);
+ /* 19: convubw */
+ var63.x4[0] = (orc_uint8) var62.x4[0];
+ var63.x4[1] = (orc_uint8) var62.x4[1];
+ var63.x4[2] = (orc_uint8) var62.x4[2];
+ var63.x4[3] = (orc_uint8) var62.x4[3];
+ /* 20: mullw */
+ var64.x4[0] = (var63.x4[0] * var57.x4[0]) & 0xffff;
+ var64.x4[1] = (var63.x4[1] * var57.x4[1]) & 0xffff;
+ var64.x4[2] = (var63.x4[2] * var57.x4[2]) & 0xffff;
+ var64.x4[3] = (var63.x4[3] * var57.x4[3]) & 0xffff;
+ /* 21: div255w */
+ var65.x4[0] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[0] + 128)) +
+ (((orc_uint16) (var64.x4[0] + 128)) >> 8))) >> 8;
+ var65.x4[1] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[1] + 128)) +
+ (((orc_uint16) (var64.x4[1] + 128)) >> 8))) >> 8;
+ var65.x4[2] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[2] + 128)) +
+ (((orc_uint16) (var64.x4[2] + 128)) >> 8))) >> 8;
+ var65.x4[3] =
+ ((orc_uint16) (((orc_uint16) (var64.x4[3] + 128)) +
+ (((orc_uint16) (var64.x4[3] + 128)) >> 8))) >> 8;
+ /* 22: convubw */
+ var66.x4[0] = (orc_uint8) var58.x4[0];
+ var66.x4[1] = (orc_uint8) var58.x4[1];
+ var66.x4[2] = (orc_uint8) var58.x4[2];
+ var66.x4[3] = (orc_uint8) var58.x4[3];
+ /* 23: mullw */
+ var67.x4[0] = (var66.x4[0] * var65.x4[0]) & 0xffff;
+ var67.x4[1] = (var66.x4[1] * var65.x4[1]) & 0xffff;
+ var67.x4[2] = (var66.x4[2] * var65.x4[2]) & 0xffff;
+ var67.x4[3] = (var66.x4[3] * var65.x4[3]) & 0xffff;
+ /* 24: addw */
+ var68.x4[0] = var67.x4[0] + var54.x4[0];
+ var68.x4[1] = var67.x4[1] + var54.x4[1];
+ var68.x4[2] = var67.x4[2] + var54.x4[2];
+ var68.x4[3] = var67.x4[3] + var54.x4[3];
+ /* 25: addw */
+ var69.x4[0] = var65.x4[0] + var52.x4[0];
+ var69.x4[1] = var65.x4[1] + var52.x4[1];
+ var69.x4[2] = var65.x4[2] + var52.x4[2];
+ var69.x4[3] = var65.x4[3] + var52.x4[3];
+ /* 26: divluw */
+ var70.x4[0] =
+ ((var69.x4[0] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[0]) /
+ ((orc_uint16) var69.x4[0] & 0xff));
+ var70.x4[1] =
+ ((var69.x4[1] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[1]) /
+ ((orc_uint16) var69.x4[1] & 0xff));
+ var70.x4[2] =
+ ((var69.x4[2] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[2]) /
+ ((orc_uint16) var69.x4[2] & 0xff));
+ var70.x4[3] =
+ ((var69.x4[3] & 0xff) ==
+ 0) ? 255 : ORC_CLAMP_UB (((orc_uint16) var68.x4[3]) /
+ ((orc_uint16) var69.x4[3] & 0xff));
+ /* 27: convwb */
+ var71.x4[0] = var70.x4[0];
+ var71.x4[1] = var70.x4[1];
+ var71.x4[2] = var70.x4[2];
+ var71.x4[3] = var70.x4[3];
+ /* 29: andl */
+ var72.i = var71.i & var43.i;
+ /* 30: convwb */
+ var73.x4[0] = var69.x4[0];
+ var73.x4[1] = var69.x4[1];
+ var73.x4[2] = var69.x4[2];
+ var73.x4[3] = var69.x4[3];
+ /* 32: andl */
+ var74.i = var73.i & var44.i;
+ /* 33: orl */
+ var75.i = var72.i | var74.i;
+ /* 34: storel */
+ ptr0[i] = var75;
+ }
+ }
+
+}
+
+void
+compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride,
+ const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m)
+{
+ OrcExecutor _ex, *ex = &_ex;
+ static volatile int p_inited = 0;
+ static OrcCode *c = 0;
+ void (*func) (OrcExecutor *);
+
+ if (!p_inited) {
+ orc_once_mutex_lock ();
+ if (!p_inited) {
+ OrcProgram *p;
+
+#if 1
+ static const orc_uint8 bc[] = {
+ 1, 7, 9, 27, 99, 111, 109, 112, 111, 115, 105, 116, 111, 114, 95, 111,
+ 114, 99, 95, 111, 118, 101, 114, 108, 97, 121, 95, 98, 103, 114, 97, 11,
+ 4, 4, 12, 4, 4, 14, 4, 255, 255, 255, 255, 14, 4, 0, 0, 0,
+ 255, 14, 4, 255, 255, 255, 0, 14, 4, 24, 0, 0, 0, 14, 4, 8,
+ 0, 0, 0, 16, 2, 20, 4, 20, 4, 20, 2, 20, 1, 20, 8, 20,
+ 8, 20, 8, 20, 4, 20, 8, 20, 8, 113, 32, 4, 126, 33, 32, 19,
+ 163, 34, 33, 157, 35, 34, 152, 39, 35, 21, 2, 150, 36, 39, 21, 2,
+ 89, 36, 36, 24, 21, 2, 95, 36, 36, 20, 21, 2, 150, 41, 32, 21,
+ 2, 89, 41, 41, 36, 115, 39, 16, 21, 2, 150, 37, 39, 21, 2, 98,
+ 37, 37, 36, 113, 32, 0, 126, 33, 32, 19, 163, 34, 33, 157, 35, 34,
+ 152, 39, 35, 21, 2, 150, 38, 39, 21, 2, 89, 38, 38, 37, 21, 2,
+ 80, 38, 38, 21, 2, 150, 40, 32, 21, 2, 89, 40, 40, 38, 21, 2,
+ 70, 40, 40, 41, 21, 2, 70, 38, 38, 36, 21, 2, 81, 40, 40, 38,
+ 21, 2, 157, 32, 40, 106, 32, 32, 18, 21, 2, 157, 39, 38, 106, 39,
+ 39, 17, 123, 32, 32, 39, 128, 0, 32, 2, 0,
+ };
+ p = orc_program_new_from_static_bytecode (bc);
+ orc_program_set_backup_function (p, _backup_compositor_orc_overlay_bgra);
+#else
+ p = orc_program_new ();
+ orc_program_set_2d (p);
+ orc_program_set_name (p, "compositor_orc_overlay_bgra");
+ orc_program_set_backup_function (p, _backup_compositor_orc_overlay_bgra);
+ orc_program_add_destination (p, 4, "d1");
+ orc_program_add_source (p, 4, "s1");
+ orc_program_add_constant (p, 4, 0xffffffff, "c1");
+ orc_program_add_constant (p, 4, 0xff000000, "c2");
+ orc_program_add_constant (p, 4, 0x00ffffff, "c3");
+ orc_program_add_constant (p, 4, 0x00000018, "c4");
+ orc_program_add_constant (p, 4, 0x00000008, "c5");
+ orc_program_add_parameter (p, 2, "p1");
+ orc_program_add_temporary (p, 4, "t1");
+ orc_program_add_temporary (p, 4, "t2");
+ orc_program_add_temporary (p, 2, "t3");
+ orc_program_add_temporary (p, 1, "t4");
+ orc_program_add_temporary (p, 8, "t5");
+ orc_program_add_temporary (p, 8, "t6");
+ orc_program_add_temporary (p, 8, "t7");
+ orc_program_add_temporary (p, 4, "t8");
+ orc_program_add_temporary (p, 8, "t9");
+ orc_program_add_temporary (p, 8, "t10");
+
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shrul", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_C4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T8, ORC_VAR_T4, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T5, ORC_VAR_T8, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_P1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shruw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_C5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T10, ORC_VAR_T1,
+ ORC_VAR_D1, ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T10, ORC_VAR_T10, ORC_VAR_T5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadpl", 0, ORC_VAR_T8, ORC_VAR_C1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T6, ORC_VAR_T8, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "subw", 2, ORC_VAR_T6, ORC_VAR_T6, ORC_VAR_T5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "shrul", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_C4,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convlw", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 0, ORC_VAR_T4, ORC_VAR_T3, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "splatbl", 0, ORC_VAR_T8, ORC_VAR_T4, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T7, ORC_VAR_T8, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_T6,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "div255w", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convubw", 2, ORC_VAR_T9, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "mullw", 2, ORC_VAR_T9, ORC_VAR_T9, ORC_VAR_T7,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T9, ORC_VAR_T9, ORC_VAR_T10,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "addw", 2, ORC_VAR_T7, ORC_VAR_T7, ORC_VAR_T5,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "divluw", 2, ORC_VAR_T9, ORC_VAR_T9, ORC_VAR_T7,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T1, ORC_VAR_T9, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "andl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C3,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "convwb", 2, ORC_VAR_T8, ORC_VAR_T7, ORC_VAR_D1,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "andl", 0, ORC_VAR_T8, ORC_VAR_T8, ORC_VAR_C2,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "orl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T8,
+ ORC_VAR_D1);
+ orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1,
+ ORC_VAR_D1);
+#endif
+
+ orc_program_compile (p);
+ c = orc_program_take_code (p);
+ orc_program_free (p);
+ }
+ p_inited = TRUE;
+ orc_once_mutex_unlock ();
+ }
+ ex->arrays[ORC_VAR_A2] = c;
+ ex->program = 0;
+
+ ex->n = n;
+ ORC_EXECUTOR_M (ex) = m;
+ ex->arrays[ORC_VAR_D1] = d1;
+ ex->params[ORC_VAR_D1] = d1_stride;
+ ex->arrays[ORC_VAR_S1] = (void *) s1;
+ ex->params[ORC_VAR_S1] = s1_stride;
+ ex->params[ORC_VAR_P1] = p1;
+
+ func = c->exec;
+ func (ex);
+}
+#endif
diff --git a/gst/compositor/compositororc-dist.h b/gst/compositor/compositororc-dist.h
new file mode 100644
index 000000000..907b262b1
--- /dev/null
+++ b/gst/compositor/compositororc-dist.h
@@ -0,0 +1,96 @@
+
+/* autogenerated from compositororc.orc */
+
+#ifndef _COMPOSITORORC_H_
+#define _COMPOSITORORC_H_
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#ifndef _ORC_INTEGER_TYPEDEFS_
+#define _ORC_INTEGER_TYPEDEFS_
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <stdint.h>
+typedef int8_t orc_int8;
+typedef int16_t orc_int16;
+typedef int32_t orc_int32;
+typedef int64_t orc_int64;
+typedef uint8_t orc_uint8;
+typedef uint16_t orc_uint16;
+typedef uint32_t orc_uint32;
+typedef uint64_t orc_uint64;
+#define ORC_UINT64_C(x) UINT64_C(x)
+#elif defined(_MSC_VER)
+typedef signed __int8 orc_int8;
+typedef signed __int16 orc_int16;
+typedef signed __int32 orc_int32;
+typedef signed __int64 orc_int64;
+typedef unsigned __int8 orc_uint8;
+typedef unsigned __int16 orc_uint16;
+typedef unsigned __int32 orc_uint32;
+typedef unsigned __int64 orc_uint64;
+#define ORC_UINT64_C(x) (x##Ui64)
+#define inline __inline
+#else
+#include <limits.h>
+typedef signed char orc_int8;
+typedef short orc_int16;
+typedef int orc_int32;
+typedef unsigned char orc_uint8;
+typedef unsigned short orc_uint16;
+typedef unsigned int orc_uint32;
+#if INT_MAX == LONG_MAX
+typedef long long orc_int64;
+typedef unsigned long long orc_uint64;
+#define ORC_UINT64_C(x) (x##ULL)
+#else
+typedef long orc_int64;
+typedef unsigned long orc_uint64;
+#define ORC_UINT64_C(x) (x##UL)
+#endif
+#endif
+typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16;
+typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32;
+typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64;
+#endif
+#ifndef ORC_RESTRICT
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ORC_RESTRICT restrict
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#define ORC_RESTRICT __restrict__
+#else
+#define ORC_RESTRICT
+#endif
+#endif
+
+#ifndef ORC_INTERNAL
+#if defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#define ORC_INTERNAL __hidden
+#elif defined (__GNUC__)
+#define ORC_INTERNAL __attribute__((visibility("hidden")))
+#else
+#define ORC_INTERNAL
+#endif
+#endif
+
+void compositor_orc_splat_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
+void compositor_orc_memcpy_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n);
+void compositor_orc_blend_u8 (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_blend_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_argb (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+void compositor_orc_overlay_bgra (guint8 * ORC_RESTRICT d1, int d1_stride, const guint8 * ORC_RESTRICT s1, int s1_stride, int p1, int n, int m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/gst/compositor/compositororc.orc b/gst/compositor/compositororc.orc
new file mode 100644
index 000000000..5a348b253
--- /dev/null
+++ b/gst/compositor/compositororc.orc
@@ -0,0 +1,220 @@
+.function compositor_orc_splat_u32
+.dest 4 d1 guint32
+.param 4 p1 guint32
+
+copyl d1, p1
+
+.function compositor_orc_memcpy_u32
+.dest 4 d1 guint32
+.source 4 s1 guint32
+
+copyl d1, s1
+
+.function compositor_orc_blend_u8
+.flags 2d
+.dest 1 d1 guint8
+.source 1 s1 guint8
+.param 2 p1
+.temp 2 t1
+.temp 2 t2
+.const 1 c1 8
+
+convubw t1, d1
+convubw t2, s1
+subw t2, t2, t1
+mullw t2, t2, p1
+shlw t1, t1, c1
+addw t2, t1, t2
+shruw t2, t2, c1
+convsuswb d1, t2
+
+
+.function compositor_orc_blend_argb
+.flags 2d
+.dest 4 d guint8
+.source 4 s guint8
+.param 2 alpha
+.temp 4 t
+.temp 2 tw
+.temp 1 tb
+.temp 4 a
+.temp 8 d_wide
+.temp 8 s_wide
+.temp 8 a_wide
+.const 4 a_alpha 0x000000ff
+
+loadl t, s
+convlw tw, t
+convwb tb, tw
+splatbl a, tb
+x4 convubw a_wide, a
+x4 mullw a_wide, a_wide, alpha
+x4 shruw a_wide, a_wide, 8
+x4 convubw s_wide, t
+loadl t, d
+x4 convubw d_wide, t
+x4 subw s_wide, s_wide, d_wide
+x4 mullw s_wide, s_wide, a_wide
+x4 div255w s_wide, s_wide
+x4 addw d_wide, d_wide, s_wide
+x4 convwb t, d_wide
+orl t, t, a_alpha
+storel d, t
+
+.function compositor_orc_blend_bgra
+.flags 2d
+.dest 4 d guint8
+.source 4 s guint8
+.param 2 alpha
+.temp 4 t
+.temp 4 t2
+.temp 2 tw
+.temp 1 tb
+.temp 4 a
+.temp 8 d_wide
+.temp 8 s_wide
+.temp 8 a_wide
+.const 4 a_alpha 0xff000000
+
+loadl t, s
+shrul t2, t, 24
+convlw tw, t2
+convwb tb, tw
+splatbl a, tb
+x4 convubw a_wide, a
+x4 mullw a_wide, a_wide, alpha
+x4 shruw a_wide, a_wide, 8
+x4 convubw s_wide, t
+loadl t, d
+x4 convubw d_wide, t
+x4 subw s_wide, s_wide, d_wide
+x4 mullw s_wide, s_wide, a_wide
+x4 div255w s_wide, s_wide
+x4 addw d_wide, d_wide, s_wide
+x4 convwb t, d_wide
+orl t, t, a_alpha
+storel d, t
+
+
+.function compositor_orc_overlay_argb
+.flags 2d
+.dest 4 d guint8
+.source 4 s guint8
+.param 2 alpha
+.temp 4 t
+.temp 2 tw
+.temp 1 tb
+.temp 8 alpha_s
+.temp 8 alpha_s_inv
+.temp 8 alpha_d
+.temp 4 a
+.temp 8 d_wide
+.temp 8 s_wide
+.const 4 xfs 0xffffffff
+.const 4 a_alpha 0x000000ff
+.const 4 a_alpha_inv 0xffffff00
+
+# calc source alpha as alpha_s = alpha_s * alpha / 256
+loadl t, s
+convlw tw, t
+convwb tb, tw
+splatbl a, tb
+x4 convubw alpha_s, a
+x4 mullw alpha_s, alpha_s, alpha
+x4 shruw alpha_s, alpha_s, 8
+x4 convubw s_wide, t
+x4 mullw s_wide, s_wide, alpha_s
+
+# calc destination alpha as alpha_d = (255-alpha_s) * alpha_d / 255
+loadpl a, xfs
+x4 convubw alpha_s_inv, a
+x4 subw alpha_s_inv, alpha_s_inv, alpha_s
+loadl t, d
+convlw tw, t
+convwb tb, tw
+splatbl a, tb
+x4 convubw alpha_d, a
+x4 mullw alpha_d, alpha_d, alpha_s_inv
+x4 div255w alpha_d, alpha_d
+x4 convubw d_wide, t
+x4 mullw d_wide, d_wide, alpha_d
+
+# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_d*(255-alpha_s)/255
+x4 addw d_wide, d_wide, s_wide
+
+# calc the final destination alpha_d = alpha_s + alpha_d * (255-alpha_s)/255
+x4 addw alpha_d, alpha_d, alpha_s
+
+# now normalize the pix_d by the final alpha to make it associative
+x4 divluw, d_wide, d_wide, alpha_d
+
+# pack the new alpha into the correct spot
+x4 convwb t, d_wide
+andl t, t, a_alpha_inv
+x4 convwb a, alpha_d
+andl a, a, a_alpha
+orl t, t, a
+storel d, t
+
+.function compositor_orc_overlay_bgra
+.flags 2d
+.dest 4 d guint8
+.source 4 s guint8
+.param 2 alpha
+.temp 4 t
+.temp 4 t2
+.temp 2 tw
+.temp 1 tb
+.temp 8 alpha_s
+.temp 8 alpha_s_inv
+.temp 8 alpha_d
+.temp 4 a
+.temp 8 d_wide
+.temp 8 s_wide
+.const 4 xfs 0xffffffff
+.const 4 a_alpha 0xff000000
+.const 4 a_alpha_inv 0x00ffffff
+
+# calc source alpha as alpha_s = alpha_s * alpha / 256
+loadl t, s
+shrul t2, t, 24
+convlw tw, t2
+convwb tb, tw
+splatbl a, tb
+x4 convubw alpha_s, a
+x4 mullw alpha_s, alpha_s, alpha
+x4 shruw alpha_s, alpha_s, 8
+x4 convubw s_wide, t
+x4 mullw s_wide, s_wide, alpha_s
+
+# calc destination alpha as alpha_d = (255-alpha_s) * alpha_d / 255
+loadpl a, xfs
+x4 convubw alpha_s_inv, a
+x4 subw alpha_s_inv, alpha_s_inv, alpha_s
+loadl t, d
+shrul t2, t, 24
+convlw tw, t2
+convwb tb, tw
+splatbl a, tb
+x4 convubw alpha_d, a
+x4 mullw alpha_d, alpha_d, alpha_s_inv
+x4 div255w alpha_d, alpha_d
+x4 convubw d_wide, t
+x4 mullw d_wide, d_wide, alpha_d
+
+# calc final pixel as pix_d = pix_s*alpha_s + pix_d*alpha_d*(255-alpha_s)/255
+x4 addw d_wide, d_wide, s_wide
+
+# calc the final destination alpha_d = alpha_s + alpha_d * (255-alpha_s)/255
+x4 addw alpha_d, alpha_d, alpha_s
+
+# now normalize the pix_d by the final alpha to make it associative
+x4 divluw, d_wide, d_wide, alpha_d
+
+# pack the new alpha into the correct spot
+x4 convwb t, d_wide
+andl t, t, a_alpha_inv
+x4 convwb a, alpha_d
+andl a, a, a_alpha
+orl t, t, a
+storel d, t
diff --git a/gst/compositor/compositorpad.h b/gst/compositor/compositorpad.h
new file mode 100644
index 000000000..0ba580e5b
--- /dev/null
+++ b/gst/compositor/compositorpad.h
@@ -0,0 +1,65 @@
+/* Generic compositor plugin pad
+ * Copyright (C) 2008 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_COMPOSITOR_PAD_H__
+#define __GST_COMPOSITOR_PAD_H__
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_COMPOSITOR_PAD (gst_compositor_pad_get_type())
+#define GST_COMPOSITOR_PAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COMPOSITOR_PAD, GstCompositorPad))
+#define GST_COMPOSITOR_PAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COMPOSITOR_PAD, GstCompositorPadClass))
+#define GST_IS_COMPOSITOR_PAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COMPOSITOR_PAD))
+#define GST_IS_COMPOSITOR_PAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COMPOSITOR_PAD))
+
+typedef struct _GstCompositorPad GstCompositorPad;
+typedef struct _GstCompositorPadClass GstCompositorPadClass;
+
+/**
+ * GstCompositorPad:
+ *
+ * The opaque #GstCompositorPad structure.
+ */
+struct _GstCompositorPad
+{
+ GstVideoAggregatorPad parent;
+
+ /* properties */
+ gint xpos, ypos;
+ guint zorder;
+ gdouble alpha;
+};
+
+struct _GstCompositorPadClass
+{
+ GstVideoAggregatorPadClass parent_class;
+};
+
+GType gst_compositor_pad_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_COMPOSITOR_PAD_H__ */
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 6233d013c..90677f775 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -125,7 +125,7 @@ check_mimic=
endif
if HAVE_ORC
-check_orc = orc/bayer orc/audiomixer
+check_orc = orc/bayer orc/audiomixer orc/compositor
else
check_orc =
endif
@@ -227,6 +227,7 @@ check_PROGRAMS = \
elements/dataurisrc \
elements/gdppay \
elements/gdpdepay \
+ elements/compositor \
$(check_jifmux) \
elements/jpegparse \
elements/h263parse \
@@ -466,6 +467,19 @@ libs_aggregator_CFLAGS = \
-DGST_USE_UNSTABLE_API \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
+elements_compositor_LDADD = $(LDADD) $(GST_BASE_LIBS)
+elements_compositor_CFLAGS = $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
+
+orc_compositor_CFLAGS = $(ORC_CFLAGS)
+orc_compositor_LDADD = $(ORC_LIBS) -lorc-test-0.4
+nodist_orc_compositor_SOURCES = orc/compositor.c
+orc_videobox_CFLAGS = $(ORC_CFLAGS)
+
+orc/compositor.c: $(top_srcdir)/gst/compositor/compositororc.orc
+ $(MKDIR_P) orc/
+ $(ORCC) --test -o $@ $<
+
+
distclean-local-orc:
rm -rf orc
diff --git a/tests/check/elements/compositor.c b/tests/check/elements/compositor.c
new file mode 100644
index 000000000..20b1c3930
--- /dev/null
+++ b/tests/check/elements/compositor.c
@@ -0,0 +1,1071 @@
+/* GStreamer
+ *
+ * unit test for compositor
+ *
+ * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
+ * Copyright (C) <2013> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_VALGRIND
+# include <valgrind/valgrind.h>
+#endif
+
+#include <unistd.h>
+
+#include <gst/check/gstcheck.h>
+#include <gst/check/gstconsistencychecker.h>
+#include <gst/base/gstbasesrc.h>
+
+#define VIDEO_CAPS_STRING \
+ "video/x-raw, " \
+ "width = (int) 320, " \
+ "height = (int) 240, " \
+ "framerate = (fraction) 25/1 , " \
+ "format = (string) I420"
+
+static GMainLoop *main_loop;
+
+/* make sure downstream gets a CAPS event before buffers are sent */
+GST_START_TEST (test_caps)
+{
+ GstElement *pipeline, *src, *compositor, *sink;
+ GstStateChangeReturn state_res;
+ GstCaps *caps;
+ GstPad *pad;
+
+ /* build pipeline */
+ pipeline = gst_pipeline_new ("pipeline");
+
+ src = gst_element_factory_make ("videotestsrc", "src1");
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (pipeline), src, compositor, sink, NULL);
+
+ fail_unless (gst_element_link_many (src, compositor, sink, NULL));
+
+ /* prepare playing */
+ state_res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ fail_unless_equals_int (state_res, GST_STATE_CHANGE_ASYNC);
+
+ /* wait for preroll */
+ state_res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
+ fail_unless_equals_int (state_res, GST_STATE_CHANGE_SUCCESS);
+
+ /* check caps on fakesink */
+ pad = gst_element_get_static_pad (sink, "sink");
+ caps = gst_pad_get_current_caps (pad);
+ fail_unless (caps != NULL);
+ gst_caps_unref (caps);
+ gst_object_unref (pad);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
+static void
+message_received (GstBus * bus, GstMessage * message, GstPipeline * bin)
+{
+ GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
+ GST_MESSAGE_SRC (message), message);
+
+ switch (message->type) {
+ case GST_MESSAGE_EOS:
+ g_main_loop_quit (main_loop);
+ break;
+ case GST_MESSAGE_WARNING:{
+ GError *gerror;
+ gchar *debug;
+
+ gst_message_parse_warning (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ g_error_free (gerror);
+ g_free (debug);
+ break;
+ }
+ case GST_MESSAGE_ERROR:{
+ GError *gerror;
+ gchar *debug;
+
+ gst_message_parse_error (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ g_error_free (gerror);
+ g_free (debug);
+ g_main_loop_quit (main_loop);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+static GstFormat format = GST_FORMAT_UNDEFINED;
+static gint64 position = -1;
+
+static void
+test_event_message_received (GstBus * bus, GstMessage * message,
+ GstPipeline * bin)
+{
+ GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
+ GST_MESSAGE_SRC (message), message);
+
+ switch (message->type) {
+ case GST_MESSAGE_SEGMENT_DONE:
+ gst_message_parse_segment_done (message, &format, &position);
+ GST_INFO ("received segment_done : %" G_GINT64_FORMAT, position);
+ g_main_loop_quit (main_loop);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+
+GST_START_TEST (test_event)
+{
+ GstElement *bin, *src1, *src2, *compositor, *sink;
+ GstBus *bus;
+ GstEvent *seek_event;
+ GstStateChangeReturn state_res;
+ gboolean res;
+ GstPad *srcpad, *sinkpad;
+ GstStreamConsistency *chk_1, *chk_2, *chk_3;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ src2 = gst_element_factory_make ("videotestsrc", "src2");
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
+
+ res = gst_element_link (src1, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (src2, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ srcpad = gst_element_get_static_pad (compositor, "src");
+ chk_3 = gst_consistency_checker_new (srcpad);
+ gst_object_unref (srcpad);
+
+ /* create consistency checkers for the pads */
+ srcpad = gst_element_get_static_pad (src1, "src");
+ chk_1 = gst_consistency_checker_new (srcpad);
+ sinkpad = gst_pad_get_peer (srcpad);
+ gst_consistency_checker_add_pad (chk_3, sinkpad);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ srcpad = gst_element_get_static_pad (src2, "src");
+ chk_2 = gst_consistency_checker_new (srcpad);
+ sinkpad = gst_pad_get_peer (srcpad);
+ gst_consistency_checker_add_pad (chk_3, sinkpad);
+ gst_object_unref (sinkpad);
+ gst_object_unref (srcpad);
+
+ seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, (GstClockTime) 0,
+ GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
+
+ format = GST_FORMAT_UNDEFINED;
+ position = -1;
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done",
+ (GCallback) test_event_message_received, bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ GST_INFO ("starting test");
+
+ /* prepare playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ res = gst_element_send_event (bin, seek_event);
+ fail_unless (res == TRUE, NULL);
+
+ /* run pipeline */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ GST_INFO ("running main loop");
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ ck_assert_int_eq (position, 2 * GST_SECOND);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_consistency_checker_free (chk_1);
+ gst_consistency_checker_free (chk_2);
+ gst_consistency_checker_free (chk_3);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+static guint play_count = 0;
+static GstEvent *play_seek_event = NULL;
+
+static void
+test_play_twice_message_received (GstBus * bus, GstMessage * message,
+ GstPipeline * bin)
+{
+ gboolean res;
+ GstStateChangeReturn state_res;
+
+ GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
+ GST_MESSAGE_SRC (message), message);
+
+ switch (message->type) {
+ case GST_MESSAGE_SEGMENT_DONE:
+ play_count++;
+ if (play_count == 1) {
+ state_res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* prepare playing again */
+ state_res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ res = gst_element_send_event (GST_ELEMENT (bin),
+ gst_event_ref (play_seek_event));
+ fail_unless (res == TRUE, NULL);
+
+ state_res =
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+ } else {
+ g_main_loop_quit (main_loop);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+
+GST_START_TEST (test_play_twice)
+{
+ GstElement *bin, *src1, *src2, *compositor, *sink;
+ GstBus *bus;
+ gboolean res;
+ GstStateChangeReturn state_res;
+ GstPad *srcpad;
+ GstStreamConsistency *consist;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ src2 = gst_element_factory_make ("videotestsrc", "src2");
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
+
+ res = gst_element_link (src1, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (src2, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ srcpad = gst_element_get_static_pad (compositor, "src");
+ consist = gst_consistency_checker_new (srcpad);
+ gst_object_unref (srcpad);
+
+ play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, (GstClockTime) 0,
+ GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
+
+ play_count = 0;
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done",
+ (GCallback) test_play_twice_message_received, bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ GST_INFO ("starting test");
+
+ /* prepare playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ res = gst_element_send_event (bin, gst_event_ref (play_seek_event));
+ fail_unless (res == TRUE, NULL);
+
+ GST_INFO ("seeked");
+
+ /* run pipeline */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ ck_assert_int_eq (play_count, 2);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_consistency_checker_free (consist);
+ gst_event_ref (play_seek_event);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_play_twice_then_add_and_play_again)
+{
+ GstElement *bin, *src1, *src2, *src3, *compositor, *sink;
+ GstBus *bus;
+ gboolean res;
+ GstStateChangeReturn state_res;
+ gint i;
+ GstPad *srcpad;
+ GstStreamConsistency *consist;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ src2 = gst_element_factory_make ("videotestsrc", "src2");
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
+
+ srcpad = gst_element_get_static_pad (compositor, "src");
+ consist = gst_consistency_checker_new (srcpad);
+ gst_object_unref (srcpad);
+
+ res = gst_element_link (src1, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (src2, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, (GstClockTime) 0,
+ GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done",
+ (GCallback) test_play_twice_message_received, bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ /* run it twice */
+ for (i = 0; i < 2; i++) {
+ play_count = 0;
+
+ GST_INFO ("starting test-loop %d", i);
+
+ /* prepare playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ res = gst_element_send_event (bin, gst_event_ref (play_seek_event));
+ fail_unless (res == TRUE, NULL);
+
+ GST_INFO ("seeked");
+
+ /* run pipeline */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_READY);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ ck_assert_int_eq (play_count, 2);
+
+ /* plug another source */
+ if (i == 0) {
+ src3 = gst_element_factory_make ("videotestsrc", "src3");
+ gst_bin_add (GST_BIN (bin), src3);
+
+ res = gst_element_link (src3, compositor);
+ fail_unless (res == TRUE, NULL);
+ }
+
+ gst_consistency_checker_reset (consist);
+ }
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_event_ref (play_seek_event);
+ gst_consistency_checker_free (consist);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+/* check if adding pads work as expected */
+GST_START_TEST (test_add_pad)
+{
+ GstElement *bin, *src1, *src2, *compositor, *sink;
+ GstBus *bus;
+ GstPad *srcpad;
+ gboolean res;
+ GstStateChangeReturn state_res;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ g_object_set (src1, "num-buffers", 4, NULL);
+ src2 = gst_element_factory_make ("videotestsrc", "src2");
+ /* one buffer less, we connect with 1 buffer of delay */
+ g_object_set (src2, "num-buffers", 3, NULL);
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src1, compositor, sink, NULL);
+
+ res = gst_element_link (src1, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ srcpad = gst_element_get_static_pad (compositor, "src");
+ gst_object_unref (srcpad);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done", (GCallback) message_received,
+ bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ GST_INFO ("starting test");
+
+ /* prepare playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* add other element */
+ gst_bin_add_many (GST_BIN (bin), src2, NULL);
+
+ /* now link the second element */
+ res = gst_element_link (src2, compositor);
+ fail_unless (res == TRUE, NULL);
+
+ /* set to PAUSED as well */
+ state_res = gst_element_set_state (src2, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* now play all */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+/* check if removing pads work as expected */
+GST_START_TEST (test_remove_pad)
+{
+ GstElement *bin, *src, *compositor, *sink;
+ GstBus *bus;
+ GstPad *pad, *srcpad;
+ gboolean res;
+ GstStateChangeReturn state_res;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src = gst_element_factory_make ("videotestsrc", "src");
+ g_object_set (src, "num-buffers", 4, NULL);
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src, compositor, sink, NULL);
+
+ res = gst_element_link (src, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ /* create an unconnected sinkpad in compositor */
+ pad = gst_element_get_request_pad (compositor, "sink_%u");
+ fail_if (pad == NULL, NULL);
+
+ srcpad = gst_element_get_static_pad (compositor, "src");
+ gst_object_unref (srcpad);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done", (GCallback) message_received,
+ bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ GST_INFO ("starting test");
+
+ /* prepare playing, this will not preroll as compositor is waiting
+ * on the unconnected sinkpad. */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion for one second, will return ASYNC */
+ state_res = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_SECOND);
+ ck_assert_int_eq (state_res, GST_STATE_CHANGE_ASYNC);
+
+ /* get rid of the pad now, compositor should stop waiting on it and
+ * continue the preroll */
+ gst_element_release_request_pad (compositor, pad);
+ gst_object_unref (pad);
+
+ /* wait for completion, should work now */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* now play all */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (G_OBJECT (bus));
+ gst_object_unref (G_OBJECT (bin));
+}
+
+GST_END_TEST;
+
+
+static GstBuffer *handoff_buffer = NULL;
+
+static gboolean
+_quit (GMainLoop * ml)
+{
+ g_main_loop_quit (ml);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+ gpointer user_data)
+{
+ GST_DEBUG ("got buffer %p", buffer);
+ gst_buffer_replace (&handoff_buffer, buffer);
+
+ if (main_loop)
+ g_idle_add ((GSourceFunc) _quit, main_loop);
+}
+
+/* check if clipping works as expected */
+GST_START_TEST (test_clip)
+{
+ GstSegment segment;
+ GstElement *bin, *compositor, *sink;
+ GstBus *bus;
+ GstPad *sinkpad;
+ gboolean res;
+ GstStateChangeReturn state_res;
+ GstFlowReturn ret;
+ GstEvent *event;
+ GstBuffer *buffer;
+ GstCaps *caps;
+ GMainLoop *local_mainloop;
+
+ GST_INFO ("preparing test");
+
+ local_mainloop = g_main_loop_new (NULL, FALSE);
+ main_loop = NULL;
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ /* just an compositor and a fakesink */
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ g_object_set (sink, "signal-handoffs", TRUE, NULL);
+ g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb, NULL);
+ gst_bin_add_many (GST_BIN (bin), compositor, sink, NULL);
+
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ /* set to playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* create an unconnected sinkpad in compositor, should also automatically activate
+ * the pad */
+ sinkpad = gst_element_get_request_pad (compositor, "sink_%u");
+ fail_if (sinkpad == NULL, NULL);
+
+ gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
+
+ caps = gst_caps_from_string (VIDEO_CAPS_STRING);
+
+ gst_pad_set_caps (sinkpad, caps);
+ gst_caps_unref (caps);
+
+ /* send segment to compositor */
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ segment.start = GST_SECOND;
+ segment.stop = 2 * GST_SECOND;
+ segment.time = 0;
+ event = gst_event_new_segment (&segment);
+ gst_pad_send_event (sinkpad, event);
+
+ /* should be clipped and ok */
+ buffer = gst_buffer_new_and_alloc (115200);
+ GST_BUFFER_TIMESTAMP (buffer) = 0;
+ GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+ GST_DEBUG ("pushing buffer %p", buffer);
+ ret = gst_pad_chain (sinkpad, buffer);
+ ck_assert_int_eq (ret, GST_FLOW_OK);
+ fail_unless (handoff_buffer == NULL);
+
+ /* should be partially clipped */
+ buffer = gst_buffer_new_and_alloc (115200);
+ GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND;
+ GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+ GST_DEBUG ("pushing buffer %p", buffer);
+
+ main_loop = local_mainloop;
+ ret = gst_pad_chain (sinkpad, buffer);
+ ck_assert_int_eq (ret, GST_FLOW_OK);
+ g_main_loop_run (main_loop);
+ gst_buffer_replace (&handoff_buffer, NULL);
+
+ /* should not be clipped */
+ buffer = gst_buffer_new_and_alloc (115200);
+ GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
+ GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+ GST_DEBUG ("pushing buffer %p", buffer);
+ ret = gst_pad_chain (sinkpad, buffer);
+ g_main_loop_run (main_loop);
+ main_loop = NULL;
+ ck_assert_int_eq (ret, GST_FLOW_OK);
+ fail_unless (handoff_buffer != NULL);
+ gst_buffer_replace (&handoff_buffer, NULL);
+
+ /* should be clipped and ok */
+ buffer = gst_buffer_new_and_alloc (115200);
+ GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
+ GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+ GST_DEBUG ("pushing buffer %p", buffer);
+ ret = gst_pad_chain (sinkpad, buffer);
+ ck_assert_int_eq (ret, GST_FLOW_OK);
+ fail_unless (handoff_buffer == NULL);
+
+ gst_object_unref (sinkpad);
+ gst_element_set_state (bin, GST_STATE_NULL);
+ g_main_loop_unref (local_mainloop);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_duration_is_max)
+{
+ GstElement *bin, *src[3], *compositor, *sink;
+ GstStateChangeReturn state_res;
+ GstFormat format = GST_FORMAT_TIME;
+ gboolean res;
+ gint64 duration;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+
+ /* 3 sources, an compositor and a fakesink */
+ src[0] = gst_element_factory_make ("videotestsrc", NULL);
+ src[1] = gst_element_factory_make ("videotestsrc", NULL);
+ src[2] = gst_element_factory_make ("videotestsrc", NULL);
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], compositor, sink,
+ NULL);
+
+ gst_element_link (src[0], compositor);
+ gst_element_link (src[1], compositor);
+ gst_element_link (src[2], compositor);
+ gst_element_link (compositor, sink);
+
+ /* irks, duration is reset on basesrc */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ /* set durations on src */
+ GST_BASE_SRC (src[0])->segment.duration = 1000;
+ GST_BASE_SRC (src[1])->segment.duration = 3000;
+ GST_BASE_SRC (src[2])->segment.duration = 2000;
+
+ /* set to playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
+ fail_unless (res, NULL);
+
+ ck_assert_int_eq (duration, 3000);
+
+ gst_element_set_state (bin, GST_STATE_NULL);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_duration_unknown_overrides)
+{
+ GstElement *bin, *src[3], *compositor, *sink;
+ GstStateChangeReturn state_res;
+ GstFormat format = GST_FORMAT_TIME;
+ gboolean res;
+ gint64 duration;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+
+ /* 3 sources, an compositor and a fakesink */
+ src[0] = gst_element_factory_make ("videotestsrc", NULL);
+ src[1] = gst_element_factory_make ("videotestsrc", NULL);
+ src[2] = gst_element_factory_make ("videotestsrc", NULL);
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src[0], src[1], src[2], compositor, sink,
+ NULL);
+
+ gst_element_link (src[0], compositor);
+ gst_element_link (src[1], compositor);
+ gst_element_link (src[2], compositor);
+ gst_element_link (compositor, sink);
+
+ /* irks, duration is reset on basesrc */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ /* set durations on src */
+ GST_BASE_SRC (src[0])->segment.duration = GST_CLOCK_TIME_NONE;
+ GST_BASE_SRC (src[1])->segment.duration = 3000;
+ GST_BASE_SRC (src[2])->segment.duration = 2000;
+
+ /* set to playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ fail_unless (state_res != GST_STATE_CHANGE_FAILURE, NULL);
+
+ res = gst_element_query_duration (GST_ELEMENT (bin), format, &duration);
+ fail_unless (res, NULL);
+
+ ck_assert_int_eq (duration, GST_CLOCK_TIME_NONE);
+
+ gst_element_set_state (bin, GST_STATE_NULL);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+
+static gboolean looped = FALSE;
+
+static void
+loop_segment_done (GstBus * bus, GstMessage * message, GstElement * bin)
+{
+ GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT,
+ GST_MESSAGE_SRC (message), message);
+
+ if (looped) {
+ g_main_loop_quit (main_loop);
+ } else {
+ GstEvent *seek_event;
+ gboolean res;
+
+ seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_SEGMENT,
+ GST_SEEK_TYPE_SET, (GstClockTime) 0,
+ GST_SEEK_TYPE_SET, (GstClockTime) 1 * GST_SECOND);
+
+ res = gst_element_send_event (bin, seek_event);
+ fail_unless (res == TRUE, NULL);
+ looped = TRUE;
+ }
+}
+
+GST_START_TEST (test_loop)
+{
+ GstElement *bin, *src1, *src2, *compositor, *sink;
+ GstBus *bus;
+ GstEvent *seek_event;
+ GstStateChangeReturn state_res;
+ gboolean res;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ bin = gst_pipeline_new ("pipeline");
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
+
+ src1 = gst_element_factory_make ("videotestsrc", "src1");
+ src2 = gst_element_factory_make ("videotestsrc", "src2");
+ compositor = gst_element_factory_make ("compositor", "compositor");
+ sink = gst_element_factory_make ("fakesink", "sink");
+ gst_bin_add_many (GST_BIN (bin), src1, src2, compositor, sink, NULL);
+
+ res = gst_element_link (src1, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (src2, compositor);
+ fail_unless (res == TRUE, NULL);
+ res = gst_element_link (compositor, sink);
+ fail_unless (res == TRUE, NULL);
+
+ seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, (GstClockTime) 0, GST_SEEK_TYPE_SET,
+ (GstClockTime) 2 * GST_SECOND);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (bus, "message::segment-done",
+ (GCallback) loop_segment_done, bin);
+ g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
+ g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
+
+ GST_INFO ("starting test");
+
+ /* prepare playing */
+ state_res = gst_element_set_state (bin, GST_STATE_PAUSED);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ /* wait for completion */
+ state_res =
+ gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
+ GST_CLOCK_TIME_NONE);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ res = gst_element_send_event (bin, seek_event);
+ fail_unless (res == TRUE, NULL);
+
+ /* run pipeline */
+ state_res = gst_element_set_state (bin, GST_STATE_PLAYING);
+ ck_assert_int_ne (state_res, GST_STATE_CHANGE_FAILURE);
+
+ GST_INFO ("running main loop");
+ g_main_loop_run (main_loop);
+
+ state_res = gst_element_set_state (bin, GST_STATE_NULL);
+
+ /* cleanup */
+ g_main_loop_unref (main_loop);
+ gst_bus_remove_signal_watch (bus);
+ gst_object_unref (bus);
+ gst_object_unref (bin);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_flush_start_flush_stop)
+{
+ GstPadTemplate *sink_template;
+ GstPad *sinkpad1, *sinkpad2, *compositor_src;
+ GstElement *compositor;
+
+ GST_INFO ("preparing test");
+
+ /* build pipeline */
+ compositor = gst_element_factory_make ("compositor", "compositor");
+
+ sink_template =
+ gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (compositor),
+ "sink_%u");
+ fail_unless (GST_IS_PAD_TEMPLATE (sink_template));
+ sinkpad1 = gst_element_request_pad (compositor, sink_template, NULL, NULL);
+ sinkpad2 = gst_element_request_pad (compositor, sink_template, NULL, NULL);
+ gst_object_unref (sinkpad2);
+
+ gst_element_set_state (compositor, GST_STATE_PLAYING);
+ fail_unless (gst_element_get_state (compositor, NULL, NULL,
+ GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_SUCCESS);
+
+ compositor_src = gst_element_get_static_pad (compositor, "src");
+ fail_if (GST_PAD_IS_FLUSHING (compositor_src));
+ gst_pad_send_event (sinkpad1, gst_event_new_flush_start ());
+ fail_if (GST_PAD_IS_FLUSHING (compositor_src));
+ fail_unless (GST_PAD_IS_FLUSHING (sinkpad1));
+ gst_pad_send_event (sinkpad1, gst_event_new_flush_stop (TRUE));
+ fail_if (GST_PAD_IS_FLUSHING (compositor_src));
+ fail_if (GST_PAD_IS_FLUSHING (sinkpad1));
+ gst_object_unref (compositor_src);
+
+ /* cleanup */
+ gst_element_set_state (compositor, GST_STATE_NULL);
+ gst_object_unref (compositor);
+}
+
+GST_END_TEST;
+
+
+static Suite *
+compositor_suite (void)
+{
+ Suite *s = suite_create ("compositor");
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_caps);
+ tcase_add_test (tc_chain, test_event);
+ tcase_add_test (tc_chain, test_play_twice);
+ tcase_add_test (tc_chain, test_play_twice_then_add_and_play_again);
+ tcase_add_test (tc_chain, test_add_pad);
+ tcase_add_test (tc_chain, test_remove_pad);
+ tcase_add_test (tc_chain, test_clip);
+ tcase_add_test (tc_chain, test_duration_is_max);
+ tcase_add_test (tc_chain, test_duration_unknown_overrides);
+ tcase_add_test (tc_chain, test_loop);
+ tcase_add_test (tc_chain, test_flush_start_flush_stop);
+
+ /* Use a longer timeout */
+#ifdef HAVE_VALGRIND
+ if (RUNNING_ON_VALGRIND) {
+ tcase_set_timeout (tc_chain, 5 * 60);
+ } else
+#endif
+ {
+ /* this is shorter than the default 60 seconds?! (tpm) */
+ /* tcase_set_timeout (tc_chain, 6); */
+ }
+
+ return s;
+}
+
+GST_CHECK_MAIN (compositor);