Work towards handling all planes in subtites, generalizing for CVD, and
[vlc.git] / modules / codec / ogt / render.c
1 /*****************************************************************************
2  * render.c : Philips OGT (SVCD Subtitle) renderer
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: render.c,v 1.3 2003/12/28 02:01:11 rocky Exp $
6  *
7  * Author: Rocky Bernstein 
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 "subtitle.h"
36 #include "render.h"
37
38 /* We use 8 bits for an alpha value: 0..255. Note: For DVDs; 0.15. */
39 #define ALPHA_BITS (8)
40 #define MAX_ALPHA  ((1<<ALPHA_BITS) - 1) 
41
42 /* Horrible hack to get dbg_print to do the right thing */
43 #define p_dec p_vout
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static void RenderI420( vout_thread_t *, picture_t *, const subpicture_t *,
49                         vlc_bool_t );
50
51 /*****************************************************************************
52  * RenderSPU: draw an SPU on a picture
53  *****************************************************************************
54  
55   This is a fast implementation of the subpicture drawing code. The
56   data has been preprocessed. Each byte has a run-length 1 in the upper
57   nibble and a color in the lower nibble. The interleaving of rows has
58   been done. Most sanity checks are already done so that this
59   routine can be as fast as possible.
60
61  *****************************************************************************/
62 void VCDRenderSPU( vout_thread_t *p_vout, picture_t *p_pic,
63                    const subpicture_t *p_spu )
64 {
65     struct subpicture_sys_t *p_sys = p_spu->p_sys;
66   
67     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
68                "chroma %x", p_vout->output.i_chroma );
69   
70     switch( p_vout->output.i_chroma )
71     {
72         /* I420 target, no scaling */
73         case VLC_FOURCC('I','4','2','0'):
74         case VLC_FOURCC('I','Y','U','V'):
75         case VLC_FOURCC('Y','V','1','2'):
76             RenderI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
77             break;
78
79         /* RV16 target, scaling */
80         case VLC_FOURCC('R','V','1','6'):
81             msg_Err( p_vout, "RV16 not implimented yet" );
82             break;
83
84         /* RV32 target, scaling */
85         case VLC_FOURCC('R','V','2','4'):
86         case VLC_FOURCC('R','V','3','2'):
87             msg_Err( p_vout, "RV24/VF32 not implimented yet" );
88             break;
89
90         /* NVidia overlay, no scaling */
91         case VLC_FOURCC('Y','U','Y','2'):
92             msg_Err( p_vout, "YUV2 not implimented yet" );
93             break;
94
95         default:
96             msg_Err( p_vout, "unknown chroma, can't render SPU" );
97             break;
98     }
99 }
100
101 /* Following functions are local */
102
103 static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
104                         const subpicture_t *p_spu, vlc_bool_t b_crop )
105 {
106   /* Common variables */
107   uint8_t *p_dest;
108   uint8_t *p_destptr;
109   ogt_yuvt_t *p_source;
110
111   unsigned int i_plane;
112   int i_x, i_y;
113   uint16_t i_colprecomp, i_destalpha;
114   
115   /* Crop-specific */
116   int i_x_start, i_y_start, i_x_end, i_y_end;
117   /* int i=0; */
118
119   struct subpicture_sys_t *p_sys = p_spu->p_sys;
120   
121   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
122              "spu width: %d, height %d, pitch (%d, %d, %d)", 
123              p_spu->i_width,  p_spu->i_height, 
124              p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
125
126   
127   /*for ( i_plane = 0; i_plane < p_pic->i_planes ; i_plane++ )*/
128   for ( i_plane = 0; i_plane < 1 ; i_plane++ )
129     {
130       
131       p_dest = p_pic->p[i_plane].p_pixels + p_spu->i_x + p_spu->i_width
132         + p_pic->p[i_plane].i_pitch * ( p_spu->i_y + p_spu->i_height );
133       
134       i_x_start = p_spu->i_width - p_sys->i_x_end;
135       i_y_start = p_pic->p[i_plane].i_pitch 
136         * (p_spu->i_height - p_sys->i_y_end );
137       
138       i_x_end   = p_spu->i_width - p_sys->i_x_start;
139       i_y_end   = p_pic->p[i_plane].i_pitch 
140         * (p_spu->i_height - p_sys->i_y_start );
141       
142       p_source = (ogt_yuvt_t *)p_sys->p_data;
143       
144       /* Draw until we reach the bottom of the subtitle */
145       for( i_y = p_spu->i_height * p_pic->p[i_plane].i_pitch ;
146            i_y ;
147            i_y -= p_pic->p[i_plane].i_pitch )
148         {
149           /* printf("+++begin line: %d,\n", i++); */
150           /* Draw until we reach the end of the line */
151           for( i_x = p_spu->i_width ; i_x ; i_x--, p_source++ )
152             {
153               
154               if( b_crop
155                   && ( i_x < i_x_start || i_x > i_x_end
156                        || i_y < i_y_start || i_y > i_y_end ) )
157                 {
158                   continue;
159                 }
160               
161               /* printf( "t: %x, y: %x, u: %x, v: %x\n", 
162                  p_source->s.t, p_source->y, p_source->u, p_source->v ); */
163               
164               switch( p_source->s.t )
165                 {
166                 case 0x00: 
167                   /* Completely transparent. Don't change underlying pixel */
168                   break;
169                   
170                 case MAX_ALPHA:
171                   /* Completely opaque. Completely overwrite underlying
172                      pixel with subtitle pixel. */
173                   
174                   p_destptr = p_dest - i_x - i_y;
175                   
176                   i_colprecomp = 
177                     (uint16_t) ( p_source->plane[i_plane] * MAX_ALPHA );
178                   *p_destptr = i_colprecomp >> ALPHA_BITS;
179                   
180                   break;
181                   
182                 default:
183                   /* Blend in underlying pixel subtitle pixel. */
184                   
185                   /* To be able to ALPHA_BITS, we add 1 to the alpha.
186                    * This means Alpha 0 won't be completely transparent, but
187                    * that's handled in a special case above anyway. */
188                   
189                   p_destptr = p_dest - i_x - i_y;
190                   
191                   i_colprecomp = (uint16_t) (p_source->plane[i_plane] 
192                                * (uint16_t) (p_source->s.t+1) );
193                   i_destalpha = MAX_ALPHA - p_source->s.t;
194                   
195                   *p_destptr = ( i_colprecomp +
196                                  (uint16_t)*p_destptr * i_destalpha ) 
197                     >> ALPHA_BITS;
198                   break;
199                 }
200             }
201         }
202   }
203 }
204