]> git.sesse.net Git - vlc/blob - src/input/ressource.c
d7b8e067bd1394913a127f8ad3e63e295358fad6
[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 static void HoldVouts( input_ressource_t *p_ressource, vout_thread_t ***ppp_vout, int *pi_vout )
193 {
194     vout_thread_t **pp_vout;
195
196     *pi_vout = 0;
197     *ppp_vout = NULL;
198     if( p_ressource->i_vout <= 0 )
199         return;
200
201     pp_vout = calloc( p_ressource->i_vout, sizeof(*pp_vout) );
202     if( !pp_vout )
203         return;
204
205     *ppp_vout = pp_vout;
206     *pi_vout = p_ressource->i_vout;
207
208     for( int i = 0; i < p_ressource->i_vout; i++ )
209     {
210         pp_vout[i] = p_ressource->pp_vout[i];
211         vlc_object_hold( pp_vout[i] );
212     }
213 }
214
215 /* */
216 static void DestroyAout( input_ressource_t *p_ressource )
217 {
218     if( p_ressource->p_aout )
219         vlc_object_release( p_ressource->p_aout );
220     p_ressource->p_aout = NULL;
221 }
222 static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
223 {
224     assert( p_ressource->p_input );
225
226     if( p_aout )
227     {
228         msg_Dbg( p_ressource->p_input, "releasing aout" );
229         vlc_object_release( p_aout );
230         return NULL;
231     }
232     else
233     {
234         if( !p_ressource->p_aout )
235         {
236             msg_Dbg( p_ressource->p_input, "creating aout" );
237             p_ressource->p_aout = aout_New( p_ressource->p_input );
238         }
239         else
240         {
241             msg_Dbg( p_ressource->p_input, "reusing aout" );
242         }
243
244         if( !p_ressource->p_aout )
245             return NULL;
246
247         vlc_object_detach( p_ressource->p_aout );
248         vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
249         vlc_object_hold( p_ressource->p_aout );
250         return p_ressource->p_aout;
251     }
252 }
253 static aout_instance_t *HoldAout( input_ressource_t *p_ressource )
254 {
255     if( !p_ressource->p_aout )
256         return NULL;
257
258     /* TODO FIXME: p_ressource->pp_vout order is NOT stable */
259     aout_instance_t *p_aout = p_ressource->p_aout;
260
261     vlc_object_hold( p_aout );
262
263     return p_aout;
264 }
265 /* */
266 input_ressource_t *input_ressource_New( void )
267 {
268     input_ressource_t *p_ressource = calloc( 1, sizeof(*p_ressource) );
269     if( !p_ressource )
270         return NULL;
271
272     vlc_mutex_init( &p_ressource->lock );
273     return p_ressource;
274 }
275
276 void input_ressource_Delete( input_ressource_t *p_ressource )
277 {
278     DestroySout( p_ressource );
279     DestroyVout( p_ressource );
280     DestroyAout( p_ressource );
281
282     vlc_mutex_destroy( &p_ressource->lock );
283     free( p_ressource );
284 }
285
286 void input_ressource_SetInput( input_ressource_t *p_ressource, input_thread_t *p_input )
287 {
288     vlc_mutex_lock( &p_ressource->lock );
289
290     if( p_ressource->p_input && !p_input )
291     {
292         if( p_ressource->p_aout )
293             vlc_object_detach( p_ressource->p_aout );
294
295         assert( p_ressource->i_vout == 0 );
296         if( p_ressource->p_vout_free )
297             vlc_object_detach( p_ressource->p_vout_free );
298
299         if( p_ressource->p_sout )
300             vlc_object_detach( p_ressource->p_sout );
301     }
302
303     /* */
304     p_ressource->p_input = p_input;
305
306     vlc_mutex_unlock( &p_ressource->lock );
307 }
308
309 vout_thread_t *input_ressource_RequestVout( input_ressource_t *p_ressource,
310                                             vout_thread_t *p_vout, video_format_t *p_fmt )
311 {
312     vlc_mutex_lock( &p_ressource->lock );
313     vout_thread_t *p_ret = RequestVout( p_ressource, p_vout, p_fmt );
314     vlc_mutex_unlock( &p_ressource->lock );
315
316     return p_ret;
317 }
318 vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
319 {
320     vlc_mutex_lock( &p_ressource->lock );
321     vout_thread_t *p_ret = HoldVout( p_ressource );
322     vlc_mutex_unlock( &p_ressource->lock );
323
324     return p_ret;
325 }
326 void input_ressource_HoldVouts( input_ressource_t *p_ressource, vout_thread_t ***ppp_vout, int *pi_vout )
327 {
328     vlc_mutex_lock( &p_ressource->lock );
329     HoldVouts( p_ressource, ppp_vout, pi_vout );
330     vlc_mutex_unlock( &p_ressource->lock );
331 }
332 void input_ressource_TerminateVout( input_ressource_t *p_ressource )
333 {
334     input_ressource_RequestVout( p_ressource, NULL, NULL );
335 }
336
337 /* */
338 aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
339 {
340     vlc_mutex_lock( &p_ressource->lock );
341     aout_instance_t *p_ret = RequestAout( p_ressource, p_aout );
342     vlc_mutex_unlock( &p_ressource->lock );
343
344     return p_ret;
345 }
346 aout_instance_t *input_ressource_HoldAout( input_ressource_t *p_ressource )
347 {
348     vlc_mutex_lock( &p_ressource->lock );
349     aout_instance_t *p_ret = HoldAout( p_ressource );
350     vlc_mutex_unlock( &p_ressource->lock );
351
352     return p_ret;
353 }
354 /* */
355 sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, sout_instance_t *p_sout, const char *psz_sout )
356 {
357     vlc_mutex_lock( &p_ressource->lock );
358     sout_instance_t *p_ret = RequestSout( p_ressource, p_sout, psz_sout );
359     vlc_mutex_unlock( &p_ressource->lock );
360
361     return p_ret;
362 }
363 void input_ressource_TerminateSout( input_ressource_t *p_ressource )
364 {
365     input_ressource_RequestSout( p_ressource, NULL, NULL );
366 }
367