03383909a551e80bf6fc86fa6a71768a856aa377
[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.7 2002/11/06 18:07:57 sam 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 #ifdef HAVE_UNISTD_H
35 #   include <unistd.h>                                           /* getpid() */
36 #endif
37
38 #ifdef WIN32                   /* getpid() for win32 is located in process.h */
39 #   include <process.h>
40 #endif
41
42 #include "spudec.h"
43
44 /*****************************************************************************
45  * Local prototypes
46  *****************************************************************************/
47 static int  OpenDecoder   ( vlc_object_t * );      
48 static int  RunDecoder    ( decoder_fifo_t * );
49 static int  InitThread    ( spudec_thread_t * );
50 static void EndThread     ( spudec_thread_t * );
51
52 /*****************************************************************************
53  * Module descriptor.
54  *****************************************************************************/
55 vlc_module_begin();
56     set_description( _("DVD 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     {   
74         return VLC_EGENERIC;
75     }
76     
77     p_fifo->pf_run = RunDecoder;
78
79     return VLC_SUCCESS;
80 }
81
82 /*****************************************************************************
83  * RunDecoder: this function is called just after the thread is created
84  *****************************************************************************/
85 static int RunDecoder( decoder_fifo_t * p_fifo )
86 {
87     spudec_thread_t *     p_spudec;
88
89     /* Allocate the memory needed to store the thread's structure */
90     p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
91
92     if ( p_spudec == NULL )
93     {
94         msg_Err( p_fifo, "out of memory" );
95         DecoderError( p_fifo );
96         return( -1 );
97     }
98     
99     /*
100      * Initialize the thread properties
101      */
102     p_spudec->p_vout = NULL;
103     p_spudec->p_fifo = p_fifo;
104         
105     /*
106      * Initialize thread and free configuration
107      */
108     p_spudec->p_fifo->b_error = InitThread( p_spudec );
109
110     /*
111      * Main loop - it is not executed if an error occured during
112      * initialization
113      */
114     while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
115     {
116         if( E_(SyncPacket)( p_spudec ) )
117         {
118             continue;
119         }
120
121         E_(ParsePacket)( p_spudec );
122     }
123
124     /*
125      * Error loop
126      */
127     if( p_spudec->p_fifo->b_error )
128     {
129         DecoderError( p_spudec->p_fifo );
130
131         /* End of thread */
132         EndThread( p_spudec );
133         return -1;
134     }
135
136     /* End of thread */
137     EndThread( p_spudec );
138     return 0;
139 }
140
141 /* following functions are local */
142
143 /*****************************************************************************
144  * InitThread: initialize spu decoder thread
145  *****************************************************************************
146  * This function is called from RunThread and performs the second step of the
147  * initialization. It returns 0 on success. Note that the thread's flag are not
148  * modified inside this function.
149  *****************************************************************************/
150 static int InitThread( spudec_thread_t *p_spudec )
151 {
152     /* Find an available video output */
153     do
154     {
155         if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error )
156         {
157             /* Call InitBitstream anyway so p_spudec is in a known state
158              * before calling CloseBitstream */
159             InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo,
160                            NULL, NULL );
161             return -1;
162         }
163
164         p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT,
165                                                               FIND_ANYWHERE );
166
167         if( p_spudec->p_vout )
168         {
169             break;
170         }
171
172         msleep( VOUT_OUTMEM_SLEEP );
173     }
174     while( 1 );
175
176     return InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo,
177                           NULL, NULL );
178 }
179
180 /*****************************************************************************
181  * EndThread: thread destruction
182  *****************************************************************************
183  * This function is called when the thread ends after a sucessful
184  * initialization.
185  *****************************************************************************/
186 static void EndThread( spudec_thread_t *p_spudec )
187 {
188     if( p_spudec->p_vout != NULL 
189          && p_spudec->p_vout->p_subpicture != NULL )
190     {
191         subpicture_t *  p_subpic;
192         int             i_subpic;
193     
194         for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
195         {
196             p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic];
197
198             if( p_subpic != NULL &&
199               ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
200              || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
201             {
202                 vout_DestroySubPicture( p_spudec->p_vout, p_subpic );
203             }
204         }
205
206         vlc_object_release( p_spudec->p_vout );
207     }
208     
209     CloseBitstream( &p_spudec->bit_stream );
210     free( p_spudec );
211 }
212