]> git.sesse.net Git - vlc/blob - modules/codec/spudec/spudec.c
* ALL: Introduction of a new api for decoders.
[vlc] / 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.25 2003/09/02 20:19:26 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 static vout_thread_t *FindVout( spudec_thread_t *);
44
45 /*****************************************************************************
46  * Module descriptor.
47  *****************************************************************************/
48 vlc_module_begin();
49     set_description( _("DVD subtitles decoder") );
50     set_capability( "decoder", 50 );
51     set_callbacks( OpenDecoder, NULL );
52 vlc_module_end();
53
54 /*****************************************************************************
55  * OpenDecoder: probe the decoder and return score
56  *****************************************************************************
57  * Tries to launch a decoder and return score so that the interface is able 
58  * to chose.
59  *****************************************************************************/
60 static int OpenDecoder( vlc_object_t *p_this )
61 {
62     decoder_t *p_dec = (decoder_t*)p_this;
63
64     if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u',' ')
65          && p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') )
66     {   
67         return VLC_EGENERIC;
68     }
69     
70     p_dec->pf_run = RunDecoder;
71
72     return VLC_SUCCESS;
73 }
74
75 /*****************************************************************************
76  * RunDecoder: this function is called just after the thread is created
77  *****************************************************************************/
78 static int RunDecoder( decoder_fifo_t * p_fifo )
79 {
80     spudec_thread_t *     p_spudec;
81
82     /* Allocate the memory needed to store the thread's structure */
83     p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
84
85     if ( p_spudec == NULL )
86     {
87         msg_Err( p_fifo, "out of memory" );
88         DecoderError( p_fifo );
89         return( -1 );
90     }
91     
92     /*
93      * Initialize the thread properties
94      */
95     p_spudec->p_vout = NULL;
96     p_spudec->p_fifo = p_fifo;
97         
98     /*
99      * Initialize thread and free configuration
100      */
101     p_spudec->p_fifo->b_error = InitThread( p_spudec );
102
103     /*
104      * Main loop - it is not executed if an error occured during
105      * initialization
106      */
107     while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
108     {
109         if( E_(SyncPacket)( p_spudec ) )
110         {
111             continue;
112         }
113
114         /* Find/Wait for a video output */
115         p_spudec->p_vout = FindVout( p_spudec );
116         if( p_spudec->p_vout)
117         {
118             E_(ParsePacket)( p_spudec );
119             vlc_object_release( p_spudec->p_vout );
120         }
121     }
122
123     /*
124      * Error loop
125      */
126     if( p_spudec->p_fifo->b_error )
127     {
128         DecoderError( p_spudec->p_fifo );
129
130         /* End of thread */
131         EndThread( p_spudec );
132         return -1;
133     }
134
135     /* End of thread */
136     EndThread( p_spudec );
137     return 0;
138 }
139
140 /* following functions are local */
141
142 /*****************************************************************************
143  * InitThread: initialize spu decoder thread
144  *****************************************************************************
145  * This function is called from RunThread and performs the second step of the
146  * initialization. It returns 0 on success. Note that the thread's flag are not
147  * modified inside this function.
148  *****************************************************************************/
149 static int InitThread( spudec_thread_t *p_spudec )
150 {
151     int i_ret;
152     
153     /* Call InitBitstream anyway so p_spudec->bit_stream is in a known
154      * state before calling CloseBitstream */
155     i_ret = InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo,
156                             NULL, NULL );
157
158     /* Check for a video output */
159     p_spudec->p_vout = FindVout( p_spudec );
160     
161     if( !p_spudec->p_vout )
162     {
163         return -1;
164     }
165     
166     /* It was just a check */
167     vlc_object_release( p_spudec->p_vout );
168     p_spudec->p_vout = NULL;
169     
170     return i_ret;
171 }
172
173 /*****************************************************************************
174  * FindVout: Find a vout or wait for one to be created.
175  *****************************************************************************/
176 static vout_thread_t *FindVout( spudec_thread_t *p_spudec )
177 {
178     vout_thread_t *p_vout = NULL;
179     
180     /* Find an available video output */
181     do
182     {
183         if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error )
184         {
185             break;
186         }
187
188         p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT,
189                                                               FIND_ANYWHERE );
190
191         if( p_vout )
192         {
193             break;
194         }
195
196         msleep( VOUT_OUTMEM_SLEEP );
197     }
198     while( 1 );
199
200     return p_vout;
201 }
202
203 /*****************************************************************************
204  * EndThread: thread destruction
205  *****************************************************************************
206  * This function is called when the thread ends after a sucessful
207  * initialization.
208  *****************************************************************************/
209 static void EndThread( spudec_thread_t *p_spudec )
210 {
211     if( p_spudec->p_vout != NULL 
212          && p_spudec->p_vout->p_subpicture != NULL )
213     {
214         subpicture_t *  p_subpic;
215         int             i_subpic;
216     
217         for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
218         {
219             p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic];
220
221             if( p_subpic != NULL &&
222               ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
223              || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
224             {
225                 vout_DestroySubPicture( p_spudec->p_vout, p_subpic );
226             }
227         }
228     }
229     
230     CloseBitstream( &p_spudec->bit_stream );
231     free( p_spudec );
232 }