]> git.sesse.net Git - vlc/blob - src/input/ressource.c
0de570b229077748ae6552ce5baae29cf033fd70
[vlc] / src / input / ressource.c
1 /*****************************************************************************
2  * ressource.c
3  *****************************************************************************
4  * Copyright (C) 2008 Laurent Aimar
5  * $Id$
6  *
7  * Authors: Laurent Aimar < fenrir _AT_ videolan _DOT_ 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_vout.h>
33 #include <vlc_aout.h>
34 #include <vlc_sout.h>
35 #include "../libvlc.h"
36 #include "../stream_output/stream_output.h"
37 #include "../audio_output/aout_internal.h"
38 #include "input_interface.h"
39 #include "ressource.h"
40
41 struct input_ressource_t
42 {
43     vlc_mutex_t    lock;
44
45     input_thread_t *p_input;
46
47     sout_instance_t *p_sout;
48
49     int             i_vout;
50     vout_thread_t   **pp_vout;
51     vout_thread_t   *p_vout_free;
52
53     aout_instance_t *p_aout;
54 };
55
56 /* */
57 static void DestroySout( input_ressource_t *p_ressource )
58 {
59     if( p_ressource->p_sout )
60         sout_DeleteInstance( p_ressource->p_sout );
61     p_ressource->p_sout = NULL;
62 }
63 static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
64                                      sout_instance_t *p_sout, const char *psz_sout )
65 {
66     if( !p_sout && !psz_sout )
67     {
68         if( p_ressource->p_sout )
69             msg_Dbg( p_ressource->p_sout, "destroying useless sout" );
70         DestroySout( p_ressource );
71         return NULL;
72     }
73
74     assert( p_ressource->p_input );
75     assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
76
77     /* Check the validity of the sout */
78     if( p_ressource->p_sout &&
79         strcmp( p_ressource->p_sout->psz_sout, psz_sout ) )
80     {
81         msg_Dbg( p_ressource->p_input, "destroying unusable sout" );
82         DestroySout( p_ressource );
83     }
84
85     if( psz_sout )
86     {
87         if( p_ressource->p_sout )
88         {
89             /* Reuse it */
90             msg_Dbg( p_ressource->p_input, "reusing sout" );
91             msg_Dbg( p_ressource->p_input, "you probably want to use gather stream_out" );
92             vlc_object_attach( p_ressource->p_sout, p_ressource->p_input );
93         }
94         else
95         {
96             /* Create a new one */
97             p_ressource->p_sout = sout_NewInstance( p_ressource->p_input, psz_sout );
98         }
99
100         p_sout = p_ressource->p_sout;
101         p_ressource->p_sout = NULL;
102
103         return p_sout;
104     }
105     else
106     {
107         vlc_object_detach( p_sout );
108         p_ressource->p_sout = p_sout;
109
110         return NULL;
111     }
112 }
113
114 /* */
115 static void DestroyVout( input_ressource_t *p_ressource )
116 {
117     assert( p_ressource->i_vout == 0 );
118
119     if( p_ressource->p_vout_free )
120         vout_CloseAndRelease( p_ressource->p_vout_free );
121
122     p_ressource->p_vout_free = NULL;
123 }
124 static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
125                                    vout_thread_t *p_vout, video_format_t *p_fmt )
126 {
127     if( !p_vout && !p_fmt )
128     {
129         if( p_ressource->p_vout_free )
130         {
131             msg_Dbg( p_ressource->p_vout_free, "destroying useless vout" );
132             vout_CloseAndRelease( p_ressource->p_vout_free );
133             p_ressource->p_vout_free = NULL;
134         }
135         return NULL;
136     }
137
138     assert( p_ressource->p_input );
139     if( p_fmt )
140     {
141         /* */
142         if( !p_vout && p_ressource->p_vout_free )
143         {
144             msg_Dbg( p_ressource->p_input, "trying to reuse free vout" );
145             p_vout = p_ressource->p_vout_free;
146
147             p_ressource->p_vout_free = NULL;
148         }
149         else if( p_vout )
150         {
151             assert( p_vout != p_ressource->p_vout_free );
152             TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
153         }
154
155         /* */
156         p_vout = vout_Request( p_ressource->p_input, p_vout, p_fmt );
157         if( !p_vout )
158             return NULL;
159
160         TAB_APPEND( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
161         return p_vout;
162     }
163     else
164     {
165         assert( p_vout );
166         TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
167         if( p_ressource->p_vout_free )
168         {
169             msg_Dbg( p_ressource->p_input, "detroying vout (already one saved)" );
170             vout_CloseAndRelease( p_vout );
171         }
172         else
173         {
174             msg_Dbg( p_ressource->p_input, "saving a free vout" );
175             p_ressource->p_vout_free = p_vout;
176         }
177         return NULL;
178     }
179 }
180 static vout_thread_t *HoldVout( input_ressource_t *p_ressource )
181 {
182     if( p_ressource->i_vout <= 0 )
183         return NULL;
184
185     /* TODO FIXME: p_ressource->pp_vout order is NOT stable */
186     vout_thread_t *p_vout = p_ressource->pp_vout[0];
187
188     vlc_object_hold( p_vout );
189
190     return p_vout;
191 }
192
193 /* */
194 static void DestroyAout( input_ressource_t *p_ressource )
195 {
196     if( p_ressource->p_aout )
197         vlc_object_release( p_ressource->p_aout );
198     p_ressource->p_aout = NULL;
199 }
200 static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
201 {
202     assert( p_ressource->p_input );
203
204     if( p_aout )
205     {
206         msg_Dbg( p_ressource->p_input, "releasing aout" );
207         vlc_object_release( p_aout );
208         return NULL;
209     }
210     else
211     {
212         if( !p_ressource->p_aout )
213         {
214             msg_Dbg( p_ressource->p_input, "creating aout" );
215             p_ressource->p_aout = aout_New( p_ressource->p_input );
216         }
217         else
218         {
219             msg_Dbg( p_ressource->p_input, "reusing aout" );
220         }
221
222         if( !p_ressource->p_aout )
223             return NULL;
224
225         vlc_object_detach( p_ressource->p_aout );
226         vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
227         vlc_object_hold( p_ressource->p_aout );
228         return p_ressource->p_aout;
229     }
230 }
231
232 /* */
233 input_ressource_t *input_ressource_New( void )
234 {
235     input_ressource_t *p_ressource = calloc( 1, sizeof(*p_ressource) );
236     if( !p_ressource )
237         return NULL;
238
239     vlc_mutex_init( &p_ressource->lock );
240     return p_ressource;
241 }
242
243 void input_ressource_Delete( input_ressource_t *p_ressource )
244 {
245     DestroySout( p_ressource );
246     DestroyVout( p_ressource );
247     DestroyAout( p_ressource );
248
249     vlc_mutex_destroy( &p_ressource->lock );
250     free( p_ressource );
251 }
252
253 void input_ressource_SetInput( input_ressource_t *p_ressource, input_thread_t *p_input )
254 {
255     vlc_mutex_lock( &p_ressource->lock );
256
257     if( p_ressource->p_input && !p_input )
258     {
259         if( p_ressource->p_aout )
260             vlc_object_detach( p_ressource->p_aout );
261
262         assert( p_ressource->i_vout == 0 );
263         if( p_ressource->p_vout_free )
264             vlc_object_detach( p_ressource->p_vout_free );
265
266         if( p_ressource->p_sout )
267             vlc_object_detach( p_ressource->p_sout );
268     }
269
270     /* */
271     p_ressource->p_input = p_input;
272
273     vlc_mutex_unlock( &p_ressource->lock );
274 }
275
276 vout_thread_t *input_ressource_RequestVout( input_ressource_t *p_ressource,
277                                             vout_thread_t *p_vout, video_format_t *p_fmt )
278 {
279     vlc_mutex_lock( &p_ressource->lock );
280     vout_thread_t *p_ret = RequestVout( p_ressource, p_vout, p_fmt );
281     vlc_mutex_unlock( &p_ressource->lock );
282
283     return p_ret;
284 }
285 vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
286 {
287     vlc_mutex_lock( &p_ressource->lock );
288     vout_thread_t *p_ret = HoldVout( p_ressource );
289     vlc_mutex_unlock( &p_ressource->lock );
290
291     return p_ret;
292 }
293 void input_ressource_TerminateVout( input_ressource_t *p_ressource )
294 {
295     input_ressource_RequestVout( p_ressource, NULL, NULL );
296 }
297
298 /* */
299 aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
300 {
301     vlc_mutex_lock( &p_ressource->lock );
302     aout_instance_t *p_ret = RequestAout( p_ressource, p_aout );
303     vlc_mutex_unlock( &p_ressource->lock );
304
305     return p_ret;
306 }
307
308 /* */
309 sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, sout_instance_t *p_sout, const char *psz_sout )
310 {
311     vlc_mutex_lock( &p_ressource->lock );
312     sout_instance_t *p_ret = RequestSout( p_ressource, p_sout, psz_sout );
313     vlc_mutex_unlock( &p_ressource->lock );
314
315     return p_ret;
316 }
317 void input_ressource_TerminateSout( input_ressource_t *p_ressource )
318 {
319     input_ressource_RequestSout( p_ressource, NULL, NULL );
320 }
321