bayer2rgb: Convert to Orc

Seriously faster.  Algorithm is nearly the same as bilinear, which
given the speed of this code, should be considered the baseline of
quality.  Speed appears to be limited by memory bandwidth, so I
didn't bother trying to make it any faster.
This commit is contained in:
David Schleef 2011-05-30 23:43:39 -07:00
parent f0c75b06a7
commit db7fe611ed
5 changed files with 3640 additions and 260 deletions

View file

@ -1,16 +1,23 @@
plugin_LTLIBRARIES = libgstbayer.la
ORC_SOURCE=gstbayerorc
include $(top_srcdir)/common/orc.mak
libgstbayer_la_SOURCES = \
gstbayer.c \
gstbayer2rgb.c \
gstrgb2bayer.c \
gstrgb2bayer.h
libgstbayer_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
$(ORC_CFLAGS) \
$(GST_CFLAGS)
libgstbayer_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
$(ORC_LIBS) \
$(GST_BASE_LIBS)
libgstbayer_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstbayer_la_LIBTOOLFLAGS = --tag=disable-static
nodist_libgstbayer_la_SOURCES = $(ORC_NODIST_SOURCES)
Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \

View file

@ -80,7 +80,8 @@
#include <gst/video/video.h>
#include <string.h>
#include <stdlib.h>
#include "_stdint.h"
#include <_stdint.h>
#include "gstbayerorc.h"
#define GST_CAT_DEFAULT gst_bayer2rgb_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@ -125,7 +126,6 @@ struct _GstBayer2RGBClass
GstBaseTransformClass parent;
};
//#define SRC_CAPS GST_VIDEO_CAPS_RGBx
#define SRC_CAPS \
GST_VIDEO_CAPS_RGBx ";" \
GST_VIDEO_CAPS_xRGB ";" \
@ -134,9 +134,7 @@ struct _GstBayer2RGBClass
GST_VIDEO_CAPS_RGBA ";" \
GST_VIDEO_CAPS_ARGB ";" \
GST_VIDEO_CAPS_BGRA ";" \
GST_VIDEO_CAPS_ABGR ";" \
GST_VIDEO_CAPS_RGB ";" \
GST_VIDEO_CAPS_BGR
GST_VIDEO_CAPS_ABGR
#define SINK_CAPS "video/x-raw-bayer,format=(string){bggr,grbg,gbrg,rggb}," \
"width=(int)[1,MAX],height=(int)[1,MAX],framerate=(fraction)[0/1,MAX]"
@ -365,7 +363,6 @@ gst_bayer2rgb_get_unit_size (GstBaseTransform * base, GstCaps * caps,
name = gst_structure_get_name (structure);
/* Our name must be either video/x-raw-bayer video/x-raw-rgb */
if (strcmp (name, "video/x-raw-rgb")) {
/* For bayer, we handle only BA81 (BGGR), which is BPP=24 */
*size = GST_ROUND_UP_4 (width) * height;
return TRUE;
} else {
@ -382,282 +379,108 @@ gst_bayer2rgb_get_unit_size (GstBaseTransform * base, GstCaps * caps,
return FALSE;
}
#define RECONSTRUCT_SQUARE(x) \
do { \
int _h1 = next[i-1]; \
int _h2 = prev[i+1]; \
int _v1 = next[i+1]; \
int _v2 = prev[i-1]; \
(x) = (_h1+_h2+_v1+_v2+2)>>2; \
} while (0)
#define RECONSTRUCT_DIAMOND(x) \
do { \
int _h1 = src[i-1]; \
int _h2 = src[i+1]; \
int _v1 = next[i]; \
int _v2 = prev[i]; \
(x) = (_h1+_h2+_v1+_v2+2)>>2; \
} while (0)
#define RECONSTRUCT_HORIZ(x) \
do { \
(x) = (src[i-1] + src[i+1] + 1) >> 1; \
} while (0)
#define RECONSTRUCT_VERT(x) \
do { \
(x) = (next[i] + prev[i] + 1) >> 1; \
} while (0)
static void
reconstruct_blue_green (GstBayer2RGB * bayer2rgb, uint8_t * dest,
uint8_t * src, int src_stride, int blue_loc)
gst_bayer2rgb_split_and_upsample_horiz (guint8 * dest0, guint8 * dest1,
const guint8 * src, int n)
{
int i;
int r, g, b;
uint8_t *prev;
uint8_t *next;
int width = bayer2rgb->width;
prev = src - src_stride;
next = src + src_stride;
dest0[0] = src[0];
dest1[0] = src[1];
dest0[1] = (src[0] + src[2] + 1) >> 1;
dest1[1] = src[1];
i = 0;
if ((i & 1) == blue_loc) {
b = src[i];
r = (next[i + 1] + prev[i + 1] + 1) >> 1;
g = (next[i] + prev[i] + 1) >> 1;
} else {
b = src[i + 1];
r = (next[i] + prev[i] + 1) >> 1;
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
for (i = 1; i < width - 1; i++) {
if ((i & 1) == blue_loc) {
b = src[i];
RECONSTRUCT_SQUARE (r);
RECONSTRUCT_DIAMOND (g);
#if defined(__i386__) || defined(__amd64__)
gst_bayer_horiz_upsample_unaligned (dest0 + 2, dest1 + 2, src + 1,
(n - 4) >> 1);
#else
gst_bayer_horiz_upsample (dest0 + 2, dest1 + 2, src + 2, (n - 4) >> 1);
#endif
for (i = n - 2; i < n; i++) {
if ((i & 1) == 0) {
dest0[i] = src[i];
dest1[i] = src[i - 1];
} else {
RECONSTRUCT_HORIZ (b);
RECONSTRUCT_VERT (r);
g = src[i];
dest0[i] = src[i - 1];
dest1[i] = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
if ((i & 1) == blue_loc) {
b = src[i];
r = (next[i - 1] + prev[i - 1] + 1) >> 1;
g = (next[i] + prev[i] + 1) >> 1;
} else {
b = src[i - 1];
r = (next[i] + prev[i] + 1) >> 1;
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
static void
reconstruct_green_red (GstBayer2RGB * bayer2rgb, uint8_t * dest,
uint8_t * src, int src_stride, int red_loc)
{
int i;
int r, g, b;
uint8_t *prev;
uint8_t *next;
int width = bayer2rgb->width;
prev = src - src_stride;
next = src + src_stride;
i = 0;
if ((i & 1) == red_loc) {
r = src[i];
b = (next[i + 1] + prev[i + 1] + 1) >> 1;
g = (next[i] + prev[i] + 1) >> 1;
} else {
r = src[i + 1];
b = (next[i] + prev[i] + 1) >> 1;
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
for (i = 1; i < width - 1; i++) {
if ((i & 1) == red_loc) {
r = src[i];
RECONSTRUCT_SQUARE (b);
RECONSTRUCT_DIAMOND (g);
} else {
RECONSTRUCT_HORIZ (r);
RECONSTRUCT_VERT (b);
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
if ((i & 1) == red_loc) {
r = src[i];
b = (next[i - 1] + prev[i - 1] + 1) >> 1;
g = (next[i] + prev[i] + 1) >> 1;
} else {
r = src[i - 1];
b = (next[i] + prev[i] + 1) >> 1;
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
typedef void (*process_func) (guint8 * d0, const guint8 * s0, const guint8 * s1,
const guint8 * s2, const guint8 * s3, const guint8 * s4, const guint8 * s5,
int n);
static void
reconstruct_blue_green_edge (GstBayer2RGB * bayer2rgb, uint8_t * dest,
uint8_t * src, int src_stride, int blue_loc, int offset)
{
int i;
int r, g, b;
uint8_t *next;
int width = bayer2rgb->width;
next = src + offset * src_stride;
i = 0;
if ((i & 1) == blue_loc) {
b = src[i];
r = next[i + 1];
g = next[i];
} else {
b = src[i + 1];
r = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
for (i = 1; i < width - 1; i++) {
if ((i & 1) == blue_loc) {
b = src[i];
r = (next[i - 1] + next[i + 1] + 1) >> 1;
g = (src[i - 1] + src[i + 1] + 1) >> 1;
} else {
b = (src[i - 1] + src[i + 1] + 1) >> 1;
r = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
if ((i & 1) == blue_loc) {
b = src[i];
r = next[i - 1];
g = next[i];
} else {
b = src[i - 1];
r = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
static void
reconstruct_green_red_edge (GstBayer2RGB * bayer2rgb, uint8_t * dest,
uint8_t * src, int src_stride, int red_loc, int offset)
{
int i;
int r, g, b;
uint8_t *next;
int width = bayer2rgb->width;
next = src + offset * src_stride;
i = 0;
if ((i & 1) == red_loc) {
r = src[i];
b = next[i + 1];
g = next[i];
} else {
r = src[i + 1];
b = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
for (i = 1; i < width - 1; i++) {
if ((i & 1) == red_loc) {
r = src[i];
b = (next[i - 1] + next[i + 1] + 1) >> 1;
g = (src[i - 1] + src[i + 1] + 1) >> 1;
} else {
r = (src[i - 1] + src[i + 1] + 1) >> 1;
b = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
if ((i & 1) == red_loc) {
r = src[i];
b = next[i - 1];
g = next[i];
} else {
r = src[i - 1];
b = next[i];
g = src[i];
}
dest[i * 4 + bayer2rgb->r_off] = r;
dest[i * 4 + bayer2rgb->g_off] = g;
dest[i * 4 + bayer2rgb->b_off] = b;
}
static void
gst_bayer2rgb_process_ref (GstBayer2RGB * bayer2rgb, uint8_t * dest,
gst_bayer2rgb_process (GstBayer2RGB * bayer2rgb, uint8_t * dest,
int dest_stride, uint8_t * src, int src_stride)
{
int j;
int format = bayer2rgb->format;
guint8 *tmp;
process_func merge[2] = { NULL, NULL };
int r_off, g_off, b_off;
/* We exploit some symmetry in the functions here. The base functions
* are all named for the BGGR arrangement. For RGGB, we swap the
* red offset and blue offset in the output. For GRBG, we swap the
* order of the merge functions. For GBRG, do both. */
r_off = bayer2rgb->r_off;
g_off = bayer2rgb->g_off;
b_off = bayer2rgb->b_off;
if (bayer2rgb->format == GST_BAYER_2_RGB_FORMAT_RGGB ||
bayer2rgb->format == GST_BAYER_2_RGB_FORMAT_GBRG) {
r_off = bayer2rgb->b_off;
b_off = bayer2rgb->r_off;
}
if (r_off == 2 && g_off == 1 && b_off == 0) {
merge[0] = gst_bayer_merge_bg_bgra;
merge[1] = gst_bayer_merge_gr_bgra;
} else if (r_off == 3 && g_off == 2 && b_off == 1) {
merge[0] = gst_bayer_merge_bg_abgr;
merge[1] = gst_bayer_merge_gr_abgr;
} else if (r_off == 1 && g_off == 2 && b_off == 3) {
merge[0] = gst_bayer_merge_bg_argb;
merge[1] = gst_bayer_merge_gr_argb;
} else if (r_off == 0 && g_off == 1 && b_off == 2) {
merge[0] = gst_bayer_merge_bg_rgba;
merge[1] = gst_bayer_merge_gr_rgba;
}
if (bayer2rgb->format == GST_BAYER_2_RGB_FORMAT_GRBG ||
bayer2rgb->format == GST_BAYER_2_RGB_FORMAT_GBRG) {
process_func tmp = merge[0];
merge[0] = merge[1];
merge[1] = tmp;
}
tmp = g_malloc (2 * 4 * bayer2rgb->width);
#define LINE(x) (tmp + ((x)&7) * bayer2rgb->width)
gst_bayer2rgb_split_and_upsample_horiz (LINE (3 * 2 + 0), LINE (3 * 2 + 1),
src + 1 * src_stride, bayer2rgb->width);
j = 0;
if ((j & 1) == (format & 2) >> 1) {
reconstruct_blue_green_edge (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, format & 1, 1);
} else {
reconstruct_green_red_edge (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, (format & 1) ^ 1, 1);
}
for (j = 1; j < bayer2rgb->height - 1; j++) {
if ((j & 1) == (format & 2) >> 1) {
reconstruct_blue_green (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, format & 1);
} else {
reconstruct_green_red (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, (format & 1) ^ 1);
gst_bayer2rgb_split_and_upsample_horiz (LINE (j * 2 + 0), LINE (j * 2 + 1),
src + j * src_stride, bayer2rgb->width);
for (j = 0; j < bayer2rgb->height; j++) {
if (j < bayer2rgb->height - 1) {
gst_bayer2rgb_split_and_upsample_horiz (LINE ((j + 1) * 2 + 0),
LINE ((j + 1) * 2 + 1), src + (j + 1) * src_stride, bayer2rgb->width);
}
}
if ((j & 1) == (format & 2) >> 1) {
reconstruct_blue_green_edge (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, format & 1, -1);
} else {
reconstruct_green_red_edge (bayer2rgb, dest + j * dest_stride,
src + j * src_stride, src_stride, (format & 1) ^ 1, -1);
merge[j & 1] (dest + j * dest_stride,
LINE (j * 2 - 2), LINE (j * 2 - 1),
LINE (j * 2 + 0), LINE (j * 2 + 1),
LINE (j * 2 + 2), LINE (j * 2 + 3), bayer2rgb->width >> 1);
}
g_free (tmp);
}
static GstFlowReturn
gst_bayer2rgb_transform (GstBaseTransform * base, GstBuffer * inbuf,
GstBuffer * outbuf)
@ -675,7 +498,7 @@ gst_bayer2rgb_transform (GstBaseTransform * base, GstBuffer * inbuf,
GST_DEBUG ("transforming buffer");
input = (uint8_t *) GST_BUFFER_DATA (inbuf);
output = (uint8_t *) GST_BUFFER_DATA (outbuf);
gst_bayer2rgb_process_ref (filter, output, filter->width * 4,
gst_bayer2rgb_process (filter, output, filter->width * 4,
input, filter->width);
GST_OBJECT_UNLOCK (filter);

3212
gst/bayer/gstbayerorc-dist.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,86 @@
/* autogenerated from gstbayerorc.orc */
#ifndef _GSTBAYERORC_H_
#define _GSTBAYERORC_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
void gst_bayer_horiz_upsample_unaligned (guint8 * ORC_RESTRICT d1, guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, int n);
void gst_bayer_horiz_upsample (guint8 * ORC_RESTRICT d1, guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, int n);
void gst_bayer_merge_bg_bgra (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_gr_bgra (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_bg_abgr (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_gr_abgr (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_bg_rgba (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_gr_rgba (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_bg_argb (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
void gst_bayer_merge_gr_argb (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, const guint8 * ORC_RESTRICT s5, const guint8 * ORC_RESTRICT s6, int n);
#ifdef __cplusplus
}
#endif
#endif

252
gst/bayer/gstbayerorc.orc Normal file
View file

@ -0,0 +1,252 @@
.function gst_bayer_horiz_upsample_unaligned
.dest 2 d0 guint8
.dest 2 d1 guint8
.source 2 s guint8
.temp 2 t
.temp 1 b
.temp 1 c
.temp 1 d
.temp 1 e
splitwb c, b, s
loadoffw t, s, 1
splitwb e, d, t
avgub e, c, e
mergebw d0, c, e
avgub b, b, d
mergebw d1, b, d
.function gst_bayer_horiz_upsample
.dest 2 d0 guint8
.dest 2 d1 guint8
.source 2 s guint8
.temp 2 t
.temp 1 a
.temp 1 b
.temp 1 c
.temp 1 d
.temp 1 e
.temp 1 f
loadoffw t, s, -1
splitwb b, a, t
splitwb d, c, s
loadoffw t, s, 1
splitwb f, e, t
avgub e, c, e
mergebw d0, c, e
avgub b, b, d
mergebw d1, b, d
.function gst_bayer_merge_bg_bgra
.dest 8 d guint8
.source 2 g0 guint8
.source 2 r0 guint8
.source 2 b1 guint8
.source 2 g1 guint8
.source 2 g2 guint8
.source 2 r2 guint8
.temp 4 ra
.temp 4 bg
.temp 2 r
.temp 2 g
.temp 2 t
x2 avgub r, r0, r2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 255
andw t, t, 65280
orw g, t, g
x2 mergebw bg, b1, g
x2 mergebw ra, r, 255
x2 mergewl d, bg, ra
.function gst_bayer_merge_gr_bgra
.dest 8 d guint8
.source 2 b0 guint8
.source 2 g0 guint8
.source 2 g1 guint8
.source 2 r1 guint8
.source 2 b2 guint8
.source 2 g2 guint8
.temp 4 ra
.temp 4 bg
.temp 2 b
.temp 2 g
.temp 2 t
x2 avgub b, b0, b2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 65280
andw t, t, 255
orw g, t, g
x2 mergebw bg, b, g
x2 mergebw ra, r1, 255
x2 mergewl d, bg, ra
.function gst_bayer_merge_bg_abgr
.dest 8 d guint8
.source 2 g0 guint8
.source 2 r0 guint8
.source 2 b1 guint8
.source 2 g1 guint8
.source 2 g2 guint8
.source 2 r2 guint8
.temp 4 ab
.temp 4 gr
.temp 2 r
.temp 2 g
.temp 2 t
x2 avgub r, r0, r2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 255
andw t, t, 65280
orw g, t, g
x2 mergebw ab, 255, b1
x2 mergebw gr, g, r
x2 mergewl d, ab, gr
.function gst_bayer_merge_gr_abgr
.dest 8 d guint8
.source 2 b0 guint8
.source 2 g0 guint8
.source 2 g1 guint8
.source 2 r1 guint8
.source 2 b2 guint8
.source 2 g2 guint8
.temp 4 ab
.temp 4 gr
.temp 2 b
.temp 2 g
.temp 2 t
x2 avgub b, b0, b2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 65280
andw t, t, 255
orw g, t, g
x2 mergebw ab, 255, b
x2 mergebw gr, g, r1
x2 mergewl d, ab, gr
.function gst_bayer_merge_bg_rgba
.dest 8 d guint8
.source 2 g0 guint8
.source 2 r0 guint8
.source 2 b1 guint8
.source 2 g1 guint8
.source 2 g2 guint8
.source 2 r2 guint8
.temp 4 rg
.temp 4 ba
.temp 2 r
.temp 2 g
.temp 2 t
x2 avgub r, r0, r2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 255
andw t, t, 65280
orw g, t, g
x2 mergebw rg, r, g
x2 mergebw ba, b1, 255
x2 mergewl d, rg, ba
.function gst_bayer_merge_gr_rgba
.dest 8 d guint8
.source 2 b0 guint8
.source 2 g0 guint8
.source 2 g1 guint8
.source 2 r1 guint8
.source 2 b2 guint8
.source 2 g2 guint8
.temp 4 rg
.temp 4 ba
.temp 2 b
.temp 2 g
.temp 2 t
x2 avgub b, b0, b2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 65280
andw t, t, 255
orw g, t, g
x2 mergebw rg, r1, g
x2 mergebw ba, b, 255
x2 mergewl d, rg, ba
.function gst_bayer_merge_bg_argb
.dest 8 d guint8
.source 2 g0 guint8
.source 2 r0 guint8
.source 2 b1 guint8
.source 2 g1 guint8
.source 2 g2 guint8
.source 2 r2 guint8
.temp 4 ar
.temp 4 gb
.temp 2 r
.temp 2 g
.temp 2 t
x2 avgub r, r0, r2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 255
andw t, t, 65280
orw g, t, g
x2 mergebw ar, 255, r
x2 mergebw gb, g, b1
x2 mergewl d, ar, gb
.function gst_bayer_merge_gr_argb
.dest 8 d guint8
.source 2 b0 guint8
.source 2 g0 guint8
.source 2 g1 guint8
.source 2 r1 guint8
.source 2 b2 guint8
.source 2 g2 guint8
.temp 4 ar
.temp 4 gb
.temp 2 b
.temp 2 g
.temp 2 t
x2 avgub b, b0, b2
x2 avgub g, g0, g2
copyw t, g1
x2 avgub g, g, t
andw g, g, 65280
andw t, t, 255
orw g, t, g
x2 mergebw ar, 255, r1
x2 mergebw gb, g, b
x2 mergewl d, ar, gb