summaryrefslogtreecommitdiff
authorzecke <zecke>2005-04-17 13:56:34 (UTC)
committer zecke <zecke>2005-04-17 13:56:34 (UTC)
commit3d5e5c098ccb686588380bc1f220beafbc5a6d76 (patch) (side-by-side diff)
tree92fad8a98ea341ec290dc7f9fca7759470b795f6
parent49335d66d8e96b1fc86ecfe95cd343c8960126bc (diff)
downloadopie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.zip
opie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.tar.gz
opie-3d5e5c098ccb686588380bc1f220beafbc5a6d76.tar.bz2
Opie Player2 XINE update:
-update xine code alphablend, yuv2rgb to be up to date -XINELib: -use the XINE infrastructure to change the gui width/height -use the XINE infrastructure to change the brightness -Update the NULL Video Driver: -make use of frame_dest_cb and and dest_size_cb (callback) to update the size of the gui -use alphablend -merge the video_out_fb xine driver To Alwin: your testvideo now lockups op2. with valgrind I see it has to do with the yuv2rgb conversion methods
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/alphablend.c1567
-rw-r--r--noncore/multimedia/opieplayer2/alphablend.h91
-rw-r--r--noncore/multimedia/opieplayer2/lib.cpp74
-rw-r--r--noncore/multimedia/opieplayer2/lib.h40
-rw-r--r--noncore/multimedia/opieplayer2/mainTest.cpp16
-rw-r--r--noncore/multimedia/opieplayer2/nullvideo.c292
-rw-r--r--noncore/multimedia/opieplayer2/yuv2rgb.c446
-rw-r--r--noncore/multimedia/opieplayer2/yuv2rgb.h56
8 files changed, 1893 insertions, 689 deletions
diff --git a/noncore/multimedia/opieplayer2/alphablend.c b/noncore/multimedia/opieplayer2/alphablend.c
index cdd7b28..ab80531 100644
--- a/noncore/multimedia/opieplayer2/alphablend.c
+++ b/noncore/multimedia/opieplayer2/alphablend.c
@@ -1,755 +1,1784 @@
-//TOAST_SPU will define ALL spu entries - no matter the tranparency
-//#define TOAST_SPU
-/* #define PRIV_CLUT */
-/* Currently only blend_yuv(..) works */
/*
*
* Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001
*
* Copyright (C) 2000 Thomas Mirlacher
+ * 2002-2004 the xine project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be reached as <dent@linuxvideo.org>
*
*------------------------------------------------------------
*
*/
/*
#define LOG_BLEND_YUV
+#define LOG_BLEND_RGB16
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
-#include <inttypes.h>
-#include <xine.h>
#include <xine/xine_internal.h>
#include <xine/video_out.h>
#include "alphablend.h"
+#include "bswap.h"
#define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask)
#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf)
static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) {
uint16_t *limit = mem + len;
while (mem < limit) {
*mem =
BLEND_COLOR(*mem, clr, 0xf800, o) |
BLEND_COLOR(*mem, clr, 0x07e0, o) |
BLEND_COLOR(*mem, clr, 0x001f, o);
mem++;
}
}
static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
- uint8_t o, int len) {
+ uint8_t o, int len) {
uint8_t *limit = mem + len*3;
while (mem < limit) {
*mem = BLEND_BYTE(*mem, r, o);
mem++;
*mem = BLEND_BYTE(*mem, g, o);
mem++;
*mem = BLEND_BYTE(*mem, b, o);
mem++;
}
}
-static void mem_blend24_32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
- uint8_t o, int len) {
- uint8_t *limit = mem + len*4;
- while (mem < limit) {
- *mem = BLEND_BYTE(*mem, r, o);
- mem++;
- *mem = BLEND_BYTE(*mem, g, o);
- mem++;
- *mem = BLEND_BYTE(*mem, b, o);
- mem += 2;
- }
-}
-
static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
uint8_t *limit = mem + len*4;
while (mem < limit) {
*mem = BLEND_BYTE(*mem, src[0], o);
mem++;
*mem = BLEND_BYTE(*mem, src[1], o);
mem++;
*mem = BLEND_BYTE(*mem, src[2], o);
mem++;
*mem = BLEND_BYTE(*mem, src[3], o);
mem++;
}
}
-
/*
* Some macros for fixed point arithmetic.
*
* The blend_rgb* routines perform rle image scaling using
* scale factors that are expressed as integers scaled with
* a factor of 2**16.
*
* INT_TO_SCALED()/SCALED_TO_INT() converts from integer
* to scaled fixed point and back.
*/
#define SCALE_SHIFT 16
#define SCALE_FACTOR (1<<SCALE_SHIFT)
#define INT_TO_SCALED(i) ((i) << SCALE_SHIFT)
#define SCALED_TO_INT(sc) ((sc) >> SCALE_SHIFT)
static rle_elem_t *
rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w)
{
int x;
for (x = 0; x < w && rle < rle_limit; ) {
x += rle->len;
rle++;
}
return rle;
}
-
void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
- int img_width, int img_height,
- int dst_width, int dst_height)
+ int img_width, int img_height,
+ int dst_width, int dst_height,
+ alphablend_t *extra_data)
{
uint8_t *trans;
- clut_t* clut = (clut_t*) img_overl->clip_color;
+ clut_t *clut;
int src_width = img_overl->width;
int src_height = img_overl->height;
rle_elem_t *rle = img_overl->rle;
+ rle_elem_t *rle_start = img_overl->rle;
rle_elem_t *rle_limit = rle + img_overl->num_rle;
int x, y, x1_scaled, x2_scaled;
- int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */
+ int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */
int clip_right;
uint16_t *img_pix;
+ int rlelen;
+ int rle_this_bite;
+ int rle_remainder;
+ int zone_state=0;
+ uint8_t clr_next,clr;
+ uint16_t o;
+ double img_offset;
+ int stripe_height;
+/*
+ * Let zone_state keep state.
+ * 0 = Starting.
+ * 1 = Above button.
+ * 2 = Left of button.
+ * 3 = Inside of button.
+ * 4 = Right of button.
+ * 5 = Below button.
+ * 6 = Finished.
+ *
+ * Each time round the loop, update the state.
+ * We can do this easily and cheaply(fewer IF statements per cycle) as we are testing rle end position anyway.
+ * Possible optimization is to ensure that rle never overlaps from outside to inside a button.
+ * Possible optimization is to pre-scale the RLE overlay, so that no scaling is needed here.
+ */
- dy_step = INT_TO_SCALED(dst_height) / img_height;
- x_scale = INT_TO_SCALED(img_width) / dst_width;
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: img_height=%i, dst_height=%i\n", img_height, dst_height);
+ printf("blend_rgb16: img_width=%i, dst_width=%i\n", img_width, dst_width);
+ if (img_width & 1) { printf("blend_rgb16s: odd\n");}
+ else { printf("blend_rgb16s: even\n");}
- img_pix = (uint16_t *) img
+#endif
+/* stripe_height is used in yuv2rgb scaling, so use the same scale factor here for overlays. */
+ stripe_height = 16 * img_height / dst_height;
+/* dy_step = INT_TO_SCALED(dst_height) / img_height; */
+ dy_step = INT_TO_SCALED(16) / stripe_height;
+ x_scale = INT_TO_SCALED(img_width) / dst_width;
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: dy_step=%i, x_scale=%i\n", dy_step, x_scale);
+#endif
+ if (img_width & 1) img_width++;
+ img_offset = ( ( (img_overl->y * img_height) / dst_height) * img_width)
+ + ( (img_overl->x * img_width) / dst_width);
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: x=%i, y=%i, w=%i, h=%i, img_offset=%lf\n", img_overl->x, img_overl->y,
+ img_overl->width,
+ img_overl->height,
+ img_offset);
+#endif
+ img_pix = (uint16_t *) img + (int)img_offset;
+/*
+ (img_overl->y * img_height / dst_height) * img_width
+ (img_overl->x * img_width / dst_width);
-
- trans = img_overl->clip_trans;
+*/
/* avoid wraping overlay if drawing to small image */
if( (img_overl->x + img_overl->clip_right) < dst_width )
clip_right = img_overl->clip_right;
else
- clip_right = dst_width - 1 - img_overl->x;
+ clip_right = dst_width - img_overl->x;
/* avoid buffer overflow */
if( (src_height + img_overl->y) >= dst_height )
- src_height = dst_height - 1 - img_overl->y;
+ src_height = dst_height - img_overl->y;
- for (y = dy = 0; y < src_height && rle < rle_limit;) {
- int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
- rle_elem_t *rle_start = rle;
+ rlelen = rle_remainder = rle_this_bite = 0;
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ y = dy = 0;
+ x = x1_scaled = x2_scaled = 0;
- for (x = x1_scaled = 0; x < src_width;) {
- uint8_t clr;
- uint16_t o;
- int rlelen;
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16 started\n");
+#endif
+
+ while (zone_state != 6) {
+ clr = clr_next;
+ switch (zone_state) {
+ case 0: /* Starting */
+ /* FIXME: Get libspudec to set clip_top to -1 if no button */
+ if (img_overl->clip_top < 0) {
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: No button clip area\n");
+#endif
- clr = rle->color;
+ zone_state = 7;
+ break;
+ }
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: Button clip area found. (%d,%d) .. (%d,%d)\n",
+ img_overl->clip_left,
+ img_overl->clip_top,
+ img_overl->clip_right,
+ img_overl->clip_bottom);
+#endif
+ if (y < img_overl->clip_top) {
+ zone_state = 1;
+ break;
+ } else if (y >= img_overl->clip_bottom) {
+ zone_state = 5;
+ break;
+ } else if (x < img_overl->clip_left) {
+ zone_state = 2;
+ break;
+ } else if (x >= img_overl->clip_right) {
+ zone_state = 4;
+ break;
+ } else {
+ zone_state = 3;
+ break;
+ }
+ break;
+ case 1: /* Above clip area */
+ clut = (clut_t*) img_overl->color;
+ trans = img_overl->trans;
o = trans[clr];
- rlelen = rle->len;
-
- if (o && mask) {
- /* threat cases where clipping border is inside rle->len pixels */
- if ( img_overl->clip_left > x ) {
- if( img_overl->clip_left < x + rlelen ) {
- x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
- rlelen -= img_overl->clip_left - x;
- x += img_overl->clip_left - x;
- } else {
- o = 0;
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ /*printf("(x,y) = (%03i,%03i), clr=%03x, len=%03i, zone=%i\n", x, y, clr, rle_this_bite, zone_state); */
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ }
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
}
- } else if( clip_right < x + rlelen ) {
- if( clip_right > x ) {
- x2_scaled = SCALED_TO_INT( clip_right * x_scale);
- mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o,
- x2_scaled-x1_scaled);
- o = 0;
- } else {
- o = 0;
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ }
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ if (y >= img_overl->clip_top) {
+ zone_state = 2;
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16: Button clip top reached. y=%i, top=%i\n",
+ y, img_overl->clip_top);
+#endif
+ if (x >= img_overl->clip_left) {
+ zone_state = 3;
+ if (x >= img_overl->clip_right) {
+ zone_state = 4;
}
- }
+ }
}
-
- x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
- if (o && mask) {
- mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ break;
+ case 2: /* Left of button */
+ clut = (clut_t*) img_overl->color;
+ trans = img_overl->trans;
+ o = trans[clr];
+ if (x + rle_remainder <= img_overl->clip_left) {
+ rle_this_bite = rle_remainder;
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ } else {
+ rle_this_bite = img_overl->clip_left - x;
+ rle_remainder -= rle_this_bite;
+ zone_state = 3;
}
-
- x1_scaled = x2_scaled;
- x += rlelen;
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ }
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ }
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ if (y >= img_overl->clip_bottom) {
+ zone_state = 5;
+ break;
+ }
+ }
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ break;
+ case 3: /* In button */
+ clut = (clut_t*) img_overl->clip_color;
+ trans = img_overl->clip_trans;
+ o = trans[clr];
+ if (x + rle_remainder <= img_overl->clip_right) {
+ rle_this_bite = rle_remainder;
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ } else {
+ rle_this_bite = img_overl->clip_right - x;
+ rle_remainder -= rle_this_bite;
+ zone_state = 4;
+ }
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ }
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ }
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ if (y >= img_overl->clip_bottom) {
+ zone_state = 5;
+ break;
+ }
+ }
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ break;
+ case 4: /* Right of button */
+ clut = (clut_t*) img_overl->color;
+ trans = img_overl->trans;
+ o = trans[clr];
+ if (x + rle_remainder <= src_width) {
+ rle_this_bite = rle_remainder;
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ } else {
+ rle_this_bite = src_width - x;
+ rle_remainder -= rle_this_bite;
+ zone_state = 2;
+ }
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ }
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ }
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ if (y >= img_overl->clip_bottom) {
+ zone_state = 5;
+ break;
+ }
+ }
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ break;
+ case 5: /* Below button */
+ clut = (clut_t*) img_overl->color;
+ trans = img_overl->trans;
+ o = trans[clr];
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
+ }
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ }
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ }
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
rle++;
- if (rle >= rle_limit) break;
- }
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ break;
+ case 6: /* Finished */
+ _x_abort();
- img_pix += img_width;
- dy += dy_step;
- if (dy >= INT_TO_SCALED(1)) {
- dy -= INT_TO_SCALED(1);
- ++y;
- while (dy >= INT_TO_SCALED(1)) {
- rle = rle_img_advance_line(rle, rle_limit, src_width);
- dy -= INT_TO_SCALED(1);
- ++y;
+ case 7: /* No button */
+ clut = (clut_t*) img_overl->color;
+ trans = img_overl->trans;
+ o = trans[clr];
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ if (o) {
+ x1_scaled = SCALED_TO_INT( x * x_scale );
+ x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
+ mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
}
- } else {
- rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ x += rle_this_bite;
+ if (x >= src_width ) {
+ x -= src_width;
+ img_pix += img_width;
+ dy += dy_step;
+ if (dy >= INT_TO_SCALED(1)) {
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ while (dy >= INT_TO_SCALED(1)) {
+ rle = rle_img_advance_line(rle, rle_limit, src_width);
+ dy -= INT_TO_SCALED(1);
+ ++y;
+ }
+ rle_start = rle;
+ } else {
+ rle = rle_start; /* y-scaling, reuse the last rle encoded line */
+ }
+ }
+ rle_remainder = rlelen = rle->len;
+ clr_next = rle->color;
+ rle++;
+ if (rle >= rle_limit) {
+ zone_state = 6;
+ }
+ break;
+ default:
+ ;
}
}
+#ifdef LOG_BLEND_RGB16
+ printf("blend_rgb16 ended\n");
+#endif
+
}
void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
- int dst_width, int dst_height)
+ int dst_width, int dst_height,
+ alphablend_t *extra_data)
{
- clut_t* clut = (clut_t*) img_overl->clip_color;
- uint8_t *trans;
int src_width = img_overl->width;
int src_height = img_overl->height;
rle_elem_t *rle = img_overl->rle;
rle_elem_t *rle_limit = rle + img_overl->num_rle;
int x, y, x1_scaled, x2_scaled;
int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */
int clip_right;
uint8_t *img_pix;
dy_step = INT_TO_SCALED(dst_height) / img_height;
x_scale = INT_TO_SCALED(img_width) / dst_width;
img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width
+ (img_overl->x * img_width / dst_width));
- trans = img_overl->clip_trans;
-
/* avoid wraping overlay if drawing to small image */
- if( (img_overl->x + img_overl->clip_right) < dst_width )
+ if( (img_overl->x + img_overl->clip_right) <= dst_width )
clip_right = img_overl->clip_right;
else
- clip_right = dst_width - 1 - img_overl->x;
+ clip_right = dst_width - img_overl->x;
/* avoid buffer overflow */
- if( (src_height + img_overl->y) >= dst_height )
- src_height = dst_height - 1 - img_overl->y;
+ if( (src_height + img_overl->y) > dst_height )
+ src_height = dst_height - img_overl->y;
for (dy = y = 0; y < src_height && rle < rle_limit; ) {
- int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
+ int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
rle_elem_t *rle_start = rle;
+ int rlelen = 0;
+ uint8_t clr = 0;
+
for (x = x1_scaled = 0; x < src_width;) {
- uint8_t clr;
+ int rle_bite;
+ clut_t *colors;
+ uint8_t *trans;
uint16_t o;
- int rlelen;
- clr = rle->color;
- o = trans[clr];
- rlelen = rle->len;
-
- if (o && mask) {
- /* threat cases where clipping border is inside rle->len pixels */
- if ( img_overl->clip_left > x ) {
- if( img_overl->clip_left < x + rlelen ) {
- x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
- rlelen -= img_overl->clip_left - x;
- x += img_overl->clip_left - x;
+ /* take next element from rle list everytime an element is finished */
+ if (rlelen <= 0) {
+ if (rle >= rle_limit)
+ break;
+
+ rlelen = rle->len;
+ clr = rle->color;
+ rle++;
+ }
+
+ if (!mask) {
+ /* above or below clipping area */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
+ } else {
+ /* treat cases where clipping border is inside rle->len pixels */
+ if ( x < img_overl->clip_left ) {
+ /* starts left */
+ if( x + rlelen > img_overl->clip_left ) {
+ /* ends not left */
+
+ /* choose the largest "bite" up to palette change */
+ rle_bite = img_overl->clip_left - x;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
} else {
- o = 0;
+ /* ends left */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
}
- } else if( clip_right < x + rlelen ) {
- if( clip_right > x ) {
- x2_scaled = SCALED_TO_INT( clip_right * x_scale);
- mem_blend24(img_pix + x1_scaled*3, clut[clr].cb,
- clut[clr].cr, clut[clr].y,
- o, x2_scaled-x1_scaled);
- o = 0;
+ } else if( x + rlelen > clip_right ) {
+ /* ends right */
+ if( x < clip_right ) {
+ /* starts not right */
+
+ /* choose the largest "bite" up to palette change */
+ rle_bite = clip_right - x;
+ /* we're in the center area so choose clip palette */
+ colors = (clut_t*)img_overl->clip_color;
+ trans = img_overl->clip_trans;
} else {
- o = 0;
+ /* starts right */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
}
- }
+ } else {
+ /* starts not left and ends not right */
+
+ rle_bite = rlelen;
+ /* we're in the center area so choose clip palette */
+ colors = (clut_t*)img_overl->clip_color;
+ trans = img_overl->clip_trans;
+ }
}
- x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
- if (o && mask) {
- mem_blend24(img_pix + x1_scaled*3, clut[clr].cb,
- clut[clr].cr, clut[clr].y,
+ x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
+
+ o = trans[clr];
+ if (o) {
+ mem_blend24(img_pix + x1_scaled*3,
+ colors[clr].cb, colors[clr].cr, colors[clr].y,
o, x2_scaled-x1_scaled);
}
x1_scaled = x2_scaled;
- x += rlelen;
- rle++;
- if (rle >= rle_limit) break;
+ x += rle_bite;
+ rlelen -= rle_bite;
}
img_pix += img_width * 3;
dy += dy_step;
if (dy >= INT_TO_SCALED(1)) {
dy -= INT_TO_SCALED(1);
++y;
while (dy >= INT_TO_SCALED(1)) {
rle = rle_img_advance_line(rle, rle_limit, src_width);
dy -= INT_TO_SCALED(1);
++y;
}
} else {
rle = rle_start; /* y-scaling, reuse the last rle encoded line */
}
}
}
void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
- int dst_width, int dst_height)
+ int dst_width, int dst_height,
+ alphablend_t *extra_data)
{
- clut_t* clut = (clut_t*) img_overl->clip_color;
- uint8_t *trans;
int src_width = img_overl->width;
int src_height = img_overl->height;
rle_elem_t *rle = img_overl->rle;
rle_elem_t *rle_limit = rle + img_overl->num_rle;
int x, y, x1_scaled, x2_scaled;
int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */
int clip_right;
uint8_t *img_pix;
dy_step = INT_TO_SCALED(dst_height) / img_height;
x_scale = INT_TO_SCALED(img_width) / dst_width;
img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width
+ (img_overl->x * img_width / dst_width));
- trans = img_overl->clip_trans;
-
/* avoid wraping overlay if drawing to small image */
- if( (img_overl->x + img_overl->clip_right) < dst_width )
+ if( (img_overl->x + img_overl->clip_right) <= dst_width )
clip_right = img_overl->clip_right;
else
- clip_right = dst_width - 1 - img_overl->x;
+ clip_right = dst_width - img_overl->x;
/* avoid buffer overflow */
- if( (src_height + img_overl->y) >= dst_height )
- src_height = dst_height - 1 - img_overl->y;
+ if( (src_height + img_overl->y) > dst_height )
+ src_height = dst_height - img_overl->y;
for (y = dy = 0; y < src_height && rle < rle_limit; ) {
- int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
+ int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
rle_elem_t *rle_start = rle;
+ int rlelen = 0;
+ uint8_t clr = 0;
+
for (x = x1_scaled = 0; x < src_width;) {
- uint8_t clr;
+ int rle_bite;
+ clut_t *colors;
+ uint8_t *trans;
uint16_t o;
- int rlelen;
+
+ /* take next element from rle list everytime an element is finished */
+ if (rlelen <= 0) {
+ if (rle >= rle_limit)
+ break;
+
+ rlelen = rle->len;
+ clr = rle->color;
+ rle++;
+ }
- clr = rle->color;
- o = trans[clr];
- rlelen = rle->len;
-
- if (o && mask) {
- /* threat cases where clipping border is inside rle->len pixels */
- if ( img_overl->clip_left > x ) {
- if( img_overl->clip_left < x + rlelen ) {
- x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale );
- rlelen -= img_overl->clip_left - x;
- x += img_overl->clip_left - x;
+ if (!mask) {
+ /* above or below clipping area */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
+ } else {
+ /* treat cases where clipping border is inside rle->len pixels */
+ if ( x < img_overl->clip_left ) {
+ /* starts left */
+ if( x + rlelen > img_overl->clip_left ) {
+ /* ends not left */
+
+ /* choose the largest "bite" up to palette change */
+ rle_bite = img_overl->clip_left - x;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
} else {
- o = 0;
+ /* ends left */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
}
- } else if( clip_right < x + rlelen ) {
- if( clip_right > x ) {
- x2_scaled = SCALED_TO_INT( clip_right * x_scale);
- mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb,
- clut[clr].cr, clut[clr].y,
- o, x2_scaled-x1_scaled);
- o = 0;
+ } else if( x + rlelen > clip_right ) {
+ /* ends right */
+ if( x < clip_right ) {
+ /* starts not right */
+
+ /* choose the largest "bite" up to palette change */
+ rle_bite = clip_right - x;
+ /* we're in the center area so choose clip palette */
+ colors = (clut_t*)img_overl->clip_color;
+ trans = img_overl->clip_trans;
} else {
- o = 0;
+ /* starts right */
+
+ rle_bite = rlelen;
+ /* choose palette for surrounding area */
+ colors = (clut_t*)img_overl->color;
+ trans = img_overl->trans;
}
- }
+ } else {
+ /* starts not left and ends not right */
+
+ rle_bite = rlelen;
+ /* we're in the center area so choose clip palette */
+ colors = (clut_t*)img_overl->clip_color;
+ trans = img_overl->clip_trans;
+ }
}
+
+ x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
- x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale);
- if (o && mask) {
- mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb,
- clut[clr].cr, clut[clr].y,
- o, x2_scaled-x1_scaled);
+ o = trans[clr];
+ if (o) {
+ mem_blend32(img_pix + x1_scaled*4, (uint8_t *)&colors[clr], o, x2_scaled-x1_scaled);
}
x1_scaled = x2_scaled;
- x += rlelen;
- rle++;
- if (rle >= rle_limit) break;
+ x += rle_bite;
+ rlelen -= rle_bite;
}
img_pix += img_width * 4;
dy += dy_step;
if (dy >= INT_TO_SCALED(1)) {
dy -= INT_TO_SCALED(1);
++y;
while (dy >= INT_TO_SCALED(1)) {
rle = rle_img_advance_line(rle, rle_limit, src_width);
dy -= INT_TO_SCALED(1);
++y;
}
} else {
rle = rle_start; /* y-scaling, reuse the last rle encoded line */
}
}
}
static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz)
{
uint8_t *limit = mem + sz;
while (mem < limit) {
*mem = BLEND_BYTE(*mem, val, o);
mem++;
}
}
+static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb,
+ int src_width, int x_odd,
+ uint8_t *(*blend_yuv_data)[ 3 ][ 2 ])
+{
+ int x;
+
+ for (x = 0; x < src_width; x += 2) {
+ /* get opacity of the 4 pixels that share chroma */
+ int o00 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 0 ];
+ int o01 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 1 ];
+ int o10 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 0 ];
+ int o11 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 1 ];
+
+ /* are there any pixels a little bit opaque? */
+ if (o00 || o01 || o10 || o11) {
+ /* get the chroma components of the 4 pixels */
+ int cr00 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 0 ];
+ int cr01 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 1 ];
+ int cr10 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 0 ];
+ int cr11 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 1 ];
+
+ int cb00 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 0 ];
+ int cb01 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 1 ];
+ int cb10 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 0 ];
+ int cb11 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 1 ];
+
+ /* are all pixels completely opaque? */
+ if (o00 >= 0xf && o01 >= 0xf && o10 >= 0xf && o11 >= 0xf) {
+ /* set the output chroma to the average of the four pixels */
+ *dst_cr = 128 + (cr00 + cr01 + cr10 + cr11) / 4;
+ *dst_cb = 128 + (cb00 + cb01 + cb10 + cb11) / 4;
+ } else {
+ int t4, cr, cb;
+
+ /* blending required, so clamp opacity values to allowed range */
+ if (o00 > 0xf) o00 = 0xf;
+ if (o01 > 0xf) o01 = 0xf;
+ if (o10 > 0xf) o10 = 0xf;
+ if (o11 > 0xf) o11 = 0xf;
+
+ /* calculate transparency of background over the four pixels */
+ t4 = (0xf - o00) + (0xf - o01) + (0xf - o10) + (0xf - o11);
+
+ /* get background chroma */
+ cr = -128 + *dst_cr;
+ cb = -128 + *dst_cb;
+
+ /* blend the output chroma to the average of the four pixels */
+ *dst_cr = 128 + (cr * t4 + cr00 * o00 + cr01 * o01 + cr10 * o10 + cr11 * o11) / (4 * 0xf);
+ *dst_cb = 128 + (cb * t4 + cb00 * o00 + cb01 * o01 + cb10 * o10 + cb11 * o11) / (4 * 0xf);
+ }
+ }
+
+ /* next chroma sample */
+ dst_cr++;
+ dst_cb++;
+ }
+}
+
+static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ]
+{
+ struct __attribute__((packed)) header_s {
+ int id;
+ int max_width;
+ uint8_t *data[ 3 ][ 2 ];
+ } **header = (struct header_s **)&extra_data->buffer;
+
+ int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ 2 ][ osd_width ]);
+
+ if (extra_data->buffer_size < needed_buffer_size) {
+
+ free(extra_data->buffer);
+ extra_data->buffer = xine_xmalloc(needed_buffer_size);
+
+ if (!extra_data->buffer) {
+ extra_data->buffer_size = 0;
+ return 0;
+ }
+
+ extra_data->buffer_size = needed_buffer_size;
+ (*header)->max_width = 0;
+ }
+
+ if ((*header)->id != ME_FOURCC('y', 'u', 'v', 0) || (*header)->max_width < osd_width) {
+ (*header)->id = ME_FOURCC('y', 'u', 'v', 0);
+ (*header)->max_width = osd_width;
+
+ (*header)->data[ 0 ][ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
+ (*header)->data[ 0 ][ 1 ] = (*header)->data[ 0 ][ 0 ] + osd_width;
+ (*header)->data[ 1 ][ 0 ] = (*header)->data[ 0 ][ 1 ] + osd_width;
+ (*header)->data[ 1 ][ 1 ] = (*header)->data[ 1 ][ 0 ] + osd_width;
+ (*header)->data[ 2 ][ 0 ] = (*header)->data[ 1 ][ 1 ] + osd_width;
+ (*header)->data[ 2 ][ 1 ] = (*header)->data[ 2 ][ 0 ] + osd_width;
+ }
+
+ return &(*header)->data;
+}
+
void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
- int dst_width, int dst_height)
+ int dst_width, int dst_height, int dst_pitches[3],
+ alphablend_t *extra_data)
{
+ int enable_exact_blending = !extra_data->disable_exact_blending;
clut_t *my_clut;
uint8_t *my_trans;
int src_width = img_overl->width;
int src_height = img_overl->height;
rle_elem_t *rle = img_overl->rle;
rle_elem_t *rle_limit = rle + img_overl->num_rle;
int x_off = img_overl->x;
int y_off = img_overl->y;
+ int x_odd = x_off & 1;
+ int y_odd = y_off & 1;
int ymask,xmask;
int rle_this_bite;
int rle_remainder;
int rlelen;
int x, y;
int clip_right;
uint8_t clr=0;
-
- uint8_t *dst_y = dst_base[0] + dst_width * y_off + x_off;
- uint8_t *dst_cr = dst_base[2] +
- (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1;
- uint8_t *dst_cb = dst_base[1] +
- (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1;
+
+ int any_line_buffered = 0;
+ int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
+ int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
+ uint8_t *(*blend_yuv_data)[ 3 ][ 2 ] = 0;
+
+ uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off;
+ uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2);
+ uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2);
#ifdef LOG_BLEND_YUV
printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height);
#endif
my_clut = (clut_t*) img_overl->clip_color;
my_trans = img_overl->clip_trans;
/* avoid wraping overlay if drawing to small image */
- if( (x_off + img_overl->clip_right) < dst_width )
+ if( (x_off + img_overl->clip_right) <= dst_width )
clip_right = img_overl->clip_right;
else
- clip_right = dst_width - 1 - x_off;
+ clip_right = dst_width - x_off;
/* avoid buffer overflow */
- if( (src_height + y_off) >= dst_height )
- src_height = dst_height - 1 - y_off;
+ if( (src_height + y_off) > dst_height )
+ src_height = dst_height - y_off;
+ if (src_height <= 0)
+ return;
+
+ if (enable_exact_blending) {
+ if (exact_blend_width <= 0)
+ return;
+
+ blend_yuv_data = blend_yuv_grow_extra_data(extra_data, exact_blend_width_m2);
+ if (!blend_yuv_data)
+ return;
+
+ /* make linebuffer transparent */
+ memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2);
+ memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
+ }
+
rlelen=rle_remainder=0;
for (y = 0; y < src_height; y++) {
- ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y));
+ if (rle >= rle_limit) {
+#ifdef LOG_BLEND_YUV
+ printf("y-rle_limit\n");
+#endif
+ break;
+ }
+
+ ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
xmask = 0;
#ifdef LOG_BLEND_YUV
printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height);
#endif
for (x = 0; x < src_width;) {
uint16_t o;
+
+ if (rle >= rle_limit) {
+#ifdef LOG_BLEND_YUV
+ printf("x-rle_limit\n");
+#endif
+ break;
+ }
+
#ifdef LOG_BLEND_YUV
printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
#endif
if ((rlelen < 0) || (rle_remainder < 0)) {
+#ifdef LOG_BLEND_YUV
printf("alphablend: major bug in blend_yuv < 0\n");
+#endif
}
if (rlelen == 0) {
rle_remainder = rlelen = rle->len;
clr = rle->color;
rle++;
}
if (rle_remainder == 0) {
rle_remainder = rlelen;
}
if ((rle_remainder + x) > src_width) {
/* Do something for long rlelengths */
- rle_remainder = src_width - x;
- ;
+ rle_remainder = src_width - x;
}
#ifdef LOG_BLEND_YUV
printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
#endif
if (ymask == 0) {
- if (x <= img_overl->clip_left) {
+ if (x < img_overl->clip_left) {
/* Starts outside clip area */
- if ((x + rle_remainder - 1) > img_overl->clip_left ) {
+ if ((x + rle_remainder) > img_overl->clip_left ) {
#ifdef LOG_BLEND_YUV
printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
#endif
/* Cutting needed, starts outside, ends inside */
- rle_this_bite = (img_overl->clip_left - x + 1);
+ rle_this_bite = (img_overl->clip_left - x);
rle_remainder -= rle_this_bite;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->color;
my_trans = img_overl->trans;
xmask = 0;
} else {
#ifdef LOG_BLEND_YUV
printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
#endif
/* no cutting needed, starts outside, ends outside */
rle_this_bite = rle_remainder;
rle_remainder = 0;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->color;
my_trans = img_overl->trans;
xmask = 0;
}
} else if (x < clip_right) {
/* Starts inside clip area */
if ((x + rle_remainder) > clip_right ) {
#ifdef LOG_BLEND_YUV
printf("Inside clip right %d, ending outside\n", clip_right);
#endif
/* Cutting needed, starts inside, ends outside */
rle_this_bite = (clip_right - x);
rle_remainder -= rle_this_bite;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->clip_color;
my_trans = img_overl->clip_trans;
xmask++;
} else {
#ifdef LOG_BLEND_YUV
printf("Inside clip right %d, ending inside\n", clip_right);
#endif
/* no cutting needed, starts inside, ends inside */
rle_this_bite = rle_remainder;
rle_remainder = 0;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->clip_color;
my_trans = img_overl->clip_trans;
xmask++;
}
} else if (x >= clip_right) {
- /* Starts outside clip area, ends outsite clip area */
+ /* Starts outside clip area, ends outside clip area */
if ((x + rle_remainder ) > src_width ) {
#ifdef LOG_BLEND_YUV
printf("Outside clip right %d, ending eol\n", clip_right);
#endif
/* Cutting needed, starts outside, ends at right edge */
/* It should never reach here due to the earlier test of src_width */
rle_this_bite = (src_width - x );
rle_remainder -= rle_this_bite;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->color;
my_trans = img_overl->trans;
xmask = 0;
} else {
/* no cutting needed, starts outside, ends outside */
#ifdef LOG_BLEND_YUV
printf("Outside clip right %d, ending outside\n", clip_right);
#endif
rle_this_bite = rle_remainder;
rle_remainder = 0;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->color;
my_trans = img_overl->trans;
xmask = 0;
}
}
} else {
/* Outside clip are due to y */
/* no cutting needed, starts outside, ends outside */
rle_this_bite = rle_remainder;
rle_remainder = 0;
rlelen -= rle_this_bite;
my_clut = (clut_t*) img_overl->color;
my_trans = img_overl->trans;
xmask = 0;
}
o = my_trans[clr];
#ifdef LOG_BLEND_YUV
printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y);
#endif
- if (o) {
- if(o >= 15) {
- memset(dst_y + x, my_clut[clr].y, rle_this_bite);
- if (y & 1) {
- memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
- memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
- }
- } else {
- mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
- if (y & 1) {
- /* Blending cr and cb should use a different function, with pre -128 to each sample */
- mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
- mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
- }
+
+ if (x < (dst_width - x_off)) {
+ /* clip against right edge of destination area */
+ if ((x + rle_this_bite) > (dst_width - x_off)) {
+ int toClip = (x + rle_this_bite) - (dst_width - x_off);
+
+ rle_this_bite -= toClip;
+ rle_remainder += toClip;
+ rlelen += toClip;
}
+ if (enable_exact_blending) {
+ /* remember opacity of current line */
+ memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite);
+ any_line_buffered |= ((y + y_odd) & 1) ? 2 : 1;
+ }
+
+ if (o) {
+ if(o >= 15) {
+ memset(dst_y + x, my_clut[clr].y, rle_this_bite);
+ if (!enable_exact_blending) {
+ if ((y + y_odd) & 1) {
+ memset(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
+ memset(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
+ }
+ }
+ } else {
+ mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
+ if (!enable_exact_blending) {
+ if ((y + y_odd) & 1) {
+ /* Blending cr and cb should use a different function, with pre -128 to each sample */
+ mem_blend8(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
+ mem_blend8(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
+ }
+ }
+ }
+
+ if (enable_exact_blending) {
+ /* remember chroma of current line */
+ memset(&(*blend_yuv_data)[ 1 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
+ memset(&(*blend_yuv_data)[ 2 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
+ }
+ }
}
#ifdef LOG_BLEND_YUV
printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x);
#endif
x += rle_this_bite;
- if (rle >= rle_limit) {
-#ifdef LOG_BLEND_YUV
- printf("x-rle_limit\n");
-#endif
- break;
- }
- }
- if (rle >= rle_limit) {
-#ifdef LOG_BLEND_YUV
- printf("x-rle_limit\n");
-#endif
- break;
}
- dst_y += dst_width;
+ if ((y + y_odd) & 1) {
+ if (enable_exact_blending) {
+ /* blend buffered lines */
+ if (any_line_buffered) {
+ if (!(any_line_buffered & 2)) {
+ /* make second line transparent */
+ memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
+ }
+
+ blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
+
+ any_line_buffered = 0;
+ }
+ }
+
+ dst_cr += dst_pitches[2];
+ dst_cb += dst_pitches[1];
+ }
+
+ dst_y += dst_pitches[0];
+ }
- if (y & 1) {
- dst_cr += (dst_width + 1) / 2;
- dst_cb += (dst_width + 1) / 2;
+ if (enable_exact_blending) {
+ /* blend buffered lines */
+ if (any_line_buffered) {
+ if (!(any_line_buffered & 2)) {
+ /* make second line transparent */
+ memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
+ }
+
+ blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
}
}
+
#ifdef LOG_BLEND_YUV
printf("overlay_blend ended\n");
#endif
}
+static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb,
+ int src_width, int x_odd,
+ uint8_t *(*blend_yuy2_data)[ 3 ])
+{
+ int x;
+
+ for (x = 0; x < src_width; x += 2) {
+ /* get opacity of the 2 pixels that share chroma */
+ int o0 = (*blend_yuy2_data)[ 0 ][ x + 0 ];
+ int o1 = (*blend_yuy2_data)[ 0 ][ x + 1 ];
+
+ /* are there any pixels a little bit opaque? */
+ if (o0 || o1) {
+ /* get the chroma components of the 2 pixels */
+ int cr0 = -128 + (*blend_yuy2_data)[ 1 ][ x + 0 ];
+ int cr1 = -128 + (*blend_yuy2_data)[ 1 ][ x + 1 ];
+
+ int cb0 = -128 + (*blend_yuy2_data)[ 2 ][ x + 0 ];
+ int cb1 = -128 + (*blend_yuy2_data)[ 2 ][ x + 1 ];
+
+ /* are all pixels completely opaque? */
+ if (o0 >= 0xf && o1 >= 0xf) {
+ /* set the output chroma to the average of the two pixels */
+ *dst_cr = 128 + (cr0 + cr1) / 2;
+ *dst_cb = 128 + (cb0 + cb1) / 2;
+ } else {
+ int t2, cr, cb;
+
+ /* blending required, so clamp opacity values to allowed range */
+ if (o0 > 0xf) o0 = 0xf;
+ if (o1 > 0xf) o1 = 0xf;
+
+ /* calculate transparency of background over the two pixels */
+ t2 = (0xf - o0) + (0xf - o1);
+
+ /* get background chroma */
+ cr = -128 + *dst_cr;
+ cb = -128 + *dst_cb;
+
+ /* blend the output chroma to the average of the two pixels */
+ *dst_cr = 128 + (cr * t2 + cr0 * o0 + cr1 * o1) / (2 * 0xf);
+ *dst_cb = 128 + (cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf);
+ }
+ }
+
+ /* next chroma sample */
+ dst_cr += 4;
+ dst_cb += 4;
+ }
+}
+
+static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ]
+{
+ struct __attribute__((packed)) header_s {
+ int id;
+ int max_width;
+ uint8_t *data[ 3 ];
+ } **header = (struct header_s **)&extra_data->buffer;
+
+ int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ osd_width ]);
+
+ if (extra_data->buffer_size < needed_buffer_size) {
+
+ free(extra_data->buffer);
+ extra_data->buffer = xine_xmalloc(needed_buffer_size);
+
+ if (!extra_data->buffer) {
+ extra_data->buffer_size = 0;
+ return 0;
+ }
+
+ extra_data->buffer_size = needed_buffer_size;
+ (*header)->max_width = 0;
+ }
+
+ if ((*header)->id != ME_FOURCC('y', 'u', 'y', '2') || (*header)->max_width < osd_width) {
+ (*header)->id = ME_FOURCC('y', 'u', 'y', '2');
+ (*header)->max_width = osd_width;
+
+ (*header)->data[ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
+ (*header)->data[ 1 ] = (*header)->data[ 0 ] + osd_width;
+ (*header)->data[ 2 ] = (*header)->data[ 1 ] + osd_width;
+ }
+
+ return &(*header)->data;
+}
+
void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
- int dst_width, int dst_height)
+ int dst_width, int dst_height, int dst_pitch,
+ alphablend_t *extra_data)
{
+ int enable_exact_blending = !extra_data->disable_exact_blending;
clut_t *my_clut;
uint8_t *my_trans;
int src_width = img_overl->width;
int src_height = img_overl->height;
rle_elem_t *rle = img_overl->rle;
rle_elem_t *rle_limit = rle + img_overl->num_rle;
int x_off = img_overl->x;
int y_off = img_overl->y;
- int mask;
+ int x_odd = x_off & 1;
+ int ymask;
+ int rle_this_bite;
+ int rle_remainder;
+ int rlelen;
int x, y;
- int l;
+ int l = 0;
int clip_right;
- uint32_t yuy2;
+
+ union {
+ uint32_t value;
+ uint8_t b[4];
+ uint16_t h[2];
+ } yuy2;
+
+ uint8_t clr = 0;
+
+ int any_line_buffered = 0;
+ int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
+ int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
+ uint8_t *(*blend_yuy2_data)[ 3 ] = 0;
- uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off);
+ uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off;
uint8_t *dst;
my_clut = (clut_t*) img_overl->clip_color;
my_trans = img_overl->clip_trans;
/* avoid wraping overlay if drawing to small image */
- if( (x_off + img_overl->clip_right) < dst_width )
+ if( (x_off + img_overl->clip_right) <= dst_width )
clip_right = img_overl->clip_right;
else
- clip_right = dst_width - 1 - x_off;
+ clip_right = dst_width - x_off;
/* avoid buffer overflow */
- if( (src_height + y_off) >= dst_height )
- src_height = dst_height - 1 - y_off;
+ if( (src_height + y_off) > dst_height )
+ src_height = dst_height - y_off;
+
+ if (src_height <= 0)
+ return;
+
+ if (enable_exact_blending) {
+ if (exact_blend_width <= 0)
+ return;
+
+ blend_yuy2_data = blend_yuy2_grow_extra_data(extra_data, exact_blend_width_m2);
+ if (!blend_yuy2_data)
+ return;
+
+ /* make linebuffer transparent */
+ memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2);
+ }
+ rlelen=rle_remainder=0;
for (y = 0; y < src_height; y++) {
- mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y);
+ if (rle >= rle_limit)
+ break;
+
+ ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
dst = dst_y;
for (x = 0; x < src_width;) {
- uint8_t clr;
uint16_t o;
- int rlelen;
- clr = rle->color;
- o = my_trans[clr];
- rlelen = rle->len;
-
- if (o && mask) {
- /* threat cases where clipping border is inside rle->len pixels */
- if ( img_overl->clip_left > x ) {
- if( img_overl->clip_left < x + rlelen ) {
- rlelen -= img_overl->clip_left - x;
- x += img_overl->clip_left - x;
+ if (rle >= rle_limit)
+ break;
+
+ if ((rlelen < 0) || (rle_remainder < 0)) {
+#ifdef LOG_BLEND_YUV
+ printf("alphablend: major bug in blend_yuv < 0\n");
+#endif
+ }
+ if (rlelen == 0) {
+ rle_remainder = rlelen = rle->len;
+ clr = rle->color;
+ rle++;
+ }
+ if (rle_remainder == 0) {
+ rle_remainder = rlelen;
+ }
+ if ((rle_remainder + x) > src_width) {
+ /* Do something for long rlelengths */
+ rle_remainder = src_width - x;
+ }
+#ifdef LOG_BLEND_YUV
+ printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
+#endif
+
+ if (ymask == 0) {
+ if (x < img_overl->clip_left) {
+ /* Starts outside clip area */
+ if ((x + rle_remainder) > img_overl->clip_left ) {
+#ifdef LOG_BLEND_YUV
+ printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
+#endif
+ /* Cutting needed, starts outside, ends inside */
+ rle_this_bite = (img_overl->clip_left - x);
+ rle_remainder -= rle_this_bite;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
} else {
- o = 0;
+#ifdef LOG_BLEND_YUV
+ printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
+#endif
+ /* no cutting needed, starts outside, ends outside */
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
}
- } else if( clip_right < x + rlelen ) {
- if( clip_right > x ) {
- /* fixme: case not implemented */
- o = 0;
+ } else if (x < clip_right) {
+ /* Starts inside clip area */
+ if ((x + rle_remainder) > clip_right ) {
+#ifdef LOG_BLEND_YUV
+ printf("Inside clip right %d, ending outside\n", clip_right);
+#endif
+ /* Cutting needed, starts inside, ends outside */
+ rle_this_bite = (clip_right - x);
+ rle_remainder -= rle_this_bite;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->clip_color;
+ my_trans = img_overl->clip_trans;
} else {
- o = 0;
+#ifdef LOG_BLEND_YUV
+ printf("Inside clip right %d, ending inside\n", clip_right);
+#endif
+ /* no cutting needed, starts inside, ends inside */
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->clip_color;
+ my_trans = img_overl->clip_trans;
}
- }
+ } else if (x >= clip_right) {
+ /* Starts outside clip area, ends outsite clip area */
+ if ((x + rle_remainder ) > src_width ) {
+#ifdef LOG_BLEND_YUV
+ printf("Outside clip right %d, ending eol\n", clip_right);
+#endif
+ /* Cutting needed, starts outside, ends at right edge */
+ /* It should never reach here due to the earlier test of src_width */
+ rle_this_bite = (src_width - x );
+ rle_remainder -= rle_this_bite;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
+ } else {
+ /* no cutting needed, starts outside, ends outside */
+#ifdef LOG_BLEND_YUV
+ printf("Outside clip right %d, ending outside\n", clip_right);
+#endif
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
+ }
+ }
+ } else {
+ /* Outside clip are due to y */
+ /* no cutting needed, starts outside, ends outside */
+ rle_this_bite = rle_remainder;
+ rle_remainder = 0;
+ rlelen -= rle_this_bite;
+ my_clut = (clut_t*) img_overl->color;
+ my_trans = img_overl->trans;
}
-
+ o = my_trans[clr];
+
+ if (x < (dst_width - x_off)) {
+ /* clip against right edge of destination area */
+ if ((x + rle_this_bite) > (dst_width - x_off)) {
+ int toClip = (x + rle_this_bite) - (dst_width - x_off);
+
+ rle_this_bite -= toClip;
+ rle_remainder += toClip;
+ rlelen += toClip;
+ }
+
+ if (enable_exact_blending) {
+ /* remember opacity of current line */
+ memset(&(*blend_yuy2_data)[ 0 ][ x + x_odd ], o, rle_this_bite);
+ any_line_buffered = 1;
+ }
+
+ if (o) {
+ if (!enable_exact_blending) {
+ l = rle_this_bite>>1;
+ if( !((x_odd+x) & 1) ) {
+ yuy2.b[0] = my_clut[clr].y;
+ yuy2.b[1] = my_clut[clr].cb;
+ yuy2.b[2] = my_clut[clr].y;
+ yuy2.b[3] = my_clut[clr].cr;
+ } else {
+ yuy2.b[0] = my_clut[clr].y;
+ yuy2.b[1] = my_clut[clr].cr;
+ yuy2.b[2] = my_clut[clr].y;
+ yuy2.b[3] = my_clut[clr].cb;
+ }
+ }
+ if (o >= 15) {
+ if (!enable_exact_blending) {
+ while(l--) {
+ *(uint16_t *)dst = yuy2.h[0];
+ dst += 2;
+ *(uint16_t *)dst = yuy2.h[1];
+ dst += 2;
+ }
+ if(rle_this_bite & 1) {
+ *(uint16_t *)dst = yuy2.h[0];
+ dst += 2;
+ }
+ } else {
+ l = rle_this_bite;
+ while (l--) {
+ *dst = my_clut[clr].y;
+ dst += 2;
+ }
+ }
+ } else {
+ if (!enable_exact_blending) {
+ if( l ) {
+ mem_blend32(dst, &yuy2.b[0], o, l);
+ dst += 4*l;
+ }
+
+ if(rle_this_bite & 1) {
+ *dst = BLEND_BYTE(*dst, yuy2.b[0], o);
+ dst++;
+ *dst = BLEND_BYTE(*dst, yuy2.b[1], o);
+ dst++;
+ }
+ } else {
+ l = rle_this_bite;
+ while (l--) {
+ *dst = BLEND_BYTE(*dst, my_clut[clr].y, o);
+ dst += 2;
+ }
+ }
+ }
- if (o && mask) {
- l = rlelen>>1;
- if( !(x & 1) ) {
- yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) +
- (my_clut[clr].y << 16) + (my_clut[clr].cr << 24);
+ if (enable_exact_blending) {
+ /* remember chroma of current line */
+ memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
+ memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
+ }
} else {
- yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) +
- (my_clut[clr].y << 16) + (my_clut[clr].cb << 24);
+ dst += rle_this_bite*2;
}
+ }
+
+ x += rle_this_bite;
+ }
+
+ if (enable_exact_blending) {
+ /* blend buffered line */
+ if (any_line_buffered) {
+ blend_yuy2_exact(dst_y - x_odd * 2 + 3, dst_y - x_odd * 2 + 1, exact_blend_width, x_odd, blend_yuy2_data);
- if (o >= 15) {
- while(l--) {
- *((uint32_t *)dst)++ = yuy2;
+ any_line_buffered = 0;
+ }
+ }
+
+ dst_y += dst_pitch;
+ }
+}
+
+void clear_xx44_palette(xx44_palette_t *p)
+{
+ register int i;
+ register uint32_t *cluts = p->cluts;
+ register int *ids = p->lookup_cache;
+
+ i= p->size;
+ while(i--)
+ *cluts++ = 0;
+ i = 2*OVL_PALETTE_SIZE;
+ while(i--)
+ *ids++ = -1;
+ p->max_used=1;
+}
+
+void init_xx44_palette(xx44_palette_t *p, unsigned num_entries)
+{
+ p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries;
+}
+
+void dispose_xx44_palette(xx44_palette_t *p)
+{
+}
+
+static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p,
+ unsigned num_xvmc_components, char *xvmc_components)
+{
+ const clut_t *color = (const clut_t *) icolor;
+ int i;
+ for (i=0; i<num_xvmc_components; ++i) {
+ switch(xvmc_components[i]) {
+ case 'V': *palette_p = color->cr; break;
+ case 'U': *palette_p = color->cb; break;
+ case 'Y':
+ default: *palette_p = color->y; break;
+ }
+ *palette_p++;
+ }
+}
+
+
+void xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette,
+ unsigned first_xx44_entry, unsigned num_xx44_entries,
+ unsigned num_xvmc_components, char *xvmc_components)
+{
+ register int i;
+ register const uint32_t *cluts = p->cluts + first_xx44_entry;
+
+ for (i=0; i<num_xx44_entries; ++i) {
+ if ((cluts - p->cluts) < p->size) {
+ colorToPalette(cluts++, xvmc_palette, num_xvmc_components, xvmc_components);
+ xvmc_palette += num_xvmc_components;
+ }
+ }
+}
+
+static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut)
+{
+
+ register int i;
+ register uint32_t *cluts = p->cluts;
+ register int tmp;
+
+ if ((tmp = p->lookup_cache[color]) >= 0)
+ if (cluts[tmp] == clut) return tmp;
+
+ for (i=0; i<p->max_used; ++i) {
+ if (*cluts++ == clut) return p->lookup_cache[color] = i;
+ }
+
+ if (p->max_used == p->size -1) {
+ printf("video_out: Warning! Out of xx44 palette colors!\n");
+ return 1;
+ }
+ p->cluts[p->max_used] = clut;
+ return p->lookup_cache[color] = p->max_used++;
+}
+
+static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask)
+{
+ register uint8_t masked_val = val & mask;
+
+ while(size--) {
+ if ((*mem & mask) <= masked_val ) *mem = val;
+ mem++;
+ }
+}
+
+void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
+ int dst_width, int dst_height, int dst_pitch,
+ alphablend_t *extra_data,
+ xx44_palette_t *palette,int ia44)
+{
+ int src_width = img_overl->width;
+ int src_height = img_overl->height;
+ rle_elem_t *rle = img_overl->rle;
+ rle_elem_t *rle_limit = rle + img_overl->num_rle;
+ int mask;
+ int x_off = img_overl->x;
+ int y_off = img_overl->y;
+ int x, y;
+ uint8_t norm_pixel,clip_pixel;
+ uint8_t *dst_y;
+ uint8_t *dst;
+ uint8_t alphamask = (ia44) ? 0x0F : 0xF0;
+ int clip_right;
+
+ if (!img_overl)
+ return;
+
+ dst_y = dst_img + dst_pitch*y_off + x_off;
+
+ if( (x_off + img_overl->width) <= dst_width )
+ clip_right = img_overl->width;
+ else
+ clip_right = dst_width - x_off;
+
+ if ((src_height + y_off) > dst_height)
+ src_height = dst_height - y_off;
+
+ for (y = 0; y < src_height; y++) {
+
+ mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
+ dst = dst_y;
+
+ for (x = 0; x < src_width;) {
+ int len = (x + rle->len > clip_right) ? clip_right - x : rle->len;
+
+ if (len > 0) {
+ norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color,
+ img_overl->color[rle->color]) << 4) |
+ (img_overl->trans[rle->color] & 0x0F));
+ clip_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color+OVL_PALETTE_SIZE,
+ img_overl->clip_color[rle->color]) << 4) |
+ (img_overl->clip_trans[rle->color] & 0x0F));
+ if (!ia44) {
+ norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
+ clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
+ }
+ if (mask) {
+ if (x < img_overl->clip_left) {
+ if (x + len <= img_overl->clip_left) {
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,norm_pixel,img_overl->clip_left -x, alphamask);
+ dst += img_overl->clip_left - x;
+ len -= img_overl->clip_left - x;
+ if (len <= img_overl->clip_right - img_overl->clip_left) {
+ memblend_xx44(dst,clip_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,clip_pixel,img_overl->clip_right - img_overl->clip_left,
+ alphamask);
+ dst += img_overl->clip_right - img_overl->clip_left;
+ len -= img_overl->clip_right - img_overl->clip_left;
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ }
+ } else if (x < img_overl->clip_right) {
+ if (len <= img_overl->clip_right - x) {
+ memblend_xx44(dst,clip_pixel,len, alphamask);
+ dst += len;
+ } else {
+ memblend_xx44(dst,clip_pixel,img_overl->clip_right - x,alphamask);
+ dst += img_overl->clip_right - x;
+ len -= img_overl->clip_right - x;
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
+ }
+ } else {
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
}
- if(rlelen & 1)
- *((uint16_t *)dst)++ = yuy2 & 0xffff;
} else {
- if( l ) {
- mem_blend32(dst, (uint8_t *)&yuy2, o, l);
- dst += 4*l;
- }
-
- if(rlelen & 1) {
- *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o);
- dst++;
- *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o);
- dst++;
- }
+ memblend_xx44(dst,norm_pixel,len, alphamask);
+ dst += len;
}
- } else {
- dst += rlelen*2;
}
-
- x += rlelen;
+ x += rle->len;
rle++;
if (rle >= rle_limit) break;
- }
+ }
if (rle >= rle_limit) break;
+ dst_y += dst_pitch;
+ }
+}
+
+static void alphablend_disable_exact_osd_alpha_blending_changed(void *user_data, xine_cfg_entry_t *entry)
+{
+ alphablend_t *extra_data = (alphablend_t *)user_data;
+
+ extra_data->disable_exact_blending = entry->num_value;
+}
- dst_y += dst_width*2;
+void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine)
+{
+ config_values_t *config = xine->config;
+
+ extra_data->buffer = 0;
+ extra_data->buffer_size = 0;
+
+ extra_data->disable_exact_blending =
+ config->register_bool(config, "video.output.disable_exact_alphablend", 0,
+ _("disable exact alpha blending of overlays"),
+ _("If you experience a performance impact when an On Screen Display or other "
+ "overlays like DVD subtitles are active, then you might want to enable this option.\n"
+ "The result is that alpha blending of overlays is less accurate than before, "
+ "but the CPU usage will be decreased as well."),
+ 10, alphablend_disable_exact_osd_alpha_blending_changed, extra_data);
+}
+
+void _x_alphablend_free(alphablend_t *extra_data)
+{
+ if (extra_data->buffer) {
+ free(extra_data->buffer);
+ extra_data->buffer = NULL;
}
+
+ extra_data->buffer_size = 0;
}
+
diff --git a/noncore/multimedia/opieplayer2/alphablend.h b/noncore/multimedia/opieplayer2/alphablend.h
index 7230f41..1edb5ba 100644
--- a/noncore/multimedia/opieplayer2/alphablend.h
+++ b/noncore/multimedia/opieplayer2/alphablend.h
@@ -6,52 +6,129 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The author may be reached as <dent@linuxvideo.org>
*
*------------------------------------------------------------
*
*/
#ifndef __ALPHABLEND_H__
#define __ALPHABLEND_H__
#include <xine/video_out.h>
+typedef struct {
+ void *buffer;
+ int buffer_size;
+
+ int disable_exact_blending;
+} alphablend_t;
+
+void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine);
+void _x_alphablend_free(alphablend_t *extra_data);
+
+/* _MSC_VER port changes */
+#undef ATTRIBUTE_PACKED
+#undef PRAGMA_PACK_BEGIN
+#undef PRAGMA_PACK_END
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) || defined(__ICC)
+#define ATTRIBUTE_PACKED __attribute__ ((packed))
+#define PRAGMA_PACK 0
+#endif
+
+#if !defined(ATTRIBUTE_PACKED)
+#define ATTRIBUTE_PACKED
+#define PRAGMA_PACK 1
+#endif
+
+#if PRAGMA_PACK
+#pragma pack(8)
+#endif
+
typedef struct { /* CLUT == Color LookUp Table */
uint8_t cb : 8;
uint8_t cr : 8;
uint8_t y : 8;
uint8_t foo : 8;
-} __attribute__ ((packed)) clut_t;
+} ATTRIBUTE_PACKED clut_t;
+
+
+#if PRAGMA_PACK
+#pragma pack()
+#endif
+
+#define XX44_PALETTE_SIZE 32
+
+typedef struct {
+ unsigned size;
+ unsigned max_used;
+ uint32_t cluts[XX44_PALETTE_SIZE];
+ /* cache palette entries for both colors and clip_colors */
+ int lookup_cache[OVL_PALETTE_SIZE*2];
+} xx44_palette_t;
+
void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
- int dst_width, int dst_height);
+ int dst_width, int dst_height,
+ alphablend_t *extra_data);
void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
- int dst_width, int dst_height);
+ int dst_width, int dst_height,
+ alphablend_t *extra_data);
void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
int img_width, int img_height,
- int dst_width, int dst_height);
+ int dst_width, int dst_height,
+ alphablend_t *extra_data);
void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
- int dst_width, int dst_height);
+ int dst_width, int dst_height, int dst_pitches[3],
+ alphablend_t *extra_data);
void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
- int dst_width, int dst_height);
+ int dst_width, int dst_height, int dst_pitch,
+ alphablend_t *extra_data);
+
+/*
+ * This function isn't too smart about blending. We want to avoid creating new
+ * colors in the palette as a result from two non-zero colors needed to be
+ * blended. Instead we choose the color with the highest alpha value to be
+ * visible. Some parts of the code taken from the "VeXP" project.
+ */
+
+void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
+ int dst_width, int dst_height, int dst_pitch,
+ alphablend_t *extra_data,
+ xx44_palette_t *palette,int ia44);
+
+/*
+ * Functions to handle the xine-specific palette.
+ */
+
+void clear_xx44_palette(xx44_palette_t *p);
+void init_xx44_palette(xx44_palette_t *p, unsigned num_entries);
+void dispose_xx44_palette(xx44_palette_t *p);
+
+/*
+ * Convert the xine-specific palette to something useful.
+ */
+
+void xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette,
+ unsigned first_xx44_entry, unsigned num_xx44_entries,
+ unsigned num_xvmc_components, char *xvmc_components);
-void crop_overlay (vo_overlay_t * overlay);
#endif
diff --git a/noncore/multimedia/opieplayer2/lib.cpp b/noncore/multimedia/opieplayer2/lib.cpp
index 4ae8490..84d28ce 100644
--- a/noncore/multimedia/opieplayer2/lib.cpp
+++ b/noncore/multimedia/opieplayer2/lib.cpp
@@ -28,64 +28,59 @@ _;:, .> :=|. This program is free software; you can
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "xinevideowidget.h"
#include "lib.h"
/* OPIE */
#include <opie2/odebug.h>
#include <qpe/global.h>
/* QT */
#include <qtextstream.h>
#include <qdir.h>
#include <qgfx_qws.h>
/* STD */
#include <assert.h>
#include <unistd.h>
typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
int width, int height,int bytes );
+typedef void (*vo_scale_cb) (void*, int, int, double,
+ int*, int*, int*, int*, double*, int*, int* );
+typedef void (*dest_size_cb) (void*, int, int, double, int*, int*, double*);
+
extern "C" {
- xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void * );
+ xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void *, vo_scale_cb, dest_size_cb );
int null_is_showing_video( const xine_vo_driver_t* self );
void null_set_show_video( const xine_vo_driver_t* self, int show );
- int null_is_fullscreen( const xine_vo_driver_t* self );
- void null_set_fullscreen( const xine_vo_driver_t* self, int screen );
- int null_is_scaling( const xine_vo_driver_t* self );
- void null_set_scaling( const xine_vo_driver_t* self, int scale );
- void null_set_gui_width( const xine_vo_driver_t* self, int width );
- void null_set_gui_height( const xine_vo_driver_t* self, int height );
void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb );
- void null_set_videoGamma( const xine_vo_driver_t* self , int value );
void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data );
-
- void null_preload_decoders( xine_stream_t *stream );
}
using namespace XINE;
Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
{
m_initialized = false;
m_duringInitialization = false;
m_video = false;
m_wid = widget;
printf("Lib");
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
// get the configuration
// not really OO, should be an extra class, later
if ( !QFile::exists(configPath) ) {
QFile f(configPath);
f.open(IO_WriteOnly);
QTextStream ts( &f );
ts << "misc.memcpy_method:glibc\n";
ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n";
ts << "codec.ffmpeg_pp_quality:3\n";
ts << "audio.num_buffers:50\n";
ts << "audio.size_buffers:4096\n";
@@ -106,90 +101,89 @@ Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
start();
}
void Lib::run()
{
odebug << "Lib::run() started" << oendl;
initialize();
m_initialized = true;
odebug << "Lib::run() finished" << oendl;
}
void Lib::initialize()
{
m_duringInitialization = true;
m_xine = xine_new( );
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
xine_config_load( m_xine, QFile::encodeName( configPath ) );
xine_init( m_xine );
// allocate oss for sound
// and fb for framebuffer
m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL );
- m_videoOutput = ::init_video_out_plugin( m_xine, NULL, xine_display_frame, this );
+ m_videoOutput = ::init_video_out_plugin( m_xine, NULL,
+ xine_display_frame, this,
+ xine_vo_scale_cb,
+ xine_dest_cb );
m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
if (m_wid != 0 )
setWidget( m_wid );
m_queue = xine_event_new_queue (m_stream);
xine_event_create_listener_thread (m_queue, xine_event_handler, this);
- ::null_preload_decoders( m_stream );
-
m_duringInitialization = false;
}
Lib::~Lib() {
assert( isRunning() == false );
assert( m_initialized );
// free( m_config );
xine_close( m_stream );
xine_event_dispose_queue( m_queue );
xine_dispose( m_stream );
xine_close_audio_driver(m_xine,m_audioOutput);
xine_close_video_driver(m_xine,m_videoOutput);
xine_exit( m_xine );
/* FIXME either free or delete but valgrind bitches against both */
//free( m_videoOutput );
//delete m_audioOutput;
}
void Lib::resize ( const QSize &s ) {
assert( m_initialized || m_duringInitialization );
- if ( s. width ( ) && s. height ( ) ) {
- ::null_set_gui_width( m_videoOutput, s. width() );
- ::null_set_gui_height( m_videoOutput, s. height() );
- }
+ if ( s. width ( ) && s. height ( ) )
+ m_videoSize = s;
}
int Lib::majorVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return major;
}
int Lib::minorVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return minor;
}
int Lib::subVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return sub;
}
int Lib::setfile(const QString& fileName)
{
QString str = fileName.stripWhiteSpace();
@@ -401,71 +395,97 @@ void Lib::handleXineEvent( int type, int data, const char* name ) {
emit stopped();
}else if ( type == XINE_EVENT_PROGRESS ) {
QString str = name == 0 ? QString::null : QString::fromUtf8( name );
Global::statusMessage( tr( "Progress: %1 %2" ).arg( name, data ) );;
}
}
void Lib::setShowVideo( bool video ) {
assert( m_initialized );
m_video = video;
::null_set_show_video( m_videoOutput, video );
}
bool Lib::isShowingVideo() const {
assert( m_initialized );
return ::null_is_showing_video( m_videoOutput );
}
void Lib::showVideoFullScreen( bool fullScreen ) {
assert( m_initialized );
- ::null_set_fullscreen( m_videoOutput, fullScreen );
+ #warning use xine
}
bool Lib::isVideoFullScreen() const {
assert( m_initialized );
- return ::null_is_fullscreen( m_videoOutput );
+ #warning use xine
+ return false;
}
void Lib::setScaling( bool scale ) {
assert( m_initialized );
- ::null_set_scaling( m_videoOutput, scale );
+ xine_set_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO,
+ scale ? XINE_VO_ASPECT_AUTO : XINE_VO_ASPECT_SQUARE );
}
void Lib::setGamma( int value ) {
assert( m_initialized );
-
- ::null_set_videoGamma( m_videoOutput, value );
+ xine_set_param( m_stream, XINE_PARAM_VO_BRIGHTNESS, value );
}
bool Lib::isScaling() const {
assert( m_initialized );
- return ::null_is_scaling( m_videoOutput );
+ int aratio = xine_get_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO );
+ return aratio == XINE_VO_ASPECT_AUTO;
}
void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) {
( (Lib*)user_data)->handleXineEvent( t );
}
void Lib::xine_display_frame( void* user_data, uint8_t *frame,
int width, int height, int bytes ) {
( (Lib*)user_data)->drawFrame( frame, width, height, bytes );
}
+void Lib::xine_vo_scale_cb( void *user_data, int video_with, int video_height,
+ double video_pixel_aspect,
+ int *dest_x, int *dest_y, int *dest_width,
+ int *dest_height, double *dest_pixel_aspect,
+ int *win_x, int *win_y ) {
+ QSize size = ((Lib*)user_data)->m_videoSize;
+ if (!size.isValid())
+ return;
+
+ *dest_x = 0;
+ *dest_y = 0;
+ *dest_width = size.width();
+ *dest_height = size.height();
+ *win_x = 0;
+ *win_y = 0;
+}
+
+void Lib::xine_dest_cb( void* user_data, int, int, double,
+ int *dest_width, int* dest_height, double* ) {
+ QSize size = ((Lib*)user_data)->m_videoSize;
+ if ( !size.isValid() )
+ return;
+
+ *dest_width = size.width();
+ *dest_height = size.height();
+}
+
void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) {
assert( m_initialized );
- if ( !m_video ) {
+ if ( !m_video )
return;
- }
-
-// assert( m_wid );
if (m_wid) m_wid-> setVideoFrame ( frame, width, height, bytes );
}
diff --git a/noncore/multimedia/opieplayer2/lib.h b/noncore/multimedia/opieplayer2/lib.h
index 2607193..a6ac033 100644
--- a/noncore/multimedia/opieplayer2/lib.h
+++ b/noncore/multimedia/opieplayer2/lib.h
@@ -166,50 +166,54 @@ namespace XINE {
* XINE_ERROR_DEMUXER_FAILED 3
*/
int error() const;
void ensureInitialized();
void setWidget( XineVideoWidget *widget );
QSize videoSize()const;
int audioBitrate()const;
int videoBitrate()const;
signals:
void stopped();
void initialized();
protected:
virtual void receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType );
virtual void run();
private:
- void initialize();
-
- int m_bytes_per_pixel;
- bool m_initialized:1;
- bool m_duringInitialization:1;
- bool m_video:1;
- XineVideoWidget *m_wid;
- xine_t *m_xine;
- xine_stream_t *m_stream;
- xine_cfg_entry_t *m_config;
- xine_vo_driver_t *m_videoOutput;
- xine_ao_driver_t* m_audioOutput;
- xine_event_queue_t *m_queue;
-
- void handleXineEvent( const xine_event_t* t );
- void handleXineEvent( int type, int data, const char* name );
- void drawFrame( uint8_t* frame, int width, int height, int bytes );
+ void initialize();
+
+ int m_bytes_per_pixel;
+ bool m_initialized:1;
+ bool m_duringInitialization:1;
+ bool m_video:1;
+ XineVideoWidget *m_wid;
+ QSize m_videoSize;
+ xine_t *m_xine;
+ xine_stream_t *m_stream;
+ xine_cfg_entry_t *m_config;
+ xine_vo_driver_t *m_videoOutput;
+ xine_ao_driver_t* m_audioOutput;
+ xine_event_queue_t *m_queue;
+
+ void handleXineEvent( const xine_event_t* t );
+ void handleXineEvent( int type, int data, const char* name );
+ void drawFrame( uint8_t* frame, int width, int height, int bytes );
// C -> C++ bridge for the event system
static void xine_event_handler( void* user_data, const xine_event_t* t);
static void xine_display_frame( void* user_data, uint8_t* frame ,
- int width, int height, int bytes );
+ int width, int height, int bytes );
+ static void xine_vo_scale_cb(void *, int, int, double,
+ int*,int*,int*,int*,double*,int*,int*);
+ static void xine_dest_cb(void*,int,int,double,int*,int*,double*);
};
};
#endif
diff --git a/noncore/multimedia/opieplayer2/mainTest.cpp b/noncore/multimedia/opieplayer2/mainTest.cpp
deleted file mode 100644
index e374c89..0000000
--- a/noncore/multimedia/opieplayer2/mainTest.cpp
+++ b/dev/null
@@ -1,16 +0,0 @@
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "lib.h"
-
-int main( int argc, char *argv[] ) {
- printf("FixME\n");
- //return 0;
- XINE::Lib lib;
- QString str = QString::fromLatin1( argv[1] );
- lib.play( str );
- for (;;) sleep( 60 );
- return 0;
-}
diff --git a/noncore/multimedia/opieplayer2/nullvideo.c b/noncore/multimedia/opieplayer2/nullvideo.c
index 6769a37..99fa329 100644
--- a/noncore/multimedia/opieplayer2/nullvideo.c
+++ b/noncore/multimedia/opieplayer2/nullvideo.c
@@ -1,272 +1,285 @@
/*
                This file is part of the Opie Project
              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
- Copyright (c) 2002 LJP <>
Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
Copyright (c) 2002-2003 Miguel Freitas of xine
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. This program 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; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <xine.h>
#include <xine/video_out.h>
#include <xine/xine_internal.h>
-//#include <xine/xineutils.h>
#include <xine/vo_scale.h>
#include <xine/buffer.h>
#include <pthread.h>
#include "alphablend.h"
#include "yuv2rgb.h"
#define printf(x,...)
/*
-#define LOG
-*/
+ * #define LOG
+ */
/* the caller for our event draw handler */
typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
- int width, int height,int bytes );
+ int width, int height,int bytes );
+typedef void (*vo_scale_cb) (void*, int, int, double,
+ int*, int*, int*, double*, int*, int* );
+typedef void (*dest_size_cb) (void*, int, int, double, int*, int*, double*);
+
typedef struct null_driver_s null_driver_t;
struct null_driver_s {
vo_driver_t vo_driver;
- uint32_t m_capabilities;
int m_show_video;
int m_video_fullscreen;
- int m_is_scaling;
int depth, bpp, bytes_per_pixel;
int yuv2rgb_mode;
int yuv2rgb_swap;
- int yuv2rgb_gamma;
+ int yuv2rgb_brightness;
uint8_t *yuv2rgb_cmap;
yuv2rgb_factory_t *yuv2rgb_factory;
vo_overlay_t *overlay;
- vo_scale_t sc;
-
- int gui_width;
- int gui_height;
- int gui_changed;
+ vo_scale_t sc;
- double display_ratio;
- void* caller;
+ /*
+ * DISPLAY to widget...
+ */
display_xine_frame_t frameDis;
+ void *userData;
+
+ xine_t *xine;
+ alphablend_t alphablend_extra_data;
};
typedef struct opie_frame_s opie_frame_t;
struct opie_frame_s {
vo_frame_t frame;
int format;
int flags;
vo_scale_t sc;
uint8_t *chunk[3];
uint8_t *data; /* rgb */
int bytes_per_line;
yuv2rgb_t *yuv2rgb;
uint8_t *rgb_dst;
int yuv_stride;
int stripe_height, stripe_inc;
-
+
null_driver_t *output;
};
static uint32_t null_get_capabilities( vo_driver_t *self ){
- null_driver_t* this = (null_driver_t*)self;
- return this->m_capabilities;
+ self = self;
+ return VO_CAP_YUY2 | VO_CAP_YV12;
}
static void null_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) {
opie_frame_t *frame = (opie_frame_t *) vo_img ;
vo_img->proc_called = 1;
- if (!frame->output->m_show_video) {
- /* printf("nullvideo: no video\n"); */
+ /*
+ * drop hard if we don't show the video
+ */
+ if (!frame->output->m_show_video)
+ return;
+
+ if( frame->frame.crop_left || frame->frame.crop_top ||
+ frame->frame.crop_right || frame->frame.crop_bottom )
+ {
+ /* we don't support crop, so don't even waste cpu cycles.
+ * cropping will be performed by video_out.c
+ */
return;
}
if (frame->format == XINE_IMGFMT_YV12) {
frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst,
src[0], src[1], src[2]);
} else {
frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst,
src[0]);
}
frame->rgb_dst += frame->stripe_inc;
}
static void null_frame_field (vo_frame_t *vo_img, int which_field) {
opie_frame_t *frame = (opie_frame_t *) vo_img ;
switch (which_field) {
case VO_TOP_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data;
+ frame->rgb_dst = frame->data;
frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTTOM_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ;
+ frame->rgb_dst = frame->data + frame->bytes_per_line ;
frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTH_FIELDS:
- frame->rgb_dst = (uint8_t *)frame->data;
+ frame->rgb_dst = frame->data;
break;
}
}
/* take care of the frame*/
static void null_frame_dispose( vo_frame_t* vo_img){
opie_frame_t* frame = (opie_frame_t*)vo_img;
if (frame->data)
free( frame->data );
free (frame);
}
/* end take care of frames*/
static vo_frame_t* null_alloc_frame( vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self;
opie_frame_t* frame;
#ifdef LOG
fprintf (stderr, "nullvideo: alloc_frame\n");
#endif
frame = (opie_frame_t*)xine_xmalloc ( sizeof(opie_frame_t) );
+ if(!frame)
+ return NULL;
memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
pthread_mutex_init (&frame->frame.mutex, NULL);
frame->output = this;
/* initialize the frame*/
frame->frame.driver = self;
frame->frame.proc_slice = null_frame_proc_slice;
+ frame->frame.proc_frame = NULL;
frame->frame.field = null_frame_field;
frame->frame.dispose = null_frame_dispose;
/*
* colorspace converter for this frame
*/
frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);
return (vo_frame_t*) frame;
}
-static void null_frame_compute_ideal_size( null_driver_t *this,
+static void null_frame_compute_ideal_size( null_driver_t *this,
opie_frame_t *frame ) {
this = this;
_x_vo_scale_compute_ideal_size(&frame->sc);
}
static void null_frame_compute_rgb_size( null_driver_t *this,
opie_frame_t *frame ){
this = this;
_x_vo_scale_compute_output_size(&frame->sc);
/* avoid problems in yuv2rgb */
if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4)
frame->sc.output_height = (frame->sc.delivered_height+15) >> 4;
if (frame->sc.output_width < 8)
frame->sc.output_width = 8;
/* yuv2rgb_mlib needs an even YUV2 width */
if (frame->sc.output_width & 1)
frame->sc.output_width++;
}
static void null_frame_reallocate( null_driver_t *this, opie_frame_t *frame,
uint32_t width, uint32_t height, int format){
/*
* (re-) allocate
*/
- if( frame->data ) {
- if( frame->chunk[0] ){
- free( frame->chunk[0] );
- frame->chunk[0] = NULL;
- }
- if( frame->chunk[1] ){
- free ( frame->chunk[1] );
- frame->chunk[1] = NULL;
- }
- if( frame->chunk[2] ){
- free ( frame->chunk[2] );
- frame->chunk[2] = NULL;
- }
- free ( frame->data );
+ if( frame->chunk[0] ){
+ free( frame->chunk[0] );
+ frame->chunk[0] = NULL;
+ }
+ if( frame->chunk[1] ){
+ free ( frame->chunk[1] );
+ frame->chunk[1] = NULL;
}
+ if( frame->chunk[2] ){
+ free ( frame->chunk[2] );
+ frame->chunk[2] = NULL;
+ }
+ if(frame->data)
+ free ( frame->data );
- frame->data = xine_xmalloc (frame->sc.output_width
+ frame->data = xine_xmalloc (frame->sc.output_width
* frame->sc.output_height
* this->bytes_per_pixel );
if( format == XINE_IMGFMT_YV12 ) {
frame->frame.pitches[0] = 8*((width + 7) / 8);
frame->frame.pitches[1] = 8*((width + 15) / 16);
frame->frame.pitches[2] = 8*((width + 15) / 16);
frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,(void **)&frame->chunk[0]);
frame->frame.base[1] = xine_xmalloc_aligned (16, frame->frame.pitches[1] * ((height+ 1)/2), (void **)&frame->chunk[1]);
frame->frame.base[2] = xine_xmalloc_aligned (16, frame->frame.pitches[2] * ((height+ 1)/2), (void **)&frame->chunk[2]);
}else{
frame->frame.pitches[0] = 8*((width + 3) / 4);
frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,
(void **)&frame->chunk[0]);
frame->chunk[1] = NULL;
frame->chunk[2] = NULL;
}
}
static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) {
switch (flags) {
@@ -280,135 +293,140 @@ static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) {
frame->sc.output_width,
frame->stripe_height,
frame->bytes_per_line*2);
frame->yuv_stride = frame->bytes_per_line*2;
break;
case VO_BOTH_FIELDS:
frame->yuv2rgb->configure (frame->yuv2rgb,
frame->sc.delivered_width,
16,
frame->frame.pitches[0],
frame->frame.pitches[1],
frame->sc.output_width,
frame->stripe_height,
frame->bytes_per_line);
frame->yuv_stride = frame->bytes_per_line;
break;
}
#ifdef LOG
fprintf (stderr, "nullvideo: colorspace converter configured.\n");
#endif
}
static void null_update_frame_format( vo_driver_t* self, vo_frame_t* img,
uint32_t width, uint32_t height,
- double ratio_code, int format,
+ double ratio_code, int format,
int flags ){
null_driver_t* this = (null_driver_t*) self;
opie_frame_t* frame = (opie_frame_t*)img;
#ifdef LOG
fprintf (stderr, "nullvideo: update_frame_format\n");
#endif
+ int gui_width = 0;
+ int gui_height = 0;
+ double gui_pixel_aspect = 0.0;
+
flags &= VO_BOTH_FIELDS;
- /* find out if we need to adapt this frame */
+ frame->sc.dest_size_cb(frame->sc.user_data, width, height,
+ frame->sc.video_pixel_aspect,
+ &gui_width, &gui_height, &gui_pixel_aspect);
+ /* find out if we need to adapt this frame */
if ((width != frame->sc.delivered_width)
|| (height != frame->sc.delivered_height)
|| (ratio_code != frame->sc.delivered_ratio)
|| (flags != frame->flags)
|| (format != frame->format)
|| (this->sc.user_ratio != frame->sc.user_ratio)
- || (this->gui_width != frame->sc.gui_width)
- || (this->gui_height != frame->sc.gui_height)) {
-
+ || (gui_width != frame->sc.gui_width)
+ || (gui_height != frame->sc.gui_height)) {
frame->sc.delivered_width = width;
frame->sc.delivered_height = height;
frame->sc.delivered_ratio = ratio_code;
frame->flags = flags;
frame->format = format;
frame->sc.user_ratio = this->sc.user_ratio;
- frame->sc.gui_width = this->gui_width;
- frame->sc.gui_height = this->gui_height;
- frame->sc.gui_pixel_aspect = 1.0;
+ frame->sc.gui_width = gui_width;
+ frame->sc.gui_height = gui_height;
null_frame_compute_ideal_size(this, frame);
null_frame_compute_rgb_size(this, frame);
null_frame_reallocate(this, frame, width, height, format);
#ifdef LOG
fprintf (stderr, "nullvideo: gui %dx%d delivered %dx%d output %dx%d\n",
frame->sc.gui_width, frame->sc.gui_height,
frame->sc.delivered_width, frame->sc.delivered_height,
frame->sc.output_width, frame->sc.output_height);
#endif
frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height;
frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel;
/*
* set up colorspace converter
*/
null_setup_colorspace_converter(frame, flags);
}
/*
* reset dest pointers
*/
if (frame->data) {
switch (flags) {
case VO_TOP_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data;
+ frame->rgb_dst = frame->data;
frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTTOM_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ;
+ frame->rgb_dst = frame->data + frame->bytes_per_line ;
frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTH_FIELDS:
- frame->rgb_dst = (uint8_t *)frame->data;
+ frame->rgb_dst = frame->data;
frame->stripe_inc = frame->stripe_height * frame->bytes_per_line;
break;
}
}
}
static void null_display_frame( vo_driver_t* self, vo_frame_t *frame_gen ){
null_driver_t* this = (null_driver_t*) self;
opie_frame_t* frame = (opie_frame_t*)frame_gen;
display_xine_frame_t display = this->frameDis;
if (!this->m_show_video)
return;
if( display != NULL ) {
- (*display)(this->caller, frame->data,
+ (*display)(this->userData, frame->data,
frame->sc.output_width, frame->sc.output_height,
frame->bytes_per_line );
}
frame->frame.free(&frame->frame);
}
/* blending related */
static void null_overlay_clut_yuv2rgb (null_driver_t *this,
vo_overlay_t *overlay,
opie_frame_t *frame) {
this = this;
int i;
clut_t* clut = (clut_t*) overlay->color;
if (!overlay->rgb_clut) {
for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
*((uint32_t *)&clut[i]) =
frame->yuv2rgb->
yuv2rgb_single_pixel_fun (frame->yuv2rgb,
clut[i].y, clut[i].cb,
clut[i].cr);
@@ -421,315 +439,257 @@ static void null_overlay_clut_yuv2rgb (null_driver_t *this,
*((uint32_t *)&clut[i]) =
frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb,
clut[i].y, clut[i].cb, clut[i].cr);
}
overlay->clip_rgb_clut++;
}
}
static void null_overlay_blend ( vo_driver_t *this_gen, vo_frame_t *frame_gen,
vo_overlay_t *overlay) {
null_driver_t *this = (null_driver_t *) this_gen;
opie_frame_t *frame = (opie_frame_t *) frame_gen;
if(!this->m_show_video || frame->sc.output_width == 0
|| frame->sc.output_height== 0)
return;
/* Alpha Blend here */
if (overlay->rle) {
if( !overlay->rgb_clut || !overlay->clip_rgb_clut)
null_overlay_clut_yuv2rgb(this,overlay,frame);
switch(this->bpp) {
case 16:
- blend_rgb16((uint8_t *)frame->data,
+ blend_rgb16(frame->data,
overlay,
frame->sc.output_width,
frame->sc.output_height,
frame->sc.delivered_width,
- frame->sc.delivered_height);
+ frame->sc.delivered_height,
+ &this->alphablend_extra_data);
break;
case 24:
- blend_rgb24((uint8_t *)frame->data,
+ blend_rgb24(frame->data,
overlay,
frame->sc.output_width,
frame->sc.output_height,
frame->sc.delivered_width,
- frame->sc.delivered_height);
+ frame->sc.delivered_height,
+ &this->alphablend_extra_data);
break;
case 32:
- blend_rgb32((uint8_t *)frame->data,
+ blend_rgb32(frame->data,
overlay,
frame->sc.output_width,
frame->sc.output_height,
frame->sc.delivered_width,
- frame->sc.delivered_height);
+ frame->sc.delivered_height,
+ &this->alphablend_extra_data);
break;
default:
/* It should never get here */
break;
}
}
}
static int null_get_property( vo_driver_t* self, int property ){
-#if 0
null_driver_t *this = (null_driver_t *)self;
switch(property)
{
case VO_PROP_ASPECT_RATIO:
return this->sc.user_ratio;
case VO_PROP_BRIGHTNESS:
return this->yuv2rgb_brightness;
case VO_PROP_WINDOW_WIDTH:
return this->sc.gui_width;
case VO_PROP_WINDOW_HEIGHT:
return this->sc.gui_height;
default:
break;
}
-#else
- property = property;
- self = self;
-#endif
return 0;
}
static int null_set_property( vo_driver_t* self, int property,
int value ){
-#if 0
null_driver_t *this = (null_driver_t *)self;
switch(property)
{
case VO_PROP_ASPECT_RATIO:
if(value>=XINE_VO_ASPECT_NUM_RATIOS)
value = XINE_VO_ASPECT_AUTO;
this->sc.user_ratio = value;
break;
case VO_PROP_BRIGHTNESS:
this->yuv2rgb_brightness = value;
this->yuv2rgb_factory->
set_csc_levels(this->yuv2rgb_factory, value, 128, 128);
break;
default:
break;
}
-#else
- self = self;
- property = property;
-#endif
return value;
}
static void null_get_property_min_max( vo_driver_t* self,
int property, int *min,
int *max ){
- self = self;
- property = property;
-
- *max = 0;
- *min = 0;
+ if(property == VO_PROP_BRIGHTNESS) {
+ *min = -100;
+ *max = +100;
+ }else {
+ *min = 0;
+ *max = 0;
+ }
}
static int null_gui_data_exchange( vo_driver_t* self,
int data_type,
void *data ){
- self = self;
- data_type = data_type;
- data = data;
-
return 0;
}
static void null_dispose ( vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self;
+ _x_alphablend_free(&this->alphablend_extra_data);
free ( this );
}
static int null_redraw_needed( vo_driver_t* self ){
- self = self;
-
- return 0;
+ null_driver_t *this = (null_driver_t*)self;
+ return _x_vo_scale_redraw_needed(&this->sc);
}
xine_video_port_t* init_video_out_plugin( xine_t *xine,
- void* video,
- display_xine_frame_t frameDisplayFunc,
- void *userData ){
- video = video;
-
-
+ void* video,
+ display_xine_frame_t frameDisplayFunc,
+ void *userData, vo_scale_cb frame_cb,
+ dest_size_cb dest_cb) {
null_driver_t *vo;
- vo = (null_driver_t*)malloc( sizeof(null_driver_t ) );
-
- /* memset? */
- memset(vo,0, sizeof(null_driver_t ) );
+ vo = (null_driver_t*)xine_xmalloc(sizeof(null_driver_t ));
+ vo->xine = xine;
+ _x_alphablend_init(&vo->alphablend_extra_data, xine);
_x_vo_scale_init (&vo->sc, 0, 0, xine->config);
+ vo->sc.gui_width = 18;
+ vo->sc.gui_height = 6;
+ vo->sc.user_ratio = XINE_VO_ASPECT_AUTO;
+ vo->sc.user_data = userData;
+ vo->sc.frame_output_cb = frame_cb;
+ vo->sc.dest_size_cb = dest_cb;
- vo->sc.gui_pixel_aspect = 1.0;
vo->m_show_video = 0; // false
- vo->m_video_fullscreen = 0;
- vo->m_is_scaling = 0;
- vo->display_ratio = 1.0;
- vo->gui_width = 16;
- vo->gui_height = 8;
- vo->frameDis = NULL;
/* install callback handlers*/
- vo->vo_driver.get_capabilities = null_get_capabilities;
- vo->vo_driver.alloc_frame = null_alloc_frame;
- vo->vo_driver.update_frame_format = null_update_frame_format;
- vo->vo_driver.display_frame = null_display_frame;
- vo->vo_driver.overlay_blend = null_overlay_blend;
- vo->vo_driver.get_property = null_get_property;
- vo->vo_driver.set_property = null_set_property;
- vo->vo_driver.get_property_min_max = null_get_property_min_max;
- vo->vo_driver.gui_data_exchange = null_gui_data_exchange;
- vo->vo_driver.dispose = null_dispose;
- vo->vo_driver.redraw_needed = null_redraw_needed;
-
+ vo->vo_driver.get_capabilities = null_get_capabilities;
+ vo->vo_driver.alloc_frame = null_alloc_frame;
+ vo->vo_driver.update_frame_format = null_update_frame_format;
+ vo->vo_driver.display_frame = null_display_frame;
+ vo->vo_driver.overlay_begin = 0;
+ vo->vo_driver.overlay_blend = null_overlay_blend;
+ vo->vo_driver.overlay_end = 0;
+ vo->vo_driver.get_property = null_get_property;
+ vo->vo_driver.set_property = null_set_property;
+ vo->vo_driver.get_property_min_max= null_get_property_min_max;
+ vo->vo_driver.gui_data_exchange = null_gui_data_exchange;
+ vo->vo_driver.dispose = null_dispose;
+ vo->vo_driver.redraw_needed = null_redraw_needed;
/* capabilities */
- vo->m_capabilities = VO_CAP_YUY2 | VO_CAP_YV12;
- vo->yuv2rgb_factory = yuv2rgb_factory_init (MODE_16_RGB, vo->yuv2rgb_swap,
+ vo->yuv2rgb_mode = MODE_16_RGB;
+ vo->yuv2rgb_brightness = 0;
+ vo->yuv2rgb_factory = yuv2rgb_factory_init (vo->yuv2rgb_mode,
+ vo->yuv2rgb_swap,
vo->yuv2rgb_cmap);
+ vo->yuv2rgb_factory->set_csc_levels(vo->yuv2rgb_factory,
+ vo->yuv2rgb_brightness,
+ 128,128);
- vo->caller = userData;
+ vo->userData = userData;
vo->frameDis = frameDisplayFunc;
return _x_vo_new_port(xine, &vo->vo_driver, 0);
}
/* this is special for this device */
/**
* We know that we will be controled by the XINE LIB++
*/
/**
*
*/
int null_is_showing_video( xine_vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self->driver;
return this->m_show_video;
}
void null_set_show_video( xine_vo_driver_t* self, int show ) {
((null_driver_t*)self->driver)->m_show_video = show;
}
-int null_is_fullscreen( xine_vo_driver_t* self ){
- return ((null_driver_t*)self->driver)->m_video_fullscreen;
-}
-void null_set_fullscreen( xine_vo_driver_t* self, int screen ){
- ((null_driver_t*)self->driver)->m_video_fullscreen = screen;
-}
-int null_is_scaling( xine_vo_driver_t* self ){
- return ((null_driver_t*)self->driver)->m_is_scaling;
-}
-
-void null_set_videoGamma( xine_vo_driver_t* self , int value ) {
- ((null_driver_t*) self->driver) ->yuv2rgb_gamma = value;
- ((null_driver_t*) self->driver) ->yuv2rgb_factory->set_gamma( ((null_driver_t*) self->driver) ->yuv2rgb_factory, value );
-}
-
-void null_set_scaling( xine_vo_driver_t* self, int scale ) {
- ((null_driver_t*)self->driver)->m_is_scaling = scale;
-}
-
-void null_set_gui_width( xine_vo_driver_t* self, int width ) {
- ((null_driver_t*)self->driver)->gui_width = width;
-}
-void null_set_gui_height( xine_vo_driver_t* self, int height ) {
- ((null_driver_t*)self->driver)->gui_height = height;
-}
void null_set_mode( xine_vo_driver_t* self, int depth, int rgb ) {
null_driver_t* this = (null_driver_t*)self->driver;
this->bytes_per_pixel = (depth + 7 ) / 8;
this->bpp = this->bytes_per_pixel * 8;
this->depth = depth;
-
+
switch ( this->depth ) {
case 32:
if( rgb == 0 )
this->yuv2rgb_mode = MODE_32_RGB;
else
this->yuv2rgb_mode = MODE_32_BGR;
case 24:
if( this->bpp == 32 ) {
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_32_RGB;
} else {
this->yuv2rgb_mode = MODE_32_BGR;
}
}else{
if( rgb == 0 )
this->yuv2rgb_mode = MODE_24_RGB;
else
this->yuv2rgb_mode = MODE_24_BGR;
};
break;
case 16:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_16_RGB;
} else {
this->yuv2rgb_mode = MODE_16_BGR;
}
break;
case 15:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_15_RGB;
} else {
this->yuv2rgb_mode = MODE_15_BGR;
}
break;
case 8:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_8_RGB;
} else {
this->yuv2rgb_mode = MODE_8_BGR;
}
break;
};
- //free(this->yuv2rgb_factory );
- // this->yuv2rgb_factory = yuv2rgb_factory_init (this->yuv2rgb_mode, this->yuv2rgb_swap,
- // this->yuv2rgb_cmap);
};
-void null_display_handler( xine_vo_driver_t* self, display_xine_frame_t t,
- void* user_data ) {
+void null_display_handler( xine_vo_driver_t* self, display_xine_frame_t t,
+ void* user_data ) {
null_driver_t* this = (null_driver_t*) self->driver;
- this->caller = user_data;
+ this->userData = user_data;
this->frameDis = t;
}
-void null_preload_decoders( xine_stream_t *stream )
-{
- static const uint32_t preloadedAudioDecoders[] = { BUF_AUDIO_MPEG, BUF_AUDIO_VORBIS };
- static const uint8_t preloadedAudioDecoderCount = sizeof( preloadedAudioDecoders ) / sizeof( preloadedAudioDecoders[ 0 ] );
- static const uint32_t preloadedVideoDecoders[] = { BUF_VIDEO_MPEG, BUF_VIDEO_MPEG4, BUF_VIDEO_DIVX5 };
- static const uint8_t preloadedVideoDecoderCount = sizeof( preloadedVideoDecoders ) / sizeof( preloadedVideoDecoders[ 0 ] );
-
- uint8_t i;
-#if 0
-
- for ( i = 0; i < preloadedAudioDecoderCount; ++i ) {
- audio_decoder_t *decoder = get_audio_decoder( stream, ( preloadedAudioDecoders[ i ] >> 16 ) & 0xff );
- decoder = decoder;
-/* free_audio_decoder( stream, decoder ); */
- }
-
- for ( i = 0; i < preloadedVideoDecoderCount; ++i ) {
- video_decoder_t *decoder = get_video_decoder( stream, ( preloadedVideoDecoders[ i ] >> 16 ) & 0xff );
- decoder = decoder;
-/* free_video_decoder( stream, decoder ); */
- }
-#endif
-}
diff --git a/noncore/multimedia/opieplayer2/yuv2rgb.c b/noncore/multimedia/opieplayer2/yuv2rgb.c
index 8e34052..487ed20 100644
--- a/noncore/multimedia/opieplayer2/yuv2rgb.c
+++ b/noncore/multimedia/opieplayer2/yuv2rgb.c
@@ -1,169 +1,240 @@
/*
* yuv2rgb.c
*
- * This file is part of xine, a unix video player.
+ * Copyright (C) 2003-2004 the xine project
+ * This file is part of xine, a free video player.
*
* based on work from mpeg2dec:
* Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
*
* This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
*
* mpeg2dec is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* mpeg2dec 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "yuv2rgb.h"
-#include <xine/xineutils.h>
+#define LOG_MODULE "yuv2rgb"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include <xine/xineutils.h>
static int prof_scale_line = -1;
static scale_line_func_t find_scale_line_func(int step);
const int32_t Inverse_Table_6_9[8][4] = {
{117504, 138453, 13954, 34903}, /* no sequence_display_extension */
{117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
{104597, 132201, 25675, 53279}, /* unspecified */
{104597, 132201, 25675, 53279}, /* reserved */
{104448, 132798, 24759, 53109}, /* FCC */
{104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
{104597, 132201, 25675, 53279}, /* SMPTE 170M */
{117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
};
-static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk) {
-
+static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk)
+{
char *pMem;
pMem = xine_xmalloc (size+alignment);
*chunk = pMem;
- while ((int) pMem % alignment)
+ while ((uintptr_t) pMem % alignment)
pMem++;
return pMem;
}
+static int yuv2rgb_next_slice (yuv2rgb_t *this, uint8_t **dest)
+{
+ int y0, y1;
+
+ if (dest == NULL) {
+ this->slice_offset = 0;
+ this->slice_height = 16;
+ return 0;
+ }
+ if (this->slice_height == this->source_height) {
+ return this->dest_height;
+ }
+
+ y0 = (this->slice_offset * this->dest_height) / this->source_height;
+ y1 = ((this->slice_offset + this->slice_height) * this->dest_height) / this->source_height;
+ *dest += (this->rgb_stride * y0);
+
+ if ((this->slice_offset + this->slice_height) >= this->source_height) {
+ this->slice_offset = 0;
+ return (this->dest_height - y0);
+ } else {
+ this->slice_offset += this->slice_height;
+ return (y1 - y0);
+ }
+}
+
+static void yuv2rgb_dispose (yuv2rgb_t *this)
+{
+ free (this->y_chunk);
+ free (this->u_chunk);
+ free (this->v_chunk);
+#ifdef HAVE_MLIB
+ free (this->mlib_chunk);
+#endif
+ free (this);
+}
+
static int yuv2rgb_configure (yuv2rgb_t *this,
int source_width, int source_height,
int y_stride, int uv_stride,
int dest_width, int dest_height,
int rgb_stride) {
- /*
+/*
printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height,
dest_width, dest_height);
- */
+*/
if (prof_scale_line == -1)
prof_scale_line = xine_profiler_allocate_slot("xshm scale line");
this->source_width = source_width;
this->source_height = source_height;
this->y_stride = y_stride;
this->uv_stride = uv_stride;
this->dest_width = dest_width;
this->dest_height = dest_height;
this->rgb_stride = rgb_stride;
-
+ this->slice_height = source_height;
+ this->slice_offset = 0;
+
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;
}
-
+#ifdef HAVE_MLIB
+ if (this->mlib_chunk) {
+ free (this->mlib_chunk);
+ this->mlib_buffer = this->mlib_chunk = NULL;
+ }
+ if (this->mlib_resize_chunk) {
+ free (this->mlib_resize_chunk);
+ this->mlib_resize_buffer = this->mlib_resize_chunk = NULL;
+ }
+#endif
+
this->step_dx = source_width * 32768 / dest_width;
this->step_dy = source_height * 32768 / dest_height;
-
+/*
+ printf("yuv2rgb config: src_ht=%i, dst_ht=%i\n",source_height, dest_height);
+ printf("yuv2rgb config: step_dy=%i %f\n",this->step_dy, (float)this->step_dy / 32768.0);
+*/
this->scale_line = find_scale_line_func(this->step_dx);
if ((source_width == dest_width) && (source_height == dest_height)) {
this->do_scale = 0;
/*
* space for two y-lines (for yuv2rgb_mlib)
* u,v subsampled 2:1
*/
this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk);
if (!this->y_buffer)
return 0;
this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk);
if (!this->u_buffer)
return 0;
this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk);
if (!this->v_buffer)
return 0;
} else {
this->do_scale = 1;
/*
* space for two y-lines (for yuv2rgb_mlib)
* u,v subsampled 2:1
*/
this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk);
if (!this->y_buffer)
return 0;
this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk);
if (!this->u_buffer)
return 0;
this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk);
if (!this->v_buffer)
return 0;
+
+#if HAVE_MLIB
+ /* Only need these if we are resizing and in mlib code */
+ this->mlib_buffer = my_malloc_aligned (16, source_width*source_height*4, &this->mlib_chunk);
+ if (!this->mlib_buffer)
+ return 0;
+ /* Only need this one if we are 24 bit */
+ if((rgb_stride / dest_width) == 3) {
+ this->mlib_resize_buffer = my_malloc_aligned (16, dest_width*dest_height*4, &this->mlib_resize_chunk);
+ if (!this->mlib_resize_buffer)
+ return 0;
+ }
+#endif
}
return 1;
}
-
static void scale_line_gen (uint8_t *source, uint8_t *dest,
int width, int step) {
/*
* scales a yuv source row to a dest row, with interpolation
* (good quality, but slow)
*/
int p1;
int p2;
int dx;
xine_profiler_start_count(prof_scale_line);
p1 = *source++;
p2 = *source++;
dx = 0;
/*
* the following code has been optimized by Scott Smith <ssmith@akamai.com>:
*
* ok now I have a meaningful optimization for yuv2rgb.c:scale_line_gen.
* it removes the loop from within the while() loop by separating it out
* into 3 cases: where you are enlarging the line (<32768), where you are
* between 50% and 100% of the original line (<=65536), and where you are
@@ -1183,58 +1254,71 @@ static void scale_line_1_1 (uint8_t *source, uint8_t *dest,
xine_fast_memcpy(dest, source, width);
xine_profiler_stop_count(prof_scale_line);
}
static scale_line_func_t find_scale_line_func(int step) {
static struct {
int src_step;
int dest_step;
scale_line_func_t func;
char *desc;
} scale_line[] = {
{ 15, 16, scale_line_15_16, "dvd 4:3(pal)" },
{ 45, 64, scale_line_45_64, "dvd 16:9(pal), fullscreen(1024x768)" },
{ 9, 16, scale_line_9_16, "dvd fullscreen(1280x1024)" },
{ 45, 53, scale_line_45_53, "dvd 16:9(ntsc)" },
{ 11, 12, scale_line_11_12, "vcd 4:3(pal)" },
{ 11, 24, scale_line_11_24, "vcd 4:3(pal) 2*zoom" },
{ 5, 8, scale_line_5_8, "svcd 4:3(pal)" },
{ 3, 4, scale_line_3_4, "svcd 4:3(ntsc)" },
{ 1, 2, scale_line_1_2, "2*zoom" },
{ 1, 1, scale_line_1_1, "non-scaled" },
};
int i;
+#ifdef LOG
+ /* to filter out multiple messages about the scale_line variant we're using */
+ static int reported_for_step;
+#endif
for (i = 0; i < sizeof(scale_line)/sizeof(scale_line[0]); i++) {
if (step == scale_line[i].src_step*32768/scale_line[i].dest_step) {
- //printf("yuv2rgb: using %s optimized scale_line\n", scale_line[i].desc);
+#ifdef LOG
+ if (step != reported_for_step)
+ printf("yuv2rgb: using %s optimized scale_line\n", scale_line[i].desc);
+ reported_for_step = step;
+#endif
return scale_line[i].func;
}
}
- //printf("yuv2rgb: using generic scale_line with interpolation\n");
- return scale_line_gen;
+#ifdef LOG
+ if (step != reported_for_step)
+ printf("yuv2rgb: using generic scale_line with interpolation\n");
+ reported_for_step = step;
+#endif
+
+ return scale_line_gen;
}
static void scale_line_2 (uint8_t *source, uint8_t *dest,
int width, int step) {
int p1;
int p2;
int dx;
p1 = *source; source+=2;
p2 = *source; source+=2;
dx = 0;
while (width) {
*dest = (p1 * (32768 - dx) + p2 * dx) / 32768;
dx += step;
while (dx > 32768) {
dx -= 32768;
p1 = p2;
p2 = *source;
source+=2;
}
@@ -1251,49 +1335,49 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest,
int dx;
p1 = *source; source+=4;
p2 = *source; source+=4;
dx = 0;
while (width) {
*dest = (p1 * (32768 - dx) + p2 * dx) / 32768;
dx += step;
while (dx > 32768) {
dx -= 32768;
p1 = p2;
p2 = *source;
source+=4;
}
dest ++;
width --;
}
}
-#define RGB(i) \
+#define X_RGB(i) \
U = pu[i]; \
V = pv[i]; \
r = this->table_rV[V]; \
g = (void *) (((uint8_t *)this->table_gU[U]) + this->table_gV[V]); \
b = this->table_bU[U];
#define DST1(i) \
Y = py_1[2*i]; \
dst_1[2*i] = r[Y] + g[Y] + b[Y]; \
Y = py_1[2*i+1]; \
dst_1[2*i+1] = r[Y] + g[Y] + b[Y];
#define DST2(i) \
Y = py_2[2*i]; \
dst_2[2*i] = r[Y] + g[Y] + b[Y]; \
Y = py_2[2*i+1]; \
dst_2[2*i+1] = r[Y] + g[Y] + b[Y];
#define DST1RGB(i) \
Y = py_1[2*i]; \
dst_1[6*i] = r[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = b[Y]; \
Y = py_1[2*i+1]; \
dst_1[6*i+3] = r[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = b[Y];
@@ -1327,1033 +1411,1054 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest,
Y = py_2[2*i+1]; \
dst_2[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]];
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;
int width, height, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
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);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while( dy>=32768);
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 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);
+ X_RGB(0);
DST1(0);
DST2(0);
- RGB(1);
+ X_RGB(1);
DST2(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
DST2(2);
- RGB(3);
+ X_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 * _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, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
dst_1 = _dst;
py_1 = this->y_buffer;
pu = this->u_buffer;
pv = this->v_buffer;
width = this->dest_width >> 3;
do {
- RGB(0);
+ X_RGB(0);
DST1RGB(0);
- RGB(1);
+ X_RGB(1);
DST1RGB(1);
- RGB(2);
+ X_RGB(2);
DST1RGB(2);
- RGB(3);
+ X_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 (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while (dy>=32768);
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 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);
+ X_RGB(0);
DST1RGB(0);
DST2RGB(0);
- RGB(1);
+ X_RGB(1);
DST2RGB(1);
DST1RGB(1);
- RGB(2);
+ X_RGB(2);
DST1RGB(2);
DST2RGB(2);
- RGB(3);
+ X_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 * _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, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
dst_1 = _dst;
py_1 = this->y_buffer;
pu = this->u_buffer;
pv = this->v_buffer;
width = this->dest_width >> 3;
do {
- RGB(0);
+ X_RGB(0);
DST1BGR(0);
- RGB(1);
+ X_RGB(1);
DST1BGR(1);
- RGB(2);
+ X_RGB(2);
DST1BGR(2);
- RGB(3);
+ X_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 (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while( dy>=32768 );
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 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);
+ X_RGB(0);
DST1BGR(0);
DST2BGR(0);
- RGB(1);
+ X_RGB(1);
DST2BGR(1);
DST1BGR(1);
- RGB(2);
+ X_RGB(2);
DST1BGR(2);
DST2BGR(2);
- RGB(3);
+ X_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 * _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;
int width, height, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
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);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while( dy>=32768);
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 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);
+ X_RGB(0);
DST1(0);
DST2(0);
- RGB(1);
+ X_RGB(1);
DST2(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
DST2(2);
- RGB(3);
+ X_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 exactly the same code as yuv2rgb_c_32 except for the types of */
/* r, g, b, dst_1, dst_2 */
static void yuv2rgb_c_8 (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, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
dst_1 = (uint8_t*)_dst;
py_1 = this->y_buffer;
pu = this->u_buffer;
pv = this->v_buffer;
width = this->dest_width >> 3;
do {
- RGB(0);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while( dy>=32768 );
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 1;
do {
dst_1 = (uint8_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);
+ X_RGB(0);
DST1(0);
DST2(0);
- RGB(1);
+ X_RGB(1);
DST2(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
DST2(2);
- RGB(3);
+ X_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);
}
}
/* now for something different: 256 grayscale mode */
static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst,
uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
{
int height, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
dy = 0;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (;;) {
scale_line (_py, _dst, this->dest_width, this->step_dx);
dy += this->step_dy;
_dst += this->rgb_stride;
while (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
_py += this->y_stride*(dy>>15);
dy &= 32767;
/* dy -= 32768;
_py += this->y_stride;
*/
}
} else {
- for (height = this->source_height; --height >= 0; ) {
+ for (height = this->next_slice (this, &_dst); --height >= 0; ) {
xine_fast_memcpy(_dst, _py, this->dest_width);
_dst += this->rgb_stride;
_py += this->y_stride;
}
}
}
/* now for something different: 256 color mode */
static void yuv2rgb_c_palette (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;
uint8_t * dst_1, * dst_2;
int width, height, dst_height;
int dy;
if (this->do_scale) {
scale_line_func_t scale_line = this->scale_line;
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;
- dst_height = this->dest_height;
+ dst_height = this->next_slice (this, &_dst);
for (height = 0;; ) {
dst_1 = _dst;
py_1 = this->y_buffer;
pu = this->u_buffer;
pv = this->v_buffer;
width = this->dest_width >> 3;
do {
- RGB(0);
+ X_RGB(0);
DST1CMAP(0);
- RGB(1);
+ X_RGB(1);
DST1CMAP(1);
- RGB(2);
+ X_RGB(2);
DST1CMAP(2);
- RGB(3);
+ X_RGB(3);
DST1CMAP(3);
pu += 4;
pv += 4;
py_1 += 8;
dst_1 += 8;
} while (--width);
dy += this->step_dy;
_dst += this->rgb_stride;
while (--dst_height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (dst_height <= 0)
break;
do {
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);
}
height++;
} while( dy>=32768 );
}
} else {
- height = this->source_height >> 1;
+ height = this->next_slice (this, &_dst) >> 1;
do {
dst_1 = _dst;
dst_2 = _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);
+ X_RGB(0);
DST1CMAP(0);
DST2CMAP(0);
- RGB(1);
+ X_RGB(1);
DST2CMAP(1);
DST1CMAP(1);
- RGB(2);
+ X_RGB(2);
DST1CMAP(2);
DST2CMAP(2);
- RGB(3);
+ X_RGB(3);
DST2CMAP(3);
DST1CMAP(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)
{
if (dividend > 0)
return (dividend + (divisor>>1)) / divisor;
else
return -((-dividend + (divisor>>1)) / divisor);
}
-static void yuv2rgb_setup_tables (yuv2rgb_factory_t *this, int mode, int swapped)
+static void yuv2rgb_set_csc_levels (yuv2rgb_factory_t *this,
+ int brightness, int contrast, int saturation)
{
int i;
uint8_t table_Y[1024];
uint32_t * table_32 = 0;
uint16_t * table_16 = 0;
uint8_t * table_8 = 0;
int entry_size = 0;
void *table_r = 0, *table_g = 0, *table_b = 0;
int shift_r = 0, shift_g = 0, shift_b = 0;
int crv = Inverse_Table_6_9[this->matrix_coefficients][0];
int cbu = Inverse_Table_6_9[this->matrix_coefficients][1];
int cgu = -Inverse_Table_6_9[this->matrix_coefficients][2];
int cgv = -Inverse_Table_6_9[this->matrix_coefficients][3];
+ int mode = this->mode;
+ int swapped = this->swapped;
+
for (i = 0; i < 1024; i++) {
int j;
- j = (76309 * (i - 384 - 16) + 32768) >> 16;
+ j = (76309 * (i - 384 - 16 + brightness) + 32768) >> 16;
j = (j < 0) ? 0 : ((j > 255) ? 255 : j);
table_Y[i] = j;
}
switch (mode) {
case MODE_32_RGB:
case MODE_32_BGR:
- table_32 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t));
+ if (this->table_base == NULL) {
+ this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t));
+ }
+ table_32 = this->table_base;
entry_size = sizeof (uint32_t);
table_r = table_32 + 197;
table_b = table_32 + 197 + 685;
table_g = table_32 + 197 + 2*682;
if (swapped) {
switch (mode) {
case MODE_32_RGB: shift_r = 8; shift_g = 16; shift_b = 24; break;
case MODE_32_BGR: shift_r = 24; shift_g = 16; shift_b = 8; break;
}
} else {
switch (mode) {
case MODE_32_RGB: shift_r = 16; shift_g = 8; shift_b = 0; break;
case MODE_32_BGR: shift_r = 0; shift_g = 8; shift_b = 16; break;
}
}
for (i = -197; i < 256+197; i++)
((uint32_t *) table_r)[i] = table_Y[i+384] << shift_r;
for (i = -132; i < 256+132; i++)
((uint32_t *) table_g)[i] = table_Y[i+384] << shift_g;
for (i = -232; i < 256+232; i++)
((uint32_t *) table_b)[i] = table_Y[i+384] << shift_b;
break;
case MODE_24_RGB:
case MODE_24_BGR:
- table_8 = malloc ((256 + 2*232) * sizeof (uint8_t));
+ if (this->table_base == NULL) {
+ this->table_base = malloc ((256 + 2*232) * sizeof (uint8_t));
+ }
+ table_8 = this->table_base;
entry_size = sizeof (uint8_t);
table_r = table_g = table_b = table_8 + 232;
for (i = -232; i < 256+232; i++)
((uint8_t * )table_b)[i] = table_Y[i+384];
break;
case MODE_15_BGR:
case MODE_16_BGR:
case MODE_15_RGB:
case MODE_16_RGB:
- table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
+ if (this->table_base == NULL) {
+ this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
+ }
+ table_16 = this->table_base;
entry_size = sizeof (uint16_t);
table_r = table_16 + 197;
table_b = table_16 + 197 + 685;
table_g = table_16 + 197 + 2*682;
if (swapped) {
switch (mode) {
case MODE_15_BGR: shift_r = 8; shift_g = 5; shift_b = 2; break;
case MODE_16_BGR: shift_r = 8; shift_g = 5; shift_b = 3; break;
case MODE_15_RGB: shift_r = 2; shift_g = 5; shift_b = 8; break;
case MODE_16_RGB: shift_r = 3; shift_g = 5; shift_b = 8; break;
}
} else {
switch (mode) {
case MODE_15_BGR: shift_r = 0; shift_g = 5; shift_b = 10; break;
case MODE_16_BGR: shift_r = 0; shift_g = 5; shift_b = 11; break;
case MODE_15_RGB: shift_r = 10; shift_g = 5; shift_b = 0; break;
case MODE_16_RGB: shift_r = 11; shift_g = 5; shift_b = 0; break;
}
}
for (i = -197; i < 256+197; i++)
((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << shift_r;
for (i = -132; i < 256+132; i++) {
int j = table_Y[i+384] >> (((mode==MODE_16_RGB) || (mode==MODE_16_BGR)) ? 2 : 3);
if (swapped)
((uint16_t *)table_g)[i] = (j&7) << 13 | (j>>3);
else
((uint16_t *)table_g)[i] = j << 5;
}
for (i = -232; i < 256+232; i++)
((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << shift_b;
break;
case MODE_8_RGB:
case MODE_8_BGR:
- table_8 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t));
+ if (this->table_base == NULL) {
+ this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t));
+ }
+ table_8 = this->table_base;
entry_size = sizeof (uint8_t);
table_r = table_8 + 197;
table_b = table_8 + 197 + 685;
table_g = table_8 + 197 + 2*682;
switch (mode) {
case MODE_8_RGB: shift_r = 5; shift_g = 2; shift_b = 0; break;
case MODE_8_BGR: shift_r = 0; shift_g = 3; shift_b = 6; break;
}
for (i = -197; i < 256+197; i++)
((uint8_t *) table_r)[i] = (table_Y[i+384] >> 5) << shift_r;
for (i = -132; i < 256+132; i++)
((uint8_t *) table_g)[i] = (table_Y[i+384] >> 5) << shift_g;
for (i = -232; i < 256+232; i++)
((uint8_t *) table_b)[i] = (table_Y[i+384] >> 6) << shift_b;
break;
case MODE_8_GRAY:
return;
case MODE_PALETTE:
- table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
+ if (this->table_base == NULL) {
+ this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
+ }
+ table_16 = this->table_base;
entry_size = sizeof (uint16_t);
table_r = table_16 + 197;
table_b = table_16 + 197 + 685;
table_g = table_16 + 197 + 2*682;
shift_r = 10;
shift_g = 5;
shift_b = 0;
for (i = -197; i < 256+197; i++)
((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << 10;
for (i = -132; i < 256+132; i++)
((uint16_t *)table_g)[i] = (table_Y[i+384] >> 3) << 5;
for (i = -232; i < 256+232; i++)
((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << 0;
break;
default:
- fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode);
- abort();
+ lprintf ("mode %d not supported by yuv2rgb\n", mode);
+ _x_abort();
}
for (i = 0; i < 256; i++) {
this->table_rV[i] = (((uint8_t *) table_r) +
entry_size * div_round (crv * (i-128), 76309));
this->table_gU[i] = (((uint8_t *) table_g) +
entry_size * div_round (cgu * (i-128), 76309));
this->table_gV[i] = entry_size * div_round (cgv * (i-128), 76309);
this->table_bU[i] = (((uint8_t *)table_b) +
entry_size * div_round (cbu * (i-128), 76309));
}
- this->gamma = 0;
- this->entry_size = entry_size;
+
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+ mmx_yuv2rgb_set_csc_levels (this, brightness, contrast, saturation);
+#endif
}
static uint32_t yuv2rgb_single_pixel_32 (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v)
{
uint32_t * r, * g, * b;
r = this->table_rV[v];
g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]);
b = this->table_bU[u];
return r[y] + g[y] + b[y];
}
static uint32_t yuv2rgb_single_pixel_24_rgb (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v)
{
uint8_t * r, * g, * b;
r = this->table_rV[v];
g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]);
b = this->table_bU[u];
return (uint32_t) r[y] +
((uint32_t) g[y] << 8) +
((uint32_t) b[y] << 16);
@@ -2427,741 +2532,746 @@ static void yuv2rgb_c_init (yuv2rgb_factory_t *this)
: yuv2rgb_c_24_bgr;
break;
case MODE_15_BGR:
case MODE_16_BGR:
case MODE_15_RGB:
case MODE_16_RGB:
this->yuv2rgb_fun = yuv2rgb_c_16;
break;
case MODE_8_RGB:
case MODE_8_BGR:
this->yuv2rgb_fun = yuv2rgb_c_8;
break;
case MODE_8_GRAY:
this->yuv2rgb_fun = yuv2rgb_c_gray;
break;
case MODE_PALETTE:
this->yuv2rgb_fun = yuv2rgb_c_palette;
break;
default:
- printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode);
- abort();
+ lprintf ("mode %d not supported by yuv2rgb\n", this->mode);
+ _x_abort();
}
}
static void yuv2rgb_single_pixel_init (yuv2rgb_factory_t *this) {
switch (this->mode) {
case MODE_32_RGB:
case MODE_32_BGR:
this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_32;
break;
case MODE_24_RGB:
case MODE_24_BGR:
this->yuv2rgb_single_pixel_fun =
(this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped)
? yuv2rgb_single_pixel_24_rgb
: yuv2rgb_single_pixel_24_bgr;
break;
case MODE_15_BGR:
case MODE_16_BGR:
case MODE_15_RGB:
case MODE_16_RGB:
this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_16;
break;
case MODE_8_RGB:
case MODE_8_BGR:
this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_8;
break;
case MODE_8_GRAY:
this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_gray;
break;
case MODE_PALETTE:
this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_palette;
break;
default:
- printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode);
- abort();
+ lprintf ("mode %d not supported by yuv2rgb\n", this->mode);
+ _x_abort();
}
}
/*
* yuy2 stuff
*/
static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint32_t * r, * g, * b;
uint32_t * dst_1;
int width, height;
int dy;
/* FIXME: implement unscaled version */
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
/*
dy -= 32768;
_p += this->y_stride*2;
*/
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint8_t * r, * g, * b;
uint8_t * dst_1;
int width, height;
int dy;
/* FIXME: implement unscaled version */
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1RGB(0);
- RGB(1);
+ X_RGB(1);
DST1RGB(1);
- RGB(2);
+ X_RGB(2);
DST1RGB(2);
- RGB(3);
+ X_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 (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
/*
dy -= 32768;
_p += this->y_stride*2;
*/
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint8_t * r, * g, * b;
uint8_t * dst_1;
int width, height;
int dy;
/* FIXME: implement unscaled version */
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1BGR(0);
- RGB(1);
+ X_RGB(1);
DST1BGR(1);
- RGB(2);
+ X_RGB(2);
DST1BGR(2);
- RGB(3);
+ X_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 (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint16_t * r, * g, * b;
uint16_t * dst_1;
int width, height;
int dy;
/* FIXME: implement unscaled version */
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint8_t * r, * g, * b;
uint8_t * dst_1;
int width, height;
int dy;
/* FIXME: implement unscaled version */
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1(0);
- RGB(1);
+ X_RGB(1);
DST1(1);
- RGB(2);
+ X_RGB(2);
DST1(2);
- RGB(3);
+ X_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 (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int width, height;
int dy;
uint8_t * dst;
uint8_t * y;
if (this->do_scale) {
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
for (;;) {
scale_line_2 (_p, _dst, this->dest_width, this->step_dx);
dy += this->step_dy;
_dst += this->rgb_stride;
while (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
}
} else {
- for (height = this->source_height; --height >= 0; ) {
+ for (height = this->next_slice (this, &_dst); --height >= 0; ) {
dst = _dst;
y = _p;
for (width = this->source_width; --width >= 0; ) {
*dst++ = *y;
y += 2;
}
_dst += this->rgb_stride;
- _p += this->y_stride*2;
+ _p += this->y_stride;
}
}
}
static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
{
int U, V, Y;
uint8_t * py_1, * pu, * pv;
uint16_t * r, * g, * b;
uint8_t * dst_1;
int width, height;
int dy;
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
dy = 0;
- height = this->dest_height;
+ height = this->next_slice (this, &_dst);
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);
+ X_RGB(0);
DST1CMAP(0);
- RGB(1);
+ X_RGB(1);
DST1CMAP(1);
- RGB(2);
+ X_RGB(2);
DST1CMAP(2);
- RGB(3);
+ X_RGB(3);
DST1CMAP(3);
pu += 4;
pv += 4;
py_1 += 8;
dst_1 += 8;
} while (--width);
dy += this->step_dy;
_dst += this->rgb_stride;
while (--height > 0 && dy < 32768) {
xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
dy += this->step_dy;
_dst += this->rgb_stride;
}
if (height <= 0)
break;
- _p += this->y_stride*2*(dy>>15);
+ _p += this->y_stride*(dy>>15);
dy &= 32767;
scale_line_4 (_p+1, this->u_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_4 (_p+3, this->v_buffer,
this->dest_width >> 1, this->step_dx);
scale_line_2 (_p, this->y_buffer,
this->dest_width, this->step_dx);
}
}
static void yuy22rgb_c_init (yuv2rgb_factory_t *this)
{
switch (this->mode) {
case MODE_32_RGB:
case MODE_32_BGR:
this->yuy22rgb_fun = yuy22rgb_c_32;
break;
case MODE_24_RGB:
case MODE_24_BGR:
this->yuy22rgb_fun =
(this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped)
? yuy22rgb_c_24_rgb
: yuy22rgb_c_24_bgr;
break;
case MODE_15_BGR:
case MODE_16_BGR:
case MODE_15_RGB:
case MODE_16_RGB:
this->yuy22rgb_fun = yuy22rgb_c_16;
break;
case MODE_8_RGB:
case MODE_8_BGR:
this->yuy22rgb_fun = yuy22rgb_c_8;
break;
case MODE_8_GRAY:
this->yuy22rgb_fun = yuy22rgb_c_gray;
break;
case MODE_PALETTE:
this->yuy22rgb_fun = yuy22rgb_c_palette;
break;
default:
- printf ("yuv2rgb: mode %d not supported for yuy2\n", this->mode);
+ lprintf ("mode %d not supported for yuy2\n", this->mode);
}
}
-yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) {
+static yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) {
yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t));
-
+
+ this->swapped = factory->swapped;
this->cmap = factory->cmap;
this->y_chunk = this->y_buffer = NULL;
this->u_chunk = this->u_buffer = NULL;
this->v_chunk = this->v_buffer = NULL;
+#ifdef HAVE_MLIB
+ this->mlib_chunk = this->mlib_buffer = NULL;
+ this->mlib_resize_chunk = this->mlib_resize_buffer = NULL;
+ this->mlib_filter_type = MLIB_BILINEAR;
+#endif
+
this->table_rV = factory->table_rV;
this->table_gU = factory->table_gU;
this->table_gV = factory->table_gV;
this->table_bU = factory->table_bU;
+ this->table_mmx = factory->table_mmx;
this->yuv2rgb_fun = factory->yuv2rgb_fun;
this->yuy22rgb_fun = factory->yuy22rgb_fun;
this->yuv2rgb_single_pixel_fun = factory->yuv2rgb_single_pixel_fun;
this->configure = yuv2rgb_configure;
+ this->next_slice = yuv2rgb_next_slice;
+ this->dispose = yuv2rgb_dispose;
return this;
}
/*
* factory functions
*/
-void yuv2rgb_set_gamma (yuv2rgb_factory_t *this, int gamma) {
-
- int i;
-
- for (i = 0; i < 256; i++) {
- (uint8_t *)this->table_rV[i] += this->entry_size*(gamma - this->gamma);
- (uint8_t *)this->table_gU[i] += this->entry_size*(gamma - this->gamma);
- (uint8_t *)this->table_bU[i] += this->entry_size*(gamma - this->gamma);
- }
-#ifdef ARCH_X86
- mmx_yuv2rgb_set_gamma(gamma);
-#endif
- this->gamma = gamma;
-}
-int yuv2rgb_get_gamma (yuv2rgb_factory_t *this) {
+static void yuv2rgb_factory_dispose (yuv2rgb_factory_t *this) {
- return this->gamma;
+ free (this->table_base);
+ free (this->table_mmx_base);
+ free (this);
}
yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped,
uint8_t *cmap) {
yuv2rgb_factory_t *this;
-
-#ifdef ARCH_X86
uint32_t mm = xine_mm_accel();
-#endif
this = malloc (sizeof (yuv2rgb_factory_t));
this->mode = mode;
this->swapped = swapped;
this->cmap = cmap;
this->create_converter = yuv2rgb_create_converter;
- this->set_gamma = yuv2rgb_set_gamma;
- this->get_gamma = yuv2rgb_get_gamma;
+ this->set_csc_levels = yuv2rgb_set_csc_levels;
+ this->dispose = yuv2rgb_factory_dispose;
this->matrix_coefficients = 6;
+ this->table_base = NULL;
+ this->table_mmx = NULL;
+ this->table_mmx_base = NULL;
- yuv2rgb_setup_tables (this, mode, swapped);
+ yuv2rgb_set_csc_levels (this, 0, 128, 128);
/*
* auto-probe for the best yuv2rgb function
*/
this->yuv2rgb_fun = NULL;
-#ifdef ARCH_X86
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMXEXT)) {
yuv2rgb_init_mmxext (this);
+#ifdef LOG
if (this->yuv2rgb_fun != NULL)
printf ("yuv2rgb: using MMXEXT for colorspace transform\n");
+#endif
}
if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMX)) {
yuv2rgb_init_mmx (this);
+#ifdef LOG
if (this->yuv2rgb_fun != NULL)
printf ("yuv2rgb: using MMX for colorspace transform\n");
+#endif
+ }
+#ifdef __arm__
+ if (this->yuv2rgb_fun == NULL) {
+ yuv2rgb_init_arm ( this );
+
+ if(this->yuv2rgb_fun != NULL)
+ printf("yuv2rgb: using arm4l assembler for colorspace transform\n" );
}
#endif
+
+#endif
#if HAVE_MLIB
- if (this->yuv2rgb_fun == NULL) {
+ if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_MLIB)) {
yuv2rgb_init_mlib (this);
+#ifdef LOG
if (this->yuv2rgb_fun != NULL)
printf ("yuv2rgb: using medialib for colorspace transform\n");
- }
#endif
-#ifdef __arm__
- if (this->yuv2rgb_fun == NULL) {
- yuv2rgb_init_arm ( this );
-
- if(this->yuv2rgb_fun != NULL)
- printf("yuv2rgb: using arm4l assembler for colorspace transform\n" );
}
#endif
if (this->yuv2rgb_fun == NULL) {
- printf ("yuv2rgb: no accelerated colorspace conversion found\n");
+ lprintf ("no accelerated colorspace conversion found\n");
+
yuv2rgb_c_init (this);
}
/*
* auto-probe for the best yuy22rgb function
*/
/* FIXME: implement mmx/mlib functions */
yuy22rgb_c_init (this);
/*
* set up single pixel function
*/
yuv2rgb_single_pixel_init (this);
return this;
}
-
diff --git a/noncore/multimedia/opieplayer2/yuv2rgb.h b/noncore/multimedia/opieplayer2/yuv2rgb.h
index e453243..1833889 100644
--- a/noncore/multimedia/opieplayer2/yuv2rgb.h
+++ b/noncore/multimedia/opieplayer2/yuv2rgb.h
@@ -1,152 +1,172 @@
#ifndef HAVE_YUV2RGB_H
#define HAVE_YUV2RGB_h
+#ifdef HAVE_MLIB
+#include <mlib_video.h>
+#endif
+
#include <inttypes.h>
typedef struct yuv2rgb_s yuv2rgb_t;
typedef struct yuv2rgb_factory_s yuv2rgb_factory_t;
/*
* function types for functions which can be replaced
* by hardware-accelerated versions
*/
/* internal function use to scale yuv data */
typedef void (*scale_line_func_t) (uint8_t *source, uint8_t *dest, int width, int step);
typedef void (*yuv2rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) ;
typedef void (*yuy22rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * p);
typedef uint32_t (*yuv2rgb_single_pixel_fun_t) (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v);
-
/*
* modes supported - feel free to implement yours
*/
#define MODE_8_RGB 1
#define MODE_8_BGR 2
#define MODE_15_RGB 3
#define MODE_15_BGR 4
#define MODE_16_RGB 5
#define MODE_16_BGR 6
#define MODE_24_RGB 7
#define MODE_24_BGR 8
#define MODE_32_RGB 9
#define MODE_32_BGR 10
#define MODE_8_GRAY 11
#define MODE_PALETTE 12
struct yuv2rgb_s {
-
/*
* configure converter for scaling factors
*/
int (*configure) (yuv2rgb_t *this,
int source_width, int source_height,
int y_stride, int uv_stride,
int dest_width, int dest_height,
int rgb_stride);
/*
+ * start a new field or frame if dest is NULL
+ */
+ int (*next_slice) (yuv2rgb_t *this, uint8_t **dest);
+
+ /*
+ * free resources
+ */
+ void (*dispose) (yuv2rgb_t *this);
+
+ /*
* this is the function to call for the yuv2rgb and scaling process
*/
yuv2rgb_fun_t yuv2rgb_fun;
/*
* this is the function to call for the yuy2->rgb and scaling process
*/
yuy22rgb_fun_t yuy22rgb_fun;
/*
* this is the function to call for the yuv2rgb for a single pixel
* (used for converting clut colors)
*/
yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun;
/* private stuff below */
int source_width, source_height;
int y_stride, uv_stride;
int dest_width, dest_height;
int rgb_stride;
+ int slice_height, slice_offset;
int step_dx, step_dy;
- int do_scale;
+ int do_scale, swapped;
uint8_t *y_buffer;
uint8_t *u_buffer;
uint8_t *v_buffer;
void *y_chunk;
void *u_chunk;
void *v_chunk;
+#ifdef HAVE_MLIB
+ uint8_t *mlib_buffer;
+ uint8_t *mlib_resize_buffer;
+ void *mlib_chunk;
+ void *mlib_resize_chunk;
+ mlib_filter mlib_filter_type;
+#endif
+
void **table_rV;
void **table_gU;
int *table_gV;
void **table_bU;
+ void *table_mmx;
uint8_t *cmap;
- scale_line_func_t scale_line;
-
+ scale_line_func_t scale_line;
} ;
/*
* convenience class to easily create a lot of converters
*/
struct yuv2rgb_factory_s {
-
yuv2rgb_t* (*create_converter) (yuv2rgb_factory_t *this);
- /*
- * adjust gamma (-100 to 100 looks fine)
+ /*
+ * set color space conversion levels
* for all converters produced by this factory
*/
- void (*set_gamma) (yuv2rgb_factory_t *this, int gamma);
+ void (*set_csc_levels) (yuv2rgb_factory_t *this,
+ int brightness, int contrast, int saturation);
/*
- * get gamma value
+ * free resources
*/
- int (*get_gamma) (yuv2rgb_factory_t *this);
+ void (*dispose) (yuv2rgb_factory_t *this);
/* private data */
int mode;
int swapped;
uint8_t *cmap;
- int gamma;
- int entry_size;
-
uint32_t matrix_coefficients;
+ void *table_base;
void *table_rV[256];
void *table_gU[256];
int table_gV[256];
void *table_bU[256];
+ void *table_mmx_base;
+ void *table_mmx;
/* preselected functions for mode/swap/hardware */
yuv2rgb_fun_t yuv2rgb_fun;
yuy22rgb_fun_t yuy22rgb_fun;
yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun;
-
};
yuv2rgb_factory_t *yuv2rgb_factory_init (int mode, int swapped, uint8_t *colormap);
-
+
/*
* internal stuff below this line
*/
-void mmx_yuv2rgb_set_gamma(int gamma);
+void mmx_yuv2rgb_set_csc_levels(yuv2rgb_factory_t *this,
+ int brightness, int contrast, int saturation);
void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this);
void yuv2rgb_init_mmx (yuv2rgb_factory_t *this);
void yuv2rgb_init_mlib (yuv2rgb_factory_t *this);
-void yuv2rgb_init_arm (yuv2rgb_factory_t *this);
#endif