1 /*****************************************************************************
2 * render.c : Philips OGT and CVD (VCD Subtitle) blending routines
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 VideoLAN
5 * $Id: render.c,v 1.22 2004/01/23 11:03:06 rocky Exp $
7 * Author: Rocky Bernstein <rocky@panix.com>
9 * Sam Hocevar <sam@zoy.org>
10 * Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
11 * Roine Gustafsson <roine@popstar.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
26 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
33 #include <vlc/decoder.h>
39 /* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and
40 0 completely opaque. Note that although SVCD allow 8-bits, pixels
41 previously should be scaled down to 4 bits to use these routines.
43 #define ALPHA_BITS (4)
44 #define MAX_ALPHA ((1<<ALPHA_BITS) - 1)
45 #define ALPHA_SCALEDOWN (8-ALPHA_BITS)
47 /* We use a fixed-point arithmetic to scaling ratios so that we
48 can use integer arithmetic and still get fairly precise
49 results. ASCALE is a left shift amount.
51 #define ASCALE 6 /* 2^6 = 32 */
53 /* Horrible hack to get dbg_print to do the right thing */
56 /*****************************************************************************
58 *****************************************************************************/
59 static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *,
61 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
62 const subpicture_t *p_spu, vlc_bool_t b_crop );
63 static void BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
64 const subpicture_t *p_spu, vlc_bool_t b_crop,
66 static void BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
67 const subpicture_t *p_spu, vlc_bool_t b_crop );
68 static void BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
69 const subpicture_t *p_spu, vlc_bool_t b_crop );
70 static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
71 const subpicture_t *p_spu, vlc_bool_t b_crop );
73 /*****************************************************************************
74 * BlendSPU: blend a subtitle into a picture
75 *****************************************************************************
77 This blends subtitles (a subpicture) into the underlying
78 picture. Subtitle data has been preprocessed as YUV + transparancy
79 or 4 bytes per pixel with interleaving of rows in the subtitle
82 *****************************************************************************/
83 void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic,
84 const subpicture_t *p_spu )
86 struct subpicture_sys_t *p_sys = p_spu->p_sys;
88 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
89 "chroma %x", p_vout->output.i_chroma );
91 switch( p_vout->output.i_chroma )
93 /* I420 target, no scaling */
94 case VLC_FOURCC('I','4','2','0'):
95 case VLC_FOURCC('I','Y','U','V'):
96 case VLC_FOURCC('Y','V','1','2'):
97 BlendI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
100 /* RGB 555 - scaled */
101 case VLC_FOURCC('R','V','1','5'):
102 BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
106 case VLC_FOURCC('R','V','1','6'):
107 BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
111 /* RV24 target, scaling */
112 case VLC_FOURCC('R','V','2','4'):
113 BlendRV24( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
116 /* RV32 target, scaling */
117 case VLC_FOURCC('R','V','3','2'):
118 BlendRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
121 /* NVidia overlay, no scaling */
122 case VLC_FOURCC('Y','U','Y','2'):
123 BlendYUY2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
126 /* Palettized 8 bits per pixel (256 colors). Each
127 pixel is an uint8_t index in the palette
130 case VLC_FOURCC('R','G','B','2'):
131 BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
136 msg_Err( p_vout, "unknown chroma, can't render SPU" );
141 /* Following functions are local */
146 All Y samples are found first in memory as an array of bytes
147 (possibly with a larger stride for memory alignment), followed
148 immediately by all Cr (=U) samples (with half the stride of the Y
149 lines, and half the number of lines), then followed immediately by
150 all Cb (=V) samples in a similar fashion.
153 static void BlendI420( vout_thread_t *p_vout, picture_t *p_pic,
154 const subpicture_t *p_spu, vlc_bool_t b_crop )
156 /* Common variables */
157 uint8_t *p_pixel_base_Y, *p_pixel_base_V, *p_pixel_base_U;
158 ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
161 vlc_bool_t even_scanline = VLC_FALSE;
164 int i_x_start, i_y_start, i_x_end, i_y_end;
167 const struct subpicture_sys_t *p_sys = p_spu->p_sys;
169 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
170 "spu width x height: (%dx%d), (x,y)=(%d,%d), yuv pitch (%d,%d,%d)",
171 p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y,
172 p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
175 p_pixel_base_Y = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x
176 + p_pic->p[Y_PLANE].i_pitch * p_spu->i_y;
178 p_pixel_base_U = p_pic->p[U_PLANE].p_pixels + p_spu->i_x/2
179 + p_pic->p[U_PLANE].i_pitch * p_spu->i_y/2;
181 p_pixel_base_V = p_pic->p[V_PLANE].p_pixels + p_spu->i_x/2
182 + p_pic->p[V_PLANE].i_pitch * p_spu->i_y/2;
184 i_x_start = p_sys->i_x_start;
185 i_y_start = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_start;
187 i_x_end = p_sys->i_x_end;
188 i_y_end = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_end;
190 p_source = (ogt_yuvt_t *)p_sys->p_data;
192 /* Draw until we reach the bottom of the subtitle */
194 i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
195 i_y += p_pic->p[Y_PLANE].i_pitch )
197 uint8_t *p_pixel_base_Y_y = p_pixel_base_Y + i_y;
198 uint8_t *p_pixel_base_U_y = p_pixel_base_U + i_y/4;
199 uint8_t *p_pixel_base_V_y = p_pixel_base_V + i_y/4;
204 if ( i_y > i_y_end ) break;
207 p_source += i_x_start;
211 even_scanline = !even_scanline;
213 /* Draw until we reach the end of the line */
214 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
219 /* FIXME: y cropping should be dealt with outside of this loop.*/
220 if ( i_y < i_y_start) continue;
224 p_source += p_spu->i_width - i_x;
229 switch( p_source->s.t )
232 /* Completely transparent. Don't change pixel. */
237 /* Completely opaque. Completely overwrite underlying
238 pixel with subtitle pixel. */
240 /* This is the location that's going to get changed.*/
241 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
243 *p_pixel_Y = p_source->plane[Y_PLANE];
245 if ( even_scanline && i_x % 2 == 0 ) {
246 uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2;
247 uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2;
248 *p_pixel_U = p_source->plane[U_PLANE];
249 *p_pixel_V = p_source->plane[V_PLANE];
257 /* Blend in underlying subtitle pixel. */
259 /* This is the location that's going to get changed. */
260 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
263 /* This is the weighted part of the subtitle. The
264 color plane is 8 bits and transparancy is 4 bits so
265 when multiplied we get up to 12 bits.
267 uint16_t i_sub_color_Y =
268 (uint16_t) ( p_source->plane[Y_PLANE] *
269 (uint16_t) (p_source->s.t) );
271 /* This is the weighted part of the underlying pixel.
272 For the same reasons above, the result is up to 12
273 bits. However since the transparancies are
274 inverses, the sum of i_sub_color and i_pixel_color
275 will not exceed 12 bits.
277 uint16_t i_pixel_color_Y =
278 (uint16_t) ( *p_pixel_Y *
279 (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
281 /* Scale the 12-bit result back down to 8 bits. A
282 precise scaling after adding the two components,
283 would divide by one less than a power of 2. However
284 to simplify and speed things we use a power of
285 2. This means the boundaries (either all
286 transparent and all opaque) aren't handled properly.
287 But we deal with them in special cases above. */
289 *p_pixel_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> ALPHA_BITS;
291 if ( even_scanline && i_x % 2 == 0 ) {
292 uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2;
293 uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2;
294 uint16_t i_sub_color_U =
295 (uint16_t) ( p_source->plane[U_PLANE] *
296 (uint16_t) (p_source->s.t) );
298 uint16_t i_sub_color_V =
299 (uint16_t) ( p_source->plane[V_PLANE] *
300 (uint16_t) (p_source->s.t) );
301 uint16_t i_pixel_color_U =
302 (uint16_t) ( *p_pixel_U *
303 (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
304 uint16_t i_pixel_color_V =
305 (uint16_t) ( *p_pixel_V *
306 (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
307 *p_pixel_U = ( i_sub_color_U + i_pixel_color_U )>>ALPHA_BITS;
308 *p_pixel_V = ( i_sub_color_V + i_pixel_color_V )>>ALPHA_BITS;
322 Data is found in memory as an array of bytes in which the first byte
323 contains the first sample of Y, the second byte contains the first
324 sample of Cb (=U), the third byte contains the second sample of Y,
325 the fourth byte contains the first sample of Cr (=V); and so
326 on. Each 32-bit word then contains information for two contiguous
327 horizontal pixels, two 8-bit Y values plus a single Cb and Cr which
328 spans the two pixels.
331 #define BYTES_PER_PIXEL 4
333 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
334 const subpicture_t *p_spu, vlc_bool_t b_crop )
336 /* Common variables */
337 uint8_t *p_pixel_base;
339 /* This is the where the subtitle pixels come from */
340 ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;;
343 ogt_yuvt_t *p_source_end = (ogt_yuvt_t *)p_spu->p_sys->p_data +
344 (p_spu->i_width * p_spu->i_height);
349 /* Make sure we start on a word (4-byte) boundary. */
350 uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2;
353 int i_x_start, i_y_start, i_x_end, i_y_end;
355 const struct subpicture_sys_t *p_sys = p_spu->p_sys;
357 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
358 "spu width x height: (%dx%d), (x,y)=(%d,%d), pitch: %d",
359 p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y,
363 p_pixel_base = p_pic->p->p_pixels +
364 + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x;
366 i_x_start = p_sys->i_x_start;
367 i_y_start = p_sys->i_y_start * p_pic->p->i_pitch;
369 i_x_end = p_sys->i_x_end;
370 i_y_end = p_sys->i_y_end * p_pic->p->i_pitch;
372 /* Draw until we reach the bottom of the subtitle */
374 i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
375 i_y += p_pic->p[Y_PLANE].i_pitch )
377 uint8_t *p_pixel_base_y = p_pixel_base + i_y;
382 if ( i_y > i_y_end ) break;
385 p_source += (i_x_start*2);
390 /* Draw until we reach the end of the line. Each output pixel
391 is a combination of two source pixels.
393 for( i_x = 0; i_x < p_spu->i_width / 2; i_x++, p_source +=2 )
395 uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/
398 if (p_source > p_source_end-1) {
399 msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d",
407 /* FIXME: y cropping should be dealt with outside of this loop.*/
408 if ( i_y < i_y_start) continue;
412 p_source += p_spu->i_width - (i_x*2);
418 /* Favor opaque subtitle pixels. */
419 if ( (p_source->s.t == 0) && (p_source+1)->s.t == MAX_ALPHA )
420 i_avg_tr = (p_source+1)->s.t;
421 else if ( (p_source->s.t == MAX_ALPHA) && (p_source+1)->s.t == 0 )
422 i_avg_tr = p_source->s.t;
424 i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2;
430 /* Completely transparent. Don't change pixel. */
435 /* Completely opaque. Completely overwrite underlying
436 pixel with subtitle pixel. */
438 /* This is the location that's going to get changed. */
439 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
443 /* Favor opaque subtitle pixel. */
444 if (p_source->s.t == MAX_ALPHA ) {
445 i_avg_u = p_source->plane[U_PLANE] ;
446 i_avg_v = p_source->plane[V_PLANE] ;
447 } else if ( (p_source+1)->s.t == MAX_ALPHA ) {
448 i_avg_u = (p_source+1)->plane[U_PLANE] ;
449 i_avg_v = (p_source+1)->plane[V_PLANE] ;
451 i_avg_u = ( p_source->plane[U_PLANE]
452 + (p_source+1)->plane[U_PLANE] ) / 2;
453 i_avg_v = ( p_source->plane[V_PLANE]
454 + (p_source+1)->plane[V_PLANE] ) / 2;
457 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
458 *p_pixel++ = p_source->plane[Y_PLANE] ;
459 *p_pixel++ = i_avg_u;
460 *p_pixel++ = (p_source+1)->plane[Y_PLANE] ;
461 *p_pixel++ = i_avg_v;
468 /* Blend in underlying subtitle pixels. */
470 /* This is the location that's going to get changed. */
471 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
472 uint8_t i_avg_u = ( p_source->plane[U_PLANE]
473 + (p_source+1)->plane[U_PLANE] ) / 2;
474 uint8_t i_avg_v = ( p_source->plane[V_PLANE]
475 + (p_source+1)->plane[V_PLANE] ) / 2;
477 /* This is the weighted part of the two subtitle
478 pixels. The color plane is 8 bits and transparancy
479 is 4 bits so when multiplied we get up to 12 bits.
481 uint16_t i_sub_color_Y1 =
482 (uint16_t) ( p_source->plane[Y_PLANE] *
483 (uint16_t) (p_source->s.t) );
485 uint16_t i_sub_color_Y2 =
486 (uint16_t) ( (p_source+1)->plane[Y_PLANE] *
487 (uint16_t) ((p_source+1)->s.t) );
489 /* This is the weighted part of the underlying pixels.
490 For the same reasons above, the result is up to 12
491 bits. However since the transparancies are
492 inverses, the sum of i_sub_color and i_pixel_color
493 will not exceed 12 bits.
495 uint16_t i_sub_color_U =
496 (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr );
498 uint16_t i_sub_color_V =
499 (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr );
501 uint16_t i_pixel_color_Y1 =
502 (uint16_t) ( *(p_pixel) *
503 (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
504 uint16_t i_pixel_color_Y2 =
505 (uint16_t) ( *(p_pixel) *
506 (uint16_t) (MAX_ALPHA - (p_source+1)->s.t) ) ;
507 uint16_t i_pixel_color_U =
508 (uint16_t) ( *(p_pixel+1) *
509 (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
510 uint16_t i_pixel_color_V =
511 (uint16_t) ( *(p_pixel+3) *
512 (uint16_t) (MAX_ALPHA - i_avg_tr) ) ;
514 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
516 /* Scale the 12-bit result back down to 8 bits. A
517 precise scaling after adding the two components,
518 would divide by one less than a power of 2. However
519 to simplify and speed things we use a power of
520 2. This means the boundaries (either all
521 transparent and all opaque) aren't handled properly.
522 But we deal with them in special cases above. */
524 *p_pixel++ = ( i_sub_color_Y1 + i_pixel_color_Y1 )>>ALPHA_BITS;
525 *p_pixel++ = ( i_sub_color_V + i_pixel_color_V ) >>ALPHA_BITS;
526 *p_pixel++ = ( i_sub_color_Y2 + i_pixel_color_Y2 )>>ALPHA_BITS;
527 *p_pixel++ = ( i_sub_color_U + i_pixel_color_U ) >>ALPHA_BITS;
533 /* For an odd width source, we'll just have to drop off a pixel. */
534 if (p_spu->i_width % 2) p_source++;
539 Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel.
541 A RGB 5-5-5 pixel looks like this:
542 RGB 5-5-5 bit (MSB) 7 6 5 4 3 2 1 0 (LSB)
543 p ? B4 B3 B2 B1 B0 R4 R3
544 q R2 R1 R0 G4 G3 G2 G1 G0
549 yuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
555 #define GREEN_PIXEL 1
560 /* Scale RGB from 8 bits down to 5. */
561 rgb[RED_PIXEL] >>= (8-5);
562 rgb[GREEN_PIXEL] >>= (8-5);
563 rgb[BLUE_PIXEL] >>= (8-5);
565 *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c ) | ( (rgb[RED_PIXEL]>>3) & 0x03 );
566 *p_rgb2 = ( (rgb[RED_PIXEL] << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
569 printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
570 "rgb1: %02x, rgb2 %02x\n",
571 p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
572 rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
579 Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel.
581 A RGB 5-6-5 pixel looks like this:
582 RGB 5-6-5 bit (MSB) 7 6 5 4 3 2 1 0 (LSB)
583 p B4 B3 B2 B1 B0 R5 R4 R3
584 q R2 R1 R0 G4 G3 G2 G1 G0
589 yuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
596 /* Scale RGB from 8 bits down to 5 or 6 bits. */
597 rgb[RED_PIXEL] >>= (8-6);
598 rgb[GREEN_PIXEL] >>= (8-5);
599 rgb[BLUE_PIXEL] >>= (8-5);
601 *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 ) | ( (rgb[RED_PIXEL]>>3) & 0x07 );
602 *p_rgb2 = ( (rgb[RED_PIXEL] << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
605 printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
606 "rgb1: %02x, rgb2 %02x\n",
607 p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
608 rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
614 #undef BYTES_PER_PIXEL
615 #define BYTES_PER_PIXEL 2
618 BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
619 const subpicture_t *p_spu, vlc_bool_t b_crop,
622 /* Common variables */
623 uint8_t *p_pixel_base;
624 ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
625 ogt_yuvt_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width];
626 ogt_yuvt_t *p_source;
631 /* Chroma specific */
632 uint32_t i_xscale; /* Amount we scale subtitle in the x direction,
633 multiplied by 2**ASCALE. */
634 uint32_t i_yscale; /* Amount we scale subtitle in the y direction.
635 multiplied by 2**ASCALE. */
637 int i_width, i_height, i_ytmp, i_ynext;
640 int i_x_start, i_y_start, i_x_end, i_y_end;
642 struct subpicture_sys_t *p_sys = p_spu->p_sys;
644 i_xscale = ( p_vout->output.i_width << ASCALE ) / p_vout->render.i_width;
645 i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
647 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
648 "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d",
649 p_spu->i_width, p_spu->i_height,
650 p_vout->output.i_width, p_vout->output.i_height,
651 p_vout->render.i_width, p_vout->render.i_height,
655 i_width = p_spu->i_width * i_xscale;
656 i_height = p_spu->i_height * i_yscale;
658 /* Set where we will start blending subtitle from using
659 the picture coordinates subtitle offsets
661 p_pixel_base = p_pic->p->p_pixels
662 + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
663 + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
665 i_x_start = p_sys->i_x_start;
666 i_y_start = i_yscale * p_sys->i_y_start;
667 i_x_end = p_sys->i_x_end;
668 i_y_end = i_yscale * p_sys->i_y_end;
670 p_source = (ogt_yuvt_t *)p_sys->p_data;
672 /* Draw until we reach the bottom of the subtitle */
674 for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;
675 i_y_src += p_spu->i_width )
677 uint8_t *p_pixel_base_y;
678 i_ytmp = i_y >> ASCALE;
680 p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
684 if ( i_y > i_y_end ) break;
687 p_source += i_x_start;
691 /* Check whether we need to draw one line or more than one */
692 if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
694 /* Draw until we reach the end of the line */
695 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
699 uint8_t *p=(uint8_t *) p_source;
700 printf("+++ %02x %02x %02x %02x\n",
701 p[0], p[1], p[2], p[3]);
706 /* FIXME: y cropping should be dealt with outside of this
708 if ( i_y < i_y_start) continue;
712 p_source += p_spu->i_width - i_x;
717 if (p_source >= p_src_end) {
718 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
719 i_x, i_y / i_yscale, i_height);
723 switch( p_source->s.t )
726 /* Completely transparent. Don't change pixel. */
732 /* Completely opaque. Completely overwrite underlying
733 pixel with subtitle pixel. */
735 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
737 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
739 uint32_t len = i_xlast - i_xdest;
744 /* This is the location that's going to get changed. */
745 uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
748 yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
750 yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
752 for ( len = i_xlast - i_xdest; len ; len--) {
759 #ifdef TRANSPARENCY_FINISHED
762 /* Blend in underlying pixel subtitle pixel. */
764 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
766 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
768 uint32_t len = i_xlast - i_xdest;
770 /* This is the location that's going to get changed. */
771 uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
773 /* To be able to scale correctly for full opaqueness, we
774 add 1 to the alpha. This means alpha value 0 won't
775 be completely transparent and is not correct, but
776 that's handled in a special case above anyway. */
778 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
783 yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
785 yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
786 rv16_pack_blend(p_dest, rgb, dest_alpha, ALPHA_SCALEDOWN);
789 #endif /*TRANSPARENCY_FINISHED*/
795 i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
798 /* Draw until we reach the end of the line */
799 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
804 /* FIXME: y cropping should be dealt with outside of this
806 if ( i_y < i_y_start) continue;
810 p_source += p_spu->i_width - i_x;
815 if (p_source >= p_src_end) {
816 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
817 i_x, i_y / i_yscale, i_height);
821 switch( p_source->s.t )
824 /* Completely transparent. Don't change pixel. */
830 /* Completely opaque. Completely overwrite underlying
831 pixel with subtitle pixel. */
833 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
835 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
837 uint32_t len = i_xlast - i_xdest;
839 uint8_t *p_pixel_base_x = p_pixel_base + i_xdest;
841 for( ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
843 /* This is the location that's going to get changed. */
844 uint8_t *p_dest = p_pixel_base_x + i_ytmp;
848 yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
850 yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
852 for ( len = i_xlast - i_xdest; len ; len--) {
859 #ifdef TRANSPARENCY_FINISHED
861 for( ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
863 /* Blend in underlying pixel subtitle pixel. */
865 /* To be able to scale correctly for full opaqueness, we
866 add 1 to the alpha. This means alpha value 0 won't
867 be completely transparent and is not correct, but
868 that's handled in a special case above anyway. */
870 uint8_t *p_dest = p_pixel_base + i_ytmp;
871 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
876 yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
878 yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
879 rv16_pack_blend(p_dest, rgb, dest_alpha,ALPHA_SCALEDOWN);
882 #endif /*TRANSPARENCY_FINISHED*/
889 #undef BYTES_PER_PIXEL
890 #define BYTES_PER_PIXEL 4
893 RV24 format??? Is this just for X11? Or just not for Win32? Is this
896 a pixel is represented by 3 bytes containing a red,
897 blue and green sample with blue stored at the lowest address, green
898 next then red. One padding byte is added between pixels. Although
899 this may not be part of a spec, images should be stored with each
900 line padded to a u_int32 boundary.
903 BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
904 const subpicture_t *p_spu, vlc_bool_t b_crop )
906 /* Common variables */
907 uint8_t *p_pixel_base;
908 ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
909 ogt_yuvt_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width];
910 ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
915 /* Make sure we start on a word (4-byte) boundary. */
918 /* Chroma specific */
919 uint32_t i_xscale; /* Amount we scale subtitle in the x direction,
920 multiplied by 2**ASCALE. */
921 uint32_t i_yscale; /* Amount we scale subtitle in the y direction.
922 multiplied by 2**ASCALE. */
924 int i_width, i_height, i_ytmp, i_ynext;
927 int32_t i_x_start, i_y_start, i_x_end, i_y_end;
929 struct subpicture_sys_t *p_sys = p_spu->p_sys;
930 unsigned int i_aspect_x, i_aspect_y;
932 vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
935 i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
936 / (i_aspect_y * p_vout->render.i_width);
937 i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
939 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
940 "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d",
941 p_spu->i_width, p_spu->i_height,
942 p_vout->output.i_width, p_vout->output.i_height,
943 p_vout->render.i_width, p_vout->render.i_height,
947 i_width = p_spu->i_width * i_xscale;
948 i_height = p_spu->i_height * i_yscale;
950 /* Set where we will start blending subtitle from using
951 the picture coordinates subtitle offsets.
953 i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
955 p_pixel_base = p_pic->p->p_pixels + i_spu_x
956 + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
958 i_x_start = p_sys->i_x_start;
959 i_y_start = i_yscale * p_sys->i_y_start;
960 i_x_end = p_sys->i_x_end;
961 i_y_end = i_yscale * p_sys->i_y_end;
963 p_source = (ogt_yuvt_t *)p_sys->p_data;
965 /* Draw until we reach the bottom of the subtitle */
967 for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;
968 i_y_src += p_spu->i_width )
970 uint8_t *p_pixel_base_y;
971 i_ytmp = i_y >> ASCALE;
973 p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
977 if ( i_y > i_y_end ) break;
980 p_source += i_x_start;
984 /* Check whether we need to draw one line or more than one */
985 if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
987 /* Draw until we reach the end of the line */
988 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
993 /* FIXME: y cropping should be dealt with outside of this
995 if ( i_y < i_y_start) continue;
999 p_source += p_spu->i_width - i_x;
1004 if (p_source >= p_src_end) {
1005 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1006 i_x, i_y / i_yscale, i_height);
1010 switch( p_source->s.t )
1013 /* Completely transparent. Don't change pixel. */
1019 /* Completely opaque. Completely overwrite underlying
1020 pixel with subtitle pixel. */
1022 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1023 * BYTES_PER_PIXEL );
1024 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1025 * BYTES_PER_PIXEL );
1026 uint32_t len = i_xlast - i_xdest;
1030 /* This is the location that's going to get changed. */
1031 uint8_t *p_dest = p_pixel_base_y + i_xdest;
1033 yuv2rgb(p_source, rgb);
1035 for ( len = i_xlast - i_xdest; len ; len--) {
1036 *p_dest++ = rgb[BLUE_PIXEL];
1037 *p_dest++ = rgb[GREEN_PIXEL];
1038 *p_dest++ = rgb[RED_PIXEL];
1042 #ifdef TRANSPARENCY_FINISHED
1045 /* Blend in underlying pixel subtitle pixel. */
1047 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1048 * BYTES_PER_PIXEL );
1049 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1050 * BYTES_PER_PIXEL );
1051 uint32_t len = i_xlast - i_xdest;
1053 /* To be able to scale correctly for full opaqueness, we
1054 add 1 to the alpha. This means alpha value 0 won't
1055 be completely transparent and is not correct, but
1056 that's handled in a special case above anyway. */
1058 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1061 /* This is the location that's going to get changed. */
1062 uint8_t *p_dest = p_pixel_base_y + i_xdest;
1064 yuv2rgb(p_source, rgb);
1065 rv32_pack_blend(p_dest, rgb, dest_alpha,
1068 for ( len = i_xlast - i_xdest; len ; len--) {
1069 *p_dest++ = rgb[BLUE_PIXEL];
1070 *p_dest++ = rgb[GREEN_PIXEL];
1071 *p_dest++ = rgb[RED_PIXEL];
1076 #endif /*TRANSPARENCY_FINISHED*/
1083 i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1086 /* Draw until we reach the end of the line */
1087 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1092 /* FIXME: y cropping should be dealt with outside of this
1094 if ( i_y < i_y_start) continue;
1096 if ( i_x > i_x_end )
1098 p_source += p_spu->i_width - i_x;
1103 if (p_source >= p_src_end) {
1104 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1105 i_x, i_y / i_yscale, i_height);
1109 switch( p_source->s.t )
1112 /* Completely transparent. Don't change pixel. */
1118 /* Completely opaque. Completely overwrite underlying
1119 pixel with subtitle pixel. */
1121 /* This is the location that's going to get changed. */
1122 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1123 * BYTES_PER_PIXEL );
1124 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1125 * BYTES_PER_PIXEL );
1126 uint32_t len = i_xlast - i_xdest;
1130 yuv2rgb(p_source, rgb);
1132 for( ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1134 /* Completely opaque. Completely overwrite underlying
1135 pixel with subtitle pixel. */
1137 /* This is the location that's going to get changed. */
1138 uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1140 for ( len = i_xlast - i_xdest; len ; len--) {
1141 *p_dest++ = rgb[BLUE_PIXEL];
1142 *p_dest++ = rgb[GREEN_PIXEL];
1143 *p_dest++ = rgb[RED_PIXEL];
1149 #ifdef TRANSPARENCY_FINISHED
1154 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1155 * BYTES_PER_PIXEL );
1156 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1157 * BYTES_PER_PIXEL );
1158 uint32_t len = i_xlast - i_xdest;
1161 yuv2rgb(p_source, rgb);
1163 for( ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1165 /* Blend in underlying pixel subtitle pixel. */
1167 /* This is the location that's going to get changed. */
1168 uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1170 /* To be able to scale correctly for full opaqueness, we
1171 add 1 to the alpha. This means alpha value 0 won't
1172 be completely transparent and is not correct, but
1173 that's handled in a special case above anyway. */
1175 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1176 rv32_pack_blend(p_dest, rgb, dest_alpha,
1180 #endif /*TRANSPARENCY_FINISHED*/
1187 #undef BYTES_PER_PIXEL
1188 #define BYTES_PER_PIXEL 4
1191 RV32 format??? Is this just for X11? Or just not for Win32? Is this
1194 RV32 format: a pixel is represented by 4 bytes containing a red,
1195 blue and green sample with blue stored at the lowest address, green
1196 next then red. One padding byte is added between pixels. Although
1197 this may not be part of a spec, images should be stored with each
1198 line padded to a u_int32 boundary.
1201 BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
1202 const subpicture_t *p_spu, vlc_bool_t b_crop )
1204 /* Common variables */
1205 uint8_t *p_pixel_base;
1206 ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
1207 ogt_yuvt_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width];
1208 ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
1213 /* Make sure we start on a word (4-byte) boundary. */
1216 /* Chroma specific */
1217 uint32_t i_xscale; /* Amount we scale subtitle in the x direction,
1218 multiplied by 2**ASCALE. */
1219 uint32_t i_yscale; /* Amount we scale subtitle in the y direction.
1220 multiplied by 2**ASCALE. */
1222 int i_width, i_height, i_ytmp, i_ynext;
1225 int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1227 struct subpicture_sys_t *p_sys = p_spu->p_sys;
1228 unsigned int i_aspect_x, i_aspect_y;
1230 vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
1233 i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1234 / (i_aspect_y * p_vout->render.i_width);
1235 i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1237 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
1238 "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d",
1239 p_spu->i_width, p_spu->i_height,
1240 p_vout->output.i_width, p_vout->output.i_height,
1241 p_vout->render.i_width, p_vout->render.i_height,
1245 i_width = p_spu->i_width * i_xscale;
1246 i_height = p_spu->i_height * i_yscale;
1248 /* Set where we will start blending subtitle from using
1249 the picture coordinates subtitle offsets.
1251 i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
1253 p_pixel_base = p_pic->p->p_pixels + i_spu_x
1254 + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1256 i_x_start = p_sys->i_x_start;
1257 i_y_start = i_yscale * p_sys->i_y_start;
1258 i_x_end = p_sys->i_x_end;
1259 i_y_end = i_yscale * p_sys->i_y_end;
1261 p_source = (ogt_yuvt_t *)p_sys->p_data;
1263 /* Draw until we reach the bottom of the subtitle */
1265 for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;
1266 i_y_src += p_spu->i_width )
1268 uint8_t *p_pixel_base_y;
1269 i_ytmp = i_y >> ASCALE;
1271 p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1275 if ( i_y > i_y_end ) break;
1278 p_source += i_x_start;
1282 /* Check whether we need to draw one line or more than one */
1283 if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1285 /* Draw until we reach the end of the line */
1286 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1291 /* FIXME: y cropping should be dealt with outside of this
1293 if ( i_y < i_y_start) continue;
1295 if ( i_x > i_x_end )
1297 p_source += p_spu->i_width - i_x;
1302 if (p_source >= p_src_end) {
1303 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1304 i_x, i_y / i_yscale, i_height);
1308 switch( p_source->s.t )
1311 /* Completely transparent. Don't change pixel. */
1317 /* Completely opaque. Completely overwrite underlying
1318 pixel with subtitle pixel. */
1320 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1321 * BYTES_PER_PIXEL );
1322 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1323 * BYTES_PER_PIXEL );
1324 uint32_t len = i_xlast - i_xdest;
1328 /* This is the location that's going to get changed. */
1329 uint8_t *p_dest = p_pixel_base_y + i_xdest;
1331 yuv2rgb(p_source, rgb);
1333 for ( len = i_xlast - i_xdest; len ; len--) {
1334 *p_dest++ = rgb[BLUE_PIXEL];
1335 *p_dest++ = rgb[GREEN_PIXEL];
1336 *p_dest++ = rgb[RED_PIXEL];
1340 #ifdef TRANSPARENCY_FINISHED
1343 /* Blend in underlying pixel subtitle pixel. */
1345 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1346 * BYTES_PER_PIXEL );
1347 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1348 * BYTES_PER_PIXEL );
1349 uint32_t len = i_xlast - i_xdest;
1351 /* To be able to scale correctly for full opaqueness, we
1352 add 1 to the alpha. This means alpha value 0 won't
1353 be completely transparent and is not correct, but
1354 that's handled in a special case above anyway. */
1356 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1359 /* This is the location that's going to get changed. */
1360 uint8_t *p_dest = p_pixel_base_y + i_xdest;
1362 yuv2rgb(p_source, rgb);
1363 rv32_pack_blend(p_dest, rgb, dest_alpha,
1366 for ( len = i_xlast - i_xdest; len ; len--) {
1367 *p_dest++ = rgb[BLUE_PIXEL];
1368 *p_dest++ = rgb[GREEN_PIXEL];
1369 *p_dest++ = rgb[RED_PIXEL];
1374 #endif /*TRANSPARENCY_FINISHED*/
1381 i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1384 /* Draw until we reach the end of the line */
1385 for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1390 /* FIXME: y cropping should be dealt with outside of this
1392 if ( i_y < i_y_start) continue;
1394 if ( i_x > i_x_end )
1396 p_source += p_spu->i_width - i_x;
1401 if (p_source >= p_src_end) {
1402 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1403 i_x, i_y / i_yscale, i_height);
1407 switch( p_source->s.t )
1410 /* Completely transparent. Don't change pixel. */
1416 /* Completely opaque. Completely overwrite underlying
1417 pixel with subtitle pixel. */
1419 /* This is the location that's going to get changed. */
1420 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1421 * BYTES_PER_PIXEL );
1422 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1423 * BYTES_PER_PIXEL );
1424 uint32_t len = i_xlast - i_xdest;
1428 yuv2rgb(p_source, rgb);
1430 for( ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1432 /* Completely opaque. Completely overwrite underlying
1433 pixel with subtitle pixel. */
1435 /* This is the location that's going to get changed. */
1436 uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1438 for ( len = i_xlast - i_xdest; len ; len--) {
1439 *p_dest++ = rgb[BLUE_PIXEL];
1440 *p_dest++ = rgb[GREEN_PIXEL];
1441 *p_dest++ = rgb[RED_PIXEL];
1447 #ifdef TRANSPARENCY_FINISHED
1452 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1453 * BYTES_PER_PIXEL );
1454 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1455 * BYTES_PER_PIXEL );
1456 uint32_t len = i_xlast - i_xdest;
1459 yuv2rgb(p_source, rgb);
1461 for( ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1463 /* Blend in underlying pixel subtitle pixel. */
1465 /* This is the location that's going to get changed. */
1466 uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1468 /* To be able to scale correctly for full opaqueness, we
1469 add 1 to the alpha. This means alpha value 0 won't
1470 be completely transparent and is not correct, but
1471 that's handled in a special case above anyway. */
1473 uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1474 rv32_pack_blend(p_dest, rgb, dest_alpha,
1478 #endif /*TRANSPARENCY_FINISHED*/
1485 #undef BYTES_PER_PIXEL
1486 #define BYTES_PER_PIXEL 1
1489 BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
1490 const subpicture_t *p_spu, vlc_bool_t b_crop )
1492 /* Common variables */
1493 uint8_t *p_pixel_base;
1494 uint8_t *p_src_start = (uint8_t *)p_spu->p_sys->p_data;
1495 uint8_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width];
1496 uint8_t *p_source; /* This is the where the subtitle pixels come from */
1501 /* Chroma specific */
1502 uint32_t i_xscale; /* Amount we scale subtitle in the x direction,
1503 multiplied by 2**ASCALE. */
1504 uint32_t i_yscale; /* Amount we scale subtitle in the y direction.
1505 multiplied by 2**ASCALE. */
1507 int i_width, i_height, i_ytmp;
1510 int i_x_start, i_y_start, i_x_end, i_y_end;
1512 /* 4 entry colormap */
1513 uint8_t cmap[NUM_SUBTITLE_COLORS];
1516 struct subpicture_sys_t *p_sys = p_spu->p_sys;
1517 unsigned int i_aspect_x, i_aspect_y;
1519 vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
1522 /* Find a corresponding colormap entries for our palette entries. */
1523 for( i_cmap = 0; i_cmap < NUM_SUBTITLE_COLORS; i_cmap++ )
1525 uint8_t Y = p_sys->p_palette[i_cmap].s.y;
1527 /* FIXME: when we have a way to look at colormap entries we can
1528 do better. For now we have to use 0xff for white 0x00 for
1529 black and 0x44 for something in between. To do this we use
1530 only the Y component.
1533 cmap[i_cmap] = 0xff; /* Use white. */
1535 cmap[i_cmap] = 0x00; /* Use black. */
1537 cmap[i_cmap] = 0x44; /* Use something else. */
1540 i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1541 / (i_aspect_y * p_vout->render.i_width);
1542 i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1544 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER),
1545 "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d",
1546 p_spu->i_width, p_spu->i_height,
1547 p_vout->output.i_width, p_vout->output.i_height,
1548 p_vout->render.i_width, p_vout->render.i_height,
1552 i_width = p_spu->i_width * i_xscale;
1553 i_height = p_spu->i_height * i_yscale;
1555 /* Set where we will start blending subtitle from using
1556 the picture coordinates subtitle offsets
1558 p_pixel_base = p_pic->p->p_pixels
1559 + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
1560 + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1562 i_x_start = p_sys->i_x_start;
1563 i_y_start = i_yscale * p_sys->i_y_start;
1564 i_x_end = p_sys->i_x_end;
1565 i_y_end = i_yscale * p_sys->i_y_end;
1567 p_source = (uint8_t *)p_sys->p_data;
1569 /* Draw until we reach the bottom of the subtitle */
1571 for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;
1572 i_y_src += p_spu->i_width )
1574 uint8_t *p_pixel_base_y;
1575 i_ytmp = i_y >> ASCALE;
1577 p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1581 if ( i_y > i_y_end ) break;
1584 p_source += i_x_start;
1588 /* Check whether we need to draw one line or more than one */
1589 if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1592 /* Draw until we reach the end of the line */
1593 for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1599 /* FIXME: y cropping should be dealt with outside of this
1601 if ( i_y < i_y_start) continue;
1603 if ( i_x > i_x_end )
1605 p_source += p_spu->i_width - i_x;
1610 if (p_source >= p_src_end) {
1611 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1612 i_x, i_y / i_yscale, i_height);
1616 p_yuvt = p_sys->p_palette[*p_source & 0x3];
1617 if ( (p_yuvt.s.t) < (MAX_ALPHA) / 2 ) {
1618 /* Completely or relatively transparent. Don't change pixel. */
1621 printf(" "); /*++++*/
1624 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1625 * BYTES_PER_PIXEL );
1626 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1627 * BYTES_PER_PIXEL );
1628 /* This is the pixel that's going to change;*/
1629 uint8_t *p_dest = p_pixel_base_y + i_xdest;
1630 memset( p_dest, cmap[*p_source & 0x3], i_xlast - i_xdest );
1632 printf("%1d", *p_source); /*++++*/
1638 printf("\n"); /*++++*/
1641 /* Have to scale over many lines. */
1642 int i_yreal = p_pic->p->i_pitch * i_ytmp;
1643 int i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1645 /* Draw until we reach the end of the line */
1646 for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1648 ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];
1652 /* FIXME: y cropping should be dealt with outside of this
1654 if ( i_y < i_y_start) continue;
1656 if ( i_x > i_x_end )
1658 p_source += p_spu->i_width - i_x;
1663 if (p_source >= p_src_end) {
1664 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1665 i_x, i_y / i_yscale, i_height);
1669 if ( (p_yuvt.s.t) < (MAX_ALPHA) / 2 ) {
1670 /* Completely or relatively transparent. Don't change pixel. */
1673 printf(" "); /*++++*/
1676 uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)
1677 * BYTES_PER_PIXEL );
1678 uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1679 * BYTES_PER_PIXEL );
1680 uint32_t len = i_xlast - i_xdest;
1682 printf("%1d", *p_source); /*++++*/
1684 for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
1685 i_ytmp += p_pic->p->i_pitch ) {
1686 uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1687 memset( p_dest, cmap[*p_source & 0x3], len );
1699 * c-file-style: "gnu"
1701 * indent-tabs-mode: nil