1 /*****************************************************************************
2 * Common SVCD and VCD subtitle routines.
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: common.c,v 1.1 2003/12/28 04:51: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 );
164 /* Scales down (reduces size) of p_dest in the x direction as
165 determined through aspect ratio x_scale by y_scale. Scaling
166 is done in place. p_spu->i_width, is updated to new width
168 The aspect ratio is assumed to be between 1/2 and 1.
171 VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
172 unsigned int i_scale_x, unsigned int i_scale_y )
176 decoder_sys_t *p_sys = p_dec->p_sys;
177 uint8_t *p_src1 = p_spu->p_sys->p_data;
178 uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
179 uint8_t *p_dst = p_src1;
180 unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
181 unsigned int used=0; /* Number of bytes used up in p_src1. */
183 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) ,
184 "Old width: %d, new width: %d",
185 p_spu->i_width, i_new_width);
187 for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
190 /* Discard the remaining piece of the column of the previous line*/
193 p_src2 += PIXEL_SIZE;
196 for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
198 unsigned int w1= i_scale_x - used;
199 unsigned int w2= i_scale_y - w1;
202 for (i = 0; i < PIXEL_SIZE; i++ ) {
203 *p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
204 p_src1++; p_src2++; p_dst++;
207 if (i_scale_x == used) {
208 /* End of last pixel was end of p_src2. */
210 p_src2 += PIXEL_SIZE;
216 p_spu->i_width = i_new_width;
218 if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
220 ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
221 for ( i_row=0; i_row < p_spu->i_height - 1; i_row++ ) {
222 for ( i_col=0; i_col < p_spu->i_width - 1; i_col++ ) {
223 printf("%1x", p_source->s.t);
232 /*****************************************************************************
233 * DestroySPU: subpicture destructor
234 *****************************************************************************/
235 void VCDSubDestroySPU( subpicture_t *p_spu )
237 if( p_spu->p_sys->p_input )
239 /* Detach from our input thread */
240 vlc_object_release( p_spu->p_sys->p_input );
243 vlc_mutex_destroy( &p_spu->p_sys->lock );
244 free( p_spu->p_sys );
247 /*****************************************************************************
248 This callback is called from the input thread when we need cropping
249 *****************************************************************************/
250 int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
251 vlc_value_t oldval, vlc_value_t newval, void *p_data )
253 VCDSubUpdateSPU( (subpicture_t *)p_data, p_object );
259 /*****************************************************************************
260 update subpicture settings
261 *****************************************************************************
262 This function is called from CropCallback and at initialization time, to
263 retrieve crop information from the input.
264 *****************************************************************************/
265 void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
269 p_spu->p_sys->b_crop = val.b_bool;
270 if( !p_spu->p_sys->b_crop )
275 var_Get( p_object, "x-start", &val );
276 p_spu->p_sys->i_x_start = val.i_int;
277 var_Get( p_object, "y-start", &val );
278 p_spu->p_sys->i_y_start = val.i_int;
279 var_Get( p_object, "x-end", &val );
280 p_spu->p_sys->i_x_end = val.i_int;
281 var_Get( p_object, "y-end", &val );
282 p_spu->p_sys->i_y_end = val.i_int;