]> git.sesse.net Git - vlc/blob - src/input/decoder.c
* English grammar fixes and beautifications for the intf_UserFatal messages
[vlc] / src / input / decoder.c
1 /*****************************************************************************
2  * decoder.c: Functions for the management of decoders
3  *****************************************************************************
4  * Copyright (C) 1999-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *          Laurent Aimar <fenrir@via.ecp.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <vlc/vlc.h>
30
31 #include <vlc_block.h>
32 #include <vlc_vout.h>
33 #include <vlc_aout.h>
34 #include <vlc_sout.h>
35 #include <vlc_codec.h>
36 #include <vlc_osd.h>
37
38 #include <vlc_interface.h>
39 #include "audio_output/aout_internal.h"
40 #include "stream_output/stream_output.h"
41 #include "input_internal.h"
42
43 static decoder_t * CreateDecoder( input_thread_t *, es_format_t *, int );
44 static void        DeleteDecoder( decoder_t * );
45
46 static int         DecoderThread( decoder_t * );
47 static int         DecoderDecode( decoder_t * p_dec, block_t *p_block );
48
49 /* Buffers allocation callbacks for the decoders */
50 static aout_buffer_t *aout_new_buffer( decoder_t *, int );
51 static void aout_del_buffer( decoder_t *, aout_buffer_t * );
52
53 static picture_t *vout_new_buffer( decoder_t * );
54 static void vout_del_buffer( decoder_t *, picture_t * );
55 static void vout_link_picture( decoder_t *, picture_t * );
56 static void vout_unlink_picture( decoder_t *, picture_t * );
57
58 static subpicture_t *spu_new_buffer( decoder_t * );
59 static void spu_del_buffer( decoder_t *, subpicture_t * );
60
61 static es_format_t null_es_format;
62
63 struct decoder_owner_sys_t
64 {
65     vlc_bool_t      b_own_thread;
66
67     int64_t         i_preroll_end;
68
69     input_thread_t  *p_input;
70
71     aout_instance_t *p_aout;
72     aout_input_t    *p_aout_input;
73
74     vout_thread_t   *p_vout;
75
76     vout_thread_t   *p_spu_vout;
77     int              i_spu_channel;
78
79     sout_instance_t         *p_sout;
80     sout_packetizer_input_t *p_sout_input;
81
82     /* Some decoders require already packetized data (ie. not truncated) */
83     decoder_t *p_packetizer;
84
85     /* Current format in use by the output */
86     video_format_t video;
87     audio_format_t audio;
88     es_format_t    sout;
89
90     /* fifo */
91     block_fifo_t *p_fifo;
92
93     /* CC */
94     vlc_bool_t b_cc_supported;
95     vlc_mutex_t lock_cc;
96     vlc_bool_t pb_cc_present[4];
97     decoder_t *pp_cc[4];
98 };
99
100 /* */
101 static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
102 {
103     msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
104              "VLC probably does not support this sound or video format.",
105              (char*)&codec );
106     intf_UserFatal( p_dec, VLC_FALSE, _("No suitable decoder module"), 
107                     _("VLC does not support the audio or video format \"%4.4s\". "
108                       "Unfortunately there is no way for you to fix this."), (char*)&codec );
109 }
110
111 /* decoder_GetInputAttachment:
112  */
113 input_attachment_t *decoder_GetInputAttachment( decoder_t *p_dec,
114                                                 const char *psz_name )
115 {
116     input_attachment_t *p_attachment;
117     if( input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENT, &p_attachment, psz_name ) )
118         return NULL;
119     return p_attachment;
120 }
121 /* decoder_GetInputAttachments:
122  */
123 int decoder_GetInputAttachments( decoder_t *p_dec,
124                                  input_attachment_t ***ppp_attachment,
125                                  int *pi_attachment )
126 {
127     return input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENTS,
128                           ppp_attachment, pi_attachment );
129 }
130 /* decoder_GetDisplayDate:
131  */
132 mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
133 {
134     return i_ts;
135 }
136
137 /**
138  * Spawns a new decoder thread
139  *
140  * \param p_input the input thread
141  * \param p_es the es descriptor
142  * \return the spawned decoder object
143  */
144 decoder_t *input_DecoderNew( input_thread_t *p_input,
145                              es_format_t *fmt, vlc_bool_t b_force_decoder )
146 {
147     decoder_t   *p_dec = NULL;
148     vlc_value_t val;
149
150     /* If we are in sout mode, search for packetizer module */
151     if( p_input->p->p_sout && !b_force_decoder )
152     {
153         /* Create the decoder configuration structure */
154         p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_PACKETIZER );
155         if( p_dec == NULL )
156         {
157             msg_Err( p_input, "could not create packetizer" );
158             intf_UserFatal( p_input, VLC_FALSE, _("Streaming / Transcoding failed"),
159                             _("VLC could not open the packetizer module.") );
160             return NULL;
161         }
162     }
163     else
164     {
165         /* Create the decoder configuration structure */
166         p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_DECODER );
167         if( p_dec == NULL )
168         {
169             msg_Err( p_input, "could not create decoder" );
170             intf_UserFatal( p_input, VLC_FALSE, _("Streaming / Transcoding failed"),
171                             _("VLC could not open the decoder module.") );
172             return NULL;
173         }
174     }
175
176     if( !p_dec->p_module )
177     {
178         DecoderUnsupportedCodec( p_dec, fmt->i_codec );
179
180         DeleteDecoder( p_dec );
181         vlc_object_destroy( p_dec );
182         return NULL;
183     }
184
185     if( p_input->p->p_sout && p_input->p->input.b_can_pace_control &&
186         !b_force_decoder )
187     {
188         msg_Dbg( p_input, "stream out mode -> no decoder thread" );
189         p_dec->p_owner->b_own_thread = VLC_FALSE;
190     }
191     else
192     {
193         var_Get( p_input, "minimize-threads", &val );
194         p_dec->p_owner->b_own_thread = !val.b_bool;
195     }
196
197     if( p_dec->p_owner->b_own_thread )
198     {
199         int i_priority;
200         if( fmt->i_cat == AUDIO_ES )
201             i_priority = VLC_THREAD_PRIORITY_AUDIO;
202         else
203             i_priority = VLC_THREAD_PRIORITY_VIDEO;
204
205         /* Spawn the decoder thread */
206         if( vlc_thread_create( p_dec, "decoder", DecoderThread,
207                                i_priority, VLC_FALSE ) )
208         {
209             msg_Err( p_dec, "cannot spawn decoder thread" );
210             module_Unneed( p_dec, p_dec->p_module );
211             DeleteDecoder( p_dec );
212             vlc_object_destroy( p_dec );
213             return NULL;
214         }
215     }
216
217     return p_dec;
218 }
219
220 /**
221  * Kills a decoder thread and waits until it's finished
222  *
223  * \param p_input the input thread
224  * \param p_es the es descriptor
225  * \return nothing
226  */
227 void input_DecoderDelete( decoder_t *p_dec )
228 {
229     vlc_object_kill( p_dec );
230
231     if( p_dec->p_owner->b_own_thread )
232     {
233         /* Make sure the thread leaves the function by
234          * sending it an empty block. */
235         block_t *p_block = block_New( p_dec, 0 );
236         input_DecoderDecode( p_dec, p_block );
237
238         vlc_thread_join( p_dec );
239
240         /* Don't module_Unneed() here because of the dll loader that wants
241          * close() in the same thread than open()/decode() */
242     }
243     else
244     {
245         /* Flush */
246         input_DecoderDecode( p_dec, NULL );
247
248         module_Unneed( p_dec, p_dec->p_module );
249     }
250
251     /* */
252     if( p_dec->p_owner->b_cc_supported )
253     {
254         int i;
255         for( i = 0; i < 4; i++ )
256             input_DecoderSetCcState( p_dec, VLC_FALSE, i );
257     }
258
259     /* Delete decoder configuration */
260     DeleteDecoder( p_dec );
261
262     /* Delete the decoder */
263     vlc_object_destroy( p_dec );
264 }
265
266 /**
267  * Put a block_t in the decoder's fifo.
268  *
269  * \param p_dec the decoder object
270  * \param p_block the data block
271  */
272 void input_DecoderDecode( decoder_t * p_dec, block_t *p_block )
273 {
274     if( p_dec->p_owner->b_own_thread )
275     {
276         if( p_dec->p_owner->p_input->p->b_out_pace_control )
277         {
278             /* FIXME !!!!! */
279             while( !p_dec->b_die && !p_dec->b_error &&
280                    block_FifoCount( p_dec->p_owner->p_fifo ) > 10 )
281             {
282                 msleep( 1000 );
283             }
284         }
285         else if( block_FifoSize( p_dec->p_owner->p_fifo ) > 50000000 /* 50 MB */ )
286         {
287             /* FIXME: ideally we would check the time amount of data
288              * in the fifo instead of its size. */
289             msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
290                       "consumed quickly enough), resetting fifo!" );
291             block_FifoEmpty( p_dec->p_owner->p_fifo );
292         }
293
294         block_FifoPut( p_dec->p_owner->p_fifo, p_block );
295     }
296     else
297     {
298         if( p_dec->b_error || (p_block && p_block->i_buffer <= 0) )
299         {
300             if( p_block ) block_Release( p_block );
301         }
302         else
303         {
304             DecoderDecode( p_dec, p_block );
305         }
306     }
307 }
308
309 void input_DecoderDiscontinuity( decoder_t * p_dec, vlc_bool_t b_flush )
310 {
311     block_t *p_null;
312
313     /* Empty the fifo */
314     if( p_dec->p_owner->b_own_thread && b_flush )
315         block_FifoEmpty( p_dec->p_owner->p_fifo );
316
317     /* Send a special block */
318     p_null = block_New( p_dec, 128 );
319     p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
320     /* FIXME check for p_packetizer or b_packitized from es_format_t of input ? */
321     if( p_dec->p_owner->p_packetizer && b_flush )
322         p_null->i_flags |= BLOCK_FLAG_CORRUPTED;
323     memset( p_null->p_buffer, 0, p_null->i_buffer );
324
325     input_DecoderDecode( p_dec, p_null );
326 }
327
328 vlc_bool_t input_DecoderEmpty( decoder_t * p_dec )
329 {
330     if( p_dec->p_owner->b_own_thread
331      && block_FifoCount( p_dec->p_owner->p_fifo ) > 0 )
332     {
333         return VLC_FALSE;
334     }
335     return VLC_TRUE;
336 }
337
338 void input_DecoderIsCcPresent( decoder_t *p_dec, vlc_bool_t pb_present[4] )
339 {
340     int i;
341
342     vlc_mutex_lock( &p_dec->p_owner->lock_cc );
343     for( i = 0; i < 4; i++ )
344         pb_present[i] =  p_dec->p_owner->pb_cc_present[i];
345     vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
346 }
347 int input_DecoderSetCcState( decoder_t *p_dec, vlc_bool_t b_decode, int i_channel )
348 {
349     decoder_owner_sys_t *p_owner = p_dec->p_owner;
350
351     //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel );
352
353     if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
354         return VLC_EGENERIC;
355
356     if( b_decode )
357     {
358         static const vlc_fourcc_t fcc[4] = {
359             VLC_FOURCC('c', 'c', '1', ' '),
360             VLC_FOURCC('c', 'c', '2', ' '),
361             VLC_FOURCC('c', 'c', '3', ' '),
362             VLC_FOURCC('c', 'c', '4', ' '),
363         };
364         decoder_t *p_cc;
365         es_format_t fmt;
366
367         es_format_Init( &fmt, SPU_ES, fcc[i_channel] );
368         p_cc = CreateDecoder( p_owner->p_input, &fmt, VLC_OBJECT_DECODER );
369         if( !p_cc )
370         {
371             msg_Err( p_dec, "could not create decoder" );
372             intf_UserFatal( p_dec, VLC_FALSE, _("Streaming / Transcoding failed"),
373                             _("VLC could not open the decoder module.") );
374             return VLC_EGENERIC;
375         }
376         else if( !p_cc->p_module )
377         {
378             DecoderUnsupportedCodec( p_dec, fcc[i_channel] );
379             DeleteDecoder( p_cc );
380             vlc_object_destroy( p_cc );
381             return VLC_EGENERIC;
382         }
383
384         vlc_mutex_lock( &p_owner->lock_cc );
385         p_dec->p_owner->pp_cc[i_channel] = p_cc;
386         vlc_mutex_unlock( &p_owner->lock_cc );
387     }
388     else
389     {
390         decoder_t *p_cc;
391
392         vlc_mutex_lock( &p_owner->lock_cc );
393         p_cc = p_dec->p_owner->pp_cc[i_channel];
394         p_dec->p_owner->pp_cc[i_channel] = NULL;
395         vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
396
397         if( p_cc )
398         {
399             vlc_object_kill( p_cc );
400             module_Unneed( p_cc, p_cc->p_module );
401             DeleteDecoder( p_cc );
402             vlc_object_destroy( p_cc );
403         }
404     }
405     return VLC_SUCCESS;
406 }
407 int input_DecoderGetCcState( decoder_t *p_dec, vlc_bool_t *pb_decode, int i_channel )
408 {
409     decoder_owner_sys_t *p_owner = p_dec->p_owner;
410
411     *pb_decode = VLC_FALSE;
412     if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
413         return VLC_EGENERIC;
414
415     vlc_mutex_lock( &p_owner->lock_cc );
416     *pb_decode = p_dec->p_owner->pp_cc[i_channel] != NULL;
417     vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
418     return VLC_EGENERIC;
419 }
420
421 /**
422  * Create a decoder object
423  *
424  * \param p_input the input thread
425  * \param p_es the es descriptor
426  * \param i_object_type Object type as define in include/vlc_objects.h
427  * \return the decoder object
428  */
429 static decoder_t * CreateDecoder( input_thread_t *p_input,
430                                   es_format_t *fmt, int i_object_type )
431 {
432     decoder_t *p_dec;
433     decoder_owner_sys_t *p_owner;
434     int i;
435
436     p_dec = vlc_object_create( p_input, i_object_type );
437     if( p_dec == NULL )
438     {
439         msg_Err( p_input, "out of memory" );
440         return NULL;
441     }
442
443     p_dec->pf_decode_audio = 0;
444     p_dec->pf_decode_video = 0;
445     p_dec->pf_decode_sub = 0;
446     p_dec->pf_get_cc = 0;
447     p_dec->pf_packetize = 0;
448
449     /* Initialize the decoder fifo */
450     p_dec->p_module = NULL;
451
452     memset( &null_es_format, 0, sizeof(es_format_t) );
453     es_format_Copy( &p_dec->fmt_in, fmt );
454     es_format_Copy( &p_dec->fmt_out, &null_es_format );
455
456     /* Allocate our private structure for the decoder */
457     p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
458     if( p_dec->p_owner == NULL )
459     {
460         msg_Err( p_dec, "out of memory" );
461         return NULL;
462     }
463     p_dec->p_owner->b_own_thread = VLC_TRUE;
464     p_dec->p_owner->i_preroll_end = -1;
465     p_dec->p_owner->p_input = p_input;
466     p_dec->p_owner->p_aout = NULL;
467     p_dec->p_owner->p_aout_input = NULL;
468     p_dec->p_owner->p_vout = NULL;
469     p_dec->p_owner->p_spu_vout = NULL;
470     p_dec->p_owner->i_spu_channel = 0;
471     p_dec->p_owner->p_sout = p_input->p->p_sout;
472     p_dec->p_owner->p_sout_input = NULL;
473     p_dec->p_owner->p_packetizer = NULL;
474
475     /* decoder fifo */
476     if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL )
477     {
478         msg_Err( p_dec, "out of memory" );
479         return NULL;
480     }
481
482     /* Set buffers allocation callbacks for the decoders */
483     p_dec->pf_aout_buffer_new = aout_new_buffer;
484     p_dec->pf_aout_buffer_del = aout_del_buffer;
485     p_dec->pf_vout_buffer_new = vout_new_buffer;
486     p_dec->pf_vout_buffer_del = vout_del_buffer;
487     p_dec->pf_picture_link    = vout_link_picture;
488     p_dec->pf_picture_unlink  = vout_unlink_picture;
489     p_dec->pf_spu_buffer_new  = spu_new_buffer;
490     p_dec->pf_spu_buffer_del  = spu_del_buffer;
491
492     vlc_object_attach( p_dec, p_input );
493
494     /* Find a suitable decoder/packetizer module */
495     if( i_object_type == VLC_OBJECT_DECODER )
496         p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );
497     else
498         p_dec->p_module = module_Need( p_dec, "packetizer", "$packetizer", 0 );
499
500     /* Check if decoder requires already packetized data */
501     if( i_object_type == VLC_OBJECT_DECODER &&
502         p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
503     {
504         p_dec->p_owner->p_packetizer =
505             vlc_object_create( p_input, VLC_OBJECT_PACKETIZER );
506         if( p_dec->p_owner->p_packetizer )
507         {
508             es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in,
509                             &p_dec->fmt_in );
510
511             es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_out,
512                             &null_es_format );
513
514             vlc_object_attach( p_dec->p_owner->p_packetizer, p_input );
515
516             p_dec->p_owner->p_packetizer->p_module =
517                 module_Need( p_dec->p_owner->p_packetizer,
518                              "packetizer", "$packetizer", 0 );
519
520             if( !p_dec->p_owner->p_packetizer->p_module )
521             {
522                 es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
523                 vlc_object_detach( p_dec->p_owner->p_packetizer );
524                 vlc_object_destroy( p_dec->p_owner->p_packetizer );
525             }
526         }
527     }
528
529     /* Copy ourself the input replay gain */
530     if( fmt->i_cat == AUDIO_ES )
531     {
532         for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
533         {
534             if( !p_dec->fmt_out.audio_replay_gain.pb_peak[i] )
535             {
536                 p_dec->fmt_out.audio_replay_gain.pb_peak[i] = fmt->audio_replay_gain.pb_peak[i];
537                 p_dec->fmt_out.audio_replay_gain.pf_peak[i] = fmt->audio_replay_gain.pf_peak[i];
538             }
539             if( !p_dec->fmt_out.audio_replay_gain.pb_gain[i] )
540             {
541                 p_dec->fmt_out.audio_replay_gain.pb_gain[i] = fmt->audio_replay_gain.pb_gain[i];
542                 p_dec->fmt_out.audio_replay_gain.pf_gain[i] = fmt->audio_replay_gain.pf_gain[i];
543             }
544         }
545     }
546     /* */
547     p_owner->b_cc_supported = VLC_FALSE;
548     if( i_object_type == VLC_OBJECT_DECODER )
549     {
550         if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
551             p_owner->b_cc_supported = VLC_TRUE;
552         if( p_dec->pf_get_cc )
553             p_owner->b_cc_supported = VLC_TRUE;
554     }
555
556     vlc_mutex_init( p_dec, &p_owner->lock_cc );
557     for( i = 0; i < 4; i++ )
558     {
559         p_owner->pb_cc_present[i] = VLC_FALSE;
560         p_owner->pp_cc[i] = NULL;
561     }
562     return p_dec;
563 }
564
565 /**
566  * The decoding main loop
567  *
568  * \param p_dec the decoder
569  * \return 0
570  */
571 static int DecoderThread( decoder_t * p_dec )
572 {
573     block_t *p_block;
574
575     /* The decoder's main loop */
576     while( !p_dec->b_die && !p_dec->b_error )
577     {
578         if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL )
579         {
580             p_dec->b_error = 1;
581             break;
582         }
583         if( DecoderDecode( p_dec, p_block ) != VLC_SUCCESS )
584         {
585             break;
586         }
587     }
588
589     while( !p_dec->b_die )
590     {
591         /* Trash all received PES packets */
592         p_block = block_FifoGet( p_dec->p_owner->p_fifo );
593         if( p_block ) block_Release( p_block );
594     }
595
596     /* We do it here because of the dll loader that wants close() in the
597      * same thread than open()/decode() */
598     module_Unneed( p_dec, p_dec->p_module );
599
600     return 0;
601 }
602
603 static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
604 {
605     if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
606         *pi_preroll = INT64_MAX;
607     else if( p->i_pts > 0 )
608         *pi_preroll = __MIN( *pi_preroll, p->i_pts );
609     else if( p->i_dts > 0 )
610         *pi_preroll = __MIN( *pi_preroll, p->i_dts );
611 }
612 static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
613 {
614     input_thread_t *p_input = p_dec->p_owner->p_input;
615     const int i_rate = p_block->i_rate;
616     aout_buffer_t *p_aout_buf;
617
618     while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
619     {
620         vlc_mutex_lock( &p_input->p->counters.counters_lock );
621         stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio, 1, NULL );
622         vlc_mutex_unlock( &p_input->p->counters.counters_lock );
623
624         if( p_aout_buf->start_date < p_dec->p_owner->i_preroll_end )
625         {
626             aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
627                                   p_dec->p_owner->p_aout_input, p_aout_buf );
628             continue;
629         }
630
631         if( p_dec->p_owner->i_preroll_end > 0 )
632         {
633             /* FIXME TODO flush audio output (don't know how to do that) */
634             msg_Dbg( p_dec, "End of audio preroll" );
635             p_dec->p_owner->i_preroll_end = -1;
636         }
637         aout_DecPlay( p_dec->p_owner->p_aout,
638                       p_dec->p_owner->p_aout_input,
639                       p_aout_buf, i_rate );
640     }
641 }
642 static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
643 {
644     block_t *p_cc;
645     vlc_bool_t pb_present[4];
646     int i;
647     int i_cc_decoder;
648
649     assert( p_dec_cc->pf_get_cc != NULL );
650
651     /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
652     if( !p_dec->p_owner->b_cc_supported )
653         return;
654
655     p_cc = p_dec_cc->pf_get_cc( p_dec_cc, pb_present );
656     if( !p_cc )
657         return;
658
659     vlc_mutex_lock( &p_dec->p_owner->lock_cc );
660     for( i = 0, i_cc_decoder = 0; i < 4; i++ )
661     {
662         p_dec->p_owner->pb_cc_present[i] |= pb_present[i];
663         if( p_dec->p_owner->pp_cc[i] )
664             i_cc_decoder++;
665     }
666
667     for( i = 0; i < 4; i++ )
668     {
669         if( !p_dec->p_owner->pp_cc[i] )
670             continue;
671
672         if( i_cc_decoder > 1 )
673             DecoderDecode( p_dec->p_owner->pp_cc[i], block_Duplicate( p_cc ) );
674         else
675             DecoderDecode( p_dec->p_owner->pp_cc[i], p_cc );
676         i_cc_decoder--;
677     }
678     vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
679 }
680 static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic )
681 {
682     vlc_mutex_lock( &p_vout->picture_lock );
683
684     if( p_pic->i_status == READY_PICTURE )
685     {
686         /* Grr cannot destroy ready picture by myself so be sure vout won't like it */
687         p_pic->date = 1;
688     }
689     else if( p_pic->i_refcount > 0 )
690     {
691         p_pic->i_status = DISPLAYED_PICTURE;
692     }
693     else
694     {
695         p_pic->i_status = DESTROYED_PICTURE;
696         p_vout->i_heap_size--;
697     }
698
699     vlc_mutex_unlock( &p_vout->picture_lock );
700 }
701 static void VoutFlushPicture( vout_thread_t *p_vout )
702 {
703     int i;
704     vlc_mutex_lock( &p_vout->picture_lock );
705     for( i = 0; i < p_vout->render.i_pictures; i++ )
706     {
707         picture_t *p_pic = p_vout->render.pp_picture[i];
708
709         if( p_pic->i_status == READY_PICTURE ||
710             p_pic->i_status == DISPLAYED_PICTURE )
711         {
712             /* We cannot change picture status if it is in READY_PICTURE state,
713              * Just make sure they won't be displayed */
714             p_pic->date = 1;
715         }
716     }
717     vlc_mutex_unlock( &p_vout->picture_lock );
718 }
719 static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
720 {
721     input_thread_t *p_input = p_dec->p_owner->p_input;
722     picture_t *p_pic;
723
724     while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
725     {
726         vlc_mutex_lock( &p_input->p->counters.counters_lock );
727         stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video, 1, NULL );
728         vlc_mutex_unlock( &p_input->p->counters.counters_lock );
729
730         if( p_pic->date < p_dec->p_owner->i_preroll_end )
731         {
732             VoutDisplayedPicture( p_dec->p_owner->p_vout, p_pic );
733             continue;
734         }
735
736         if( p_dec->p_owner->i_preroll_end > 0 )
737         {
738             msg_Dbg( p_dec, "End of video preroll" );
739             if( p_dec->p_owner->p_vout )
740                 VoutFlushPicture( p_dec->p_owner->p_vout );
741             /* */
742             p_dec->p_owner->i_preroll_end = -1;
743         }
744
745         if( ( !p_dec->p_owner->p_packetizer || !p_dec->p_owner->p_packetizer->pf_get_cc ) && p_dec->pf_get_cc )
746             DecoderGetCc( p_dec, p_dec );
747
748         vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
749                           p_pic->date );
750         vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
751     }
752 }
753
754 /**
755  * Decode a block
756  *
757  * \param p_dec the decoder object
758  * \param p_block the block to decode
759  * \return VLC_SUCCESS or an error code
760  */
761 static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
762 {
763     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
764     const int i_rate = p_block ? p_block->i_rate : INPUT_RATE_DEFAULT;
765
766     if( p_block && p_block->i_buffer <= 0 )
767     {
768         block_Release( p_block );
769         return VLC_SUCCESS;
770     }
771
772     if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
773     {
774         block_t *p_sout_block;
775
776         while( ( p_sout_block =
777                      p_dec->pf_packetize( p_dec, p_block ? &p_block : 0 ) ) )
778         {
779             if( !p_dec->p_owner->p_sout_input )
780             {
781                 es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
782
783                 p_dec->p_owner->sout.i_group = p_dec->fmt_in.i_group;
784                 p_dec->p_owner->sout.i_id = p_dec->fmt_in.i_id;
785                 if( p_dec->fmt_in.psz_language )
786                 {
787                     if( p_dec->p_owner->sout.psz_language )
788                         free( p_dec->p_owner->sout.psz_language );
789                     p_dec->p_owner->sout.psz_language =
790                         strdup( p_dec->fmt_in.psz_language );
791                 }
792
793                 p_dec->p_owner->p_sout_input =
794                     sout_InputNew( p_dec->p_owner->p_sout,
795                                    &p_dec->p_owner->sout );
796
797                 if( p_dec->p_owner->p_sout_input == NULL )
798                 {
799                     msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
800                              (char *)&p_dec->p_owner->sout.i_codec );
801                     p_dec->b_error = VLC_TRUE;
802
803                     while( p_sout_block )
804                     {
805                         block_t *p_next = p_sout_block->p_next;
806                         block_Release( p_sout_block );
807                         p_sout_block = p_next;
808                     }
809                     break;
810                 }
811             }
812
813             while( p_sout_block )
814             {
815                 block_t *p_next = p_sout_block->p_next;
816
817                 p_sout_block->p_next = NULL;
818                 p_sout_block->i_rate = i_rate;
819
820                 sout_InputSendBuffer( p_dec->p_owner->p_sout_input,
821                                       p_sout_block );
822
823                 p_sout_block = p_next;
824             }
825
826             /* For now it's enough, as only sout inpact on this flag */
827             if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 &&
828                 p_dec->p_owner->p_input->p->b_out_pace_control )
829             {
830                 msg_Dbg( p_dec, "switching to sync mode" );
831                 p_dec->p_owner->p_input->p->b_out_pace_control = VLC_FALSE;
832             }
833             else if( p_dec->p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
834                      !p_dec->p_owner->p_input->p->b_out_pace_control )
835             {
836                 msg_Dbg( p_dec, "switching to async mode" );
837                 p_dec->p_owner->p_input->p->b_out_pace_control = VLC_TRUE;
838             }
839         }
840     }
841     else if( p_dec->fmt_in.i_cat == AUDIO_ES )
842     {
843         if( p_block )
844             DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );
845
846         if( p_dec->p_owner->p_packetizer )
847         {
848             block_t *p_packetized_block;
849             decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
850
851             while( (p_packetized_block =
852                     p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
853             {
854                 if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
855                 {
856                     es_format_Clean( &p_dec->fmt_in );
857                     es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
858                 }
859
860                 while( p_packetized_block )
861                 {
862                     block_t *p_next = p_packetized_block->p_next;
863                     p_packetized_block->p_next = NULL;
864                     p_packetized_block->i_rate = i_rate;
865
866                     DecoderDecodeAudio( p_dec, p_packetized_block );
867
868                     p_packetized_block = p_next;
869                 }
870             }
871         }
872         else if( p_block )
873         {
874             DecoderDecodeAudio( p_dec, p_block );
875         }
876     }
877     else if( p_dec->fmt_in.i_cat == VIDEO_ES )
878     {
879         if( p_block )
880             DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );
881
882         if( p_dec->p_owner->p_packetizer )
883         {
884             block_t *p_packetized_block;
885             decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
886
887             while( (p_packetized_block =
888                     p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
889             {
890                 if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
891                 {
892                     es_format_Clean( &p_dec->fmt_in );
893                     es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
894                 }
895                 if( p_packetizer->pf_get_cc )
896                     DecoderGetCc( p_dec, p_packetizer );
897
898                 while( p_packetized_block )
899                 {
900                     block_t *p_next = p_packetized_block->p_next;
901                     p_packetized_block->p_next = NULL;
902                     p_packetized_block->i_rate = i_rate;
903
904                     DecoderDecodeVideo( p_dec, p_packetized_block );
905
906                     p_packetized_block = p_next;
907                 }
908             }
909         }
910         else if( p_block )
911         {
912             DecoderDecodeVideo( p_dec, p_block );
913         }
914     }
915     else if( p_dec->fmt_in.i_cat == SPU_ES )
916     {
917         input_thread_t *p_input = p_dec->p_owner->p_input;
918         vout_thread_t *p_vout;
919         subpicture_t *p_spu;
920
921         if( p_block )
922             DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );
923
924         while( (p_spu = p_dec->pf_decode_sub( p_dec, p_block ? &p_block : NULL ) ) )
925         {
926             vlc_mutex_lock( &p_input->p->counters.counters_lock );
927             stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
928             vlc_mutex_unlock( &p_input->p->counters.counters_lock );
929
930             p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
931             if( p_vout && p_sys->p_spu_vout == p_vout )
932             {
933                 /* Prerool does not work very well with subtitle */
934                 if( p_spu->i_start < p_dec->p_owner->i_preroll_end &&
935                     ( p_spu->i_stop <= 0 || p_spu->i_stop < p_dec->p_owner->i_preroll_end ) )
936                     spu_DestroySubpicture( p_vout->p_spu, p_spu );
937                 else
938                     spu_DisplaySubpicture( p_vout->p_spu, p_spu );
939             }
940             else
941             {
942                 msg_Warn( p_dec, "no vout found, leaking subpicture" );
943             }
944             if( p_vout )
945                 vlc_object_release( p_vout );
946         }
947     }
948     else
949     {
950         msg_Err( p_dec, "unknown ES format" );
951         p_dec->b_error = 1;
952     }
953
954     return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
955 }
956
957 /**
958  * Destroys a decoder object
959  *
960  * \param p_dec the decoder object
961  * \return nothing
962  */
963 static void DeleteDecoder( decoder_t * p_dec )
964 {
965     msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %u PES in FIFO",
966              (char*)&p_dec->fmt_in.i_codec,
967              (unsigned)block_FifoCount( p_dec->p_owner->p_fifo ) );
968
969     /* Free all packets still in the decoder fifo. */
970     block_FifoEmpty( p_dec->p_owner->p_fifo );
971     block_FifoRelease( p_dec->p_owner->p_fifo );
972
973     /* Cleanup */
974     if( p_dec->p_owner->p_aout_input )
975         aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
976
977     if( p_dec->p_owner->p_vout )
978     {
979         int i_pic;
980
981 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
982         /* Hack to make sure all the the pictures are freed by the decoder */
983         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
984              i_pic++ )
985         {
986             if( p_pic->i_status == RESERVED_PICTURE )
987                 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
988             if( p_pic->i_refcount > 0 )
989                 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
990         }
991 #undef p_pic
992
993         /* We are about to die. Reattach video output to p_vlc. */
994         vout_Request( p_dec, p_dec->p_owner->p_vout, 0 );
995     }
996
997     if( p_dec->p_owner->p_sout_input )
998     {
999         sout_InputDelete( p_dec->p_owner->p_sout_input );
1000         es_format_Clean( &p_dec->p_owner->sout );
1001     }
1002
1003     if( p_dec->fmt_in.i_cat == SPU_ES )
1004     {
1005         vout_thread_t *p_vout;
1006
1007         p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
1008         if( p_vout )
1009         {
1010             spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
1011                          p_dec->p_owner->i_spu_channel );
1012             vlc_object_release( p_vout );
1013         }
1014     }
1015
1016     es_format_Clean( &p_dec->fmt_in );
1017     es_format_Clean( &p_dec->fmt_out );
1018
1019     if( p_dec->p_owner->p_packetizer )
1020     {
1021         module_Unneed( p_dec->p_owner->p_packetizer,
1022                        p_dec->p_owner->p_packetizer->p_module );
1023         es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
1024         es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_out );
1025         vlc_object_detach( p_dec->p_owner->p_packetizer );
1026         vlc_object_destroy( p_dec->p_owner->p_packetizer );
1027     }
1028
1029     vlc_mutex_destroy( &p_dec->p_owner->lock_cc );
1030
1031     vlc_object_detach( p_dec );
1032
1033     free( p_dec->p_owner );
1034 }
1035
1036 /*****************************************************************************
1037  * Buffers allocation callbacks for the decoders
1038  *****************************************************************************/
1039 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
1040 {
1041     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
1042     aout_buffer_t *p_buffer;
1043
1044     if( p_sys->p_aout_input != NULL &&
1045         ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate ||
1046           p_dec->fmt_out.audio.i_original_channels !=
1047               p_sys->audio.i_original_channels ||
1048           p_dec->fmt_out.audio.i_bytes_per_frame !=
1049               p_sys->audio.i_bytes_per_frame ) )
1050     {
1051         /* Parameters changed, restart the aout */
1052         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
1053         p_sys->p_aout_input = NULL;
1054     }
1055
1056     if( p_sys->p_aout_input == NULL )
1057     {
1058         audio_sample_format_t format;
1059         int i_force_dolby = config_GetInt( p_dec, "force-dolby-surround" );
1060
1061         p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
1062         p_sys->audio = p_dec->fmt_out.audio;
1063
1064         memcpy( &format, &p_sys->audio, sizeof( audio_sample_format_t ) );
1065         if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK)
1066                                     == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
1067         {
1068             if ( i_force_dolby == 1 )
1069             {
1070                 format.i_original_channels = format.i_original_channels |
1071                                              AOUT_CHAN_DOLBYSTEREO;
1072             }
1073             else /* i_force_dolby == 2 */
1074             {
1075                 format.i_original_channels = format.i_original_channels &
1076                                              ~AOUT_CHAN_DOLBYSTEREO;
1077             }
1078         }
1079
1080         p_sys->p_aout_input =
1081             aout_DecNew( p_dec, &p_sys->p_aout, &format, &p_dec->fmt_out.audio_replay_gain );
1082         if( p_sys->p_aout_input == NULL )
1083         {
1084             msg_Err( p_dec, "failed to create audio output" );
1085             p_dec->b_error = VLC_TRUE;
1086             return NULL;
1087         }
1088         p_dec->fmt_out.audio.i_bytes_per_frame =
1089             p_sys->audio.i_bytes_per_frame;
1090     }
1091
1092     p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
1093                                   i_samples );
1094
1095     return p_buffer;
1096 }
1097
1098 static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
1099 {
1100     aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
1101                           p_dec->p_owner->p_aout_input, p_buffer );
1102 }
1103
1104 static picture_t *vout_new_buffer( decoder_t *p_dec )
1105 {
1106     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
1107     picture_t *p_pic;
1108
1109     if( p_sys->p_vout == NULL ||
1110         p_dec->fmt_out.video.i_width != p_sys->video.i_width ||
1111         p_dec->fmt_out.video.i_height != p_sys->video.i_height ||
1112         p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma ||
1113         p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect )
1114     {
1115         if( !p_dec->fmt_out.video.i_width ||
1116             !p_dec->fmt_out.video.i_height )
1117         {
1118             /* Can't create a new vout without display size */
1119             return NULL;
1120         }
1121
1122         if( !p_dec->fmt_out.video.i_visible_width ||
1123             !p_dec->fmt_out.video.i_visible_height )
1124         {
1125             if( p_dec->fmt_in.video.i_visible_width &&
1126                 p_dec->fmt_in.video.i_visible_height )
1127             {
1128                 p_dec->fmt_out.video.i_visible_width =
1129                     p_dec->fmt_in.video.i_visible_width;
1130                 p_dec->fmt_out.video.i_visible_height =
1131                     p_dec->fmt_in.video.i_visible_height;
1132             }
1133             else
1134             {
1135                 p_dec->fmt_out.video.i_visible_width =
1136                     p_dec->fmt_out.video.i_width;
1137                 p_dec->fmt_out.video.i_visible_height =
1138                     p_dec->fmt_out.video.i_height;
1139             }
1140         }
1141
1142         if( p_dec->fmt_out.video.i_visible_height == 1088 &&
1143             var_CreateGetBool( p_dec, "hdtv-fix" ) )
1144         {
1145             p_dec->fmt_out.video.i_visible_height = 1080;
1146             p_dec->fmt_out.video.i_sar_num *= 135;
1147             p_dec->fmt_out.video.i_sar_den *= 136;
1148             msg_Warn( p_dec, "Fixing broken HDTV stream (display_height=1088)");
1149         }
1150
1151         if( !p_dec->fmt_out.video.i_sar_num ||
1152             !p_dec->fmt_out.video.i_sar_den )
1153         {
1154             p_dec->fmt_out.video.i_sar_num = p_dec->fmt_out.video.i_aspect *
1155               p_dec->fmt_out.video.i_visible_height;
1156
1157             p_dec->fmt_out.video.i_sar_den = VOUT_ASPECT_FACTOR *
1158               p_dec->fmt_out.video.i_visible_width;
1159         }
1160
1161         vlc_ureduce( &p_dec->fmt_out.video.i_sar_num,
1162                      &p_dec->fmt_out.video.i_sar_den,
1163                      p_dec->fmt_out.video.i_sar_num,
1164                      p_dec->fmt_out.video.i_sar_den, 50000 );
1165
1166         p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
1167         p_sys->video = p_dec->fmt_out.video;
1168
1169         p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
1170                                       &p_dec->fmt_out.video );
1171         if( p_sys->p_vout == NULL )
1172         {
1173             msg_Err( p_dec, "failed to create video output" );
1174             p_dec->b_error = VLC_TRUE;
1175             return NULL;
1176         }
1177
1178         if( p_sys->video.i_rmask )
1179             p_sys->p_vout->render.i_rmask = p_sys->video.i_rmask;
1180         if( p_sys->video.i_gmask )
1181             p_sys->p_vout->render.i_gmask = p_sys->video.i_gmask;
1182         if( p_sys->video.i_bmask )
1183             p_sys->p_vout->render.i_bmask = p_sys->video.i_bmask;
1184     }
1185
1186     /* Get a new picture */
1187     while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
1188     {
1189         int i_pic, i_ready_pic = 0;
1190
1191         if( p_dec->b_die || p_dec->b_error )
1192         {
1193             return NULL;
1194         }
1195
1196 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
1197         /* Check the decoder doesn't leak pictures */
1198         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
1199              i_pic++ )
1200         {
1201             if( p_pic->i_status == READY_PICTURE )
1202             {
1203                 if( i_ready_pic++ > 0 ) break;
1204                 else continue;
1205             }
1206
1207             if( p_pic->i_status != DISPLAYED_PICTURE &&
1208                 p_pic->i_status != RESERVED_PICTURE &&
1209                 p_pic->i_status != READY_PICTURE ) break;
1210
1211             if( !p_pic->i_refcount && p_pic->i_status != RESERVED_PICTURE )
1212                 break;
1213         }
1214         if( i_pic == p_dec->p_owner->p_vout->render.i_pictures )
1215         {
1216             msg_Err( p_dec, "decoder is leaking pictures, resetting the heap" );
1217
1218             /* Just free all the pictures */
1219             for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
1220                  i_pic++ )
1221             {
1222                 if( p_pic->i_status == RESERVED_PICTURE )
1223                     vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
1224                 if( p_pic->i_refcount > 0 )
1225                 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
1226             }
1227         }
1228 #undef p_pic
1229
1230         msleep( VOUT_OUTMEM_SLEEP );
1231     }
1232
1233     return p_pic;
1234 }
1235
1236 static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
1237 {
1238     VoutDisplayedPicture( p_dec->p_owner->p_vout, p_pic );
1239 }
1240
1241 static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
1242 {
1243     vout_LinkPicture( p_dec->p_owner->p_vout, p_pic );
1244 }
1245
1246 static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
1247 {
1248     vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
1249 }
1250
1251 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
1252 {
1253     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
1254     vout_thread_t *p_vout = NULL;
1255     subpicture_t *p_subpic;
1256     int i_attempts = 30;
1257
1258     while( i_attempts-- )
1259     {
1260         if( p_dec->b_die || p_dec->b_error ) break;
1261
1262         p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
1263         if( p_vout ) break;
1264
1265         msleep( VOUT_DISPLAY_DELAY );
1266     }
1267
1268     if( !p_vout )
1269     {
1270         msg_Warn( p_dec, "no vout found, dropping subpicture" );
1271         return NULL;
1272     }
1273
1274     if( p_sys->p_spu_vout != p_vout )
1275     {
1276         spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER,
1277                      &p_sys->i_spu_channel );
1278         p_sys->p_spu_vout = p_vout;
1279     }
1280
1281     p_subpic = spu_CreateSubpicture( p_vout->p_spu );
1282     if( p_subpic )
1283     {
1284         p_subpic->i_channel = p_sys->i_spu_channel;
1285     }
1286
1287     vlc_object_release( p_vout );
1288
1289     return p_subpic;
1290 }
1291
1292 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
1293 {
1294     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
1295     vout_thread_t *p_vout = NULL;
1296
1297     p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
1298     if( !p_vout || p_sys->p_spu_vout != p_vout )
1299     {
1300         if( p_vout )
1301             vlc_object_release( p_vout );
1302         msg_Warn( p_dec, "no vout found, leaking subpicture" );
1303         return;
1304     }
1305
1306     spu_DestroySubpicture( p_vout->p_spu, p_subpic );
1307
1308     vlc_object_release( p_vout );
1309 }
1310