* modules/codec/spudec/*: modified the spu decoder to handle text subtitles.
[vlc.git] / modules / codec / spudec / spudec.c
1 /*****************************************************************************
2  * spudec.c : SPU decoder thread
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: spudec.c,v 1.8 2002/11/06 21:48:24 gbazin Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>                                    /* memcpy(), memset() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/vout.h>
32 #include <vlc/decoder.h>
33
34 #include "spudec.h"
35
36 /*****************************************************************************
37  * Local prototypes
38  *****************************************************************************/
39 static int  OpenDecoder   ( vlc_object_t * );      
40 static int  RunDecoder    ( decoder_fifo_t * );
41 static int  InitThread    ( spudec_thread_t * );
42 static void EndThread     ( spudec_thread_t * );
43
44 /*****************************************************************************
45  * Module descriptor.
46  *****************************************************************************/
47 #define FONT_TEXT N_("Font used by the text subtitler")
48 #define FONT_LONGTEXT N_(\
49     "When the subtitles are coded in text form then, you can choose " \
50     "which font will be used to display them.")
51
52 vlc_module_begin();
53     add_category_hint( N_("subtitles"), NULL );
54     add_file( "spudec-font", "./share/font-eutopiabold36.rle", NULL,
55               FONT_TEXT, FONT_LONGTEXT );
56     set_description( _("subtitles decoder module") );
57     set_capability( "decoder", 50 );
58     set_callbacks( OpenDecoder, NULL );
59 vlc_module_end();
60
61 /*****************************************************************************
62  * OpenDecoder: probe the decoder and return score
63  *****************************************************************************
64  * Tries to launch a decoder and return score so that the interface is able 
65  * to chose.
66  *****************************************************************************/
67 static int OpenDecoder( vlc_object_t *p_this )
68 {
69     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
70
71     if( p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ')
72          && p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b')
73          && p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') )
74     {
75         return VLC_EGENERIC;
76     }
77
78     p_fifo->pf_run = RunDecoder;
79
80     return VLC_SUCCESS;
81 }
82
83 /*****************************************************************************
84  * RunDecoder: this function is called just after the thread is created
85  *****************************************************************************/
86 static int RunDecoder( decoder_fifo_t * p_fifo )
87 {
88     spudec_thread_t *     p_spudec;
89     subtitler_font_t *    p_font;
90     char *                psz_font;
91
92     /* Allocate the memory needed to store the thread's structure */
93     p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
94
95     if ( p_spudec == NULL )
96     {
97         msg_Err( p_fifo, "out of memory" );
98         DecoderError( p_fifo );
99         return( -1 );
100     }
101     
102     /*
103      * Initialize the thread properties
104      */
105     p_spudec->p_vout = NULL;
106     p_spudec->p_fifo = p_fifo;
107
108     /*
109      * Initialize thread and free configuration
110      */
111     p_spudec->p_fifo->b_error = InitThread( p_spudec );
112
113     /*
114      * Main loop - it is not executed if an error occured during
115      * initialization
116      */
117     if( p_fifo->i_fourcc == VLC_FOURCC('s','u','b','t') )
118     {
119         /* Here we are dealing with text subtitles */
120
121         if( (psz_font = config_GetPsz( p_fifo, "spudec-font" )) == NULL )
122         {
123             msg_Err( p_fifo, "no default font selected" );
124             p_font = NULL;
125             p_spudec->p_fifo->b_error;
126         }
127         else
128         {
129             p_font = subtitler_LoadFont( p_spudec->p_vout, psz_font );
130             if ( p_font == NULL )
131             {
132                 msg_Err( p_fifo, "unable to load font: %s", psz_font );
133                 p_spudec->p_fifo->b_error;
134             }
135         }
136         if( psz_font ) free( psz_font );
137
138         while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
139         {
140             E_(ParseText)( p_spudec, p_font );
141         }
142
143         if( p_font ) subtitler_UnloadFont( p_spudec->p_vout, p_font );
144
145     }
146     else
147     {
148         /* Here we are dealing with sub-pictures subtitles*/
149
150         while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
151         {
152             if( E_(SyncPacket)( p_spudec ) )
153             {
154                 continue;
155             }
156
157             E_(ParsePacket)( p_spudec );
158         }
159     }
160
161     /*
162      * Error loop
163      */
164     if( p_spudec->p_fifo->b_error )
165     {
166         DecoderError( p_spudec->p_fifo );
167
168         /* End of thread */
169         EndThread( p_spudec );
170         return -1;
171     }
172
173     /* End of thread */
174     EndThread( p_spudec );
175     return 0;
176 }
177
178 /* following functions are local */
179
180 /*****************************************************************************
181  * InitThread: initialize spu decoder thread
182  *****************************************************************************
183  * This function is called from RunThread and performs the second step of the
184  * initialization. It returns 0 on success. Note that the thread's flag are not
185  * modified inside this function.
186  *****************************************************************************/
187 static int InitThread( spudec_thread_t *p_spudec )
188 {
189     /* Find an available video output */
190     do
191     {
192         if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error )
193         {
194             /* Call InitBitstream anyway so p_spudec->bit_stream is in a known
195              * state before calling CloseBitstream */
196             InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo,
197                            NULL, NULL );
198             return -1;
199         }
200
201         p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT,
202                                                               FIND_ANYWHERE );
203
204         if( p_spudec->p_vout )
205         {
206             break;
207         }
208
209         msleep( VOUT_OUTMEM_SLEEP );
210     }
211     while( 1 );
212
213     return InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo,
214                           NULL, NULL );
215 }
216
217 /*****************************************************************************
218  * EndThread: thread destruction
219  *****************************************************************************
220  * This function is called when the thread ends after a sucessful
221  * initialization.
222  *****************************************************************************/
223 static void EndThread( spudec_thread_t *p_spudec )
224 {
225     if( p_spudec->p_vout != NULL 
226          && p_spudec->p_vout->p_subpicture != NULL )
227     {
228         subpicture_t *  p_subpic;
229         int             i_subpic;
230     
231         for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
232         {
233             p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic];
234
235             if( p_subpic != NULL &&
236               ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
237              || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
238             {
239                 vout_DestroySubPicture( p_spudec->p_vout, p_subpic );
240             }
241         }
242
243         vlc_object_release( p_spudec->p_vout );
244     }
245     
246     CloseBitstream( &p_spudec->bit_stream );
247     free( p_spudec );
248 }