1 /*****************************************************************************
2 * video_spu.h : DVD subpicture units functions
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
36 #include "video_output.h"
37 #include "video_spu.h"
41 typedef struct vout_spu_s
46 /* drawing coordinates inside the spu */
55 static int NewLine ( vout_spu_t *p_vspu, int *i_id );
57 /* i = get_nibble(); */
58 #define GET_NIBBLE( i ) \
61 i_next = *p_from[i_id]; \
72 /* i = j + get_nibble(); */
73 #define ADD_NIBBLE( i, j ) \
76 i_next = *p_from[i_id]; \
79 i = (j) + (i_next >> 4); \
84 i = (j) + (i_next & 0xf); \
87 /*****************************************************************************
88 * vout_RenderSPU: draws an SPU on a picture
89 *****************************************************************************
91 *****************************************************************************/
92 void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_subpic,
93 int i_bytes_per_pixel, int i_bytes_per_line )
100 /* FIXME: we need a way to get this information from the stream */
101 #define TARGET_WIDTH 720
102 #define TARGET_HEIGHT 576
103 int i_x_scale = ( p_buffer->i_pic_width << 6 ) / TARGET_WIDTH;
104 int i_y_scale = ( p_buffer->i_pic_height << 6 ) / TARGET_HEIGHT;
106 /* FIXME: fake palette - the real one has to be sought in the .IFO */
107 static int p_palette[4] = { 0x0000, 0x0000, 0x5555, 0xffff };
109 boolean_t b_aligned = 1;
113 p_from[1] = p_subpic->p_data + p_subpic->type.spu.i_offset[1];
114 p_from[0] = p_subpic->p_data + p_subpic->type.spu.i_offset[0];
118 vspu.i_width = TARGET_WIDTH;
119 vspu.i_height = TARGET_HEIGHT;
120 vspu.p_data = p_buffer->p_data
121 /* add the picture coordinates and the SPU coordinates */
122 + ( p_buffer->i_pic_x + ((p_subpic->i_x * i_x_scale) >> 6))
124 + ( p_buffer->i_pic_y + ((p_subpic->i_y * i_y_scale) >> 6))
127 while( p_from[0] < (byte_t *)p_subpic->p_data
128 + p_subpic->type.spu.i_offset[1] )
130 GET_NIBBLE( i_code );
136 if( ((i_code >> 2) + vspu.i_x + vspu.i_y * vspu.i_width)
137 > vspu.i_height * vspu.i_width )
139 intf_DbgMsg ( "video_spu: invalid draw request ! %d %d\n",
140 i_code >> 2, vspu.i_height * vspu.i_width
141 - ( (i_code >> 2) + vspu.i_x
142 + vspu.i_y * vspu.i_width ) );
147 if( (i_color = i_code & 0x3) )
149 u8 *p_target = &vspu.p_data[
150 i_bytes_per_pixel * ((vspu.i_x * i_x_scale) >> 6)
151 + i_bytes_per_line * ((vspu.i_y * i_y_scale) >> 6) ];
153 memset( p_target, p_palette[i_color],
154 ((((i_code - 1) * i_x_scale) >> 8) + 1)
155 * i_bytes_per_pixel );
157 /* if we need some horizontal scaling (unlikely )
158 * we only scale up to 2x, someone watching a DVD
159 * with more than 2x zoom must be braindead */
160 if( i_y_scale >= (1 << 6) )
162 p_target += i_bytes_per_line;
164 memset( p_target, p_palette[i_color],
165 ((((i_code - 1) * i_x_scale) >> 8) + 1)
166 * i_bytes_per_pixel );
169 vspu.i_x += i_code >> 2;
172 if( vspu.i_x >= vspu.i_width )
174 /* byte-align the stream */
176 /* finish the line */
177 NewLine( &vspu, &i_id );
182 ADD_NIBBLE( i_code, (i_code << 4) );
183 if( i_code >= 0x10 ) /* 00 11 xx cc */
184 goto found_code; /* 00 01 xx cc */
186 ADD_NIBBLE( i_code, (i_code << 4) );
187 if( i_code >= 0x040 ) /* 00 00 11 xx xx cc */
188 goto found_code; /* 00 00 01 xx xx cc */
190 ADD_NIBBLE( i_code, (i_code << 4) );
191 if( i_code >= 0x0100 ) /* 00 00 00 11 xx xx xx cc */
192 goto found_code; /* 00 00 00 01 xx xx xx cc */
194 /* if the 14 first bits are 0, then it's a newline */
195 if( i_code <= 0x0003 )
197 if( NewLine( &vspu, &i_id ) < 0 )
205 /* we have a boo boo ! */
206 intf_DbgMsg( "video_spu: unknown code 0x%x "
207 "(dest %x side %x, x=%d, y=%d)\n",
208 i_code, p_from[i_id], i_id, vspu.i_x, vspu.i_y );
209 if( NewLine( &vspu, &i_id ) < 0 )
216 static int NewLine( vout_spu_t *p_vspu, int *i_id )
223 return( p_vspu->i_width - p_vspu->i_y );