]> git.sesse.net Git - vlc/blob - modules/codec/ogt/render.c
21824770237180e5d1941f8eae19b2a13072a3a7
[vlc] / modules / codec / ogt / render.c
1 /*****************************************************************************
2  * render.c : Philips OGT and CVD (VCD Subtitle) blending routines.
3  *            stuff from here might be pulled out, abstracted or used
4  *            by DVD subtitles.
5  *****************************************************************************
6  * Copyright (C) 2003, 2004 VideoLAN
7  * $Id$
8  *
9  * Author: Rocky Bernstein <rocky@panix.com>
10  *   based on code from: 
11  *          Sam Hocevar <sam@zoy.org>
12  *          Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
13  *          Roine Gustafsson <roine@popstar.com>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
28  *****************************************************************************/
29
30 /*#define TESTING_TRANSPARENCY 1*/
31
32 /*****************************************************************************
33  * Preamble
34  *****************************************************************************/
35 #include <vlc/vlc.h>
36 #include <vlc/vout.h>
37 #include <vlc/decoder.h>
38
39 #include "pixmap.h"
40 #include "subtitle.h"
41 #include "render.h"
42
43 /* We use 4 bits for an transparency value: 0..15, 15 is completely
44    transparent and 0 completely opaque. Note that although SVCD allow
45    8-bits, for these routines pixels should previously have been be
46    scaled down to 4 bits (the range used by DVDs).
47 */
48 #define TRANS_BITS (4)
49 #define MAX_TRANS  ((1<<TRANS_BITS) - 1) 
50 #define TRANS_SCALEDOWN (8-TRANS_BITS)
51
52 /* We use a fixed-point arithmetic in scaling ratios so that we
53    can use integer arithmetic and still get fairly precise
54    results. ASCALE is a left shift amount. 
55 */
56 #define ASCALE 6  /* 2^6 = 32 */
57
58 /* Horrible hack to get dbg_print to do the right thing */
59 #define p_dec p_vout
60
61 /**
62    Take two 8-bit RGB values and a transparency and do a weighted
63    average of them. The "weight" comes from i_trans which is in the
64    range 0..MAX_TRANS. To have greater precision using integer
65    arithmetic, the RGB values are scaled. The uint16_t cast below is
66    to make sure we don't overflow the product in the multiplication
67
68    (MAX_TRANS - i_trans) is the additive "inverse" of i_trans, i.e.
69    i_trans + (MAX_TRANS - i_trans) = MAX_TRANS. So the resulting sum
70    of rgb1*i_trans + rgb2*(MAX_TRANS-i_trans) will be scaled by
71    MAX_TRANS. To reduce the value back down to 8 bits, we shift by
72    TRANS_BITS, noting that 1 << TRANS_BITS is roughly
73    MAX_TRANS. (Actually it is MAX_TRANS - 1).
74 */
75 #define avg_8bit_rgb(rgb_vout, rgb_sub, i_trans)                   \
76 {                                                                  \
77    int i;                                                          \
78    for (i=0; i < RGB_SIZE; i++) {                                  \
79    rgb_vout[i] = ( (uint16_t) rgb_vout[i]*(MAX_TRANS-i_trans) +    \
80                    (uint16_t) rgb_sub [i]*i_trans ) >> TRANS_BITS; \
81    }                                                               \
82 }
83
84
85 /*****************************************************************************
86  * Local prototypes
87  *****************************************************************************/
88 static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *,
89                         vlc_bool_t );
90 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
91                         const subpicture_t *p_spu, vlc_bool_t b_crop );
92 static void BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
93                        const subpicture_t *p_spu, vlc_bool_t b_crop,
94                        vlc_bool_t b_15bpp );
95 static void BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
96                         const subpicture_t *p_spu, vlc_bool_t b_crop );
97 static void BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
98                         const subpicture_t *p_spu, vlc_bool_t b_crop );
99 static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
100                         const subpicture_t *p_spu, vlc_bool_t b_crop );
101
102 /*****************************************************************************
103  * BlendSPU: blend a subtitle into a picture
104  *****************************************************************************
105  
106   This blends subtitles (a subpicture) into the underlying
107   picture. Subtitle data has been preprocessed as YUV + transparancy
108   or 4 bytes per pixel with interleaving of rows in the subtitle
109   removed. 
110
111  *****************************************************************************/
112 void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic,
113                    const subpicture_t *p_spu )
114 {
115     struct subpicture_sys_t *p_sys = p_spu->p_sys;
116   
117     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
118                "chroma %x", p_vout->output.i_chroma );
119
120     switch( p_vout->output.i_chroma )
121     {
122         /* I420 target, no scaling */
123         case VLC_FOURCC('I','4','2','0'):
124         case VLC_FOURCC('I','Y','U','V'):
125         case VLC_FOURCC('Y','V','1','2'):
126             BlendI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
127             break;
128
129         /* RGB 555 - scaled */
130         case VLC_FOURCC('R','V','1','5'):
131             BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop, 
132                        VLC_TRUE );
133             break;
134           
135         case VLC_FOURCC('R','V','1','6'):
136             BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
137                        /* Not sure under what conditions RV16 is really
138                           RV16 and not RV15.
139                         */
140 #if 0
141                        VLC_FALSE );
142 #else
143                        VLC_TRUE );
144 #endif
145             break;
146
147         /* RV24 target, scaling */
148         case VLC_FOURCC('R','V','2','4'):
149             BlendRV24( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
150             break;
151
152         /* RV32 target, scaling */
153         case VLC_FOURCC('R','V','3','2'):
154             BlendRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
155             break;
156
157         /* NVidia overlay, no scaling */
158         case VLC_FOURCC('Y','U','Y','2'):
159             BlendYUY2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
160             break;
161
162         /* Palettized 8 bits per pixel (256 colors). Each
163            pixel is an uint8_t index in the palette
164            Used in ASCII Art. 
165         */
166         case VLC_FOURCC('R','G','B','2'):
167             BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
168           
169             break;
170
171         default:
172             msg_Err( p_vout, "unknown chroma, can't render SPU" );
173             break;
174     }
175 }
176
177 /* Following functions are local */
178
179 /* 
180   YV12 format:  
181
182   All Y samples are found first in memory as an array of bytes
183   (possibly with a larger stride for memory alignment), followed
184   immediately by all Cr (=U) samples (with half the stride of the Y
185   lines, and half the number of lines), then followed immediately by
186   all Cb (=V) samples in a similar fashion.
187 */
188
189 static void BlendI420( vout_thread_t *p_vout, picture_t *p_pic,
190                         const subpicture_t *p_spu, vlc_bool_t b_crop )
191 {
192   /* Common variables */
193   uint8_t *p_pixel_base_Y, *p_pixel_base_V, *p_pixel_base_U;
194   ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
195
196   int i_x, i_y;
197   vlc_bool_t even_scanline = VLC_FALSE;
198
199   /* Crop-specific */
200   int i_x_start, i_y_start, i_x_end, i_y_end;
201   /* int i=0; */
202
203   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
204   
205   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
206              "spu width x height: (%dx%d), (x,y)=(%d,%d), yuv pitch (%d,%d,%d)", 
207              p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
208              p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
209
210   
211   p_pixel_base_Y = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x
212                  + p_pic->p[Y_PLANE].i_pitch * p_spu->i_y;
213   
214   p_pixel_base_U = p_pic->p[U_PLANE].p_pixels + p_spu->i_x/2
215                  + p_pic->p[U_PLANE].i_pitch * p_spu->i_y/2;
216   
217   p_pixel_base_V = p_pic->p[V_PLANE].p_pixels + p_spu->i_x/2
218                  + p_pic->p[V_PLANE].i_pitch * p_spu->i_y/2;
219   
220   i_x_start = p_sys->i_x_start;
221   i_y_start = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_start;
222   
223   i_x_end   = p_sys->i_x_end;
224   i_y_end   = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_end;
225   
226   p_source = (ogt_yuvt_t *)p_sys->p_data;
227   
228   /* Draw until we reach the bottom of the subtitle */
229   for( i_y = 0; 
230        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
231        i_y += p_pic->p[Y_PLANE].i_pitch )
232     {
233       uint8_t *p_pixel_base_Y_y = p_pixel_base_Y + i_y;
234       uint8_t *p_pixel_base_U_y = p_pixel_base_U + i_y/4;
235       uint8_t *p_pixel_base_V_y = p_pixel_base_V + i_y/4;
236
237       i_x = 0;
238
239       if ( b_crop ) {
240         if ( i_y > i_y_end ) break;
241         if (i_x_start) {
242           i_x = i_x_start;
243           p_source += i_x_start;
244         }
245       }
246
247       even_scanline = !even_scanline;
248
249       /* Draw until we reach the end of the line */
250       for( ; i_x < p_spu->i_width; i_x++, p_source++ )
251         {
252
253           if( b_crop ) {
254
255             /* FIXME: y cropping should be dealt with outside of this loop.*/
256             if ( i_y < i_y_start) continue;
257
258             if ( i_x > i_x_end )
259             {
260               p_source += p_spu->i_width - i_x;
261               break;
262             }
263           }
264
265 #ifdef TESTING_TRANSPARENCY
266           if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 1;
267 #endif
268
269           switch( p_source->s.t )
270             {
271             case 0: 
272               /* Completely transparent. Don't change pixel. */
273               break;
274               
275             case MAX_TRANS:
276               {
277                 /* Completely opaque. Completely overwrite underlying
278                    pixel with subtitle pixel. */
279                 
280                 /* This is the location that's going to get changed.*/
281                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
282                 
283                 *p_pixel_Y = p_source->plane[Y_PLANE];
284
285                 if ( even_scanline && i_x % 2 == 0 ) {
286                   uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2;
287                   uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2;
288                   *p_pixel_U = p_source->plane[U_PLANE];
289                   *p_pixel_V = p_source->plane[V_PLANE];
290                 }
291                 
292                 break;
293               }
294               
295             default:
296               {
297                 /* Blend in underlying subtitle pixel. */
298                 
299                 /* This is the location that's going to get changed. */
300                 uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
301
302
303                 /* This is the weighted part of the subtitle. The
304                    color plane is 8 bits and transparancy is 4 bits so
305                    when multiplied we get up to 12 bits.
306                  */
307                 uint16_t i_sub_color_Y = 
308                   (uint16_t) ( p_source->plane[Y_PLANE] *
309                                (uint16_t) (p_source->s.t) );
310
311                 /* This is the weighted part of the underlying pixel.
312                    For the same reasons above, the result is up to 12
313                    bits.  However since the transparancies are
314                    inverses, the sum of i_sub_color and i_pixel_color
315                    will not exceed 12 bits.
316                 */
317                 uint16_t i_pixel_color_Y = 
318                   (uint16_t) ( *p_pixel_Y * 
319                                (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
320                 
321                 /* Scale the 12-bit result back down to 8 bits. A
322                    precise scaling after adding the two components,
323                    would divide by one less than a power of 2. However
324                    to simplify and speed things we use a power of
325                    2. This means the boundaries (either all
326                    transparent and all opaque) aren't handled properly.
327                    But we deal with them in special cases above. */
328
329                 *p_pixel_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> TRANS_BITS;
330
331                 if ( even_scanline && i_x % 2 == 0 ) {
332                   uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2
333                     - p_pic->p[U_PLANE].i_pitch / 2;
334                   uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2
335                     - p_pic->p[V_PLANE].i_pitch / 2;
336                   uint16_t i_sub_color_U = 
337                     (uint16_t) ( p_source->plane[U_PLANE] *
338                                  (uint16_t) (p_source->s.t) );
339                   
340                   uint16_t i_sub_color_V = 
341                     (uint16_t) ( p_source->plane[V_PLANE] *
342                                  (uint16_t) (p_source->s.t) );
343                   uint16_t i_pixel_color_U = 
344                     (uint16_t) ( *p_pixel_U * 
345                                  (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
346                   uint16_t i_pixel_color_V = 
347                     (uint16_t) ( *p_pixel_V * 
348                                  (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
349                   *p_pixel_U = ( i_sub_color_U + i_pixel_color_U )>>TRANS_BITS;
350                   *p_pixel_V = ( i_sub_color_V + i_pixel_color_V )>>TRANS_BITS;
351                 }
352                 break;
353               }
354               
355             }
356         }
357     }
358 }
359
360 /*
361
362   YUY2 Format:
363
364   Data is found in memory as an array of bytes in which the first byte
365   contains the first sample of Y, the second byte contains the first
366   sample of Cb (=U), the third byte contains the second sample of Y,
367   the fourth byte contains the first sample of Cr (=V); and so
368   on. Each 32-bit word then contains information for two contiguous
369   horizontal pixels, two 8-bit Y values plus a single Cb and Cr which
370   spans the two pixels.
371 */
372
373 #define BYTES_PER_PIXEL 4
374
375 static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
376                         const subpicture_t *p_spu, vlc_bool_t b_crop )
377 {
378   /* Common variables */
379   uint8_t *p_pixel_base;
380
381   /* This is the where the subtitle pixels come from */
382   ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
383
384   ogt_yuvt_t *p_source_end = (ogt_yuvt_t *)p_spu->p_sys->p_data + 
385     (p_spu->i_width * p_spu->i_height);
386
387   uint16_t i_x, i_y;
388
389   /* Make sure we start on a word (4-byte) boundary. */
390   uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2;
391
392   /* Crop-specific */
393   int i_x_start, i_y_start, i_x_end, i_y_end;
394
395   const struct subpicture_sys_t *p_sys = p_spu->p_sys;
396   
397   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
398              "spu width x height: (%dx%d), (x,y)=(%d,%d), pitch: %d", 
399              p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
400              p_pic->p->i_pitch );
401
402   
403   p_pixel_base = p_pic->p->p_pixels + 
404     + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x;
405
406   i_x_start = p_sys->i_x_start;
407   i_y_start = p_sys->i_y_start * p_pic->p->i_pitch;
408   
409   i_x_end   = p_sys->i_x_end;
410   i_y_end   = p_sys->i_y_end   * p_pic->p->i_pitch;
411
412   /* Draw until we reach the bottom of the subtitle */
413   for( i_y = 0; 
414        i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
415        i_y += p_pic->p[Y_PLANE].i_pitch )
416     {
417       uint8_t *p_pixel_base_y = p_pixel_base + i_y;
418
419       i_x = 0;
420
421       if ( b_crop ) {
422         if ( i_y > i_y_end ) break;
423         if (i_x_start) {
424           i_x = i_x_start;
425           p_source += (i_x_start*2);
426         }
427       }
428   
429
430       /* Draw until we reach the end of the line. Each output pixel
431          is a combination of two source pixels. 
432        */
433       for( i_x = 0;  i_x < p_spu->i_width / 2; i_x++, p_source +=2 )
434         {
435           uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/
436
437           if (p_source > p_source_end-1) {
438             msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d",
439                      i_x, i_y);
440             return;
441           }
442
443           if( b_crop ) {
444
445             /* FIXME: y cropping should be dealt with outside of this loop.*/
446             if ( i_y < i_y_start) continue;
447
448             if ( i_x > i_x_end )
449             {
450               p_source += p_spu->i_width - (i_x*2);
451               break;
452             }
453           }
454   
455           
456           /* Favor opaque subtitle pixels. */
457           if ( (p_source->s.t == 0) && (p_source+1)->s.t == MAX_TRANS )
458             i_avg_tr = (p_source+1)->s.t;
459           else if ( (p_source->s.t == MAX_TRANS) && (p_source+1)->s.t == 0 )
460             i_avg_tr = p_source->s.t;
461           else 
462             i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2;
463           
464 #ifdef TESTING_TRANSPARENCY 
465           if (i_avg_tr == MAX_TRANS) i_avg_tr >>= 1;
466 #endif
467
468           switch( i_avg_tr )
469             {
470             case 0: 
471               /* Completely transparent. Don't change pixel. */
472               break;
473               
474             case MAX_TRANS:
475               {
476                 /* Completely opaque. Completely overwrite underlying
477                    pixel with subtitle pixel. */
478                 
479                 /* This is the location that's going to get changed. */
480                 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
481                 uint8_t i_avg_u;
482                 uint8_t i_avg_v;
483
484                 /* Favor opaque subtitle pixel. */
485                 if (p_source->s.t == MAX_TRANS ) {
486                   i_avg_u = p_source->plane[U_PLANE] ;
487                   i_avg_v = p_source->plane[V_PLANE] ;
488                 } else if ( (p_source+1)->s.t == MAX_TRANS ) {
489                   i_avg_u = (p_source+1)->plane[U_PLANE] ;
490                   i_avg_v = (p_source+1)->plane[V_PLANE] ;
491                 } else {
492                   i_avg_u = ( p_source->plane[U_PLANE] 
493                               + (p_source+1)->plane[U_PLANE] ) / 2;
494                   i_avg_v = ( p_source->plane[V_PLANE] 
495                               + (p_source+1)->plane[V_PLANE] ) / 2;
496                 }
497
498                 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
499                 *p_pixel++ = p_source->plane[Y_PLANE] ;
500                 *p_pixel++ = i_avg_u;
501                 *p_pixel++ = (p_source+1)->plane[Y_PLANE] ;
502                 *p_pixel++ = i_avg_v;
503                 
504                 break;
505               }
506
507             default:
508               {
509                 /* Blend in underlying subtitle pixels. */
510                 
511                 /* This is the location that's going to get changed. */
512                 uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
513                 uint8_t i_avg_u = ( p_source->plane[U_PLANE] 
514                                     + (p_source+1)->plane[U_PLANE] ) / 2;
515                 uint8_t i_avg_v = ( p_source->plane[V_PLANE] 
516                                     + (p_source+1)->plane[V_PLANE] ) / 2;
517
518                 /* This is the weighted part of the two subtitle
519                    pixels. The color plane is 8 bits and transparancy
520                    is 4 bits so when multiplied we get up to 12 bits.
521                  */
522                 uint16_t i_sub_color_Y1 = 
523                   (uint16_t) ( p_source->plane[Y_PLANE] *
524                                (uint16_t) (p_source->s.t) );
525
526                 uint16_t i_sub_color_Y2 = 
527                   (uint16_t) ( (p_source+1)->plane[Y_PLANE] *
528                                (uint16_t) ((p_source+1)->s.t) );
529
530                 /* This is the weighted part of the underlying pixels.
531                    For the same reasons above, the result is up to 12
532                    bits.  However since the transparancies are
533                    inverses, the sum of i_sub_color and i_pixel_color
534                    will not exceed 12 bits.
535                 */
536                 uint16_t i_sub_color_U = 
537                   (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr );
538                 
539                 uint16_t i_sub_color_V = 
540                   (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr );
541
542                 uint16_t i_pixel_color_Y1 = 
543                   (uint16_t) ( *(p_pixel) * 
544                                (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
545                 uint16_t i_pixel_color_Y2 = 
546                   (uint16_t) ( *(p_pixel+2) * 
547                                (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
548                 uint16_t i_pixel_color_U = 
549                   (uint16_t) ( *(p_pixel+1) * 
550                                (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
551                 uint16_t i_pixel_color_V = 
552                   (uint16_t) ( *(p_pixel+3) * 
553                                (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
554
555                 /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
556
557                 /* Scale the 12-bit result back down to 8 bits. A
558                    precise scaling after adding the two components,
559                    would divide by one less than a power of 2. However
560                    to simplify and speed things we use a power of
561                    2. This means the boundaries (either all
562                    transparent and all opaque) aren't handled properly.
563                    But we deal with them in special cases above. */
564
565                 *p_pixel++ = ( i_sub_color_Y1 + i_pixel_color_Y1 )>>TRANS_BITS;
566                 *p_pixel++ = ( i_sub_color_U + i_pixel_color_U )  >>TRANS_BITS;
567                 *p_pixel++ = ( i_sub_color_Y2 + i_pixel_color_Y2 )>>TRANS_BITS;
568                 *p_pixel++ = ( i_sub_color_V + i_pixel_color_V )  >>TRANS_BITS;
569                 break;
570               }
571             }
572         }
573
574       /* For an odd width source, we'll just have to drop off a pixel. */
575       if (p_spu->i_width % 2) p_source++;
576     }
577 }
578
579 /**
580    Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel.
581
582    A RGB 5-5-5 pixel looks like this:
583    RGB 5-5-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
584                  p        ? B4  B3 B2 B1 B0 R4  R3
585                  q       R2 R1  R0 G4 G3 G2 G1  G0
586
587 **/
588
589 static inline void
590 yuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
591 {
592
593   uint8_t rgb[RGB_SIZE];
594
595   yuv2rgb(p_yuv, rgb);
596   
597   /* Scale RGB from 8 bits down to 5. */
598   rgb[RED_PIXEL]   >>= (8-5);
599   rgb[GREEN_PIXEL] >>= (8-5);
600   rgb[BLUE_PIXEL]  >>= (8-5);
601   
602   *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c ) | ( (rgb[RED_PIXEL]>>3) & 0x03 );
603   *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
604
605 #if 0
606   printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
607          "rgb1: %02x, rgb2 %02x\n",
608          p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
609          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
610          *p_rgb1, *p_rgb2);
611 #endif
612
613 }
614
615 /**
616    Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel.
617
618    A RGB 5-6-5 pixel looks like this:
619    RGB 5-6-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
620                  p       B4 B3  B2 B1 B0 R5 R4  R3
621                  q       R2 R1  R0 G4 G3 G2 G1  G0
622
623 **/
624
625 static inline void
626 yuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
627 {
628
629   uint8_t rgb[RGB_SIZE];
630
631   yuv2rgb(p_yuv, rgb);
632   
633   /* Scale RGB from 8 bits down to 5 or 6 bits. */
634   rgb[RED_PIXEL]   >>= (8-6);
635   rgb[GREEN_PIXEL] >>= (8-5);
636   rgb[BLUE_PIXEL]  >>= (8-5);
637   
638   *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 ) | ( (rgb[RED_PIXEL]>>3) & 0x07 );
639   *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
640
641 #if 0
642   printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
643          "rgb1: %02x, rgb2 %02x\n",
644          p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
645          rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
646          *p_rgb1, *p_rgb2);
647 #endif
648
649 }
650
651 static inline void
652 rv16_pack_blend(uint8_t *p_pixel, ogt_yuvt_t *p_source,  uint8_t *p_rgb1,
653                 uint8_t *p_rgb2, vlc_bool_t b_15bpp, uint8_t i_trans, 
654                 int a_scale_down )
655 {
656   uint8_t rgb_sub[3];
657   uint8_t rgb_vout[RGB_SIZE];
658   int i;
659
660   yuv2rgb(p_source, rgb_sub);
661
662   /* Scale RGB from 8 bits down to 6 or 5. */
663   rgb_sub[GREEN_PIXEL] >>= (8-5);
664   rgb_sub[BLUE_PIXEL]  >>= (8-5);
665
666   rgb_vout[GREEN_PIXEL] = *(p_pixel+1)    & 0x1f;
667   if (b_15bpp) {
668     rgb_sub[RED_PIXEL]   >>= (8-5);
669     rgb_vout[BLUE_PIXEL]  = ((*p_pixel)>>2) & 0x1f;
670     rgb_vout[RED_PIXEL]   = ((*p_pixel & 0x03) << 3) | ((*(p_pixel+1)&0xe0)>>5);
671   } else {
672     rgb_sub[RED_PIXEL]   >>= (8-6);
673     rgb_vout[BLUE_PIXEL]  = ((*p_pixel)>>3) & 0x1f;
674     rgb_vout[RED_PIXEL]   = ((*p_pixel & 0x07) << 3) | ((*(p_pixel+1)&0xe0)>>5);
675   }
676   
677
678 #if 0
679   printf("r,g,b=(%d,%d,%d), sub r,g,b=(%d,%d,%d), trans %d, inv_trans %d\n",
680          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL],
681          rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], 
682          rgb_sub[BLUE_PIXEL], i_trans, i_inv_trans);
683 #endif
684
685 #ifdef FIXED_RV16_TRANSPARENCY
686   avg_8bit_rgb(rgb_vout, rgb_sub, i_trans);
687 #else 
688   for (i=0; i < RGB_SIZE; i++) {
689     /* For now the Best we can do is fade the color. Picking up 
690        video underneath doesn't work. */
691     /* rgb_vout[i] = ( (uint16_t) rgb_vout[i]*i_inv_trans ) >> TRANS_BITS; */
692     rgb_vout[i] = ( (uint16_t) rgb_sub[i]*i_trans ) >> TRANS_BITS;
693 #endif 
694   }
695   
696
697 #if 0
698   printf("avg r,g,b=(%d,%d,%d)\n",
699          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL] );
700 #endif
701
702 #if 0
703   if (b_15bpp) {
704     *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 2)&0x7c )|( (rgb_vout[RED_PIXEL]>>3)&0x03 );
705   } else {
706     *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 3)&0xF8 )|( (rgb_vout[RED_PIXEL]>>3)&0x07 );
707   }
708   *p_rgb2 = ( (rgb_vout[RED_PIXEL]  << 5)&0xe0 ) | ( rgb_vout[GREEN_PIXEL]&0x1f );
709 #else 
710   *p_rgb1 = (*p_rgb1)+1;
711   *p_rgb2 = (*p_rgb2)+1;
712 #endif
713   
714 }
715
716 #undef BYTES_PER_PIXEL
717 #define BYTES_PER_PIXEL 2
718
719 static void 
720 BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
721            const subpicture_t *p_spu, vlc_bool_t b_crop,
722            vlc_bool_t b_15bpp )
723 {
724     /* Common variables */
725     uint8_t *p_pixel_base;
726     ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
727     ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
728     ogt_yuvt_t *p_source;
729
730     int i_x, i_y;
731     int i_y_src;
732
733     /* Chroma specific */
734     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
735                             multiplied by 2**ASCALE. */
736     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
737                             multiplied by 2**ASCALE. */
738
739     int i_width, i_height, i_ytmp, i_ynext;
740
741     /* Crop-specific */
742     int i_x_start, i_y_start, i_x_end, i_y_end;
743
744     struct subpicture_sys_t *p_sys = p_spu->p_sys;
745
746     i_xscale = ( p_vout->output.i_width << ASCALE ) / p_vout->render.i_width;
747     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
748
749     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
750                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
751                p_spu->i_width,  p_spu->i_height, 
752                p_vout->output.i_width, p_vout->output.i_height,
753                p_vout->render.i_width, p_vout->render.i_height,
754                i_xscale, i_yscale
755                );
756
757     i_width  = p_spu->i_width  * i_xscale;
758     i_height = p_spu->i_height * i_yscale;
759
760     /* Set where we will start blending subtitle from using
761        the picture coordinates subtitle offsets
762     */
763     p_pixel_base = p_pic->p->p_pixels 
764               + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
765               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
766
767     i_x_start = p_sys->i_x_start;
768     i_y_start = i_yscale * p_sys->i_y_start;
769     i_x_end   = p_sys->i_x_end;
770     i_y_end   = i_yscale * p_sys->i_y_end;
771
772     p_source = (ogt_yuvt_t *)p_sys->p_data;
773   
774     /* Draw until we reach the bottom of the subtitle */
775     i_y = 0;
776     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
777          i_y_src += p_spu->i_width )
778     {
779         uint8_t *p_pixel_base_y;
780         i_ytmp = i_y >> ASCALE;
781         i_y += i_yscale;
782         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
783         i_x = 0;
784
785         if ( b_crop ) {
786           if ( i_y > i_y_end ) break;
787           if (i_x_start) {
788             i_x = i_x_start;
789             p_source += i_x_start;
790           }
791         }
792
793         /* Check whether we need to draw one line or more than one */
794         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
795         {
796           /* Draw until we reach the end of the line */
797           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
798             {
799
800 #if 0              
801               uint8_t *p=(uint8_t *) p_source;
802               printf("+++ %02x %02x %02x %02x\n", 
803                      p[0], p[1], p[2], p[3]);
804 #endif
805     
806               if( b_crop ) {
807                 
808                 /* FIXME: y cropping should be dealt with outside of this 
809                    loop.*/
810                 if ( i_y < i_y_start) continue;
811                 
812                 if ( i_x > i_x_end )
813                   {
814                     p_source += p_spu->i_width - i_x;
815                     break;
816                   }
817               }
818
819               if (p_source >= p_src_end) {
820                 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
821                          i_x, i_y / i_yscale, i_height);
822                 return;
823               }
824               
825 #ifdef TESTING_TRANSPARENCY
826               if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 1;
827 #endif
828
829               switch( p_source->s.t )
830                 {
831                 case 0:
832                   /* Completely transparent. Don't change pixel. */
833                   break;
834                   
835                 case MAX_TRANS:
836                   {
837                     /* Completely opaque. Completely overwrite underlying
838                        pixel with subtitle pixel. */
839                 
840                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
841                                          * BYTES_PER_PIXEL );
842                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
843                                          * BYTES_PER_PIXEL );
844                     uint32_t len     = i_xlast - i_xdest;
845
846                     uint8_t i_rgb1;
847                     uint8_t i_rgb2;
848
849                     /* This is the location that's going to get changed. */
850                     uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
851
852                     if (b_15bpp) 
853                       yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
854                     else 
855                       yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
856
857                     for ( len = i_xlast - i_xdest; len ; len--) {
858                       *p_dest++ = i_rgb1;
859                       *p_dest++ = i_rgb2;
860                     }
861                     break;
862                   }
863
864                 default:
865                   {
866                     /* Blend in underlying pixel subtitle pixel. */
867                     
868                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
869                                          * BYTES_PER_PIXEL );
870                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
871                                          * BYTES_PER_PIXEL );
872                     uint8_t i_rgb1;
873                     uint8_t i_rgb2;
874                     uint32_t len     = i_xlast - i_xdest;
875
876                     /* This is the location that's going to get changed. */
877                     uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
878
879                     for ( len = i_xlast - i_xdest; len ; len--) {
880                       rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2, 
881                                       b_15bpp, p_source->s.t, TRANS_SCALEDOWN);
882                       *p_dest++ = i_rgb1;
883                       *p_dest++ = i_rgb2;
884                     }
885                     break;
886                   }
887                 }
888             }
889         }
890         else
891         {
892             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
893
894
895             /* Draw until we reach the end of the line */
896             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
897             {
898
899               if( b_crop ) {
900                 
901                 /* FIXME: y cropping should be dealt with outside of this 
902                    loop.*/
903                 if ( i_y < i_y_start) continue;
904                 
905                 if ( i_x > i_x_end )
906                   {
907                     p_source += p_spu->i_width - i_x;
908                     break;
909                   }
910               }
911               
912               if (p_source >= p_src_end) {
913                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
914                          i_x, i_y / i_yscale, i_height);
915                 return;
916               }
917               
918               switch( p_source->s.t )
919                 {
920                 case 0:
921                     /* Completely transparent. Don't change pixel. */
922                     break;
923
924                 case MAX_TRANS: 
925                   {
926                     /* Completely opaque. Completely overwrite underlying
927                        pixel with subtitle pixel. */
928
929                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
930                                          * BYTES_PER_PIXEL );
931                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
932                                          * BYTES_PER_PIXEL );
933                     uint32_t len     = i_xlast - i_xdest;
934
935                     uint8_t *p_pixel_base_x = p_pixel_base + i_xdest;
936
937                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
938                     {
939                       /* This is the location that's going to get changed. */
940                       uint8_t *p_dest = p_pixel_base_x + i_ytmp;
941                       uint8_t i_rgb1, i_rgb2;
942                       if (b_15bpp) 
943                         yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
944                       else 
945                         yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
946
947                       for ( len = i_xlast - i_xdest; len ; len--) {
948                         *p_dest++ = i_rgb1;
949                         *p_dest++ = i_rgb2;
950                       }
951                     }
952                     break;
953                   }
954                 default: 
955                   {
956                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
957                                          * BYTES_PER_PIXEL );
958                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
959                                          * BYTES_PER_PIXEL );
960                     uint32_t len     = i_xlast - i_xdest;
961                     uint8_t i_rgb1, i_rgb2;
962                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
963                     {
964                       /* Blend in underlying pixel subtitle pixel. */
965                       uint8_t *p_dest = p_pixel_base + i_ytmp;
966                       for ( len = i_xlast - i_xdest; len ; len--) {
967                         rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2,
968                                       b_15bpp, p_source->s.t, TRANS_SCALEDOWN);
969                         *p_dest++ = i_rgb1;
970                         *p_dest++ = i_rgb2;
971                       }
972                     }
973                     break;
974                   }
975                 }
976             }
977         }
978     }
979 }
980
981 #undef  BYTES_PER_PIXEL
982 #define BYTES_PER_PIXEL 4
983
984 static inline void
985 rv24_pack_blend(uint8_t *rgb_vout, const uint8_t *rgb_sub,  uint8_t i_trans,  
986                 int a_scale_down )
987 {
988
989 #if 0
990   printf("r,g,b=(%d,%d,%d), source r,g,b=(%d,%d,%d), trans %d\n",
991          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL],
992          rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], 
993          rgb_sub[BLUE_PIXEL], i_trans);
994 #endif
995
996 #ifdef WORDS_BIGENDIAN
997   *rgb_vout++;
998 #endif
999
1000   avg_8bit_rgb(rgb_vout, rgb_sub, i_trans);
1001   
1002 #if 0
1003   printf("avg r,g,b=(%d,%d,%d)\n",
1004          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL] );
1005 #endif
1006
1007 }
1008
1009 /* 
1010   RV24 format??? Is this just for X11? Or just not for Win32? Is this
1011   the same as RV32?
1012
1013   a pixel is represented by 3 bytes containing a red,
1014   blue and green sample with blue stored at the lowest address, green
1015   next then red. One padding byte is added between pixels. Although
1016   this may not be part of a spec, images should be stored with each
1017   line padded to a u_int32 boundary. 
1018 */
1019 static void 
1020 BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
1021             const subpicture_t *p_spu, vlc_bool_t b_crop )
1022 {
1023   /* Common variables */
1024   uint8_t *p_pixel_base;
1025   ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
1026   ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1027   ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
1028   
1029   int i_x, i_y;
1030   int i_y_src;
1031   
1032   /* Make sure we start on a word (4-byte) boundary. */
1033   uint32_t i_spu_x;
1034   
1035   /* Chroma specific */
1036   uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1037                           multiplied by 2**ASCALE. */
1038   uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1039                           multiplied by 2**ASCALE. */
1040   
1041   int i_width, i_height, i_ytmp, i_ynext;
1042   
1043   /* Crop-specific */
1044   int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1045   
1046   struct subpicture_sys_t *p_sys = p_spu->p_sys;
1047   int i_aspect_x, i_aspect_y;
1048   
1049   vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
1050                VOUT_ASPECT_FACTOR, 0 );
1051   
1052   i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1053     / (i_aspect_y * p_vout->render.i_width);
1054   i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1055   
1056   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1057              "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1058              p_spu->i_width,  p_spu->i_height, 
1059              p_vout->output.i_width, p_vout->output.i_height,
1060              p_vout->render.i_width, p_vout->render.i_height,
1061              i_xscale, i_yscale
1062              );
1063   
1064   i_width  = p_spu->i_width  * i_xscale;
1065   i_height = p_spu->i_height * i_yscale;
1066   
1067   /* Set where we will start blending subtitle from using
1068      the picture coordinates subtitle offsets.
1069   */
1070   i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
1071   
1072   p_pixel_base = p_pic->p->p_pixels + i_spu_x
1073     + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1074   
1075   i_x_start = p_sys->i_x_start;
1076   i_y_start = i_yscale * p_sys->i_y_start;
1077   i_x_end   = p_sys->i_x_end;
1078   i_y_end   = i_yscale * p_sys->i_y_end;
1079   
1080   p_source = (ogt_yuvt_t *)p_sys->p_data;
1081   
1082   /* Draw until we reach the bottom of the subtitle */
1083   i_y = 0;
1084   for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1085        i_y_src += p_spu->i_width )
1086     {
1087       uint8_t *p_pixel_base_y;
1088       i_ytmp = i_y >> ASCALE;
1089       i_y += i_yscale;
1090       p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1091       i_x = 0;
1092       
1093       if ( b_crop ) {
1094         if ( i_y > i_y_end ) break;
1095         if (i_x_start) {
1096           i_x = i_x_start;
1097           p_source += i_x_start;
1098         }
1099       }
1100       
1101       /* Check whether we need to draw one line or more than one */
1102       if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1103         {
1104           /* Draw until we reach the end of the line */
1105           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
1106             {
1107               
1108               if( b_crop ) {
1109                 
1110                 /* FIXME: y cropping should be dealt with outside of this 
1111                    loop.*/
1112                 if ( i_y < i_y_start) continue;
1113                 
1114                 if ( i_x > i_x_end )
1115                   {
1116                     p_source += p_spu->i_width - i_x;
1117                     break;
1118                   }
1119               }
1120               
1121               if (p_source >= p_src_end) {
1122                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1123                          i_x, i_y / i_yscale, i_height);
1124                 return;
1125               }
1126               
1127 #ifdef TESTING_TRANSPARENCY
1128               if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 2;
1129 #endif
1130
1131               switch( p_source->s.t )
1132                 {
1133                 case 0:
1134                   /* Completely transparent. Don't change pixel. */
1135                   break;
1136                   
1137                 case MAX_TRANS:
1138                   {
1139                     /* Completely opaque. Completely overwrite underlying
1140                        pixel with subtitle pixel. */
1141                     
1142                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1143                                          * BYTES_PER_PIXEL );
1144                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1145                                          * BYTES_PER_PIXEL );
1146                     uint32_t len     = i_xlast - i_xdest;
1147                     
1148                     uint8_t rgb[RGB_SIZE];
1149                     
1150                     /* This is the location that's going to get changed. */
1151                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1152                     
1153                     yuv2rgb(p_source, rgb);
1154                     
1155                     for ( len = i_xlast - i_xdest; len ; len--) {
1156                       put_rgb24_pixel(rgb, p_dest);
1157                       p_dest += BYTES_PER_PIXEL;
1158                     }
1159                     
1160                   default:
1161                     {
1162                       /* Blend in underlying pixel subtitle pixel. */
1163                       
1164                       uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1165                                            * BYTES_PER_PIXEL );
1166                       uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1167                                            * BYTES_PER_PIXEL );
1168                       uint32_t len     = i_xlast - i_xdest * BYTES_PER_PIXEL;
1169                       
1170                       /* To be able to scale correctly for full
1171                          opaqueness, we add 1 to the transparency.
1172                          This means transparency value 0 won't be
1173                          completely transparent which is not correct.
1174                          But that's handled in a special case above
1175                          anyway. */
1176                       
1177                       /* This is the location that's going to get changed. */
1178                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1179                       uint8_t rgb[RGB_SIZE];
1180                       
1181                       yuv2rgb(p_source, rgb);
1182
1183                       for ( len = i_xlast - i_xdest; len ; len--) {
1184                         rv24_pack_blend(p_dest, rgb, p_source->s.t,
1185                                         TRANS_SCALEDOWN);
1186                         p_dest += BYTES_PER_PIXEL;
1187                       }
1188                       break;
1189                     }
1190                   }
1191                 }
1192             }
1193         } 
1194         else
1195         {
1196             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1197
1198
1199             /* Draw until we reach the end of the line */
1200             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1201             {
1202
1203               if( b_crop ) {
1204                 
1205                 /* FIXME: y cropping should be dealt with outside of this 
1206                    loop.*/
1207                 if ( i_y < i_y_start) continue;
1208                 
1209                 if ( i_x > i_x_end )
1210                   {
1211                     p_source += p_spu->i_width - i_x;
1212                     break;
1213                   }
1214               }
1215               
1216               if (p_source >= p_src_end) {
1217                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1218                          i_x, i_y / i_yscale, i_height);
1219                 return;
1220               }
1221               
1222               switch( p_source->s.t )
1223                 {
1224                 case 0:
1225                     /* Completely transparent. Don't change pixel. */
1226                     break;
1227
1228                 case MAX_TRANS: 
1229                   {
1230                     /* Completely opaque. Completely overwrite underlying
1231                        pixel with subtitle pixel. */
1232
1233                     /* This is the location that's going to get changed. */
1234                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1235                                          * BYTES_PER_PIXEL );
1236                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1237                                          * BYTES_PER_PIXEL );
1238                     uint32_t len     = i_xlast - i_xdest;
1239
1240                     uint8_t rgb[RGB_SIZE];
1241
1242                     yuv2rgb(p_source, rgb); 
1243
1244                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1245                     {
1246                       /* Completely opaque. Completely overwrite underlying
1247                          pixel with subtitle pixel. */
1248                       
1249                       /* This is the location that's going to get changed. */
1250                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1251                       
1252                       for ( len = i_xlast - i_xdest; len ; len--) {
1253                         put_rgb24_pixel(rgb, p_dest);
1254                         p_dest += BYTES_PER_PIXEL;
1255                       }
1256                     }
1257                     break;
1258                   }
1259                 default: 
1260                   {
1261                     
1262
1263                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1264                                          * BYTES_PER_PIXEL );
1265                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1266                                          * BYTES_PER_PIXEL );
1267                     uint32_t len     = i_xlast - i_xdest;
1268                     uint8_t  rgb[RGB_SIZE];
1269
1270                     yuv2rgb(p_source, rgb);
1271
1272                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1273                     {
1274                       /* Blend in underlying pixel subtitle pixel. */
1275                       
1276                       /* This is the location that's going to get changed. */
1277                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1278
1279                       /* To be able to scale correctly for full opaqueness, we
1280                          add 1 to the alpha.  This means alpha value 0 won't
1281                          be completely transparent and is not correct, but
1282                          that's handled in a special case above anyway. */
1283
1284                       for ( len = i_xlast - i_xdest; len ; len--) {
1285                         rv24_pack_blend(p_dest, rgb, p_source->s.t,
1286                                         TRANS_SCALEDOWN);
1287                         p_dest += BYTES_PER_PIXEL;
1288                       }
1289                     }
1290                     break;
1291                   }
1292                 }
1293             }
1294         }
1295     }
1296 }
1297
1298 #undef  BYTES_PER_PIXEL
1299 #define BYTES_PER_PIXEL 4
1300
1301 /* 
1302   RV32 format??? Is this just for X11? Or just not for Win32? Is this
1303   the same as RV24?
1304
1305   RV32 format: a pixel is represented by 4 bytes containing a red,
1306   blue and green sample with blue stored at the lowest address, green
1307   next then red. One padding byte is added between pixels. Although
1308   this may not be part of a spec, images should be stored with each
1309   line padded to a u_int32 boundary. 
1310 */
1311 static void 
1312 BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
1313             const subpicture_t *p_spu, vlc_bool_t b_crop )
1314 {
1315     /* Common variables */
1316     uint8_t *p_pixel_base;
1317     ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
1318     ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1319     ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
1320
1321     int i_x, i_y;
1322     int i_y_src;
1323
1324     /* Make sure we start on a word (4-byte) boundary. */
1325     uint32_t i_spu_x;
1326
1327     /* Chroma specific */
1328     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1329                             multiplied by 2**ASCALE. */
1330     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1331                             multiplied by 2**ASCALE. */
1332
1333     int i_width, i_height, i_ytmp, i_ynext;
1334
1335     /* Crop-specific */
1336     int32_t i_x_start, i_y_start, i_x_end, i_y_end;
1337
1338     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1339     int i_aspect_x, i_aspect_y;
1340
1341     vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
1342                 VOUT_ASPECT_FACTOR, 0 );
1343
1344     i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1345       / (i_aspect_y * p_vout->render.i_width);
1346     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1347
1348     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1349                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1350                p_spu->i_width,  p_spu->i_height, 
1351                p_vout->output.i_width, p_vout->output.i_height,
1352                p_vout->render.i_width, p_vout->render.i_height,
1353                i_xscale, i_yscale
1354                );
1355
1356     i_width  = p_spu->i_width  * i_xscale;
1357     i_height = p_spu->i_height * i_yscale;
1358
1359     /* Set where we will start blending subtitle from using
1360        the picture coordinates subtitle offsets.
1361     */
1362     i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL; 
1363
1364     p_pixel_base = p_pic->p->p_pixels + i_spu_x
1365               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1366
1367     i_x_start = p_sys->i_x_start;
1368     i_y_start = i_yscale * p_sys->i_y_start;
1369     i_x_end   = p_sys->i_x_end;
1370     i_y_end   = i_yscale * p_sys->i_y_end;
1371
1372     p_source = (ogt_yuvt_t *)p_sys->p_data;
1373   
1374     /* Draw until we reach the bottom of the subtitle */
1375     i_y = 0;
1376     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1377          i_y_src += p_spu->i_width )
1378     {
1379         uint8_t *p_pixel_base_y;
1380         i_ytmp = i_y >> ASCALE;
1381         i_y += i_yscale;
1382         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1383         i_x = 0;
1384
1385         if ( b_crop ) {
1386           if ( i_y > i_y_end ) break;
1387           if (i_x_start) {
1388             i_x = i_x_start;
1389             p_source += i_x_start;
1390           }
1391         }
1392
1393         /* Check whether we need to draw one line or more than one */
1394         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1395         {
1396           /* Draw until we reach the end of the line */
1397           for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
1398             {
1399
1400               if( b_crop ) {
1401                 
1402                 /* FIXME: y cropping should be dealt with outside of this 
1403                    loop.*/
1404                 if ( i_y < i_y_start) continue;
1405                 
1406                 if ( i_x > i_x_end )
1407                   {
1408                     p_source += p_spu->i_width - i_x;
1409                     break;
1410                   }
1411               }
1412
1413               if (p_source >= p_src_end) {
1414                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1415                          i_x, i_y / i_yscale, i_height);
1416                 return;
1417               }
1418               
1419               switch( p_source->s.t )
1420                 {
1421                 case 0:
1422                   /* Completely transparent. Don't change pixel. */
1423                   break;
1424                   
1425                 default:
1426                 case MAX_TRANS:
1427                   {
1428                     /* Completely opaque. Completely overwrite underlying
1429                        pixel with subtitle pixel. */
1430
1431                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1432                                          * BYTES_PER_PIXEL );
1433                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1434                                          * BYTES_PER_PIXEL );
1435                     uint32_t len     = i_xlast - i_xdest;
1436
1437                     uint8_t rgb[RGB_SIZE];
1438
1439                     /* This is the location that's going to get changed. */
1440                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1441
1442                     yuv2rgb(p_source, rgb);
1443
1444                     for ( len = i_xlast - i_xdest; len ; len--) {
1445                       *p_dest++ = rgb[BLUE_PIXEL];
1446                       *p_dest++ = rgb[GREEN_PIXEL];
1447                       *p_dest++ = rgb[RED_PIXEL];
1448                       *p_dest++;
1449                     }
1450
1451 #ifdef TRANSPARENCY_FINISHED
1452                   default:
1453                     {
1454                       /* Blend in underlying pixel subtitle pixel. */
1455                       
1456                       uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1457                                            * BYTES_PER_PIXEL );
1458                       uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1459                                            * BYTES_PER_PIXEL );
1460                       uint32_t len     = i_xlast - i_xdest;
1461
1462                       /* To be able to scale correctly for full opaqueness, we
1463                          add 1 to the alpha.  This means alpha value 0 won't
1464                          be completely transparent and is not correct, but
1465                          that's handled in a special case above anyway. */
1466                       
1467                       uint8_t i_destalpha = MAX_TRANS - p_source->s.t;
1468                       uint8_t rgb[RGB_SIZE];
1469
1470                       /* This is the location that's going to get changed. */
1471                       uint8_t *p_dest = p_pixel_base_y + i_xdest;
1472                       
1473                       yuv2rgb(p_source, rgb);
1474                       rv32_pack_blend(p_dest, rgb, dest_alpha, 
1475                                       TRANS_SCALEDOWN);
1476
1477                       for ( len = i_xlast - i_xdest; len ; len--) {
1478                         *p_dest++ = rgb[BLUE_PIXEL];
1479                         *p_dest++ = rgb[GREEN_PIXEL];
1480                         *p_dest++ = rgb[RED_PIXEL];
1481                         *p_dest++;
1482                       }
1483                       break;
1484                     }
1485 #endif /*TRANSPARENCY_FINISHED*/
1486                   }
1487                 }
1488             }
1489         } 
1490         else
1491         {
1492             i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1493
1494
1495             /* Draw until we reach the end of the line */
1496             for( ; i_x < p_spu->i_width; i_x++, p_source++ )
1497             {
1498
1499               if( b_crop ) {
1500                 
1501                 /* FIXME: y cropping should be dealt with outside of this 
1502                    loop.*/
1503                 if ( i_y < i_y_start) continue;
1504                 
1505                 if ( i_x > i_x_end )
1506                   {
1507                     p_source += p_spu->i_width - i_x;
1508                     break;
1509                   }
1510               }
1511               
1512               if (p_source >= p_src_end) {
1513                 msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
1514                          i_x, i_y / i_yscale, i_height);
1515                 return;
1516               }
1517               
1518               switch( p_source->s.t )
1519                 {
1520                 case 0:
1521                     /* Completely transparent. Don't change pixel. */
1522                     break;
1523
1524                 default:
1525                 case MAX_TRANS: 
1526                   {
1527                     /* Completely opaque. Completely overwrite underlying
1528                        pixel with subtitle pixel. */
1529
1530                     /* This is the location that's going to get changed. */
1531                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1532                                          * BYTES_PER_PIXEL );
1533                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1534                                          * BYTES_PER_PIXEL );
1535                     uint32_t len     = i_xlast - i_xdest;
1536
1537                     uint8_t rgb[RGB_SIZE];
1538
1539                     yuv2rgb(p_source, rgb); 
1540
1541                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
1542                     {
1543                       /* Completely opaque. Completely overwrite underlying
1544                          pixel with subtitle pixel. */
1545                       
1546                       /* This is the location that's going to get changed. */
1547                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1548                       
1549                       for ( len = i_xlast - i_xdest; len ; len--) {
1550                         put_rgb24_pixel(rgb, p_dest);
1551                       }
1552                     }
1553                     break;
1554                   }
1555 #ifdef TRANSPARENCY_FINISHED
1556                 default: 
1557                   {
1558                     
1559
1560                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1561                                          * BYTES_PER_PIXEL );
1562                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1563                                          * BYTES_PER_PIXEL );
1564                     uint32_t len     = i_xlast - i_xdest;
1565                     uint8_t rgb[RGB_SIZE];
1566
1567                     yuv2rgb(p_source, rgb);
1568
1569                     for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
1570                     {
1571                       /* Blend in underlying pixel subtitle pixel. */
1572                       
1573                       /* This is the location that's going to get changed. */
1574                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1575
1576                       /* To be able to scale correctly for full opaqueness, we
1577                          add 1 to the alpha.  This means alpha value 0 won't
1578                          be completely transparent and is not correct, but
1579                          that's handled in a special case above anyway. */
1580
1581                       uint8_t i_destalpha = MAX_TRANS - p_source->s.t;
1582                       rv32_pack_blend(p_dest, rgb, dest_alpha,
1583                                       TRANS_SCALEDOWN);
1584                     }
1585                     break;
1586 #endif /*TRANSPARENCY_FINISHED*/
1587                 }
1588             }
1589         }
1590     }
1591 }
1592
1593 /* 4-entry array of colormap indices */
1594 static  uint8_t cmap[NUM_SUBTITLE_COLORS];
1595
1596 /* Actual RGB values for above; this is used in blending.*/
1597 static uint8_t cmap_rgb[NUM_SUBTITLE_COLORS][RGB_SIZE];
1598
1599 /*
1600   Return the colormap index for the average of i_pixel and a subtitle
1601   pixel whose subtitle palette entry is i_cmap. 
1602  */
1603 static inline cmap_t
1604 avg_rgb2(const vout_thread_t *p_vout, uint8_t i_pixel, uint8_t i_trans, 
1605          int i_cmap, mtime_t i_pts)
1606 {
1607   uint8_t rgb_vout[RGB_SIZE];
1608
1609   /* Cache the average of a vout colormap entry and a subtitle palette
1610      entry. There are not too many of these 256*4 = 1024.
1611    */
1612   static cmap_t avg_cache[CMAP_RGB2_SIZE][NUM_SUBTITLE_COLORS];
1613
1614   /* subtitle palettes might change between two subtitles. i_last_pts
1615      will be used to figure out if the subtitle has changed, and
1616      we have to invalidate the cache. */
1617   static mtime_t i_last_pts = -1;
1618
1619   if (i_pts != i_last_pts) 
1620     {
1621       /* Hack: We rely on the fact that INVALID_CMAP_ENTRY is repeated
1622          0xFF.
1623        */
1624       memset(avg_cache, 0xFF, sizeof(avg_cache));
1625       i_last_pts = i_pts;
1626     }
1627
1628   if ( avg_cache[i_pixel][i_cmap] != INVALID_CMAP_ENTRY ) 
1629     return avg_cache[i_pixel][i_cmap];
1630
1631   if ( !query_color(p_vout, i_pixel, rgb_vout) ) return INVALID_CMAP_ENTRY;
1632
1633   avg_8bit_rgb(rgb_vout, cmap_rgb[i_cmap], i_trans);
1634
1635 #if 0
1636  {
1637   uint8_t rgb_approx[RGB_SIZE];
1638
1639   avg_cache[i_pixel][i_cmap] = 
1640     find_cmap_rgb8_nearest(p_vout, rgb_vout, rgb_approx);
1641   printf(
1642          "cmap old %0x avg approx 0%x sub: %d sub=(%0x, %0x, %0x) "
1643          "approx=(%0x, %0x, %0x) avg vout=(%0x, %0x, %0x)\n", 
1644          i_pixel, avg_cache[i_pixel][i_cmap], i_cmap,
1645          cmap_rgb[i_cmap][RED_PIXEL], cmap_rgb[i_cmap][GREEN_PIXEL], 
1646          cmap_rgb[i_cmap][BLUE_PIXEL],
1647          rgb_approx[RED_PIXEL], rgb_approx[GREEN_PIXEL], rgb_approx[BLUE_PIXEL],
1648          rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL]);
1649  }  
1650 #else 
1651   avg_cache[i_pixel][i_cmap] = 
1652     find_cmap_rgb8_nearest(p_vout, rgb_vout, NULL);
1653 #endif
1654   return avg_cache[i_pixel][i_cmap];
1655 }
1656
1657 #undef  BYTES_PER_PIXEL
1658 #define BYTES_PER_PIXEL 1
1659
1660 static void 
1661 BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
1662             const subpicture_t *p_spu, vlc_bool_t b_crop )
1663 {
1664     /* Common variables */
1665     uint8_t *p_pixel_base;
1666     uint8_t *p_src_start = (uint8_t *)p_spu->p_sys->p_data;
1667     uint8_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
1668     uint8_t *p_source; /* This is the where the subtitle pixels come from */
1669     int i;
1670
1671     int i_x, i_y;
1672     int i_y_src;
1673
1674     /* Chroma specific */
1675     uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
1676                             multiplied by 2**ASCALE. */
1677     uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
1678                             multiplied by 2**ASCALE. */
1679
1680     int i_width, i_height, i_ytmp;
1681
1682     /* Crop-specific */
1683     int i_x_start, i_y_start, i_x_end, i_y_end;
1684
1685     struct subpicture_sys_t *p_sys = p_spu->p_sys;
1686     int i_aspect_x, i_aspect_y;
1687
1688     vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
1689                 VOUT_ASPECT_FACTOR, 0 );
1690     
1691     i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
1692       / (i_aspect_y * p_vout->render.i_width);
1693     i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
1694
1695     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
1696                "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
1697                p_spu->i_width,  p_spu->i_height, 
1698                p_vout->output.i_width, p_vout->output.i_height,
1699                p_vout->render.i_width, p_vout->render.i_height,
1700                i_xscale, i_yscale
1701                );
1702
1703     i_width  = p_spu->i_width  * i_xscale;
1704     i_height = p_spu->i_height * i_yscale;
1705
1706
1707     /** FIXME: do once per subtitle in subtitle processing, not here
1708         each time we render.  */
1709     /* Find a corresponding colormap entries for our palette entries. */
1710     for( i = 0; i < NUM_SUBTITLE_COLORS; i++ )
1711     {
1712
1713       if ( p_sys->p_palette[i].s.t != 0 ) {
1714         uint8_t rgb[RGB_SIZE]; 
1715         yuv2rgb(&(p_sys->p_palette[i]), rgb);
1716         cmap[i] = 
1717           find_cmap_rgb8_nearest(p_vout, rgb, cmap_rgb[i]);
1718         dbg_print( (DECODE_DBG_RENDER), 
1719                    "palette %d RGB=(%0x, %0x, %0x)\n", i,
1720                    rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL]);
1721       }
1722     }
1723
1724     /* Set where we will start blending subtitle from using
1725        the picture coordinates subtitle offsets
1726     */
1727     p_pixel_base = p_pic->p->p_pixels 
1728               + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
1729               + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
1730
1731     i_x_start = p_sys->i_x_start;
1732     i_y_start = i_yscale * p_sys->i_y_start;
1733     i_x_end   = p_sys->i_x_end;
1734     i_y_end   = i_yscale * p_sys->i_y_end;
1735
1736     p_source = (uint8_t *)p_sys->p_data;
1737   
1738     /* Draw until we reach the bottom of the subtitle */
1739     i_y = 0;
1740     for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
1741          i_y_src += p_spu->i_width )
1742       {
1743         uint8_t *p_pixel_base_y;
1744         i_ytmp = i_y >> ASCALE;
1745         i_y += i_yscale;
1746         p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
1747         i_x = 0;
1748
1749         if ( b_crop ) {
1750           if ( i_y > i_y_end ) break;
1751           if (i_x_start) {
1752             i_x = i_x_start;
1753             p_source += i_x_start;
1754           }
1755         }
1756         
1757         /* Check whether we need to draw one line or more than one */
1758         if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
1759         {
1760
1761           /* Draw until we reach the end of the line */
1762           for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1763             {
1764               ogt_yuvt_t p_yuvt;
1765
1766               if( b_crop ) {
1767                 
1768                 /* FIXME: y cropping should be dealt with outside of this 
1769                    loop.*/
1770                 if ( i_y < i_y_start) continue;
1771                 
1772                 if ( i_x > i_x_end )
1773                   {
1774                     p_source += p_spu->i_width - i_x;
1775                     break;
1776                   }
1777               }
1778               
1779               if (p_source >= p_src_end) {
1780                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1781                          i_x, i_y / i_yscale, i_height);
1782                 return;
1783               }
1784               
1785               p_yuvt = p_sys->p_palette[*p_source & 0x3];
1786
1787 #ifdef TESTING_TRANSPARENCY
1788               if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;
1789 #endif
1790
1791               switch ( p_yuvt.s.t ) 
1792                 {
1793                 case 0:
1794                   /* Completely transparent. Don't change pixel. */
1795 #if 0
1796                   printf(" "); /*++++*/
1797 #endif
1798                   break;
1799                 case MAX_TRANS: 
1800                   {
1801                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1802                                          * BYTES_PER_PIXEL );
1803                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1804                                          * BYTES_PER_PIXEL );
1805                     /* This is the pixel that's going to change;*/
1806                     uint8_t *p_dest = p_pixel_base_y + i_xdest;
1807                     memset( p_dest, cmap[*p_source & 0x3], i_xlast - i_xdest );
1808 #if 0
1809                     printf("%1d", *p_source); /*++++*/
1810 #endif
1811                     break;
1812                   }
1813                 default:
1814                   {
1815                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1816                                          * BYTES_PER_PIXEL );
1817                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1818                                          * BYTES_PER_PIXEL );
1819                     /* This is the pixel that's going to change;*/
1820                     uint8_t *p_pixel = p_pixel_base_y + i_xdest;
1821                     uint32_t len     = i_xlast - i_xdest;
1822
1823 #if FULL_TRANSPARENCY
1824                     /* This is what should be done, but it may be too
1825                        slow.  */
1826                     for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
1827                       {
1828                         cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,
1829                                                   *p_source, p_sys->i_pts);
1830                                                   
1831                         if (i_cmap != INVALID_CMAP_ENTRY) 
1832                           *p_pixel= (uint8_t) i_cmap;
1833                         p_pixel++;
1834                       }
1835 #else
1836                     cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,
1837                                               *p_source, p_sys->i_pts);
1838                     if (i_cmap != INVALID_CMAP_ENTRY) 
1839                       memset(p_pixel, i_cmap, len);
1840 #endif 
1841
1842 #if 0
1843                     printf("%1d", *p_source); /*++++*/
1844 #endif
1845                   }
1846                 }
1847             }
1848 #if 0
1849           printf("\n"); /*++++*/
1850 #endif
1851         } else {
1852           /* Have to scale over many lines. */
1853           int i_yreal = p_pic->p->i_pitch * i_ytmp;
1854           int i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
1855
1856            /* Draw until we reach the end of the line */
1857            for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
1858              {
1859               ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];
1860
1861               if( b_crop ) {
1862                 
1863                 /* FIXME: y cropping should be dealt with outside of this 
1864                    loop.*/
1865                 if ( i_y < i_y_start) continue;
1866                 
1867                 if ( i_x > i_x_end )
1868                   {
1869                     p_source += p_spu->i_width - i_x;
1870                     break;
1871                   }
1872               }
1873               
1874               if (p_source >= p_src_end) {
1875                 msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
1876                          i_x, i_y / i_yscale, i_height);
1877                 return;
1878               }
1879               
1880 #ifdef TESTING_TRANSPARENCY
1881               if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;
1882 #endif
1883               switch ( p_yuvt.s.t ) 
1884                 {
1885                 case 0:
1886                   /* Completely transparent. Don't change pixel. */
1887 #if 0
1888                   printf(" "); /*++++*/
1889 #endif
1890                   break;
1891                 case MAX_TRANS: 
1892                   {
1893                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1894                                          * BYTES_PER_PIXEL );
1895                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1896                                          * BYTES_PER_PIXEL );
1897                     uint32_t len     = i_xlast - i_xdest;
1898 #if 0
1899                     printf("%1d", *p_source); /*++++*/
1900 #endif
1901                     for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
1902                          i_ytmp += p_pic->p->i_pitch ) {
1903                       uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
1904                       memset( p_dest, cmap[*p_source & 0x3], len );
1905                     }
1906                     break;
1907                   }
1908                 default:
1909                   {
1910                     uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
1911                                          * BYTES_PER_PIXEL );
1912                     uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
1913                                          * BYTES_PER_PIXEL );
1914                     int32_t len = i_xlast - i_xdest;
1915 #if 0
1916                     printf("%1d", *p_source); /*++++*/
1917 #endif
1918
1919                     for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
1920                          i_ytmp += p_pic->p->i_pitch ) {
1921                       /* This is the pixel that's going to change;*/
1922                       uint8_t *p_pixel = p_pixel_base + i_ytmp + i_xdest;
1923
1924 #if FULL_TRANSPARENCY
1925                     /* This is what should be done, but it may be too
1926                        slow.  */
1927                       for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
1928                         {
1929                           cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, 
1930                                                     p_yuvt.s.t, *p_source, 
1931                                                     p_sys->i_pts);
1932                           if (i_cmap != INVALID_CMAP_ENTRY) 
1933                             *p_pixel= (uint8_t) i_cmap;
1934                           p_pixel++;
1935                         }
1936 #else
1937                     cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t, 
1938                                               *p_source, p_sys->i_pts);
1939                     if (i_cmap != INVALID_CMAP_ENTRY) 
1940                       memset(p_pixel, i_cmap, len);
1941 #endif 
1942
1943                     }
1944                   }
1945                 }
1946              }
1947         }
1948       }
1949 }
1950
1951 \f
1952 /* 
1953  * Local variables:
1954  *  c-file-style: "gnu"
1955  *  tab-width: 8
1956  *  indent-tabs-mode: nil
1957  * End:
1958  */