]> git.sesse.net Git - vlc/blob - modules/codec/ogt/render.c
string review
[vlc] / modules / codec / ogt / render.c
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.23 2004/01/25 18:20:12 bigben Exp $
6  *
7  * Author: Rocky Bernstein <rocky@panix.com>
8  *   based on code from: 
9  *          Sam Hocevar <sam@zoy.org>
10  *          Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
11  *          Roine Gustafsson <roine@popstar.com>
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33 #include <vlc/decoder.h>
34
35 #include "pixmap.h"
36 #include "subtitle.h"
37 #include "render.h"
38
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.
42 */
43 #define ALPHA_BITS (4)
44 #define MAX_ALPHA  ((1<<ALPHA_BITS) - 1) 
45 #define ALPHA_SCALEDOWN (8-ALPHA_BITS)
46
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. 
50 */
51 #define ASCALE 6  /* 2^6 = 32 */
52
53 /* Horrible hack to get dbg_print to do the right thing */
54 #define p_dec p_vout
55
56 /*****************************************************************************
57  * Local prototypes
58  *****************************************************************************/
59 static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *,
60                         vlc_bool_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,
65                        vlc_bool_t b_15bpp );
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 );
72
73 /*****************************************************************************
74  * BlendSPU: blend a subtitle into a picture
75  *****************************************************************************
76  
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
80   removed. 
81
82  *****************************************************************************/
83 void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic,
84                    const subpicture_t *p_spu )
85 {
86     struct subpicture_sys_t *p_sys = p_spu->p_sys;
87   
88     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
89                "chroma %x", p_vout->output.i_chroma );
90
91     switch( p_vout->output.i_chroma )
92     {
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 );
98             break;
99
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, 
103                        VLC_TRUE );
104             break;
105           
106         case VLC_FOURCC('R','V','1','6'):
107             BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
108                        VLC_FALSE );
109             break;
110
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 );
114             break;
115
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 );
119             break;
120
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 );
124             break;
125
126         /* Palettized 8 bits per pixel (256 colors). Each
127            pixel is an uint8_t index in the palette
128            Used in ASCII Art. 
129         */
130         case VLC_FOURCC('R','G','B','2'):
131             BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
132           
133             break;
134
135         default:
136             msg_Err( p_vout, "unknown chroma, can't render SPU" );
137             break;
138     }
139 }
140
141 /* Following functions are local */
142
143 /* 
144   YV12 format:  
145
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.
151 */
152
153 static void BlendI420( vout_thread_t *p_vout, picture_t *p_pic,
154                         const subpicture_t *p_spu, vlc_bool_t b_crop )
155 {
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 */
159
160   int i_x, i_y;
161   vlc_bool_t even_scanline = VLC_FALSE;
162
163   /* Crop-specific */
164   int i_x_start, i_y_start, i_x_end, i_y_end;
165   /* int i=0; */
166
167   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
168   
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 );
173
174   
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;
177   
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;
180   
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;
183   
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;
186   
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;
189   
190   p_source = (ogt_yuvt_t *)p_sys->p_data;
191   
192   /* Draw until we reach the bottom of the subtitle */
193   for( i_y = 0; 
194        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
195        i_y += p_pic->p[Y_PLANE].i_pitch )
196     {
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;
200
201       i_x = 0;
202
203       if ( b_crop ) {
204         if ( i_y > i_y_end ) break;
205         if (i_x_start) {
206           i_x = i_x_start;
207           p_source += i_x_start;
208         }
209       }
210
211       even_scanline = !even_scanline;
212
213       /* Draw until we reach the end of the line */
214       for( ; i_x < p_spu->i_width; i_x++, p_source++ )
215         {
216
217           if( b_crop ) {
218
219             /* FIXME: y cropping should be dealt with outside of this loop.*/
220             if ( i_y < i_y_start) continue;
221
222             if ( i_x > i_x_end )
223             {
224               p_source += p_spu->i_width - i_x;
225               break;
226             }
227           }
228           
229           switch( p_source->s.t )
230             {
231             case 0: 
232               /* Completely transparent. Don't change pixel. */
233               break;
234               
235             case MAX_ALPHA:
236               {
237                 /* Completely opaque. Completely overwrite underlying
238                    pixel with subtitle pixel. */
239                 
240                 /* This is the location that's going to get changed.*/
241                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
242                 
243                 *p_pixel_Y = p_source->plane[Y_PLANE];
244
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];
250                 }
251                 
252                 break;
253               }
254               
255             default:
256               {
257                 /* Blend in underlying subtitle pixel. */
258                 
259                 /* This is the location that's going to get changed. */
260                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
261
262
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.
266                  */
267                 uint16_t i_sub_color_Y = 
268                   (uint16_t) ( p_source->plane[Y_PLANE] *
269                                (uint16_t) (p_source->s.t) );
270
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.
276                 */
277                 uint16_t i_pixel_color_Y = 
278                   (uint16_t) ( *p_pixel_Y * 
279                                (uint16_t) (MAX_ALPHA - p_source->s.t) ) ;
280                 
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. */
288
289                 *p_pixel_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> ALPHA_BITS;
290
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) );
297                   
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;
309                 }
310                 break;
311               }
312               
313             }
314         }
315     }
316 }
317
318 /*
319
320   YUY2 Format:
321
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.
329 */
330
331 #define BYTES_PER_PIXEL 4
332
333 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
334                         const subpicture_t *p_spu, vlc_bool_t b_crop )
335 {
336   /* Common variables */
337   uint8_t *p_pixel_base;
338
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;;
341
342 #if 1
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);
345 #endif
346
347   uint16_t i_x, i_y;
348
349   /* Make sure we start on a word (4-byte) boundary. */
350   uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2;
351
352   /* Crop-specific */
353   int i_x_start, i_y_start, i_x_end, i_y_end;
354
355   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
356   
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,
360              p_pic->p->i_pitch );
361
362   
363   p_pixel_base = p_pic->p->p_pixels + 
364     + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x;
365
366   i_x_start = p_sys->i_x_start;
367   i_y_start = p_sys->i_y_start * p_pic->p->i_pitch;
368   
369   i_x_end   = p_sys->i_x_end;
370   i_y_end   = p_sys->i_y_end   * p_pic->p->i_pitch;
371
372   /* Draw until we reach the bottom of the subtitle */
373   for( i_y = 0; 
374        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
375        i_y += p_pic->p[Y_PLANE].i_pitch )
376     {
377       uint8_t *p_pixel_base_y = p_pixel_base + i_y;
378
379       i_x = 0;
380
381       if ( b_crop ) {
382         if ( i_y > i_y_end ) break;
383         if (i_x_start) {
384           i_x = i_x_start;
385           p_source += (i_x_start*2);
386         }
387       }
388   
389
390       /* Draw until we reach the end of the line. Each output pixel
391          is a combination of two source pixels. 
392        */
393       for( i_x = 0;  i_x < p_spu->i_width / 2; i_x++, p_source +=2 )
394         {
395           uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/
396
397 #if 1
398           if (p_source > p_source_end-1) {
399             msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d",
400                      i_x, i_y);
401             return;
402           }
403 #endif
404
405           if( b_crop ) {
406
407             /* FIXME: y cropping should be dealt with outside of this loop.*/
408             if ( i_y < i_y_start) continue;
409
410             if ( i_x > i_x_end )
411             {
412               p_source += p_spu->i_width - (i_x*2);
413               break;
414             }
415           }
416   
417           
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;
423           else 
424             i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2;
425           
426
427           switch( i_avg_tr )
428             {
429             case 0: 
430               /* Completely transparent. Don't change pixel. */
431               break;
432               
433             case MAX_ALPHA:
434               {
435                 /* Completely opaque. Completely overwrite underlying
436                    pixel with subtitle pixel. */
437                 
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;
440                 uint8_t i_avg_u;
441                 uint8_t i_avg_v;
442
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] ;
450                 } else {
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;
455                 }
456
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;
462                 
463                 break;
464               }
465
466             default:
467               {
468                 /* Blend in underlying subtitle pixels. */
469                 
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;
476
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.
480                  */
481                 uint16_t i_sub_color_Y1 = 
482                   (uint16_t) ( p_source->plane[Y_PLANE] *
483                                (uint16_t) (p_source->s.t) );
484
485                 uint16_t i_sub_color_Y2 = 
486                   (uint16_t) ( (p_source+1)->plane[Y_PLANE] *
487                                (uint16_t) ((p_source+1)->s.t) );
488
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.
494                 */
495                 uint16_t i_sub_color_U = 
496                   (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr );
497                 
498                 uint16_t i_sub_color_V = 
499                   (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr );
500
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) ) ;
513
514                 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
515
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. */
523
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;
528                 break;
529               }
530             }
531         }
532
533       /* For an odd width source, we'll just have to drop off a pixel. */
534       if (p_spu->i_width % 2) p_source++;
535     }
536 }
537
538 /**
539    Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel.
540
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
545
546 **/
547
548 static inline void
549 yuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
550 {
551
552   uint8_t rgb[3];
553
554 #define RED_PIXEL   0
555 #define GREEN_PIXEL 1
556 #define BLUE_PIXEL  2
557
558   yuv2rgb(p_yuv, rgb);
559   
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);
564   
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 );
567
568 #if 0
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],
573          *p_rgb1, *p_rgb2);
574 #endif
575
576 }
577
578 /**
579    Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel.
580
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
585
586 **/
587
588 static inline void
589 yuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
590 {
591
592   uint8_t rgb[3];
593
594   yuv2rgb(p_yuv, rgb);
595   
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);
600   
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 );
603
604 #if 0
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],
609          *p_rgb1, *p_rgb2);
610 #endif
611
612 }
613
614 #undef BYTES_PER_PIXEL
615 #define BYTES_PER_PIXEL 2
616
617 static void 
618 BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
619            const subpicture_t *p_spu, vlc_bool_t b_crop,
620            vlc_bool_t b_15bpp )
621 {
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;
627
628     int i_x, i_y;
629     int i_y_src;
630
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. */
636
637     int i_width, i_height, i_ytmp, i_ynext;
638
639     /* Crop-specific */
640     int i_x_start, i_y_start, i_x_end, i_y_end;
641
642     struct subpicture_sys_t *p_sys = p_spu->p_sys;
643
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;
646
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,
652                i_xscale, i_yscale
653                );
654
655     i_width  = p_spu->i_width  * i_xscale;
656     i_height = p_spu->i_height * i_yscale;
657
658     /* Set where we will start blending subtitle from using
659        the picture coordinates subtitle offsets
660     */
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;
664
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;
669
670     p_source = (ogt_yuvt_t *)p_sys->p_data;
671   
672     /* Draw until we reach the bottom of the subtitle */
673     i_y = 0;
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 )
676     {
677         uint8_t *p_pixel_base_y;
678         i_ytmp = i_y >> ASCALE;
679         i_y += i_yscale;
680         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
681         i_x = 0;
682
683         if ( b_crop ) {
684           if ( i_y > i_y_end ) break;
685           if (i_x_start) {
686             i_x = i_x_start;
687             p_source += i_x_start;
688           }
689         }
690
691         /* Check whether we need to draw one line or more than one */
692         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
693         {
694           /* Draw until we reach the end of the line */
695           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
696             {
697
698 #if 0              
699               uint8_t *p=(uint8_t *) p_source;
700               printf("+++ %02x %02x %02x %02x\n", 
701                      p[0], p[1], p[2], p[3]);
702 #endif
703     
704               if( b_crop ) {
705                 
706                 /* FIXME: y cropping should be dealt with outside of this 
707                    loop.*/
708                 if ( i_y < i_y_start) continue;
709                 
710                 if ( i_x > i_x_end )
711                   {
712                     p_source += p_spu->i_width - i_x;
713                     break;
714                   }
715               }
716
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);
720                 return;
721               }
722               
723               switch( p_source->s.t )
724                 {
725                 case 0:
726                   /* Completely transparent. Don't change pixel. */
727                   break;
728                   
729                 default:
730                 case MAX_ALPHA:
731                   {
732                     /* Completely opaque. Completely overwrite underlying
733                        pixel with subtitle pixel. */
734                 
735                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
736                                          * BYTES_PER_PIXEL );
737                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
738                                          * BYTES_PER_PIXEL );
739                     uint32_t len     = i_xlast - i_xdest;
740
741                     uint8_t i_rgb1;
742                     uint8_t i_rgb2;
743
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;
746
747                     if (b_15bpp) 
748                       yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
749                     else 
750                       yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
751
752                     for ( len = i_xlast - i_xdest; len ; len--) {
753                       *p_dest++ = i_rgb1;
754                       *p_dest++ = i_rgb2;
755                     }
756                     break;
757                   }
758
759 #ifdef TRANSPARENCY_FINISHED
760                 default:
761                   {
762                     /* Blend in underlying pixel subtitle pixel. */
763                     
764                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
765                                          * BYTES_PER_PIXEL );
766                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
767                                          * BYTES_PER_PIXEL );
768                     uint32_t len     = i_xlast - i_xdest;
769
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;
772
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. */
777                 
778                     uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
779                     uint8_t i_rgb1;
780                     uint8_t i_rgb2;
781
782                     if (b_15bpp) 
783                       yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
784                     else 
785                       yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
786                     rv16_pack_blend(p_dest, rgb, dest_alpha, ALPHA_SCALEDOWN);
787                     break;
788                   }
789 #endif /*TRANSPARENCY_FINISHED*/
790                 }
791             }
792         }
793         else
794         {
795             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
796
797
798             /* Draw until we reach the end of the line */
799             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
800             {
801
802               if( b_crop ) {
803                 
804                 /* FIXME: y cropping should be dealt with outside of this 
805                    loop.*/
806                 if ( i_y < i_y_start) continue;
807                 
808                 if ( i_x > i_x_end )
809                   {
810                     p_source += p_spu->i_width - i_x;
811                     break;
812                   }
813               }
814               
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);
818                 return;
819               }
820               
821               switch( p_source->s.t )
822                 {
823                 case 0:
824                     /* Completely transparent. Don't change pixel. */
825                     break;
826
827                 default:
828                 case MAX_ALPHA: 
829                   {
830                     /* Completely opaque. Completely overwrite underlying
831                        pixel with subtitle pixel. */
832
833                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
834                                          * BYTES_PER_PIXEL );
835                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
836                                          * BYTES_PER_PIXEL );
837                     uint32_t len     = i_xlast - i_xdest;
838
839                     uint8_t *p_pixel_base_x = p_pixel_base + i_xdest;
840
841                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
842                     {
843                       /* This is the location that's going to get changed. */
844                       uint8_t *p_dest = p_pixel_base_x + i_ytmp;
845                       uint8_t i_rgb1;
846                       uint8_t i_rgb2;
847                       if (b_15bpp) 
848                         yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
849                       else 
850                         yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
851
852                       for ( len = i_xlast - i_xdest; len ; len--) {
853                         *p_dest++ = i_rgb1;
854                         *p_dest++ = i_rgb2;
855                       }
856                     }
857                     break;
858                   }
859 #ifdef TRANSPARENCY_FINISHED
860                 default:
861                     for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
862                     {
863                       /* Blend in underlying pixel subtitle pixel. */
864                       
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. */
869                       
870                       uint8_t *p_dest = p_pixel_base + i_ytmp;
871                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
872                       uint8_t i_rgb1;
873                       uint8_t i_rgb2;
874
875                       if (b_15bpp) 
876                         yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
877                       else 
878                         yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
879                       rv16_pack_blend(p_dest, rgb, dest_alpha,ALPHA_SCALEDOWN);
880                     }
881                     break;
882 #endif /*TRANSPARENCY_FINISHED*/
883                 }
884             }
885         }
886     }
887 }
888
889 #undef  BYTES_PER_PIXEL
890 #define BYTES_PER_PIXEL 4
891
892 /* 
893   RV24 format??? Is this just for X11? Or just not for Win32? Is this
894   the same as RV32?
895
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. 
901 */
902 static void 
903 BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
904             const subpicture_t *p_spu, vlc_bool_t b_crop )
905 {
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 */
911
912     int i_x, i_y;
913     int i_y_src;
914
915     /* Make sure we start on a word (4-byte) boundary. */
916     uint32_t i_spu_x;
917
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. */
923
924     int i_width, i_height, i_ytmp, i_ynext;
925
926     /* Crop-specific */
927     int32_t i_x_start, i_y_start, i_x_end, i_y_end;
928
929     struct subpicture_sys_t *p_sys = p_spu->p_sys;
930     unsigned int i_aspect_x, i_aspect_y;
931
932     vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
933                       &i_aspect_x );
934
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;
938
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,
944                i_xscale, i_yscale
945                );
946
947     i_width  = p_spu->i_width  * i_xscale;
948     i_height = p_spu->i_height * i_yscale;
949
950     /* Set where we will start blending subtitle from using
951        the picture coordinates subtitle offsets.
952     */
953     i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
954
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;
957
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;
962
963     p_source = (ogt_yuvt_t *)p_sys->p_data;
964   
965     /* Draw until we reach the bottom of the subtitle */
966     i_y = 0;
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 )
969     {
970         uint8_t *p_pixel_base_y;
971         i_ytmp = i_y >> ASCALE;
972         i_y += i_yscale;
973         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
974         i_x = 0;
975
976         if ( b_crop ) {
977           if ( i_y > i_y_end ) break;
978           if (i_x_start) {
979             i_x = i_x_start;
980             p_source += i_x_start;
981           }
982         }
983
984         /* Check whether we need to draw one line or more than one */
985         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
986         {
987           /* Draw until we reach the end of the line */
988           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
989             {
990
991               if( b_crop ) {
992                 
993                 /* FIXME: y cropping should be dealt with outside of this 
994                    loop.*/
995                 if ( i_y < i_y_start) continue;
996                 
997                 if ( i_x > i_x_end )
998                   {
999                     p_source += p_spu->i_width - i_x;
1000                     break;
1001                   }
1002               }
1003
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);
1007                 return;
1008               }
1009               
1010               switch( p_source->s.t )
1011                 {
1012                 case 0:
1013                   /* Completely transparent. Don't change pixel. */
1014                   break;
1015                   
1016                 default:
1017                 case MAX_ALPHA:
1018                   {
1019                     /* Completely opaque. Completely overwrite underlying
1020                        pixel with subtitle pixel. */
1021
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;
1027
1028                     uint8_t rgb[3];
1029
1030                     /* This is the location that's going to get changed. */
1031                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1032
1033                     yuv2rgb(p_source, rgb);
1034
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];
1039                       *p_dest++;
1040                     }
1041
1042 #ifdef TRANSPARENCY_FINISHED
1043                   default:
1044                     {
1045                       /* Blend in underlying pixel subtitle pixel. */
1046                       
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;
1052
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. */
1057                       
1058                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1059                       uint8_t rgb[3];
1060
1061                       /* This is the location that's going to get changed. */
1062                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1063                       
1064                       yuv2rgb(p_source, rgb);
1065                       rv32_pack_blend(p_dest, rgb, dest_alpha, 
1066                                       ALPHA_SCALEDOWN);
1067
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];
1072                         *p_dest++;
1073                       }
1074                       break;
1075                     }
1076 #endif /*TRANSPARENCY_FINISHED*/
1077                   }
1078                 }
1079             }
1080         } 
1081         else
1082         {
1083             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1084
1085
1086             /* Draw until we reach the end of the line */
1087             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1088             {
1089
1090               if( b_crop ) {
1091                 
1092                 /* FIXME: y cropping should be dealt with outside of this 
1093                    loop.*/
1094                 if ( i_y < i_y_start) continue;
1095                 
1096                 if ( i_x > i_x_end )
1097                   {
1098                     p_source += p_spu->i_width - i_x;
1099                     break;
1100                   }
1101               }
1102               
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);
1106                 return;
1107               }
1108               
1109               switch( p_source->s.t )
1110                 {
1111                 case 0:
1112                     /* Completely transparent. Don't change pixel. */
1113                     break;
1114
1115                 default:
1116                 case MAX_ALPHA: 
1117                   {
1118                     /* Completely opaque. Completely overwrite underlying
1119                        pixel with subtitle pixel. */
1120
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;
1127
1128                     uint8_t rgb[3];
1129
1130                     yuv2rgb(p_source, rgb); 
1131
1132                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1133                     {
1134                       /* Completely opaque. Completely overwrite underlying
1135                          pixel with subtitle pixel. */
1136                       
1137                       /* This is the location that's going to get changed. */
1138                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1139                       
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];
1144                         *p_dest++;
1145                       }
1146                     }
1147                     break;
1148                   }
1149 #ifdef TRANSPARENCY_FINISHED
1150                 default: 
1151                   {
1152                     
1153
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;
1159                     uint8_t rgb[3];
1160
1161                     yuv2rgb(p_source, rgb);
1162
1163                     for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1164                     {
1165                       /* Blend in underlying pixel subtitle pixel. */
1166                       
1167                       /* This is the location that's going to get changed. */
1168                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1169
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. */
1174
1175                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1176                       rv32_pack_blend(p_dest, rgb, dest_alpha,
1177                                       ALPHA_SCALEDOWN);
1178                     }
1179                     break;
1180 #endif /*TRANSPARENCY_FINISHED*/
1181                 }
1182             }
1183         }
1184     }
1185 }
1186
1187 #undef  BYTES_PER_PIXEL
1188 #define BYTES_PER_PIXEL 4
1189
1190 /* 
1191   RV32 format??? Is this just for X11? Or just not for Win32? Is this
1192   the same as RV24?
1193
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. 
1199 */
1200 static void 
1201 BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
1202             const subpicture_t *p_spu, vlc_bool_t b_crop )
1203 {
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 */
1209
1210     int i_x, i_y;
1211     int i_y_src;
1212
1213     /* Make sure we start on a word (4-byte) boundary. */
1214     uint32_t i_spu_x;
1215
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. */
1221
1222     int i_width, i_height, i_ytmp, i_ynext;
1223
1224     /* Crop-specific */
1225     int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1226
1227     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1228     unsigned int i_aspect_x, i_aspect_y;
1229
1230     vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
1231                       &i_aspect_x );
1232
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;
1236
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,
1242                i_xscale, i_yscale
1243                );
1244
1245     i_width  = p_spu->i_width  * i_xscale;
1246     i_height = p_spu->i_height * i_yscale;
1247
1248     /* Set where we will start blending subtitle from using
1249        the picture coordinates subtitle offsets.
1250     */
1251     i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL; 
1252
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;
1255
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;
1260
1261     p_source = (ogt_yuvt_t *)p_sys->p_data;
1262   
1263     /* Draw until we reach the bottom of the subtitle */
1264     i_y = 0;
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 )
1267     {
1268         uint8_t *p_pixel_base_y;
1269         i_ytmp = i_y >> ASCALE;
1270         i_y += i_yscale;
1271         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1272         i_x = 0;
1273
1274         if ( b_crop ) {
1275           if ( i_y > i_y_end ) break;
1276           if (i_x_start) {
1277             i_x = i_x_start;
1278             p_source += i_x_start;
1279           }
1280         }
1281
1282         /* Check whether we need to draw one line or more than one */
1283         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1284         {
1285           /* Draw until we reach the end of the line */
1286           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
1287             {
1288
1289               if( b_crop ) {
1290                 
1291                 /* FIXME: y cropping should be dealt with outside of this 
1292                    loop.*/
1293                 if ( i_y < i_y_start) continue;
1294                 
1295                 if ( i_x > i_x_end )
1296                   {
1297                     p_source += p_spu->i_width - i_x;
1298                     break;
1299                   }
1300               }
1301
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);
1305                 return;
1306               }
1307               
1308               switch( p_source->s.t )
1309                 {
1310                 case 0:
1311                   /* Completely transparent. Don't change pixel. */
1312                   break;
1313                   
1314                 default:
1315                 case MAX_ALPHA:
1316                   {
1317                     /* Completely opaque. Completely overwrite underlying
1318                        pixel with subtitle pixel. */
1319
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;
1325
1326                     uint8_t rgb[3];
1327
1328                     /* This is the location that's going to get changed. */
1329                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1330
1331                     yuv2rgb(p_source, rgb);
1332
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];
1337                       *p_dest++;
1338                     }
1339
1340 #ifdef TRANSPARENCY_FINISHED
1341                   default:
1342                     {
1343                       /* Blend in underlying pixel subtitle pixel. */
1344                       
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;
1350
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. */
1355                       
1356                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1357                       uint8_t rgb[3];
1358
1359                       /* This is the location that's going to get changed. */
1360                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1361                       
1362                       yuv2rgb(p_source, rgb);
1363                       rv32_pack_blend(p_dest, rgb, dest_alpha, 
1364                                       ALPHA_SCALEDOWN);
1365
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];
1370                         *p_dest++;
1371                       }
1372                       break;
1373                     }
1374 #endif /*TRANSPARENCY_FINISHED*/
1375                   }
1376                 }
1377             }
1378         } 
1379         else
1380         {
1381             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1382
1383
1384             /* Draw until we reach the end of the line */
1385             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1386             {
1387
1388               if( b_crop ) {
1389                 
1390                 /* FIXME: y cropping should be dealt with outside of this 
1391                    loop.*/
1392                 if ( i_y < i_y_start) continue;
1393                 
1394                 if ( i_x > i_x_end )
1395                   {
1396                     p_source += p_spu->i_width - i_x;
1397                     break;
1398                   }
1399               }
1400               
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);
1404                 return;
1405               }
1406               
1407               switch( p_source->s.t )
1408                 {
1409                 case 0:
1410                     /* Completely transparent. Don't change pixel. */
1411                     break;
1412
1413                 default:
1414                 case MAX_ALPHA: 
1415                   {
1416                     /* Completely opaque. Completely overwrite underlying
1417                        pixel with subtitle pixel. */
1418
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;
1425
1426                     uint8_t rgb[3];
1427
1428                     yuv2rgb(p_source, rgb); 
1429
1430                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1431                     {
1432                       /* Completely opaque. Completely overwrite underlying
1433                          pixel with subtitle pixel. */
1434                       
1435                       /* This is the location that's going to get changed. */
1436                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1437                       
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];
1442                         *p_dest++;
1443                       }
1444                     }
1445                     break;
1446                   }
1447 #ifdef TRANSPARENCY_FINISHED
1448                 default: 
1449                   {
1450                     
1451
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;
1457                     uint8_t rgb[3];
1458
1459                     yuv2rgb(p_source, rgb);
1460
1461                     for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1462                     {
1463                       /* Blend in underlying pixel subtitle pixel. */
1464                       
1465                       /* This is the location that's going to get changed. */
1466                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1467
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. */
1472
1473                       uint8_t i_destalpha = MAX_ALPHA - p_source->s.t;
1474                       rv32_pack_blend(p_dest, rgb, dest_alpha,
1475                                       ALPHA_SCALEDOWN);
1476                     }
1477                     break;
1478 #endif /*TRANSPARENCY_FINISHED*/
1479                 }
1480             }
1481         }
1482     }
1483 }
1484
1485 #undef  BYTES_PER_PIXEL
1486 #define BYTES_PER_PIXEL 1
1487
1488 static void 
1489 BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
1490             const subpicture_t *p_spu, vlc_bool_t b_crop )
1491 {
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 */
1497
1498     int i_x, i_y;
1499     int i_y_src;
1500
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. */
1506
1507     int i_width, i_height, i_ytmp;
1508
1509     /* Crop-specific */
1510     int i_x_start, i_y_start, i_x_end, i_y_end;
1511
1512     /* 4 entry colormap */
1513     uint8_t cmap[NUM_SUBTITLE_COLORS];
1514     int i_cmap;
1515
1516     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1517     unsigned int i_aspect_x, i_aspect_y;
1518
1519     vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y, 
1520                       &i_aspect_x );
1521     
1522     /* Find a corresponding colormap entries for our palette entries. */
1523     for( i_cmap = 0; i_cmap < NUM_SUBTITLE_COLORS; i_cmap++ )
1524     {
1525       uint8_t Y = p_sys->p_palette[i_cmap].s.y;
1526
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.
1531       */
1532       if (Y > 0x70) 
1533         cmap[i_cmap] = 0xff; /* Use white. */
1534       else if (Y < 0x10) 
1535         cmap[i_cmap] = 0x00; /* Use black. */
1536       else 
1537         cmap[i_cmap] = 0x44; /* Use something else. */
1538     }
1539
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;
1543
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,
1549                i_xscale, i_yscale
1550                );
1551
1552     i_width  = p_spu->i_width  * i_xscale;
1553     i_height = p_spu->i_height * i_yscale;
1554
1555     /* Set where we will start blending subtitle from using
1556        the picture coordinates subtitle offsets
1557     */
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;
1561
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;
1566
1567     p_source = (uint8_t *)p_sys->p_data;
1568   
1569     /* Draw until we reach the bottom of the subtitle */
1570     i_y = 0;
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 )
1573       {
1574         uint8_t *p_pixel_base_y;
1575         i_ytmp = i_y >> ASCALE;
1576         i_y += i_yscale;
1577         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1578         i_x = 0;
1579
1580         if ( b_crop ) {
1581           if ( i_y > i_y_end ) break;
1582           if (i_x_start) {
1583             i_x = i_x_start;
1584             p_source += i_x_start;
1585           }
1586         }
1587         
1588         /* Check whether we need to draw one line or more than one */
1589         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1590         {
1591
1592           /* Draw until we reach the end of the line */
1593           for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1594             {
1595               ogt_yuvt_t p_yuvt;
1596
1597               if( b_crop ) {
1598                 
1599                 /* FIXME: y cropping should be dealt with outside of this 
1600                    loop.*/
1601                 if ( i_y < i_y_start) continue;
1602                 
1603                 if ( i_x > i_x_end )
1604                   {
1605                     p_source += p_spu->i_width - i_x;
1606                     break;
1607                   }
1608               }
1609               
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);
1613                 return;
1614               }
1615               
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. */
1619                 ;
1620 #if 0
1621                 printf(" "); /*++++*/
1622 #endif
1623               } else {
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 );
1631 #if 0
1632                 printf("%1d", *p_source); /*++++*/
1633 #endif
1634               }
1635               
1636             }
1637 #if 0
1638           printf("\n"); /*++++*/
1639 #endif
1640         } else {
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;
1644
1645            /* Draw until we reach the end of the line */
1646            for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1647              {
1648               ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];
1649
1650               if( b_crop ) {
1651                 
1652                 /* FIXME: y cropping should be dealt with outside of this 
1653                    loop.*/
1654                 if ( i_y < i_y_start) continue;
1655                 
1656                 if ( i_x > i_x_end )
1657                   {
1658                     p_source += p_spu->i_width - i_x;
1659                     break;
1660                   }
1661               }
1662               
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);
1666                 return;
1667               }
1668               
1669               if ( (p_yuvt.s.t) < (MAX_ALPHA) / 2 ) {
1670                 /* Completely or relatively transparent. Don't change pixel. */
1671                 ;
1672 #if 0
1673                 printf(" "); /*++++*/
1674 #endif
1675               } else {
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;
1681 #if 0
1682                 printf("%1d", *p_source); /*++++*/
1683 #endif
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 );
1688                 }
1689               }
1690             }
1691
1692         }
1693       }
1694 }
1695
1696 \f
1697 /* 
1698  * Local variables:
1699  *  c-file-style: "gnu"
1700  *  tab-width: 8
1701  *  indent-tabs-mode: nil
1702  * End:
1703  */