1 /*****************************************************************************
2 * decoder.c: Functions for the management of decoders
3 *****************************************************************************
4 * Copyright (C) 1999-2004 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
34 #include <vlc_common.h>
36 #include <vlc_block.h>
40 #include <vlc_codec.h>
43 #include <vlc_interface.h>
44 #include "audio_output/aout_internal.h"
45 #include "stream_output/stream_output.h"
46 #include "input_internal.h"
48 static decoder_t
* CreateDecoder( input_thread_t
*, es_format_t
*, int );
49 static void DeleteDecoder( decoder_t
* );
51 static int DecoderThread( decoder_t
* );
52 static int DecoderDecode( decoder_t
* p_dec
, block_t
*p_block
);
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
* );
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
* );
63 static subpicture_t
*spu_new_buffer( decoder_t
* );
64 static void spu_del_buffer( decoder_t
*, subpicture_t
* );
66 static es_format_t null_es_format
;
68 struct decoder_owner_sys_t
72 int64_t i_preroll_end
;
74 input_thread_t
*p_input
;
76 aout_instance_t
*p_aout
;
77 aout_input_t
*p_aout_input
;
79 vout_thread_t
*p_vout
;
81 vout_thread_t
*p_spu_vout
;
84 sout_instance_t
*p_sout
;
85 sout_packetizer_input_t
*p_sout_input
;
87 /* Some decoders require already packetized data (ie. not truncated) */
88 decoder_t
*p_packetizer
;
90 /* Current format in use by the output */
101 bool pb_cc_present
[4];
106 static void DecoderUnsupportedCodec( decoder_t
*p_dec
, vlc_fourcc_t codec
)
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.",
111 intf_UserFatal( p_dec
, 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
);
116 /* decoder_GetInputAttachment:
118 input_attachment_t
*decoder_GetInputAttachment( decoder_t
*p_dec
,
119 const char *psz_name
)
121 input_attachment_t
*p_attachment
;
122 if( input_Control( p_dec
->p_owner
->p_input
, INPUT_GET_ATTACHMENT
, &p_attachment
, psz_name
) )
126 /* decoder_GetInputAttachments:
128 int decoder_GetInputAttachments( decoder_t
*p_dec
,
129 input_attachment_t
***ppp_attachment
,
132 return input_Control( p_dec
->p_owner
->p_input
, INPUT_GET_ATTACHMENTS
,
133 ppp_attachment
, pi_attachment
);
135 /* decoder_GetDisplayDate:
137 mtime_t
decoder_GetDisplayDate( decoder_t
*p_dec
, mtime_t i_ts
)
144 * Spawns a new decoder thread
146 * \param p_input the input thread
147 * \param p_es the es descriptor
148 * \return the spawned decoder object
150 decoder_t
*input_DecoderNew( input_thread_t
*p_input
,
151 es_format_t
*fmt
, bool b_force_decoder
)
153 decoder_t
*p_dec
= NULL
;
157 (void)b_force_decoder
;
159 /* If we are in sout mode, search for packetizer module */
160 if( p_input
->p
->p_sout
&& !b_force_decoder
)
162 /* Create the decoder configuration structure */
163 p_dec
= CreateDecoder( p_input
, fmt
, VLC_OBJECT_PACKETIZER
);
166 msg_Err( p_input
, "could not create packetizer" );
167 intf_UserFatal( p_input
, false, _("Streaming / Transcoding failed"),
168 _("VLC could not open the packetizer module.") );
175 /* Create the decoder configuration structure */
176 p_dec
= CreateDecoder( p_input
, fmt
, VLC_OBJECT_DECODER
);
179 msg_Err( p_input
, "could not create decoder" );
180 intf_UserFatal( p_input
, false, _("Streaming / Transcoding failed"),
181 _("VLC could not open the decoder module.") );
186 if( !p_dec
->p_module
)
188 DecoderUnsupportedCodec( p_dec
, fmt
->i_codec
);
190 DeleteDecoder( p_dec
);
191 vlc_object_release( p_dec
);
195 if( p_input
->p
->p_sout
&& p_input
->p
->input
.b_can_pace_control
&&
198 msg_Dbg( p_input
, "stream out mode -> no decoder thread" );
199 p_dec
->p_owner
->b_own_thread
= false;
203 var_Get( p_input
, "minimize-threads", &val
);
204 p_dec
->p_owner
->b_own_thread
= !val
.b_bool
;
207 if( p_dec
->p_owner
->b_own_thread
)
210 if( fmt
->i_cat
== AUDIO_ES
)
211 i_priority
= VLC_THREAD_PRIORITY_AUDIO
;
213 i_priority
= VLC_THREAD_PRIORITY_VIDEO
;
215 /* Spawn the decoder thread */
216 if( vlc_thread_create( p_dec
, "decoder", DecoderThread
,
217 i_priority
, false ) )
219 msg_Err( p_dec
, "cannot spawn decoder thread" );
220 module_Unneed( p_dec
, p_dec
->p_module
);
221 DeleteDecoder( p_dec
);
222 vlc_object_release( p_dec
);
231 * Kills a decoder thread and waits until it's finished
233 * \param p_input the input thread
234 * \param p_es the es descriptor
237 void input_DecoderDelete( decoder_t
*p_dec
)
239 vlc_object_kill( p_dec
);
241 if( p_dec
->p_owner
->b_own_thread
)
243 /* Make sure the thread leaves the function by
244 * sending it an empty block. */
245 block_t
*p_block
= block_New( p_dec
, 0 );
246 input_DecoderDecode( p_dec
, p_block
);
248 vlc_thread_join( p_dec
);
250 /* Don't module_Unneed() here because of the dll loader that wants
251 * close() in the same thread than open()/decode() */
256 input_DecoderDecode( p_dec
, NULL
);
258 module_Unneed( p_dec
, p_dec
->p_module
);
262 if( p_dec
->p_owner
->b_cc_supported
)
265 for( i
= 0; i
< 4; i
++ )
266 input_DecoderSetCcState( p_dec
, false, i
);
269 /* Delete decoder configuration */
270 DeleteDecoder( p_dec
);
272 /* Delete the decoder */
273 vlc_object_release( p_dec
);
277 * Put a block_t in the decoder's fifo.
279 * \param p_dec the decoder object
280 * \param p_block the data block
282 void input_DecoderDecode( decoder_t
* p_dec
, block_t
*p_block
)
284 if( p_dec
->p_owner
->b_own_thread
)
286 if( p_dec
->p_owner
->p_input
->p
->b_out_pace_control
)
289 while( !p_dec
->b_die
&& !p_dec
->b_error
&&
290 block_FifoCount( p_dec
->p_owner
->p_fifo
) > 10 )
295 else if( block_FifoSize( p_dec
->p_owner
->p_fifo
) > 50000000 /* 50 MB */ )
297 /* FIXME: ideally we would check the time amount of data
298 * in the fifo instead of its size. */
299 msg_Warn( p_dec
, "decoder/packetizer fifo full (data not "
300 "consumed quickly enough), resetting fifo!" );
301 block_FifoEmpty( p_dec
->p_owner
->p_fifo
);
304 block_FifoPut( p_dec
->p_owner
->p_fifo
, p_block
);
308 if( p_dec
->b_error
|| (p_block
&& p_block
->i_buffer
<= 0) )
310 if( p_block
) block_Release( p_block
);
314 DecoderDecode( p_dec
, p_block
);
319 void input_DecoderDiscontinuity( decoder_t
* p_dec
, bool b_flush
)
324 if( p_dec
->p_owner
->b_own_thread
&& b_flush
)
325 block_FifoEmpty( p_dec
->p_owner
->p_fifo
);
327 /* Send a special block */
328 p_null
= block_New( p_dec
, 128 );
329 p_null
->i_flags
|= BLOCK_FLAG_DISCONTINUITY
;
330 /* FIXME check for p_packetizer or b_packitized from es_format_t of input ? */
331 if( p_dec
->p_owner
->p_packetizer
&& b_flush
)
332 p_null
->i_flags
|= BLOCK_FLAG_CORRUPTED
;
333 memset( p_null
->p_buffer
, 0, p_null
->i_buffer
);
335 input_DecoderDecode( p_dec
, p_null
);
338 bool input_DecoderEmpty( decoder_t
* p_dec
)
340 if( p_dec
->p_owner
->b_own_thread
341 && block_FifoCount( p_dec
->p_owner
->p_fifo
) > 0 )
348 void input_DecoderIsCcPresent( decoder_t
*p_dec
, bool pb_present
[4] )
352 vlc_mutex_lock( &p_dec
->p_owner
->lock_cc
);
353 for( i
= 0; i
< 4; i
++ )
354 pb_present
[i
] = p_dec
->p_owner
->pb_cc_present
[i
];
355 vlc_mutex_unlock( &p_dec
->p_owner
->lock_cc
);
357 int input_DecoderSetCcState( decoder_t
*p_dec
, bool b_decode
, int i_channel
)
359 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
361 //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel );
363 if( i_channel
< 0 || i_channel
>= 4 || !p_owner
->pb_cc_present
[i_channel
] )
368 static const vlc_fourcc_t fcc
[4] = {
369 VLC_FOURCC('c', 'c', '1', ' '),
370 VLC_FOURCC('c', 'c', '2', ' '),
371 VLC_FOURCC('c', 'c', '3', ' '),
372 VLC_FOURCC('c', 'c', '4', ' '),
377 es_format_Init( &fmt
, SPU_ES
, fcc
[i_channel
] );
378 p_cc
= CreateDecoder( p_owner
->p_input
, &fmt
, VLC_OBJECT_DECODER
);
381 msg_Err( p_dec
, "could not create decoder" );
382 intf_UserFatal( p_dec
, false, _("Streaming / Transcoding failed"),
383 _("VLC could not open the decoder module.") );
386 else if( !p_cc
->p_module
)
388 DecoderUnsupportedCodec( p_dec
, fcc
[i_channel
] );
389 DeleteDecoder( p_cc
);
390 vlc_object_release( p_cc
);
394 vlc_mutex_lock( &p_owner
->lock_cc
);
395 p_dec
->p_owner
->pp_cc
[i_channel
] = p_cc
;
396 vlc_mutex_unlock( &p_owner
->lock_cc
);
402 vlc_mutex_lock( &p_owner
->lock_cc
);
403 p_cc
= p_dec
->p_owner
->pp_cc
[i_channel
];
404 p_dec
->p_owner
->pp_cc
[i_channel
] = NULL
;
405 vlc_mutex_unlock( &p_dec
->p_owner
->lock_cc
);
409 vlc_object_kill( p_cc
);
410 module_Unneed( p_cc
, p_cc
->p_module
);
411 DeleteDecoder( p_cc
);
412 vlc_object_release( p_cc
);
417 int input_DecoderGetCcState( decoder_t
*p_dec
, bool *pb_decode
, int i_channel
)
419 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
422 if( i_channel
< 0 || i_channel
>= 4 || !p_owner
->pb_cc_present
[i_channel
] )
425 vlc_mutex_lock( &p_owner
->lock_cc
);
426 *pb_decode
= p_dec
->p_owner
->pp_cc
[i_channel
] != NULL
;
427 vlc_mutex_unlock( &p_dec
->p_owner
->lock_cc
);
432 * Create a decoder object
434 * \param p_input the input thread
435 * \param p_es the es descriptor
436 * \param i_object_type Object type as define in include/vlc_objects.h
437 * \return the decoder object
439 static decoder_t
* CreateDecoder( input_thread_t
*p_input
,
440 es_format_t
*fmt
, int i_object_type
)
443 decoder_owner_sys_t
*p_owner
;
446 p_dec
= vlc_object_create( p_input
, i_object_type
);
450 p_dec
->pf_decode_audio
= 0;
451 p_dec
->pf_decode_video
= 0;
452 p_dec
->pf_decode_sub
= 0;
453 p_dec
->pf_get_cc
= 0;
454 p_dec
->pf_packetize
= 0;
456 /* Initialize the decoder fifo */
457 p_dec
->p_module
= NULL
;
459 memset( &null_es_format
, 0, sizeof(es_format_t
) );
460 es_format_Copy( &p_dec
->fmt_in
, fmt
);
461 es_format_Copy( &p_dec
->fmt_out
, &null_es_format
);
463 /* Allocate our private structure for the decoder */
464 p_dec
->p_owner
= p_owner
= malloc( sizeof( decoder_owner_sys_t
) );
465 if( p_dec
->p_owner
== NULL
)
467 vlc_object_release( p_dec
);
470 p_dec
->p_owner
->b_own_thread
= true;
471 p_dec
->p_owner
->i_preroll_end
= -1;
472 p_dec
->p_owner
->p_input
= p_input
;
473 p_dec
->p_owner
->p_aout
= NULL
;
474 p_dec
->p_owner
->p_aout_input
= NULL
;
475 p_dec
->p_owner
->p_vout
= NULL
;
476 p_dec
->p_owner
->p_spu_vout
= NULL
;
477 p_dec
->p_owner
->i_spu_channel
= 0;
478 p_dec
->p_owner
->p_sout
= p_input
->p
->p_sout
;
479 p_dec
->p_owner
->p_sout_input
= NULL
;
480 p_dec
->p_owner
->p_packetizer
= NULL
;
483 if( ( p_dec
->p_owner
->p_fifo
= block_FifoNew() ) == NULL
)
485 free( p_dec
->p_owner
);
486 vlc_object_release( p_dec
);
490 /* Set buffers allocation callbacks for the decoders */
491 p_dec
->pf_aout_buffer_new
= aout_new_buffer
;
492 p_dec
->pf_aout_buffer_del
= aout_del_buffer
;
493 p_dec
->pf_vout_buffer_new
= vout_new_buffer
;
494 p_dec
->pf_vout_buffer_del
= vout_del_buffer
;
495 p_dec
->pf_picture_link
= vout_link_picture
;
496 p_dec
->pf_picture_unlink
= vout_unlink_picture
;
497 p_dec
->pf_spu_buffer_new
= spu_new_buffer
;
498 p_dec
->pf_spu_buffer_del
= spu_del_buffer
;
500 vlc_object_attach( p_dec
, p_input
);
502 /* Find a suitable decoder/packetizer module */
503 if( i_object_type
== VLC_OBJECT_DECODER
)
504 p_dec
->p_module
= module_Need( p_dec
, "decoder", "$codec", 0 );
506 p_dec
->p_module
= module_Need( p_dec
, "packetizer", "$packetizer", 0 );
508 /* Check if decoder requires already packetized data */
509 if( i_object_type
== VLC_OBJECT_DECODER
&&
510 p_dec
->b_need_packetized
&& !p_dec
->fmt_in
.b_packetized
)
512 p_dec
->p_owner
->p_packetizer
=
513 vlc_object_create( p_input
, VLC_OBJECT_PACKETIZER
);
514 if( p_dec
->p_owner
->p_packetizer
)
516 es_format_Copy( &p_dec
->p_owner
->p_packetizer
->fmt_in
,
519 es_format_Copy( &p_dec
->p_owner
->p_packetizer
->fmt_out
,
522 vlc_object_attach( p_dec
->p_owner
->p_packetizer
, p_input
);
524 p_dec
->p_owner
->p_packetizer
->p_module
=
525 module_Need( p_dec
->p_owner
->p_packetizer
,
526 "packetizer", "$packetizer", 0 );
528 if( !p_dec
->p_owner
->p_packetizer
->p_module
)
530 es_format_Clean( &p_dec
->p_owner
->p_packetizer
->fmt_in
);
531 vlc_object_detach( p_dec
->p_owner
->p_packetizer
);
532 vlc_object_release( p_dec
->p_owner
->p_packetizer
);
537 /* Copy ourself the input replay gain */
538 if( fmt
->i_cat
== AUDIO_ES
)
540 for( i
= 0; i
< AUDIO_REPLAY_GAIN_MAX
; i
++ )
542 if( !p_dec
->fmt_out
.audio_replay_gain
.pb_peak
[i
] )
544 p_dec
->fmt_out
.audio_replay_gain
.pb_peak
[i
] = fmt
->audio_replay_gain
.pb_peak
[i
];
545 p_dec
->fmt_out
.audio_replay_gain
.pf_peak
[i
] = fmt
->audio_replay_gain
.pf_peak
[i
];
547 if( !p_dec
->fmt_out
.audio_replay_gain
.pb_gain
[i
] )
549 p_dec
->fmt_out
.audio_replay_gain
.pb_gain
[i
] = fmt
->audio_replay_gain
.pb_gain
[i
];
550 p_dec
->fmt_out
.audio_replay_gain
.pf_gain
[i
] = fmt
->audio_replay_gain
.pf_gain
[i
];
555 p_owner
->b_cc_supported
= false;
556 if( i_object_type
== VLC_OBJECT_DECODER
)
558 if( p_owner
->p_packetizer
&& p_owner
->p_packetizer
->pf_get_cc
)
559 p_owner
->b_cc_supported
= true;
560 if( p_dec
->pf_get_cc
)
561 p_owner
->b_cc_supported
= true;
564 vlc_mutex_init( &p_owner
->lock_cc
);
565 for( i
= 0; i
< 4; i
++ )
567 p_owner
->pb_cc_present
[i
] = false;
568 p_owner
->pp_cc
[i
] = NULL
;
574 * The decoding main loop
576 * \param p_dec the decoder
579 static int DecoderThread( decoder_t
* p_dec
)
583 /* The decoder's main loop */
584 while( !p_dec
->b_die
&& !p_dec
->b_error
)
586 if( ( p_block
= block_FifoGet( p_dec
->p_owner
->p_fifo
) ) == NULL
)
591 if( DecoderDecode( p_dec
, p_block
) != VLC_SUCCESS
)
597 while( !p_dec
->b_die
)
599 /* Trash all received PES packets */
600 p_block
= block_FifoGet( p_dec
->p_owner
->p_fifo
);
601 if( p_block
) block_Release( p_block
);
604 /* We do it here because of the dll loader that wants close() in the
605 * same thread than open()/decode() */
606 module_Unneed( p_dec
, p_dec
->p_module
);
611 static inline void DecoderUpdatePreroll( int64_t *pi_preroll
, const block_t
*p
)
613 if( p
->i_flags
& (BLOCK_FLAG_PREROLL
|BLOCK_FLAG_DISCONTINUITY
) )
614 *pi_preroll
= INT64_MAX
;
615 else if( p
->i_pts
> 0 )
616 *pi_preroll
= __MIN( *pi_preroll
, p
->i_pts
);
617 else if( p
->i_dts
> 0 )
618 *pi_preroll
= __MIN( *pi_preroll
, p
->i_dts
);
620 static void DecoderDecodeAudio( decoder_t
*p_dec
, block_t
*p_block
)
622 input_thread_t
*p_input
= p_dec
->p_owner
->p_input
;
623 const int i_rate
= p_block
->i_rate
;
624 aout_buffer_t
*p_aout_buf
;
626 while( (p_aout_buf
= p_dec
->pf_decode_audio( p_dec
, &p_block
)) )
628 aout_instance_t
*p_aout
= p_dec
->p_owner
->p_aout
;
629 aout_input_t
*p_aout_input
= p_dec
->p_owner
->p_aout_input
;
633 /* It prevent freezing VLC in case of broken decoder */
634 aout_DecDeleteBuffer( p_aout
, p_aout_input
, p_aout_buf
);
636 block_Release( p_block
);
639 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
640 stats_UpdateInteger( p_dec
, p_input
->p
->counters
.p_decoded_audio
, 1, NULL
);
641 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
643 if( p_aout_buf
->start_date
< p_dec
->p_owner
->i_preroll_end
)
645 aout_DecDeleteBuffer( p_aout
, p_aout_input
, p_aout_buf
);
649 if( p_dec
->p_owner
->i_preroll_end
> 0 )
651 /* FIXME TODO flush audio output (don't know how to do that) */
652 msg_Dbg( p_dec
, "End of audio preroll" );
653 p_dec
->p_owner
->i_preroll_end
= -1;
655 aout_DecPlay( p_aout
, p_aout_input
, p_aout_buf
, i_rate
);
658 static void DecoderGetCc( decoder_t
*p_dec
, decoder_t
*p_dec_cc
)
665 assert( p_dec_cc
->pf_get_cc
!= NULL
);
667 /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
668 if( !p_dec
->p_owner
->b_cc_supported
)
671 p_cc
= p_dec_cc
->pf_get_cc( p_dec_cc
, pb_present
);
675 vlc_mutex_lock( &p_dec
->p_owner
->lock_cc
);
676 for( i
= 0, i_cc_decoder
= 0; i
< 4; i
++ )
678 p_dec
->p_owner
->pb_cc_present
[i
] |= pb_present
[i
];
679 if( p_dec
->p_owner
->pp_cc
[i
] )
683 for( i
= 0; i
< 4; i
++ )
685 if( !p_dec
->p_owner
->pp_cc
[i
] )
688 if( i_cc_decoder
> 1 )
689 DecoderDecode( p_dec
->p_owner
->pp_cc
[i
], block_Duplicate( p_cc
) );
691 DecoderDecode( p_dec
->p_owner
->pp_cc
[i
], p_cc
);
694 vlc_mutex_unlock( &p_dec
->p_owner
->lock_cc
);
696 static void VoutDisplayedPicture( vout_thread_t
*p_vout
, picture_t
*p_pic
)
698 vlc_mutex_lock( &p_vout
->picture_lock
);
700 if( p_pic
->i_status
== READY_PICTURE
)
702 /* Grr cannot destroy ready picture by myself so be sure vout won't like it */
705 else if( p_pic
->i_refcount
> 0 )
707 p_pic
->i_status
= DISPLAYED_PICTURE
;
711 p_pic
->i_status
= DESTROYED_PICTURE
;
712 p_vout
->i_heap_size
--;
715 vlc_mutex_unlock( &p_vout
->picture_lock
);
717 static void VoutFlushPicture( vout_thread_t
*p_vout
)
720 vlc_mutex_lock( &p_vout
->picture_lock
);
721 for( i
= 0; i
< p_vout
->render
.i_pictures
; i
++ )
723 picture_t
*p_pic
= p_vout
->render
.pp_picture
[i
];
725 if( p_pic
->i_status
== READY_PICTURE
||
726 p_pic
->i_status
== DISPLAYED_PICTURE
)
728 /* We cannot change picture status if it is in READY_PICTURE state,
729 * Just make sure they won't be displayed */
733 vlc_mutex_unlock( &p_vout
->picture_lock
);
737 static void optimize_video_pts( decoder_t
*p_dec
)
739 picture_t
* oldest_pict
= NULL
;
740 picture_t
* youngest_pict
= NULL
;
743 input_thread_t
* p_input
= p_dec
->p_owner
->p_input
;
744 vout_thread_t
* p_vout
= p_dec
->p_owner
->p_vout
;
745 input_thread_private_t
* p_priv
= p_input
->p
;
747 /* Enable with --auto-adjust-pts-delay */
748 if( !p_priv
->pts_adjust
.auto_adjust
) return;
750 for( i
= 0; i
< I_RENDERPICTURES
; i
++ )
752 picture_t
* pic
= PP_RENDERPICTURE
[i
];
753 if( pic
->i_status
!= READY_PICTURE
)
756 if( !oldest_pict
|| pic
->date
< oldest_pict
->date
)
758 if( !youngest_pict
|| pic
->date
> youngest_pict
->date
)
762 if( !youngest_pict
|| !oldest_pict
)
765 /* Try to find if we can reduce the pts
766 * This first draft is way to simple, and we can't say if the
767 * algo will converge. It's also full of constants.
768 * But this simple algo allows to reduce the latency
770 * The whole point of this, is to bypass the pts_delay set
771 * by the access but also the delay arbitraly set by
773 * Actually the remote server's muxer may set up a
774 * pts<->dts delay in the muxed stream. That is
775 * why we may end up in having a negative pts_delay,
776 * to compensate that artificial delay. */
777 mtime_t buffer_size
= youngest_pict
->date
- oldest_pict
->date
;
778 int64_t pts_slide
= 0;
779 if( buffer_size
< 10000 )
781 if( p_priv
->pts_adjust
.i_num_faulty
> 10 )
783 pts_slide
= __MAX(p_input
->i_pts_delay
*3 / 2, 10000);
784 p_priv
->pts_adjust
.i_num_faulty
= 0;
786 if( p_priv
->pts_adjust
.to_high
)
788 p_priv
->pts_adjust
.to_high
= !p_priv
->pts_adjust
.to_high
;
789 p_priv
->pts_adjust
.i_num_faulty
= 0;
791 p_priv
->pts_adjust
.i_num_faulty
++;
793 else if( buffer_size
> 100000 )
795 if( p_priv
->pts_adjust
.i_num_faulty
> 25 )
797 pts_slide
= -buffer_size
/2;
798 p_priv
->pts_adjust
.i_num_faulty
= 0;
800 if( p_priv
->pts_adjust
.to_high
)
802 p_priv
->pts_adjust
.to_high
= !p_priv
->pts_adjust
.to_high
;
803 p_priv
->pts_adjust
.i_num_faulty
= 0;
805 p_priv
->pts_adjust
.i_num_faulty
++;
809 mtime_t origi_delay
= p_input
->i_pts_delay
;
811 p_input
->i_pts_delay
+= pts_slide
;
813 /* Don't play with the pts delay for more than -2<->3sec */
814 if( p_input
->i_pts_delay
< -2000000 )
815 p_input
->i_pts_delay
= -2000000;
816 else if( p_input
->i_pts_delay
> 3000000 )
817 p_input
->i_pts_delay
= 3000000;
818 pts_slide
= p_input
->i_pts_delay
- origi_delay
;
820 msg_Dbg( p_input
, "Sliding the pts by %dms pts delay at %dms picture buffer was %dms",
821 (int)pts_slide
/1000, (int)p_input
->i_pts_delay
/1000, (int)buffer_size
/1000);
823 vlc_mutex_lock( &p_vout
->picture_lock
);
824 /* Slide all the picture */
825 for( i
= 0; i
< I_RENDERPICTURES
; i
++ )
826 PP_RENDERPICTURE
[i
]->date
+= pts_slide
;
827 /* FIXME: slide aout/spu */
828 vlc_mutex_unlock( &p_vout
->picture_lock
);
833 static void DecoderDecodeVideo( decoder_t
*p_dec
, block_t
*p_block
)
835 input_thread_t
*p_input
= p_dec
->p_owner
->p_input
;
838 while( (p_pic
= p_dec
->pf_decode_video( p_dec
, &p_block
)) )
840 vout_thread_t
*p_vout
= p_dec
->p_owner
->p_vout
;
843 /* It prevent freezing VLC in case of broken decoder */
844 VoutDisplayedPicture( p_vout
, p_pic
);
846 block_Release( p_block
);
850 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
851 stats_UpdateInteger( p_dec
, p_input
->p
->counters
.p_decoded_video
, 1, NULL
);
852 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
854 if( p_pic
->date
< p_dec
->p_owner
->i_preroll_end
)
856 VoutDisplayedPicture( p_vout
, p_pic
);
860 if( p_dec
->p_owner
->i_preroll_end
> 0 )
862 msg_Dbg( p_dec
, "End of video preroll" );
864 VoutFlushPicture( p_vout
);
866 p_dec
->p_owner
->i_preroll_end
= -1;
869 if( ( !p_dec
->p_owner
->p_packetizer
|| !p_dec
->p_owner
->p_packetizer
->pf_get_cc
) && p_dec
->pf_get_cc
)
870 DecoderGetCc( p_dec
, p_dec
);
872 vout_DatePicture( p_vout
, p_pic
, p_pic
->date
);
874 optimize_video_pts( p_dec
);
876 vout_DisplayPicture( p_vout
, p_pic
);
883 * \param p_dec the decoder object
884 * \param p_block the block to decode
885 * \return VLC_SUCCESS or an error code
887 static int DecoderDecode( decoder_t
*p_dec
, block_t
*p_block
)
889 decoder_owner_sys_t
*p_sys
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
890 const int i_rate
= p_block
? p_block
->i_rate
: INPUT_RATE_DEFAULT
;
892 if( p_block
&& p_block
->i_buffer
<= 0 )
894 block_Release( p_block
);
899 if( p_dec
->i_object_type
== VLC_OBJECT_PACKETIZER
)
901 block_t
*p_sout_block
;
903 while( ( p_sout_block
=
904 p_dec
->pf_packetize( p_dec
, p_block
? &p_block
: 0 ) ) )
906 if( !p_dec
->p_owner
->p_sout_input
)
908 es_format_Copy( &p_dec
->p_owner
->sout
, &p_dec
->fmt_out
);
910 p_dec
->p_owner
->sout
.i_group
= p_dec
->fmt_in
.i_group
;
911 p_dec
->p_owner
->sout
.i_id
= p_dec
->fmt_in
.i_id
;
912 if( p_dec
->fmt_in
.psz_language
)
914 if( p_dec
->p_owner
->sout
.psz_language
)
915 free( p_dec
->p_owner
->sout
.psz_language
);
916 p_dec
->p_owner
->sout
.psz_language
=
917 strdup( p_dec
->fmt_in
.psz_language
);
920 p_dec
->p_owner
->p_sout_input
=
921 sout_InputNew( p_dec
->p_owner
->p_sout
,
922 &p_dec
->p_owner
->sout
);
924 if( p_dec
->p_owner
->p_sout_input
== NULL
)
926 msg_Err( p_dec
, "cannot create packetizer output (%4.4s)",
927 (char *)&p_dec
->p_owner
->sout
.i_codec
);
928 p_dec
->b_error
= true;
930 while( p_sout_block
)
932 block_t
*p_next
= p_sout_block
->p_next
;
933 block_Release( p_sout_block
);
934 p_sout_block
= p_next
;
940 while( p_sout_block
)
942 block_t
*p_next
= p_sout_block
->p_next
;
944 p_sout_block
->p_next
= NULL
;
945 p_sout_block
->i_rate
= i_rate
;
947 sout_InputSendBuffer( p_dec
->p_owner
->p_sout_input
,
950 p_sout_block
= p_next
;
953 /* For now it's enough, as only sout impact on this flag */
954 if( p_dec
->p_owner
->p_sout
->i_out_pace_nocontrol
> 0 &&
955 p_dec
->p_owner
->p_input
->p
->b_out_pace_control
)
957 msg_Dbg( p_dec
, "switching to sync mode" );
958 p_dec
->p_owner
->p_input
->p
->b_out_pace_control
= false;
960 else if( p_dec
->p_owner
->p_sout
->i_out_pace_nocontrol
<= 0 &&
961 !p_dec
->p_owner
->p_input
->p
->b_out_pace_control
)
963 msg_Dbg( p_dec
, "switching to async mode" );
964 p_dec
->p_owner
->p_input
->p
->b_out_pace_control
= true;
970 if( p_dec
->fmt_in
.i_cat
== AUDIO_ES
)
973 DecoderUpdatePreroll( &p_dec
->p_owner
->i_preroll_end
, p_block
);
975 if( p_dec
->p_owner
->p_packetizer
)
977 block_t
*p_packetized_block
;
978 decoder_t
*p_packetizer
= p_dec
->p_owner
->p_packetizer
;
980 while( (p_packetized_block
=
981 p_packetizer
->pf_packetize( p_packetizer
, p_block
? &p_block
: NULL
)) )
983 if( p_packetizer
->fmt_out
.i_extra
&& !p_dec
->fmt_in
.i_extra
)
985 es_format_Clean( &p_dec
->fmt_in
);
986 es_format_Copy( &p_dec
->fmt_in
, &p_packetizer
->fmt_out
);
989 while( p_packetized_block
)
991 block_t
*p_next
= p_packetized_block
->p_next
;
992 p_packetized_block
->p_next
= NULL
;
993 p_packetized_block
->i_rate
= i_rate
;
995 DecoderDecodeAudio( p_dec
, p_packetized_block
);
997 p_packetized_block
= p_next
;
1003 DecoderDecodeAudio( p_dec
, p_block
);
1006 else if( p_dec
->fmt_in
.i_cat
== VIDEO_ES
)
1009 DecoderUpdatePreroll( &p_dec
->p_owner
->i_preroll_end
, p_block
);
1011 if( p_dec
->p_owner
->p_packetizer
)
1013 block_t
*p_packetized_block
;
1014 decoder_t
*p_packetizer
= p_dec
->p_owner
->p_packetizer
;
1016 while( (p_packetized_block
=
1017 p_packetizer
->pf_packetize( p_packetizer
, p_block
? &p_block
: NULL
)) )
1019 if( p_packetizer
->fmt_out
.i_extra
&& !p_dec
->fmt_in
.i_extra
)
1021 es_format_Clean( &p_dec
->fmt_in
);
1022 es_format_Copy( &p_dec
->fmt_in
, &p_packetizer
->fmt_out
);
1024 if( p_packetizer
->pf_get_cc
)
1025 DecoderGetCc( p_dec
, p_packetizer
);
1027 while( p_packetized_block
)
1029 block_t
*p_next
= p_packetized_block
->p_next
;
1030 p_packetized_block
->p_next
= NULL
;
1031 p_packetized_block
->i_rate
= i_rate
;
1033 DecoderDecodeVideo( p_dec
, p_packetized_block
);
1035 p_packetized_block
= p_next
;
1041 DecoderDecodeVideo( p_dec
, p_block
);
1044 else if( p_dec
->fmt_in
.i_cat
== SPU_ES
)
1046 input_thread_t
*p_input
= p_dec
->p_owner
->p_input
;
1047 vout_thread_t
*p_vout
;
1048 subpicture_t
*p_spu
;
1051 DecoderUpdatePreroll( &p_dec
->p_owner
->i_preroll_end
, p_block
);
1053 while( (p_spu
= p_dec
->pf_decode_sub( p_dec
, p_block
? &p_block
: NULL
) ) )
1055 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
1056 stats_UpdateInteger( p_dec
, p_input
->p
->counters
.p_decoded_sub
, 1, NULL
);
1057 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
1059 p_vout
= vlc_object_find( p_dec
, VLC_OBJECT_VOUT
, FIND_ANYWHERE
);
1060 if( p_vout
&& p_sys
->p_spu_vout
== p_vout
)
1062 /* Prerool does not work very well with subtitle */
1063 if( p_spu
->i_start
< p_dec
->p_owner
->i_preroll_end
&&
1064 ( p_spu
->i_stop
<= 0 || p_spu
->i_stop
< p_dec
->p_owner
->i_preroll_end
) )
1065 spu_DestroySubpicture( p_vout
->p_spu
, p_spu
);
1067 spu_DisplaySubpicture( p_vout
->p_spu
, p_spu
);
1071 msg_Warn( p_dec
, "no vout found, leaking subpicture" );
1074 vlc_object_release( p_vout
);
1079 msg_Err( p_dec
, "unknown ES format" );
1083 return p_dec
->b_error
? VLC_EGENERIC
: VLC_SUCCESS
;
1087 * Destroys a decoder object
1089 * \param p_dec the decoder object
1092 static void DeleteDecoder( decoder_t
* p_dec
)
1094 msg_Dbg( p_dec
, "killing decoder fourcc `%4.4s', %u PES in FIFO",
1095 (char*)&p_dec
->fmt_in
.i_codec
,
1096 (unsigned)block_FifoCount( p_dec
->p_owner
->p_fifo
) );
1098 /* Free all packets still in the decoder fifo. */
1099 block_FifoEmpty( p_dec
->p_owner
->p_fifo
);
1100 block_FifoRelease( p_dec
->p_owner
->p_fifo
);
1103 if( p_dec
->p_owner
->p_aout_input
)
1104 aout_DecDelete( p_dec
->p_owner
->p_aout
, p_dec
->p_owner
->p_aout_input
);
1105 if( p_dec
->p_owner
->p_aout
)
1107 vlc_object_release( p_dec
->p_owner
->p_aout
);
1108 p_dec
->p_owner
->p_aout
= NULL
;
1110 if( p_dec
->p_owner
->p_vout
)
1114 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
1115 /* Hack to make sure all the the pictures are freed by the decoder */
1116 for( i_pic
= 0; i_pic
< p_dec
->p_owner
->p_vout
->render
.i_pictures
;
1119 if( p_pic
->i_status
== RESERVED_PICTURE
)
1120 vout_DestroyPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1121 if( p_pic
->i_refcount
> 0 )
1122 vout_UnlinkPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1126 /* We are about to die. Reattach video output to p_vlc. */
1127 vout_Request( p_dec
, p_dec
->p_owner
->p_vout
, 0 );
1131 if( p_dec
->p_owner
->p_sout_input
)
1133 sout_InputDelete( p_dec
->p_owner
->p_sout_input
);
1134 es_format_Clean( &p_dec
->p_owner
->sout
);
1138 if( p_dec
->fmt_in
.i_cat
== SPU_ES
)
1140 vout_thread_t
*p_vout
;
1142 p_vout
= vlc_object_find( p_dec
, VLC_OBJECT_VOUT
, FIND_ANYWHERE
);
1145 spu_Control( p_vout
->p_spu
, SPU_CHANNEL_CLEAR
,
1146 p_dec
->p_owner
->i_spu_channel
);
1147 vlc_object_release( p_vout
);
1151 es_format_Clean( &p_dec
->fmt_in
);
1152 es_format_Clean( &p_dec
->fmt_out
);
1154 if( p_dec
->p_owner
->p_packetizer
)
1156 module_Unneed( p_dec
->p_owner
->p_packetizer
,
1157 p_dec
->p_owner
->p_packetizer
->p_module
);
1158 es_format_Clean( &p_dec
->p_owner
->p_packetizer
->fmt_in
);
1159 es_format_Clean( &p_dec
->p_owner
->p_packetizer
->fmt_out
);
1160 vlc_object_detach( p_dec
->p_owner
->p_packetizer
);
1161 vlc_object_release( p_dec
->p_owner
->p_packetizer
);
1164 vlc_mutex_destroy( &p_dec
->p_owner
->lock_cc
);
1166 vlc_object_detach( p_dec
);
1168 free( p_dec
->p_owner
);
1171 /*****************************************************************************
1172 * Buffers allocation callbacks for the decoders
1173 *****************************************************************************/
1174 static aout_buffer_t
*aout_new_buffer( decoder_t
*p_dec
, int i_samples
)
1176 decoder_owner_sys_t
*p_sys
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1177 aout_buffer_t
*p_buffer
;
1179 if( p_sys
->p_aout_input
!= NULL
&&
1180 ( p_dec
->fmt_out
.audio
.i_rate
!= p_sys
->audio
.i_rate
||
1181 p_dec
->fmt_out
.audio
.i_original_channels
!=
1182 p_sys
->audio
.i_original_channels
||
1183 p_dec
->fmt_out
.audio
.i_bytes_per_frame
!=
1184 p_sys
->audio
.i_bytes_per_frame
) )
1186 /* Parameters changed, restart the aout */
1187 aout_DecDelete( p_sys
->p_aout
, p_sys
->p_aout_input
);
1188 p_sys
->p_aout_input
= NULL
;
1191 if( p_sys
->p_aout_input
== NULL
)
1193 audio_sample_format_t format
;
1194 int i_force_dolby
= config_GetInt( p_dec
, "force-dolby-surround" );
1196 p_dec
->fmt_out
.audio
.i_format
= p_dec
->fmt_out
.i_codec
;
1197 p_sys
->audio
= p_dec
->fmt_out
.audio
;
1199 memcpy( &format
, &p_sys
->audio
, sizeof( audio_sample_format_t
) );
1200 if ( i_force_dolby
&& (format
.i_original_channels
&AOUT_CHAN_PHYSMASK
)
1201 == (AOUT_CHAN_LEFT
|AOUT_CHAN_RIGHT
) )
1203 if ( i_force_dolby
== 1 )
1205 format
.i_original_channels
= format
.i_original_channels
|
1206 AOUT_CHAN_DOLBYSTEREO
;
1208 else /* i_force_dolby == 2 */
1210 format
.i_original_channels
= format
.i_original_channels
&
1211 ~AOUT_CHAN_DOLBYSTEREO
;
1215 p_sys
->p_aout_input
=
1216 aout_DecNew( p_dec
, &p_sys
->p_aout
, &format
, &p_dec
->fmt_out
.audio_replay_gain
);
1217 if( p_sys
->p_aout_input
== NULL
)
1219 msg_Err( p_dec
, "failed to create audio output" );
1220 p_dec
->b_error
= true;
1223 p_dec
->fmt_out
.audio
.i_bytes_per_frame
=
1224 p_sys
->audio
.i_bytes_per_frame
;
1227 p_buffer
= aout_DecNewBuffer( p_sys
->p_aout_input
, i_samples
);
1232 static void aout_del_buffer( decoder_t
*p_dec
, aout_buffer_t
*p_buffer
)
1234 aout_DecDeleteBuffer( p_dec
->p_owner
->p_aout
,
1235 p_dec
->p_owner
->p_aout_input
, p_buffer
);
1238 static picture_t
*vout_new_buffer( decoder_t
*p_dec
)
1240 decoder_owner_sys_t
*p_sys
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1243 if( p_sys
->p_vout
== NULL
||
1244 p_dec
->fmt_out
.video
.i_width
!= p_sys
->video
.i_width
||
1245 p_dec
->fmt_out
.video
.i_height
!= p_sys
->video
.i_height
||
1246 p_dec
->fmt_out
.video
.i_chroma
!= p_sys
->video
.i_chroma
||
1247 p_dec
->fmt_out
.video
.i_aspect
!= p_sys
->video
.i_aspect
)
1249 if( !p_dec
->fmt_out
.video
.i_width
||
1250 !p_dec
->fmt_out
.video
.i_height
)
1252 /* Can't create a new vout without display size */
1256 if( !p_dec
->fmt_out
.video
.i_visible_width
||
1257 !p_dec
->fmt_out
.video
.i_visible_height
)
1259 if( p_dec
->fmt_in
.video
.i_visible_width
&&
1260 p_dec
->fmt_in
.video
.i_visible_height
)
1262 p_dec
->fmt_out
.video
.i_visible_width
=
1263 p_dec
->fmt_in
.video
.i_visible_width
;
1264 p_dec
->fmt_out
.video
.i_visible_height
=
1265 p_dec
->fmt_in
.video
.i_visible_height
;
1269 p_dec
->fmt_out
.video
.i_visible_width
=
1270 p_dec
->fmt_out
.video
.i_width
;
1271 p_dec
->fmt_out
.video
.i_visible_height
=
1272 p_dec
->fmt_out
.video
.i_height
;
1276 if( p_dec
->fmt_out
.video
.i_visible_height
== 1088 &&
1277 var_CreateGetBool( p_dec
, "hdtv-fix" ) )
1279 p_dec
->fmt_out
.video
.i_visible_height
= 1080;
1280 p_dec
->fmt_out
.video
.i_sar_num
*= 135;
1281 p_dec
->fmt_out
.video
.i_sar_den
*= 136;
1282 msg_Warn( p_dec
, "Fixing broken HDTV stream (display_height=1088)");
1285 if( !p_dec
->fmt_out
.video
.i_sar_num
||
1286 !p_dec
->fmt_out
.video
.i_sar_den
)
1288 p_dec
->fmt_out
.video
.i_sar_num
= p_dec
->fmt_out
.video
.i_aspect
*
1289 p_dec
->fmt_out
.video
.i_visible_height
;
1291 p_dec
->fmt_out
.video
.i_sar_den
= VOUT_ASPECT_FACTOR
*
1292 p_dec
->fmt_out
.video
.i_visible_width
;
1295 vlc_ureduce( &p_dec
->fmt_out
.video
.i_sar_num
,
1296 &p_dec
->fmt_out
.video
.i_sar_den
,
1297 p_dec
->fmt_out
.video
.i_sar_num
,
1298 p_dec
->fmt_out
.video
.i_sar_den
, 50000 );
1300 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
1301 p_sys
->video
= p_dec
->fmt_out
.video
;
1303 p_sys
->p_vout
= vout_Request( p_dec
, p_sys
->p_vout
,
1304 &p_dec
->fmt_out
.video
);
1305 if( p_sys
->p_vout
== NULL
)
1307 msg_Err( p_dec
, "failed to create video output" );
1308 p_dec
->b_error
= true;
1312 if( p_sys
->video
.i_rmask
)
1313 p_sys
->p_vout
->render
.i_rmask
= p_sys
->video
.i_rmask
;
1314 if( p_sys
->video
.i_gmask
)
1315 p_sys
->p_vout
->render
.i_gmask
= p_sys
->video
.i_gmask
;
1316 if( p_sys
->video
.i_bmask
)
1317 p_sys
->p_vout
->render
.i_bmask
= p_sys
->video
.i_bmask
;
1320 /* Get a new picture */
1321 while( !(p_pic
= vout_CreatePicture( p_sys
->p_vout
, 0, 0, 0 ) ) )
1323 int i_pic
, i_ready_pic
= 0;
1325 if( p_dec
->b_die
|| p_dec
->b_error
)
1330 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
1331 /* Check the decoder doesn't leak pictures */
1332 for( i_pic
= 0; i_pic
< p_dec
->p_owner
->p_vout
->render
.i_pictures
;
1335 if( p_pic
->i_status
== READY_PICTURE
)
1337 if( i_ready_pic
++ > 0 ) break;
1341 if( p_pic
->i_status
!= DISPLAYED_PICTURE
&&
1342 p_pic
->i_status
!= RESERVED_PICTURE
&&
1343 p_pic
->i_status
!= READY_PICTURE
) break;
1345 if( !p_pic
->i_refcount
&& p_pic
->i_status
!= RESERVED_PICTURE
)
1348 if( i_pic
== p_dec
->p_owner
->p_vout
->render
.i_pictures
)
1350 msg_Err( p_dec
, "decoder is leaking pictures, resetting the heap" );
1352 /* Just free all the pictures */
1353 for( i_pic
= 0; i_pic
< p_dec
->p_owner
->p_vout
->render
.i_pictures
;
1356 if( p_pic
->i_status
== RESERVED_PICTURE
)
1357 vout_DestroyPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1358 if( p_pic
->i_refcount
> 0 )
1359 vout_UnlinkPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1364 msleep( VOUT_OUTMEM_SLEEP
);
1370 static void vout_del_buffer( decoder_t
*p_dec
, picture_t
*p_pic
)
1372 VoutDisplayedPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1375 static void vout_link_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
1377 vout_LinkPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1380 static void vout_unlink_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
1382 vout_UnlinkPicture( p_dec
->p_owner
->p_vout
, p_pic
);
1385 static subpicture_t
*spu_new_buffer( decoder_t
*p_dec
)
1387 decoder_owner_sys_t
*p_sys
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1388 vout_thread_t
*p_vout
= NULL
;
1389 subpicture_t
*p_subpic
;
1390 int i_attempts
= 30;
1392 while( i_attempts
-- )
1394 if( p_dec
->b_die
|| p_dec
->b_error
) break;
1396 p_vout
= vlc_object_find( p_dec
, VLC_OBJECT_VOUT
, FIND_ANYWHERE
);
1399 msleep( VOUT_DISPLAY_DELAY
);
1404 msg_Warn( p_dec
, "no vout found, dropping subpicture" );
1408 if( p_sys
->p_spu_vout
!= p_vout
)
1410 spu_Control( p_vout
->p_spu
, SPU_CHANNEL_REGISTER
,
1411 &p_sys
->i_spu_channel
);
1412 p_sys
->p_spu_vout
= p_vout
;
1415 p_subpic
= spu_CreateSubpicture( p_vout
->p_spu
);
1418 p_subpic
->i_channel
= p_sys
->i_spu_channel
;
1421 vlc_object_release( p_vout
);
1426 static void spu_del_buffer( decoder_t
*p_dec
, subpicture_t
*p_subpic
)
1428 decoder_owner_sys_t
*p_sys
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1429 vout_thread_t
*p_vout
= NULL
;
1431 p_vout
= vlc_object_find( p_dec
, VLC_OBJECT_VOUT
, FIND_ANYWHERE
);
1432 if( !p_vout
|| p_sys
->p_spu_vout
!= p_vout
)
1435 vlc_object_release( p_vout
);
1436 msg_Warn( p_dec
, "no vout found, leaking subpicture" );
1440 spu_DestroySubpicture( p_vout
->p_spu
, p_subpic
);
1442 vlc_object_release( p_vout
);