1 /*****************************************************************************
2 * video_spu.c : DVD subpicture units functions
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
6 * Authors: Samuel Hocevar <sam@zoy.org>
7 * Henri Fallon <henri@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
37 #include "video_output.h"
38 #include "video_spu.h"
42 /* FIXME: fake palette - the real one has to be sought in the .IFO */
43 static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
45 static __inline__ u8 GetNibble( u8 *p_source, int *pi_index )
49 return( p_source[(*pi_index)++ >> 1] & 0xf );
53 return( p_source[(*pi_index)++ >> 1] >> 4 );
57 /*****************************************************************************
58 * vout_RenderSPU: draw an SPU on a picture
59 *****************************************************************************
61 *****************************************************************************/
62 void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
63 int i_bytes_per_pixel, int i_bytes_per_line )
70 int i_width = p_spu->i_width;
71 int i_height = p_spu->i_height;
73 /* Drawing coordinates inside the SPU */
76 /* FIXME: we need a way to get this information from the stream */
77 #define TARGET_WIDTH 720
78 #define TARGET_HEIGHT 576
79 int i_xscale = ( p_buffer->i_pic_width << 6 ) / TARGET_WIDTH;
80 int i_yscale = ( p_buffer->i_pic_height << 6 ) / TARGET_HEIGHT;
82 u8 *p_source = p_spu->p_data;
86 pi_index[0] = ( p_spu->type.spu.i_offset[0] - 2 ) << 1;
87 pi_index[1] = ( p_spu->type.spu.i_offset[1] - 2 ) << 1;
89 p_dest = p_buffer->p_data
90 /* add the picture coordinates and the SPU coordinates */
91 + ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6))
93 + ( p_buffer->i_pic_y + ((p_spu->i_y * i_yscale) >> 6))
96 while( pi_index[0] >> 1 < p_spu->type.spu.i_offset[1] )
98 i_code = GetNibble( p_source, pi_index + i_id );
104 if( ((i_code >> 2) + i_x + i_y * i_width) > i_height * i_width )
106 intf_DbgMsg ( "video_spu: invalid draw request ! %d %d",
107 i_code >> 2, i_height * i_width
108 - ( (i_code >> 2) + i_x + i_y * i_width ) );
113 if( (i_color = i_code & 0x3) )
115 u8 *p_target = p_dest
116 + i_bytes_per_pixel * ((i_x * i_xscale) >> 6)
117 + i_bytes_per_line * ((i_y * i_yscale) >> 6);
119 memset( p_target, p_palette[i_color],
120 ((((i_code >> 2) * i_xscale) >> 6) + 1)
121 * i_bytes_per_pixel );
128 /* byte-align the stream */
129 if( pi_index[i_id] & 0x1 )
147 i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
149 if( i_code >= 0x10 ) /* 00 11 xx cc */
151 goto found_code; /* 00 01 xx cc */
154 i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
155 if( i_code >= 0x040 ) /* 00 00 11 xx xx cc */
157 goto found_code; /* 00 00 01 xx xx cc */
160 i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
161 if( i_code >= 0x0100 ) /* 00 00 00 11 xx xx xx cc */
163 goto found_code; /* 00 00 00 01 xx xx xx cc */
166 if( i_code & ~0x0003 )
168 /* we have a boo boo ! */
169 intf_ErrMsg( "video_spu: unknown code 0x%x "
170 "(dest %x side %x, x=%d, y=%d)",
171 i_code, p_source, i_id, i_x, i_y );
176 /* if the 14 first bits are 0, then it's a new line */
177 if( pi_index[i_id] & 0x1 )