]> git.sesse.net Git - vlc/blob - src/video_output/video_spu.c
*) Fixed stupid bug in vout_Manage. It sometimes called SetDSequenceMatrix
[vlc] / src / video_output / video_spu.c
1 /*****************************************************************************
2  * video_spu.c : DVD subpicture units functions
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: video_spu.c,v 1.22 2001/11/28 15:08:06 massiot Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <stdio.h>
30 #include <string.h>                                    /* memcpy(), memset() */
31
32 #include "config.h"
33 #include "common.h"
34 #include "intf_msg.h"
35 #include "threads.h"
36 #include "mtime.h"
37
38 #include "video.h"
39 #include "video_output.h"
40 #include "video_spu.h"
41
42 /* FIXME: fake palette - the real one has to be sought in the .IFO */
43 static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
44
45 /*****************************************************************************
46  * vout_RenderRGBSPU: draw an SPU on a picture
47  *****************************************************************************
48  * This is a fast implementation of the subpicture drawing code. The data
49  * has been preprocessed once in spu_decoder.c, so we don't need to parse the
50  * RLE buffer again and again. Most sanity checks are done in spu_decoder.c
51  * so that this routine can be as fast as possible.
52  *****************************************************************************/
53 void   vout_RenderRGBSPU( picture_t *p_pic, const subpicture_t *p_spu,
54                           vout_buffer_t *p_buffer,
55                           int i_bytes_per_pixel, int i_bytes_per_line )
56 {
57     int  i_len, i_color;
58     u16 *p_source = (u16 *)p_spu->p_data;
59
60     int i_xscale = ( p_buffer->i_pic_width << 6 ) / p_pic->i_width;
61     int i_yscale = ( p_buffer->i_pic_height << 6 ) / p_pic->i_height;
62
63     int i_width  = p_spu->i_width  * i_xscale;
64     int i_height = p_spu->i_height * i_yscale;
65
66     int i_x, i_y, i_ytmp, i_yreal, i_ynext;
67
68     u8 *p_dest = p_buffer->p_data + ( i_width >> 6 ) * i_bytes_per_pixel
69                   /* Add the picture coordinates and the SPU coordinates */
70                   + ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6))
71                        * i_bytes_per_pixel
72                   + ( p_buffer->i_pic_y + ((p_spu->i_y * i_yscale) >> 6))
73                        * i_bytes_per_line;
74
75     /* Draw until we reach the bottom of the subtitle */
76     i_y = 0;
77
78     while( i_y < i_height )
79     {
80         i_ytmp = i_y >> 6;
81         i_y += i_yscale;
82
83         /* Check whether we need to draw one line or more than one */
84         if( i_ytmp + 1 >= ( i_y >> 6 ) )
85         {
86             /* Just one line : we precalculate i_y >> 6 */
87             i_yreal = i_bytes_per_line * i_ytmp;
88
89             /* Draw until we reach the end of the line */
90             i_x = i_width;
91
92             while( i_x )
93             {
94                 /* Get the RLE part */
95                 i_color = *p_source & 0x3;
96
97                 /* Draw the line */
98                 if( i_color )
99                 {
100                     i_len = i_xscale * ( *p_source++ >> 2 );
101
102                     memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
103                                    + i_yreal,
104                             p_palette[ i_color ],
105                             i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
106
107                     i_x -= i_len;
108                     continue;
109                 }
110
111                 i_x -= i_xscale * ( *p_source++ >> 2 );
112             }
113         }
114         else
115         {
116             i_yreal = i_bytes_per_line * i_ytmp;
117             i_ynext = i_bytes_per_line * i_y >> 6;
118
119             /* Draw until we reach the end of the line */
120             i_x = i_width;
121
122             while( i_x )
123             {
124                 /* Get the RLE part */
125                 i_color = *p_source & 0x3;
126
127                 /* Draw as many lines as needed */
128                 if( i_color )
129                 {
130                     i_len = i_xscale * ( *p_source++ >> 2 );
131
132                     for( i_ytmp = i_yreal ;
133                          i_ytmp < i_ynext ;
134                          i_ytmp += i_bytes_per_line )
135                     {
136                         memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
137                                        + i_ytmp,
138                                 p_palette[ i_color ],
139                                 i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
140                     }
141
142                     i_x -= i_len;
143                     continue;
144                 }
145
146                 i_x -= i_xscale * ( *p_source++ >> 2 );
147             }
148         }
149     }
150 }
151
152 /*****************************************************************************
153  * vout_RenderYUVSPU: draw an SPU on an YUV overlay
154  *****************************************************************************
155  * This is a fast implementation of the subpicture drawing code. The data
156  * has been preprocessed once in spu_decoder.c, so we don't need to parse the
157  * RLE buffer again and again. Most sanity checks are done in spu_decoder.c
158  * so that this routine can be as fast as possible.
159  *****************************************************************************/
160 void vout_RenderYUVSPU( picture_t *p_pic, const subpicture_t *p_spu )
161 {
162     int  i_len, i_color;
163     u16 *p_source = (u16 *)p_spu->p_data;
164
165     int i_x, i_y;
166
167     u8 *p_dest = p_pic->p_y + p_spu->i_x + p_spu->i_width
168                         + p_pic->i_width * ( p_spu->i_y + p_spu->i_height );
169
170     /* Draw until we reach the bottom of the subtitle */
171     i_y = p_spu->i_height * p_pic->i_width;
172
173     while( i_y )
174     {
175         /* Draw until we reach the end of the line */
176         i_x = p_spu->i_width;
177
178         while( i_x )
179         {
180             /* Draw the line if needed */
181             i_color = *p_source & 0x3;
182
183             if( i_color )
184             {
185                 i_len = *p_source++ >> 2;
186                 memset( p_dest - i_x - i_y, p_palette[ i_color ], i_len );
187                 i_x -= i_len;
188                 continue;
189             }
190
191             i_x -= *p_source++ >> 2;
192         }
193
194         i_y -= p_pic->i_width;
195     }
196 }
197