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