8f65d8ddba1a9bd170a9c346896571bcb4614a58
[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.2 2003/12/27 01:49:59 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 "ogt.h"
36
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 static void RenderI420( vout_thread_t *, picture_t *, const subpicture_t *,
41                         vlc_bool_t );
42
43 /*****************************************************************************
44  * RenderSPU: draw an SPU on a picture
45  *****************************************************************************
46  
47   This is a fast implementation of the subpicture drawing code. The
48   data has been preprocessed. Each byte has a run-length 1 in the upper
49   nibble and a color in the lower nibble. The interleaving of rows has
50   been done. Most sanity checks are already done so that this
51   routine can be as fast as possible.
52
53  *****************************************************************************/
54 void E_(RenderSPU)( vout_thread_t *p_vout, picture_t *p_pic,
55                     const subpicture_t *p_spu )
56 {
57
58     /*
59       printf("+++%x\n", p_vout->output.i_chroma);
60     */
61   
62     switch( p_vout->output.i_chroma )
63     {
64         /* I420 target, no scaling */
65         case VLC_FOURCC('I','4','2','0'):
66         case VLC_FOURCC('I','Y','U','V'):
67         case VLC_FOURCC('Y','V','1','2'):
68             RenderI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
69             break;
70
71         /* RV16 target, scaling */
72         case VLC_FOURCC('R','V','1','6'):
73             msg_Err( p_vout, "RV16 not implimented yet" );
74             break;
75
76         /* RV32 target, scaling */
77         case VLC_FOURCC('R','V','2','4'):
78         case VLC_FOURCC('R','V','3','2'):
79             msg_Err( p_vout, "RV24/VF32 not implimented yet" );
80             break;
81
82         /* NVidia overlay, no scaling */
83         case VLC_FOURCC('Y','U','Y','2'):
84             msg_Err( p_vout, "YUV2 not implimented yet" );
85             break;
86
87         default:
88             msg_Err( p_vout, "unknown chroma, can't render SPU" );
89             break;
90     }
91 }
92
93 /* Following functions are local */
94
95 static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
96                         const subpicture_t *p_spu, vlc_bool_t b_crop )
97 {
98   /* Common variables */
99   uint8_t *p_dest;
100   uint8_t *p_destptr;
101   ogt_yuvt_t *p_source;
102   
103   int i_x, i_y;
104   uint16_t i_colprecomp, i_destalpha;
105   
106   /* Crop-specific */
107   int i_x_start, i_y_start, i_x_end, i_y_end;
108   /* int i=0; */
109   
110   p_dest = p_pic->Y_PIXELS + p_spu->i_x + p_spu->i_width
111     + p_pic->Y_PITCH * ( p_spu->i_y + p_spu->i_height );
112   
113   i_x_start = p_spu->i_width - p_spu->p_sys->i_x_end;
114   i_y_start = p_pic->Y_PITCH * (p_spu->i_height - p_spu->p_sys->i_y_end );
115   i_x_end   = p_spu->i_width - p_spu->p_sys->i_x_start;
116   i_y_end   = p_pic->Y_PITCH * (p_spu->i_height - p_spu->p_sys->i_y_start );
117   
118   p_source = (ogt_yuvt_t *)p_spu->p_sys->p_data;
119
120   /* printf("+++spu width: %d, height %d\n", p_spu->i_width, 
121      p_spu->i_height); */
122   
123   /* Draw until we reach the bottom of the subtitle */
124   for( i_y = p_spu->i_height * p_pic->Y_PITCH ;
125        i_y ;
126        i_y -= p_pic->Y_PITCH )
127     {
128       /* printf("+++begin line: %d,\n", i++); */
129       /* Draw until we reach the end of the line */
130       for( i_x = p_spu->i_width ; i_x ; i_x--, p_source++ )
131         {
132           
133           if( b_crop
134               && ( i_x < i_x_start || i_x > i_x_end
135                    || i_y < i_y_start || i_y > i_y_end ) )
136             {
137               continue;
138             }
139
140           /* printf( "t: %x, y: %x, u: %x, v: %x\n", 
141              p_source->t, p_source->y, p_source->u, p_source->v ); */
142           
143           switch( p_source->t )
144             {
145             case 0x00: 
146               /* Completely transparent. Don't change underlying pixel */
147               break;
148               
149             case 0x0f:
150               /* Completely opaque. Completely overwrite underlying
151                  pixel with subtitle pixel. */
152
153               p_destptr = p_dest - i_x - i_y;
154
155               i_colprecomp = (uint16_t) ( p_source->y * 15 );
156               *p_destptr = i_colprecomp >> 4;
157
158               break;
159               
160             default:
161               /* Blend in underlying pixel subtitle pixel. */
162
163               /* To be able to divide by 16 (>>4) we add 1 to the alpha.
164                * This means Alpha 0 won't be completely transparent, but
165                * that's handled in a special case above anyway. */
166
167               p_destptr = p_dest - i_x - i_y;
168
169               i_colprecomp = (uint16_t) ( (p_source->y 
170                                            * (uint16_t)(p_source->t + 1) ) );
171               i_destalpha = 15 - p_source->t;
172
173               *p_destptr = ( i_colprecomp +
174                                (uint16_t)*p_destptr * i_destalpha ) >> 4;
175               break;
176             }
177         }
178     }
179 }
180