1 /*****************************************************************************
2 * Common SVCD and VCD subtitle routines.
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: common.c,v 1.2 2003/12/30 04:43:52 rocky Exp $
7 * Author: Rocky Bernstein
9 * Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10 * Samuel Hocevar <sam@zoy.org>
11 * Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
33 #include <vlc/decoder.h>
38 /*****************************************************************************
39 Free Resources associated with subtitle packet.
40 *****************************************************************************/
41 void VCDSubClose( vlc_object_t *p_this )
43 decoder_t *p_dec = (decoder_t*)p_this;
44 decoder_sys_t *p_sys = p_dec->p_sys;
46 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
48 if( !p_sys->b_packetizer )
50 /* FIXME check if it's ok to not lock vout */
51 if( p_sys->p_vout != NULL && p_sys->p_vout->p_subpicture != NULL )
53 subpicture_t * p_subpic;
56 for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
58 p_subpic = &p_sys->p_vout->p_subpicture[i_subpic];
60 if( p_subpic != NULL &&
61 ( ( p_subpic->i_status == RESERVED_SUBPICTURE ) ||
62 ( p_subpic->i_status == READY_SUBPICTURE ) ) )
64 vout_DestroySubPicture( p_sys->p_vout, p_subpic );
72 block_ChainRelease( p_sys->p_block );
78 /*****************************************************************************
80 Initialize so the next packet will start off a new one.
82 *****************************************************************************/
84 VCDSubInitSubtitleBlock( decoder_sys_t * p_sys )
86 p_sys->i_spu_size = 0;
87 p_sys->state = SUBTITLE_BLOCK_EMPTY;
89 p_sys->p_block = NULL;
90 p_sys->subtitle_data_pos = 0;
95 VCDSubInitSubtitleData(decoder_sys_t *p_sys)
97 if ( p_sys->subtitle_data ) {
98 if ( p_sys->subtitle_data_size < p_sys->i_spu_size ) {
99 p_sys->subtitle_data = realloc(p_sys->subtitle_data,
101 p_sys->subtitle_data_size = p_sys->i_spu_size;
104 p_sys->subtitle_data = malloc(p_sys->i_spu_size);
105 p_sys->subtitle_data_size = p_sys->i_spu_size;
106 /* FIXME: wrong place to get p_sys */
109 p_sys->subtitle_data_pos = 0;
113 VCDSubAppendData ( decoder_t *p_dec, uint8_t *buffer, uint32_t buf_len )
115 decoder_sys_t *p_sys = p_dec->p_sys;
116 int chunk_length = buf_len;
118 if ( chunk_length > p_sys->i_spu_size - p_sys->subtitle_data_pos ) {
119 msg_Warn( p_dec, "too much data (%d) expecting at most %u",
120 chunk_length, p_sys->i_spu_size - p_sys->subtitle_data_pos );
122 chunk_length = p_sys->i_spu_size - p_sys->subtitle_data_pos;
125 if ( chunk_length > 0 ) {
126 memcpy(p_sys->subtitle_data + p_sys->subtitle_data_pos,
127 buffer, chunk_length);
128 p_sys->subtitle_data_pos += chunk_length;
129 dbg_print(DECODE_DBG_PACKET, "%d bytes appended, pointer now %d",
130 chunk_length, p_sys->subtitle_data_pos);
135 /*****************************************************************************
136 * FindVout: Find a vout or wait for one to be created.
137 *****************************************************************************/
138 vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
140 vout_thread_t *p_vout = NULL;
142 /* Find an available video output */
145 if( p_dec->b_die || p_dec->b_error )
150 p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
156 msleep( VOUT_OUTMEM_SLEEP );
165 /* Remove color palette by expanding pixel entries to contain the
166 palette values. We work from the free space at the end to the
167 beginning so we can expand inline.
170 VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
171 unsigned int i_height, unsigned int i_width )
173 int n = (i_height * i_width) - 1;
174 uint8_t *p_from = p_dest;
175 ogt_yuvt_t *p_to = (ogt_yuvt_t *) p_dest;
177 for ( ; n >= 0 ; n-- ) {
178 p_to[n] = p_sys->pi_palette[p_from[n]];
183 /* Scales down (reduces size) of p_dest in the x direction as
184 determined through aspect ratio x_scale by y_scale. Scaling
185 is done in place. p_spu->i_width, is updated to new width
187 The aspect ratio is assumed to be between 1/2 and 1.
190 VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
191 unsigned int i_scale_x, unsigned int i_scale_y )
195 decoder_sys_t *p_sys = p_dec->p_sys;
196 uint8_t *p_src1 = p_spu->p_sys->p_data;
197 uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
198 uint8_t *p_dst = p_src1;
199 unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
200 unsigned int used=0; /* Number of bytes used up in p_src1. */
202 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) ,
203 "Old width: %d, new width: %d",
204 p_spu->i_width, i_new_width);
206 for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
209 /* Discard the remaining piece of the column of the previous line*/
212 p_src2 += PIXEL_SIZE;
215 for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
217 unsigned int w1= i_scale_x - used;
218 unsigned int w2= i_scale_y - w1;
221 for (i = 0; i < PIXEL_SIZE; i++ ) {
222 *p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
223 p_src1++; p_src2++; p_dst++;
226 if (i_scale_x == used) {
227 /* End of last pixel was end of p_src2. */
229 p_src2 += PIXEL_SIZE;
235 p_spu->i_width = i_new_width;
237 if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
239 ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
240 for ( i_row=0; i_row < p_spu->i_height - 1; i_row++ ) {
241 for ( i_col=0; i_col < p_spu->i_width - 1; i_col++ ) {
242 printf("%1x", p_source->s.t);
251 /*****************************************************************************
252 * DestroySPU: subpicture destructor
253 *****************************************************************************/
254 void VCDSubDestroySPU( subpicture_t *p_spu )
256 if( p_spu->p_sys->p_input )
258 /* Detach from our input thread */
259 vlc_object_release( p_spu->p_sys->p_input );
262 vlc_mutex_destroy( &p_spu->p_sys->lock );
263 free( p_spu->p_sys );
266 /*****************************************************************************
267 This callback is called from the input thread when we need cropping
268 *****************************************************************************/
269 int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
270 vlc_value_t oldval, vlc_value_t newval, void *p_data )
272 VCDSubUpdateSPU( (subpicture_t *)p_data, p_object );
278 /*****************************************************************************
279 update subpicture settings
280 *****************************************************************************
281 This function is called from CropCallback and at initialization time, to
282 retrieve crop information from the input.
283 *****************************************************************************/
284 void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
288 p_spu->p_sys->b_crop = val.b_bool;
289 if( !p_spu->p_sys->b_crop )
294 var_Get( p_object, "x-start", &val );
295 p_spu->p_sys->i_x_start = val.i_int;
296 var_Get( p_object, "y-start", &val );
297 p_spu->p_sys->i_y_start = val.i_int;
298 var_Get( p_object, "x-end", &val );
299 p_spu->p_sys->i_x_end = val.i_int;
300 var_Get( p_object, "y-end", &val );
301 p_spu->p_sys->i_y_end = val.i_int;