summaryrefslogtreecommitdiff
Unidiff
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 @@
1//TOAST_SPU will define ALL spu entries - no matter the tranparency
2//#define TOAST_SPU
3/* #define PRIV_CLUT */
4/* Currently only blend_yuv(..) works */
5/* 1/*
6 * 2 *
7 * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 3 * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001
8 * 4 *
9 * Copyright (C) 2000 Thomas Mirlacher 5 * Copyright (C) 2000 Thomas Mirlacher
6 * 2002-2004 the xine project
10 * 7 *
11 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. 11 * (at your option) any later version.
15 * 12 *
16 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details. 16 * GNU General Public License for more details.
20 * 17 *
21 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * 21 *
25 * The author may be reached as <dent@linuxvideo.org> 22 * The author may be reached as <dent@linuxvideo.org>
26 * 23 *
27 *------------------------------------------------------------ 24 *------------------------------------------------------------
28 * 25 *
29 */ 26 */
30 27
31/* 28/*
32#define LOG_BLEND_YUV 29#define LOG_BLEND_YUV
30#define LOG_BLEND_RGB16
33*/ 31*/
34 32
35#include <string.h> 33#include <string.h>
36#include <stdlib.h> 34#include <stdlib.h>
37#include <stdio.h> 35#include <stdio.h>
38#include <inttypes.h>
39 36
40#include <xine.h>
41#include <xine/xine_internal.h> 37#include <xine/xine_internal.h>
42#include <xine/video_out.h> 38#include <xine/video_out.h>
43#include "alphablend.h" 39#include "alphablend.h"
40#include "bswap.h"
44 41
45 42
46#define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) 43#define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask)
47 44
48#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) 45#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf)
49 46
50static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) { 47static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) {
51 uint16_t *limit = mem + len; 48 uint16_t *limit = mem + len;
52 while (mem < limit) { 49 while (mem < limit) {
53 *mem = 50 *mem =
54 BLEND_COLOR(*mem, clr, 0xf800, o) | 51 BLEND_COLOR(*mem, clr, 0xf800, o) |
55 BLEND_COLOR(*mem, clr, 0x07e0, o) | 52 BLEND_COLOR(*mem, clr, 0x07e0, o) |
56 BLEND_COLOR(*mem, clr, 0x001f, o); 53 BLEND_COLOR(*mem, clr, 0x001f, o);
57 mem++; 54 mem++;
58 } 55 }
59} 56}
60 57
61static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, 58static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
62 uint8_t o, int len) { 59 uint8_t o, int len) {
63 uint8_t *limit = mem + len*3; 60 uint8_t *limit = mem + len*3;
64 while (mem < limit) { 61 while (mem < limit) {
65 *mem = BLEND_BYTE(*mem, r, o); 62 *mem = BLEND_BYTE(*mem, r, o);
66 mem++; 63 mem++;
67 *mem = BLEND_BYTE(*mem, g, o); 64 *mem = BLEND_BYTE(*mem, g, o);
68 mem++; 65 mem++;
69 *mem = BLEND_BYTE(*mem, b, o); 66 *mem = BLEND_BYTE(*mem, b, o);
70 mem++; 67 mem++;
71 } 68 }
72} 69}
73 70
74static void mem_blend24_32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b,
75 uint8_t o, int len) {
76 uint8_t *limit = mem + len*4;
77 while (mem < limit) {
78 *mem = BLEND_BYTE(*mem, r, o);
79 mem++;
80 *mem = BLEND_BYTE(*mem, g, o);
81 mem++;
82 *mem = BLEND_BYTE(*mem, b, o);
83 mem += 2;
84 }
85}
86
87static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) { 71static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
88 uint8_t *limit = mem + len*4; 72 uint8_t *limit = mem + len*4;
89 while (mem < limit) { 73 while (mem < limit) {
90 *mem = BLEND_BYTE(*mem, src[0], o); 74 *mem = BLEND_BYTE(*mem, src[0], o);
91 mem++; 75 mem++;
92 *mem = BLEND_BYTE(*mem, src[1], o); 76 *mem = BLEND_BYTE(*mem, src[1], o);
93 mem++; 77 mem++;
94 *mem = BLEND_BYTE(*mem, src[2], o); 78 *mem = BLEND_BYTE(*mem, src[2], o);
95 mem++; 79 mem++;
96 *mem = BLEND_BYTE(*mem, src[3], o); 80 *mem = BLEND_BYTE(*mem, src[3], o);
97 mem++; 81 mem++;
98 } 82 }
99} 83}
100 84
101
102/* 85/*
103 * Some macros for fixed point arithmetic. 86 * Some macros for fixed point arithmetic.
104 * 87 *
105 * The blend_rgb* routines perform rle image scaling using 88 * The blend_rgb* routines perform rle image scaling using
106 * scale factors that are expressed as integers scaled with 89 * scale factors that are expressed as integers scaled with
107 * a factor of 2**16. 90 * a factor of 2**16.
108 * 91 *
109 * INT_TO_SCALED()/SCALED_TO_INT() converts from integer 92 * INT_TO_SCALED()/SCALED_TO_INT() converts from integer
110 * to scaled fixed point and back. 93 * to scaled fixed point and back.
111 */ 94 */
112 #define SCALE_SHIFT 16 95 #define SCALE_SHIFT 16
113 #define SCALE_FACTOR (1<<SCALE_SHIFT) 96 #define SCALE_FACTOR (1<<SCALE_SHIFT)
114 #defineINT_TO_SCALED(i) ((i) << SCALE_SHIFT) 97 #defineINT_TO_SCALED(i) ((i) << SCALE_SHIFT)
115 #defineSCALED_TO_INT(sc) ((sc) >> SCALE_SHIFT) 98 #defineSCALED_TO_INT(sc) ((sc) >> SCALE_SHIFT)
116 99
117 100
118static rle_elem_t * 101static rle_elem_t *
119rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w) 102rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w)
120{ 103{
121 int x; 104 int x;
122 105
123 for (x = 0; x < w && rle < rle_limit; ) { 106 for (x = 0; x < w && rle < rle_limit; ) {
124 x += rle->len; 107 x += rle->len;
125 rle++; 108 rle++;
126 } 109 }
127 return rle; 110 return rle;
128} 111}
129 112
130
131void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, 113void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
132 int img_width, int img_height, 114 int img_width, int img_height,
133 int dst_width, int dst_height) 115 int dst_width, int dst_height,
116 alphablend_t *extra_data)
134{ 117{
135 uint8_t *trans; 118 uint8_t *trans;
136 clut_t* clut = (clut_t*) img_overl->clip_color; 119 clut_t *clut;
137 120
138 int src_width = img_overl->width; 121 int src_width = img_overl->width;
139 int src_height = img_overl->height; 122 int src_height = img_overl->height;
140 rle_elem_t *rle = img_overl->rle; 123 rle_elem_t *rle = img_overl->rle;
124 rle_elem_t *rle_start = img_overl->rle;
141 rle_elem_t *rle_limit = rle + img_overl->num_rle; 125 rle_elem_t *rle_limit = rle + img_overl->num_rle;
142 int x, y, x1_scaled, x2_scaled; 126 int x, y, x1_scaled, x2_scaled;
143 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ 127 int dy, dy_step, x_scale; /* scaled 2**SCALE_SHIFT */
144 int clip_right; 128 int clip_right;
145 uint16_t *img_pix; 129 uint16_t *img_pix;
130 int rlelen;
131 int rle_this_bite;
132 int rle_remainder;
133 int zone_state=0;
134 uint8_t clr_next,clr;
135 uint16_t o;
136 double img_offset;
137 int stripe_height;
138/*
139 * Let zone_state keep state.
140 * 0 = Starting.
141 * 1 = Above button.
142 * 2 = Left of button.
143 * 3 = Inside of button.
144 * 4 = Right of button.
145 * 5 = Below button.
146 * 6 = Finished.
147 *
148 * Each time round the loop, update the state.
149 * We can do this easily and cheaply(fewer IF statements per cycle) as we are testing rle end position anyway.
150 * Possible optimization is to ensure that rle never overlaps from outside to inside a button.
151 * Possible optimization is to pre-scale the RLE overlay, so that no scaling is needed here.
152 */
146 153
147 dy_step = INT_TO_SCALED(dst_height) / img_height; 154#ifdef LOG_BLEND_RGB16
148 x_scale = INT_TO_SCALED(img_width) / dst_width; 155 printf("blend_rgb16: img_height=%i, dst_height=%i\n", img_height, dst_height);
156 printf("blend_rgb16: img_width=%i, dst_width=%i\n", img_width, dst_width);
157 if (img_width & 1) { printf("blend_rgb16s: odd\n");}
158 else { printf("blend_rgb16s: even\n");}
149 159
150 img_pix = (uint16_t *) img 160#endif
161/* stripe_height is used in yuv2rgb scaling, so use the same scale factor here for overlays. */
162 stripe_height = 16 * img_height / dst_height;
163/* dy_step = INT_TO_SCALED(dst_height) / img_height; */
164 dy_step = INT_TO_SCALED(16) / stripe_height;
165 x_scale = INT_TO_SCALED(img_width) / dst_width;
166#ifdef LOG_BLEND_RGB16
167 printf("blend_rgb16: dy_step=%i, x_scale=%i\n", dy_step, x_scale);
168#endif
169 if (img_width & 1) img_width++;
170 img_offset = ( ( (img_overl->y * img_height) / dst_height) * img_width)
171 + ( (img_overl->x * img_width) / dst_width);
172#ifdef LOG_BLEND_RGB16
173 printf("blend_rgb16: x=%i, y=%i, w=%i, h=%i, img_offset=%lf\n", img_overl->x, img_overl->y,
174 img_overl->width,
175 img_overl->height,
176 img_offset);
177#endif
178 img_pix = (uint16_t *) img + (int)img_offset;
179/*
151 + (img_overl->y * img_height / dst_height) * img_width 180 + (img_overl->y * img_height / dst_height) * img_width
152 + (img_overl->x * img_width / dst_width); 181 + (img_overl->x * img_width / dst_width);
153 182*/
154 trans = img_overl->clip_trans;
155 183
156 /* avoid wraping overlay if drawing to small image */ 184 /* avoid wraping overlay if drawing to small image */
157 if( (img_overl->x + img_overl->clip_right) < dst_width ) 185 if( (img_overl->x + img_overl->clip_right) < dst_width )
158 clip_right = img_overl->clip_right; 186 clip_right = img_overl->clip_right;
159 else 187 else
160 clip_right = dst_width - 1 - img_overl->x; 188 clip_right = dst_width - img_overl->x;
161 189
162 /* avoid buffer overflow */ 190 /* avoid buffer overflow */
163 if( (src_height + img_overl->y) >= dst_height ) 191 if( (src_height + img_overl->y) >= dst_height )
164 src_height = dst_height - 1 - img_overl->y; 192 src_height = dst_height - img_overl->y;
165 193
166 for (y = dy = 0; y < src_height && rle < rle_limit;) { 194 rlelen = rle_remainder = rle_this_bite = 0;
167 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 195 rle_remainder = rlelen = rle->len;
168 rle_elem_t *rle_start = rle; 196 clr_next = rle->color;
197 rle++;
198 y = dy = 0;
199 x = x1_scaled = x2_scaled = 0;
169 200
170 for (x = x1_scaled = 0; x < src_width;) { 201#ifdef LOG_BLEND_RGB16
171 uint8_t clr; 202 printf("blend_rgb16 started\n");
172 uint16_t o; 203#endif
173 int rlelen; 204
205 while (zone_state != 6) {
206 clr = clr_next;
207 switch (zone_state) {
208 case 0: /* Starting */
209 /* FIXME: Get libspudec to set clip_top to -1 if no button */
210 if (img_overl->clip_top < 0) {
211#ifdef LOG_BLEND_RGB16
212 printf("blend_rgb16: No button clip area\n");
213#endif
174 214
175 clr = rle->color; 215 zone_state = 7;
216 break;
217 }
218#ifdef LOG_BLEND_RGB16
219 printf("blend_rgb16: Button clip area found. (%d,%d) .. (%d,%d)\n",
220 img_overl->clip_left,
221 img_overl->clip_top,
222 img_overl->clip_right,
223 img_overl->clip_bottom);
224#endif
225 if (y < img_overl->clip_top) {
226 zone_state = 1;
227 break;
228 } else if (y >= img_overl->clip_bottom) {
229 zone_state = 5;
230 break;
231 } else if (x < img_overl->clip_left) {
232 zone_state = 2;
233 break;
234 } else if (x >= img_overl->clip_right) {
235 zone_state = 4;
236 break;
237 } else {
238 zone_state = 3;
239 break;
240 }
241 break;
242 case 1: /* Above clip area */
243 clut = (clut_t*) img_overl->color;
244 trans = img_overl->trans;
176 o = trans[clr]; 245 o = trans[clr];
177 rlelen = rle->len; 246 rle_this_bite = rle_remainder;
178 247 rle_remainder = 0;
179 if (o && mask) { 248 rlelen -= rle_this_bite;
180 /* threat cases where clipping border is inside rle->len pixels */ 249 /*printf("(x,y) = (%03i,%03i), clr=%03x, len=%03i, zone=%i\n", x, y, clr, rle_this_bite, zone_state); */
181 if ( img_overl->clip_left > x ) { 250 if (o) {
182 if( img_overl->clip_left < x + rlelen ) { 251 x1_scaled = SCALED_TO_INT( x * x_scale );
183 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 252 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
184 rlelen -= img_overl->clip_left - x; 253 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
185 x += img_overl->clip_left - x; 254 }
186 } else { 255 x += rle_this_bite;
187 o = 0; 256 if (x >= src_width ) {
257 x -= src_width;
258 img_pix += img_width;
259
260 dy += dy_step;
261 if (dy >= INT_TO_SCALED(1)) {
262 dy -= INT_TO_SCALED(1);
263 ++y;
264 while (dy >= INT_TO_SCALED(1)) {
265 rle = rle_img_advance_line(rle, rle_limit, src_width);
266 dy -= INT_TO_SCALED(1);
267 ++y;
188 } 268 }
189 } else if( clip_right < x + rlelen ) { 269 rle_start = rle;
190 if( clip_right > x ) { 270 } else {
191 x2_scaled = SCALED_TO_INT( clip_right * x_scale); 271 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
192 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, 272 }
193 x2_scaled-x1_scaled); 273 }
194 o = 0; 274 rle_remainder = rlelen = rle->len;
195 } else { 275 clr_next = rle->color;
196 o = 0; 276 rle++;
277 if (rle >= rle_limit) {
278 zone_state = 6;
279 }
280 if (y >= img_overl->clip_top) {
281 zone_state = 2;
282#ifdef LOG_BLEND_RGB16
283 printf("blend_rgb16: Button clip top reached. y=%i, top=%i\n",
284 y, img_overl->clip_top);
285#endif
286 if (x >= img_overl->clip_left) {
287 zone_state = 3;
288 if (x >= img_overl->clip_right) {
289 zone_state = 4;
197 } 290 }
198 } 291 }
199 } 292 }
200 293 break;
201 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 294 case 2: /* Left of button */
202 if (o && mask) { 295 clut = (clut_t*) img_overl->color;
203 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); 296 trans = img_overl->trans;
297 o = trans[clr];
298 if (x + rle_remainder <= img_overl->clip_left) {
299 rle_this_bite = rle_remainder;
300 rle_remainder = rlelen = rle->len;
301 clr_next = rle->color;
302 rle++;
303 } else {
304 rle_this_bite = img_overl->clip_left - x;
305 rle_remainder -= rle_this_bite;
306 zone_state = 3;
204 } 307 }
205 308 if (o) {
206 x1_scaled = x2_scaled; 309 x1_scaled = SCALED_TO_INT( x * x_scale );
207 x += rlelen; 310 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
311 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
312 }
313 x += rle_this_bite;
314 if (x >= src_width ) {
315 x -= src_width;
316 img_pix += img_width;
317 dy += dy_step;
318 if (dy >= INT_TO_SCALED(1)) {
319 dy -= INT_TO_SCALED(1);
320 ++y;
321 while (dy >= INT_TO_SCALED(1)) {
322 rle = rle_img_advance_line(rle, rle_limit, src_width);
323 dy -= INT_TO_SCALED(1);
324 ++y;
325 }
326 rle_start = rle;
327 } else {
328 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
329 }
330 if (y >= img_overl->clip_bottom) {
331 zone_state = 5;
332 break;
333 }
334 }
335 if (rle >= rle_limit) {
336 zone_state = 6;
337 }
338 break;
339 case 3: /* In button */
340 clut = (clut_t*) img_overl->clip_color;
341 trans = img_overl->clip_trans;
342 o = trans[clr];
343 if (x + rle_remainder <= img_overl->clip_right) {
344 rle_this_bite = rle_remainder;
345 rle_remainder = rlelen = rle->len;
346 clr_next = rle->color;
347 rle++;
348 } else {
349 rle_this_bite = img_overl->clip_right - x;
350 rle_remainder -= rle_this_bite;
351 zone_state = 4;
352 }
353 if (o) {
354 x1_scaled = SCALED_TO_INT( x * x_scale );
355 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
356 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
357 }
358 x += rle_this_bite;
359 if (x >= src_width ) {
360 x -= src_width;
361 img_pix += img_width;
362 dy += dy_step;
363 if (dy >= INT_TO_SCALED(1)) {
364 dy -= INT_TO_SCALED(1);
365 ++y;
366 while (dy >= INT_TO_SCALED(1)) {
367 rle = rle_img_advance_line(rle, rle_limit, src_width);
368 dy -= INT_TO_SCALED(1);
369 ++y;
370 }
371 rle_start = rle;
372 } else {
373 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
374 }
375 if (y >= img_overl->clip_bottom) {
376 zone_state = 5;
377 break;
378 }
379 }
380 if (rle >= rle_limit) {
381 zone_state = 6;
382 }
383 break;
384 case 4: /* Right of button */
385 clut = (clut_t*) img_overl->color;
386 trans = img_overl->trans;
387 o = trans[clr];
388 if (x + rle_remainder <= src_width) {
389 rle_this_bite = rle_remainder;
390 rle_remainder = rlelen = rle->len;
391 clr_next = rle->color;
392 rle++;
393 } else {
394 rle_this_bite = src_width - x;
395 rle_remainder -= rle_this_bite;
396 zone_state = 2;
397 }
398 if (o) {
399 x1_scaled = SCALED_TO_INT( x * x_scale );
400 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
401 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
402 }
403 x += rle_this_bite;
404 if (x >= src_width ) {
405 x -= src_width;
406 img_pix += img_width;
407 dy += dy_step;
408 if (dy >= INT_TO_SCALED(1)) {
409 dy -= INT_TO_SCALED(1);
410 ++y;
411 while (dy >= INT_TO_SCALED(1)) {
412 rle = rle_img_advance_line(rle, rle_limit, src_width);
413 dy -= INT_TO_SCALED(1);
414 ++y;
415 }
416 rle_start = rle;
417 } else {
418 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
419 }
420 if (y >= img_overl->clip_bottom) {
421 zone_state = 5;
422 break;
423 }
424 }
425 if (rle >= rle_limit) {
426 zone_state = 6;
427 }
428 break;
429 case 5: /* Below button */
430 clut = (clut_t*) img_overl->color;
431 trans = img_overl->trans;
432 o = trans[clr];
433 rle_this_bite = rle_remainder;
434 rle_remainder = 0;
435 rlelen -= rle_this_bite;
436 if (o) {
437 x1_scaled = SCALED_TO_INT( x * x_scale );
438 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
439 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
440 }
441 x += rle_this_bite;
442 if (x >= src_width ) {
443 x -= src_width;
444 img_pix += img_width;
445 dy += dy_step;
446 if (dy >= INT_TO_SCALED(1)) {
447 dy -= INT_TO_SCALED(1);
448 ++y;
449 while (dy >= INT_TO_SCALED(1)) {
450 rle = rle_img_advance_line(rle, rle_limit, src_width);
451 dy -= INT_TO_SCALED(1);
452 ++y;
453 }
454 rle_start = rle;
455 } else {
456 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
457 }
458 }
459 rle_remainder = rlelen = rle->len;
460 clr_next = rle->color;
208 rle++; 461 rle++;
209 if (rle >= rle_limit) break; 462 if (rle >= rle_limit) {
210 } 463 zone_state = 6;
464 }
465 break;
466 case 6: /* Finished */
467 _x_abort();
211 468
212 img_pix += img_width; 469 case 7: /* No button */
213 dy += dy_step; 470 clut = (clut_t*) img_overl->color;
214 if (dy >= INT_TO_SCALED(1)) { 471 trans = img_overl->trans;
215 dy -= INT_TO_SCALED(1); 472 o = trans[clr];
216 ++y; 473 rle_this_bite = rle_remainder;
217 while (dy >= INT_TO_SCALED(1)) { 474 rle_remainder = 0;
218 rle = rle_img_advance_line(rle, rle_limit, src_width); 475 rlelen -= rle_this_bite;
219 dy -= INT_TO_SCALED(1); 476 if (o) {
220 ++y; 477 x1_scaled = SCALED_TO_INT( x * x_scale );
478 x2_scaled = SCALED_TO_INT( (x + rle_this_bite) * x_scale);
479 mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled);
221 } 480 }
222 } else { 481 x += rle_this_bite;
223 rle = rle_start; /* y-scaling, reuse the last rle encoded line */ 482 if (x >= src_width ) {
483 x -= src_width;
484 img_pix += img_width;
485 dy += dy_step;
486 if (dy >= INT_TO_SCALED(1)) {
487 dy -= INT_TO_SCALED(1);
488 ++y;
489 while (dy >= INT_TO_SCALED(1)) {
490 rle = rle_img_advance_line(rle, rle_limit, src_width);
491 dy -= INT_TO_SCALED(1);
492 ++y;
493 }
494 rle_start = rle;
495 } else {
496 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
497 }
498 }
499 rle_remainder = rlelen = rle->len;
500 clr_next = rle->color;
501 rle++;
502 if (rle >= rle_limit) {
503 zone_state = 6;
504 }
505 break;
506 default:
507 ;
224 } 508 }
225 } 509 }
510#ifdef LOG_BLEND_RGB16
511 printf("blend_rgb16 ended\n");
512#endif
513
226} 514}
227 515
228void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, 516void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
229 int img_width, int img_height, 517 int img_width, int img_height,
230 int dst_width, int dst_height) 518 int dst_width, int dst_height,
519 alphablend_t *extra_data)
231{ 520{
232 clut_t* clut = (clut_t*) img_overl->clip_color;
233 uint8_t *trans;
234 int src_width = img_overl->width; 521 int src_width = img_overl->width;
235 int src_height = img_overl->height; 522 int src_height = img_overl->height;
236 rle_elem_t *rle = img_overl->rle; 523 rle_elem_t *rle = img_overl->rle;
237 rle_elem_t *rle_limit = rle + img_overl->num_rle; 524 rle_elem_t *rle_limit = rle + img_overl->num_rle;
238 int x, y, x1_scaled, x2_scaled; 525 int x, y, x1_scaled, x2_scaled;
239 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ 526 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */
240 int clip_right; 527 int clip_right;
241 uint8_t *img_pix; 528 uint8_t *img_pix;
242 529
243 dy_step = INT_TO_SCALED(dst_height) / img_height; 530 dy_step = INT_TO_SCALED(dst_height) / img_height;
244 x_scale = INT_TO_SCALED(img_width) / dst_width; 531 x_scale = INT_TO_SCALED(img_width) / dst_width;
245 532
246 img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width 533 img_pix = img + 3 * ( (img_overl->y * img_height / dst_height) * img_width
247 + (img_overl->x * img_width / dst_width)); 534 + (img_overl->x * img_width / dst_width));
248 535
249 trans = img_overl->clip_trans;
250
251 /* avoid wraping overlay if drawing to small image */ 536 /* avoid wraping overlay if drawing to small image */
252 if( (img_overl->x + img_overl->clip_right) < dst_width ) 537 if( (img_overl->x + img_overl->clip_right) <= dst_width )
253 clip_right = img_overl->clip_right; 538 clip_right = img_overl->clip_right;
254 else 539 else
255 clip_right = dst_width - 1 - img_overl->x; 540 clip_right = dst_width - img_overl->x;
256 541
257 /* avoid buffer overflow */ 542 /* avoid buffer overflow */
258 if( (src_height + img_overl->y) >= dst_height ) 543 if( (src_height + img_overl->y) > dst_height )
259 src_height = dst_height - 1 - img_overl->y; 544 src_height = dst_height - img_overl->y;
260 545
261 for (dy = y = 0; y < src_height && rle < rle_limit; ) { 546 for (dy = y = 0; y < src_height && rle < rle_limit; ) {
262 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 547 int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
263 rle_elem_t *rle_start = rle; 548 rle_elem_t *rle_start = rle;
264 549
550 int rlelen = 0;
551 uint8_t clr = 0;
552
265 for (x = x1_scaled = 0; x < src_width;) { 553 for (x = x1_scaled = 0; x < src_width;) {
266 uint8_t clr; 554 int rle_bite;
555 clut_t *colors;
556 uint8_t *trans;
267 uint16_t o; 557 uint16_t o;
268 int rlelen;
269 558
270 clr = rle->color; 559 /* take next element from rle list everytime an element is finished */
271 o = trans[clr]; 560 if (rlelen <= 0) {
272 rlelen = rle->len; 561 if (rle >= rle_limit)
273 562 break;
274 if (o && mask) { 563
275 /* threat cases where clipping border is inside rle->len pixels */ 564 rlelen = rle->len;
276 if ( img_overl->clip_left > x ) { 565 clr = rle->color;
277 if( img_overl->clip_left < x + rlelen ) { 566 rle++;
278 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 567 }
279 rlelen -= img_overl->clip_left - x; 568
280 x += img_overl->clip_left - x; 569 if (!mask) {
570 /* above or below clipping area */
571
572 rle_bite = rlelen;
573 /* choose palette for surrounding area */
574 colors = (clut_t*)img_overl->color;
575 trans = img_overl->trans;
576 } else {
577 /* treat cases where clipping border is inside rle->len pixels */
578 if ( x < img_overl->clip_left ) {
579 /* starts left */
580 if( x + rlelen > img_overl->clip_left ) {
581 /* ends not left */
582
583 /* choose the largest "bite" up to palette change */
584 rle_bite = img_overl->clip_left - x;
585 /* choose palette for surrounding area */
586 colors = (clut_t*)img_overl->color;
587 trans = img_overl->trans;
281 } else { 588 } else {
282 o = 0; 589 /* ends left */
590
591 rle_bite = rlelen;
592 /* choose palette for surrounding area */
593 colors = (clut_t*)img_overl->color;
594 trans = img_overl->trans;
283 } 595 }
284 } else if( clip_right < x + rlelen ) { 596 } else if( x + rlelen > clip_right ) {
285 if( clip_right > x ) { 597 /* ends right */
286 x2_scaled = SCALED_TO_INT( clip_right * x_scale); 598 if( x < clip_right ) {
287 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, 599 /* starts not right */
288 clut[clr].cr, clut[clr].y, 600
289 o, x2_scaled-x1_scaled); 601 /* choose the largest "bite" up to palette change */
290 o = 0; 602 rle_bite = clip_right - x;
603 /* we're in the center area so choose clip palette */
604 colors = (clut_t*)img_overl->clip_color;
605 trans = img_overl->clip_trans;
291 } else { 606 } else {
292 o = 0; 607 /* starts right */
608
609 rle_bite = rlelen;
610 /* choose palette for surrounding area */
611 colors = (clut_t*)img_overl->color;
612 trans = img_overl->trans;
293 } 613 }
294 } 614 } else {
615 /* starts not left and ends not right */
616
617 rle_bite = rlelen;
618 /* we're in the center area so choose clip palette */
619 colors = (clut_t*)img_overl->clip_color;
620 trans = img_overl->clip_trans;
621 }
295 } 622 }
296 623
297 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 624 x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
298 if (o && mask) { 625
299 mem_blend24(img_pix + x1_scaled*3, clut[clr].cb, 626 o = trans[clr];
300 clut[clr].cr, clut[clr].y, 627 if (o) {
628 mem_blend24(img_pix + x1_scaled*3,
629 colors[clr].cb, colors[clr].cr, colors[clr].y,
301 o, x2_scaled-x1_scaled); 630 o, x2_scaled-x1_scaled);
302 } 631 }
303 632
304 x1_scaled = x2_scaled; 633 x1_scaled = x2_scaled;
305 x += rlelen; 634 x += rle_bite;
306 rle++; 635 rlelen -= rle_bite;
307 if (rle >= rle_limit) break;
308 } 636 }
309 637
310 img_pix += img_width * 3; 638 img_pix += img_width * 3;
311 dy += dy_step; 639 dy += dy_step;
312 if (dy >= INT_TO_SCALED(1)) { 640 if (dy >= INT_TO_SCALED(1)) {
313 dy -= INT_TO_SCALED(1); 641 dy -= INT_TO_SCALED(1);
314 ++y; 642 ++y;
315 while (dy >= INT_TO_SCALED(1)) { 643 while (dy >= INT_TO_SCALED(1)) {
316 rle = rle_img_advance_line(rle, rle_limit, src_width); 644 rle = rle_img_advance_line(rle, rle_limit, src_width);
317 dy -= INT_TO_SCALED(1); 645 dy -= INT_TO_SCALED(1);
318 ++y; 646 ++y;
319 } 647 }
320 } else { 648 } else {
321 rle = rle_start; /* y-scaling, reuse the last rle encoded line */ 649 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
322 } 650 }
323 } 651 }
324} 652}
325 653
326void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, 654void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
327 int img_width, int img_height, 655 int img_width, int img_height,
328 int dst_width, int dst_height) 656 int dst_width, int dst_height,
657 alphablend_t *extra_data)
329{ 658{
330 clut_t* clut = (clut_t*) img_overl->clip_color;
331 uint8_t *trans;
332 int src_width = img_overl->width; 659 int src_width = img_overl->width;
333 int src_height = img_overl->height; 660 int src_height = img_overl->height;
334 rle_elem_t *rle = img_overl->rle; 661 rle_elem_t *rle = img_overl->rle;
335 rle_elem_t *rle_limit = rle + img_overl->num_rle; 662 rle_elem_t *rle_limit = rle + img_overl->num_rle;
336 int x, y, x1_scaled, x2_scaled; 663 int x, y, x1_scaled, x2_scaled;
337 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */ 664 int dy, dy_step, x_scale;/* scaled 2**SCALE_SHIFT */
338 int clip_right; 665 int clip_right;
339 uint8_t *img_pix; 666 uint8_t *img_pix;
340 667
341 dy_step = INT_TO_SCALED(dst_height) / img_height; 668 dy_step = INT_TO_SCALED(dst_height) / img_height;
342 x_scale = INT_TO_SCALED(img_width) / dst_width; 669 x_scale = INT_TO_SCALED(img_width) / dst_width;
343 670
344 img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width 671 img_pix = img + 4 * ( (img_overl->y * img_height / dst_height) * img_width
345 + (img_overl->x * img_width / dst_width)); 672 + (img_overl->x * img_width / dst_width));
346 673
347 trans = img_overl->clip_trans;
348
349 /* avoid wraping overlay if drawing to small image */ 674 /* avoid wraping overlay if drawing to small image */
350 if( (img_overl->x + img_overl->clip_right) < dst_width ) 675 if( (img_overl->x + img_overl->clip_right) <= dst_width )
351 clip_right = img_overl->clip_right; 676 clip_right = img_overl->clip_right;
352 else 677 else
353 clip_right = dst_width - 1 - img_overl->x; 678 clip_right = dst_width - img_overl->x;
354 679
355 /* avoid buffer overflow */ 680 /* avoid buffer overflow */
356 if( (src_height + img_overl->y) >= dst_height ) 681 if( (src_height + img_overl->y) > dst_height )
357 src_height = dst_height - 1 - img_overl->y; 682 src_height = dst_height - img_overl->y;
358 683
359 for (y = dy = 0; y < src_height && rle < rle_limit; ) { 684 for (y = dy = 0; y < src_height && rle < rle_limit; ) {
360 int mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 685 int mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
361 rle_elem_t *rle_start = rle; 686 rle_elem_t *rle_start = rle;
362 687
688 int rlelen = 0;
689 uint8_t clr = 0;
690
363 for (x = x1_scaled = 0; x < src_width;) { 691 for (x = x1_scaled = 0; x < src_width;) {
364 uint8_t clr; 692 int rle_bite;
693 clut_t *colors;
694 uint8_t *trans;
365 uint16_t o; 695 uint16_t o;
366 int rlelen; 696
697 /* take next element from rle list everytime an element is finished */
698 if (rlelen <= 0) {
699 if (rle >= rle_limit)
700 break;
701
702 rlelen = rle->len;
703 clr = rle->color;
704 rle++;
705 }
367 706
368 clr = rle->color; 707 if (!mask) {
369 o = trans[clr]; 708 /* above or below clipping area */
370 rlelen = rle->len; 709
371 710 rle_bite = rlelen;
372 if (o && mask) { 711 /* choose palette for surrounding area */
373 /* threat cases where clipping border is inside rle->len pixels */ 712 colors = (clut_t*)img_overl->color;
374 if ( img_overl->clip_left > x ) { 713 trans = img_overl->trans;
375 if( img_overl->clip_left < x + rlelen ) { 714 } else {
376 x1_scaled = SCALED_TO_INT( img_overl->clip_left * x_scale ); 715 /* treat cases where clipping border is inside rle->len pixels */
377 rlelen -= img_overl->clip_left - x; 716 if ( x < img_overl->clip_left ) {
378 x += img_overl->clip_left - x; 717 /* starts left */
718 if( x + rlelen > img_overl->clip_left ) {
719 /* ends not left */
720
721 /* choose the largest "bite" up to palette change */
722 rle_bite = img_overl->clip_left - x;
723 /* choose palette for surrounding area */
724 colors = (clut_t*)img_overl->color;
725 trans = img_overl->trans;
379 } else { 726 } else {
380 o = 0; 727 /* ends left */
728
729 rle_bite = rlelen;
730 /* choose palette for surrounding area */
731 colors = (clut_t*)img_overl->color;
732 trans = img_overl->trans;
381 } 733 }
382 } else if( clip_right < x + rlelen ) { 734 } else if( x + rlelen > clip_right ) {
383 if( clip_right > x ) { 735 /* ends right */
384 x2_scaled = SCALED_TO_INT( clip_right * x_scale); 736 if( x < clip_right ) {
385 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, 737 /* starts not right */
386 clut[clr].cr, clut[clr].y, 738
387 o, x2_scaled-x1_scaled); 739 /* choose the largest "bite" up to palette change */
388 o = 0; 740 rle_bite = clip_right - x;
741 /* we're in the center area so choose clip palette */
742 colors = (clut_t*)img_overl->clip_color;
743 trans = img_overl->clip_trans;
389 } else { 744 } else {
390 o = 0; 745 /* starts right */
746
747 rle_bite = rlelen;
748 /* choose palette for surrounding area */
749 colors = (clut_t*)img_overl->color;
750 trans = img_overl->trans;
391 } 751 }
392 } 752 } else {
753 /* starts not left and ends not right */
754
755 rle_bite = rlelen;
756 /* we're in the center area so choose clip palette */
757 colors = (clut_t*)img_overl->clip_color;
758 trans = img_overl->clip_trans;
759 }
393 } 760 }
761
762 x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale);
394 763
395 x2_scaled = SCALED_TO_INT((x + rlelen) * x_scale); 764 o = trans[clr];
396 if (o && mask) { 765 if (o) {
397 mem_blend24_32(img_pix + x1_scaled*4, clut[clr].cb, 766 mem_blend32(img_pix + x1_scaled*4, (uint8_t *)&colors[clr], o, x2_scaled-x1_scaled);
398 clut[clr].cr, clut[clr].y,
399 o, x2_scaled-x1_scaled);
400 } 767 }
401 768
402 x1_scaled = x2_scaled; 769 x1_scaled = x2_scaled;
403 x += rlelen; 770 x += rle_bite;
404 rle++; 771 rlelen -= rle_bite;
405 if (rle >= rle_limit) break;
406 } 772 }
407 773
408 img_pix += img_width * 4; 774 img_pix += img_width * 4;
409 dy += dy_step; 775 dy += dy_step;
410 if (dy >= INT_TO_SCALED(1)) { 776 if (dy >= INT_TO_SCALED(1)) {
411 dy -= INT_TO_SCALED(1); 777 dy -= INT_TO_SCALED(1);
412 ++y; 778 ++y;
413 while (dy >= INT_TO_SCALED(1)) { 779 while (dy >= INT_TO_SCALED(1)) {
414 rle = rle_img_advance_line(rle, rle_limit, src_width); 780 rle = rle_img_advance_line(rle, rle_limit, src_width);
415 dy -= INT_TO_SCALED(1); 781 dy -= INT_TO_SCALED(1);
416 ++y; 782 ++y;
417 } 783 }
418 } else { 784 } else {
419 rle = rle_start; /* y-scaling, reuse the last rle encoded line */ 785 rle = rle_start; /* y-scaling, reuse the last rle encoded line */
420 } 786 }
421 } 787 }
422} 788}
423 789
424static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) 790static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz)
425{ 791{
426 uint8_t *limit = mem + sz; 792 uint8_t *limit = mem + sz;
427 while (mem < limit) { 793 while (mem < limit) {
428 *mem = BLEND_BYTE(*mem, val, o); 794 *mem = BLEND_BYTE(*mem, val, o);
429 mem++; 795 mem++;
430 } 796 }
431} 797}
432 798
799static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb,
800 int src_width, int x_odd,
801 uint8_t *(*blend_yuv_data)[ 3 ][ 2 ])
802{
803 int x;
804
805 for (x = 0; x < src_width; x += 2) {
806 /* get opacity of the 4 pixels that share chroma */
807 int o00 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 0 ];
808 int o01 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 1 ];
809 int o10 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 0 ];
810 int o11 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 1 ];
811
812 /* are there any pixels a little bit opaque? */
813 if (o00 || o01 || o10 || o11) {
814 /* get the chroma components of the 4 pixels */
815 int cr00 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 0 ];
816 int cr01 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 1 ];
817 int cr10 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 0 ];
818 int cr11 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 1 ];
819
820 int cb00 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 0 ];
821 int cb01 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 1 ];
822 int cb10 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 0 ];
823 int cb11 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 1 ];
824
825 /* are all pixels completely opaque? */
826 if (o00 >= 0xf && o01 >= 0xf && o10 >= 0xf && o11 >= 0xf) {
827 /* set the output chroma to the average of the four pixels */
828 *dst_cr = 128 + (cr00 + cr01 + cr10 + cr11) / 4;
829 *dst_cb = 128 + (cb00 + cb01 + cb10 + cb11) / 4;
830 } else {
831 int t4, cr, cb;
832
833 /* blending required, so clamp opacity values to allowed range */
834 if (o00 > 0xf) o00 = 0xf;
835 if (o01 > 0xf) o01 = 0xf;
836 if (o10 > 0xf) o10 = 0xf;
837 if (o11 > 0xf) o11 = 0xf;
838
839 /* calculate transparency of background over the four pixels */
840 t4 = (0xf - o00) + (0xf - o01) + (0xf - o10) + (0xf - o11);
841
842 /* get background chroma */
843 cr = -128 + *dst_cr;
844 cb = -128 + *dst_cb;
845
846 /* blend the output chroma to the average of the four pixels */
847 *dst_cr = 128 + (cr * t4 + cr00 * o00 + cr01 * o01 + cr10 * o10 + cr11 * o11) / (4 * 0xf);
848 *dst_cb = 128 + (cb * t4 + cb00 * o00 + cb01 * o01 + cb10 * o10 + cb11 * o11) / (4 * 0xf);
849 }
850 }
851
852 /* next chroma sample */
853 dst_cr++;
854 dst_cb++;
855 }
856}
857
858static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ]
859{
860 struct __attribute__((packed)) header_s {
861 int id;
862 int max_width;
863 uint8_t *data[ 3 ][ 2 ];
864 } **header = (struct header_s **)&extra_data->buffer;
865
866 int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ 2 ][ osd_width ]);
867
868 if (extra_data->buffer_size < needed_buffer_size) {
869
870 free(extra_data->buffer);
871 extra_data->buffer = xine_xmalloc(needed_buffer_size);
872
873 if (!extra_data->buffer) {
874 extra_data->buffer_size = 0;
875 return 0;
876 }
877
878 extra_data->buffer_size = needed_buffer_size;
879 (*header)->max_width = 0;
880 }
881
882 if ((*header)->id != ME_FOURCC('y', 'u', 'v', 0) || (*header)->max_width < osd_width) {
883 (*header)->id = ME_FOURCC('y', 'u', 'v', 0);
884 (*header)->max_width = osd_width;
885
886 (*header)->data[ 0 ][ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
887 (*header)->data[ 0 ][ 1 ] = (*header)->data[ 0 ][ 0 ] + osd_width;
888 (*header)->data[ 1 ][ 0 ] = (*header)->data[ 0 ][ 1 ] + osd_width;
889 (*header)->data[ 1 ][ 1 ] = (*header)->data[ 1 ][ 0 ] + osd_width;
890 (*header)->data[ 2 ][ 0 ] = (*header)->data[ 1 ][ 1 ] + osd_width;
891 (*header)->data[ 2 ][ 1 ] = (*header)->data[ 2 ][ 0 ] + osd_width;
892 }
893
894 return &(*header)->data;
895}
896
433void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, 897void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
434 int dst_width, int dst_height) 898 int dst_width, int dst_height, int dst_pitches[3],
899 alphablend_t *extra_data)
435{ 900{
901 int enable_exact_blending = !extra_data->disable_exact_blending;
436 clut_t *my_clut; 902 clut_t *my_clut;
437 uint8_t *my_trans; 903 uint8_t *my_trans;
438 904
439 int src_width = img_overl->width; 905 int src_width = img_overl->width;
440 int src_height = img_overl->height; 906 int src_height = img_overl->height;
441 rle_elem_t *rle = img_overl->rle; 907 rle_elem_t *rle = img_overl->rle;
442 rle_elem_t *rle_limit = rle + img_overl->num_rle; 908 rle_elem_t *rle_limit = rle + img_overl->num_rle;
443 int x_off = img_overl->x; 909 int x_off = img_overl->x;
444 int y_off = img_overl->y; 910 int y_off = img_overl->y;
911 int x_odd = x_off & 1;
912 int y_odd = y_off & 1;
445 int ymask,xmask; 913 int ymask,xmask;
446 int rle_this_bite; 914 int rle_this_bite;
447 int rle_remainder; 915 int rle_remainder;
448 int rlelen; 916 int rlelen;
449 int x, y; 917 int x, y;
450 int clip_right; 918 int clip_right;
451 uint8_t clr=0; 919 uint8_t clr=0;
452 920
453 uint8_t *dst_y = dst_base[0] + dst_width * y_off + x_off; 921 int any_line_buffered = 0;
454 uint8_t *dst_cr = dst_base[2] + 922 int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
455 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; 923 int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
456 uint8_t *dst_cb = dst_base[1] + 924 uint8_t *(*blend_yuv_data)[ 3 ][ 2 ] = 0;
457 (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; 925
926 uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off;
927 uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2);
928 uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2);
458#ifdef LOG_BLEND_YUV 929#ifdef LOG_BLEND_YUV
459 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); 930 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);
460#endif 931#endif
461 my_clut = (clut_t*) img_overl->clip_color; 932 my_clut = (clut_t*) img_overl->clip_color;
462 my_trans = img_overl->clip_trans; 933 my_trans = img_overl->clip_trans;
463 934
464 /* avoid wraping overlay if drawing to small image */ 935 /* avoid wraping overlay if drawing to small image */
465 if( (x_off + img_overl->clip_right) < dst_width ) 936 if( (x_off + img_overl->clip_right) <= dst_width )
466 clip_right = img_overl->clip_right; 937 clip_right = img_overl->clip_right;
467 else 938 else
468 clip_right = dst_width - 1 - x_off; 939 clip_right = dst_width - x_off;
469 940
470 /* avoid buffer overflow */ 941 /* avoid buffer overflow */
471 if( (src_height + y_off) >= dst_height ) 942 if( (src_height + y_off) > dst_height )
472 src_height = dst_height - 1 - y_off; 943 src_height = dst_height - y_off;
473 944
945 if (src_height <= 0)
946 return;
947
948 if (enable_exact_blending) {
949 if (exact_blend_width <= 0)
950 return;
951
952 blend_yuv_data = blend_yuv_grow_extra_data(extra_data, exact_blend_width_m2);
953 if (!blend_yuv_data)
954 return;
955
956 /* make linebuffer transparent */
957 memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2);
958 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
959 }
960
474 rlelen=rle_remainder=0; 961 rlelen=rle_remainder=0;
475 for (y = 0; y < src_height; y++) { 962 for (y = 0; y < src_height; y++) {
476 ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y)); 963 if (rle >= rle_limit) {
964#ifdef LOG_BLEND_YUV
965 printf("y-rle_limit\n");
966#endif
967 break;
968 }
969
970 ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
477 xmask = 0; 971 xmask = 0;
478#ifdef LOG_BLEND_YUV 972#ifdef LOG_BLEND_YUV
479 printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height); 973 printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height);
480#endif 974#endif
481 975
482 for (x = 0; x < src_width;) { 976 for (x = 0; x < src_width;) {
483 uint16_t o; 977 uint16_t o;
978
979 if (rle >= rle_limit) {
980#ifdef LOG_BLEND_YUV
981 printf("x-rle_limit\n");
982#endif
983 break;
984 }
985
484#ifdef LOG_BLEND_YUV 986#ifdef LOG_BLEND_YUV
485 printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); 987 printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
486#endif 988#endif
487 989
488 if ((rlelen < 0) || (rle_remainder < 0)) { 990 if ((rlelen < 0) || (rle_remainder < 0)) {
991#ifdef LOG_BLEND_YUV
489 printf("alphablend: major bug in blend_yuv < 0\n"); 992 printf("alphablend: major bug in blend_yuv < 0\n");
993#endif
490 } 994 }
491 if (rlelen == 0) { 995 if (rlelen == 0) {
492 rle_remainder = rlelen = rle->len; 996 rle_remainder = rlelen = rle->len;
493 clr = rle->color; 997 clr = rle->color;
494 rle++; 998 rle++;
495 } 999 }
496 if (rle_remainder == 0) { 1000 if (rle_remainder == 0) {
497 rle_remainder = rlelen; 1001 rle_remainder = rlelen;
498 } 1002 }
499 if ((rle_remainder + x) > src_width) { 1003 if ((rle_remainder + x) > src_width) {
500 /* Do something for long rlelengths */ 1004 /* Do something for long rlelengths */
501 rle_remainder = src_width - x; 1005 rle_remainder = src_width - x;
502 ;
503 } 1006 }
504#ifdef LOG_BLEND_YUV 1007#ifdef LOG_BLEND_YUV
505 printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); 1008 printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
506#endif 1009#endif
507 1010
508 if (ymask == 0) { 1011 if (ymask == 0) {
509 if (x <= img_overl->clip_left) { 1012 if (x < img_overl->clip_left) {
510 /* Starts outside clip area */ 1013 /* Starts outside clip area */
511 if ((x + rle_remainder - 1) > img_overl->clip_left ) { 1014 if ((x + rle_remainder) > img_overl->clip_left ) {
512#ifdef LOG_BLEND_YUV 1015#ifdef LOG_BLEND_YUV
513 printf("Outside clip left %d, ending inside\n", img_overl->clip_left); 1016 printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
514#endif 1017#endif
515 /* Cutting needed, starts outside, ends inside */ 1018 /* Cutting needed, starts outside, ends inside */
516 rle_this_bite = (img_overl->clip_left - x + 1); 1019 rle_this_bite = (img_overl->clip_left - x);
517 rle_remainder -= rle_this_bite; 1020 rle_remainder -= rle_this_bite;
518 rlelen -= rle_this_bite; 1021 rlelen -= rle_this_bite;
519 my_clut = (clut_t*) img_overl->color; 1022 my_clut = (clut_t*) img_overl->color;
520 my_trans = img_overl->trans; 1023 my_trans = img_overl->trans;
521 xmask = 0; 1024 xmask = 0;
522 } else { 1025 } else {
523#ifdef LOG_BLEND_YUV 1026#ifdef LOG_BLEND_YUV
524 printf("Outside clip left %d, ending outside\n", img_overl->clip_left); 1027 printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
525#endif 1028#endif
526 /* no cutting needed, starts outside, ends outside */ 1029 /* no cutting needed, starts outside, ends outside */
527 rle_this_bite = rle_remainder; 1030 rle_this_bite = rle_remainder;
528 rle_remainder = 0; 1031 rle_remainder = 0;
529 rlelen -= rle_this_bite; 1032 rlelen -= rle_this_bite;
530 my_clut = (clut_t*) img_overl->color; 1033 my_clut = (clut_t*) img_overl->color;
531 my_trans = img_overl->trans; 1034 my_trans = img_overl->trans;
532 xmask = 0; 1035 xmask = 0;
533 } 1036 }
534 } else if (x < clip_right) { 1037 } else if (x < clip_right) {
535 /* Starts inside clip area */ 1038 /* Starts inside clip area */
536 if ((x + rle_remainder) > clip_right ) { 1039 if ((x + rle_remainder) > clip_right ) {
537#ifdef LOG_BLEND_YUV 1040#ifdef LOG_BLEND_YUV
538 printf("Inside clip right %d, ending outside\n", clip_right); 1041 printf("Inside clip right %d, ending outside\n", clip_right);
539#endif 1042#endif
540 /* Cutting needed, starts inside, ends outside */ 1043 /* Cutting needed, starts inside, ends outside */
541 rle_this_bite = (clip_right - x); 1044 rle_this_bite = (clip_right - x);
542 rle_remainder -= rle_this_bite; 1045 rle_remainder -= rle_this_bite;
543 rlelen -= rle_this_bite; 1046 rlelen -= rle_this_bite;
544 my_clut = (clut_t*) img_overl->clip_color; 1047 my_clut = (clut_t*) img_overl->clip_color;
545 my_trans = img_overl->clip_trans; 1048 my_trans = img_overl->clip_trans;
546 xmask++; 1049 xmask++;
547 } else { 1050 } else {
548#ifdef LOG_BLEND_YUV 1051#ifdef LOG_BLEND_YUV
549 printf("Inside clip right %d, ending inside\n", clip_right); 1052 printf("Inside clip right %d, ending inside\n", clip_right);
550#endif 1053#endif
551 /* no cutting needed, starts inside, ends inside */ 1054 /* no cutting needed, starts inside, ends inside */
552 rle_this_bite = rle_remainder; 1055 rle_this_bite = rle_remainder;
553 rle_remainder = 0; 1056 rle_remainder = 0;
554 rlelen -= rle_this_bite; 1057 rlelen -= rle_this_bite;
555 my_clut = (clut_t*) img_overl->clip_color; 1058 my_clut = (clut_t*) img_overl->clip_color;
556 my_trans = img_overl->clip_trans; 1059 my_trans = img_overl->clip_trans;
557 xmask++; 1060 xmask++;
558 } 1061 }
559 } else if (x >= clip_right) { 1062 } else if (x >= clip_right) {
560 /* Starts outside clip area, ends outsite clip area */ 1063 /* Starts outside clip area, ends outside clip area */
561 if ((x + rle_remainder ) > src_width ) { 1064 if ((x + rle_remainder ) > src_width ) {
562#ifdef LOG_BLEND_YUV 1065#ifdef LOG_BLEND_YUV
563 printf("Outside clip right %d, ending eol\n", clip_right); 1066 printf("Outside clip right %d, ending eol\n", clip_right);
564#endif 1067#endif
565 /* Cutting needed, starts outside, ends at right edge */ 1068 /* Cutting needed, starts outside, ends at right edge */
566 /* It should never reach here due to the earlier test of src_width */ 1069 /* It should never reach here due to the earlier test of src_width */
567 rle_this_bite = (src_width - x ); 1070 rle_this_bite = (src_width - x );
568 rle_remainder -= rle_this_bite; 1071 rle_remainder -= rle_this_bite;
569 rlelen -= rle_this_bite; 1072 rlelen -= rle_this_bite;
570 my_clut = (clut_t*) img_overl->color; 1073 my_clut = (clut_t*) img_overl->color;
571 my_trans = img_overl->trans; 1074 my_trans = img_overl->trans;
572 xmask = 0; 1075 xmask = 0;
573 } else { 1076 } else {
574 /* no cutting needed, starts outside, ends outside */ 1077 /* no cutting needed, starts outside, ends outside */
575#ifdef LOG_BLEND_YUV 1078#ifdef LOG_BLEND_YUV
576 printf("Outside clip right %d, ending outside\n", clip_right); 1079 printf("Outside clip right %d, ending outside\n", clip_right);
577#endif 1080#endif
578 rle_this_bite = rle_remainder; 1081 rle_this_bite = rle_remainder;
579 rle_remainder = 0; 1082 rle_remainder = 0;
580 rlelen -= rle_this_bite; 1083 rlelen -= rle_this_bite;
581 my_clut = (clut_t*) img_overl->color; 1084 my_clut = (clut_t*) img_overl->color;
582 my_trans = img_overl->trans; 1085 my_trans = img_overl->trans;
583 xmask = 0; 1086 xmask = 0;
584 } 1087 }
585 } 1088 }
586 } else { 1089 } else {
587 /* Outside clip are due to y */ 1090 /* Outside clip are due to y */
588 /* no cutting needed, starts outside, ends outside */ 1091 /* no cutting needed, starts outside, ends outside */
589 rle_this_bite = rle_remainder; 1092 rle_this_bite = rle_remainder;
590 rle_remainder = 0; 1093 rle_remainder = 0;
591 rlelen -= rle_this_bite; 1094 rlelen -= rle_this_bite;
592 my_clut = (clut_t*) img_overl->color; 1095 my_clut = (clut_t*) img_overl->color;
593 my_trans = img_overl->trans; 1096 my_trans = img_overl->trans;
594 xmask = 0; 1097 xmask = 0;
595 } 1098 }
596 o = my_trans[clr]; 1099 o = my_trans[clr];
597#ifdef LOG_BLEND_YUV 1100#ifdef LOG_BLEND_YUV
598 printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y); 1101 printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y);
599#endif 1102#endif
600 if (o) { 1103
601 if(o >= 15) { 1104 if (x < (dst_width - x_off)) {
602 memset(dst_y + x, my_clut[clr].y, rle_this_bite); 1105 /* clip against right edge of destination area */
603 if (y & 1) { 1106 if ((x + rle_this_bite) > (dst_width - x_off)) {
604 memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); 1107 int toClip = (x + rle_this_bite) - (dst_width - x_off);
605 memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); 1108
606 } 1109 rle_this_bite -= toClip;
607 } else { 1110 rle_remainder += toClip;
608 mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); 1111 rlelen += toClip;
609 if (y & 1) {
610 /* Blending cr and cb should use a different function, with pre -128 to each sample */
611 mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
612 mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
613 }
614 } 1112 }
615 1113
1114 if (enable_exact_blending) {
1115 /* remember opacity of current line */
1116 memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite);
1117 any_line_buffered |= ((y + y_odd) & 1) ? 2 : 1;
1118 }
1119
1120 if (o) {
1121 if(o >= 15) {
1122 memset(dst_y + x, my_clut[clr].y, rle_this_bite);
1123 if (!enable_exact_blending) {
1124 if ((y + y_odd) & 1) {
1125 memset(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
1126 memset(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
1127 }
1128 }
1129 } else {
1130 mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
1131 if (!enable_exact_blending) {
1132 if ((y + y_odd) & 1) {
1133 /* Blending cr and cb should use a different function, with pre -128 to each sample */
1134 mem_blend8(dst_cr + ((x + x_odd) >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1);
1135 mem_blend8(dst_cb + ((x + x_odd) >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1);
1136 }
1137 }
1138 }
1139
1140 if (enable_exact_blending) {
1141 /* remember chroma of current line */
1142 memset(&(*blend_yuv_data)[ 1 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
1143 memset(&(*blend_yuv_data)[ 2 ][ (y + y_odd) & 1 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
1144 }
1145 }
616 } 1146 }
617#ifdef LOG_BLEND_YUV 1147#ifdef LOG_BLEND_YUV
618 printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x); 1148 printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x);
619#endif 1149#endif
620 x += rle_this_bite; 1150 x += rle_this_bite;
621 if (rle >= rle_limit) {
622#ifdef LOG_BLEND_YUV
623 printf("x-rle_limit\n");
624#endif
625 break;
626 }
627 }
628 if (rle >= rle_limit) {
629#ifdef LOG_BLEND_YUV
630 printf("x-rle_limit\n");
631#endif
632 break;
633 } 1151 }
634 1152
635 dst_y += dst_width; 1153 if ((y + y_odd) & 1) {
1154 if (enable_exact_blending) {
1155 /* blend buffered lines */
1156 if (any_line_buffered) {
1157 if (!(any_line_buffered & 2)) {
1158 /* make second line transparent */
1159 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
1160 }
1161
1162 blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
1163
1164 any_line_buffered = 0;
1165 }
1166 }
1167
1168 dst_cr += dst_pitches[2];
1169 dst_cb += dst_pitches[1];
1170 }
1171
1172 dst_y += dst_pitches[0];
1173 }
636 1174
637 if (y & 1) { 1175 if (enable_exact_blending) {
638 dst_cr += (dst_width + 1) / 2; 1176 /* blend buffered lines */
639 dst_cb += (dst_width + 1) / 2; 1177 if (any_line_buffered) {
1178 if (!(any_line_buffered & 2)) {
1179 /* make second line transparent */
1180 memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2);
1181 }
1182
1183 blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data);
640 } 1184 }
641 } 1185 }
1186
642#ifdef LOG_BLEND_YUV 1187#ifdef LOG_BLEND_YUV
643 printf("overlay_blend ended\n"); 1188 printf("overlay_blend ended\n");
644#endif 1189#endif
645} 1190}
646 1191
1192static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb,
1193 int src_width, int x_odd,
1194 uint8_t *(*blend_yuy2_data)[ 3 ])
1195{
1196 int x;
1197
1198 for (x = 0; x < src_width; x += 2) {
1199 /* get opacity of the 2 pixels that share chroma */
1200 int o0 = (*blend_yuy2_data)[ 0 ][ x + 0 ];
1201 int o1 = (*blend_yuy2_data)[ 0 ][ x + 1 ];
1202
1203 /* are there any pixels a little bit opaque? */
1204 if (o0 || o1) {
1205 /* get the chroma components of the 2 pixels */
1206 int cr0 = -128 + (*blend_yuy2_data)[ 1 ][ x + 0 ];
1207 int cr1 = -128 + (*blend_yuy2_data)[ 1 ][ x + 1 ];
1208
1209 int cb0 = -128 + (*blend_yuy2_data)[ 2 ][ x + 0 ];
1210 int cb1 = -128 + (*blend_yuy2_data)[ 2 ][ x + 1 ];
1211
1212 /* are all pixels completely opaque? */
1213 if (o0 >= 0xf && o1 >= 0xf) {
1214 /* set the output chroma to the average of the two pixels */
1215 *dst_cr = 128 + (cr0 + cr1) / 2;
1216 *dst_cb = 128 + (cb0 + cb1) / 2;
1217 } else {
1218 int t2, cr, cb;
1219
1220 /* blending required, so clamp opacity values to allowed range */
1221 if (o0 > 0xf) o0 = 0xf;
1222 if (o1 > 0xf) o1 = 0xf;
1223
1224 /* calculate transparency of background over the two pixels */
1225 t2 = (0xf - o0) + (0xf - o1);
1226
1227 /* get background chroma */
1228 cr = -128 + *dst_cr;
1229 cb = -128 + *dst_cb;
1230
1231 /* blend the output chroma to the average of the two pixels */
1232 *dst_cr = 128 + (cr * t2 + cr0 * o0 + cr1 * o1) / (2 * 0xf);
1233 *dst_cb = 128 + (cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf);
1234 }
1235 }
1236
1237 /* next chroma sample */
1238 dst_cr += 4;
1239 dst_cb += 4;
1240 }
1241}
1242
1243static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ]
1244{
1245 struct __attribute__((packed)) header_s {
1246 int id;
1247 int max_width;
1248 uint8_t *data[ 3 ];
1249 } **header = (struct header_s **)&extra_data->buffer;
1250
1251 int needed_buffer_size = sizeof (**header) + sizeof (uint8_t[ 3 ][ osd_width ]);
1252
1253 if (extra_data->buffer_size < needed_buffer_size) {
1254
1255 free(extra_data->buffer);
1256 extra_data->buffer = xine_xmalloc(needed_buffer_size);
1257
1258 if (!extra_data->buffer) {
1259 extra_data->buffer_size = 0;
1260 return 0;
1261 }
1262
1263 extra_data->buffer_size = needed_buffer_size;
1264 (*header)->max_width = 0;
1265 }
1266
1267 if ((*header)->id != ME_FOURCC('y', 'u', 'y', '2') || (*header)->max_width < osd_width) {
1268 (*header)->id = ME_FOURCC('y', 'u', 'y', '2');
1269 (*header)->max_width = osd_width;
1270
1271 (*header)->data[ 0 ] = ((uint8_t *)extra_data->buffer) + sizeof (**header);
1272 (*header)->data[ 1 ] = (*header)->data[ 0 ] + osd_width;
1273 (*header)->data[ 2 ] = (*header)->data[ 1 ] + osd_width;
1274 }
1275
1276 return &(*header)->data;
1277}
1278
647void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, 1279void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
648 int dst_width, int dst_height) 1280 int dst_width, int dst_height, int dst_pitch,
1281 alphablend_t *extra_data)
649{ 1282{
1283 int enable_exact_blending = !extra_data->disable_exact_blending;
650 clut_t *my_clut; 1284 clut_t *my_clut;
651 uint8_t *my_trans; 1285 uint8_t *my_trans;
652 1286
653 int src_width = img_overl->width; 1287 int src_width = img_overl->width;
654 int src_height = img_overl->height; 1288 int src_height = img_overl->height;
655 rle_elem_t *rle = img_overl->rle; 1289 rle_elem_t *rle = img_overl->rle;
656 rle_elem_t *rle_limit = rle + img_overl->num_rle; 1290 rle_elem_t *rle_limit = rle + img_overl->num_rle;
657 int x_off = img_overl->x; 1291 int x_off = img_overl->x;
658 int y_off = img_overl->y; 1292 int y_off = img_overl->y;
659 int mask; 1293 int x_odd = x_off & 1;
1294 int ymask;
1295 int rle_this_bite;
1296 int rle_remainder;
1297 int rlelen;
660 int x, y; 1298 int x, y;
661 int l; 1299 int l = 0;
662 int clip_right; 1300 int clip_right;
663 uint32_t yuy2; 1301
1302 union {
1303 uint32_t value;
1304 uint8_t b[4];
1305 uint16_t h[2];
1306 } yuy2;
1307
1308 uint8_t clr = 0;
1309
1310 int any_line_buffered = 0;
1311 int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off));
1312 int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */
1313 uint8_t *(*blend_yuy2_data)[ 3 ] = 0;
664 1314
665 uint8_t *dst_y = dst_img + 2 * (dst_width * y_off + x_off); 1315 uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off;
666 uint8_t *dst; 1316 uint8_t *dst;
667 1317
668 my_clut = (clut_t*) img_overl->clip_color; 1318 my_clut = (clut_t*) img_overl->clip_color;
669 my_trans = img_overl->clip_trans; 1319 my_trans = img_overl->clip_trans;
670 1320
671 /* avoid wraping overlay if drawing to small image */ 1321 /* avoid wraping overlay if drawing to small image */
672 if( (x_off + img_overl->clip_right) < dst_width ) 1322 if( (x_off + img_overl->clip_right) <= dst_width )
673 clip_right = img_overl->clip_right; 1323 clip_right = img_overl->clip_right;
674 else 1324 else
675 clip_right = dst_width - 1 - x_off; 1325 clip_right = dst_width - x_off;
676 1326
677 /* avoid buffer overflow */ 1327 /* avoid buffer overflow */
678 if( (src_height + y_off) >= dst_height ) 1328 if( (src_height + y_off) > dst_height )
679 src_height = dst_height - 1 - y_off; 1329 src_height = dst_height - y_off;
1330
1331 if (src_height <= 0)
1332 return;
1333
1334 if (enable_exact_blending) {
1335 if (exact_blend_width <= 0)
1336 return;
1337
1338 blend_yuy2_data = blend_yuy2_grow_extra_data(extra_data, exact_blend_width_m2);
1339 if (!blend_yuy2_data)
1340 return;
1341
1342 /* make linebuffer transparent */
1343 memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2);
1344 }
680 1345
1346 rlelen=rle_remainder=0;
681 for (y = 0; y < src_height; y++) { 1347 for (y = 0; y < src_height; y++) {
682 mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); 1348 if (rle >= rle_limit)
1349 break;
1350
1351 ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
683 1352
684 dst = dst_y; 1353 dst = dst_y;
685 for (x = 0; x < src_width;) { 1354 for (x = 0; x < src_width;) {
686 uint8_t clr;
687 uint16_t o; 1355 uint16_t o;
688 int rlelen;
689 1356
690 clr = rle->color; 1357 if (rle >= rle_limit)
691 o = my_trans[clr]; 1358 break;
692 rlelen = rle->len; 1359
693 1360 if ((rlelen < 0) || (rle_remainder < 0)) {
694 if (o && mask) { 1361#ifdef LOG_BLEND_YUV
695 /* threat cases where clipping border is inside rle->len pixels */ 1362 printf("alphablend: major bug in blend_yuv < 0\n");
696 if ( img_overl->clip_left > x ) { 1363#endif
697 if( img_overl->clip_left < x + rlelen ) { 1364 }
698 rlelen -= img_overl->clip_left - x; 1365 if (rlelen == 0) {
699 x += img_overl->clip_left - x; 1366 rle_remainder = rlelen = rle->len;
1367 clr = rle->color;
1368 rle++;
1369 }
1370 if (rle_remainder == 0) {
1371 rle_remainder = rlelen;
1372 }
1373 if ((rle_remainder + x) > src_width) {
1374 /* Do something for long rlelengths */
1375 rle_remainder = src_width - x;
1376 }
1377#ifdef LOG_BLEND_YUV
1378 printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x);
1379#endif
1380
1381 if (ymask == 0) {
1382 if (x < img_overl->clip_left) {
1383 /* Starts outside clip area */
1384 if ((x + rle_remainder) > img_overl->clip_left ) {
1385#ifdef LOG_BLEND_YUV
1386 printf("Outside clip left %d, ending inside\n", img_overl->clip_left);
1387#endif
1388 /* Cutting needed, starts outside, ends inside */
1389 rle_this_bite = (img_overl->clip_left - x);
1390 rle_remainder -= rle_this_bite;
1391 rlelen -= rle_this_bite;
1392 my_clut = (clut_t*) img_overl->color;
1393 my_trans = img_overl->trans;
700 } else { 1394 } else {
701 o = 0; 1395#ifdef LOG_BLEND_YUV
1396 printf("Outside clip left %d, ending outside\n", img_overl->clip_left);
1397#endif
1398 /* no cutting needed, starts outside, ends outside */
1399 rle_this_bite = rle_remainder;
1400 rle_remainder = 0;
1401 rlelen -= rle_this_bite;
1402 my_clut = (clut_t*) img_overl->color;
1403 my_trans = img_overl->trans;
702 } 1404 }
703 } else if( clip_right < x + rlelen ) { 1405 } else if (x < clip_right) {
704 if( clip_right > x ) { 1406 /* Starts inside clip area */
705 /* fixme: case not implemented */ 1407 if ((x + rle_remainder) > clip_right ) {
706 o = 0; 1408#ifdef LOG_BLEND_YUV
1409 printf("Inside clip right %d, ending outside\n", clip_right);
1410#endif
1411 /* Cutting needed, starts inside, ends outside */
1412 rle_this_bite = (clip_right - x);
1413 rle_remainder -= rle_this_bite;
1414 rlelen -= rle_this_bite;
1415 my_clut = (clut_t*) img_overl->clip_color;
1416 my_trans = img_overl->clip_trans;
707 } else { 1417 } else {
708 o = 0; 1418#ifdef LOG_BLEND_YUV
1419 printf("Inside clip right %d, ending inside\n", clip_right);
1420#endif
1421 /* no cutting needed, starts inside, ends inside */
1422 rle_this_bite = rle_remainder;
1423 rle_remainder = 0;
1424 rlelen -= rle_this_bite;
1425 my_clut = (clut_t*) img_overl->clip_color;
1426 my_trans = img_overl->clip_trans;
709 } 1427 }
710 } 1428 } else if (x >= clip_right) {
1429 /* Starts outside clip area, ends outsite clip area */
1430 if ((x + rle_remainder ) > src_width ) {
1431#ifdef LOG_BLEND_YUV
1432 printf("Outside clip right %d, ending eol\n", clip_right);
1433#endif
1434 /* Cutting needed, starts outside, ends at right edge */
1435 /* It should never reach here due to the earlier test of src_width */
1436 rle_this_bite = (src_width - x );
1437 rle_remainder -= rle_this_bite;
1438 rlelen -= rle_this_bite;
1439 my_clut = (clut_t*) img_overl->color;
1440 my_trans = img_overl->trans;
1441 } else {
1442 /* no cutting needed, starts outside, ends outside */
1443#ifdef LOG_BLEND_YUV
1444 printf("Outside clip right %d, ending outside\n", clip_right);
1445#endif
1446 rle_this_bite = rle_remainder;
1447 rle_remainder = 0;
1448 rlelen -= rle_this_bite;
1449 my_clut = (clut_t*) img_overl->color;
1450 my_trans = img_overl->trans;
1451 }
1452 }
1453 } else {
1454 /* Outside clip are due to y */
1455 /* no cutting needed, starts outside, ends outside */
1456 rle_this_bite = rle_remainder;
1457 rle_remainder = 0;
1458 rlelen -= rle_this_bite;
1459 my_clut = (clut_t*) img_overl->color;
1460 my_trans = img_overl->trans;
711 } 1461 }
712 1462 o = my_trans[clr];
1463
1464 if (x < (dst_width - x_off)) {
1465 /* clip against right edge of destination area */
1466 if ((x + rle_this_bite) > (dst_width - x_off)) {
1467 int toClip = (x + rle_this_bite) - (dst_width - x_off);
1468
1469 rle_this_bite -= toClip;
1470 rle_remainder += toClip;
1471 rlelen += toClip;
1472 }
1473
1474 if (enable_exact_blending) {
1475 /* remember opacity of current line */
1476 memset(&(*blend_yuy2_data)[ 0 ][ x + x_odd ], o, rle_this_bite);
1477 any_line_buffered = 1;
1478 }
1479
1480 if (o) {
1481 if (!enable_exact_blending) {
1482 l = rle_this_bite>>1;
1483 if( !((x_odd+x) & 1) ) {
1484 yuy2.b[0] = my_clut[clr].y;
1485 yuy2.b[1] = my_clut[clr].cb;
1486 yuy2.b[2] = my_clut[clr].y;
1487 yuy2.b[3] = my_clut[clr].cr;
1488 } else {
1489 yuy2.b[0] = my_clut[clr].y;
1490 yuy2.b[1] = my_clut[clr].cr;
1491 yuy2.b[2] = my_clut[clr].y;
1492 yuy2.b[3] = my_clut[clr].cb;
1493 }
1494 }
1495 if (o >= 15) {
1496 if (!enable_exact_blending) {
1497 while(l--) {
1498 *(uint16_t *)dst = yuy2.h[0];
1499 dst += 2;
1500 *(uint16_t *)dst = yuy2.h[1];
1501 dst += 2;
1502 }
1503 if(rle_this_bite & 1) {
1504 *(uint16_t *)dst = yuy2.h[0];
1505 dst += 2;
1506 }
1507 } else {
1508 l = rle_this_bite;
1509 while (l--) {
1510 *dst = my_clut[clr].y;
1511 dst += 2;
1512 }
1513 }
1514 } else {
1515 if (!enable_exact_blending) {
1516 if( l ) {
1517 mem_blend32(dst, &yuy2.b[0], o, l);
1518 dst += 4*l;
1519 }
1520
1521 if(rle_this_bite & 1) {
1522 *dst = BLEND_BYTE(*dst, yuy2.b[0], o);
1523 dst++;
1524 *dst = BLEND_BYTE(*dst, yuy2.b[1], o);
1525 dst++;
1526 }
1527 } else {
1528 l = rle_this_bite;
1529 while (l--) {
1530 *dst = BLEND_BYTE(*dst, my_clut[clr].y, o);
1531 dst += 2;
1532 }
1533 }
1534 }
713 1535
714 if (o && mask) { 1536 if (enable_exact_blending) {
715 l = rlelen>>1; 1537 /* remember chroma of current line */
716 if( !(x & 1) ) { 1538 memset(&(*blend_yuy2_data)[ 1 ][ x + x_odd ], my_clut[ clr ].cr, rle_this_bite);
717 yuy2 = my_clut[clr].y + (my_clut[clr].cb << 8) + 1539 memset(&(*blend_yuy2_data)[ 2 ][ x + x_odd ], my_clut[ clr ].cb, rle_this_bite);
718 (my_clut[clr].y << 16) + (my_clut[clr].cr << 24); 1540 }
719 } else { 1541 } else {
720 yuy2 = my_clut[clr].y + (my_clut[clr].cr << 8) + 1542 dst += rle_this_bite*2;
721 (my_clut[clr].y << 16) + (my_clut[clr].cb << 24);
722 } 1543 }
1544 }
1545
1546 x += rle_this_bite;
1547 }
1548
1549 if (enable_exact_blending) {
1550 /* blend buffered line */
1551 if (any_line_buffered) {
1552 blend_yuy2_exact(dst_y - x_odd * 2 + 3, dst_y - x_odd * 2 + 1, exact_blend_width, x_odd, blend_yuy2_data);
723 1553
724 if (o >= 15) { 1554 any_line_buffered = 0;
725 while(l--) { 1555 }
726 *((uint32_t *)dst)++ = yuy2; 1556 }
1557
1558 dst_y += dst_pitch;
1559 }
1560}
1561
1562void clear_xx44_palette(xx44_palette_t *p)
1563{
1564 register int i;
1565 register uint32_t *cluts = p->cluts;
1566 register int *ids = p->lookup_cache;
1567
1568 i= p->size;
1569 while(i--)
1570 *cluts++ = 0;
1571 i = 2*OVL_PALETTE_SIZE;
1572 while(i--)
1573 *ids++ = -1;
1574 p->max_used=1;
1575}
1576
1577void init_xx44_palette(xx44_palette_t *p, unsigned num_entries)
1578{
1579 p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries;
1580}
1581
1582void dispose_xx44_palette(xx44_palette_t *p)
1583{
1584}
1585
1586static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p,
1587 unsigned num_xvmc_components, char *xvmc_components)
1588{
1589 const clut_t *color = (const clut_t *) icolor;
1590 int i;
1591 for (i=0; i<num_xvmc_components; ++i) {
1592 switch(xvmc_components[i]) {
1593 case 'V': *palette_p = color->cr; break;
1594 case 'U': *palette_p = color->cb; break;
1595 case 'Y':
1596 default: *palette_p = color->y; break;
1597 }
1598 *palette_p++;
1599 }
1600}
1601
1602
1603void xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette,
1604 unsigned first_xx44_entry, unsigned num_xx44_entries,
1605 unsigned num_xvmc_components, char *xvmc_components)
1606{
1607 register int i;
1608 register const uint32_t *cluts = p->cluts + first_xx44_entry;
1609
1610 for (i=0; i<num_xx44_entries; ++i) {
1611 if ((cluts - p->cluts) < p->size) {
1612 colorToPalette(cluts++, xvmc_palette, num_xvmc_components, xvmc_components);
1613 xvmc_palette += num_xvmc_components;
1614 }
1615 }
1616}
1617
1618static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut)
1619{
1620
1621 register int i;
1622 register uint32_t *cluts = p->cluts;
1623 register int tmp;
1624
1625 if ((tmp = p->lookup_cache[color]) >= 0)
1626 if (cluts[tmp] == clut) return tmp;
1627
1628 for (i=0; i<p->max_used; ++i) {
1629 if (*cluts++ == clut) return p->lookup_cache[color] = i;
1630 }
1631
1632 if (p->max_used == p->size -1) {
1633 printf("video_out: Warning! Out of xx44 palette colors!\n");
1634 return 1;
1635 }
1636 p->cluts[p->max_used] = clut;
1637 return p->lookup_cache[color] = p->max_used++;
1638}
1639
1640static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask)
1641{
1642 register uint8_t masked_val = val & mask;
1643
1644 while(size--) {
1645 if ((*mem & mask) <= masked_val ) *mem = val;
1646 mem++;
1647 }
1648}
1649
1650void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
1651 int dst_width, int dst_height, int dst_pitch,
1652 alphablend_t *extra_data,
1653 xx44_palette_t *palette,int ia44)
1654{
1655 int src_width = img_overl->width;
1656 int src_height = img_overl->height;
1657 rle_elem_t *rle = img_overl->rle;
1658 rle_elem_t *rle_limit = rle + img_overl->num_rle;
1659 int mask;
1660 int x_off = img_overl->x;
1661 int y_off = img_overl->y;
1662 int x, y;
1663 uint8_t norm_pixel,clip_pixel;
1664 uint8_t *dst_y;
1665 uint8_t *dst;
1666 uint8_t alphamask = (ia44) ? 0x0F : 0xF0;
1667 int clip_right;
1668
1669 if (!img_overl)
1670 return;
1671
1672 dst_y = dst_img + dst_pitch*y_off + x_off;
1673
1674 if( (x_off + img_overl->width) <= dst_width )
1675 clip_right = img_overl->width;
1676 else
1677 clip_right = dst_width - x_off;
1678
1679 if ((src_height + y_off) > dst_height)
1680 src_height = dst_height - y_off;
1681
1682 for (y = 0; y < src_height; y++) {
1683
1684 mask = !(y < img_overl->clip_top || y >= img_overl->clip_bottom);
1685 dst = dst_y;
1686
1687 for (x = 0; x < src_width;) {
1688 int len = (x + rle->len > clip_right) ? clip_right - x : rle->len;
1689
1690 if (len > 0) {
1691 norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color,
1692 img_overl->color[rle->color]) << 4) |
1693 (img_overl->trans[rle->color] & 0x0F));
1694 clip_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color+OVL_PALETTE_SIZE,
1695 img_overl->clip_color[rle->color]) << 4) |
1696 (img_overl->clip_trans[rle->color] & 0x0F));
1697 if (!ia44) {
1698 norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4);
1699 clip_pixel = ((clip_pixel & 0x0F) << 4) | ((clip_pixel & 0xF0) >> 4);
1700 }
1701 if (mask) {
1702 if (x < img_overl->clip_left) {
1703 if (x + len <= img_overl->clip_left) {
1704 memblend_xx44(dst,norm_pixel,len, alphamask);
1705 dst += len;
1706 } else {
1707 memblend_xx44(dst,norm_pixel,img_overl->clip_left -x, alphamask);
1708 dst += img_overl->clip_left - x;
1709 len -= img_overl->clip_left - x;
1710 if (len <= img_overl->clip_right - img_overl->clip_left) {
1711 memblend_xx44(dst,clip_pixel,len, alphamask);
1712 dst += len;
1713 } else {
1714 memblend_xx44(dst,clip_pixel,img_overl->clip_right - img_overl->clip_left,
1715 alphamask);
1716 dst += img_overl->clip_right - img_overl->clip_left;
1717 len -= img_overl->clip_right - img_overl->clip_left;
1718 memblend_xx44(dst,norm_pixel,len, alphamask);
1719 dst += len;
1720 }
1721 }
1722 } else if (x < img_overl->clip_right) {
1723 if (len <= img_overl->clip_right - x) {
1724 memblend_xx44(dst,clip_pixel,len, alphamask);
1725 dst += len;
1726 } else {
1727 memblend_xx44(dst,clip_pixel,img_overl->clip_right - x,alphamask);
1728 dst += img_overl->clip_right - x;
1729 len -= img_overl->clip_right - x;
1730 memblend_xx44(dst,norm_pixel,len, alphamask);
1731 dst += len;
1732 }
1733 } else {
1734 memblend_xx44(dst,norm_pixel,len, alphamask);
1735 dst += len;
727 } 1736 }
728 if(rlelen & 1)
729 *((uint16_t *)dst)++ = yuy2 & 0xffff;
730 } else { 1737 } else {
731 if( l ) { 1738 memblend_xx44(dst,norm_pixel,len, alphamask);
732 mem_blend32(dst, (uint8_t *)&yuy2, o, l); 1739 dst += len;
733 dst += 4*l;
734 }
735
736 if(rlelen & 1) {
737 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2), o);
738 dst++;
739 *dst = BLEND_BYTE(*dst, *((uint8_t *)&yuy2+1), o);
740 dst++;
741 }
742 } 1740 }
743 } else {
744 dst += rlelen*2;
745 } 1741 }
746 1742 x += rle->len;
747 x += rlelen;
748 rle++; 1743 rle++;
749 if (rle >= rle_limit) break; 1744 if (rle >= rle_limit) break;
750 } 1745 }
751 if (rle >= rle_limit) break; 1746 if (rle >= rle_limit) break;
1747 dst_y += dst_pitch;
1748 }
1749}
1750
1751static void alphablend_disable_exact_osd_alpha_blending_changed(void *user_data, xine_cfg_entry_t *entry)
1752{
1753 alphablend_t *extra_data = (alphablend_t *)user_data;
1754
1755 extra_data->disable_exact_blending = entry->num_value;
1756}
752 1757
753 dst_y += dst_width*2; 1758void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine)
1759{
1760 config_values_t *config = xine->config;
1761
1762 extra_data->buffer = 0;
1763 extra_data->buffer_size = 0;
1764
1765 extra_data->disable_exact_blending =
1766 config->register_bool(config, "video.output.disable_exact_alphablend", 0,
1767 _("disable exact alpha blending of overlays"),
1768 _("If you experience a performance impact when an On Screen Display or other "
1769 "overlays like DVD subtitles are active, then you might want to enable this option.\n"
1770 "The result is that alpha blending of overlays is less accurate than before, "
1771 "but the CPU usage will be decreased as well."),
1772 10, alphablend_disable_exact_osd_alpha_blending_changed, extra_data);
1773}
1774
1775void _x_alphablend_free(alphablend_t *extra_data)
1776{
1777 if (extra_data->buffer) {
1778 free(extra_data->buffer);
1779 extra_data->buffer = NULL;
754 } 1780 }
1781
1782 extra_data->buffer_size = 0;
755} 1783}
1784
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 @@
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or 7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version. 8 * (at your option) any later version.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * 18 *
19 * The author may be reached as <dent@linuxvideo.org> 19 * The author may be reached as <dent@linuxvideo.org>
20 * 20 *
21 *------------------------------------------------------------ 21 *------------------------------------------------------------
22 * 22 *
23 */ 23 */
24 24
25#ifndef __ALPHABLEND_H__ 25#ifndef __ALPHABLEND_H__
26#define __ALPHABLEND_H__ 26#define __ALPHABLEND_H__
27 27
28#include <xine/video_out.h> 28#include <xine/video_out.h>
29 29
30typedef struct {
31 void *buffer;
32 int buffer_size;
33
34 int disable_exact_blending;
35} alphablend_t;
36
37void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine);
38void _x_alphablend_free(alphablend_t *extra_data);
39
40/* _MSC_VER port changes */
41#undef ATTRIBUTE_PACKED
42#undef PRAGMA_PACK_BEGIN
43#undef PRAGMA_PACK_END
44
45#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) || defined(__ICC)
46#define ATTRIBUTE_PACKED __attribute__ ((packed))
47#define PRAGMA_PACK 0
48#endif
49
50#if !defined(ATTRIBUTE_PACKED)
51#define ATTRIBUTE_PACKED
52#define PRAGMA_PACK 1
53#endif
54
55#if PRAGMA_PACK
56#pragma pack(8)
57#endif
58
30typedef struct { /* CLUT == Color LookUp Table */ 59typedef struct { /* CLUT == Color LookUp Table */
31 uint8_t cb : 8; 60 uint8_t cb : 8;
32 uint8_t cr : 8; 61 uint8_t cr : 8;
33 uint8_t y : 8; 62 uint8_t y : 8;
34 uint8_t foo : 8; 63 uint8_t foo : 8;
35} __attribute__ ((packed)) clut_t; 64} ATTRIBUTE_PACKED clut_t;
65
66
67#if PRAGMA_PACK
68#pragma pack()
69#endif
70
71#define XX44_PALETTE_SIZE 32
72
73typedef struct {
74 unsigned size;
75 unsigned max_used;
76 uint32_t cluts[XX44_PALETTE_SIZE];
77 /* cache palette entries for both colors and clip_colors */
78 int lookup_cache[OVL_PALETTE_SIZE*2];
79} xx44_palette_t;
80
36 81
37void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, 82void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl,
38 int img_width, int img_height, 83 int img_width, int img_height,
39 int dst_width, int dst_height); 84 int dst_width, int dst_height,
85 alphablend_t *extra_data);
40 86
41void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, 87void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl,
42 int img_width, int img_height, 88 int img_width, int img_height,
43 int dst_width, int dst_height); 89 int dst_width, int dst_height,
90 alphablend_t *extra_data);
44 91
45void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, 92void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl,
46 int img_width, int img_height, 93 int img_width, int img_height,
47 int dst_width, int dst_height); 94 int dst_width, int dst_height,
95 alphablend_t *extra_data);
48 96
49void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, 97void blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl,
50 int dst_width, int dst_height); 98 int dst_width, int dst_height, int dst_pitches[3],
99 alphablend_t *extra_data);
51 100
52void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, 101void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
53 int dst_width, int dst_height); 102 int dst_width, int dst_height, int dst_pitch,
103 alphablend_t *extra_data);
104
105/*
106 * This function isn't too smart about blending. We want to avoid creating new
107 * colors in the palette as a result from two non-zero colors needed to be
108 * blended. Instead we choose the color with the highest alpha value to be
109 * visible. Some parts of the code taken from the "VeXP" project.
110 */
111
112void blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl,
113 int dst_width, int dst_height, int dst_pitch,
114 alphablend_t *extra_data,
115 xx44_palette_t *palette,int ia44);
116
117/*
118 * Functions to handle the xine-specific palette.
119 */
120
121void clear_xx44_palette(xx44_palette_t *p);
122void init_xx44_palette(xx44_palette_t *p, unsigned num_entries);
123void dispose_xx44_palette(xx44_palette_t *p);
124
125/*
126 * Convert the xine-specific palette to something useful.
127 */
128
129void xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette,
130 unsigned first_xx44_entry, unsigned num_xx44_entries,
131 unsigned num_xvmc_components, char *xvmc_components);
54 132
55void crop_overlay (vo_overlay_t * overlay);
56 133
57#endif 134#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
28 If not, write to the Free Software Foundation, 28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330, 29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA. 30 Boston, MA 02111-1307, USA.
31 31
32*/ 32*/
33 33
34#include "xinevideowidget.h" 34#include "xinevideowidget.h"
35#include "lib.h" 35#include "lib.h"
36 36
37/* OPIE */ 37/* OPIE */
38#include <opie2/odebug.h> 38#include <opie2/odebug.h>
39#include <qpe/global.h> 39#include <qpe/global.h>
40 40
41/* QT */ 41/* QT */
42#include <qtextstream.h> 42#include <qtextstream.h>
43#include <qdir.h> 43#include <qdir.h>
44#include <qgfx_qws.h> 44#include <qgfx_qws.h>
45 45
46/* STD */ 46/* STD */
47#include <assert.h> 47#include <assert.h>
48#include <unistd.h> 48#include <unistd.h>
49 49
50typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame, 50typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
51 int width, int height,int bytes ); 51 int width, int height,int bytes );
52typedef void (*vo_scale_cb) (void*, int, int, double,
53 int*, int*, int*, int*, double*, int*, int* );
54typedef void (*dest_size_cb) (void*, int, int, double, int*, int*, double*);
55
52 56
53extern "C" { 57extern "C" {
54 xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void * ); 58 xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void *, vo_scale_cb, dest_size_cb );
55 int null_is_showing_video( const xine_vo_driver_t* self ); 59 int null_is_showing_video( const xine_vo_driver_t* self );
56 void null_set_show_video( const xine_vo_driver_t* self, int show ); 60 void null_set_show_video( const xine_vo_driver_t* self, int show );
57 int null_is_fullscreen( const xine_vo_driver_t* self );
58 void null_set_fullscreen( const xine_vo_driver_t* self, int screen );
59 int null_is_scaling( const xine_vo_driver_t* self );
60 void null_set_scaling( const xine_vo_driver_t* self, int scale );
61 void null_set_gui_width( const xine_vo_driver_t* self, int width );
62 void null_set_gui_height( const xine_vo_driver_t* self, int height );
63 void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb ); 61 void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb );
64 void null_set_videoGamma( const xine_vo_driver_t* self , int value );
65 void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data ); 62 void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data );
66
67 void null_preload_decoders( xine_stream_t *stream );
68} 63}
69 64
70using namespace XINE; 65using namespace XINE;
71 66
72Lib::Lib( InitializationMode initMode, XineVideoWidget* widget ) 67Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
73{ 68{
74 m_initialized = false; 69 m_initialized = false;
75 m_duringInitialization = false; 70 m_duringInitialization = false;
76 m_video = false; 71 m_video = false;
77 m_wid = widget; 72 m_wid = widget;
78 printf("Lib"); 73 printf("Lib");
79 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf"; 74 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
80 // get the configuration 75 // get the configuration
81 76
82 // not really OO, should be an extra class, later 77 // not really OO, should be an extra class, later
83 if ( !QFile::exists(configPath) ) { 78 if ( !QFile::exists(configPath) ) {
84 QFile f(configPath); 79 QFile f(configPath);
85 f.open(IO_WriteOnly); 80 f.open(IO_WriteOnly);
86 QTextStream ts( &f ); 81 QTextStream ts( &f );
87 ts << "misc.memcpy_method:glibc\n"; 82 ts << "misc.memcpy_method:glibc\n";
88 ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n"; 83 ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n";
89 ts << "codec.ffmpeg_pp_quality:3\n"; 84 ts << "codec.ffmpeg_pp_quality:3\n";
90 ts << "audio.num_buffers:50\n"; 85 ts << "audio.num_buffers:50\n";
91 ts << "audio.size_buffers:4096\n"; 86 ts << "audio.size_buffers:4096\n";
@@ -106,90 +101,89 @@ Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
106 start(); 101 start();
107} 102}
108 103
109void Lib::run() 104void Lib::run()
110{ 105{
111 odebug << "Lib::run() started" << oendl; 106 odebug << "Lib::run() started" << oendl;
112 initialize(); 107 initialize();
113 m_initialized = true; 108 m_initialized = true;
114 odebug << "Lib::run() finished" << oendl; 109 odebug << "Lib::run() finished" << oendl;
115} 110}
116 111
117void Lib::initialize() 112void Lib::initialize()
118{ 113{
119 m_duringInitialization = true; 114 m_duringInitialization = true;
120 m_xine = xine_new( ); 115 m_xine = xine_new( );
121 116
122 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf"; 117 QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
123 xine_config_load( m_xine, QFile::encodeName( configPath ) ); 118 xine_config_load( m_xine, QFile::encodeName( configPath ) );
124 119
125 xine_init( m_xine ); 120 xine_init( m_xine );
126 121
127 // allocate oss for sound 122 // allocate oss for sound
128 // and fb for framebuffer 123 // and fb for framebuffer
129 m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL ); 124 m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL );
130 m_videoOutput = ::init_video_out_plugin( m_xine, NULL, xine_display_frame, this ); 125 m_videoOutput = ::init_video_out_plugin( m_xine, NULL,
126 xine_display_frame, this,
127 xine_vo_scale_cb,
128 xine_dest_cb );
131 129
132 m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput ); 130 m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
133 xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1); 131 xine_set_param( m_stream, XINE_PARAM_AUDIO_CLOSE_DEVICE, 1);
134 132
135 if (m_wid != 0 ) 133 if (m_wid != 0 )
136 setWidget( m_wid ); 134 setWidget( m_wid );
137 135
138 136
139 m_queue = xine_event_new_queue (m_stream); 137 m_queue = xine_event_new_queue (m_stream);
140 xine_event_create_listener_thread (m_queue, xine_event_handler, this); 138 xine_event_create_listener_thread (m_queue, xine_event_handler, this);
141 139
142 ::null_preload_decoders( m_stream );
143
144 m_duringInitialization = false; 140 m_duringInitialization = false;
145} 141}
146 142
147Lib::~Lib() { 143Lib::~Lib() {
148 assert( isRunning() == false ); 144 assert( isRunning() == false );
149 assert( m_initialized ); 145 assert( m_initialized );
150 146
151// free( m_config ); 147// free( m_config );
152 148
153 xine_close( m_stream ); 149 xine_close( m_stream );
154 xine_event_dispose_queue( m_queue ); 150 xine_event_dispose_queue( m_queue );
155 xine_dispose( m_stream ); 151 xine_dispose( m_stream );
156 xine_close_audio_driver(m_xine,m_audioOutput); 152 xine_close_audio_driver(m_xine,m_audioOutput);
157 xine_close_video_driver(m_xine,m_videoOutput); 153 xine_close_video_driver(m_xine,m_videoOutput);
158 xine_exit( m_xine ); 154 xine_exit( m_xine );
159 155
160 /* FIXME either free or delete but valgrind bitches against both */ 156 /* FIXME either free or delete but valgrind bitches against both */
161 //free( m_videoOutput ); 157 //free( m_videoOutput );
162 //delete m_audioOutput; 158 //delete m_audioOutput;
163} 159}
164 160
165void Lib::resize ( const QSize &s ) { 161void Lib::resize ( const QSize &s ) {
166 assert( m_initialized || m_duringInitialization ); 162 assert( m_initialized || m_duringInitialization );
167 163
168 if ( s. width ( ) && s. height ( ) ) { 164 if ( s. width ( ) && s. height ( ) )
169 ::null_set_gui_width( m_videoOutput, s. width() ); 165 m_videoSize = s;
170 ::null_set_gui_height( m_videoOutput, s. height() );
171 }
172} 166}
173 167
174int Lib::majorVersion() { 168int Lib::majorVersion() {
175 int major, minor, sub; 169 int major, minor, sub;
176 xine_get_version ( &major, &minor, &sub ); 170 xine_get_version ( &major, &minor, &sub );
177 return major; 171 return major;
178} 172}
179 173
180int Lib::minorVersion() { 174int Lib::minorVersion() {
181 int major, minor, sub; 175 int major, minor, sub;
182 xine_get_version ( &major, &minor, &sub ); 176 xine_get_version ( &major, &minor, &sub );
183 return minor; 177 return minor;
184} 178}
185 179
186int Lib::subVersion() { 180int Lib::subVersion() {
187 int major, minor, sub; 181 int major, minor, sub;
188 xine_get_version ( &major, &minor, &sub ); 182 xine_get_version ( &major, &minor, &sub );
189 return sub; 183 return sub;
190} 184}
191 185
192int Lib::setfile(const QString& fileName) 186int Lib::setfile(const QString& fileName)
193{ 187{
194 QString str = fileName.stripWhiteSpace(); 188 QString str = fileName.stripWhiteSpace();
195 189
@@ -401,71 +395,97 @@ void Lib::handleXineEvent( int type, int data, const char* name ) {
401 emit stopped(); 395 emit stopped();
402 }else if ( type == XINE_EVENT_PROGRESS ) { 396 }else if ( type == XINE_EVENT_PROGRESS ) {
403 QString str = name == 0 ? QString::null : QString::fromUtf8( name ); 397 QString str = name == 0 ? QString::null : QString::fromUtf8( name );
404 Global::statusMessage( tr( "Progress: %1 %2" ).arg( name, data ) );; 398 Global::statusMessage( tr( "Progress: %1 %2" ).arg( name, data ) );;
405 } 399 }
406} 400}
407 401
408 402
409void Lib::setShowVideo( bool video ) { 403void Lib::setShowVideo( bool video ) {
410 assert( m_initialized ); 404 assert( m_initialized );
411 405
412 m_video = video; 406 m_video = video;
413 ::null_set_show_video( m_videoOutput, video ); 407 ::null_set_show_video( m_videoOutput, video );
414} 408}
415 409
416bool Lib::isShowingVideo() const { 410bool Lib::isShowingVideo() const {
417 assert( m_initialized ); 411 assert( m_initialized );
418 412
419 return ::null_is_showing_video( m_videoOutput ); 413 return ::null_is_showing_video( m_videoOutput );
420} 414}
421 415
422void Lib::showVideoFullScreen( bool fullScreen ) { 416void Lib::showVideoFullScreen( bool fullScreen ) {
423 assert( m_initialized ); 417 assert( m_initialized );
424 418
425 ::null_set_fullscreen( m_videoOutput, fullScreen ); 419 #warning use xine
426} 420}
427 421
428bool Lib::isVideoFullScreen() const { 422bool Lib::isVideoFullScreen() const {
429 assert( m_initialized ); 423 assert( m_initialized );
430 424
431 return ::null_is_fullscreen( m_videoOutput ); 425 #warning use xine
426 return false;
432} 427}
433 428
434void Lib::setScaling( bool scale ) { 429void Lib::setScaling( bool scale ) {
435 assert( m_initialized ); 430 assert( m_initialized );
436 431
437 ::null_set_scaling( m_videoOutput, scale ); 432 xine_set_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO,
433 scale ? XINE_VO_ASPECT_AUTO : XINE_VO_ASPECT_SQUARE );
438} 434}
439 435
440void Lib::setGamma( int value ) { 436void Lib::setGamma( int value ) {
441 assert( m_initialized ); 437 assert( m_initialized );
442 438 xine_set_param( m_stream, XINE_PARAM_VO_BRIGHTNESS, value );
443 ::null_set_videoGamma( m_videoOutput, value );
444} 439}
445 440
446bool Lib::isScaling() const { 441bool Lib::isScaling() const {
447 assert( m_initialized ); 442 assert( m_initialized );
448 443
449 return ::null_is_scaling( m_videoOutput ); 444 int aratio = xine_get_param( m_stream, XINE_PARAM_VO_ASPECT_RATIO );
445 return aratio == XINE_VO_ASPECT_AUTO;
450} 446}
451 447
452void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) { 448void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) {
453 ( (Lib*)user_data)->handleXineEvent( t ); 449 ( (Lib*)user_data)->handleXineEvent( t );
454} 450}
455 451
456void Lib::xine_display_frame( void* user_data, uint8_t *frame, 452void Lib::xine_display_frame( void* user_data, uint8_t *frame,
457 int width, int height, int bytes ) { 453 int width, int height, int bytes ) {
458 ( (Lib*)user_data)->drawFrame( frame, width, height, bytes ); 454 ( (Lib*)user_data)->drawFrame( frame, width, height, bytes );
459} 455}
460 456
457void Lib::xine_vo_scale_cb( void *user_data, int video_with, int video_height,
458 double video_pixel_aspect,
459 int *dest_x, int *dest_y, int *dest_width,
460 int *dest_height, double *dest_pixel_aspect,
461 int *win_x, int *win_y ) {
462 QSize size = ((Lib*)user_data)->m_videoSize;
463 if (!size.isValid())
464 return;
465
466 *dest_x = 0;
467 *dest_y = 0;
468 *dest_width = size.width();
469 *dest_height = size.height();
470 *win_x = 0;
471 *win_y = 0;
472}
473
474void Lib::xine_dest_cb( void* user_data, int, int, double,
475 int *dest_width, int* dest_height, double* ) {
476 QSize size = ((Lib*)user_data)->m_videoSize;
477 if ( !size.isValid() )
478 return;
479
480 *dest_width = size.width();
481 *dest_height = size.height();
482}
483
461void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) { 484void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) {
462 assert( m_initialized ); 485 assert( m_initialized );
463 486
464 if ( !m_video ) { 487 if ( !m_video )
465 return; 488 return;
466 }
467
468// assert( m_wid );
469 489
470 if (m_wid) m_wid-> setVideoFrame ( frame, width, height, bytes ); 490 if (m_wid) m_wid-> setVideoFrame ( frame, width, height, bytes );
471} 491}
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 {
166 * XINE_ERROR_DEMUXER_FAILED 3 166 * XINE_ERROR_DEMUXER_FAILED 3
167 */ 167 */
168 int error() const; 168 int error() const;
169 169
170 void ensureInitialized(); 170 void ensureInitialized();
171 171
172 void setWidget( XineVideoWidget *widget ); 172 void setWidget( XineVideoWidget *widget );
173 173
174 QSize videoSize()const; 174 QSize videoSize()const;
175 int audioBitrate()const; 175 int audioBitrate()const;
176 int videoBitrate()const; 176 int videoBitrate()const;
177 177
178 signals: 178 signals:
179 179
180 void stopped(); 180 void stopped();
181 181
182 void initialized(); 182 void initialized();
183 183
184 protected: 184 protected:
185 virtual void receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType ); 185 virtual void receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType );
186 186
187 virtual void run(); 187 virtual void run();
188 188
189 private: 189 private:
190 void initialize(); 190 void initialize();
191 191
192 int m_bytes_per_pixel; 192 int m_bytes_per_pixel;
193 bool m_initialized:1; 193 bool m_initialized:1;
194 bool m_duringInitialization:1; 194 bool m_duringInitialization:1;
195 bool m_video:1; 195 bool m_video:1;
196 XineVideoWidget *m_wid; 196 XineVideoWidget *m_wid;
197 xine_t *m_xine; 197 QSize m_videoSize;
198 xine_stream_t *m_stream; 198 xine_t *m_xine;
199 xine_cfg_entry_t *m_config; 199 xine_stream_t *m_stream;
200 xine_vo_driver_t *m_videoOutput; 200 xine_cfg_entry_t *m_config;
201 xine_ao_driver_t* m_audioOutput; 201 xine_vo_driver_t *m_videoOutput;
202 xine_event_queue_t *m_queue; 202 xine_ao_driver_t* m_audioOutput;
203 203 xine_event_queue_t *m_queue;
204 void handleXineEvent( const xine_event_t* t ); 204
205 void handleXineEvent( int type, int data, const char* name ); 205 void handleXineEvent( const xine_event_t* t );
206 void drawFrame( uint8_t* frame, int width, int height, int bytes ); 206 void handleXineEvent( int type, int data, const char* name );
207 void drawFrame( uint8_t* frame, int width, int height, int bytes );
207 // C -> C++ bridge for the event system 208 // C -> C++ bridge for the event system
208 static void xine_event_handler( void* user_data, const xine_event_t* t); 209 static void xine_event_handler( void* user_data, const xine_event_t* t);
209 static void xine_display_frame( void* user_data, uint8_t* frame , 210 static void xine_display_frame( void* user_data, uint8_t* frame ,
210 int width, int height, int bytes ); 211 int width, int height, int bytes );
212 static void xine_vo_scale_cb(void *, int, int, double,
213 int*,int*,int*,int*,double*,int*,int*);
214 static void xine_dest_cb(void*,int,int,double,int*,int*,double*);
211 }; 215 };
212}; 216};
213 217
214 218
215#endif 219#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 @@
1
2#include <stdlib.h>
3#include <stdio.h>
4#include <unistd.h>
5
6#include "lib.h"
7
8int main( int argc, char *argv[] ) {
9 printf("FixME\n");
10 //return 0;
11 XINE::Lib lib;
12 QString str = QString::fromLatin1( argv[1] );
13 lib.play( str );
14 for (;;) sleep( 60 );
15 return 0;
16}
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 @@
1/* 1/*
2                This file is part of the Opie Project 2                This file is part of the Opie Project
3 3
4              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org> 4              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
5 Copyright (c) 2002 LJP <>
6 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org> 5 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
7 Copyright (c) 2002-2003 Miguel Freitas of xine 6 Copyright (c) 2002-2003 Miguel Freitas of xine
8 =. 7 =.
9 .=l. 8 .=l.
10           .>+-= 9           .>+-=
11 _;:,     .>    :=|. This program is free software; you can 10 _;:,     .>    :=|. This program is free software; you can
12.> <`_,   >  .   <= redistribute it and/or modify it under 11.> <`_,   >  .   <= redistribute it and/or modify it under
13:`=1 )Y*s>-.--   : the terms of the GNU General Public 12:`=1 )Y*s>-.--   : the terms of the GNU General Public
14.="- .-=="i,     .._ License as published by the Free Software 13.="- .-=="i,     .._ License as published by the Free Software
15 - .   .-<_>     .<> Foundation; either version 2 of the License, 14 - .   .-<_>     .<> Foundation; either version 2 of the License,
16     ._= =}       : or (at your option) any later version. 15     ._= =}       : or (at your option) any later version.
17    .%`+i>       _;_. 16    .%`+i>       _;_.
18    .i_,=:_.      -<s. This program is distributed in the hope that 17    .i_,=:_.      -<s. This program is distributed in the hope that
19     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
20    : ..    .:,     . . . without even the implied warranty of 19    : ..    .:,     . . . without even the implied warranty of
21    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
22  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU 21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
23..}^=.=       =       ; Library General Public License for more 22..}^=.=       =       ; Library General Public License for more
24++=   -.     .`     .: details. 23++=   -.     .`     .: details.
25 :     =  ...= . :.=- 24 :     =  ...= . :.=-
26 -.   .:....=;==+<; You should have received a copy of the GNU 25 -.   .:....=;==+<; You should have received a copy of the GNU
27  -_. . .   )=.  = Library General Public License along with 26  -_. . .   )=.  = Library General Public License along with
28    --        :-=` this library; see the file COPYING.LIB. 27    --        :-=` this library; see the file COPYING.LIB.
29 If not, write to the Free Software Foundation, 28 If not, write to the Free Software Foundation,
30 Inc., 59 Temple Place - Suite 330, 29 Inc., 59 Temple Place - Suite 330,
31 Boston, MA 02111-1307, USA. 30 Boston, MA 02111-1307, USA.
32 31
33*/ 32*/
34 33
35#include <stdlib.h> 34#include <stdlib.h>
36#include <stdio.h> 35#include <stdio.h>
37 36
38#include <math.h> 37#include <math.h>
39 38
40#include <xine.h> 39#include <xine.h>
41#include <xine/video_out.h> 40#include <xine/video_out.h>
42#include <xine/xine_internal.h> 41#include <xine/xine_internal.h>
43//#include <xine/xineutils.h>
44#include <xine/vo_scale.h> 42#include <xine/vo_scale.h>
45#include <xine/buffer.h> 43#include <xine/buffer.h>
46 44
47#include <pthread.h> 45#include <pthread.h>
48#include "alphablend.h" 46#include "alphablend.h"
49#include "yuv2rgb.h" 47#include "yuv2rgb.h"
50 48
51#define printf(x,...) 49#define printf(x,...)
52 50
53/* 51/*
54#define LOG 52 * #define LOG
55*/ 53 */
56 54
57/* the caller for our event draw handler */ 55/* the caller for our event draw handler */
58typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame, 56typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
59 int width, int height,int bytes ); 57 int width, int height,int bytes );
58typedef void (*vo_scale_cb) (void*, int, int, double,
59 int*, int*, int*, double*, int*, int* );
60typedef void (*dest_size_cb) (void*, int, int, double, int*, int*, double*);
61
60 62
61typedef struct null_driver_s null_driver_t; 63typedef struct null_driver_s null_driver_t;
62 64
63struct null_driver_s { 65struct null_driver_s {
64 vo_driver_t vo_driver; 66 vo_driver_t vo_driver;
65 67
66 uint32_t m_capabilities;
67 int m_show_video; 68 int m_show_video;
68 int m_video_fullscreen; 69 int m_video_fullscreen;
69 int m_is_scaling;
70 70
71 int depth, bpp, bytes_per_pixel; 71 int depth, bpp, bytes_per_pixel;
72 int yuv2rgb_mode; 72 int yuv2rgb_mode;
73 int yuv2rgb_swap; 73 int yuv2rgb_swap;
74 int yuv2rgb_gamma; 74 int yuv2rgb_brightness;
75 uint8_t *yuv2rgb_cmap; 75 uint8_t *yuv2rgb_cmap;
76 yuv2rgb_factory_t *yuv2rgb_factory; 76 yuv2rgb_factory_t *yuv2rgb_factory;
77 77
78 vo_overlay_t *overlay; 78 vo_overlay_t *overlay;
79 vo_scale_t sc; 79 vo_scale_t sc;
80
81 int gui_width;
82 int gui_height;
83 int gui_changed;
84 80
85 double display_ratio; 81 /*
86 void* caller; 82 * DISPLAY to widget...
83 */
87 display_xine_frame_t frameDis; 84 display_xine_frame_t frameDis;
85 void *userData;
86
87 xine_t *xine;
88 alphablend_t alphablend_extra_data;
88}; 89};
89 90
90typedef struct opie_frame_s opie_frame_t; 91typedef struct opie_frame_s opie_frame_t;
91struct opie_frame_s { 92struct opie_frame_s {
92 vo_frame_t frame; 93 vo_frame_t frame;
93 94
94 int format; 95 int format;
95 int flags; 96 int flags;
96 97
97 vo_scale_t sc; 98 vo_scale_t sc;
98 99
99 uint8_t *chunk[3]; 100 uint8_t *chunk[3];
100 101
101 uint8_t *data; /* rgb */ 102 uint8_t *data; /* rgb */
102 int bytes_per_line; 103 int bytes_per_line;
103 104
104 yuv2rgb_t *yuv2rgb; 105 yuv2rgb_t *yuv2rgb;
105 uint8_t *rgb_dst; 106 uint8_t *rgb_dst;
106 int yuv_stride; 107 int yuv_stride;
107 int stripe_height, stripe_inc; 108 int stripe_height, stripe_inc;
108 109
109 null_driver_t *output; 110 null_driver_t *output;
110}; 111};
111 112
112static uint32_t null_get_capabilities( vo_driver_t *self ){ 113static uint32_t null_get_capabilities( vo_driver_t *self ){
113 null_driver_t* this = (null_driver_t*)self; 114 self = self;
114 return this->m_capabilities; 115 return VO_CAP_YUY2 | VO_CAP_YV12;
115} 116}
116 117
117static void null_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { 118static void null_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) {
118 opie_frame_t *frame = (opie_frame_t *) vo_img ; 119 opie_frame_t *frame = (opie_frame_t *) vo_img ;
119 120
120 vo_img->proc_called = 1; 121 vo_img->proc_called = 1;
121 122
122 if (!frame->output->m_show_video) { 123 /*
123 /* printf("nullvideo: no video\n"); */ 124 * drop hard if we don't show the video
125 */
126 if (!frame->output->m_show_video)
127 return;
128
129 if( frame->frame.crop_left || frame->frame.crop_top ||
130 frame->frame.crop_right || frame->frame.crop_bottom )
131 {
132 /* we don't support crop, so don't even waste cpu cycles.
133 * cropping will be performed by video_out.c
134 */
124 return; 135 return;
125 } 136 }
126 137
127 if (frame->format == XINE_IMGFMT_YV12) { 138 if (frame->format == XINE_IMGFMT_YV12) {
128 frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, 139 frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst,
129 src[0], src[1], src[2]); 140 src[0], src[1], src[2]);
130 } else { 141 } else {
131 142
132 frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, 143 frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst,
133 src[0]); 144 src[0]);
134 } 145 }
135 146
136 frame->rgb_dst += frame->stripe_inc; 147 frame->rgb_dst += frame->stripe_inc;
137} 148}
138 149
139static void null_frame_field (vo_frame_t *vo_img, int which_field) { 150static void null_frame_field (vo_frame_t *vo_img, int which_field) {
140 151
141 opie_frame_t *frame = (opie_frame_t *) vo_img ; 152 opie_frame_t *frame = (opie_frame_t *) vo_img ;
142 153
143 switch (which_field) { 154 switch (which_field) {
144 case VO_TOP_FIELD: 155 case VO_TOP_FIELD:
145 frame->rgb_dst = (uint8_t *)frame->data; 156 frame->rgb_dst = frame->data;
146 frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line; 157 frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
147 break; 158 break;
148 case VO_BOTTOM_FIELD: 159 case VO_BOTTOM_FIELD:
149 frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ; 160 frame->rgb_dst = frame->data + frame->bytes_per_line ;
150 frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line; 161 frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
151 break; 162 break;
152 case VO_BOTH_FIELDS: 163 case VO_BOTH_FIELDS:
153 frame->rgb_dst = (uint8_t *)frame->data; 164 frame->rgb_dst = frame->data;
154 break; 165 break;
155 } 166 }
156} 167}
157 168
158 169
159/* take care of the frame*/ 170/* take care of the frame*/
160static void null_frame_dispose( vo_frame_t* vo_img){ 171static void null_frame_dispose( vo_frame_t* vo_img){
161 opie_frame_t* frame = (opie_frame_t*)vo_img; 172 opie_frame_t* frame = (opie_frame_t*)vo_img;
162 173
163 if (frame->data) 174 if (frame->data)
164 free( frame->data ); 175 free( frame->data );
165 free (frame); 176 free (frame);
166} 177}
167 178
168/* end take care of frames*/ 179/* end take care of frames*/
169 180
170static vo_frame_t* null_alloc_frame( vo_driver_t* self ){ 181static vo_frame_t* null_alloc_frame( vo_driver_t* self ){
171 182
172 null_driver_t* this = (null_driver_t*)self; 183 null_driver_t* this = (null_driver_t*)self;
173 opie_frame_t* frame; 184 opie_frame_t* frame;
174 185
175#ifdef LOG 186#ifdef LOG
176 fprintf (stderr, "nullvideo: alloc_frame\n"); 187 fprintf (stderr, "nullvideo: alloc_frame\n");
177#endif 188#endif
178 189
179 frame = (opie_frame_t*)xine_xmalloc ( sizeof(opie_frame_t) ); 190 frame = (opie_frame_t*)xine_xmalloc ( sizeof(opie_frame_t) );
191 if(!frame)
192 return NULL;
180 193
181 memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t)); 194 memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
182 195
183 pthread_mutex_init (&frame->frame.mutex, NULL); 196 pthread_mutex_init (&frame->frame.mutex, NULL);
184 197
185 frame->output = this; 198 frame->output = this;
186 199
187 /* initialize the frame*/ 200 /* initialize the frame*/
188 frame->frame.driver = self; 201 frame->frame.driver = self;
189 frame->frame.proc_slice = null_frame_proc_slice; 202 frame->frame.proc_slice = null_frame_proc_slice;
203 frame->frame.proc_frame = NULL;
190 frame->frame.field = null_frame_field; 204 frame->frame.field = null_frame_field;
191 frame->frame.dispose = null_frame_dispose; 205 frame->frame.dispose = null_frame_dispose;
192 206
193 /* 207 /*
194 * colorspace converter for this frame 208 * colorspace converter for this frame
195 */ 209 */
196 frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); 210 frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);
197 211
198 return (vo_frame_t*) frame; 212 return (vo_frame_t*) frame;
199} 213}
200 214
201 215
202static void null_frame_compute_ideal_size( null_driver_t *this, 216static void null_frame_compute_ideal_size( null_driver_t *this,
203 opie_frame_t *frame ) { 217 opie_frame_t *frame ) {
204 this = this; 218 this = this;
205 219
206 _x_vo_scale_compute_ideal_size(&frame->sc); 220 _x_vo_scale_compute_ideal_size(&frame->sc);
207} 221}
208 222
209static void null_frame_compute_rgb_size( null_driver_t *this, 223static void null_frame_compute_rgb_size( null_driver_t *this,
210 opie_frame_t *frame ){ 224 opie_frame_t *frame ){
211 this = this; 225 this = this;
212 226
213 _x_vo_scale_compute_output_size(&frame->sc); 227 _x_vo_scale_compute_output_size(&frame->sc);
214 228
215 /* avoid problems in yuv2rgb */ 229 /* avoid problems in yuv2rgb */
216 if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4) 230 if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4)
217 frame->sc.output_height = (frame->sc.delivered_height+15) >> 4; 231 frame->sc.output_height = (frame->sc.delivered_height+15) >> 4;
218 232
219 if (frame->sc.output_width < 8) 233 if (frame->sc.output_width < 8)
220 frame->sc.output_width = 8; 234 frame->sc.output_width = 8;
221 235
222 /* yuv2rgb_mlib needs an even YUV2 width */ 236 /* yuv2rgb_mlib needs an even YUV2 width */
223 if (frame->sc.output_width & 1) 237 if (frame->sc.output_width & 1)
224 frame->sc.output_width++; 238 frame->sc.output_width++;
225} 239}
226 240
227static void null_frame_reallocate( null_driver_t *this, opie_frame_t *frame, 241static void null_frame_reallocate( null_driver_t *this, opie_frame_t *frame,
228 uint32_t width, uint32_t height, int format){ 242 uint32_t width, uint32_t height, int format){
229 /* 243 /*
230 * (re-) allocate 244 * (re-) allocate
231 */ 245 */
232 if( frame->data ) { 246 if( frame->chunk[0] ){
233 if( frame->chunk[0] ){ 247 free( frame->chunk[0] );
234 free( frame->chunk[0] ); 248 frame->chunk[0] = NULL;
235 frame->chunk[0] = NULL; 249 }
236 } 250 if( frame->chunk[1] ){
237 if( frame->chunk[1] ){ 251 free ( frame->chunk[1] );
238 free ( frame->chunk[1] ); 252 frame->chunk[1] = NULL;
239 frame->chunk[1] = NULL;
240 }
241 if( frame->chunk[2] ){
242 free ( frame->chunk[2] );
243 frame->chunk[2] = NULL;
244 }
245 free ( frame->data );
246 } 253 }
254 if( frame->chunk[2] ){
255 free ( frame->chunk[2] );
256 frame->chunk[2] = NULL;
257 }
258 if(frame->data)
259 free ( frame->data );
247 260
248 frame->data = xine_xmalloc (frame->sc.output_width 261 frame->data = xine_xmalloc (frame->sc.output_width
249 * frame->sc.output_height 262 * frame->sc.output_height
250 * this->bytes_per_pixel ); 263 * this->bytes_per_pixel );
251 264
252 if( format == XINE_IMGFMT_YV12 ) { 265 if( format == XINE_IMGFMT_YV12 ) {
253 frame->frame.pitches[0] = 8*((width + 7) / 8); 266 frame->frame.pitches[0] = 8*((width + 7) / 8);
254 frame->frame.pitches[1] = 8*((width + 15) / 16); 267 frame->frame.pitches[1] = 8*((width + 15) / 16);
255 frame->frame.pitches[2] = 8*((width + 15) / 16); 268 frame->frame.pitches[2] = 8*((width + 15) / 16);
256 frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,(void **)&frame->chunk[0]); 269 frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,(void **)&frame->chunk[0]);
257 frame->frame.base[1] = xine_xmalloc_aligned (16, frame->frame.pitches[1] * ((height+ 1)/2), (void **)&frame->chunk[1]); 270 frame->frame.base[1] = xine_xmalloc_aligned (16, frame->frame.pitches[1] * ((height+ 1)/2), (void **)&frame->chunk[1]);
258 frame->frame.base[2] = xine_xmalloc_aligned (16, frame->frame.pitches[2] * ((height+ 1)/2), (void **)&frame->chunk[2]); 271 frame->frame.base[2] = xine_xmalloc_aligned (16, frame->frame.pitches[2] * ((height+ 1)/2), (void **)&frame->chunk[2]);
259 272
260 }else{ 273 }else{
261 frame->frame.pitches[0] = 8*((width + 3) / 4); 274 frame->frame.pitches[0] = 8*((width + 3) / 4);
262 275
263 frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height, 276 frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,
264 (void **)&frame->chunk[0]); 277 (void **)&frame->chunk[0]);
265 frame->chunk[1] = NULL; 278 frame->chunk[1] = NULL;
266 frame->chunk[2] = NULL; 279 frame->chunk[2] = NULL;
267 } 280 }
268 281
269} 282}
270 283
271static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) { 284static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) {
272 switch (flags) { 285 switch (flags) {
@@ -280,135 +293,140 @@ static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) {
280 frame->sc.output_width, 293 frame->sc.output_width,
281 frame->stripe_height, 294 frame->stripe_height,
282 frame->bytes_per_line*2); 295 frame->bytes_per_line*2);
283 frame->yuv_stride = frame->bytes_per_line*2; 296 frame->yuv_stride = frame->bytes_per_line*2;
284 break; 297 break;
285 case VO_BOTH_FIELDS: 298 case VO_BOTH_FIELDS:
286 frame->yuv2rgb->configure (frame->yuv2rgb, 299 frame->yuv2rgb->configure (frame->yuv2rgb,
287 frame->sc.delivered_width, 300 frame->sc.delivered_width,
288 16, 301 16,
289 frame->frame.pitches[0], 302 frame->frame.pitches[0],
290 frame->frame.pitches[1], 303 frame->frame.pitches[1],
291 frame->sc.output_width, 304 frame->sc.output_width,
292 frame->stripe_height, 305 frame->stripe_height,
293 frame->bytes_per_line); 306 frame->bytes_per_line);
294 frame->yuv_stride = frame->bytes_per_line; 307 frame->yuv_stride = frame->bytes_per_line;
295 break; 308 break;
296 } 309 }
297#ifdef LOG 310#ifdef LOG
298 fprintf (stderr, "nullvideo: colorspace converter configured.\n"); 311 fprintf (stderr, "nullvideo: colorspace converter configured.\n");
299#endif 312#endif
300} 313}
301 314
302static void null_update_frame_format( vo_driver_t* self, vo_frame_t* img, 315static void null_update_frame_format( vo_driver_t* self, vo_frame_t* img,
303 uint32_t width, uint32_t height, 316 uint32_t width, uint32_t height,
304 double ratio_code, int format, 317 double ratio_code, int format,
305 int flags ){ 318 int flags ){
306 null_driver_t* this = (null_driver_t*) self; 319 null_driver_t* this = (null_driver_t*) self;
307 opie_frame_t* frame = (opie_frame_t*)img; 320 opie_frame_t* frame = (opie_frame_t*)img;
308 321
309#ifdef LOG 322#ifdef LOG
310 fprintf (stderr, "nullvideo: update_frame_format\n"); 323 fprintf (stderr, "nullvideo: update_frame_format\n");
311#endif 324#endif
312 325
326 int gui_width = 0;
327 int gui_height = 0;
328 double gui_pixel_aspect = 0.0;
329
313 flags &= VO_BOTH_FIELDS; 330 flags &= VO_BOTH_FIELDS;
314 331
315 /* find out if we need to adapt this frame */ 332 frame->sc.dest_size_cb(frame->sc.user_data, width, height,
333 frame->sc.video_pixel_aspect,
334 &gui_width, &gui_height, &gui_pixel_aspect);
316 335
336 /* find out if we need to adapt this frame */
317 if ((width != frame->sc.delivered_width) 337 if ((width != frame->sc.delivered_width)
318 || (height != frame->sc.delivered_height) 338 || (height != frame->sc.delivered_height)
319 || (ratio_code != frame->sc.delivered_ratio) 339 || (ratio_code != frame->sc.delivered_ratio)
320 || (flags != frame->flags) 340 || (flags != frame->flags)
321 || (format != frame->format) 341 || (format != frame->format)
322 || (this->sc.user_ratio != frame->sc.user_ratio) 342 || (this->sc.user_ratio != frame->sc.user_ratio)
323 || (this->gui_width != frame->sc.gui_width) 343 || (gui_width != frame->sc.gui_width)
324 || (this->gui_height != frame->sc.gui_height)) { 344 || (gui_height != frame->sc.gui_height)) {
325
326 frame->sc.delivered_width = width; 345 frame->sc.delivered_width = width;
327 frame->sc.delivered_height = height; 346 frame->sc.delivered_height = height;
328 frame->sc.delivered_ratio = ratio_code; 347 frame->sc.delivered_ratio = ratio_code;
329 frame->flags = flags; 348 frame->flags = flags;
330 frame->format = format; 349 frame->format = format;
331 frame->sc.user_ratio = this->sc.user_ratio; 350 frame->sc.user_ratio = this->sc.user_ratio;
332 frame->sc.gui_width = this->gui_width; 351 frame->sc.gui_width = gui_width;
333 frame->sc.gui_height = this->gui_height; 352 frame->sc.gui_height = gui_height;
334 frame->sc.gui_pixel_aspect = 1.0;
335 353
336 354
337 null_frame_compute_ideal_size(this, frame); 355 null_frame_compute_ideal_size(this, frame);
338 null_frame_compute_rgb_size(this, frame); 356 null_frame_compute_rgb_size(this, frame);
339 null_frame_reallocate(this, frame, width, height, format); 357 null_frame_reallocate(this, frame, width, height, format);
340 358
341#ifdef LOG 359#ifdef LOG
342 fprintf (stderr, "nullvideo: gui %dx%d delivered %dx%d output %dx%d\n", 360 fprintf (stderr, "nullvideo: gui %dx%d delivered %dx%d output %dx%d\n",
343 frame->sc.gui_width, frame->sc.gui_height, 361 frame->sc.gui_width, frame->sc.gui_height,
344 frame->sc.delivered_width, frame->sc.delivered_height, 362 frame->sc.delivered_width, frame->sc.delivered_height,
345 frame->sc.output_width, frame->sc.output_height); 363 frame->sc.output_width, frame->sc.output_height);
346#endif 364#endif
347 365
348 366
349 367
350 frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height; 368 frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height;
351 frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel; 369 frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel;
352 370
353 /* 371 /*
354 * set up colorspace converter 372 * set up colorspace converter
355 */ 373 */
356 null_setup_colorspace_converter(frame, flags); 374 null_setup_colorspace_converter(frame, flags);
357 375
358 } 376 }
359 /* 377 /*
360 * reset dest pointers 378 * reset dest pointers
361 */ 379 */
362 380
363 if (frame->data) { 381 if (frame->data) {
364 switch (flags) { 382 switch (flags) {
365 case VO_TOP_FIELD: 383 case VO_TOP_FIELD:
366 frame->rgb_dst = (uint8_t *)frame->data; 384 frame->rgb_dst = frame->data;
367 frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line; 385 frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
368 break; 386 break;
369 case VO_BOTTOM_FIELD: 387 case VO_BOTTOM_FIELD:
370 frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ; 388 frame->rgb_dst = frame->data + frame->bytes_per_line ;
371 frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line; 389 frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
372 break; 390 break;
373 case VO_BOTH_FIELDS: 391 case VO_BOTH_FIELDS:
374 frame->rgb_dst = (uint8_t *)frame->data; 392 frame->rgb_dst = frame->data;
375 frame->stripe_inc = frame->stripe_height * frame->bytes_per_line; 393 frame->stripe_inc = frame->stripe_height * frame->bytes_per_line;
376 break; 394 break;
377 } 395 }
378 } 396 }
379} 397}
380 398
381static void null_display_frame( vo_driver_t* self, vo_frame_t *frame_gen ){ 399static void null_display_frame( vo_driver_t* self, vo_frame_t *frame_gen ){
382 null_driver_t* this = (null_driver_t*) self; 400 null_driver_t* this = (null_driver_t*) self;
383 opie_frame_t* frame = (opie_frame_t*)frame_gen; 401 opie_frame_t* frame = (opie_frame_t*)frame_gen;
384 display_xine_frame_t display = this->frameDis; 402 display_xine_frame_t display = this->frameDis;
385 403
386 if (!this->m_show_video) 404 if (!this->m_show_video)
387 return; 405 return;
388 406
389 if( display != NULL ) { 407 if( display != NULL ) {
390 (*display)(this->caller, frame->data, 408 (*display)(this->userData, frame->data,
391 frame->sc.output_width, frame->sc.output_height, 409 frame->sc.output_width, frame->sc.output_height,
392 frame->bytes_per_line ); 410 frame->bytes_per_line );
393 } 411 }
394 412
395 frame->frame.free(&frame->frame); 413 frame->frame.free(&frame->frame);
396} 414}
397 415
398 416
399/* blending related */ 417/* blending related */
400static void null_overlay_clut_yuv2rgb (null_driver_t *this, 418static void null_overlay_clut_yuv2rgb (null_driver_t *this,
401 vo_overlay_t *overlay, 419 vo_overlay_t *overlay,
402 opie_frame_t *frame) { 420 opie_frame_t *frame) {
403 this = this; 421 this = this;
404 422
405 423
406 int i; 424 int i;
407 clut_t* clut = (clut_t*) overlay->color; 425 clut_t* clut = (clut_t*) overlay->color;
408 if (!overlay->rgb_clut) { 426 if (!overlay->rgb_clut) {
409 for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { 427 for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
410 *((uint32_t *)&clut[i]) = 428 *((uint32_t *)&clut[i]) =
411 frame->yuv2rgb-> 429 frame->yuv2rgb->
412 yuv2rgb_single_pixel_fun (frame->yuv2rgb, 430 yuv2rgb_single_pixel_fun (frame->yuv2rgb,
413 clut[i].y, clut[i].cb, 431 clut[i].y, clut[i].cb,
414 clut[i].cr); 432 clut[i].cr);
@@ -421,315 +439,257 @@ static void null_overlay_clut_yuv2rgb (null_driver_t *this,
421 *((uint32_t *)&clut[i]) = 439 *((uint32_t *)&clut[i]) =
422 frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, 440 frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb,
423 clut[i].y, clut[i].cb, clut[i].cr); 441 clut[i].y, clut[i].cb, clut[i].cr);
424 } 442 }
425 overlay->clip_rgb_clut++; 443 overlay->clip_rgb_clut++;
426 } 444 }
427} 445}
428 446
429static void null_overlay_blend ( vo_driver_t *this_gen, vo_frame_t *frame_gen, 447static void null_overlay_blend ( vo_driver_t *this_gen, vo_frame_t *frame_gen,
430 vo_overlay_t *overlay) { 448 vo_overlay_t *overlay) {
431 null_driver_t *this = (null_driver_t *) this_gen; 449 null_driver_t *this = (null_driver_t *) this_gen;
432 opie_frame_t *frame = (opie_frame_t *) frame_gen; 450 opie_frame_t *frame = (opie_frame_t *) frame_gen;
433 451
434 if(!this->m_show_video || frame->sc.output_width == 0 452 if(!this->m_show_video || frame->sc.output_width == 0
435 || frame->sc.output_height== 0) 453 || frame->sc.output_height== 0)
436 return; 454 return;
437 455
438 /* Alpha Blend here */ 456 /* Alpha Blend here */
439 if (overlay->rle) { 457 if (overlay->rle) {
440 if( !overlay->rgb_clut || !overlay->clip_rgb_clut) 458 if( !overlay->rgb_clut || !overlay->clip_rgb_clut)
441 null_overlay_clut_yuv2rgb(this,overlay,frame); 459 null_overlay_clut_yuv2rgb(this,overlay,frame);
442 460
443 switch(this->bpp) { 461 switch(this->bpp) {
444 case 16: 462 case 16:
445 blend_rgb16((uint8_t *)frame->data, 463 blend_rgb16(frame->data,
446 overlay, 464 overlay,
447 frame->sc.output_width, 465 frame->sc.output_width,
448 frame->sc.output_height, 466 frame->sc.output_height,
449 frame->sc.delivered_width, 467 frame->sc.delivered_width,
450 frame->sc.delivered_height); 468 frame->sc.delivered_height,
469 &this->alphablend_extra_data);
451 break; 470 break;
452 case 24: 471 case 24:
453 blend_rgb24((uint8_t *)frame->data, 472 blend_rgb24(frame->data,
454 overlay, 473 overlay,
455 frame->sc.output_width, 474 frame->sc.output_width,
456 frame->sc.output_height, 475 frame->sc.output_height,
457 frame->sc.delivered_width, 476 frame->sc.delivered_width,
458 frame->sc.delivered_height); 477 frame->sc.delivered_height,
478 &this->alphablend_extra_data);
459 break; 479 break;
460 case 32: 480 case 32:
461 blend_rgb32((uint8_t *)frame->data, 481 blend_rgb32(frame->data,
462 overlay, 482 overlay,
463 frame->sc.output_width, 483 frame->sc.output_width,
464 frame->sc.output_height, 484 frame->sc.output_height,
465 frame->sc.delivered_width, 485 frame->sc.delivered_width,
466 frame->sc.delivered_height); 486 frame->sc.delivered_height,
487 &this->alphablend_extra_data);
467 break; 488 break;
468 default: 489 default:
469 /* It should never get here */ 490 /* It should never get here */
470 break; 491 break;
471 } 492 }
472 } 493 }
473} 494}
474 495
475 496
476static int null_get_property( vo_driver_t* self, int property ){ 497static int null_get_property( vo_driver_t* self, int property ){
477#if 0
478 null_driver_t *this = (null_driver_t *)self; 498 null_driver_t *this = (null_driver_t *)self;
479 499
480 switch(property) 500 switch(property)
481 { 501 {
482 case VO_PROP_ASPECT_RATIO: 502 case VO_PROP_ASPECT_RATIO:
483 return this->sc.user_ratio; 503 return this->sc.user_ratio;
484 case VO_PROP_BRIGHTNESS: 504 case VO_PROP_BRIGHTNESS:
485 return this->yuv2rgb_brightness; 505 return this->yuv2rgb_brightness;
486 case VO_PROP_WINDOW_WIDTH: 506 case VO_PROP_WINDOW_WIDTH:
487 return this->sc.gui_width; 507 return this->sc.gui_width;
488 case VO_PROP_WINDOW_HEIGHT: 508 case VO_PROP_WINDOW_HEIGHT:
489 return this->sc.gui_height; 509 return this->sc.gui_height;
490 default: 510 default:
491 break; 511 break;
492 } 512 }
493#else
494 property = property;
495 self = self;
496#endif
497 513
498 return 0; 514 return 0;
499} 515}
500static int null_set_property( vo_driver_t* self, int property, 516static int null_set_property( vo_driver_t* self, int property,
501 int value ){ 517 int value ){
502#if 0
503 null_driver_t *this = (null_driver_t *)self; 518 null_driver_t *this = (null_driver_t *)self;
504 519
505 switch(property) 520 switch(property)
506 { 521 {
507 case VO_PROP_ASPECT_RATIO: 522 case VO_PROP_ASPECT_RATIO:
508 if(value>=XINE_VO_ASPECT_NUM_RATIOS) 523 if(value>=XINE_VO_ASPECT_NUM_RATIOS)
509 value = XINE_VO_ASPECT_AUTO; 524 value = XINE_VO_ASPECT_AUTO;
510 this->sc.user_ratio = value; 525 this->sc.user_ratio = value;
511 break; 526 break;
512 case VO_PROP_BRIGHTNESS: 527 case VO_PROP_BRIGHTNESS:
513 this->yuv2rgb_brightness = value; 528 this->yuv2rgb_brightness = value;
514 this->yuv2rgb_factory-> 529 this->yuv2rgb_factory->
515 set_csc_levels(this->yuv2rgb_factory, value, 128, 128); 530 set_csc_levels(this->yuv2rgb_factory, value, 128, 128);
516 break; 531 break;
517 default: 532 default:
518 break; 533 break;
519 } 534 }
520#else
521 self = self;
522 property = property;
523#endif
524 535
525 return value; 536 return value;
526} 537}
527static void null_get_property_min_max( vo_driver_t* self, 538static void null_get_property_min_max( vo_driver_t* self,
528 int property, int *min, 539 int property, int *min,
529 int *max ){ 540 int *max ){
530 self = self; 541 if(property == VO_PROP_BRIGHTNESS) {
531 property = property; 542 *min = -100;
532 543 *max = +100;
533 *max = 0; 544 }else {
534 *min = 0; 545 *min = 0;
546 *max = 0;
547 }
535} 548}
536static int null_gui_data_exchange( vo_driver_t* self, 549static int null_gui_data_exchange( vo_driver_t* self,
537 int data_type, 550 int data_type,
538 void *data ){ 551 void *data ){
539 self = self;
540 data_type = data_type;
541 data = data;
542
543 return 0; 552 return 0;
544} 553}
545 554
546static void null_dispose ( vo_driver_t* self ){ 555static void null_dispose ( vo_driver_t* self ){
547 null_driver_t* this = (null_driver_t*)self; 556 null_driver_t* this = (null_driver_t*)self;
557 _x_alphablend_free(&this->alphablend_extra_data);
548 free ( this ); 558 free ( this );
549} 559}
550static int null_redraw_needed( vo_driver_t* self ){ 560static int null_redraw_needed( vo_driver_t* self ){
551 self = self; 561 null_driver_t *this = (null_driver_t*)self;
552 562 return _x_vo_scale_redraw_needed(&this->sc);
553 return 0;
554} 563}
555 564
556 565
557xine_video_port_t* init_video_out_plugin( xine_t *xine, 566xine_video_port_t* init_video_out_plugin( xine_t *xine,
558 void* video, 567 void* video,
559 display_xine_frame_t frameDisplayFunc, 568 display_xine_frame_t frameDisplayFunc,
560 void *userData ){ 569 void *userData, vo_scale_cb frame_cb,
561 video = video; 570 dest_size_cb dest_cb) {
562
563
564 null_driver_t *vo; 571 null_driver_t *vo;
565 vo = (null_driver_t*)malloc( sizeof(null_driver_t ) ); 572 vo = (null_driver_t*)xine_xmalloc(sizeof(null_driver_t ));
566 573 vo->xine = xine;
567 /* memset? */
568 memset(vo,0, sizeof(null_driver_t ) );
569 574
575 _x_alphablend_init(&vo->alphablend_extra_data, xine);
570 _x_vo_scale_init (&vo->sc, 0, 0, xine->config); 576 _x_vo_scale_init (&vo->sc, 0, 0, xine->config);
577 vo->sc.gui_width = 18;
578 vo->sc.gui_height = 6;
579 vo->sc.user_ratio = XINE_VO_ASPECT_AUTO;
580 vo->sc.user_data = userData;
581 vo->sc.frame_output_cb = frame_cb;
582 vo->sc.dest_size_cb = dest_cb;
571 583
572 vo->sc.gui_pixel_aspect = 1.0;
573 584
574 vo->m_show_video = 0; // false 585 vo->m_show_video = 0; // false
575 vo->m_video_fullscreen = 0;
576 vo->m_is_scaling = 0;
577 vo->display_ratio = 1.0;
578 vo->gui_width = 16;
579 vo->gui_height = 8;
580 vo->frameDis = NULL;
581 586
582 /* install callback handlers*/ 587 /* install callback handlers*/
583 vo->vo_driver.get_capabilities = null_get_capabilities; 588 vo->vo_driver.get_capabilities = null_get_capabilities;
584 vo->vo_driver.alloc_frame = null_alloc_frame; 589 vo->vo_driver.alloc_frame = null_alloc_frame;
585 vo->vo_driver.update_frame_format = null_update_frame_format; 590 vo->vo_driver.update_frame_format = null_update_frame_format;
586 vo->vo_driver.display_frame = null_display_frame; 591 vo->vo_driver.display_frame = null_display_frame;
587 vo->vo_driver.overlay_blend = null_overlay_blend; 592 vo->vo_driver.overlay_begin = 0;
588 vo->vo_driver.get_property = null_get_property; 593 vo->vo_driver.overlay_blend = null_overlay_blend;
589 vo->vo_driver.set_property = null_set_property; 594 vo->vo_driver.overlay_end = 0;
590 vo->vo_driver.get_property_min_max = null_get_property_min_max; 595 vo->vo_driver.get_property = null_get_property;
591 vo->vo_driver.gui_data_exchange = null_gui_data_exchange; 596 vo->vo_driver.set_property = null_set_property;
592 vo->vo_driver.dispose = null_dispose; 597 vo->vo_driver.get_property_min_max= null_get_property_min_max;
593 vo->vo_driver.redraw_needed = null_redraw_needed; 598 vo->vo_driver.gui_data_exchange = null_gui_data_exchange;
594 599 vo->vo_driver.dispose = null_dispose;
600 vo->vo_driver.redraw_needed = null_redraw_needed;
595 601
596 /* capabilities */ 602 /* capabilities */
597 vo->m_capabilities = VO_CAP_YUY2 | VO_CAP_YV12; 603 vo->yuv2rgb_mode = MODE_16_RGB;
598 vo->yuv2rgb_factory = yuv2rgb_factory_init (MODE_16_RGB, vo->yuv2rgb_swap, 604 vo->yuv2rgb_brightness = 0;
605 vo->yuv2rgb_factory = yuv2rgb_factory_init (vo->yuv2rgb_mode,
606 vo->yuv2rgb_swap,
599 vo->yuv2rgb_cmap); 607 vo->yuv2rgb_cmap);
608 vo->yuv2rgb_factory->set_csc_levels(vo->yuv2rgb_factory,
609 vo->yuv2rgb_brightness,
610 128,128);
600 611
601 vo->caller = userData; 612 vo->userData = userData;
602 vo->frameDis = frameDisplayFunc; 613 vo->frameDis = frameDisplayFunc;
603 614
604 return _x_vo_new_port(xine, &vo->vo_driver, 0); 615 return _x_vo_new_port(xine, &vo->vo_driver, 0);
605} 616}
606 617
607 618
608/* this is special for this device */ 619/* this is special for this device */
609/** 620/**
610 * We know that we will be controled by the XINE LIB++ 621 * We know that we will be controled by the XINE LIB++
611 */ 622 */
612 623
613/** 624/**
614 * 625 *
615 */ 626 */
616int null_is_showing_video( xine_vo_driver_t* self ){ 627int null_is_showing_video( xine_vo_driver_t* self ){
617 null_driver_t* this = (null_driver_t*)self->driver; 628 null_driver_t* this = (null_driver_t*)self->driver;
618 return this->m_show_video; 629 return this->m_show_video;
619} 630}
620void null_set_show_video( xine_vo_driver_t* self, int show ) { 631void null_set_show_video( xine_vo_driver_t* self, int show ) {
621 ((null_driver_t*)self->driver)->m_show_video = show; 632 ((null_driver_t*)self->driver)->m_show_video = show;
622} 633}
623 634
624int null_is_fullscreen( xine_vo_driver_t* self ){
625 return ((null_driver_t*)self->driver)->m_video_fullscreen;
626}
627void null_set_fullscreen( xine_vo_driver_t* self, int screen ){
628 ((null_driver_t*)self->driver)->m_video_fullscreen = screen;
629}
630int null_is_scaling( xine_vo_driver_t* self ){
631 return ((null_driver_t*)self->driver)->m_is_scaling;
632}
633
634void null_set_videoGamma( xine_vo_driver_t* self , int value ) {
635 ((null_driver_t*) self->driver) ->yuv2rgb_gamma = value;
636 ((null_driver_t*) self->driver) ->yuv2rgb_factory->set_gamma( ((null_driver_t*) self->driver) ->yuv2rgb_factory, value );
637}
638
639void null_set_scaling( xine_vo_driver_t* self, int scale ) {
640 ((null_driver_t*)self->driver)->m_is_scaling = scale;
641}
642
643void null_set_gui_width( xine_vo_driver_t* self, int width ) {
644 ((null_driver_t*)self->driver)->gui_width = width;
645}
646void null_set_gui_height( xine_vo_driver_t* self, int height ) {
647 ((null_driver_t*)self->driver)->gui_height = height;
648}
649 635
650 636
651void null_set_mode( xine_vo_driver_t* self, int depth, int rgb ) { 637void null_set_mode( xine_vo_driver_t* self, int depth, int rgb ) {
652 null_driver_t* this = (null_driver_t*)self->driver; 638 null_driver_t* this = (null_driver_t*)self->driver;
653 639
654 this->bytes_per_pixel = (depth + 7 ) / 8; 640 this->bytes_per_pixel = (depth + 7 ) / 8;
655 this->bpp = this->bytes_per_pixel * 8; 641 this->bpp = this->bytes_per_pixel * 8;
656 this->depth = depth; 642 this->depth = depth;
657 643
658 switch ( this->depth ) { 644 switch ( this->depth ) {
659 case 32: 645 case 32:
660 if( rgb == 0 ) 646 if( rgb == 0 )
661 this->yuv2rgb_mode = MODE_32_RGB; 647 this->yuv2rgb_mode = MODE_32_RGB;
662 else 648 else
663 this->yuv2rgb_mode = MODE_32_BGR; 649 this->yuv2rgb_mode = MODE_32_BGR;
664 case 24: 650 case 24:
665 if( this->bpp == 32 ) { 651 if( this->bpp == 32 ) {
666 if( rgb == 0 ) { 652 if( rgb == 0 ) {
667 this->yuv2rgb_mode = MODE_32_RGB; 653 this->yuv2rgb_mode = MODE_32_RGB;
668 } else { 654 } else {
669 this->yuv2rgb_mode = MODE_32_BGR; 655 this->yuv2rgb_mode = MODE_32_BGR;
670 } 656 }
671 }else{ 657 }else{
672 if( rgb == 0 ) 658 if( rgb == 0 )
673 this->yuv2rgb_mode = MODE_24_RGB; 659 this->yuv2rgb_mode = MODE_24_RGB;
674 else 660 else
675 this->yuv2rgb_mode = MODE_24_BGR; 661 this->yuv2rgb_mode = MODE_24_BGR;
676 }; 662 };
677 break; 663 break;
678 case 16: 664 case 16:
679 if( rgb == 0 ) { 665 if( rgb == 0 ) {
680 this->yuv2rgb_mode = MODE_16_RGB; 666 this->yuv2rgb_mode = MODE_16_RGB;
681 } else { 667 } else {
682 this->yuv2rgb_mode = MODE_16_BGR; 668 this->yuv2rgb_mode = MODE_16_BGR;
683 } 669 }
684 break; 670 break;
685 case 15: 671 case 15:
686 if( rgb == 0 ) { 672 if( rgb == 0 ) {
687 this->yuv2rgb_mode = MODE_15_RGB; 673 this->yuv2rgb_mode = MODE_15_RGB;
688 } else { 674 } else {
689 this->yuv2rgb_mode = MODE_15_BGR; 675 this->yuv2rgb_mode = MODE_15_BGR;
690 } 676 }
691 break; 677 break;
692 case 8: 678 case 8:
693 if( rgb == 0 ) { 679 if( rgb == 0 ) {
694 this->yuv2rgb_mode = MODE_8_RGB; 680 this->yuv2rgb_mode = MODE_8_RGB;
695 } else { 681 } else {
696 this->yuv2rgb_mode = MODE_8_BGR; 682 this->yuv2rgb_mode = MODE_8_BGR;
697 } 683 }
698 break; 684 break;
699 }; 685 };
700 //free(this->yuv2rgb_factory );
701 // this->yuv2rgb_factory = yuv2rgb_factory_init (this->yuv2rgb_mode, this->yuv2rgb_swap,
702 // this->yuv2rgb_cmap);
703}; 686};
704 687
705void null_display_handler( xine_vo_driver_t* self, display_xine_frame_t t, 688void null_display_handler( xine_vo_driver_t* self, display_xine_frame_t t,
706 void* user_data ) { 689 void* user_data ) {
707 null_driver_t* this = (null_driver_t*) self->driver; 690 null_driver_t* this = (null_driver_t*) self->driver;
708 this->caller = user_data; 691 this->userData = user_data;
709 this->frameDis = t; 692 this->frameDis = t;
710} 693}
711 694
712void null_preload_decoders( xine_stream_t *stream )
713{
714 static const uint32_t preloadedAudioDecoders[] = { BUF_AUDIO_MPEG, BUF_AUDIO_VORBIS };
715 static const uint8_t preloadedAudioDecoderCount = sizeof( preloadedAudioDecoders ) / sizeof( preloadedAudioDecoders[ 0 ] );
716 static const uint32_t preloadedVideoDecoders[] = { BUF_VIDEO_MPEG, BUF_VIDEO_MPEG4, BUF_VIDEO_DIVX5 };
717 static const uint8_t preloadedVideoDecoderCount = sizeof( preloadedVideoDecoders ) / sizeof( preloadedVideoDecoders[ 0 ] );
718
719 uint8_t i;
720#if 0
721
722 for ( i = 0; i < preloadedAudioDecoderCount; ++i ) {
723 audio_decoder_t *decoder = get_audio_decoder( stream, ( preloadedAudioDecoders[ i ] >> 16 ) & 0xff );
724 decoder = decoder;
725/* free_audio_decoder( stream, decoder ); */
726 }
727
728 for ( i = 0; i < preloadedVideoDecoderCount; ++i ) {
729 video_decoder_t *decoder = get_video_decoder( stream, ( preloadedVideoDecoders[ i ] >> 16 ) & 0xff );
730 decoder = decoder;
731/* free_video_decoder( stream, decoder ); */
732 }
733#endif
734}
735 695
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 @@
1/* 1/*
2 * yuv2rgb.c 2 * yuv2rgb.c
3 * 3 *
4 * This file is part of xine, a unix video player. 4 * Copyright (C) 2003-2004 the xine project
5 * This file is part of xine, a free video player.
5 * 6 *
6 * based on work from mpeg2dec: 7 * based on work from mpeg2dec:
7 * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> 8 * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
8 * 9 *
9 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. 10 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
10 * 11 *
11 * mpeg2dec is free software; you can redistribute it and/or modify 12 * mpeg2dec is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or 14 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. 15 * (at your option) any later version.
15 * 16 *
16 * mpeg2dec is distributed in the hope that it will be useful, 17 * mpeg2dec is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details. 20 * GNU General Public License for more details.
20 * 21 *
21 * You should have received a copy of the GNU General Public License 22 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software 23 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * 25 *
25 * $Id$ 26 * $Id$
26 */ 27 */
27 28
28#include <stdio.h> 29#include <stdio.h>
29#include <stdlib.h> 30#include <stdlib.h>
30#include <string.h> 31#include <string.h>
31#include <inttypes.h> 32#include <inttypes.h>
32 33
33#include "yuv2rgb.h" 34#include "yuv2rgb.h"
34#include <xine/xineutils.h>
35 35
36#define LOG_MODULE "yuv2rgb"
37#define LOG_VERBOSE
38/*
39#define LOG
40*/
41
42#include <xine/xineutils.h>
36 43
37static int prof_scale_line = -1; 44static int prof_scale_line = -1;
38 45
39static scale_line_func_t find_scale_line_func(int step); 46static scale_line_func_t find_scale_line_func(int step);
40 47
41 48
42const int32_t Inverse_Table_6_9[8][4] = { 49const int32_t Inverse_Table_6_9[8][4] = {
43 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */ 50 {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
44 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */ 51 {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
45 {104597, 132201, 25675, 53279}, /* unspecified */ 52 {104597, 132201, 25675, 53279}, /* unspecified */
46 {104597, 132201, 25675, 53279}, /* reserved */ 53 {104597, 132201, 25675, 53279}, /* reserved */
47 {104448, 132798, 24759, 53109}, /* FCC */ 54 {104448, 132798, 24759, 53109}, /* FCC */
48 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */ 55 {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
49 {104597, 132201, 25675, 53279}, /* SMPTE 170M */ 56 {104597, 132201, 25675, 53279}, /* SMPTE 170M */
50 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */ 57 {117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
51}; 58};
52 59
53 60
54static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk) { 61static void *my_malloc_aligned (size_t alignment, size_t size, void **chunk)
55 62{
56 char *pMem; 63 char *pMem;
57 64
58 pMem = xine_xmalloc (size+alignment); 65 pMem = xine_xmalloc (size+alignment);
59 66
60 *chunk = pMem; 67 *chunk = pMem;
61 68
62 while ((int) pMem % alignment) 69 while ((uintptr_t) pMem % alignment)
63 pMem++; 70 pMem++;
64 71
65 return pMem; 72 return pMem;
66} 73}
67 74
68 75
76static int yuv2rgb_next_slice (yuv2rgb_t *this, uint8_t **dest)
77{
78 int y0, y1;
79
80 if (dest == NULL) {
81 this->slice_offset = 0;
82 this->slice_height = 16;
83 return 0;
84 }
85 if (this->slice_height == this->source_height) {
86 return this->dest_height;
87 }
88
89 y0 = (this->slice_offset * this->dest_height) / this->source_height;
90 y1 = ((this->slice_offset + this->slice_height) * this->dest_height) / this->source_height;
91 *dest += (this->rgb_stride * y0);
92
93 if ((this->slice_offset + this->slice_height) >= this->source_height) {
94 this->slice_offset = 0;
95 return (this->dest_height - y0);
96 } else {
97 this->slice_offset += this->slice_height;
98 return (y1 - y0);
99 }
100}
101
102static void yuv2rgb_dispose (yuv2rgb_t *this)
103{
104 free (this->y_chunk);
105 free (this->u_chunk);
106 free (this->v_chunk);
107#ifdef HAVE_MLIB
108 free (this->mlib_chunk);
109#endif
110 free (this);
111}
112
69static int yuv2rgb_configure (yuv2rgb_t *this, 113static int yuv2rgb_configure (yuv2rgb_t *this,
70 int source_width, int source_height, 114 int source_width, int source_height,
71 int y_stride, int uv_stride, 115 int y_stride, int uv_stride,
72 int dest_width, int dest_height, 116 int dest_width, int dest_height,
73 int rgb_stride) { 117 int rgb_stride) {
74 /* 118/*
75 printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height, 119 printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height,
76 dest_width, dest_height); 120 dest_width, dest_height);
77 */ 121 */
78 if (prof_scale_line == -1) 122 if (prof_scale_line == -1)
79 prof_scale_line = xine_profiler_allocate_slot("xshm scale line"); 123 prof_scale_line = xine_profiler_allocate_slot("xshm scale line");
80 124
81 this->source_width = source_width; 125 this->source_width = source_width;
82 this->source_height = source_height; 126 this->source_height = source_height;
83 this->y_stride = y_stride; 127 this->y_stride = y_stride;
84 this->uv_stride = uv_stride; 128 this->uv_stride = uv_stride;
85 this->dest_width = dest_width; 129 this->dest_width = dest_width;
86 this->dest_height = dest_height; 130 this->dest_height = dest_height;
87 this->rgb_stride = rgb_stride; 131 this->rgb_stride = rgb_stride;
88 132 this->slice_height = source_height;
133 this->slice_offset = 0;
134
89 if (this->y_chunk) { 135 if (this->y_chunk) {
90 free (this->y_chunk); 136 free (this->y_chunk);
91 this->y_buffer = this->y_chunk = NULL; 137 this->y_buffer = this->y_chunk = NULL;
92 } 138 }
93 if (this->u_chunk) { 139 if (this->u_chunk) {
94 free (this->u_chunk); 140 free (this->u_chunk);
95 this->u_buffer = this->u_chunk = NULL; 141 this->u_buffer = this->u_chunk = NULL;
96 } 142 }
97 if (this->v_chunk) { 143 if (this->v_chunk) {
98 free (this->v_chunk); 144 free (this->v_chunk);
99 this->v_buffer = this->v_chunk = NULL; 145 this->v_buffer = this->v_chunk = NULL;
100 } 146 }
101 147
102 148#ifdef HAVE_MLIB
149 if (this->mlib_chunk) {
150 free (this->mlib_chunk);
151 this->mlib_buffer = this->mlib_chunk = NULL;
152 }
153 if (this->mlib_resize_chunk) {
154 free (this->mlib_resize_chunk);
155 this->mlib_resize_buffer = this->mlib_resize_chunk = NULL;
156 }
157#endif
158
103 this->step_dx = source_width * 32768 / dest_width; 159 this->step_dx = source_width * 32768 / dest_width;
104 this->step_dy = source_height * 32768 / dest_height; 160 this->step_dy = source_height * 32768 / dest_height;
105 161/*
162 printf("yuv2rgb config: src_ht=%i, dst_ht=%i\n",source_height, dest_height);
163 printf("yuv2rgb config: step_dy=%i %f\n",this->step_dy, (float)this->step_dy / 32768.0);
164*/
106 this->scale_line = find_scale_line_func(this->step_dx); 165 this->scale_line = find_scale_line_func(this->step_dx);
107 166
108 if ((source_width == dest_width) && (source_height == dest_height)) { 167 if ((source_width == dest_width) && (source_height == dest_height)) {
109 this->do_scale = 0; 168 this->do_scale = 0;
110 169
111 /* 170 /*
112 * space for two y-lines (for yuv2rgb_mlib) 171 * space for two y-lines (for yuv2rgb_mlib)
113 * u,v subsampled 2:1 172 * u,v subsampled 2:1
114 */ 173 */
115 this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk); 174 this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk);
116 if (!this->y_buffer) 175 if (!this->y_buffer)
117 return 0; 176 return 0;
118 this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk); 177 this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk);
119 if (!this->u_buffer) 178 if (!this->u_buffer)
120 return 0; 179 return 0;
121 this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk); 180 this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk);
122 if (!this->v_buffer) 181 if (!this->v_buffer)
123 return 0; 182 return 0;
124 183
125 } else { 184 } else {
126 this->do_scale = 1; 185 this->do_scale = 1;
127 186
128 /* 187 /*
129 * space for two y-lines (for yuv2rgb_mlib) 188 * space for two y-lines (for yuv2rgb_mlib)
130 * u,v subsampled 2:1 189 * u,v subsampled 2:1
131 */ 190 */
132 this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk); 191 this->y_buffer = my_malloc_aligned (16, 2*dest_width, &this->y_chunk);
133 if (!this->y_buffer) 192 if (!this->y_buffer)
134 return 0; 193 return 0;
135 this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk); 194 this->u_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->u_chunk);
136 if (!this->u_buffer) 195 if (!this->u_buffer)
137 return 0; 196 return 0;
138 this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk); 197 this->v_buffer = my_malloc_aligned (16, (dest_width+1)/2, &this->v_chunk);
139 if (!this->v_buffer) 198 if (!this->v_buffer)
140 return 0; 199 return 0;
200
201#if HAVE_MLIB
202 /* Only need these if we are resizing and in mlib code */
203 this->mlib_buffer = my_malloc_aligned (16, source_width*source_height*4, &this->mlib_chunk);
204 if (!this->mlib_buffer)
205 return 0;
206 /* Only need this one if we are 24 bit */
207 if((rgb_stride / dest_width) == 3) {
208 this->mlib_resize_buffer = my_malloc_aligned (16, dest_width*dest_height*4, &this->mlib_resize_chunk);
209 if (!this->mlib_resize_buffer)
210 return 0;
211 }
212 #endif
141 } 213 }
142 return 1; 214 return 1;
143} 215}
144 216
145
146static void scale_line_gen (uint8_t *source, uint8_t *dest, 217static void scale_line_gen (uint8_t *source, uint8_t *dest,
147 int width, int step) { 218 int width, int step) {
148 219
149 /* 220 /*
150 * scales a yuv source row to a dest row, with interpolation 221 * scales a yuv source row to a dest row, with interpolation
151 * (good quality, but slow) 222 * (good quality, but slow)
152 */ 223 */
153 int p1; 224 int p1;
154 int p2; 225 int p2;
155 int dx; 226 int dx;
156 227
157 xine_profiler_start_count(prof_scale_line); 228 xine_profiler_start_count(prof_scale_line);
158 229
159 p1 = *source++; 230 p1 = *source++;
160 p2 = *source++; 231 p2 = *source++;
161 dx = 0; 232 dx = 0;
162 233
163 /* 234 /*
164 * the following code has been optimized by Scott Smith <ssmith@akamai.com>: 235 * the following code has been optimized by Scott Smith <ssmith@akamai.com>:
165 * 236 *
166 * ok now I have a meaningful optimization for yuv2rgb.c:scale_line_gen. 237 * ok now I have a meaningful optimization for yuv2rgb.c:scale_line_gen.
167 * it removes the loop from within the while() loop by separating it out 238 * it removes the loop from within the while() loop by separating it out
168 * into 3 cases: where you are enlarging the line (<32768), where you are 239 * into 3 cases: where you are enlarging the line (<32768), where you are
169 * between 50% and 100% of the original line (<=65536), and where you are 240 * 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,
1183 xine_fast_memcpy(dest, source, width); 1254 xine_fast_memcpy(dest, source, width);
1184 xine_profiler_stop_count(prof_scale_line); 1255 xine_profiler_stop_count(prof_scale_line);
1185} 1256}
1186 1257
1187 1258
1188static scale_line_func_t find_scale_line_func(int step) { 1259static scale_line_func_t find_scale_line_func(int step) {
1189 static struct { 1260 static struct {
1190 int src_step; 1261 int src_step;
1191 int dest_step; 1262 int dest_step;
1192 scale_line_func_tfunc; 1263 scale_line_func_tfunc;
1193 char *desc; 1264 char *desc;
1194 } scale_line[] = { 1265 } scale_line[] = {
1195 { 15, 16, scale_line_15_16, "dvd 4:3(pal)" }, 1266 { 15, 16, scale_line_15_16, "dvd 4:3(pal)" },
1196 { 45, 64, scale_line_45_64, "dvd 16:9(pal), fullscreen(1024x768)" }, 1267 { 45, 64, scale_line_45_64, "dvd 16:9(pal), fullscreen(1024x768)" },
1197 { 9, 16, scale_line_9_16, "dvd fullscreen(1280x1024)" }, 1268 { 9, 16, scale_line_9_16, "dvd fullscreen(1280x1024)" },
1198 { 45, 53, scale_line_45_53, "dvd 16:9(ntsc)" }, 1269 { 45, 53, scale_line_45_53, "dvd 16:9(ntsc)" },
1199 { 11, 12, scale_line_11_12, "vcd 4:3(pal)" }, 1270 { 11, 12, scale_line_11_12, "vcd 4:3(pal)" },
1200 { 11, 24, scale_line_11_24, "vcd 4:3(pal) 2*zoom" }, 1271 { 11, 24, scale_line_11_24, "vcd 4:3(pal) 2*zoom" },
1201 { 5, 8, scale_line_5_8, "svcd 4:3(pal)" }, 1272 { 5, 8, scale_line_5_8, "svcd 4:3(pal)" },
1202 { 3, 4, scale_line_3_4, "svcd 4:3(ntsc)" }, 1273 { 3, 4, scale_line_3_4, "svcd 4:3(ntsc)" },
1203 { 1, 2, scale_line_1_2, "2*zoom" }, 1274 { 1, 2, scale_line_1_2, "2*zoom" },
1204 { 1, 1, scale_line_1_1, "non-scaled" }, 1275 { 1, 1, scale_line_1_1, "non-scaled" },
1205 }; 1276 };
1206 int i; 1277 int i;
1278 #ifdefLOG
1279 /* to filter out multiple messages about the scale_line variant we're using */
1280 static int reported_for_step;
1281#endif
1207 1282
1208 for (i = 0; i < sizeof(scale_line)/sizeof(scale_line[0]); i++) { 1283 for (i = 0; i < sizeof(scale_line)/sizeof(scale_line[0]); i++) {
1209 if (step == scale_line[i].src_step*32768/scale_line[i].dest_step) { 1284 if (step == scale_line[i].src_step*32768/scale_line[i].dest_step) {
1210 //printf("yuv2rgb: using %s optimized scale_line\n", scale_line[i].desc); 1285 #ifdefLOG
1286 if (step != reported_for_step)
1287 printf("yuv2rgb: using %s optimized scale_line\n", scale_line[i].desc);
1288 reported_for_step = step;
1289#endif
1211 return scale_line[i].func; 1290 return scale_line[i].func;
1212 } 1291 }
1213 } 1292 }
1214 //printf("yuv2rgb: using generic scale_line with interpolation\n");
1215 return scale_line_gen;
1216 1293
1294 #ifdefLOG
1295 if (step != reported_for_step)
1296 printf("yuv2rgb: using generic scale_line with interpolation\n");
1297 reported_for_step = step;
1298#endif
1299
1300 return scale_line_gen;
1217} 1301}
1218 1302
1219 1303
1220static void scale_line_2 (uint8_t *source, uint8_t *dest, 1304static void scale_line_2 (uint8_t *source, uint8_t *dest,
1221 int width, int step) { 1305 int width, int step) {
1222 int p1; 1306 int p1;
1223 int p2; 1307 int p2;
1224 int dx; 1308 int dx;
1225 1309
1226 p1 = *source; source+=2; 1310 p1 = *source; source+=2;
1227 p2 = *source; source+=2; 1311 p2 = *source; source+=2;
1228 dx = 0; 1312 dx = 0;
1229 1313
1230 while (width) { 1314 while (width) {
1231 1315
1232 *dest = (p1 * (32768 - dx) + p2 * dx) / 32768; 1316 *dest = (p1 * (32768 - dx) + p2 * dx) / 32768;
1233 1317
1234 dx += step; 1318 dx += step;
1235 while (dx > 32768) { 1319 while (dx > 32768) {
1236 dx -= 32768; 1320 dx -= 32768;
1237 p1 = p2; 1321 p1 = p2;
1238 p2 = *source; 1322 p2 = *source;
1239 source+=2; 1323 source+=2;
1240 } 1324 }
@@ -1251,49 +1335,49 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest,
1251 int dx; 1335 int dx;
1252 1336
1253 p1 = *source; source+=4; 1337 p1 = *source; source+=4;
1254 p2 = *source; source+=4; 1338 p2 = *source; source+=4;
1255 dx = 0; 1339 dx = 0;
1256 1340
1257 while (width) { 1341 while (width) {
1258 1342
1259 *dest = (p1 * (32768 - dx) + p2 * dx) / 32768; 1343 *dest = (p1 * (32768 - dx) + p2 * dx) / 32768;
1260 1344
1261 dx += step; 1345 dx += step;
1262 while (dx > 32768) { 1346 while (dx > 32768) {
1263 dx -= 32768; 1347 dx -= 32768;
1264 p1 = p2; 1348 p1 = p2;
1265 p2 = *source; 1349 p2 = *source;
1266 source+=4; 1350 source+=4;
1267 } 1351 }
1268 1352
1269 dest ++; 1353 dest ++;
1270 width --; 1354 width --;
1271 } 1355 }
1272} 1356}
1273 1357
1274 1358
1275 #define RGB(i) \ 1359 #define X_RGB(i) \
1276 U = pu[i]; \ 1360 U = pu[i]; \
1277 V = pv[i]; \ 1361 V = pv[i]; \
1278 r = this->table_rV[V]; \ 1362 r = this->table_rV[V]; \
1279 g = (void *) (((uint8_t *)this->table_gU[U]) + this->table_gV[V]);\ 1363 g = (void *) (((uint8_t *)this->table_gU[U]) + this->table_gV[V]);\
1280 b = this->table_bU[U]; 1364 b = this->table_bU[U];
1281 1365
1282 #define DST1(i) \ 1366 #define DST1(i) \
1283 Y = py_1[2*i]; \ 1367 Y = py_1[2*i]; \
1284 dst_1[2*i] = r[Y] + g[Y] + b[Y];\ 1368 dst_1[2*i] = r[Y] + g[Y] + b[Y];\
1285 Y = py_1[2*i+1]; \ 1369 Y = py_1[2*i+1]; \
1286 dst_1[2*i+1] = r[Y] + g[Y] + b[Y]; 1370 dst_1[2*i+1] = r[Y] + g[Y] + b[Y];
1287 1371
1288 #define DST2(i) \ 1372 #define DST2(i) \
1289 Y = py_2[2*i]; \ 1373 Y = py_2[2*i]; \
1290 dst_2[2*i] = r[Y] + g[Y] + b[Y];\ 1374 dst_2[2*i] = r[Y] + g[Y] + b[Y];\
1291 Y = py_2[2*i+1]; \ 1375 Y = py_2[2*i+1]; \
1292 dst_2[2*i+1] = r[Y] + g[Y] + b[Y]; 1376 dst_2[2*i+1] = r[Y] + g[Y] + b[Y];
1293 1377
1294 #define DST1RGB(i) \ 1378 #define DST1RGB(i) \
1295 Y = py_1[2*i]; \ 1379 Y = py_1[2*i]; \
1296 dst_1[6*i] = r[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = b[Y];\ 1380 dst_1[6*i] = r[Y]; dst_1[6*i+1] = g[Y]; dst_1[6*i+2] = b[Y];\
1297 Y = py_1[2*i+1]; \ 1381 Y = py_1[2*i+1]; \
1298 dst_1[6*i+3] = r[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = b[Y]; 1382 dst_1[6*i+3] = r[Y]; dst_1[6*i+4] = g[Y]; dst_1[6*i+5] = b[Y];
1299 1383
@@ -1327,1033 +1411,1054 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest,
1327 Y = py_2[2*i+1]; \ 1411 Y = py_2[2*i+1]; \
1328 dst_2[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]]; 1412 dst_2[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]];
1329 1413
1330static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, 1414static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst,
1331 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 1415 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1332{ 1416{
1333 int U, V, Y; 1417 int U, V, Y;
1334 uint8_t * py_1, * py_2, * pu, * pv; 1418 uint8_t * py_1, * py_2, * pu, * pv;
1335 uint32_t * r, * g, * b; 1419 uint32_t * r, * g, * b;
1336 uint32_t * dst_1, * dst_2; 1420 uint32_t * dst_1, * dst_2;
1337 int width, height, dst_height; 1421 int width, height, dst_height;
1338 int dy; 1422 int dy;
1339 1423
1340 if (this->do_scale) { 1424 if (this->do_scale) {
1341 scale_line_func_t scale_line = this->scale_line; 1425 scale_line_func_t scale_line = this->scale_line;
1342 1426
1343 scale_line (_pu, this->u_buffer, 1427 scale_line (_pu, this->u_buffer,
1344 this->dest_width >> 1, this->step_dx); 1428 this->dest_width >> 1, this->step_dx);
1345 scale_line (_pv, this->v_buffer, 1429 scale_line (_pv, this->v_buffer,
1346 this->dest_width >> 1, this->step_dx); 1430 this->dest_width >> 1, this->step_dx);
1347 scale_line (_py, this->y_buffer, 1431 scale_line (_py, this->y_buffer,
1348 this->dest_width, this->step_dx); 1432 this->dest_width, this->step_dx);
1349 1433
1350 dy = 0; 1434 dy = 0;
1351 dst_height = this->dest_height; 1435 dst_height = this->next_slice (this, &_dst);
1352 1436
1353 for (height = 0;; ) { 1437 for (height = 0;; ) {
1354 dst_1 = (uint32_t*)_dst; 1438 dst_1 = (uint32_t*)_dst;
1355 py_1 = this->y_buffer; 1439 py_1 = this->y_buffer;
1356 pu = this->u_buffer; 1440 pu = this->u_buffer;
1357 pv = this->v_buffer; 1441 pv = this->v_buffer;
1358 1442
1359 width = this->dest_width >> 3; 1443 width = this->dest_width >> 3;
1360 1444
1361 do { 1445 do {
1362 RGB(0); 1446 X_RGB(0);
1363 DST1(0); 1447 DST1(0);
1364 1448
1365 RGB(1); 1449 X_RGB(1);
1366 DST1(1); 1450 DST1(1);
1367 1451
1368 RGB(2); 1452 X_RGB(2);
1369 DST1(2); 1453 DST1(2);
1370 1454
1371 RGB(3); 1455 X_RGB(3);
1372 DST1(3); 1456 DST1(3);
1373 1457
1374 pu += 4; 1458 pu += 4;
1375 pv += 4; 1459 pv += 4;
1376 py_1 += 8; 1460 py_1 += 8;
1377 dst_1 += 8; 1461 dst_1 += 8;
1378 } while (--width); 1462 } while (--width);
1379 1463
1380 dy += this->step_dy; 1464 dy += this->step_dy;
1381 _dst += this->rgb_stride; 1465 _dst += this->rgb_stride;
1382 1466
1383 while (--dst_height > 0 && dy < 32768) { 1467 while (--dst_height > 0 && dy < 32768) {
1384 1468
1385 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); 1469 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4);
1386 1470
1387 dy += this->step_dy; 1471 dy += this->step_dy;
1388 _dst += this->rgb_stride; 1472 _dst += this->rgb_stride;
1389 } 1473 }
1390 1474
1391 if (dst_height <= 0) 1475 if (dst_height <= 0)
1392 break; 1476 break;
1393 1477
1394 do { 1478 do {
1395 dy -= 32768; 1479 dy -= 32768;
1396 _py += this->y_stride; 1480 _py += this->y_stride;
1397 1481
1398 scale_line (_py, this->y_buffer, 1482 scale_line (_py, this->y_buffer,
1399 this->dest_width, this->step_dx); 1483 this->dest_width, this->step_dx);
1400 1484
1401 if (height & 1) { 1485 if (height & 1) {
1402 _pu += this->uv_stride; 1486 _pu += this->uv_stride;
1403 _pv += this->uv_stride; 1487 _pv += this->uv_stride;
1404 1488
1405 scale_line (_pu, this->u_buffer, 1489 scale_line (_pu, this->u_buffer,
1406 this->dest_width >> 1, this->step_dx); 1490 this->dest_width >> 1, this->step_dx);
1407 scale_line (_pv, this->v_buffer, 1491 scale_line (_pv, this->v_buffer,
1408 this->dest_width >> 1, this->step_dx); 1492 this->dest_width >> 1, this->step_dx);
1409 1493
1410 } 1494 }
1411 height++; 1495 height++;
1412 } while( dy>=32768); 1496 } while( dy>=32768);
1413 } 1497 }
1414 } else { 1498 } else {
1415 height = this->source_height >> 1; 1499 height = this->next_slice (this, &_dst) >> 1;
1416 do { 1500 do {
1417 dst_1 = (uint32_t*)_dst; 1501 dst_1 = (uint32_t*)_dst;
1418 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); 1502 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
1419 py_1 = _py; 1503 py_1 = _py;
1420 py_2 = _py + this->y_stride; 1504 py_2 = _py + this->y_stride;
1421 pu = _pu; 1505 pu = _pu;
1422 pv = _pv; 1506 pv = _pv;
1423 1507
1424 width = this->source_width >> 3; 1508 width = this->source_width >> 3;
1425 do { 1509 do {
1426 RGB(0); 1510 X_RGB(0);
1427 DST1(0); 1511 DST1(0);
1428 DST2(0); 1512 DST2(0);
1429 1513
1430 RGB(1); 1514 X_RGB(1);
1431 DST2(1); 1515 DST2(1);
1432 DST1(1); 1516 DST1(1);
1433 1517
1434 RGB(2); 1518 X_RGB(2);
1435 DST1(2); 1519 DST1(2);
1436 DST2(2); 1520 DST2(2);
1437 1521
1438 RGB(3); 1522 X_RGB(3);
1439 DST2(3); 1523 DST2(3);
1440 DST1(3); 1524 DST1(3);
1441 1525
1442 pu += 4; 1526 pu += 4;
1443 pv += 4; 1527 pv += 4;
1444 py_1 += 8; 1528 py_1 += 8;
1445 py_2 += 8; 1529 py_2 += 8;
1446 dst_1 += 8; 1530 dst_1 += 8;
1447 dst_2 += 8; 1531 dst_2 += 8;
1448 } while (--width); 1532 } while (--width);
1449 1533
1450 _dst += 2 * this->rgb_stride; 1534 _dst += 2 * this->rgb_stride;
1451 _py += 2 * this->y_stride; 1535 _py += 2 * this->y_stride;
1452 _pu += this->uv_stride; 1536 _pu += this->uv_stride;
1453 _pv += this->uv_stride; 1537 _pv += this->uv_stride;
1454 1538
1455 } while (--height); 1539 } while (--height);
1456 } 1540 }
1457} 1541}
1458 1542
1459/* This is very near from the yuv2rgb_c_32 code */ 1543/* This is very near from the yuv2rgb_c_32 code */
1460static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, 1544static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst,
1461 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 1545 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1462{ 1546{
1463 int U, V, Y; 1547 int U, V, Y;
1464 uint8_t * py_1, * py_2, * pu, * pv; 1548 uint8_t * py_1, * py_2, * pu, * pv;
1465 uint8_t * r, * g, * b; 1549 uint8_t * r, * g, * b;
1466 uint8_t * dst_1, * dst_2; 1550 uint8_t * dst_1, * dst_2;
1467 int width, height, dst_height; 1551 int width, height, dst_height;
1468 int dy; 1552 int dy;
1469 1553
1470 if (this->do_scale) { 1554 if (this->do_scale) {
1471 1555
1472 scale_line_func_t scale_line = this->scale_line; 1556 scale_line_func_t scale_line = this->scale_line;
1473 1557
1474 scale_line (_pu, this->u_buffer, 1558 scale_line (_pu, this->u_buffer,
1475 this->dest_width >> 1, this->step_dx); 1559 this->dest_width >> 1, this->step_dx);
1476 scale_line (_pv, this->v_buffer, 1560 scale_line (_pv, this->v_buffer,
1477 this->dest_width >> 1, this->step_dx); 1561 this->dest_width >> 1, this->step_dx);
1478 scale_line (_py, this->y_buffer, 1562 scale_line (_py, this->y_buffer,
1479 this->dest_width, this->step_dx); 1563 this->dest_width, this->step_dx);
1480 1564
1481 dy = 0; 1565 dy = 0;
1482 dst_height = this->dest_height; 1566 dst_height = this->next_slice (this, &_dst);
1483 1567
1484 for (height = 0;; ) { 1568 for (height = 0;; ) {
1485 dst_1 = _dst; 1569 dst_1 = _dst;
1486 py_1 = this->y_buffer; 1570 py_1 = this->y_buffer;
1487 pu = this->u_buffer; 1571 pu = this->u_buffer;
1488 pv = this->v_buffer; 1572 pv = this->v_buffer;
1489 1573
1490 width = this->dest_width >> 3; 1574 width = this->dest_width >> 3;
1491 1575
1492 do { 1576 do {
1493 RGB(0); 1577 X_RGB(0);
1494 DST1RGB(0); 1578 DST1RGB(0);
1495 1579
1496 RGB(1); 1580 X_RGB(1);
1497 DST1RGB(1); 1581 DST1RGB(1);
1498 1582
1499 RGB(2); 1583 X_RGB(2);
1500 DST1RGB(2); 1584 DST1RGB(2);
1501 1585
1502 RGB(3); 1586 X_RGB(3);
1503 DST1RGB(3); 1587 DST1RGB(3);
1504 1588
1505 pu += 4; 1589 pu += 4;
1506 pv += 4; 1590 pv += 4;
1507 py_1 += 8; 1591 py_1 += 8;
1508 dst_1 += 24; 1592 dst_1 += 24;
1509 } while (--width); 1593 } while (--width);
1510 1594
1511 dy += this->step_dy; 1595 dy += this->step_dy;
1512 _dst += this->rgb_stride; 1596 _dst += this->rgb_stride;
1513 1597
1514 while (--dst_height > 0 && dy < 32768) { 1598 while (--dst_height > 0 && dy < 32768) {
1515 1599
1516 xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3); 1600 xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
1517 1601
1518 dy += this->step_dy; 1602 dy += this->step_dy;
1519 _dst += this->rgb_stride; 1603 _dst += this->rgb_stride;
1520 } 1604 }
1521 1605
1522 if (dst_height <= 0) 1606 if (dst_height <= 0)
1523 break; 1607 break;
1524 1608
1525 do { 1609 do {
1526 dy -= 32768; 1610 dy -= 32768;
1527 _py += this->y_stride; 1611 _py += this->y_stride;
1528 1612
1529 scale_line (_py, this->y_buffer, 1613 scale_line (_py, this->y_buffer,
1530 this->dest_width, this->step_dx); 1614 this->dest_width, this->step_dx);
1531 1615
1532 if (height & 1) { 1616 if (height & 1) {
1533 _pu += this->uv_stride; 1617 _pu += this->uv_stride;
1534 _pv += this->uv_stride; 1618 _pv += this->uv_stride;
1535 1619
1536 scale_line (_pu, this->u_buffer, 1620 scale_line (_pu, this->u_buffer,
1537 this->dest_width >> 1, this->step_dx); 1621 this->dest_width >> 1, this->step_dx);
1538 scale_line (_pv, this->v_buffer, 1622 scale_line (_pv, this->v_buffer,
1539 this->dest_width >> 1, this->step_dx); 1623 this->dest_width >> 1, this->step_dx);
1540 1624
1541 } 1625 }
1542 height++; 1626 height++;
1543 } while (dy>=32768); 1627 } while (dy>=32768);
1544 } 1628 }
1545 } else { 1629 } else {
1546 height = this->source_height >> 1; 1630 height = this->next_slice (this, &_dst) >> 1;
1547 do { 1631 do {
1548 dst_1 = _dst; 1632 dst_1 = _dst;
1549 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); 1633 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
1550 py_1 = _py; 1634 py_1 = _py;
1551 py_2 = _py + this->y_stride; 1635 py_2 = _py + this->y_stride;
1552 pu = _pu; 1636 pu = _pu;
1553 pv = _pv; 1637 pv = _pv;
1554 1638
1555 width = this->source_width >> 3; 1639 width = this->source_width >> 3;
1556 do { 1640 do {
1557 RGB(0); 1641 X_RGB(0);
1558 DST1RGB(0); 1642 DST1RGB(0);
1559 DST2RGB(0); 1643 DST2RGB(0);
1560 1644
1561 RGB(1); 1645 X_RGB(1);
1562 DST2RGB(1); 1646 DST2RGB(1);
1563 DST1RGB(1); 1647 DST1RGB(1);
1564 1648
1565 RGB(2); 1649 X_RGB(2);
1566 DST1RGB(2); 1650 DST1RGB(2);
1567 DST2RGB(2); 1651 DST2RGB(2);
1568 1652
1569 RGB(3); 1653 X_RGB(3);
1570 DST2RGB(3); 1654 DST2RGB(3);
1571 DST1RGB(3); 1655 DST1RGB(3);
1572 1656
1573 pu += 4; 1657 pu += 4;
1574 pv += 4; 1658 pv += 4;
1575 py_1 += 8; 1659 py_1 += 8;
1576 py_2 += 8; 1660 py_2 += 8;
1577 dst_1 += 24; 1661 dst_1 += 24;
1578 dst_2 += 24; 1662 dst_2 += 24;
1579 } while (--width); 1663 } while (--width);
1580 1664
1581 _dst += 2 * this->rgb_stride; 1665 _dst += 2 * this->rgb_stride;
1582 _py += 2 * this->y_stride; 1666 _py += 2 * this->y_stride;
1583 _pu += this->uv_stride; 1667 _pu += this->uv_stride;
1584 _pv += this->uv_stride; 1668 _pv += this->uv_stride;
1585 1669
1586 } while (--height); 1670 } while (--height);
1587 } 1671 }
1588} 1672}
1589 1673
1590/* only trivial mods from yuv2rgb_c_24_rgb */ 1674/* only trivial mods from yuv2rgb_c_24_rgb */
1591static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, 1675static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst,
1592 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 1676 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1593{ 1677{
1594 int U, V, Y; 1678 int U, V, Y;
1595 uint8_t * py_1, * py_2, * pu, * pv; 1679 uint8_t * py_1, * py_2, * pu, * pv;
1596 uint8_t * r, * g, * b; 1680 uint8_t * r, * g, * b;
1597 uint8_t * dst_1, * dst_2; 1681 uint8_t * dst_1, * dst_2;
1598 int width, height, dst_height; 1682 int width, height, dst_height;
1599 int dy; 1683 int dy;
1600 1684
1601 if (this->do_scale) { 1685 if (this->do_scale) {
1602 1686
1603 scale_line_func_t scale_line = this->scale_line; 1687 scale_line_func_t scale_line = this->scale_line;
1604 1688
1605 scale_line (_pu, this->u_buffer, 1689 scale_line (_pu, this->u_buffer,
1606 this->dest_width >> 1, this->step_dx); 1690 this->dest_width >> 1, this->step_dx);
1607 scale_line (_pv, this->v_buffer, 1691 scale_line (_pv, this->v_buffer,
1608 this->dest_width >> 1, this->step_dx); 1692 this->dest_width >> 1, this->step_dx);
1609 scale_line (_py, this->y_buffer, 1693 scale_line (_py, this->y_buffer,
1610 this->dest_width, this->step_dx); 1694 this->dest_width, this->step_dx);
1611 1695
1612 dy = 0; 1696 dy = 0;
1613 dst_height = this->dest_height; 1697 dst_height = this->next_slice (this, &_dst);
1614 1698
1615 for (height = 0;; ) { 1699 for (height = 0;; ) {
1616 dst_1 = _dst; 1700 dst_1 = _dst;
1617 py_1 = this->y_buffer; 1701 py_1 = this->y_buffer;
1618 pu = this->u_buffer; 1702 pu = this->u_buffer;
1619 pv = this->v_buffer; 1703 pv = this->v_buffer;
1620 1704
1621 width = this->dest_width >> 3; 1705 width = this->dest_width >> 3;
1622 1706
1623 do { 1707 do {
1624 RGB(0); 1708 X_RGB(0);
1625 DST1BGR(0); 1709 DST1BGR(0);
1626 1710
1627 RGB(1); 1711 X_RGB(1);
1628 DST1BGR(1); 1712 DST1BGR(1);
1629 1713
1630 RGB(2); 1714 X_RGB(2);
1631 DST1BGR(2); 1715 DST1BGR(2);
1632 1716
1633 RGB(3); 1717 X_RGB(3);
1634 DST1BGR(3); 1718 DST1BGR(3);
1635 1719
1636 pu += 4; 1720 pu += 4;
1637 pv += 4; 1721 pv += 4;
1638 py_1 += 8; 1722 py_1 += 8;
1639 dst_1 += 24; 1723 dst_1 += 24;
1640 } while (--width); 1724 } while (--width);
1641 1725
1642 dy += this->step_dy; 1726 dy += this->step_dy;
1643 _dst += this->rgb_stride; 1727 _dst += this->rgb_stride;
1644 1728
1645 while (--dst_height > 0 && dy < 32768) { 1729 while (--dst_height > 0 && dy < 32768) {
1646 1730
1647 xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3); 1731 xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3);
1648 1732
1649 dy += this->step_dy; 1733 dy += this->step_dy;
1650 _dst += this->rgb_stride; 1734 _dst += this->rgb_stride;
1651 } 1735 }
1652 1736
1653 if (dst_height <= 0) 1737 if (dst_height <= 0)
1654 break; 1738 break;
1655 1739
1656 do { 1740 do {
1657 dy -= 32768; 1741 dy -= 32768;
1658 _py += this->y_stride; 1742 _py += this->y_stride;
1659 1743
1660 scale_line (_py, this->y_buffer, 1744 scale_line (_py, this->y_buffer,
1661 this->dest_width, this->step_dx); 1745 this->dest_width, this->step_dx);
1662 1746
1663 if (height & 1) { 1747 if (height & 1) {
1664 _pu += this->uv_stride; 1748 _pu += this->uv_stride;
1665 _pv += this->uv_stride; 1749 _pv += this->uv_stride;
1666 1750
1667 scale_line (_pu, this->u_buffer, 1751 scale_line (_pu, this->u_buffer,
1668 this->dest_width >> 1, this->step_dx); 1752 this->dest_width >> 1, this->step_dx);
1669 scale_line (_pv, this->v_buffer, 1753 scale_line (_pv, this->v_buffer,
1670 this->dest_width >> 1, this->step_dx); 1754 this->dest_width >> 1, this->step_dx);
1671 1755
1672 } 1756 }
1673 height++; 1757 height++;
1674 } while( dy>=32768 ); 1758 } while( dy>=32768 );
1675 } 1759 }
1676 1760
1677 } else { 1761 } else {
1678 height = this->source_height >> 1; 1762 height = this->next_slice (this, &_dst) >> 1;
1679 do { 1763 do {
1680 dst_1 = _dst; 1764 dst_1 = _dst;
1681 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); 1765 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
1682 py_1 = _py; 1766 py_1 = _py;
1683 py_2 = _py + this->y_stride; 1767 py_2 = _py + this->y_stride;
1684 pu = _pu; 1768 pu = _pu;
1685 pv = _pv; 1769 pv = _pv;
1686 width = this->source_width >> 3; 1770 width = this->source_width >> 3;
1687 do { 1771 do {
1688 RGB(0); 1772 X_RGB(0);
1689 DST1BGR(0); 1773 DST1BGR(0);
1690 DST2BGR(0); 1774 DST2BGR(0);
1691 1775
1692 RGB(1); 1776 X_RGB(1);
1693 DST2BGR(1); 1777 DST2BGR(1);
1694 DST1BGR(1); 1778 DST1BGR(1);
1695 1779
1696 RGB(2); 1780 X_RGB(2);
1697 DST1BGR(2); 1781 DST1BGR(2);
1698 DST2BGR(2); 1782 DST2BGR(2);
1699 1783
1700 RGB(3); 1784 X_RGB(3);
1701 DST2BGR(3); 1785 DST2BGR(3);
1702 DST1BGR(3); 1786 DST1BGR(3);
1703 1787
1704 pu += 4; 1788 pu += 4;
1705 pv += 4; 1789 pv += 4;
1706 py_1 += 8; 1790 py_1 += 8;
1707 py_2 += 8; 1791 py_2 += 8;
1708 dst_1 += 24; 1792 dst_1 += 24;
1709 dst_2 += 24; 1793 dst_2 += 24;
1710 } while (--width); 1794 } while (--width);
1711 1795
1712 _dst += 2 * this->rgb_stride; 1796 _dst += 2 * this->rgb_stride;
1713 _py += 2 * this->y_stride; 1797 _py += 2 * this->y_stride;
1714 _pu += this->uv_stride; 1798 _pu += this->uv_stride;
1715 _pv += this->uv_stride; 1799 _pv += this->uv_stride;
1716 1800
1717 } while (--height); 1801 } while (--height);
1718 } 1802 }
1719} 1803}
1720 1804
1721/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ 1805/* This is exactly the same code as yuv2rgb_c_32 except for the types of */
1722/* r, g, b, dst_1, dst_2 */ 1806/* r, g, b, dst_1, dst_2 */
1723static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, 1807static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst,
1724 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 1808 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1725{ 1809{
1726 int U, V, Y; 1810 int U, V, Y;
1727 uint8_t * py_1, * py_2, * pu, * pv; 1811 uint8_t * py_1, * py_2, * pu, * pv;
1728 uint16_t * r, * g, * b; 1812 uint16_t * r, * g, * b;
1729 uint16_t * dst_1, * dst_2; 1813 uint16_t * dst_1, * dst_2;
1730 int width, height, dst_height; 1814 int width, height, dst_height;
1731 int dy; 1815 int dy;
1732 1816
1733 if (this->do_scale) { 1817 if (this->do_scale) {
1734 scale_line_func_t scale_line = this->scale_line; 1818 scale_line_func_t scale_line = this->scale_line;
1735 1819
1736 scale_line (_pu, this->u_buffer, 1820 scale_line (_pu, this->u_buffer,
1737 this->dest_width >> 1, this->step_dx); 1821 this->dest_width >> 1, this->step_dx);
1738 scale_line (_pv, this->v_buffer, 1822 scale_line (_pv, this->v_buffer,
1739 this->dest_width >> 1, this->step_dx); 1823 this->dest_width >> 1, this->step_dx);
1740 scale_line (_py, this->y_buffer, 1824 scale_line (_py, this->y_buffer,
1741 this->dest_width, this->step_dx); 1825 this->dest_width, this->step_dx);
1742 1826
1743 dy = 0; 1827 dy = 0;
1744 dst_height = this->dest_height; 1828 dst_height = this->next_slice (this, &_dst);
1745 1829
1746 for (height = 0;; ) { 1830 for (height = 0;; ) {
1747 dst_1 = (uint16_t*)_dst; 1831 dst_1 = (uint16_t*)_dst;
1748 py_1 = this->y_buffer; 1832 py_1 = this->y_buffer;
1749 pu = this->u_buffer; 1833 pu = this->u_buffer;
1750 pv = this->v_buffer; 1834 pv = this->v_buffer;
1751 1835
1752 width = this->dest_width >> 3; 1836 width = this->dest_width >> 3;
1753 1837
1754 do { 1838 do {
1755 RGB(0); 1839 X_RGB(0);
1756 DST1(0); 1840 DST1(0);
1757 1841
1758 RGB(1); 1842 X_RGB(1);
1759 DST1(1); 1843 DST1(1);
1760 1844
1761 RGB(2); 1845 X_RGB(2);
1762 DST1(2); 1846 DST1(2);
1763 1847
1764 RGB(3); 1848 X_RGB(3);
1765 DST1(3); 1849 DST1(3);
1766 1850
1767 pu += 4; 1851 pu += 4;
1768 pv += 4; 1852 pv += 4;
1769 py_1 += 8; 1853 py_1 += 8;
1770 dst_1 += 8; 1854 dst_1 += 8;
1771 } while (--width); 1855 } while (--width);
1772 1856
1773 dy += this->step_dy; 1857 dy += this->step_dy;
1774 _dst += this->rgb_stride; 1858 _dst += this->rgb_stride;
1775 1859
1776 while (--dst_height > 0 && dy < 32768) { 1860 while (--dst_height > 0 && dy < 32768) {
1777 1861
1778 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); 1862 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2);
1779 1863
1780 dy += this->step_dy; 1864 dy += this->step_dy;
1781 _dst += this->rgb_stride; 1865 _dst += this->rgb_stride;
1782 } 1866 }
1783 1867
1784 if (dst_height <= 0) 1868 if (dst_height <= 0)
1785 break; 1869 break;
1786 1870
1787 do { 1871 do {
1788 dy -= 32768; 1872 dy -= 32768;
1789 _py += this->y_stride; 1873 _py += this->y_stride;
1790 1874
1791 scale_line (_py, this->y_buffer, 1875 scale_line (_py, this->y_buffer,
1792 this->dest_width, this->step_dx); 1876 this->dest_width, this->step_dx);
1793 1877
1794 if (height & 1) { 1878 if (height & 1) {
1795 _pu += this->uv_stride; 1879 _pu += this->uv_stride;
1796 _pv += this->uv_stride; 1880 _pv += this->uv_stride;
1797 1881
1798 scale_line (_pu, this->u_buffer, 1882 scale_line (_pu, this->u_buffer,
1799 this->dest_width >> 1, this->step_dx); 1883 this->dest_width >> 1, this->step_dx);
1800 scale_line (_pv, this->v_buffer, 1884 scale_line (_pv, this->v_buffer,
1801 this->dest_width >> 1, this->step_dx); 1885 this->dest_width >> 1, this->step_dx);
1802 1886
1803 } 1887 }
1804 height++; 1888 height++;
1805 } while( dy>=32768); 1889 } while( dy>=32768);
1806 } 1890 }
1807 } else { 1891 } else {
1808 height = this->source_height >> 1; 1892 height = this->next_slice (this, &_dst) >> 1;
1809 do { 1893 do {
1810 dst_1 = (uint16_t*)_dst; 1894 dst_1 = (uint16_t*)_dst;
1811 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); 1895 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
1812 py_1 = _py; 1896 py_1 = _py;
1813 py_2 = _py + this->y_stride; 1897 py_2 = _py + this->y_stride;
1814 pu = _pu; 1898 pu = _pu;
1815 pv = _pv; 1899 pv = _pv;
1816 width = this->source_width >> 3; 1900 width = this->source_width >> 3;
1817 do { 1901 do {
1818 RGB(0); 1902 X_RGB(0);
1819 DST1(0); 1903 DST1(0);
1820 DST2(0); 1904 DST2(0);
1821 1905
1822 RGB(1); 1906 X_RGB(1);
1823 DST2(1); 1907 DST2(1);
1824 DST1(1); 1908 DST1(1);
1825 1909
1826 RGB(2); 1910 X_RGB(2);
1827 DST1(2); 1911 DST1(2);
1828 DST2(2); 1912 DST2(2);
1829 1913
1830 RGB(3); 1914 X_RGB(3);
1831 DST2(3); 1915 DST2(3);
1832 DST1(3); 1916 DST1(3);
1833 1917
1834 pu += 4; 1918 pu += 4;
1835 pv += 4; 1919 pv += 4;
1836 py_1 += 8; 1920 py_1 += 8;
1837 py_2 += 8; 1921 py_2 += 8;
1838 dst_1 += 8; 1922 dst_1 += 8;
1839 dst_2 += 8; 1923 dst_2 += 8;
1840 } while (--width); 1924 } while (--width);
1841 1925
1842 _dst += 2 * this->rgb_stride; 1926 _dst += 2 * this->rgb_stride;
1843 _py += 2 * this->y_stride; 1927 _py += 2 * this->y_stride;
1844 _pu += this->uv_stride; 1928 _pu += this->uv_stride;
1845 _pv += this->uv_stride; 1929 _pv += this->uv_stride;
1846 1930
1847 } while (--height); 1931 } while (--height);
1848 } 1932 }
1849} 1933}
1850 1934
1851/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ 1935/* This is exactly the same code as yuv2rgb_c_32 except for the types of */
1852/* r, g, b, dst_1, dst_2 */ 1936/* r, g, b, dst_1, dst_2 */
1853static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, 1937static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst,
1854 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 1938 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1855{ 1939{
1856 int U, V, Y; 1940 int U, V, Y;
1857 uint8_t * py_1, * py_2, * pu, * pv; 1941 uint8_t * py_1, * py_2, * pu, * pv;
1858 uint8_t * r, * g, * b; 1942 uint8_t * r, * g, * b;
1859 uint8_t * dst_1, * dst_2; 1943 uint8_t * dst_1, * dst_2;
1860 int width, height, dst_height; 1944 int width, height, dst_height;
1861 int dy; 1945 int dy;
1862 1946
1863 if (this->do_scale) { 1947 if (this->do_scale) {
1864 scale_line_func_t scale_line = this->scale_line; 1948 scale_line_func_t scale_line = this->scale_line;
1865 1949
1866 scale_line (_pu, this->u_buffer, 1950 scale_line (_pu, this->u_buffer,
1867 this->dest_width >> 1, this->step_dx); 1951 this->dest_width >> 1, this->step_dx);
1868 scale_line (_pv, this->v_buffer, 1952 scale_line (_pv, this->v_buffer,
1869 this->dest_width >> 1, this->step_dx); 1953 this->dest_width >> 1, this->step_dx);
1870 scale_line (_py, this->y_buffer, 1954 scale_line (_py, this->y_buffer,
1871 this->dest_width, this->step_dx); 1955 this->dest_width, this->step_dx);
1872 1956
1873 dy = 0; 1957 dy = 0;
1874 dst_height = this->dest_height; 1958 dst_height = this->next_slice (this, &_dst);
1875 1959
1876 for (height = 0;; ) { 1960 for (height = 0;; ) {
1877 dst_1 = (uint8_t*)_dst; 1961 dst_1 = (uint8_t*)_dst;
1878 py_1 = this->y_buffer; 1962 py_1 = this->y_buffer;
1879 pu = this->u_buffer; 1963 pu = this->u_buffer;
1880 pv = this->v_buffer; 1964 pv = this->v_buffer;
1881 1965
1882 width = this->dest_width >> 3; 1966 width = this->dest_width >> 3;
1883 1967
1884 do { 1968 do {
1885 RGB(0); 1969 X_RGB(0);
1886 DST1(0); 1970 DST1(0);
1887 1971
1888 RGB(1); 1972 X_RGB(1);
1889 DST1(1); 1973 DST1(1);
1890 1974
1891 RGB(2); 1975 X_RGB(2);
1892 DST1(2); 1976 DST1(2);
1893 1977
1894 RGB(3); 1978 X_RGB(3);
1895 DST1(3); 1979 DST1(3);
1896 1980
1897 pu += 4; 1981 pu += 4;
1898 pv += 4; 1982 pv += 4;
1899 py_1 += 8; 1983 py_1 += 8;
1900 dst_1 += 8; 1984 dst_1 += 8;
1901 } while (--width); 1985 } while (--width);
1902 1986
1903 dy += this->step_dy; 1987 dy += this->step_dy;
1904 _dst += this->rgb_stride; 1988 _dst += this->rgb_stride;
1905 1989
1906 while (--dst_height > 0 && dy < 32768) { 1990 while (--dst_height > 0 && dy < 32768) {
1907 1991
1908 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 1992 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
1909 1993
1910 dy += this->step_dy; 1994 dy += this->step_dy;
1911 _dst += this->rgb_stride; 1995 _dst += this->rgb_stride;
1912 } 1996 }
1913 1997
1914 if (dst_height <= 0) 1998 if (dst_height <= 0)
1915 break; 1999 break;
1916 2000
1917 do { 2001 do {
1918 dy -= 32768; 2002 dy -= 32768;
1919 _py += this->y_stride; 2003 _py += this->y_stride;
1920 2004
1921 scale_line (_py, this->y_buffer, 2005 scale_line (_py, this->y_buffer,
1922 this->dest_width, this->step_dx); 2006 this->dest_width, this->step_dx);
1923 2007
1924 if (height & 1) { 2008 if (height & 1) {
1925 _pu += this->uv_stride; 2009 _pu += this->uv_stride;
1926 _pv += this->uv_stride; 2010 _pv += this->uv_stride;
1927 2011
1928 scale_line (_pu, this->u_buffer, 2012 scale_line (_pu, this->u_buffer,
1929 this->dest_width >> 1, this->step_dx); 2013 this->dest_width >> 1, this->step_dx);
1930 scale_line (_pv, this->v_buffer, 2014 scale_line (_pv, this->v_buffer,
1931 this->dest_width >> 1, this->step_dx); 2015 this->dest_width >> 1, this->step_dx);
1932 2016
1933 } 2017 }
1934 height++; 2018 height++;
1935 } while( dy>=32768 ); 2019 } while( dy>=32768 );
1936 } 2020 }
1937 } else { 2021 } else {
1938 height = this->source_height >> 1; 2022 height = this->next_slice (this, &_dst) >> 1;
1939 do { 2023 do {
1940 dst_1 = (uint8_t*)_dst; 2024 dst_1 = (uint8_t*)_dst;
1941 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); 2025 dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride );
1942 py_1 = _py; 2026 py_1 = _py;
1943 py_2 = _py + this->y_stride; 2027 py_2 = _py + this->y_stride;
1944 pu = _pu; 2028 pu = _pu;
1945 pv = _pv; 2029 pv = _pv;
1946 2030
1947 width = this->source_width >> 3; 2031 width = this->source_width >> 3;
1948 do { 2032 do {
1949 RGB(0); 2033 X_RGB(0);
1950 DST1(0); 2034 DST1(0);
1951 DST2(0); 2035 DST2(0);
1952 2036
1953 RGB(1); 2037 X_RGB(1);
1954 DST2(1); 2038 DST2(1);
1955 DST1(1); 2039 DST1(1);
1956 2040
1957 RGB(2); 2041 X_RGB(2);
1958 DST1(2); 2042 DST1(2);
1959 DST2(2); 2043 DST2(2);
1960 2044
1961 RGB(3); 2045 X_RGB(3);
1962 DST2(3); 2046 DST2(3);
1963 DST1(3); 2047 DST1(3);
1964 2048
1965 pu += 4; 2049 pu += 4;
1966 pv += 4; 2050 pv += 4;
1967 py_1 += 8; 2051 py_1 += 8;
1968 py_2 += 8; 2052 py_2 += 8;
1969 dst_1 += 8; 2053 dst_1 += 8;
1970 dst_2 += 8; 2054 dst_2 += 8;
1971 } while (--width); 2055 } while (--width);
1972 2056
1973 _dst += 2 * this->rgb_stride; 2057 _dst += 2 * this->rgb_stride;
1974 _py += 2 * this->y_stride; 2058 _py += 2 * this->y_stride;
1975 _pu += this->uv_stride; 2059 _pu += this->uv_stride;
1976 _pv += this->uv_stride; 2060 _pv += this->uv_stride;
1977 2061
1978 } while (--height); 2062 } while (--height);
1979 } 2063 }
1980} 2064}
1981 2065
1982/* now for something different: 256 grayscale mode */ 2066/* now for something different: 256 grayscale mode */
1983static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, 2067static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst,
1984 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 2068 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
1985{ 2069{
1986 int height, dst_height; 2070 int height, dst_height;
1987 int dy; 2071 int dy;
1988 2072
1989 if (this->do_scale) { 2073 if (this->do_scale) {
1990 scale_line_func_t scale_line = this->scale_line; 2074 scale_line_func_t scale_line = this->scale_line;
1991 2075
1992 dy = 0; 2076 dy = 0;
1993 dst_height = this->dest_height; 2077 dst_height = this->next_slice (this, &_dst);
1994 2078
1995 for (;;) { 2079 for (;;) {
1996 scale_line (_py, _dst, this->dest_width, this->step_dx); 2080 scale_line (_py, _dst, this->dest_width, this->step_dx);
1997 2081
1998 dy += this->step_dy; 2082 dy += this->step_dy;
1999 _dst += this->rgb_stride; 2083 _dst += this->rgb_stride;
2000 2084
2001 while (--dst_height > 0 && dy < 32768) { 2085 while (--dst_height > 0 && dy < 32768) {
2002 2086
2003 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 2087 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
2004 2088
2005 dy += this->step_dy; 2089 dy += this->step_dy;
2006 _dst += this->rgb_stride; 2090 _dst += this->rgb_stride;
2007 } 2091 }
2008 2092
2009 if (dst_height <= 0) 2093 if (dst_height <= 0)
2010 break; 2094 break;
2011 2095
2012 _py += this->y_stride*(dy>>15); 2096 _py += this->y_stride*(dy>>15);
2013 dy &= 32767; 2097 dy &= 32767;
2014 /* dy -= 32768; 2098 /* dy -= 32768;
2015 _py += this->y_stride; 2099 _py += this->y_stride;
2016 */ 2100 */
2017 } 2101 }
2018 } else { 2102 } else {
2019 for (height = this->source_height; --height >= 0; ) { 2103 for (height = this->next_slice (this, &_dst); --height >= 0; ) {
2020 xine_fast_memcpy(_dst, _py, this->dest_width); 2104 xine_fast_memcpy(_dst, _py, this->dest_width);
2021 _dst += this->rgb_stride; 2105 _dst += this->rgb_stride;
2022 _py += this->y_stride; 2106 _py += this->y_stride;
2023 } 2107 }
2024 } 2108 }
2025} 2109}
2026 2110
2027/* now for something different: 256 color mode */ 2111/* now for something different: 256 color mode */
2028static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, 2112static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst,
2029 uint8_t * _py, uint8_t * _pu, uint8_t * _pv) 2113 uint8_t * _py, uint8_t * _pu, uint8_t * _pv)
2030{ 2114{
2031 int U, V, Y; 2115 int U, V, Y;
2032 uint8_t * py_1, * py_2, * pu, * pv; 2116 uint8_t * py_1, * py_2, * pu, * pv;
2033 uint16_t * r, * g, * b; 2117 uint16_t * r, * g, * b;
2034 uint8_t * dst_1, * dst_2; 2118 uint8_t * dst_1, * dst_2;
2035 int width, height, dst_height; 2119 int width, height, dst_height;
2036 int dy; 2120 int dy;
2037 2121
2038 if (this->do_scale) { 2122 if (this->do_scale) {
2039 scale_line_func_t scale_line = this->scale_line; 2123 scale_line_func_t scale_line = this->scale_line;
2040 2124
2041 scale_line (_pu, this->u_buffer, 2125 scale_line (_pu, this->u_buffer,
2042 this->dest_width >> 1, this->step_dx); 2126 this->dest_width >> 1, this->step_dx);
2043 scale_line (_pv, this->v_buffer, 2127 scale_line (_pv, this->v_buffer,
2044 this->dest_width >> 1, this->step_dx); 2128 this->dest_width >> 1, this->step_dx);
2045 scale_line (_py, this->y_buffer, 2129 scale_line (_py, this->y_buffer,
2046 this->dest_width, this->step_dx); 2130 this->dest_width, this->step_dx);
2047 2131
2048 dy = 0; 2132 dy = 0;
2049 dst_height = this->dest_height; 2133 dst_height = this->next_slice (this, &_dst);
2050 2134
2051 for (height = 0;; ) { 2135 for (height = 0;; ) {
2052 dst_1 = _dst; 2136 dst_1 = _dst;
2053 py_1 = this->y_buffer; 2137 py_1 = this->y_buffer;
2054 pu = this->u_buffer; 2138 pu = this->u_buffer;
2055 pv = this->v_buffer; 2139 pv = this->v_buffer;
2056 2140
2057 width = this->dest_width >> 3; 2141 width = this->dest_width >> 3;
2058 2142
2059 do { 2143 do {
2060 RGB(0); 2144 X_RGB(0);
2061 DST1CMAP(0); 2145 DST1CMAP(0);
2062 2146
2063 RGB(1); 2147 X_RGB(1);
2064 DST1CMAP(1); 2148 DST1CMAP(1);
2065 2149
2066 RGB(2); 2150 X_RGB(2);
2067 DST1CMAP(2); 2151 DST1CMAP(2);
2068 2152
2069 RGB(3); 2153 X_RGB(3);
2070 DST1CMAP(3); 2154 DST1CMAP(3);
2071 2155
2072 pu += 4; 2156 pu += 4;
2073 pv += 4; 2157 pv += 4;
2074 py_1 += 8; 2158 py_1 += 8;
2075 dst_1 += 8; 2159 dst_1 += 8;
2076 } while (--width); 2160 } while (--width);
2077 2161
2078 dy += this->step_dy; 2162 dy += this->step_dy;
2079 _dst += this->rgb_stride; 2163 _dst += this->rgb_stride;
2080 2164
2081 while (--dst_height > 0 && dy < 32768) { 2165 while (--dst_height > 0 && dy < 32768) {
2082 2166
2083 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 2167 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
2084 2168
2085 dy += this->step_dy; 2169 dy += this->step_dy;
2086 _dst += this->rgb_stride; 2170 _dst += this->rgb_stride;
2087 } 2171 }
2088 2172
2089 if (dst_height <= 0) 2173 if (dst_height <= 0)
2090 break; 2174 break;
2091 2175
2092 do { 2176 do {
2093 dy -= 32768; 2177 dy -= 32768;
2094 _py += this->y_stride; 2178 _py += this->y_stride;
2095 2179
2096 scale_line (_py, this->y_buffer, 2180 scale_line (_py, this->y_buffer,
2097 this->dest_width, this->step_dx); 2181 this->dest_width, this->step_dx);
2098 2182
2099 if (height & 1) { 2183 if (height & 1) {
2100 _pu += this->uv_stride; 2184 _pu += this->uv_stride;
2101 _pv += this->uv_stride; 2185 _pv += this->uv_stride;
2102 2186
2103 scale_line (_pu, this->u_buffer, 2187 scale_line (_pu, this->u_buffer,
2104 this->dest_width >> 1, this->step_dx); 2188 this->dest_width >> 1, this->step_dx);
2105 scale_line (_pv, this->v_buffer, 2189 scale_line (_pv, this->v_buffer,
2106 this->dest_width >> 1, this->step_dx); 2190 this->dest_width >> 1, this->step_dx);
2107 2191
2108 } 2192 }
2109 height++; 2193 height++;
2110 } while( dy>=32768 ); 2194 } while( dy>=32768 );
2111 } 2195 }
2112 } else { 2196 } else {
2113 height = this->source_height >> 1; 2197 height = this->next_slice (this, &_dst) >> 1;
2114 do { 2198 do {
2115 dst_1 = _dst; 2199 dst_1 = _dst;
2116 dst_2 = _dst + this->rgb_stride; 2200 dst_2 = _dst + this->rgb_stride;
2117 py_1 = _py; 2201 py_1 = _py;
2118 py_2 = _py + this->y_stride; 2202 py_2 = _py + this->y_stride;
2119 pu = _pu; 2203 pu = _pu;
2120 pv = _pv; 2204 pv = _pv;
2121 width = this->source_width >> 3; 2205 width = this->source_width >> 3;
2122 do { 2206 do {
2123 RGB(0); 2207 X_RGB(0);
2124 DST1CMAP(0); 2208 DST1CMAP(0);
2125 DST2CMAP(0); 2209 DST2CMAP(0);
2126 2210
2127 RGB(1); 2211 X_RGB(1);
2128 DST2CMAP(1); 2212 DST2CMAP(1);
2129 DST1CMAP(1); 2213 DST1CMAP(1);
2130 2214
2131 RGB(2); 2215 X_RGB(2);
2132 DST1CMAP(2); 2216 DST1CMAP(2);
2133 DST2CMAP(2); 2217 DST2CMAP(2);
2134 2218
2135 RGB(3); 2219 X_RGB(3);
2136 DST2CMAP(3); 2220 DST2CMAP(3);
2137 DST1CMAP(3); 2221 DST1CMAP(3);
2138 2222
2139 pu += 4; 2223 pu += 4;
2140 pv += 4; 2224 pv += 4;
2141 py_1 += 8; 2225 py_1 += 8;
2142 py_2 += 8; 2226 py_2 += 8;
2143 dst_1 += 8; 2227 dst_1 += 8;
2144 dst_2 += 8; 2228 dst_2 += 8;
2145 } while (--width); 2229 } while (--width);
2146 2230
2147 _dst += 2 * this->rgb_stride; 2231 _dst += 2 * this->rgb_stride;
2148 _py += 2 * this->y_stride; 2232 _py += 2 * this->y_stride;
2149 _pu += this->uv_stride; 2233 _pu += this->uv_stride;
2150 _pv += this->uv_stride; 2234 _pv += this->uv_stride;
2151 2235
2152 } while (--height); 2236 } while (--height);
2153 } 2237 }
2154} 2238}
2155 2239
2156static int div_round (int dividend, int divisor) 2240static int div_round (int dividend, int divisor)
2157{ 2241{
2158 if (dividend > 0) 2242 if (dividend > 0)
2159 return (dividend + (divisor>>1)) / divisor; 2243 return (dividend + (divisor>>1)) / divisor;
2160 else 2244 else
2161 return -((-dividend + (divisor>>1)) / divisor); 2245 return -((-dividend + (divisor>>1)) / divisor);
2162} 2246}
2163 2247
2164static void yuv2rgb_setup_tables (yuv2rgb_factory_t *this, int mode, int swapped) 2248static void yuv2rgb_set_csc_levels (yuv2rgb_factory_t *this,
2249 int brightness, int contrast, int saturation)
2165{ 2250{
2166 int i; 2251 int i;
2167 uint8_t table_Y[1024]; 2252 uint8_t table_Y[1024];
2168 uint32_t * table_32 = 0; 2253 uint32_t * table_32 = 0;
2169 uint16_t * table_16 = 0; 2254 uint16_t * table_16 = 0;
2170 uint8_t * table_8 = 0; 2255 uint8_t * table_8 = 0;
2171 int entry_size = 0; 2256 int entry_size = 0;
2172 void *table_r = 0, *table_g = 0, *table_b = 0; 2257 void *table_r = 0, *table_g = 0, *table_b = 0;
2173 int shift_r = 0, shift_g = 0, shift_b = 0; 2258 int shift_r = 0, shift_g = 0, shift_b = 0;
2174 2259
2175 int crv = Inverse_Table_6_9[this->matrix_coefficients][0]; 2260 int crv = Inverse_Table_6_9[this->matrix_coefficients][0];
2176 int cbu = Inverse_Table_6_9[this->matrix_coefficients][1]; 2261 int cbu = Inverse_Table_6_9[this->matrix_coefficients][1];
2177 int cgu = -Inverse_Table_6_9[this->matrix_coefficients][2]; 2262 int cgu = -Inverse_Table_6_9[this->matrix_coefficients][2];
2178 int cgv = -Inverse_Table_6_9[this->matrix_coefficients][3]; 2263 int cgv = -Inverse_Table_6_9[this->matrix_coefficients][3];
2179 2264
2265 int mode = this->mode;
2266 int swapped = this->swapped;
2267
2180 for (i = 0; i < 1024; i++) { 2268 for (i = 0; i < 1024; i++) {
2181 int j; 2269 int j;
2182 2270
2183 j = (76309 * (i - 384 - 16) + 32768) >> 16; 2271 j = (76309 * (i - 384 - 16 + brightness) + 32768) >> 16;
2184 j = (j < 0) ? 0 : ((j > 255) ? 255 : j); 2272 j = (j < 0) ? 0 : ((j > 255) ? 255 : j);
2185 table_Y[i] = j; 2273 table_Y[i] = j;
2186 } 2274 }
2187 2275
2188 switch (mode) { 2276 switch (mode) {
2189 case MODE_32_RGB: 2277 case MODE_32_RGB:
2190 case MODE_32_BGR: 2278 case MODE_32_BGR:
2191 table_32 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t)); 2279 if (this->table_base == NULL) {
2280 this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t));
2281 }
2282 table_32 = this->table_base;
2192 2283
2193 entry_size = sizeof (uint32_t); 2284 entry_size = sizeof (uint32_t);
2194 table_r = table_32 + 197; 2285 table_r = table_32 + 197;
2195 table_b = table_32 + 197 + 685; 2286 table_b = table_32 + 197 + 685;
2196 table_g = table_32 + 197 + 2*682; 2287 table_g = table_32 + 197 + 2*682;
2197 2288
2198 if (swapped) { 2289 if (swapped) {
2199 switch (mode) { 2290 switch (mode) {
2200 case MODE_32_RGB: shift_r = 8; shift_g = 16; shift_b = 24; break; 2291 case MODE_32_RGB: shift_r = 8; shift_g = 16; shift_b = 24; break;
2201 case MODE_32_BGR:shift_r = 24; shift_g = 16; shift_b = 8; break; 2292 case MODE_32_BGR:shift_r = 24; shift_g = 16; shift_b = 8; break;
2202 } 2293 }
2203 } else { 2294 } else {
2204 switch (mode) { 2295 switch (mode) {
2205 case MODE_32_RGB:shift_r = 16; shift_g = 8; shift_b = 0; break; 2296 case MODE_32_RGB:shift_r = 16; shift_g = 8; shift_b = 0; break;
2206 case MODE_32_BGR:shift_r = 0; shift_g = 8; shift_b = 16; break; 2297 case MODE_32_BGR:shift_r = 0; shift_g = 8; shift_b = 16; break;
2207 } 2298 }
2208 } 2299 }
2209 2300
2210 for (i = -197; i < 256+197; i++) 2301 for (i = -197; i < 256+197; i++)
2211 ((uint32_t *) table_r)[i] = table_Y[i+384] << shift_r; 2302 ((uint32_t *) table_r)[i] = table_Y[i+384] << shift_r;
2212 for (i = -132; i < 256+132; i++) 2303 for (i = -132; i < 256+132; i++)
2213 ((uint32_t *) table_g)[i] = table_Y[i+384] << shift_g; 2304 ((uint32_t *) table_g)[i] = table_Y[i+384] << shift_g;
2214 for (i = -232; i < 256+232; i++) 2305 for (i = -232; i < 256+232; i++)
2215 ((uint32_t *) table_b)[i] = table_Y[i+384] << shift_b; 2306 ((uint32_t *) table_b)[i] = table_Y[i+384] << shift_b;
2216 break; 2307 break;
2217 2308
2218 case MODE_24_RGB: 2309 case MODE_24_RGB:
2219 case MODE_24_BGR: 2310 case MODE_24_BGR:
2220 table_8 = malloc ((256 + 2*232) * sizeof (uint8_t)); 2311 if (this->table_base == NULL) {
2312 this->table_base = malloc ((256 + 2*232) * sizeof (uint8_t));
2313 }
2314 table_8 = this->table_base;
2221 2315
2222 entry_size = sizeof (uint8_t); 2316 entry_size = sizeof (uint8_t);
2223 table_r = table_g = table_b = table_8 + 232; 2317 table_r = table_g = table_b = table_8 + 232;
2224 2318
2225 for (i = -232; i < 256+232; i++) 2319 for (i = -232; i < 256+232; i++)
2226 ((uint8_t * )table_b)[i] = table_Y[i+384]; 2320 ((uint8_t * )table_b)[i] = table_Y[i+384];
2227 break; 2321 break;
2228 2322
2229 case MODE_15_BGR: 2323 case MODE_15_BGR:
2230 case MODE_16_BGR: 2324 case MODE_16_BGR:
2231 case MODE_15_RGB: 2325 case MODE_15_RGB:
2232 case MODE_16_RGB: 2326 case MODE_16_RGB:
2233 table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t)); 2327 if (this->table_base == NULL) {
2328 this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
2329 }
2330 table_16 = this->table_base;
2234 2331
2235 entry_size = sizeof (uint16_t); 2332 entry_size = sizeof (uint16_t);
2236 table_r = table_16 + 197; 2333 table_r = table_16 + 197;
2237 table_b = table_16 + 197 + 685; 2334 table_b = table_16 + 197 + 685;
2238 table_g = table_16 + 197 + 2*682; 2335 table_g = table_16 + 197 + 2*682;
2239 2336
2240 if (swapped) { 2337 if (swapped) {
2241 switch (mode) { 2338 switch (mode) {
2242 case MODE_15_BGR: shift_r = 8; shift_g = 5; shift_b = 2; break; 2339 case MODE_15_BGR: shift_r = 8; shift_g = 5; shift_b = 2; break;
2243 case MODE_16_BGR:shift_r = 8; shift_g = 5; shift_b = 3; break; 2340 case MODE_16_BGR:shift_r = 8; shift_g = 5; shift_b = 3; break;
2244 case MODE_15_RGB:shift_r = 2; shift_g = 5; shift_b = 8; break; 2341 case MODE_15_RGB:shift_r = 2; shift_g = 5; shift_b = 8; break;
2245 case MODE_16_RGB:shift_r = 3; shift_g = 5; shift_b = 8; break; 2342 case MODE_16_RGB:shift_r = 3; shift_g = 5; shift_b = 8; break;
2246 } 2343 }
2247 } else { 2344 } else {
2248 switch (mode) { 2345 switch (mode) {
2249 case MODE_15_BGR:shift_r = 0; shift_g = 5; shift_b = 10; break; 2346 case MODE_15_BGR:shift_r = 0; shift_g = 5; shift_b = 10; break;
2250 case MODE_16_BGR:shift_r = 0; shift_g = 5; shift_b = 11; break; 2347 case MODE_16_BGR:shift_r = 0; shift_g = 5; shift_b = 11; break;
2251 case MODE_15_RGB:shift_r = 10; shift_g = 5; shift_b = 0; break; 2348 case MODE_15_RGB:shift_r = 10; shift_g = 5; shift_b = 0; break;
2252 case MODE_16_RGB:shift_r = 11; shift_g = 5; shift_b = 0; break; 2349 case MODE_16_RGB:shift_r = 11; shift_g = 5; shift_b = 0; break;
2253 } 2350 }
2254 } 2351 }
2255 2352
2256 for (i = -197; i < 256+197; i++) 2353 for (i = -197; i < 256+197; i++)
2257 ((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << shift_r; 2354 ((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << shift_r;
2258 2355
2259 for (i = -132; i < 256+132; i++) { 2356 for (i = -132; i < 256+132; i++) {
2260 int j = table_Y[i+384] >> (((mode==MODE_16_RGB) || (mode==MODE_16_BGR)) ? 2 : 3); 2357 int j = table_Y[i+384] >> (((mode==MODE_16_RGB) || (mode==MODE_16_BGR)) ? 2 : 3);
2261 if (swapped) 2358 if (swapped)
2262 ((uint16_t *)table_g)[i] = (j&7) << 13 | (j>>3); 2359 ((uint16_t *)table_g)[i] = (j&7) << 13 | (j>>3);
2263 else 2360 else
2264 ((uint16_t *)table_g)[i] = j << 5; 2361 ((uint16_t *)table_g)[i] = j << 5;
2265 } 2362 }
2266 for (i = -232; i < 256+232; i++) 2363 for (i = -232; i < 256+232; i++)
2267 ((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << shift_b; 2364 ((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << shift_b;
2268 2365
2269 break; 2366 break;
2270 2367
2271 case MODE_8_RGB: 2368 case MODE_8_RGB:
2272 case MODE_8_BGR: 2369 case MODE_8_BGR:
2273 table_8 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t)); 2370 if (this->table_base == NULL) {
2371 this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t));
2372 }
2373 table_8 = this->table_base;
2274 2374
2275 entry_size = sizeof (uint8_t); 2375 entry_size = sizeof (uint8_t);
2276 table_r = table_8 + 197; 2376 table_r = table_8 + 197;
2277 table_b = table_8 + 197 + 685; 2377 table_b = table_8 + 197 + 685;
2278 table_g = table_8 + 197 + 2*682; 2378 table_g = table_8 + 197 + 2*682;
2279 2379
2280 switch (mode) { 2380 switch (mode) {
2281 case MODE_8_RGB: shift_r = 5; shift_g = 2; shift_b = 0; break; 2381 case MODE_8_RGB: shift_r = 5; shift_g = 2; shift_b = 0; break;
2282 case MODE_8_BGR: shift_r = 0; shift_g = 3; shift_b = 6; break; 2382 case MODE_8_BGR: shift_r = 0; shift_g = 3; shift_b = 6; break;
2283 } 2383 }
2284 2384
2285 for (i = -197; i < 256+197; i++) 2385 for (i = -197; i < 256+197; i++)
2286 ((uint8_t *) table_r)[i] = (table_Y[i+384] >> 5) << shift_r; 2386 ((uint8_t *) table_r)[i] = (table_Y[i+384] >> 5) << shift_r;
2287 for (i = -132; i < 256+132; i++) 2387 for (i = -132; i < 256+132; i++)
2288 ((uint8_t *) table_g)[i] = (table_Y[i+384] >> 5) << shift_g; 2388 ((uint8_t *) table_g)[i] = (table_Y[i+384] >> 5) << shift_g;
2289 for (i = -232; i < 256+232; i++) 2389 for (i = -232; i < 256+232; i++)
2290 ((uint8_t *) table_b)[i] = (table_Y[i+384] >> 6) << shift_b; 2390 ((uint8_t *) table_b)[i] = (table_Y[i+384] >> 6) << shift_b;
2291 break; 2391 break;
2292 2392
2293 case MODE_8_GRAY: 2393 case MODE_8_GRAY:
2294 return; 2394 return;
2295 2395
2296 case MODE_PALETTE: 2396 case MODE_PALETTE:
2297 table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t)); 2397 if (this->table_base == NULL) {
2398 this->table_base = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t));
2399 }
2400 table_16 = this->table_base;
2298 2401
2299 entry_size = sizeof (uint16_t); 2402 entry_size = sizeof (uint16_t);
2300 table_r = table_16 + 197; 2403 table_r = table_16 + 197;
2301 table_b = table_16 + 197 + 685; 2404 table_b = table_16 + 197 + 685;
2302 table_g = table_16 + 197 + 2*682; 2405 table_g = table_16 + 197 + 2*682;
2303 2406
2304 shift_r = 10; 2407 shift_r = 10;
2305 shift_g = 5; 2408 shift_g = 5;
2306 shift_b = 0; 2409 shift_b = 0;
2307 2410
2308 for (i = -197; i < 256+197; i++) 2411 for (i = -197; i < 256+197; i++)
2309 ((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << 10; 2412 ((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << 10;
2310 2413
2311 for (i = -132; i < 256+132; i++) 2414 for (i = -132; i < 256+132; i++)
2312 ((uint16_t *)table_g)[i] = (table_Y[i+384] >> 3) << 5; 2415 ((uint16_t *)table_g)[i] = (table_Y[i+384] >> 3) << 5;
2313 2416
2314 for (i = -232; i < 256+232; i++) 2417 for (i = -232; i < 256+232; i++)
2315 ((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << 0; 2418 ((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << 0;
2316 2419
2317 break; 2420 break;
2318 2421
2319 2422
2320 default: 2423 default:
2321 fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode); 2424 lprintf ("mode %d not supported by yuv2rgb\n", mode);
2322 abort(); 2425 _x_abort();
2323 } 2426 }
2324 2427
2325 for (i = 0; i < 256; i++) { 2428 for (i = 0; i < 256; i++) {
2326 this->table_rV[i] = (((uint8_t *) table_r) + 2429 this->table_rV[i] = (((uint8_t *) table_r) +
2327 entry_size * div_round (crv * (i-128), 76309)); 2430 entry_size * div_round (crv * (i-128), 76309));
2328 this->table_gU[i] = (((uint8_t *) table_g) + 2431 this->table_gU[i] = (((uint8_t *) table_g) +
2329 entry_size * div_round (cgu * (i-128), 76309)); 2432 entry_size * div_round (cgu * (i-128), 76309));
2330 this->table_gV[i] = entry_size * div_round (cgv * (i-128), 76309); 2433 this->table_gV[i] = entry_size * div_round (cgv * (i-128), 76309);
2331 this->table_bU[i] = (((uint8_t *)table_b) + 2434 this->table_bU[i] = (((uint8_t *)table_b) +
2332 entry_size * div_round (cbu * (i-128), 76309)); 2435 entry_size * div_round (cbu * (i-128), 76309));
2333 } 2436 }
2334 this->gamma = 0; 2437
2335 this->entry_size = entry_size; 2438#if defined(ARCH_X86) || defined(ARCH_X86_64)
2439 mmx_yuv2rgb_set_csc_levels (this, brightness, contrast, saturation);
2440#endif
2336} 2441}
2337 2442
2338static uint32_t yuv2rgb_single_pixel_32 (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v) 2443static uint32_t yuv2rgb_single_pixel_32 (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v)
2339{ 2444{
2340 uint32_t * r, * g, * b; 2445 uint32_t * r, * g, * b;
2341 2446
2342 r = this->table_rV[v]; 2447 r = this->table_rV[v];
2343 g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]); 2448 g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]);
2344 b = this->table_bU[u]; 2449 b = this->table_bU[u];
2345 2450
2346 return r[y] + g[y] + b[y]; 2451 return r[y] + g[y] + b[y];
2347} 2452}
2348 2453
2349static uint32_t yuv2rgb_single_pixel_24_rgb (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v) 2454static uint32_t yuv2rgb_single_pixel_24_rgb (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v)
2350{ 2455{
2351 uint8_t * r, * g, * b; 2456 uint8_t * r, * g, * b;
2352 2457
2353 r = this->table_rV[v]; 2458 r = this->table_rV[v];
2354 g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]); 2459 g = (void *) (((uint8_t *)this->table_gU[u]) + this->table_gV[v]);
2355 b = this->table_bU[u]; 2460 b = this->table_bU[u];
2356 2461
2357 return (uint32_t) r[y] + 2462 return (uint32_t) r[y] +
2358 ((uint32_t) g[y] << 8) + 2463 ((uint32_t) g[y] << 8) +
2359 ((uint32_t) b[y] << 16); 2464 ((uint32_t) b[y] << 16);
@@ -2427,741 +2532,746 @@ static void yuv2rgb_c_init (yuv2rgb_factory_t *this)
2427 : yuv2rgb_c_24_bgr; 2532 : yuv2rgb_c_24_bgr;
2428 break; 2533 break;
2429 2534
2430 case MODE_15_BGR: 2535 case MODE_15_BGR:
2431 case MODE_16_BGR: 2536 case MODE_16_BGR:
2432 case MODE_15_RGB: 2537 case MODE_15_RGB:
2433 case MODE_16_RGB: 2538 case MODE_16_RGB:
2434 this->yuv2rgb_fun = yuv2rgb_c_16; 2539 this->yuv2rgb_fun = yuv2rgb_c_16;
2435 break; 2540 break;
2436 2541
2437 case MODE_8_RGB: 2542 case MODE_8_RGB:
2438 case MODE_8_BGR: 2543 case MODE_8_BGR:
2439 this->yuv2rgb_fun = yuv2rgb_c_8; 2544 this->yuv2rgb_fun = yuv2rgb_c_8;
2440 break; 2545 break;
2441 2546
2442 case MODE_8_GRAY: 2547 case MODE_8_GRAY:
2443 this->yuv2rgb_fun = yuv2rgb_c_gray; 2548 this->yuv2rgb_fun = yuv2rgb_c_gray;
2444 break; 2549 break;
2445 2550
2446 case MODE_PALETTE: 2551 case MODE_PALETTE:
2447 this->yuv2rgb_fun = yuv2rgb_c_palette; 2552 this->yuv2rgb_fun = yuv2rgb_c_palette;
2448 break; 2553 break;
2449 2554
2450 default: 2555 default:
2451 printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode); 2556 lprintf ("mode %d not supported by yuv2rgb\n", this->mode);
2452 abort(); 2557 _x_abort();
2453 } 2558 }
2454 2559
2455} 2560}
2456 2561
2457static void yuv2rgb_single_pixel_init (yuv2rgb_factory_t *this) { 2562static void yuv2rgb_single_pixel_init (yuv2rgb_factory_t *this) {
2458 2563
2459 switch (this->mode) { 2564 switch (this->mode) {
2460 case MODE_32_RGB: 2565 case MODE_32_RGB:
2461 case MODE_32_BGR: 2566 case MODE_32_BGR:
2462 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_32; 2567 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_32;
2463 break; 2568 break;
2464 2569
2465 case MODE_24_RGB: 2570 case MODE_24_RGB:
2466 case MODE_24_BGR: 2571 case MODE_24_BGR:
2467 this->yuv2rgb_single_pixel_fun = 2572 this->yuv2rgb_single_pixel_fun =
2468 (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped) 2573 (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped)
2469 ? yuv2rgb_single_pixel_24_rgb 2574 ? yuv2rgb_single_pixel_24_rgb
2470 : yuv2rgb_single_pixel_24_bgr; 2575 : yuv2rgb_single_pixel_24_bgr;
2471 break; 2576 break;
2472 2577
2473 case MODE_15_BGR: 2578 case MODE_15_BGR:
2474 case MODE_16_BGR: 2579 case MODE_16_BGR:
2475 case MODE_15_RGB: 2580 case MODE_15_RGB:
2476 case MODE_16_RGB: 2581 case MODE_16_RGB:
2477 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_16; 2582 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_16;
2478 break; 2583 break;
2479 2584
2480 case MODE_8_RGB: 2585 case MODE_8_RGB:
2481 case MODE_8_BGR: 2586 case MODE_8_BGR:
2482 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_8; 2587 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_8;
2483 break; 2588 break;
2484 2589
2485 case MODE_8_GRAY: 2590 case MODE_8_GRAY:
2486 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_gray; 2591 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_gray;
2487 break; 2592 break;
2488 2593
2489 case MODE_PALETTE: 2594 case MODE_PALETTE:
2490 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_palette; 2595 this->yuv2rgb_single_pixel_fun = yuv2rgb_single_pixel_palette;
2491 break; 2596 break;
2492 2597
2493 default: 2598 default:
2494 printf ("yuv2rgb: mode %d not supported by yuv2rgb\n", this->mode); 2599 lprintf ("mode %d not supported by yuv2rgb\n", this->mode);
2495 abort(); 2600 _x_abort();
2496 } 2601 }
2497} 2602}
2498 2603
2499 2604
2500/* 2605/*
2501 * yuy2 stuff 2606 * yuy2 stuff
2502 */ 2607 */
2503 2608
2504static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2609static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2505{ 2610{
2506 int U, V, Y; 2611 int U, V, Y;
2507 uint8_t * py_1, * pu, * pv; 2612 uint8_t * py_1, * pu, * pv;
2508 uint32_t * r, * g, * b; 2613 uint32_t * r, * g, * b;
2509 uint32_t * dst_1; 2614 uint32_t * dst_1;
2510 int width, height; 2615 int width, height;
2511 int dy; 2616 int dy;
2512 2617
2513 /* FIXME: implement unscaled version */ 2618 /* FIXME: implement unscaled version */
2514 2619
2515 scale_line_4 (_p+1, this->u_buffer, 2620 scale_line_4 (_p+1, this->u_buffer,
2516 this->dest_width >> 1, this->step_dx); 2621 this->dest_width >> 1, this->step_dx);
2517 scale_line_4 (_p+3, this->v_buffer, 2622 scale_line_4 (_p+3, this->v_buffer,
2518 this->dest_width >> 1, this->step_dx); 2623 this->dest_width >> 1, this->step_dx);
2519 scale_line_2 (_p, this->y_buffer, 2624 scale_line_2 (_p, this->y_buffer,
2520 this->dest_width, this->step_dx); 2625 this->dest_width, this->step_dx);
2521 2626
2522 dy = 0; 2627 dy = 0;
2523 height = this->dest_height; 2628 height = this->next_slice (this, &_dst);
2524 2629
2525 for (;;) { 2630 for (;;) {
2526 dst_1 = (uint32_t*)_dst; 2631 dst_1 = (uint32_t*)_dst;
2527 py_1 = this->y_buffer; 2632 py_1 = this->y_buffer;
2528 pu = this->u_buffer; 2633 pu = this->u_buffer;
2529 pv = this->v_buffer; 2634 pv = this->v_buffer;
2530 2635
2531 width = this->dest_width >> 3; 2636 width = this->dest_width >> 3;
2532 2637
2533 do { 2638 do {
2534 2639
2535 RGB(0); 2640 X_RGB(0);
2536 DST1(0); 2641 DST1(0);
2537 2642
2538 RGB(1); 2643 X_RGB(1);
2539 DST1(1); 2644 DST1(1);
2540 2645
2541 RGB(2); 2646 X_RGB(2);
2542 DST1(2); 2647 DST1(2);
2543 2648
2544 RGB(3); 2649 X_RGB(3);
2545 DST1(3); 2650 DST1(3);
2546 2651
2547 pu += 4; 2652 pu += 4;
2548 pv += 4; 2653 pv += 4;
2549 py_1 += 8; 2654 py_1 += 8;
2550 dst_1 += 8; 2655 dst_1 += 8;
2551 } while (--width); 2656 } while (--width);
2552 2657
2553 dy += this->step_dy; 2658 dy += this->step_dy;
2554 _dst += this->rgb_stride; 2659 _dst += this->rgb_stride;
2555 2660
2556 while (--height > 0 && dy < 32768) { 2661 while (--height > 0 && dy < 32768) {
2557 2662
2558 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); 2663 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4);
2559 2664
2560 dy += this->step_dy; 2665 dy += this->step_dy;
2561 _dst += this->rgb_stride; 2666 _dst += this->rgb_stride;
2562 } 2667 }
2563 2668
2564 if (height <= 0) 2669 if (height <= 0)
2565 break; 2670 break;
2566 2671
2567 _p += this->y_stride*2*(dy>>15); 2672 _p += this->y_stride*(dy>>15);
2568 dy &= 32767; 2673 dy &= 32767;
2569 /* 2674 /*
2570 dy -= 32768; 2675 dy -= 32768;
2571 _p += this->y_stride*2; 2676 _p += this->y_stride*2;
2572 */ 2677 */
2573 2678
2574 scale_line_4 (_p+1, this->u_buffer, 2679 scale_line_4 (_p+1, this->u_buffer,
2575 this->dest_width >> 1, this->step_dx); 2680 this->dest_width >> 1, this->step_dx);
2576 scale_line_4 (_p+3, this->v_buffer, 2681 scale_line_4 (_p+3, this->v_buffer,
2577 this->dest_width >> 1, this->step_dx); 2682 this->dest_width >> 1, this->step_dx);
2578 scale_line_2 (_p, this->y_buffer, 2683 scale_line_2 (_p, this->y_buffer,
2579 this->dest_width, this->step_dx); 2684 this->dest_width, this->step_dx);
2580 } 2685 }
2581} 2686}
2582 2687
2583static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2688static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2584{ 2689{
2585 int U, V, Y; 2690 int U, V, Y;
2586 uint8_t * py_1, * pu, * pv; 2691 uint8_t * py_1, * pu, * pv;
2587 uint8_t * r, * g, * b; 2692 uint8_t * r, * g, * b;
2588 uint8_t * dst_1; 2693 uint8_t * dst_1;
2589 int width, height; 2694 int width, height;
2590 int dy; 2695 int dy;
2591 2696
2592 /* FIXME: implement unscaled version */ 2697 /* FIXME: implement unscaled version */
2593 2698
2594 scale_line_4 (_p+1, this->u_buffer, 2699 scale_line_4 (_p+1, this->u_buffer,
2595 this->dest_width >> 1, this->step_dx); 2700 this->dest_width >> 1, this->step_dx);
2596 scale_line_4 (_p+3, this->v_buffer, 2701 scale_line_4 (_p+3, this->v_buffer,
2597 this->dest_width >> 1, this->step_dx); 2702 this->dest_width >> 1, this->step_dx);
2598 scale_line_2 (_p, this->y_buffer, 2703 scale_line_2 (_p, this->y_buffer,
2599 this->dest_width, this->step_dx); 2704 this->dest_width, this->step_dx);
2600 2705
2601 dy = 0; 2706 dy = 0;
2602 height = this->dest_height; 2707 height = this->next_slice (this, &_dst);
2603 2708
2604 for (;;) { 2709 for (;;) {
2605 dst_1 = _dst; 2710 dst_1 = _dst;
2606 py_1 = this->y_buffer; 2711 py_1 = this->y_buffer;
2607 pu = this->u_buffer; 2712 pu = this->u_buffer;
2608 pv = this->v_buffer; 2713 pv = this->v_buffer;
2609 2714
2610 width = this->dest_width >> 3; 2715 width = this->dest_width >> 3;
2611 2716
2612 do { 2717 do {
2613 RGB(0); 2718 X_RGB(0);
2614 DST1RGB(0); 2719 DST1RGB(0);
2615 2720
2616 RGB(1); 2721 X_RGB(1);
2617 DST1RGB(1); 2722 DST1RGB(1);
2618 2723
2619 RGB(2); 2724 X_RGB(2);
2620 DST1RGB(2); 2725 DST1RGB(2);
2621 2726
2622 RGB(3); 2727 X_RGB(3);
2623 DST1RGB(3); 2728 DST1RGB(3);
2624 2729
2625 pu += 4; 2730 pu += 4;
2626 pv += 4; 2731 pv += 4;
2627 py_1 += 8; 2732 py_1 += 8;
2628 dst_1 += 24; 2733 dst_1 += 24;
2629 } while (--width); 2734 } while (--width);
2630 2735
2631 dy += this->step_dy; 2736 dy += this->step_dy;
2632 _dst += this->rgb_stride; 2737 _dst += this->rgb_stride;
2633 2738
2634 while (--height > 0 && dy < 32768) { 2739 while (--height > 0 && dy < 32768) {
2635 2740
2636 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); 2741 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3);
2637 2742
2638 dy += this->step_dy; 2743 dy += this->step_dy;
2639 _dst += this->rgb_stride; 2744 _dst += this->rgb_stride;
2640 } 2745 }
2641 2746
2642 if (height <= 0) 2747 if (height <= 0)
2643 break; 2748 break;
2644 2749
2645 _p += this->y_stride*2*(dy>>15); 2750 _p += this->y_stride*(dy>>15);
2646 dy &= 32767; 2751 dy &= 32767;
2647 /* 2752 /*
2648 dy -= 32768; 2753 dy -= 32768;
2649 _p += this->y_stride*2; 2754 _p += this->y_stride*2;
2650 */ 2755 */
2651 2756
2652 scale_line_4 (_p+1, this->u_buffer, 2757 scale_line_4 (_p+1, this->u_buffer,
2653 this->dest_width >> 1, this->step_dx); 2758 this->dest_width >> 1, this->step_dx);
2654 scale_line_4 (_p+3, this->v_buffer, 2759 scale_line_4 (_p+3, this->v_buffer,
2655 this->dest_width >> 1, this->step_dx); 2760 this->dest_width >> 1, this->step_dx);
2656 scale_line_2 (_p, this->y_buffer, 2761 scale_line_2 (_p, this->y_buffer,
2657 this->dest_width, this->step_dx); 2762 this->dest_width, this->step_dx);
2658 } 2763 }
2659} 2764}
2660 2765
2661static void yuy22rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2766static void yuy22rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2662{ 2767{
2663 int U, V, Y; 2768 int U, V, Y;
2664 uint8_t * py_1, * pu, * pv; 2769 uint8_t * py_1, * pu, * pv;
2665 uint8_t * r, * g, * b; 2770 uint8_t * r, * g, * b;
2666 uint8_t * dst_1; 2771 uint8_t * dst_1;
2667 int width, height; 2772 int width, height;
2668 int dy; 2773 int dy;
2669 2774
2670 /* FIXME: implement unscaled version */ 2775 /* FIXME: implement unscaled version */
2671 2776
2672 scale_line_4 (_p+1, this->u_buffer, 2777 scale_line_4 (_p+1, this->u_buffer,
2673 this->dest_width >> 1, this->step_dx); 2778 this->dest_width >> 1, this->step_dx);
2674 scale_line_4 (_p+3, this->v_buffer, 2779 scale_line_4 (_p+3, this->v_buffer,
2675 this->dest_width >> 1, this->step_dx); 2780 this->dest_width >> 1, this->step_dx);
2676 scale_line_2 (_p, this->y_buffer, 2781 scale_line_2 (_p, this->y_buffer,
2677 this->dest_width, this->step_dx); 2782 this->dest_width, this->step_dx);
2678 2783
2679 dy = 0; 2784 dy = 0;
2680 height = this->dest_height; 2785 height = this->next_slice (this, &_dst);
2681 2786
2682 for (;;) { 2787 for (;;) {
2683 dst_1 = _dst; 2788 dst_1 = _dst;
2684 py_1 = this->y_buffer; 2789 py_1 = this->y_buffer;
2685 pu = this->u_buffer; 2790 pu = this->u_buffer;
2686 pv = this->v_buffer; 2791 pv = this->v_buffer;
2687 2792
2688 width = this->dest_width >> 3; 2793 width = this->dest_width >> 3;
2689 2794
2690 do { 2795 do {
2691 RGB(0); 2796 X_RGB(0);
2692 DST1BGR(0); 2797 DST1BGR(0);
2693 2798
2694 RGB(1); 2799 X_RGB(1);
2695 DST1BGR(1); 2800 DST1BGR(1);
2696 2801
2697 RGB(2); 2802 X_RGB(2);
2698 DST1BGR(2); 2803 DST1BGR(2);
2699 2804
2700 RGB(3); 2805 X_RGB(3);
2701 DST1BGR(3); 2806 DST1BGR(3);
2702 2807
2703 pu += 4; 2808 pu += 4;
2704 pv += 4; 2809 pv += 4;
2705 py_1 += 8; 2810 py_1 += 8;
2706 dst_1 += 24; 2811 dst_1 += 24;
2707 } while (--width); 2812 } while (--width);
2708 2813
2709 dy += this->step_dy; 2814 dy += this->step_dy;
2710 _dst += this->rgb_stride; 2815 _dst += this->rgb_stride;
2711 2816
2712 while (--height > 0 && dy < 32768) { 2817 while (--height > 0 && dy < 32768) {
2713 2818
2714 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); 2819 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3);
2715 2820
2716 dy += this->step_dy; 2821 dy += this->step_dy;
2717 _dst += this->rgb_stride; 2822 _dst += this->rgb_stride;
2718 } 2823 }
2719 2824
2720 if (height <= 0) 2825 if (height <= 0)
2721 break; 2826 break;
2722 2827
2723 _p += this->y_stride*2*(dy>>15); 2828 _p += this->y_stride*(dy>>15);
2724 dy &= 32767; 2829 dy &= 32767;
2725 2830
2726 scale_line_4 (_p+1, this->u_buffer, 2831 scale_line_4 (_p+1, this->u_buffer,
2727 this->dest_width >> 1, this->step_dx); 2832 this->dest_width >> 1, this->step_dx);
2728 scale_line_4 (_p+3, this->v_buffer, 2833 scale_line_4 (_p+3, this->v_buffer,
2729 this->dest_width >> 1, this->step_dx); 2834 this->dest_width >> 1, this->step_dx);
2730 scale_line_2 (_p, this->y_buffer, 2835 scale_line_2 (_p, this->y_buffer,
2731 this->dest_width, this->step_dx); 2836 this->dest_width, this->step_dx);
2732 } 2837 }
2733} 2838}
2734 2839
2735static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2840static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2736{ 2841{
2737 int U, V, Y; 2842 int U, V, Y;
2738 uint8_t * py_1, * pu, * pv; 2843 uint8_t * py_1, * pu, * pv;
2739 uint16_t * r, * g, * b; 2844 uint16_t * r, * g, * b;
2740 uint16_t * dst_1; 2845 uint16_t * dst_1;
2741 int width, height; 2846 int width, height;
2742 int dy; 2847 int dy;
2743 2848
2744 /* FIXME: implement unscaled version */ 2849 /* FIXME: implement unscaled version */
2745 2850
2746 scale_line_4 (_p+1, this->u_buffer, 2851 scale_line_4 (_p+1, this->u_buffer,
2747 this->dest_width >> 1, this->step_dx); 2852 this->dest_width >> 1, this->step_dx);
2748 scale_line_4 (_p+3, this->v_buffer, 2853 scale_line_4 (_p+3, this->v_buffer,
2749 this->dest_width >> 1, this->step_dx); 2854 this->dest_width >> 1, this->step_dx);
2750 scale_line_2 (_p, this->y_buffer, 2855 scale_line_2 (_p, this->y_buffer,
2751 this->dest_width, this->step_dx); 2856 this->dest_width, this->step_dx);
2752 2857
2753 dy = 0; 2858 dy = 0;
2754 height = this->dest_height; 2859 height = this->next_slice (this, &_dst);
2755 2860
2756 for (;;) { 2861 for (;;) {
2757 dst_1 = (uint16_t*)_dst; 2862 dst_1 = (uint16_t*)_dst;
2758 py_1 = this->y_buffer; 2863 py_1 = this->y_buffer;
2759 pu = this->u_buffer; 2864 pu = this->u_buffer;
2760 pv = this->v_buffer; 2865 pv = this->v_buffer;
2761 2866
2762 width = this->dest_width >> 3; 2867 width = this->dest_width >> 3;
2763 2868
2764 do { 2869 do {
2765 RGB(0); 2870 X_RGB(0);
2766 DST1(0); 2871 DST1(0);
2767 2872
2768 RGB(1); 2873 X_RGB(1);
2769 DST1(1); 2874 DST1(1);
2770 2875
2771 RGB(2); 2876 X_RGB(2);
2772 DST1(2); 2877 DST1(2);
2773 2878
2774 RGB(3); 2879 X_RGB(3);
2775 DST1(3); 2880 DST1(3);
2776 2881
2777 pu += 4; 2882 pu += 4;
2778 pv += 4; 2883 pv += 4;
2779 py_1 += 8; 2884 py_1 += 8;
2780 dst_1 += 8; 2885 dst_1 += 8;
2781 } while (--width); 2886 } while (--width);
2782 2887
2783 dy += this->step_dy; 2888 dy += this->step_dy;
2784 _dst += this->rgb_stride; 2889 _dst += this->rgb_stride;
2785 2890
2786 while (--height > 0 && dy < 32768) { 2891 while (--height > 0 && dy < 32768) {
2787 2892
2788 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); 2893 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2);
2789 2894
2790 dy += this->step_dy; 2895 dy += this->step_dy;
2791 _dst += this->rgb_stride; 2896 _dst += this->rgb_stride;
2792 } 2897 }
2793 2898
2794 if (height <= 0) 2899 if (height <= 0)
2795 break; 2900 break;
2796 2901
2797 _p += this->y_stride*2*(dy>>15); 2902 _p += this->y_stride*(dy>>15);
2798 dy &= 32767; 2903 dy &= 32767;
2799 2904
2800 scale_line_4 (_p+1, this->u_buffer, 2905 scale_line_4 (_p+1, this->u_buffer,
2801 this->dest_width >> 1, this->step_dx); 2906 this->dest_width >> 1, this->step_dx);
2802 scale_line_4 (_p+3, this->v_buffer, 2907 scale_line_4 (_p+3, this->v_buffer,
2803 this->dest_width >> 1, this->step_dx); 2908 this->dest_width >> 1, this->step_dx);
2804 scale_line_2 (_p, this->y_buffer, 2909 scale_line_2 (_p, this->y_buffer,
2805 this->dest_width, this->step_dx); 2910 this->dest_width, this->step_dx);
2806 } 2911 }
2807} 2912}
2808 2913
2809static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2914static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2810{ 2915{
2811 int U, V, Y; 2916 int U, V, Y;
2812 uint8_t * py_1, * pu, * pv; 2917 uint8_t * py_1, * pu, * pv;
2813 uint8_t * r, * g, * b; 2918 uint8_t * r, * g, * b;
2814 uint8_t * dst_1; 2919 uint8_t * dst_1;
2815 int width, height; 2920 int width, height;
2816 int dy; 2921 int dy;
2817 2922
2818 /* FIXME: implement unscaled version */ 2923 /* FIXME: implement unscaled version */
2819 2924
2820 scale_line_4 (_p+1, this->u_buffer, 2925 scale_line_4 (_p+1, this->u_buffer,
2821 this->dest_width >> 1, this->step_dx); 2926 this->dest_width >> 1, this->step_dx);
2822 scale_line_4 (_p+3, this->v_buffer, 2927 scale_line_4 (_p+3, this->v_buffer,
2823 this->dest_width >> 1, this->step_dx); 2928 this->dest_width >> 1, this->step_dx);
2824 scale_line_2 (_p, this->y_buffer, 2929 scale_line_2 (_p, this->y_buffer,
2825 this->dest_width, this->step_dx); 2930 this->dest_width, this->step_dx);
2826 2931
2827 dy = 0; 2932 dy = 0;
2828 height = this->dest_height; 2933 height = this->next_slice (this, &_dst);
2829 2934
2830 for (;;) { 2935 for (;;) {
2831 dst_1 = _dst; 2936 dst_1 = _dst;
2832 py_1 = this->y_buffer; 2937 py_1 = this->y_buffer;
2833 pu = this->u_buffer; 2938 pu = this->u_buffer;
2834 pv = this->v_buffer; 2939 pv = this->v_buffer;
2835 2940
2836 width = this->dest_width >> 3; 2941 width = this->dest_width >> 3;
2837 2942
2838 do { 2943 do {
2839 RGB(0); 2944 X_RGB(0);
2840 DST1(0); 2945 DST1(0);
2841 2946
2842 RGB(1); 2947 X_RGB(1);
2843 DST1(1); 2948 DST1(1);
2844 2949
2845 RGB(2); 2950 X_RGB(2);
2846 DST1(2); 2951 DST1(2);
2847 2952
2848 RGB(3); 2953 X_RGB(3);
2849 DST1(3); 2954 DST1(3);
2850 2955
2851 pu += 4; 2956 pu += 4;
2852 pv += 4; 2957 pv += 4;
2853 py_1 += 8; 2958 py_1 += 8;
2854 dst_1 += 8; 2959 dst_1 += 8;
2855 } while (--width); 2960 } while (--width);
2856 2961
2857 dy += this->step_dy; 2962 dy += this->step_dy;
2858 _dst += this->rgb_stride; 2963 _dst += this->rgb_stride;
2859 2964
2860 while (--height > 0 && dy < 32768) { 2965 while (--height > 0 && dy < 32768) {
2861 2966
2862 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 2967 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
2863 2968
2864 dy += this->step_dy; 2969 dy += this->step_dy;
2865 _dst += this->rgb_stride; 2970 _dst += this->rgb_stride;
2866 } 2971 }
2867 2972
2868 if (height <= 0) 2973 if (height <= 0)
2869 break; 2974 break;
2870 2975
2871 _p += this->y_stride*2*(dy>>15); 2976 _p += this->y_stride*(dy>>15);
2872 dy &= 32767; 2977 dy &= 32767;
2873 2978
2874 scale_line_4 (_p+1, this->u_buffer, 2979 scale_line_4 (_p+1, this->u_buffer,
2875 this->dest_width >> 1, this->step_dx); 2980 this->dest_width >> 1, this->step_dx);
2876 scale_line_4 (_p+3, this->v_buffer, 2981 scale_line_4 (_p+3, this->v_buffer,
2877 this->dest_width >> 1, this->step_dx); 2982 this->dest_width >> 1, this->step_dx);
2878 scale_line_2 (_p, this->y_buffer, 2983 scale_line_2 (_p, this->y_buffer,
2879 this->dest_width, this->step_dx); 2984 this->dest_width, this->step_dx);
2880 } 2985 }
2881} 2986}
2882 2987
2883static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 2988static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2884{ 2989{
2885 int width, height; 2990 int width, height;
2886 int dy; 2991 int dy;
2887 uint8_t * dst; 2992 uint8_t * dst;
2888 uint8_t * y; 2993 uint8_t * y;
2889 2994
2890 if (this->do_scale) { 2995 if (this->do_scale) {
2891 dy = 0; 2996 dy = 0;
2892 height = this->dest_height; 2997 height = this->next_slice (this, &_dst);
2893 2998
2894 for (;;) { 2999 for (;;) {
2895 scale_line_2 (_p, _dst, this->dest_width, this->step_dx); 3000 scale_line_2 (_p, _dst, this->dest_width, this->step_dx);
2896 3001
2897 dy += this->step_dy; 3002 dy += this->step_dy;
2898 _dst += this->rgb_stride; 3003 _dst += this->rgb_stride;
2899 3004
2900 while (--height > 0 && dy < 32768) { 3005 while (--height > 0 && dy < 32768) {
2901 3006
2902 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 3007 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
2903 3008
2904 dy += this->step_dy; 3009 dy += this->step_dy;
2905 _dst += this->rgb_stride; 3010 _dst += this->rgb_stride;
2906 } 3011 }
2907 3012
2908 if (height <= 0) 3013 if (height <= 0)
2909 break; 3014 break;
2910 3015
2911 _p += this->y_stride*2*(dy>>15); 3016 _p += this->y_stride*(dy>>15);
2912 dy &= 32767; 3017 dy &= 32767;
2913 } 3018 }
2914 } else { 3019 } else {
2915 for (height = this->source_height; --height >= 0; ) { 3020 for (height = this->next_slice (this, &_dst); --height >= 0; ) {
2916 dst = _dst; 3021 dst = _dst;
2917 y = _p; 3022 y = _p;
2918 for (width = this->source_width; --width >= 0; ) { 3023 for (width = this->source_width; --width >= 0; ) {
2919 *dst++ = *y; 3024 *dst++ = *y;
2920 y += 2; 3025 y += 2;
2921 } 3026 }
2922 _dst += this->rgb_stride; 3027 _dst += this->rgb_stride;
2923 _p += this->y_stride*2; 3028 _p += this->y_stride;
2924 } 3029 }
2925 } 3030 }
2926} 3031}
2927 3032
2928static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) 3033static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p)
2929{ 3034{
2930 int U, V, Y; 3035 int U, V, Y;
2931 uint8_t * py_1, * pu, * pv; 3036 uint8_t * py_1, * pu, * pv;
2932 uint16_t * r, * g, * b; 3037 uint16_t * r, * g, * b;
2933 uint8_t * dst_1; 3038 uint8_t * dst_1;
2934 int width, height; 3039 int width, height;
2935 int dy; 3040 int dy;
2936 3041
2937 scale_line_4 (_p+1, this->u_buffer, 3042 scale_line_4 (_p+1, this->u_buffer,
2938 this->dest_width >> 1, this->step_dx); 3043 this->dest_width >> 1, this->step_dx);
2939 scale_line_4 (_p+3, this->v_buffer, 3044 scale_line_4 (_p+3, this->v_buffer,
2940 this->dest_width >> 1, this->step_dx); 3045 this->dest_width >> 1, this->step_dx);
2941 scale_line_2 (_p, this->y_buffer, 3046 scale_line_2 (_p, this->y_buffer,
2942 this->dest_width, this->step_dx); 3047 this->dest_width, this->step_dx);
2943 3048
2944 dy = 0; 3049 dy = 0;
2945 height = this->dest_height; 3050 height = this->next_slice (this, &_dst);
2946 3051
2947 for (;;) { 3052 for (;;) {
2948 dst_1 = _dst; 3053 dst_1 = _dst;
2949 py_1 = this->y_buffer; 3054 py_1 = this->y_buffer;
2950 pu = this->u_buffer; 3055 pu = this->u_buffer;
2951 pv = this->v_buffer; 3056 pv = this->v_buffer;
2952 3057
2953 width = this->dest_width >> 3; 3058 width = this->dest_width >> 3;
2954 3059
2955 do { 3060 do {
2956 RGB(0); 3061 X_RGB(0);
2957 DST1CMAP(0); 3062 DST1CMAP(0);
2958 3063
2959 RGB(1); 3064 X_RGB(1);
2960 DST1CMAP(1); 3065 DST1CMAP(1);
2961 3066
2962 RGB(2); 3067 X_RGB(2);
2963 DST1CMAP(2); 3068 DST1CMAP(2);
2964 3069
2965 RGB(3); 3070 X_RGB(3);
2966 DST1CMAP(3); 3071 DST1CMAP(3);
2967 3072
2968 pu += 4; 3073 pu += 4;
2969 pv += 4; 3074 pv += 4;
2970 py_1 += 8; 3075 py_1 += 8;
2971 dst_1 += 8; 3076 dst_1 += 8;
2972 } while (--width); 3077 } while (--width);
2973 3078
2974 dy += this->step_dy; 3079 dy += this->step_dy;
2975 _dst += this->rgb_stride; 3080 _dst += this->rgb_stride;
2976 3081
2977 while (--height > 0 && dy < 32768) { 3082 while (--height > 0 && dy < 32768) {
2978 3083
2979 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); 3084 xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width);
2980 3085
2981 dy += this->step_dy; 3086 dy += this->step_dy;
2982 _dst += this->rgb_stride; 3087 _dst += this->rgb_stride;
2983 } 3088 }
2984 3089
2985 if (height <= 0) 3090 if (height <= 0)
2986 break; 3091 break;
2987 3092
2988 _p += this->y_stride*2*(dy>>15); 3093 _p += this->y_stride*(dy>>15);
2989 dy &= 32767; 3094 dy &= 32767;
2990 3095
2991 scale_line_4 (_p+1, this->u_buffer, 3096 scale_line_4 (_p+1, this->u_buffer,
2992 this->dest_width >> 1, this->step_dx); 3097 this->dest_width >> 1, this->step_dx);
2993 scale_line_4 (_p+3, this->v_buffer, 3098 scale_line_4 (_p+3, this->v_buffer,
2994 this->dest_width >> 1, this->step_dx); 3099 this->dest_width >> 1, this->step_dx);
2995 scale_line_2 (_p, this->y_buffer, 3100 scale_line_2 (_p, this->y_buffer,
2996 this->dest_width, this->step_dx); 3101 this->dest_width, this->step_dx);
2997 } 3102 }
2998} 3103}
2999 3104
3000static void yuy22rgb_c_init (yuv2rgb_factory_t *this) 3105static void yuy22rgb_c_init (yuv2rgb_factory_t *this)
3001{ 3106{
3002 switch (this->mode) { 3107 switch (this->mode) {
3003 case MODE_32_RGB: 3108 case MODE_32_RGB:
3004 case MODE_32_BGR: 3109 case MODE_32_BGR:
3005 this->yuy22rgb_fun = yuy22rgb_c_32; 3110 this->yuy22rgb_fun = yuy22rgb_c_32;
3006 break; 3111 break;
3007 3112
3008 case MODE_24_RGB: 3113 case MODE_24_RGB:
3009 case MODE_24_BGR: 3114 case MODE_24_BGR:
3010 this->yuy22rgb_fun = 3115 this->yuy22rgb_fun =
3011 (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped) 3116 (this->mode==MODE_24_RGB && !this->swapped) || (this->mode==MODE_24_BGR && this->swapped)
3012 ? yuy22rgb_c_24_rgb 3117 ? yuy22rgb_c_24_rgb
3013 : yuy22rgb_c_24_bgr; 3118 : yuy22rgb_c_24_bgr;
3014 break; 3119 break;
3015 case MODE_15_BGR: 3120 case MODE_15_BGR:
3016 case MODE_16_BGR: 3121 case MODE_16_BGR:
3017 case MODE_15_RGB: 3122 case MODE_15_RGB:
3018 case MODE_16_RGB: 3123 case MODE_16_RGB:
3019 this->yuy22rgb_fun = yuy22rgb_c_16; 3124 this->yuy22rgb_fun = yuy22rgb_c_16;
3020 break; 3125 break;
3021 3126
3022 case MODE_8_RGB: 3127 case MODE_8_RGB:
3023 case MODE_8_BGR: 3128 case MODE_8_BGR:
3024 this->yuy22rgb_fun = yuy22rgb_c_8; 3129 this->yuy22rgb_fun = yuy22rgb_c_8;
3025 break; 3130 break;
3026 3131
3027 case MODE_8_GRAY: 3132 case MODE_8_GRAY:
3028 this->yuy22rgb_fun = yuy22rgb_c_gray; 3133 this->yuy22rgb_fun = yuy22rgb_c_gray;
3029 break; 3134 break;
3030 3135
3031 case MODE_PALETTE: 3136 case MODE_PALETTE:
3032 this->yuy22rgb_fun = yuy22rgb_c_palette; 3137 this->yuy22rgb_fun = yuy22rgb_c_palette;
3033 break; 3138 break;
3034 3139
3035 default: 3140 default:
3036 printf ("yuv2rgb: mode %d not supported for yuy2\n", this->mode); 3141 lprintf ("mode %d not supported for yuy2\n", this->mode);
3037 } 3142 }
3038} 3143}
3039 3144
3040yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) { 3145static yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) {
3041 3146
3042 yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t)); 3147 yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t));
3043 3148
3149 this->swapped = factory->swapped;
3044 this->cmap = factory->cmap; 3150 this->cmap = factory->cmap;
3045 3151
3046 this->y_chunk = this->y_buffer = NULL; 3152 this->y_chunk = this->y_buffer = NULL;
3047 this->u_chunk = this->u_buffer = NULL; 3153 this->u_chunk = this->u_buffer = NULL;
3048 this->v_chunk = this->v_buffer = NULL; 3154 this->v_chunk = this->v_buffer = NULL;
3049 3155
3156#ifdef HAVE_MLIB
3157 this->mlib_chunk = this->mlib_buffer = NULL;
3158 this->mlib_resize_chunk = this->mlib_resize_buffer = NULL;
3159 this->mlib_filter_type = MLIB_BILINEAR;
3160#endif
3161
3050 this->table_rV = factory->table_rV; 3162 this->table_rV = factory->table_rV;
3051 this->table_gU = factory->table_gU; 3163 this->table_gU = factory->table_gU;
3052 this->table_gV = factory->table_gV; 3164 this->table_gV = factory->table_gV;
3053 this->table_bU = factory->table_bU; 3165 this->table_bU = factory->table_bU;
3166 this->table_mmx = factory->table_mmx;
3054 3167
3055 this->yuv2rgb_fun = factory->yuv2rgb_fun; 3168 this->yuv2rgb_fun = factory->yuv2rgb_fun;
3056 this->yuy22rgb_fun = factory->yuy22rgb_fun; 3169 this->yuy22rgb_fun = factory->yuy22rgb_fun;
3057 this->yuv2rgb_single_pixel_fun = factory->yuv2rgb_single_pixel_fun; 3170 this->yuv2rgb_single_pixel_fun = factory->yuv2rgb_single_pixel_fun;
3058 3171
3059 this->configure = yuv2rgb_configure; 3172 this->configure = yuv2rgb_configure;
3173 this->next_slice = yuv2rgb_next_slice;
3174 this->dispose = yuv2rgb_dispose;
3060 return this; 3175 return this;
3061} 3176}
3062 3177
3063/* 3178/*
3064 * factory functions 3179 * factory functions
3065 */ 3180 */
3066void yuv2rgb_set_gamma (yuv2rgb_factory_t *this, int gamma) {
3067
3068 int i;
3069
3070 for (i = 0; i < 256; i++) {
3071 (uint8_t *)this->table_rV[i] += this->entry_size*(gamma - this->gamma);
3072 (uint8_t *)this->table_gU[i] += this->entry_size*(gamma - this->gamma);
3073 (uint8_t *)this->table_bU[i] += this->entry_size*(gamma - this->gamma);
3074 }
3075#ifdef ARCH_X86
3076 mmx_yuv2rgb_set_gamma(gamma);
3077#endif
3078 this->gamma = gamma;
3079}
3080 3181
3081int yuv2rgb_get_gamma (yuv2rgb_factory_t *this) { 3182static void yuv2rgb_factory_dispose (yuv2rgb_factory_t *this) {
3082 3183
3083 return this->gamma; 3184 free (this->table_base);
3185 free (this->table_mmx_base);
3186 free (this);
3084} 3187}
3085 3188
3086yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped, 3189yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped,
3087 uint8_t *cmap) { 3190 uint8_t *cmap) {
3088 3191
3089 yuv2rgb_factory_t *this; 3192 yuv2rgb_factory_t *this;
3090
3091#ifdef ARCH_X86
3092 uint32_t mm = xine_mm_accel(); 3193 uint32_t mm = xine_mm_accel();
3093#endif
3094 3194
3095 this = malloc (sizeof (yuv2rgb_factory_t)); 3195 this = malloc (sizeof (yuv2rgb_factory_t));
3096 3196
3097 this->mode = mode; 3197 this->mode = mode;
3098 this->swapped = swapped; 3198 this->swapped = swapped;
3099 this->cmap = cmap; 3199 this->cmap = cmap;
3100 this->create_converter = yuv2rgb_create_converter; 3200 this->create_converter = yuv2rgb_create_converter;
3101 this->set_gamma = yuv2rgb_set_gamma; 3201 this->set_csc_levels = yuv2rgb_set_csc_levels;
3102 this->get_gamma = yuv2rgb_get_gamma; 3202 this->dispose = yuv2rgb_factory_dispose;
3103 this->matrix_coefficients = 6; 3203 this->matrix_coefficients = 6;
3204 this->table_base = NULL;
3205 this->table_mmx = NULL;
3206 this->table_mmx_base = NULL;
3104 3207
3105 3208
3106 yuv2rgb_setup_tables (this, mode, swapped); 3209 yuv2rgb_set_csc_levels (this, 0, 128, 128);
3107 3210
3108 /* 3211 /*
3109 * auto-probe for the best yuv2rgb function 3212 * auto-probe for the best yuv2rgb function
3110 */ 3213 */
3111 3214
3112 this->yuv2rgb_fun = NULL; 3215 this->yuv2rgb_fun = NULL;
3113#ifdef ARCH_X86 3216#if defined(ARCH_X86) || defined(ARCH_X86_64)
3114 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMXEXT)) { 3217 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMXEXT)) {
3115 3218
3116 yuv2rgb_init_mmxext (this); 3219 yuv2rgb_init_mmxext (this);
3117 3220
3221#ifdef LOG
3118 if (this->yuv2rgb_fun != NULL) 3222 if (this->yuv2rgb_fun != NULL)
3119 printf ("yuv2rgb: using MMXEXT for colorspace transform\n"); 3223 printf ("yuv2rgb: using MMXEXT for colorspace transform\n");
3224#endif
3120 } 3225 }
3121 3226
3122 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMX)) { 3227 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_X86_MMX)) {
3123 3228
3124 yuv2rgb_init_mmx (this); 3229 yuv2rgb_init_mmx (this);
3125 3230
3231#ifdef LOG
3126 if (this->yuv2rgb_fun != NULL) 3232 if (this->yuv2rgb_fun != NULL)
3127 printf ("yuv2rgb: using MMX for colorspace transform\n"); 3233 printf ("yuv2rgb: using MMX for colorspace transform\n");
3234#endif
3235 }
3236#ifdef __arm__
3237 if (this->yuv2rgb_fun == NULL) {
3238 yuv2rgb_init_arm ( this );
3239
3240 if(this->yuv2rgb_fun != NULL)
3241 printf("yuv2rgb: using arm4l assembler for colorspace transform\n" );
3128 } 3242 }
3129#endif 3243#endif
3244
3245#endif
3130#if HAVE_MLIB 3246#if HAVE_MLIB
3131 if (this->yuv2rgb_fun == NULL) { 3247 if ((this->yuv2rgb_fun == NULL) && (mm & MM_ACCEL_MLIB)) {
3132 3248
3133 yuv2rgb_init_mlib (this); 3249 yuv2rgb_init_mlib (this);
3134 3250
3251#ifdef LOG
3135 if (this->yuv2rgb_fun != NULL) 3252 if (this->yuv2rgb_fun != NULL)
3136 printf ("yuv2rgb: using medialib for colorspace transform\n"); 3253 printf ("yuv2rgb: using medialib for colorspace transform\n");
3137 }
3138#endif 3254#endif
3139#ifdef __arm__
3140 if (this->yuv2rgb_fun == NULL) {
3141 yuv2rgb_init_arm ( this );
3142
3143 if(this->yuv2rgb_fun != NULL)
3144 printf("yuv2rgb: using arm4l assembler for colorspace transform\n" );
3145 } 3255 }
3146#endif 3256#endif
3147 if (this->yuv2rgb_fun == NULL) { 3257 if (this->yuv2rgb_fun == NULL) {
3148 printf ("yuv2rgb: no accelerated colorspace conversion found\n"); 3258 lprintf ("no accelerated colorspace conversion found\n");
3259
3149 yuv2rgb_c_init (this); 3260 yuv2rgb_c_init (this);
3150 } 3261 }
3151 3262
3152 /* 3263 /*
3153 * auto-probe for the best yuy22rgb function 3264 * auto-probe for the best yuy22rgb function
3154 */ 3265 */
3155 3266
3156 /* FIXME: implement mmx/mlib functions */ 3267 /* FIXME: implement mmx/mlib functions */
3157 yuy22rgb_c_init (this); 3268 yuy22rgb_c_init (this);
3158 3269
3159 /* 3270 /*
3160 * set up single pixel function 3271 * set up single pixel function
3161 */ 3272 */
3162 3273
3163 yuv2rgb_single_pixel_init (this); 3274 yuv2rgb_single_pixel_init (this);
3164 3275
3165 return this; 3276 return this;
3166} 3277}
3167
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 @@
1 1
2#ifndef HAVE_YUV2RGB_H 2#ifndef HAVE_YUV2RGB_H
3#define HAVE_YUV2RGB_h 3#define HAVE_YUV2RGB_h
4 4
5#ifdef HAVE_MLIB
6#include <mlib_video.h>
7#endif
8
5#include <inttypes.h> 9#include <inttypes.h>
6 10
7typedef struct yuv2rgb_s yuv2rgb_t; 11typedef struct yuv2rgb_s yuv2rgb_t;
8 12
9typedef struct yuv2rgb_factory_s yuv2rgb_factory_t; 13typedef struct yuv2rgb_factory_s yuv2rgb_factory_t;
10 14
11/* 15/*
12 * function types for functions which can be replaced 16 * function types for functions which can be replaced
13 * by hardware-accelerated versions 17 * by hardware-accelerated versions
14 */ 18 */
15 19
16/* internal function use to scale yuv data */ 20/* internal function use to scale yuv data */
17typedef void (*scale_line_func_t) (uint8_t *source, uint8_t *dest, int width, int step); 21typedef void (*scale_line_func_t) (uint8_t *source, uint8_t *dest, int width, int step);
18 22
19typedef void (*yuv2rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) ; 23typedef void (*yuv2rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) ;
20 24
21typedef void (*yuy22rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * p); 25typedef void (*yuy22rgb_fun_t) (yuv2rgb_t *this, uint8_t * image, uint8_t * p);
22 26
23typedef uint32_t (*yuv2rgb_single_pixel_fun_t) (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v); 27typedef uint32_t (*yuv2rgb_single_pixel_fun_t) (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v);
24 28
25
26/* 29/*
27 * modes supported - feel free to implement yours 30 * modes supported - feel free to implement yours
28 */ 31 */
29 32
30#define MODE_8_RGB 1 33#define MODE_8_RGB 1
31#define MODE_8_BGR 2 34#define MODE_8_BGR 2
32#define MODE_15_RGB 3 35#define MODE_15_RGB 3
33#define MODE_15_BGR 4 36#define MODE_15_BGR 4
34#define MODE_16_RGB 5 37#define MODE_16_RGB 5
35#define MODE_16_BGR 6 38#define MODE_16_BGR 6
36#define MODE_24_RGB 7 39#define MODE_24_RGB 7
37#define MODE_24_BGR 8 40#define MODE_24_BGR 8
38#define MODE_32_RGB 9 41#define MODE_32_RGB 9
39#define MODE_32_BGR 10 42#define MODE_32_BGR 10
40 #defineMODE_8_GRAY 11 43 #defineMODE_8_GRAY 11
41#define MODE_PALETTE 12 44#define MODE_PALETTE 12
42 45
43struct yuv2rgb_s { 46struct yuv2rgb_s {
44
45 /* 47 /*
46 * configure converter for scaling factors 48 * configure converter for scaling factors
47 */ 49 */
48 int (*configure) (yuv2rgb_t *this, 50 int (*configure) (yuv2rgb_t *this,
49 int source_width, int source_height, 51 int source_width, int source_height,
50 int y_stride, int uv_stride, 52 int y_stride, int uv_stride,
51 int dest_width, int dest_height, 53 int dest_width, int dest_height,
52 int rgb_stride); 54 int rgb_stride);
53 55
54 /* 56 /*
57 * start a new field or frame if dest is NULL
58 */
59 int (*next_slice) (yuv2rgb_t *this, uint8_t **dest);
60
61 /*
62 * free resources
63 */
64 void (*dispose) (yuv2rgb_t *this);
65
66 /*
55 * this is the function to call for the yuv2rgb and scaling process 67 * this is the function to call for the yuv2rgb and scaling process
56 */ 68 */
57 yuv2rgb_fun_t yuv2rgb_fun; 69 yuv2rgb_fun_t yuv2rgb_fun;
58 70
59 /* 71 /*
60 * this is the function to call for the yuy2->rgb and scaling process 72 * this is the function to call for the yuy2->rgb and scaling process
61 */ 73 */
62 yuy22rgb_fun_t yuy22rgb_fun; 74 yuy22rgb_fun_t yuy22rgb_fun;
63 75
64 /* 76 /*
65 * this is the function to call for the yuv2rgb for a single pixel 77 * this is the function to call for the yuv2rgb for a single pixel
66 * (used for converting clut colors) 78 * (used for converting clut colors)
67 */ 79 */
68 80
69 yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun; 81 yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun;
70 82
71 /* private stuff below */ 83 /* private stuff below */
72 84
73 int source_width, source_height; 85 int source_width, source_height;
74 int y_stride, uv_stride; 86 int y_stride, uv_stride;
75 int dest_width, dest_height; 87 int dest_width, dest_height;
76 int rgb_stride; 88 int rgb_stride;
89 int slice_height, slice_offset;
77 int step_dx, step_dy; 90 int step_dx, step_dy;
78 int do_scale; 91 int do_scale, swapped;
79 92
80 uint8_t *y_buffer; 93 uint8_t *y_buffer;
81 uint8_t *u_buffer; 94 uint8_t *u_buffer;
82 uint8_t *v_buffer; 95 uint8_t *v_buffer;
83 void *y_chunk; 96 void *y_chunk;
84 void *u_chunk; 97 void *u_chunk;
85 void *v_chunk; 98 void *v_chunk;
86 99
100#ifdef HAVE_MLIB
101 uint8_t *mlib_buffer;
102 uint8_t *mlib_resize_buffer;
103 void *mlib_chunk;
104 void *mlib_resize_chunk;
105 mlib_filter mlib_filter_type;
106#endif
107
87 void **table_rV; 108 void **table_rV;
88 void **table_gU; 109 void **table_gU;
89 int *table_gV; 110 int *table_gV;
90 void **table_bU; 111 void **table_bU;
112 void *table_mmx;
91 113
92 uint8_t *cmap; 114 uint8_t *cmap;
93 scale_line_func_t scale_line; 115 scale_line_func_t scale_line;
94
95} ; 116} ;
96 117
97/* 118/*
98 * convenience class to easily create a lot of converters 119 * convenience class to easily create a lot of converters
99 */ 120 */
100 121
101struct yuv2rgb_factory_s { 122struct yuv2rgb_factory_s {
102
103 yuv2rgb_t* (*create_converter) (yuv2rgb_factory_t *this); 123 yuv2rgb_t* (*create_converter) (yuv2rgb_factory_t *this);
104 124
105 /* 125 /*
106 * adjust gamma (-100 to 100 looks fine) 126 * set color space conversion levels
107 * for all converters produced by this factory 127 * for all converters produced by this factory
108 */ 128 */
109 void (*set_gamma) (yuv2rgb_factory_t *this, int gamma); 129 void (*set_csc_levels) (yuv2rgb_factory_t *this,
130 int brightness, int contrast, int saturation);
110 131
111 /* 132 /*
112 * get gamma value 133 * free resources
113 */ 134 */
114 int (*get_gamma) (yuv2rgb_factory_t *this); 135 void (*dispose) (yuv2rgb_factory_t *this);
115 136
116 /* private data */ 137 /* private data */
117 138
118 int mode; 139 int mode;
119 int swapped; 140 int swapped;
120 uint8_t *cmap; 141 uint8_t *cmap;
121 142
122 int gamma;
123 int entry_size;
124
125 uint32_t matrix_coefficients; 143 uint32_t matrix_coefficients;
126 144
145 void *table_base;
127 void *table_rV[256]; 146 void *table_rV[256];
128 void *table_gU[256]; 147 void *table_gU[256];
129 int table_gV[256]; 148 int table_gV[256];
130 void *table_bU[256]; 149 void *table_bU[256];
150 void *table_mmx_base;
151 void *table_mmx;
131 152
132 /* preselected functions for mode/swap/hardware */ 153 /* preselected functions for mode/swap/hardware */
133 yuv2rgb_fun_t yuv2rgb_fun; 154 yuv2rgb_fun_t yuv2rgb_fun;
134 yuy22rgb_fun_t yuy22rgb_fun; 155 yuy22rgb_fun_t yuy22rgb_fun;
135 yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun; 156 yuv2rgb_single_pixel_fun_t yuv2rgb_single_pixel_fun;
136
137}; 157};
138 158
139yuv2rgb_factory_t *yuv2rgb_factory_init (int mode, int swapped, uint8_t *colormap); 159yuv2rgb_factory_t *yuv2rgb_factory_init (int mode, int swapped, uint8_t *colormap);
140 160
141 161
142/* 162/*
143 * internal stuff below this line 163 * internal stuff below this line
144 */ 164 */
145 165
146void mmx_yuv2rgb_set_gamma(int gamma); 166void mmx_yuv2rgb_set_csc_levels(yuv2rgb_factory_t *this,
167 int brightness, int contrast, int saturation);
147void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this); 168void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this);
148void yuv2rgb_init_mmx (yuv2rgb_factory_t *this); 169void yuv2rgb_init_mmx (yuv2rgb_factory_t *this);
149void yuv2rgb_init_mlib (yuv2rgb_factory_t *this); 170void yuv2rgb_init_mlib (yuv2rgb_factory_t *this);
150void yuv2rgb_init_arm (yuv2rgb_factory_t *this);
151 171
152#endif 172#endif