mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 10:41:04 +00:00
1734 lines
46 KiB
C
1734 lines
46 KiB
C
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#define COG_ENABLE_UNSTABLE_API 1
|
|
|
|
#include <cog-video/cogvirtframe.h>
|
|
#include <cog-video/cogorc.h>
|
|
#include <cog/cog.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <orc/orc.h>
|
|
|
|
|
|
CogFrame *
|
|
cog_frame_new_virtual (CogMemoryDomain * domain, CogFrameFormat format,
|
|
int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
int bytes_pp;
|
|
int h_shift, v_shift;
|
|
int chroma_width;
|
|
int chroma_height;
|
|
int i;
|
|
|
|
frame->format = format;
|
|
frame->width = width;
|
|
frame->height = height;
|
|
frame->domain = domain;
|
|
|
|
if (COG_FRAME_IS_PACKED (format)) {
|
|
frame->components[0].format = format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
if (format == COG_FRAME_FORMAT_AYUV) {
|
|
frame->components[0].stride = width * 4;
|
|
} else if (format == COG_FRAME_FORMAT_v216) {
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 4;
|
|
} else if (format == COG_FRAME_FORMAT_v210) {
|
|
frame->components[0].stride = ((width + 47) / 48) * 128;
|
|
} else {
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 2;
|
|
}
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
|
|
frame->components[0].data = frame->regions[0];
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->regions[0] =
|
|
malloc (frame->components[0].stride * COG_FRAME_CACHE_SIZE);
|
|
for (i = 0; i < COG_FRAME_CACHE_SIZE; i++) {
|
|
frame->cached_lines[0][i] = -1;
|
|
}
|
|
frame->is_virtual = TRUE;
|
|
|
|
return frame;
|
|
}
|
|
|
|
switch (COG_FRAME_FORMAT_DEPTH (format)) {
|
|
case COG_FRAME_FORMAT_DEPTH_U8:
|
|
bytes_pp = 1;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S16:
|
|
bytes_pp = 2;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S32:
|
|
bytes_pp = 4;
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
bytes_pp = 0;
|
|
break;
|
|
}
|
|
|
|
h_shift = COG_FRAME_FORMAT_H_SHIFT (format);
|
|
v_shift = COG_FRAME_FORMAT_V_SHIFT (format);
|
|
chroma_width = ROUND_UP_SHIFT (width, h_shift);
|
|
chroma_height = ROUND_UP_SHIFT (height, v_shift);
|
|
|
|
frame->components[0].format = format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_4 (width * bytes_pp);
|
|
frame->components[0].length =
|
|
frame->components[0].stride * frame->components[0].height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[1].format = format;
|
|
frame->components[1].width = chroma_width;
|
|
frame->components[1].height = chroma_height;
|
|
frame->components[1].stride = ROUND_UP_4 (chroma_width * bytes_pp);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * frame->components[1].height;
|
|
frame->components[1].v_shift = v_shift;
|
|
frame->components[1].h_shift = h_shift;
|
|
|
|
frame->components[2].format = format;
|
|
frame->components[2].width = chroma_width;
|
|
frame->components[2].height = chroma_height;
|
|
frame->components[2].stride = ROUND_UP_4 (chroma_width * bytes_pp);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * frame->components[2].height;
|
|
frame->components[2].v_shift = v_shift;
|
|
frame->components[2].h_shift = h_shift;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
CogFrameData *comp = &frame->components[i];
|
|
int j;
|
|
|
|
frame->regions[i] = malloc (comp->stride * COG_FRAME_CACHE_SIZE);
|
|
for (j = 0; j < COG_FRAME_CACHE_SIZE; j++) {
|
|
frame->cached_lines[i][j] = -1;
|
|
}
|
|
}
|
|
frame->is_virtual = TRUE;
|
|
|
|
return frame;
|
|
}
|
|
|
|
void *
|
|
cog_virt_frame_get_line (CogFrame * frame, int component, int i)
|
|
{
|
|
CogFrameData *comp = &frame->components[component];
|
|
int j;
|
|
int min;
|
|
int min_j;
|
|
|
|
//COG_ASSERT(i >= 0);
|
|
//COG_ASSERT(i < comp->height);
|
|
|
|
if (!frame->is_virtual) {
|
|
return COG_FRAME_DATA_GET_LINE (&frame->components[component], i);
|
|
}
|
|
|
|
for (j = 0; j < COG_FRAME_CACHE_SIZE; j++) {
|
|
if (frame->cached_lines[component][j] == i) {
|
|
return COG_OFFSET (frame->regions[component], comp->stride * j);
|
|
}
|
|
}
|
|
|
|
min_j = 0;
|
|
min = frame->cached_lines[component][0];
|
|
for (j = 1; j < COG_FRAME_CACHE_SIZE; j++) {
|
|
if (frame->cached_lines[component][j] < min) {
|
|
min = frame->cached_lines[component][j];
|
|
min_j = j;
|
|
}
|
|
}
|
|
frame->cached_lines[component][min_j] = i;
|
|
|
|
cog_virt_frame_render_line (frame,
|
|
COG_OFFSET (frame->regions[component], comp->stride * min_j),
|
|
component, i);
|
|
|
|
return COG_OFFSET (frame->regions[component], comp->stride * min_j);
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render_line (CogFrame * frame, void *dest, int component, int i)
|
|
{
|
|
frame->render_line (frame, dest, component, i);
|
|
}
|
|
|
|
static void
|
|
copy (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame, component, i);
|
|
switch (COG_FRAME_FORMAT_DEPTH (frame->format)) {
|
|
case COG_FRAME_FORMAT_DEPTH_U8:
|
|
orc_memcpy (dest, src, frame->components[component].width);
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S16:
|
|
orc_memcpy (dest, src, frame->components[component].width * 2);
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render (CogFrame * frame, CogFrame * dest)
|
|
{
|
|
int i, k;
|
|
|
|
COG_ASSERT (frame->width == dest->width);
|
|
COG_ASSERT (frame->height >= dest->height);
|
|
|
|
if (frame->is_virtual) {
|
|
for (k = 0; k < 3; k++) {
|
|
CogFrameData *comp = dest->components + k;
|
|
|
|
for (i = 0; i < dest->components[k].height; i++) {
|
|
cog_virt_frame_render_line (frame,
|
|
COG_FRAME_DATA_GET_LINE (comp, i), k, i);
|
|
}
|
|
}
|
|
} else {
|
|
for (k = 0; k < 3; k++) {
|
|
CogFrameData *comp = dest->components + k;
|
|
|
|
for (i = 0; i < dest->components[k].height; i++) {
|
|
copy (frame, COG_FRAME_DATA_GET_LINE (comp, i), k, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
cog_virt_frame_render_downsample_horiz_cosite_3tap (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int n_src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
n_src = frame->virt_frame1->components[component].width;
|
|
|
|
cogorc_downsample_horiz_cosite_3tap (dest + 1,
|
|
(uint16_t *) (src + 1), (uint16_t *) (src + 3),
|
|
frame->components[component].width - 1);
|
|
|
|
{
|
|
int j;
|
|
int x;
|
|
|
|
j = 0;
|
|
x = 1 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
|
|
x += 2 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
|
|
x += 1 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
|
|
dest[j] = CLAMP ((x + 2) >> 2, 0, 255);
|
|
|
|
#if 0
|
|
j = frame->components[component].width - 1;
|
|
x = 1 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
|
|
x += 2 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
|
|
x += 1 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
|
|
dest[j] = CLAMP ((x + 2) >> 2, 0, 255);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render_downsample_horiz_halfsite (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int j;
|
|
int n_src;
|
|
int taps = 4;
|
|
int k;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
n_src = frame->virt_frame1->components[component].width;
|
|
|
|
switch (taps) {
|
|
case 4:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
x += 6 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
|
|
x += 26 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
|
|
x += 26 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
|
|
x += 6 * src[CLAMP (j * 2 + 2, 0, n_src - 1)];
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
case 6:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
x += -3 * src[CLAMP (j * 2 - 2, 0, n_src - 1)];
|
|
x += 8 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
|
|
x += 27 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
|
|
x += 27 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
|
|
x += 8 * src[CLAMP (j * 2 + 2, 0, n_src - 1)];
|
|
x += -3 * src[CLAMP (j * 2 + 3, 0, n_src - 1)];
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
case 8:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
const int taps8[8] = { -2, -4, 9, 29, 29, 9, -4, -2 };
|
|
for (k = 0; k < 8; k++) {
|
|
x += taps8[k] * src[CLAMP (j * 2 - 3 + k, 0, n_src - 1)];
|
|
}
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
case 10:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
const int taps10[10] = { 1, -2, -5, 9, 29, 29, 9, -5, -2, 1 };
|
|
for (k = 0; k < 10; k++) {
|
|
x += taps10[k] * src[CLAMP (j * 2 - 4 + k, 0, n_src - 1)];
|
|
}
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_horiz_downsample (CogFrame * vf, int n_taps)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame =
|
|
cog_frame_new_virtual (NULL, vf->format, vf->width / 2, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->param1 = n_taps;
|
|
switch (n_taps) {
|
|
case 3:
|
|
virt_frame->render_line =
|
|
cog_virt_frame_render_downsample_horiz_cosite_3tap;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
case 8:
|
|
case 10:
|
|
virt_frame->render_line = cog_virt_frame_render_downsample_horiz_halfsite;
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
return NULL;
|
|
}
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render_downsample_vert_cosite (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
uint8_t *src3;
|
|
int n_src;
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 - 1, 0, n_src - 1));
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 0, 0, n_src - 1));
|
|
src3 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 1, 0, n_src - 1));
|
|
|
|
cogorc_downsample_vert_halfsite_3tap (dest, src1, src2, src3,
|
|
frame->components[component].width);
|
|
}
|
|
|
|
static void
|
|
cog_virt_frame_render_downsample_vert_halfsite_2tap (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
//static OrcProgram *p = NULL;
|
|
//OrcExecutor _ex, *ex = &_ex;
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
int n_src;
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2, 0, n_src - 1));
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 1, 0, n_src - 1));
|
|
|
|
cogorc_downsample_vert_halfsite_2tap (dest, src1, src2,
|
|
frame->components[component].width);
|
|
}
|
|
|
|
static void
|
|
cog_virt_frame_render_downsample_vert_halfsite_4tap (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
//static OrcProgram *p = NULL;
|
|
//OrcExecutor _ex, *ex = &_ex;
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
uint8_t *src3;
|
|
uint8_t *src4;
|
|
int n_src;
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 - 1, 0, n_src - 1));
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2, 0, n_src - 1));
|
|
src3 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 1, 0, n_src - 1));
|
|
src4 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 2, 0, n_src - 1));
|
|
|
|
cogorc_downsample_vert_halfsite_4tap (dest, src1, src2, src3, src4,
|
|
frame->components[component].width);
|
|
}
|
|
|
|
|
|
void
|
|
cog_virt_frame_render_downsample_vert_halfsite (CogFrame * frame,
|
|
void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src[10];
|
|
int j;
|
|
int n_src;
|
|
int taps = frame->param1;
|
|
int k;
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
for (j = 0; j < taps; j++) {
|
|
src[j] = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 - (taps - 2) / 2 + j, 0, n_src - 1));
|
|
}
|
|
|
|
switch (taps) {
|
|
case 4:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
x += 6 * src[0][j];
|
|
x += 26 * src[1][j];
|
|
x += 26 * src[2][j];
|
|
x += 6 * src[3][j];
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
case 6:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
x += -3 * src[0][j];
|
|
x += 8 * src[1][j];
|
|
x += 27 * src[2][j];
|
|
x += 27 * src[3][j];
|
|
x += 8 * src[4][j];
|
|
x += -3 * src[5][j];
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
case 8:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
const int taps8[8] = { -2, -4, 9, 29, 29, 9, -4, -2 };
|
|
for (k = 0; k < 8; k++) {
|
|
x += taps8[k] * src[k][j];
|
|
}
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
case 10:
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
int x = 0;
|
|
const int taps10[10] = { 1, -2, -5, 9, 29, 29, 9, -5, -2, 1 };
|
|
//const int taps10[10] = { -1, 1, 6, 11, 15, 15, 11, 6, 1, -1 };
|
|
for (k = 0; k < 10; k++) {
|
|
x += taps10[k] * src[k][j];
|
|
}
|
|
dest[j] = CLAMP ((x + 32) >> 6, 0, 255);
|
|
}
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_vert_downsample (CogFrame * vf, int n_taps)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame =
|
|
cog_frame_new_virtual (NULL, vf->format, vf->width, vf->height / 2);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->param1 = n_taps;
|
|
switch (n_taps) {
|
|
case 2:
|
|
virt_frame->render_line =
|
|
cog_virt_frame_render_downsample_vert_halfsite_2tap;
|
|
break;
|
|
case 3:
|
|
virt_frame->render_line = cog_virt_frame_render_downsample_vert_cosite;
|
|
break;
|
|
case 4:
|
|
virt_frame->render_line =
|
|
cog_virt_frame_render_downsample_vert_halfsite_4tap;
|
|
break;
|
|
default:
|
|
virt_frame->render_line = cog_virt_frame_render_downsample_vert_halfsite;
|
|
break;
|
|
}
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
void
|
|
get_taps (double *taps, double x)
|
|
{
|
|
taps[3] = x * x * (x - 1);
|
|
taps[2] = x * (-x * x + x + 1);
|
|
x = 1 - x;
|
|
taps[1] = x * (-x * x + x + 1);
|
|
taps[0] = x * x * (x - 1);
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render_resample_vert (CogFrame * frame, void *_dest,
|
|
int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
uint8_t *src3;
|
|
uint8_t *src4;
|
|
int n_src;
|
|
double taps[4];
|
|
double *scale = (double *) frame->virt_priv;
|
|
double x;
|
|
int src_i;
|
|
|
|
x = (*scale) * i;
|
|
src_i = floor (x);
|
|
get_taps (taps, x - floor (x));
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (src_i - 1, 0, n_src - 1));
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (src_i + 0, 0, n_src - 1));
|
|
src3 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (src_i + 1, 0, n_src - 1));
|
|
src4 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (src_i + 2, 0, n_src - 1));
|
|
|
|
cogorc_combine4_u8 (dest, src1, src2, src3, src4,
|
|
rint (taps[0] * 64.0), rint (taps[1] * 64.0),
|
|
rint (taps[2] * 64.0), rint (taps[3] * 64.0),
|
|
frame->components[component].width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_vert_resample (CogFrame * vf, int height)
|
|
{
|
|
CogFrame *virt_frame;
|
|
double *scale;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, vf->format, vf->width, height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = cog_virt_frame_render_resample_vert;
|
|
|
|
scale = malloc (sizeof (double));
|
|
virt_frame->virt_priv = scale;
|
|
|
|
*scale = (double) vf->height / height;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
void
|
|
cog_virt_frame_render_resample_horiz (CogFrame * frame, void *_dest,
|
|
int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int j;
|
|
int n_src;
|
|
double taps[4];
|
|
double *scale = (double *) frame->virt_priv;
|
|
int src_i;
|
|
|
|
n_src = frame->virt_frame1->components[component].width;
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
|
|
for (j = 0; j < frame->components[component].width; j++) {
|
|
double x;
|
|
double y = 0;
|
|
|
|
x = (*scale) * j;
|
|
src_i = floor (x);
|
|
get_taps (taps, x - floor (x));
|
|
|
|
y = 0;
|
|
y += taps[0] * src[CLAMP (src_i - 1, 0, n_src - 1)];
|
|
y += taps[1] * src[CLAMP (src_i + 0, 0, n_src - 1)];
|
|
y += taps[2] * src[CLAMP (src_i + 1, 0, n_src - 1)];
|
|
y += taps[3] * src[CLAMP (src_i + 2, 0, n_src - 1)];
|
|
dest[j] = CLAMP (rint (y), 0, 255);
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_horiz_resample (CogFrame * vf, int width)
|
|
{
|
|
CogFrame *virt_frame;
|
|
double *scale;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, vf->format, width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = cog_virt_frame_render_resample_horiz;
|
|
|
|
scale = malloc (sizeof (double));
|
|
virt_frame->virt_priv = scale;
|
|
|
|
*scale = (double) vf->width / width;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
unpack_yuyv (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
|
|
switch (component) {
|
|
case 0:
|
|
orc_unpack_yuyv_y (dest, (void *) src, frame->width);
|
|
break;
|
|
case 1:
|
|
orc_unpack_yuyv_u (dest, (void *) src, frame->width / 2);
|
|
break;
|
|
case 2:
|
|
orc_unpack_yuyv_v (dest, (void *) src, frame->width / 2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
unpack_uyvy (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
|
|
switch (component) {
|
|
case 0:
|
|
orc_unpack_uyvy_y (dest, (void *) src, frame->width);
|
|
break;
|
|
case 1:
|
|
orc_unpack_uyvy_u (dest, (void *) src, frame->width / 2);
|
|
break;
|
|
case 2:
|
|
orc_unpack_uyvy_v (dest, (void *) src, frame->width / 2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
unpack_ayuv (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint32_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
|
|
switch (component) {
|
|
case 0:
|
|
cogorc_unpack_ayuv_y (dest, src, frame->width);
|
|
break;
|
|
case 1:
|
|
cogorc_unpack_ayuv_y (dest, src, frame->width);
|
|
break;
|
|
case 2:
|
|
cogorc_unpack_ayuv_v (dest, src, frame->width);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
unpack_v210 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int j;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
|
|
#define READ_UINT32_LE(a) (((uint8_t *)(a))[0] | (((uint8_t *)(a))[1]<<8) | \
|
|
(((uint8_t *)(a))[2]<<16) | (((uint8_t *)(a))[3]<<24))
|
|
switch (component) {
|
|
case 0:
|
|
for (j = 0; j < frame->width / 6; j++) {
|
|
dest[j * 6 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 10) & 0x3ff) >> 2;
|
|
dest[j * 6 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 0) & 0x3ff) >> 2;
|
|
dest[j * 6 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 20) & 0x3ff) >> 2;
|
|
dest[j * 6 + 3] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 10) & 0x3ff) >> 2;
|
|
dest[j * 6 + 4] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 0) & 0x3ff) >> 2;
|
|
dest[j * 6 + 5] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 0 < frame->width) {
|
|
dest[j * 6 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 10) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 1 < frame->width) {
|
|
dest[j * 6 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 0) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 2 < frame->width) {
|
|
dest[j * 6 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 3 < frame->width) {
|
|
dest[j * 6 + 3] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 10) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 4 < frame->width) {
|
|
dest[j * 6 + 4] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 0) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 5 < frame->width) {
|
|
dest[j * 6 + 5] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
break;
|
|
case 1:
|
|
for (j = 0; j < frame->width / 6; j++) {
|
|
dest[j * 3 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 0) & 0x3ff) >> 2;
|
|
dest[j * 3 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 10) & 0x3ff) >> 2;
|
|
dest[j * 3 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 0 < frame->width) {
|
|
dest[j * 3 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 0) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 2 < frame->width) {
|
|
dest[j * 3 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 4) >> 10) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 4 < frame->width) {
|
|
dest[j * 3 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
break;
|
|
case 2:
|
|
for (j = 0; j < frame->width / 6; j++) {
|
|
dest[j * 3 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 20) & 0x3ff) >> 2;
|
|
dest[j * 3 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 0) & 0x3ff) >> 2;
|
|
dest[j * 3 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 10) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 0 < frame->width) {
|
|
dest[j * 3 + 0] =
|
|
((READ_UINT32_LE (src + j * 16 + 0) >> 20) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 2 < frame->width) {
|
|
dest[j * 3 + 1] =
|
|
((READ_UINT32_LE (src + j * 16 + 8) >> 0) & 0x3ff) >> 2;
|
|
}
|
|
if (j * 6 + 4 < frame->width) {
|
|
dest[j * 3 + 2] =
|
|
((READ_UINT32_LE (src + j * 16 + 12) >> 10) & 0x3ff) >> 2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
unpack_v216 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int j;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
|
|
switch (component) {
|
|
case 0:
|
|
for (j = 0; j < frame->width; j++) {
|
|
dest[j] = src[j * 4 + 2 + 1];
|
|
}
|
|
break;
|
|
case 1:
|
|
for (j = 0; j < frame->width / 2; j++) {
|
|
dest[j] = src[j * 8 + 0 + 1];
|
|
}
|
|
break;
|
|
case 2:
|
|
for (j = 0; j < frame->width / 2; j++) {
|
|
dest[j] = src[j * 8 + 4 + 1];
|
|
}
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_unpack (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
CogFrameFormat format;
|
|
CogFrameRenderFunc render_line;
|
|
|
|
switch (vf->format) {
|
|
case COG_FRAME_FORMAT_YUYV:
|
|
format = COG_FRAME_FORMAT_U8_422;
|
|
render_line = unpack_yuyv;
|
|
break;
|
|
case COG_FRAME_FORMAT_UYVY:
|
|
format = COG_FRAME_FORMAT_U8_422;
|
|
render_line = unpack_uyvy;
|
|
break;
|
|
case COG_FRAME_FORMAT_AYUV:
|
|
format = COG_FRAME_FORMAT_U8_444;
|
|
render_line = unpack_ayuv;
|
|
break;
|
|
case COG_FRAME_FORMAT_v210:
|
|
format = COG_FRAME_FORMAT_U8_422;
|
|
render_line = unpack_v210;
|
|
break;
|
|
case COG_FRAME_FORMAT_v216:
|
|
format = COG_FRAME_FORMAT_U8_422;
|
|
render_line = unpack_v216;
|
|
break;
|
|
default:
|
|
return vf;
|
|
}
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, format, vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = render_line;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
|
|
static void
|
|
pack_yuyv (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_yuyv (dest, src_y, src_u, src_v, frame->width / 2);
|
|
}
|
|
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_YUY2 (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_YUYV,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_yuyv;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_uyvy (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_uyvy (dest, src_y, src_u, src_v, frame->width / 2);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_UYVY (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_YUYV,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_uyvy;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_v216 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
int j;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
for (j = 0; j < frame->width / 2; j++) {
|
|
dest[j * 8 + 0] = src_u[j];
|
|
dest[j * 8 + 1] = src_u[j];
|
|
dest[j * 8 + 2] = src_y[j * 2 + 0];
|
|
dest[j * 8 + 3] = src_y[j * 2 + 0];
|
|
dest[j * 8 + 4] = src_v[j];
|
|
dest[j * 8 + 5] = src_v[j];
|
|
dest[j * 8 + 6] = src_y[j * 2 + 1];
|
|
dest[j * 8 + 7] = src_y[j * 2 + 1];
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_v216 (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_v216,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_v216;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_v210 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
int j;
|
|
uint32_t val;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
#define TO_10(x) (((x)<<2) | ((x)>>6))
|
|
#define WRITE_UINT32_LE(a,b) do { \
|
|
((uint8_t *)(a))[0] = (b)&0xff; \
|
|
((uint8_t *)(a))[1] = ((b)>>8)&0xff; \
|
|
((uint8_t *)(a))[2] = ((b)>>16)&0xff; \
|
|
((uint8_t *)(a))[3] = ((b)>>24)&0xff; \
|
|
} while(0)
|
|
for (j = 0; j < frame->width / 6; j++) {
|
|
int y0, y1, y2, y3, y4, y5;
|
|
int cr0, cr1, cr2;
|
|
int cb0, cb1, cb2;
|
|
|
|
y0 = TO_10 (src_y[j * 6 + 0]);
|
|
y1 = TO_10 (src_y[j * 6 + 1]);
|
|
y2 = TO_10 (src_y[j * 6 + 2]);
|
|
y3 = TO_10 (src_y[j * 6 + 3]);
|
|
y4 = TO_10 (src_y[j * 6 + 4]);
|
|
y5 = TO_10 (src_y[j * 6 + 5]);
|
|
cb0 = TO_10 (src_u[j * 3 + 0]);
|
|
cb1 = TO_10 (src_u[j * 3 + 1]);
|
|
cb2 = TO_10 (src_u[j * 3 + 2]);
|
|
cr0 = TO_10 (src_v[j * 3 + 0]);
|
|
cr1 = TO_10 (src_v[j * 3 + 1]);
|
|
cr2 = TO_10 (src_v[j * 3 + 2]);
|
|
|
|
val = (cr0 << 20) | (y0 << 10) | (cb0);
|
|
WRITE_UINT32_LE (dest + j * 16 + 0, val);
|
|
|
|
val = (y2 << 20) | (cb1 << 10) | (y1);
|
|
WRITE_UINT32_LE (dest + j * 16 + 4, val);
|
|
|
|
val = (cb2 << 20) | (y3 << 10) | (cr1);
|
|
WRITE_UINT32_LE (dest + j * 16 + 8, val);
|
|
|
|
val = (y5 << 20) | (cr2 << 10) | (y4);
|
|
WRITE_UINT32_LE (dest + j * 16 + 12, val);
|
|
}
|
|
if (j * 6 < frame->width) {
|
|
int y0, y1, y2, y3, y4, y5;
|
|
int cr0, cr1, cr2;
|
|
int cb0, cb1, cb2;
|
|
|
|
y0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_y[j * 6 + 0]) : 0;
|
|
y1 = ((j * 6 + 1) < frame->width) ? TO_10 (src_y[j * 6 + 1]) : 0;
|
|
y2 = ((j * 6 + 2) < frame->width) ? TO_10 (src_y[j * 6 + 2]) : 0;
|
|
y3 = ((j * 6 + 3) < frame->width) ? TO_10 (src_y[j * 6 + 3]) : 0;
|
|
y4 = ((j * 6 + 4) < frame->width) ? TO_10 (src_y[j * 6 + 4]) : 0;
|
|
y5 = ((j * 6 + 5) < frame->width) ? TO_10 (src_y[j * 6 + 5]) : 0;
|
|
cb0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_u[j * 3 + 0]) : 0;
|
|
cb1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_u[j * 3 + 1]) : 0;
|
|
cb2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_u[j * 3 + 2]) : 0;
|
|
cr0 = ((j * 6 + 0) < frame->width) ? TO_10 (src_v[j * 3 + 0]) : 0;
|
|
cr1 = ((j * 6 + 2) < frame->width) ? TO_10 (src_v[j * 3 + 1]) : 0;
|
|
cr2 = ((j * 6 + 4) < frame->width) ? TO_10 (src_v[j * 3 + 2]) : 0;
|
|
|
|
val = (cr0 << 20) | (y0 << 10) | (cb0);
|
|
WRITE_UINT32_LE (dest + j * 16 + 0, val);
|
|
|
|
val = (y2 << 20) | (cb1 << 10) | (y1);
|
|
WRITE_UINT32_LE (dest + j * 16 + 4, val);
|
|
|
|
val = (cb2 << 20) | (y3 << 10) | (cr1);
|
|
WRITE_UINT32_LE (dest + j * 16 + 8, val);
|
|
|
|
val = (y5 << 20) | (cr2 << 10) | (y4);
|
|
WRITE_UINT32_LE (dest + j * 16 + 12, val);
|
|
}
|
|
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_v210 (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_v210,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_v210;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_ayuv (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_x123 (dest, src_y, src_u, src_v, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_AYUV (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_AYUV,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_ayuv;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_rgb (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src_y;
|
|
uint8_t *src_u;
|
|
uint8_t *src_v;
|
|
int j;
|
|
|
|
src_y = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_u = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_v = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
for (j = 0; j < frame->width; j++) {
|
|
dest[j * 3 + 0] = src_y[j];
|
|
dest[j * 3 + 1] = src_u[j];
|
|
dest[j * 3 + 2] = src_v[j];
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_RGB (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_RGB,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_rgb;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
color_matrix (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
uint8_t *src3;
|
|
double m1, m2, m3;
|
|
double offset;
|
|
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src3 = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
#if 0
|
|
/* for RGB -> YUV */
|
|
switch (component) {
|
|
case 0:
|
|
m1 = 0.25679;
|
|
m2 = 0.50413;
|
|
m3 = 0.097906;
|
|
offset = 16;
|
|
break;
|
|
case 1:
|
|
m1 = -0.14822;
|
|
m2 = -0.29099;
|
|
m3 = 0.43922;
|
|
offset = 128;
|
|
break;
|
|
case 2:
|
|
m1 = 0.43922;
|
|
m2 = -0.36779;
|
|
m3 = -0.071427;
|
|
offset = 128;
|
|
break;
|
|
default:
|
|
m1 = 0.0;
|
|
m2 = 0.0;
|
|
m3 = 0.0;
|
|
offset = 0;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
switch (component) {
|
|
case 0:
|
|
m1 = 1.1644;
|
|
m2 = 0;
|
|
m3 = 1.596;
|
|
offset = -222.92;
|
|
orc_matrix2_u8 (dest, src1, src3, 75, 102, -14269 + 32, frame->width);
|
|
break;
|
|
case 1:
|
|
m1 = 1.1644;
|
|
m2 = -0.39176;
|
|
m3 = -0.81297;
|
|
offset = 135.58;
|
|
orc_matrix3_u8 (dest, src1, src2, src3, 75, -25, -52, 8677 + 32,
|
|
frame->width);
|
|
break;
|
|
case 2:
|
|
m1 = 1.1644;
|
|
m2 = 2.0172;
|
|
m3 = 0;
|
|
offset = -276.84;
|
|
orc_matrix2_u8 (dest, src1, src2, 75, 129, -17718 + 32, frame->width);
|
|
break;
|
|
default:
|
|
m1 = 0.0;
|
|
m2 = 0.0;
|
|
m3 = 0.0;
|
|
offset = 0;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_color_matrix (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_444,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = color_matrix;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
convert_444_422 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
int n_src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
n_src = frame->virt_frame1->components[component].width;
|
|
|
|
if (component == 0) {
|
|
orc_memcpy (dest, src, frame->width);
|
|
} else {
|
|
cogorc_downsample_horiz_cosite_3tap (dest + 1,
|
|
(uint16_t *) (src + 1), (uint16_t *) (src + 3),
|
|
frame->components[component].width - 1);
|
|
|
|
{
|
|
int j;
|
|
int x;
|
|
|
|
j = 0;
|
|
x = 1 * src[CLAMP (j * 2 - 1, 0, n_src - 1)];
|
|
x += 2 * src[CLAMP (j * 2 + 0, 0, n_src - 1)];
|
|
x += 1 * src[CLAMP (j * 2 + 1, 0, n_src - 1)];
|
|
dest[j] = CLAMP ((x + 2) >> 2, 0, 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
convert_422_420 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
if (component == 0) {
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
orc_memcpy (dest, src, frame->components[component].width);
|
|
} else {
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src1;
|
|
uint8_t *src2;
|
|
uint8_t *src3;
|
|
int n_src;
|
|
|
|
n_src = frame->virt_frame1->components[component].height;
|
|
src1 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 - 1, 0, n_src - 1));
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 0, 0, n_src - 1));
|
|
src3 = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
CLAMP (i * 2 + 1, 0, n_src - 1));
|
|
|
|
cogorc_downsample_vert_halfsite_3tap (dest, src1, src2, src3,
|
|
frame->components[component].width);
|
|
}
|
|
}
|
|
|
|
/* up */
|
|
|
|
static void
|
|
convert_422_444 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
|
|
if (component == 0) {
|
|
orc_memcpy (dest, src, frame->width);
|
|
} else {
|
|
cogorc_upsample_horiz_cosite (dest, src, src + 1,
|
|
frame->components[component].width / 2 - 1);
|
|
dest[frame->components[component].width - 2] =
|
|
src[frame->components[component].width / 2 - 1];
|
|
dest[frame->components[component].width - 1] =
|
|
src[frame->components[component].width / 2 - 1];
|
|
}
|
|
}
|
|
|
|
static void
|
|
convert_420_422 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
if (component == 0) {
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
orc_memcpy (dest, src, frame->components[component].width);
|
|
} else {
|
|
if ((i & 1) && i < frame->components[component].height - 1) {
|
|
uint8_t *src2;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i >> 1);
|
|
src2 = cog_virt_frame_get_line (frame->virt_frame1,
|
|
component, (i >> 1) + 1);
|
|
cogorc_upsample_vert_avgub (dest, src, src2,
|
|
frame->components[component].width);
|
|
} else {
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i >> 1);
|
|
orc_memcpy (dest, src, frame->components[component].width);
|
|
}
|
|
}
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_subsample (CogFrame * vf, CogFrameFormat format)
|
|
{
|
|
CogFrame *virt_frame;
|
|
CogFrameRenderFunc render_line;
|
|
|
|
if (vf->format == format) {
|
|
return vf;
|
|
}
|
|
if (vf->format == COG_FRAME_FORMAT_U8_422 &&
|
|
format == COG_FRAME_FORMAT_U8_420) {
|
|
render_line = convert_422_420;
|
|
} else if (vf->format == COG_FRAME_FORMAT_U8_444 &&
|
|
format == COG_FRAME_FORMAT_U8_420) {
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_422,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = convert_444_422;
|
|
vf = virt_frame;
|
|
|
|
render_line = convert_422_420;
|
|
} else if (vf->format == COG_FRAME_FORMAT_U8_444 &&
|
|
format == COG_FRAME_FORMAT_U8_422) {
|
|
render_line = convert_444_422;
|
|
} else if (vf->format == COG_FRAME_FORMAT_U8_420 &&
|
|
format == COG_FRAME_FORMAT_U8_422) {
|
|
render_line = convert_420_422;
|
|
} else if (vf->format == COG_FRAME_FORMAT_U8_420 &&
|
|
format == COG_FRAME_FORMAT_U8_444) {
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_U8_422,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = convert_420_422;
|
|
vf = virt_frame;
|
|
|
|
render_line = convert_422_444;
|
|
} else if (vf->format == COG_FRAME_FORMAT_U8_422 &&
|
|
format == COG_FRAME_FORMAT_U8_444) {
|
|
render_line = convert_422_444;
|
|
} else {
|
|
COG_ASSERT (0);
|
|
return NULL;
|
|
}
|
|
virt_frame = cog_frame_new_virtual (NULL, format, vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = render_line;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
|
|
static void
|
|
convert_u8_s16 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
int16_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
orc_addc_convert_u8_s16 (dest, frame->virt_priv,
|
|
frame->components[component].width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_convert_u8 (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
CogFrameFormat format;
|
|
|
|
format = (vf->format & 3) | COG_FRAME_FORMAT_U8_444;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, format, vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = convert_u8_s16;
|
|
virt_frame->virt_priv = cog_malloc (sizeof (int16_t) * vf->width);
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
convert_s16_u8 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
int16_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
|
|
orc_subc_convert_s16_u8 (dest, src, frame->components[component].width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_convert_s16 (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
CogFrameFormat format;
|
|
|
|
format = (vf->format & 3) | COG_FRAME_FORMAT_S16_444;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, format, vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = convert_s16_u8;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
crop_u8 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
orc_memcpy (dest, src, frame->components[component].width);
|
|
}
|
|
|
|
static void
|
|
crop_s16 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
int16_t *dest = _dest;
|
|
int16_t *src;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component, i);
|
|
orc_memcpy (dest, src, frame->components[component].width * sizeof (int16_t));
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_crop (CogFrame * vf, int width, int height)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
if (width == vf->width && height == vf->height)
|
|
return vf;
|
|
|
|
COG_ASSERT (width <= vf->width);
|
|
COG_ASSERT (height <= vf->height);
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, vf->format, width, height);
|
|
virt_frame->virt_frame1 = vf;
|
|
switch (COG_FRAME_FORMAT_DEPTH (vf->format)) {
|
|
case COG_FRAME_FORMAT_DEPTH_U8:
|
|
virt_frame->render_line = crop_u8;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S16:
|
|
virt_frame->render_line = crop_s16;
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
break;
|
|
}
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
edge_extend_u8 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint8_t *dest = _dest;
|
|
uint8_t *src;
|
|
CogFrame *srcframe = frame->virt_frame1;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
MIN (i, srcframe->components[component].height - 1));
|
|
orc_memcpy (dest, src, srcframe->components[component].width);
|
|
orc_splat_u8_ns (dest + srcframe->components[component].width,
|
|
dest[srcframe->components[component].width - 1],
|
|
frame->components[component].width -
|
|
srcframe->components[component].width);
|
|
}
|
|
|
|
static void
|
|
edge_extend_s16 (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
int16_t *dest = _dest;
|
|
int16_t *src;
|
|
CogFrame *srcframe = frame->virt_frame1;
|
|
|
|
src = cog_virt_frame_get_line (frame->virt_frame1, component,
|
|
MIN (i, srcframe->components[component].height - 1));
|
|
orc_memcpy (dest, src,
|
|
srcframe->components[component].width * sizeof (int16_t));
|
|
orc_splat_s16_ns (dest + srcframe->components[component].width,
|
|
dest[srcframe->components[component].width - 1],
|
|
frame->components[component].width -
|
|
srcframe->components[component].width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_edgeextend (CogFrame * vf, int width, int height)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
if (width == vf->width && height == vf->height)
|
|
return vf;
|
|
|
|
COG_ASSERT (width >= vf->width);
|
|
COG_ASSERT (height >= vf->height);
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, vf->format, width, height);
|
|
virt_frame->virt_frame1 = vf;
|
|
switch (COG_FRAME_FORMAT_DEPTH (vf->format)) {
|
|
case COG_FRAME_FORMAT_DEPTH_U8:
|
|
virt_frame->render_line = edge_extend_u8;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S16:
|
|
virt_frame->render_line = edge_extend_s16;
|
|
break;
|
|
default:
|
|
COG_ASSERT (0);
|
|
break;
|
|
}
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
pack_RGBx (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_123x (dest, src_r, src_g, src_b, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_RGBx (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_RGBx,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_RGBx;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_xRGB (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_x123 (dest, src_r, src_g, src_b, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_xRGB (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_xRGB,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_xRGB;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_BGRx (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_123x (dest, src_b, src_g, src_r, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_BGRx (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_BGRx,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_BGRx;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_xBGR (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_x123 (dest, src_b, src_g, src_r, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_xBGR (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_xBGR,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_xBGR;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_RGBA (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_123x (dest, src_r, src_g, src_b, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_RGBA (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_RGBA,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_RGBA;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_ARGB (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_x123 (dest, src_r, src_g, src_b, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_ARGB (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_ARGB,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_ARGB;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_BGRA (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_123x (dest, src_b, src_g, src_r, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_BGRA (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_BGRA,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_BGRA;
|
|
|
|
return virt_frame;
|
|
}
|
|
|
|
static void
|
|
pack_ABGR (CogFrame * frame, void *_dest, int component, int i)
|
|
{
|
|
uint32_t *dest = _dest;
|
|
uint8_t *src_r;
|
|
uint8_t *src_g;
|
|
uint8_t *src_b;
|
|
|
|
src_r = cog_virt_frame_get_line (frame->virt_frame1, 0, i);
|
|
src_g = cog_virt_frame_get_line (frame->virt_frame1, 1, i);
|
|
src_b = cog_virt_frame_get_line (frame->virt_frame1, 2, i);
|
|
|
|
orc_pack_x123 (dest, src_b, src_g, src_r, 0xff, frame->width);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_virt_frame_new_pack_ABGR (CogFrame * vf)
|
|
{
|
|
CogFrame *virt_frame;
|
|
|
|
virt_frame = cog_frame_new_virtual (NULL, COG_FRAME_FORMAT_ABGR,
|
|
vf->width, vf->height);
|
|
virt_frame->virt_frame1 = vf;
|
|
virt_frame->render_line = pack_ABGR;
|
|
|
|
return virt_frame;
|
|
}
|