* ./modules/codec/spudec/*: split spudec into the parsing and the rendering
[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.2 2002/08/16 03:07:56 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     {   
73         p_fifo->pf_run = RunDecoder;
74         return VLC_SUCCESS;
75     }
76     
77     return VLC_EGENERIC;
78 }
79
80 /*****************************************************************************
81  * RunDecoder: this function is called just after the thread is created
82  *****************************************************************************/
83 static int RunDecoder( decoder_fifo_t * p_fifo )
84 {
85     spudec_thread_t *     p_spudec;
86    
87     /* Allocate the memory needed to store the thread's structure */
88     p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
89
90     if ( p_spudec == NULL )
91     {
92         msg_Err( p_fifo, "out of memory" );
93         DecoderError( p_fifo );
94         return( -1 );
95     }
96     
97     /*
98      * Initialize the thread properties
99      */
100     p_spudec->p_vout = NULL;
101     p_spudec->p_fifo = p_fifo;
102         
103     /*
104      * Initialize thread and free configuration
105      */
106     p_spudec->p_fifo->b_error = InitThread( p_spudec );
107
108     /*
109      * Main loop - it is not executed if an error occured during
110      * initialization
111      */
112     while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
113     {
114         if( !E_(SyncPacket)( p_spudec ) )
115         {
116             E_(ParsePacket)( p_spudec );
117         }
118     }
119
120     /*
121      * Error loop
122      */
123     if( p_spudec->p_fifo->b_error )
124     {
125         DecoderError( p_spudec->p_fifo );
126
127         /* End of thread */
128         EndThread( p_spudec );
129         return -1;
130     }
131
132     /* End of thread */
133     EndThread( p_spudec );
134     return 0;
135 }
136
137 /* following functions are local */
138
139 /*****************************************************************************
140  * InitThread: initialize spu decoder thread
141  *****************************************************************************
142  * This function is called from RunThread and performs the second step of the
143  * initialization. It returns 0 on success. Note that the thread's flag are not
144  * modified inside this function.
145  *****************************************************************************/
146 static int InitThread( spudec_thread_t *p_spudec )
147 {
148     /* Find an available video output */
149     do
150     {
151         if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error )
152         {
153             return -1;
154         }
155
156         p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT,
157                                                               FIND_ANYWHERE );
158
159         if( p_spudec->p_vout )
160         {
161             break;
162         }
163
164         msleep( VOUT_OUTMEM_SLEEP );
165     }
166     while( 1 );
167
168     InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo, NULL, NULL );
169
170     /* Mark thread as running and return */
171     return 0;
172 }
173
174 /*****************************************************************************
175  * EndThread: thread destruction
176  *****************************************************************************
177  * This function is called when the thread ends after a sucessful
178  * initialization.
179  *****************************************************************************/
180 static void EndThread( spudec_thread_t *p_spudec )
181 {
182     if( p_spudec->p_vout != NULL 
183      && p_spudec->p_vout->p_subpicture != NULL )
184     {
185         subpicture_t *  p_subpic;
186         int             i_subpic;
187     
188         for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
189         {
190             p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic];
191
192             if( p_subpic != NULL &&
193               ( ( p_subpic->i_status == RESERVED_SUBPICTURE )
194              || ( p_subpic->i_status == READY_SUBPICTURE ) ) )
195             {
196                 vout_DestroySubPicture( p_spudec->p_vout, p_subpic );
197             }
198         }
199
200         vlc_object_release( p_spudec->p_vout );
201     }
202     
203     free( p_spudec );
204 }
205