summaryrefslogtreecommitdiff
path: root/src/video_out/yuv2rgb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_out/yuv2rgb.c')
-rw-r--r--src/video_out/yuv2rgb.c679
1 files changed, 519 insertions, 160 deletions
diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c
index e4b60033f..7abfdac0e 100644
--- a/src/video_out/yuv2rgb.c
+++ b/src/video_out/yuv2rgb.c
@@ -42,23 +42,6 @@ const int32_t Inverse_Table_6_9[8][4] = {
{117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
};
-static void yuv2rgb_c (yuv2rgb_t *this, uint8_t *image,
- uint8_t *py, uint8_t *pu, uint8_t *pv) {
-
- /* int dy = this->step_dy; */
- int height = this->source_height >>= 1;
-
- do {
- this->yuv2rgb_c_internal (this, py, py + this->y_stride, pu, pv,
- image, ((uint8_t *)image) + this->rgb_stride,
- this->source_width);
-
- py += 2 * this->y_stride;
- pu += this->uv_stride;
- pv += this->uv_stride;
- image = ((uint8_t *) image) + 2 * this->rgb_stride;
- } while (--height);
-}
static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk) {
@@ -91,6 +74,19 @@ int yuv2rgb_setup (yuv2rgb_t *this,
this->dest_height = dest_height;
this->rgb_stride = rgb_stride;
+ if (this->y_chunk) {
+ free (this->y_chunk);
+ this->y_buffer = this->y_chunk = NULL;
+ }
+ if (this->u_chunk) {
+ free (this->u_chunk);
+ this->u_buffer = this->u_chunk = NULL;
+ }
+ if (this->v_chunk) {
+ free (this->v_chunk);
+ this->v_buffer = this->v_chunk = NULL;
+ }
+
if ((source_width == dest_width) && (source_height == dest_height))
this->do_scale = 0;
else {
@@ -99,10 +95,6 @@ int yuv2rgb_setup (yuv2rgb_t *this,
this->step_dx = source_width * 32768 / dest_width;
this->step_dy = source_height * 32768 / dest_height;
- if (this->y_chunk) free (this->y_chunk);
- if (this->u_chunk) free (this->u_chunk);
- if (this->v_chunk) free (this->v_chunk);
-
this->y_buffer = my_malloc_aligned (16, dest_width, &this->y_chunk);
if (!this->y_buffer)
return 0;
@@ -117,6 +109,34 @@ int yuv2rgb_setup (yuv2rgb_t *this,
}
+static void scale_line (uint8_t *source, uint8_t *dest,
+ int width, int step) {
+ int p1;
+ int p2;
+ int dx;
+
+ p1 = *source++;
+ p2 = *source++;
+ dx = 0;
+
+ while (width) {
+
+ *dest = (p1 * (32768 - dx) + p2 * dx) / 32768;
+
+ dx += step;
+ while (dx > 32768) {
+ dx -= 32768;
+ p1 = p2;
+ p2 = *source++;
+ }
+
+ dest ++;
+ width --;
+ }
+
+}
+
+
#define RGB(i) \
U = pu[i]; \
V = pv[i]; \
@@ -160,164 +180,505 @@ int yuv2rgb_setup (yuv2rgb_t *this,
Y = py_2[2*i+1]; \
dst_2[6*i+3] = b[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = r[Y];
-static void yuv2rgb_c_32 (yuv2rgb_t *this,
- uint8_t * py_1, uint8_t * py_2,
- uint8_t * pu, uint8_t * pv,
- void * _dst_1, void * _dst_2, int width)
+static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst,
+ uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
{
int U, V, Y;
+ uint8_t * py_1, * py_2, * pu, * pv;
uint32_t * r, * g, * b;
uint32_t * dst_1, * dst_2;
-
- width >>= 3;
- dst_1 = _dst_1;
- dst_2 = _dst_2;
-
- do {
- RGB(0);
- DST1(0);
- DST2(0);
-
- RGB(1);
- DST2(1);
- DST1(1);
-
- RGB(2);
- DST1(2);
- DST2(2);
-
- RGB(3);
- DST2(3);
- DST1(3);
-
- pu += 4;
- pv += 4;
- py_1 += 8;
- py_2 += 8;
- dst_1 += 8;
- dst_2 += 8;
- } while (--width);
+ int width, height;
+ int dy;
+
+ if (this->do_scale) {
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ dy = 0;
+ height = this->source_height;
+
+ for (;;) {
+ dst_1 = (uint32_t*)_dst;
+ py_1 = this->y_buffer;
+ pu = this->u_buffer;
+ pv = this->v_buffer;
+
+ width = this->dest_width >> 3;
+
+ do {
+ RGB(0);
+ DST1(0);
+
+ RGB(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+
+ RGB(3);
+ DST1(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ dst_1 += 8;
+ } while (--width);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+
+ while (dy <= 32768) {
+
+ memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+ }
+
+ if (--height <= 0)
+ break;
+
+ dy -= 32768;
+ _py += this->y_stride;
+
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ if (!(height & 1)) {
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+
+ }
+ }
+ } else {
+ height = this->source_height >> 1;
+ do {
+ dst_1 = (uint32_t*)_dst;
+ dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
+ py_1 = _py;
+ py_2 = _py + this->y_stride;
+ pu = _pu;
+ pv = _pv;
+
+ width = this->source_width >> 3;
+ do {
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ py_2 += 8;
+ dst_1 += 8;
+ dst_2 += 8;
+ } while (--width);
+
+ _dst += 2 * this->rgb_stride;
+ _py += 2 * this->y_stride;
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ } while (--height);
+ }
}
/* This is very near from the yuv2rgb_c_32 code */
-static void yuv2rgb_c_24_rgb (yuv2rgb_t *this,
- uint8_t * py_1, uint8_t * py_2,
- uint8_t * pu, uint8_t * pv,
- void * _dst_1, void * _dst_2, int width)
+static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst,
+ uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
{
int U, V, Y;
+ uint8_t * py_1, * py_2, * pu, * pv;
uint8_t * r, * g, * b;
uint8_t * dst_1, * dst_2;
-
- width >>= 3;
- dst_1 = _dst_1;
- dst_2 = _dst_2;
-
- do {
- RGB(0);
- DST1RGB(0);
- DST2RGB(0);
-
- RGB(1);
- DST2RGB(1);
- DST1RGB(1);
-
- RGB(2);
- DST1RGB(2);
- DST2RGB(2);
-
- RGB(3);
- DST2RGB(3);
- DST1RGB(3);
-
- pu += 4;
- pv += 4;
- py_1 += 8;
- py_2 += 8;
- dst_1 += 24;
- dst_2 += 24;
- } while (--width);
+ int width, height;
+ int dy;
+
+ if (this->do_scale) {
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ dy = 0;
+ height = this->source_height;
+
+ for (;;) {
+ dst_1 = _dst;
+ py_1 = this->y_buffer;
+ pu = this->u_buffer;
+ pv = this->v_buffer;
+
+ width = this->dest_width >> 3;
+
+ do {
+ RGB(0);
+ DST1RGB(0);
+
+ RGB(1);
+ DST1RGB(1);
+
+ RGB(2);
+ DST1RGB(2);
+
+ RGB(3);
+ DST1RGB(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ dst_1 += 24;
+ } while (--width);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+
+ while (dy <= 32768) {
+
+ memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+ }
+
+ if (--height <= 0)
+ break;
+
+ dy -= 32768;
+ _py += this->y_stride;
+
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ if (!(height & 1)) {
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+
+ }
+ }
+ } else {
+ height = this->source_height >> 1;
+ do {
+ dst_1 = _dst;
+ dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
+ py_1 = _py;
+ py_2 = _py + this->y_stride;
+ pu = _pu;
+ pv = _pv;
+
+ width = this->source_width >> 3;
+ do {
+ RGB(0);
+ DST1RGB(0);
+ DST2RGB(0);
+
+ RGB(1);
+ DST2RGB(1);
+ DST1RGB(1);
+
+ RGB(2);
+ DST1RGB(2);
+ DST2RGB(2);
+
+ RGB(3);
+ DST2RGB(3);
+ DST1RGB(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ py_2 += 8;
+ dst_1 += 24;
+ dst_2 += 24;
+ } while (--width);
+
+ _dst += 2 * this->rgb_stride;
+ _py += 2 * this->y_stride;
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ } while (--height);
+ }
}
/* only trivial mods from yuv2rgb_c_24_rgb */
-static void yuv2rgb_c_24_bgr (yuv2rgb_t *this,
- uint8_t * py_1, uint8_t * py_2,
- uint8_t * pu, uint8_t * pv,
- void * _dst_1, void * _dst_2, int width)
+static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst,
+ uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
{
int U, V, Y;
+ uint8_t * py_1, * py_2, * pu, * pv;
uint8_t * r, * g, * b;
uint8_t * dst_1, * dst_2;
+ int width, height;
+ int dy;
+
+ if (this->do_scale) {
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ dy = 0;
+ height = this->source_height;
+
+ for (;;) {
+ dst_1 = _dst;
+ py_1 = this->y_buffer;
+ pu = this->u_buffer;
+ pv = this->v_buffer;
+
+ width = this->dest_width >> 3;
+
+ do {
+ RGB(0);
+ DST1BGR(0);
+
+ RGB(1);
+ DST1BGR(1);
+
+ RGB(2);
+ DST1BGR(2);
+
+ RGB(3);
+ DST1BGR(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ dst_1 += 24;
+ } while (--width);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+
+ while (dy <= 32768) {
+
+ memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+ }
+
+ if (--height <= 0)
+ break;
+
+ dy -= 32768;
+ _py += this->y_stride;
+
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ if (!(height & 1)) {
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+
+ }
+ }
- width >>= 3;
- dst_1 = _dst_1;
- dst_2 = _dst_2;
-
- do {
- RGB(0);
- DST1BGR(0);
- DST2BGR(0);
-
- RGB(1);
- DST2BGR(1);
- DST1BGR(1);
-
- RGB(2);
- DST1BGR(2);
- DST2BGR(2);
-
- RGB(3);
- DST2BGR(3);
- DST1BGR(3);
-
- pu += 4;
- pv += 4;
- py_1 += 8;
- py_2 += 8;
- dst_1 += 24;
- dst_2 += 24;
- } while (--width);
+ } else {
+ height = this->source_height >> 1;
+ do {
+ dst_1 = _dst;
+ dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
+ py_1 = _py;
+ py_2 = _py + this->y_stride;
+ pu = _pu;
+ pv = _pv;
+ width = this->source_width >> 3;
+ do {
+ RGB(0);
+ DST1BGR(0);
+ DST2BGR(0);
+
+ RGB(1);
+ DST2BGR(1);
+ DST1BGR(1);
+
+ RGB(2);
+ DST1BGR(2);
+ DST2BGR(2);
+
+ RGB(3);
+ DST2BGR(3);
+ DST1BGR(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ py_2 += 8;
+ dst_1 += 24;
+ dst_2 += 24;
+ } while (--width);
+
+ _dst += 2 * this->rgb_stride;
+ _py += 2 * this->y_stride;
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ } while (--height);
+ }
}
/* This is exactly the same code as yuv2rgb_c_32 except for the types of */
/* r, g, b, dst_1, dst_2 */
-static void yuv2rgb_c_16 (yuv2rgb_t *this,
- uint8_t * py_1, uint8_t * py_2,
- uint8_t * pu, uint8_t * pv,
- void * _dst_1, void * _dst_2, int width)
+static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst,
+ uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
{
int U, V, Y;
+ uint8_t * py_1, * py_2, * pu, * pv;
uint16_t * r, * g, * b;
uint16_t * dst_1, * dst_2;
-
- width >>= 3;
- dst_1 = _dst_1;
- dst_2 = _dst_2;
-
- do {
- RGB(0);
- DST1(0);
- DST2(0);
-
- RGB(1);
- DST2(1);
- DST1(1);
-
- RGB(2);
- DST1(2);
- DST2(2);
-
- RGB(3);
- DST2(3);
- DST1(3);
-
- pu += 4;
- pv += 4;
- py_1 += 8;
- py_2 += 8;
- dst_1 += 8;
- dst_2 += 8;
- } while (--width);
+ int width, height;
+ int dy;
+
+ if (this->do_scale) {
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ dy = 0;
+ height = this->source_height;
+
+ for (;;) {
+ dst_1 = (uint16_t*)_dst;
+ py_1 = this->y_buffer;
+ pu = this->u_buffer;
+ pv = this->v_buffer;
+
+ width = this->dest_width >> 3;
+
+ do {
+ RGB(0);
+ DST1(0);
+
+ RGB(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+
+ RGB(3);
+ DST1(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ dst_1 += 8;
+ } while (--width);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+
+ while (dy <= 32768) {
+
+ memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2);
+
+ dy += this->step_dy;
+ _dst += this->rgb_stride;
+ }
+
+ if (--height <= 0)
+ break;
+
+ dy -= 32768;
+ _py += this->y_stride;
+
+ scale_line (_py, this->y_buffer,
+ this->dest_width, this->step_dx);
+
+ if (!(height & 1)) {
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ scale_line (_pu, this->u_buffer,
+ this->dest_width >> 1, this->step_dx);
+ scale_line (_pv, this->v_buffer,
+ this->dest_width >> 1, this->step_dx);
+
+ }
+ }
+ } else {
+ height = this->source_height >> 1;
+ do {
+ dst_1 = (uint16_t*)_dst;
+ dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
+ py_1 = _py;
+ py_2 = _py + this->y_stride;
+ pu = _pu;
+ pv = _pv;
+ width = this->source_width >> 3;
+ do {
+ RGB(0);
+ DST1(0);
+ DST2(0);
+
+ RGB(1);
+ DST2(1);
+ DST1(1);
+
+ RGB(2);
+ DST1(2);
+ DST2(2);
+
+ RGB(3);
+ DST2(3);
+ DST1(3);
+
+ pu += 4;
+ pv += 4;
+ py_1 += 8;
+ py_2 += 8;
+ dst_1 += 8;
+ dst_2 += 8;
+ } while (--width);
+
+ _dst += 2 * this->rgb_stride;
+ _py += 2 * this->y_stride;
+ _pu += this->uv_stride;
+ _pv += this->uv_stride;
+
+ } while (--height);
+ }
}
static int div_round (int dividend, int divisor)
@@ -343,8 +704,6 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode)
int cgu = -Inverse_Table_6_9[this->matrix_coefficients][2];
int cgv = -Inverse_Table_6_9[this->matrix_coefficients][3];
- this->yuv2rgb_fun = yuv2rgb_c;
-
for (i = 0; i < 1024; i++) {
int j;
@@ -356,7 +715,7 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode)
switch (mode) {
case MODE_32_RGB:
case MODE_32_BGR:
- this->yuv2rgb_c_internal = yuv2rgb_c_32;
+ this->yuv2rgb_fun = yuv2rgb_c_32;
table_32 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t));
@@ -377,7 +736,7 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode)
case MODE_24_RGB:
case MODE_24_BGR:
- this->yuv2rgb_c_internal = (mode==MODE_24_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr;
+ this->yuv2rgb_fun = (mode==MODE_24_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr;
table_8 = malloc ((256 + 2*232) * sizeof (uint8_t));
@@ -392,7 +751,7 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode)
case MODE_16_BGR:
case MODE_15_RGB:
case MODE_16_RGB:
- this->yuv2rgb_c_internal = yuv2rgb_c_16;
+ this->yuv2rgb_fun = yuv2rgb_c_16;
table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
@@ -452,9 +811,9 @@ yuv2rgb_t *yuv2rgb_init (int mode) {
this->matrix_coefficients = 6;
- this->y_buffer = NULL;
- this->u_buffer = NULL;
- this->v_buffer = NULL;
+ this->y_chunk = this->y_buffer = NULL;
+ this->y_chunk = this->u_buffer = NULL;
+ this->y_chunk = this->v_buffer = NULL;
/*
* auto-probe for the best yuv2rgb function