81574f2f418c0eced8ca58544f08a2737189b90d
[vlc.git] / modules / codec / ogt / common.c
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 $
6  *
7  * Author: Rocky Bernstein
8  *   based on code from:
9  *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10  *       Samuel Hocevar <sam@zoy.org>
11  *       Laurent Aimar <fenrir@via.ecp.fr>
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33 #include <vlc/decoder.h>
34
35 #include "subtitle.h"
36 #include "common.h"
37
38 /*****************************************************************************
39  Free Resources associated with subtitle packet.
40  *****************************************************************************/
41 void VCDSubClose( vlc_object_t *p_this )
42 {
43     decoder_t     *p_dec = (decoder_t*)p_this;
44     decoder_sys_t *p_sys = p_dec->p_sys;
45
46     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
47
48     if( !p_sys->b_packetizer )
49     {
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 )
52         {
53             subpicture_t *  p_subpic;
54             int             i_subpic;
55
56             for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
57             {
58                 p_subpic = &p_sys->p_vout->p_subpicture[i_subpic];
59
60                 if( p_subpic != NULL &&
61                     ( ( p_subpic->i_status == RESERVED_SUBPICTURE ) ||
62                       ( p_subpic->i_status == READY_SUBPICTURE ) ) )
63                 {
64                     vout_DestroySubPicture( p_sys->p_vout, p_subpic );
65                 }
66             }
67         }
68     }
69
70     if( p_sys->p_block )
71     {
72         block_ChainRelease( p_sys->p_block );
73     }
74
75     free( p_sys );
76 }
77
78 /*****************************************************************************
79
80 Initialize so the next packet will start off a new one.
81
82  *****************************************************************************/
83 void 
84 VCDSubInitSubtitleBlock( decoder_sys_t * p_sys ) 
85 {
86   p_sys->i_spu_size = 0;
87   p_sys->state      = SUBTITLE_BLOCK_EMPTY;
88   p_sys->i_spu      = 0;
89   p_sys->p_block    = NULL;
90   p_sys->subtitle_data_pos = 0;
91
92 }
93
94 void 
95 VCDSubInitSubtitleData(decoder_sys_t *p_sys)
96 {
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,
100                                     p_sys->i_spu_size);
101       p_sys->subtitle_data_size = p_sys->i_spu_size;
102     }
103   } else {
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 */
107     p_sys->i_image = 0;
108   }
109   p_sys->subtitle_data_pos = 0;
110 }
111
112 void 
113 VCDSubAppendData ( decoder_t *p_dec, uint8_t *buffer, uint32_t buf_len )
114 {
115   decoder_sys_t *p_sys = p_dec->p_sys;
116   int chunk_length = buf_len;
117
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 );
121
122     chunk_length = p_sys->i_spu_size - p_sys->subtitle_data_pos;
123   }
124
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);
131   }
132 }
133
134
135 /*****************************************************************************
136  * FindVout: Find a vout or wait for one to be created.
137  *****************************************************************************/
138 vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
139 {
140     vout_thread_t *p_vout = NULL;
141
142     /* Find an available video output */
143     do
144     {
145         if( p_dec->b_die || p_dec->b_error )
146         {
147             break;
148         }
149
150         p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
151         if( p_vout )
152         {
153             break;
154         }
155
156         msleep( VOUT_OUTMEM_SLEEP );
157     }
158     while( 1 );
159
160     return p_vout;
161 }
162
163
164
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.
168     */
169 void
170 VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
171                    unsigned int i_height, unsigned int i_width ) 
172 {
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;
176   
177   for ( ; n >= 0 ; n-- ) {
178     p_to[n] = p_sys->pi_palette[p_from[n]];
179   }
180 }
181
182
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
186
187    The aspect ratio is assumed to be between 1/2 and 1.
188 */
189 void
190 VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu, 
191               unsigned int i_scale_x, unsigned int i_scale_y )
192 {
193   int i_row, i_col;
194
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. */
201
202   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) , 
203              "Old width: %d, new width: %d", 
204              p_spu->i_width, i_new_width);
205   
206   for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
207
208     if (used != 0) {
209       /* Discard the remaining piece of the column of the previous line*/
210       used=0;
211       p_src1 = p_src2;
212       p_src2 += PIXEL_SIZE;
213     }
214     
215     for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
216       unsigned int i;
217       unsigned int w1= i_scale_x - used;
218       unsigned int w2= i_scale_y - w1;
219
220       used = w2;
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++;
224       }
225
226       if (i_scale_x == used) {
227         /* End of last pixel was end of p_src2. */
228         p_src1 = p_src2;
229         p_src2 += PIXEL_SIZE;
230         i_col++;
231         used = 0;
232       }
233     }
234   }
235   p_spu->i_width = i_new_width;
236
237   if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
238   { 
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);
243         p_source++;
244       }
245       printf("\n");
246     }
247   }
248
249 }
250
251 /*****************************************************************************
252  * DestroySPU: subpicture destructor
253  *****************************************************************************/
254 void VCDSubDestroySPU( subpicture_t *p_spu )
255 {
256     if( p_spu->p_sys->p_input )
257     {
258         /* Detach from our input thread */
259         vlc_object_release( p_spu->p_sys->p_input );
260     }
261
262     vlc_mutex_destroy( &p_spu->p_sys->lock );
263     free( p_spu->p_sys );
264 }
265
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 )
271 {
272     VCDSubUpdateSPU( (subpicture_t *)p_data, p_object );
273
274     return VLC_SUCCESS;
275 }
276
277
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 )
285 {
286     vlc_value_t val;
287
288     p_spu->p_sys->b_crop = val.b_bool;
289     if( !p_spu->p_sys->b_crop )
290     {
291         return;
292     }
293
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;
302
303 }
304