1 /*****************************************************************************
2 * decoder.c: Functions for the management of decoders
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VLC authors and VideoLAN
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 it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * 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_dialog.h>
44 #include <vlc_modules.h>
46 #include "audio_output/aout_internal.h"
47 #include "stream_output/stream_output.h"
48 #include "input_internal.h"
54 #include "../video_output/vout_control.h"
56 struct decoder_owner_sys_t
58 int64_t i_preroll_end
;
60 input_thread_t
*p_input
;
61 input_resource_t
*p_resource
;
62 input_clock_t
*p_clock
;
65 vout_thread_t
*p_spu_vout
;
69 sout_instance_t
*p_sout
;
70 sout_packetizer_input_t
*p_sout_input
;
74 /* Some decoders require already packetized data (ie. not truncated) */
75 decoder_t
*p_packetizer
;
78 /* Current format in use by the output */
82 bool b_fmt_description
;
83 vlc_meta_t
*p_description
;
88 /* Lock for communication with decoder thread */
90 vlc_cond_t wait_request
;
91 vlc_cond_t wait_acknowledge
;
92 vlc_cond_t wait_fifo
; /* TODO: merge with wait_acknowledge */
94 /* -- These variables need locking on write(only) -- */
95 audio_output_t
*p_aout
;
97 vout_thread_t
*p_vout
;
99 /* -- Theses variables need locking on read *and* write -- */
124 decoder_t
*pp_decoder
[4];
131 /* Pictures which are DECODER_BOGUS_VIDEO_DELAY or more in advance probably have
132 * a bogus PTS and won't be displayed */
133 #define DECODER_BOGUS_VIDEO_DELAY ((mtime_t)(DEFAULT_PTS_DELAY * 30))
136 #define DECODER_SPU_VOUT_WAIT_DURATION ((int)(0.200*CLOCK_FREQ))
138 static void DecoderUpdateFormatLocked( decoder_t
*p_dec
)
140 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
142 vlc_assert_locked( &p_owner
->lock
);
144 es_format_Clean( &p_owner
->fmt
);
145 es_format_Copy( &p_owner
->fmt
, &p_dec
->fmt_out
);
147 /* Move p_description */
148 if( p_dec
->p_description
!= NULL
)
150 if( p_owner
->p_description
!= NULL
)
151 vlc_meta_Delete( p_owner
->p_description
);
152 p_owner
->p_description
= p_dec
->p_description
;
153 p_dec
->p_description
= NULL
;
156 p_owner
->b_fmt_description
= true;
159 static bool DecoderIsFlushing( decoder_t
*p_dec
)
161 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
164 vlc_mutex_lock( &p_owner
->lock
);
166 b_flushing
= p_owner
->b_flushing
;
168 vlc_mutex_unlock( &p_owner
->lock
);
173 static block_t
*DecoderBlockFlushNew()
175 block_t
*p_null
= block_Alloc( 128 );
179 p_null
->i_flags
|= BLOCK_FLAG_DISCONTINUITY
|
180 BLOCK_FLAG_CORRUPTED
|
181 BLOCK_FLAG_CORE_FLUSH
;
182 memset( p_null
->p_buffer
, 0, p_null
->i_buffer
);
187 /*****************************************************************************
188 * Buffers allocation callbacks for the decoders
189 *****************************************************************************/
190 static vout_thread_t
*aout_request_vout( void *p_private
,
191 vout_thread_t
*p_vout
, video_format_t
*p_fmt
, bool b_recyle
)
193 decoder_t
*p_dec
= p_private
;
194 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
195 input_thread_t
*p_input
= p_owner
->p_input
;
197 p_vout
= input_resource_RequestVout( p_owner
->p_resource
, p_vout
, p_fmt
, 1,
199 if( p_input
!= NULL
)
200 input_SendEventVout( p_input
);
205 static int aout_update_format( decoder_t
*p_dec
)
207 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
210 && !AOUT_FMTS_IDENTICAL(&p_dec
->fmt_out
.audio
, &p_owner
->fmt
.audio
) )
212 audio_output_t
*p_aout
= p_owner
->p_aout
;
214 /* Parameters changed, restart the aout */
215 vlc_mutex_lock( &p_owner
->lock
);
217 aout_DecDelete( p_owner
->p_aout
);
218 p_owner
->p_aout
= NULL
;
220 vlc_mutex_unlock( &p_owner
->lock
);
221 input_resource_PutAout( p_owner
->p_resource
, p_aout
);
224 if( p_owner
->p_aout
== NULL
)
226 p_dec
->fmt_out
.audio
.i_format
= p_dec
->fmt_out
.i_codec
;
228 audio_sample_format_t format
= p_dec
->fmt_out
.audio
;
229 aout_FormatPrepare( &format
);
231 const int i_force_dolby
= var_InheritInteger( p_dec
, "force-dolby-surround" );
233 (format
.i_original_channels
&AOUT_CHAN_PHYSMASK
) ==
234 (AOUT_CHAN_LEFT
|AOUT_CHAN_RIGHT
) )
236 if( i_force_dolby
== 1 )
238 format
.i_original_channels
= format
.i_original_channels
|
239 AOUT_CHAN_DOLBYSTEREO
;
241 else /* i_force_dolby == 2 */
243 format
.i_original_channels
= format
.i_original_channels
&
244 ~AOUT_CHAN_DOLBYSTEREO
;
248 aout_request_vout_t request_vout
= {
249 .pf_request_vout
= aout_request_vout
,
252 audio_output_t
*p_aout
;
254 p_aout
= input_resource_GetAout( p_owner
->p_resource
);
257 if( aout_DecNew( p_aout
, &format
,
258 &p_dec
->fmt_out
.audio_replay_gain
,
261 input_resource_PutAout( p_owner
->p_resource
, p_aout
);
266 vlc_mutex_lock( &p_owner
->lock
);
268 p_owner
->p_aout
= p_aout
;
270 DecoderUpdateFormatLocked( p_dec
);
271 aout_FormatPrepare( &p_owner
->fmt
.audio
);
273 if( unlikely(p_owner
->b_paused
) && p_aout
!= NULL
)
274 /* fake pause if needed */
275 aout_DecChangePause( p_aout
, true, mdate() );
277 vlc_mutex_unlock( &p_owner
->lock
);
279 if( p_owner
->p_input
!= NULL
)
280 input_SendEventAout( p_owner
->p_input
);
284 msg_Err( p_dec
, "failed to create audio output" );
285 p_dec
->b_error
= true;
289 p_dec
->fmt_out
.audio
.i_bytes_per_frame
=
290 p_owner
->fmt
.audio
.i_bytes_per_frame
;
291 p_dec
->fmt_out
.audio
.i_frame_length
=
292 p_owner
->fmt
.audio
.i_frame_length
;
297 static int vout_update_format( decoder_t
*p_dec
)
299 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
301 if( p_owner
->p_vout
== NULL
302 || p_dec
->fmt_out
.video
.i_width
!= p_owner
->fmt
.video
.i_width
303 || p_dec
->fmt_out
.video
.i_height
!= p_owner
->fmt
.video
.i_height
304 || p_dec
->fmt_out
.video
.i_visible_width
!= p_owner
->fmt
.video
.i_visible_width
305 || p_dec
->fmt_out
.video
.i_visible_height
!= p_owner
->fmt
.video
.i_visible_height
306 || p_dec
->fmt_out
.video
.i_x_offset
!= p_owner
->fmt
.video
.i_x_offset
307 || p_dec
->fmt_out
.video
.i_y_offset
!= p_owner
->fmt
.video
.i_y_offset
308 || p_dec
->fmt_out
.i_codec
!= p_owner
->fmt
.video
.i_chroma
309 || (int64_t)p_dec
->fmt_out
.video
.i_sar_num
* p_owner
->fmt
.video
.i_sar_den
!=
310 (int64_t)p_dec
->fmt_out
.video
.i_sar_den
* p_owner
->fmt
.video
.i_sar_num
||
311 p_dec
->fmt_out
.video
.orientation
!= p_owner
->fmt
.video
.orientation
)
313 vout_thread_t
*p_vout
;
315 if( !p_dec
->fmt_out
.video
.i_width
||
316 !p_dec
->fmt_out
.video
.i_height
)
318 /* Can't create a new vout without display size */
322 video_format_t fmt
= p_dec
->fmt_out
.video
;
323 fmt
.i_chroma
= p_dec
->fmt_out
.i_codec
;
325 if( vlc_fourcc_IsYUV( fmt
.i_chroma
) )
327 const vlc_chroma_description_t
*dsc
= vlc_fourcc_GetChromaDescription( fmt
.i_chroma
);
328 for( unsigned int i
= 0; dsc
&& i
< dsc
->plane_count
; i
++ )
330 while( fmt
.i_width
% dsc
->p
[i
].w
.den
)
332 while( fmt
.i_height
% dsc
->p
[i
].h
.den
)
337 if( !fmt
.i_visible_width
|| !fmt
.i_visible_height
)
339 if( p_dec
->fmt_in
.video
.i_visible_width
&&
340 p_dec
->fmt_in
.video
.i_visible_height
)
342 fmt
.i_visible_width
= p_dec
->fmt_in
.video
.i_visible_width
;
343 fmt
.i_visible_height
= p_dec
->fmt_in
.video
.i_visible_height
;
344 fmt
.i_x_offset
= p_dec
->fmt_in
.video
.i_x_offset
;
345 fmt
.i_y_offset
= p_dec
->fmt_in
.video
.i_y_offset
;
349 fmt
.i_visible_width
= fmt
.i_width
;
350 fmt
.i_visible_height
= fmt
.i_height
;
356 if( fmt
.i_visible_height
== 1088 &&
357 var_CreateGetBool( p_dec
, "hdtv-fix" ) )
359 fmt
.i_visible_height
= 1080;
360 if( !(fmt
.i_sar_num
% 136))
362 fmt
.i_sar_num
*= 135;
363 fmt
.i_sar_den
*= 136;
365 msg_Warn( p_dec
, "Fixing broken HDTV stream (display_height=1088)");
368 if( !fmt
.i_sar_num
|| !fmt
.i_sar_den
)
374 vlc_ureduce( &fmt
.i_sar_num
, &fmt
.i_sar_den
,
375 fmt
.i_sar_num
, fmt
.i_sar_den
, 50000 );
377 vlc_mutex_lock( &p_owner
->lock
);
379 p_vout
= p_owner
->p_vout
;
380 p_owner
->p_vout
= NULL
;
381 vlc_mutex_unlock( &p_owner
->lock
);
384 switch( p_dec
->fmt_in
.i_codec
)
388 case VLC_CODEC_DIRAC
: /* FIXME valid ? */
401 p_vout
= input_resource_RequestVout( p_owner
->p_resource
,
404 p_dec
->i_extra_picture_buffers
+ 1,
406 vlc_mutex_lock( &p_owner
->lock
);
407 p_owner
->p_vout
= p_vout
;
409 DecoderUpdateFormatLocked( p_dec
);
410 p_owner
->fmt
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
411 vlc_mutex_unlock( &p_owner
->lock
);
413 if( p_owner
->p_input
!= NULL
)
414 input_SendEventVout( p_owner
->p_input
);
417 msg_Err( p_dec
, "failed to create video output" );
424 static picture_t
*vout_new_buffer( decoder_t
*p_dec
)
426 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
430 if( DecoderIsFlushing( p_dec
) || p_dec
->b_error
)
433 picture_t
*p_picture
= vout_GetPicture( p_owner
->p_vout
);
437 /* FIXME add a vout_WaitPictureAvailable (timedwait) */
438 msleep( VOUT_OUTMEM_SLEEP
);
442 static subpicture_t
*spu_new_buffer( decoder_t
*p_dec
,
443 const subpicture_updater_t
*p_updater
)
445 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
446 vout_thread_t
*p_vout
= NULL
;
447 subpicture_t
*p_subpic
;
450 while( i_attempts
-- )
452 if( DecoderIsFlushing( p_dec
) || p_dec
->b_error
)
455 p_vout
= input_resource_HoldVout( p_owner
->p_resource
);
459 msleep( DECODER_SPU_VOUT_WAIT_DURATION
);
464 msg_Warn( p_dec
, "no vout found, dropping subpicture" );
468 if( p_owner
->p_spu_vout
!= p_vout
)
470 p_owner
->i_spu_channel
= vout_RegisterSubpictureChannel( p_vout
);
471 p_owner
->i_spu_order
= 0;
472 p_owner
->p_spu_vout
= p_vout
;
475 p_subpic
= subpicture_New( p_updater
);
478 p_subpic
->i_channel
= p_owner
->i_spu_channel
;
479 p_subpic
->i_order
= p_owner
->i_spu_order
++;
480 p_subpic
->b_subtitle
= true;
483 vlc_object_release( p_vout
);
488 static int DecoderGetInputAttachments( decoder_t
*p_dec
,
489 input_attachment_t
***ppp_attachment
,
492 input_thread_t
*p_input
= p_dec
->p_owner
->p_input
;
494 if( unlikely(p_input
== NULL
) )
496 return input_Control( p_input
, INPUT_GET_ATTACHMENTS
,
497 ppp_attachment
, pi_attachment
);
500 static mtime_t
DecoderGetDisplayDate( decoder_t
*p_dec
, mtime_t i_ts
)
502 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
504 vlc_mutex_lock( &p_owner
->lock
);
505 if( p_owner
->b_waiting
|| p_owner
->b_paused
)
506 i_ts
= VLC_TS_INVALID
;
507 vlc_mutex_unlock( &p_owner
->lock
);
509 if( !p_owner
->p_clock
|| i_ts
<= VLC_TS_INVALID
)
512 if( input_clock_ConvertTS( VLC_OBJECT(p_dec
), p_owner
->p_clock
, NULL
, &i_ts
, NULL
, INT64_MAX
) ) {
513 msg_Err(p_dec
, "Could not get display date for timestamp %"PRId64
"", i_ts
);
514 return VLC_TS_INVALID
;
520 static int DecoderGetDisplayRate( decoder_t
*p_dec
)
522 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
524 if( !p_owner
->p_clock
)
525 return INPUT_RATE_DEFAULT
;
526 return input_clock_GetRate( p_owner
->p_clock
);
529 /*****************************************************************************
531 *****************************************************************************/
532 picture_t
*decoder_NewPicture( decoder_t
*p_decoder
)
534 if( decoder_UpdateVideoFormat( p_decoder
) )
537 picture_t
*p_picture
= p_decoder
->pf_vout_buffer_new( p_decoder
);
539 msg_Warn( p_decoder
, "can't get output picture" );
543 block_t
*decoder_NewAudioBuffer( decoder_t
*dec
, int samples
)
545 if( decoder_UpdateAudioFormat( dec
) )
548 size_t length
= samples
* dec
->fmt_out
.audio
.i_bytes_per_frame
549 / dec
->fmt_out
.audio
.i_frame_length
;
550 block_t
*block
= block_Alloc( length
);
551 if( likely(block
!= NULL
) )
553 block
->i_nb_samples
= samples
;
554 block
->i_pts
= block
->i_length
= 0;
559 subpicture_t
*decoder_NewSubpicture( decoder_t
*p_decoder
,
560 const subpicture_updater_t
*p_dyn
)
562 subpicture_t
*p_subpicture
= p_decoder
->pf_spu_buffer_new( p_decoder
, p_dyn
);
564 msg_Warn( p_decoder
, "can't get output subpicture" );
568 /* decoder_GetInputAttachments:
570 int decoder_GetInputAttachments( decoder_t
*p_dec
,
571 input_attachment_t
***ppp_attachment
,
574 if( !p_dec
->pf_get_attachments
)
577 return p_dec
->pf_get_attachments( p_dec
, ppp_attachment
, pi_attachment
);
579 /* decoder_GetDisplayDate:
581 mtime_t
decoder_GetDisplayDate( decoder_t
*p_dec
, mtime_t i_ts
)
583 if( !p_dec
->pf_get_display_date
)
584 return VLC_TS_INVALID
;
586 return p_dec
->pf_get_display_date( p_dec
, i_ts
);
588 /* decoder_GetDisplayRate:
590 int decoder_GetDisplayRate( decoder_t
*p_dec
)
592 if( !p_dec
->pf_get_display_rate
)
593 return INPUT_RATE_DEFAULT
;
595 return p_dec
->pf_get_display_rate( p_dec
);
598 static bool DecoderWaitUnblock( decoder_t
*p_dec
)
600 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
602 vlc_assert_locked( &p_owner
->lock
);
606 if( p_owner
->b_flushing
)
608 if( p_owner
->b_paused
)
610 if( p_owner
->b_waiting
&& !p_owner
->b_has_data
)
612 if( p_owner
->pause
.i_ignore
> 0 )
614 p_owner
->pause
.i_ignore
--;
620 if( !p_owner
->b_waiting
|| !p_owner
->b_has_data
)
623 vlc_cond_wait( &p_owner
->wait_request
, &p_owner
->lock
);
626 return p_owner
->b_flushing
;
629 static inline void DecoderUpdatePreroll( int64_t *pi_preroll
, const block_t
*p
)
631 if( p
->i_flags
& (BLOCK_FLAG_PREROLL
|BLOCK_FLAG_DISCONTINUITY
) )
632 *pi_preroll
= INT64_MAX
;
633 else if( p
->i_dts
> VLC_TS_INVALID
)
634 *pi_preroll
= __MIN( *pi_preroll
, p
->i_dts
);
635 else if( p
->i_pts
> VLC_TS_INVALID
)
636 *pi_preroll
= __MIN( *pi_preroll
, p
->i_pts
);
639 static void DecoderFixTs( decoder_t
*p_dec
, mtime_t
*pi_ts0
, mtime_t
*pi_ts1
,
640 mtime_t
*pi_duration
, int *pi_rate
, mtime_t i_ts_bound
)
642 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
643 input_clock_t
*p_clock
= p_owner
->p_clock
;
645 vlc_assert_locked( &p_owner
->lock
);
647 const mtime_t i_es_delay
= p_owner
->i_ts_delay
;
652 const bool b_ephemere
= pi_ts1
&& *pi_ts0
== *pi_ts1
;
655 if( *pi_ts0
> VLC_TS_INVALID
)
657 *pi_ts0
+= i_es_delay
;
658 if( pi_ts1
&& *pi_ts1
> VLC_TS_INVALID
)
659 *pi_ts1
+= i_es_delay
;
660 if( i_ts_bound
!= INT64_MAX
)
661 i_ts_bound
+= i_es_delay
;
662 if( input_clock_ConvertTS( VLC_OBJECT(p_dec
), p_clock
, &i_rate
, pi_ts0
, pi_ts1
, i_ts_bound
) ) {
664 msg_Err(p_dec
, "Could not convert timestamps %"PRId64
665 ", %"PRId64
"", *pi_ts0
, *pi_ts1
);
667 msg_Err(p_dec
, "Could not convert timestamp %"PRId64
, *pi_ts0
);
668 *pi_ts0
= VLC_TS_INVALID
;
673 i_rate
= input_clock_GetRate( p_clock
);
676 /* Do not create ephemere data because of rounding errors */
677 if( !b_ephemere
&& pi_ts1
&& *pi_ts0
== *pi_ts1
)
681 *pi_duration
= ( *pi_duration
* i_rate
+ INPUT_RATE_DEFAULT
-1 )
682 / INPUT_RATE_DEFAULT
;
689 * If *pb_reject, it does nothing, otherwise it waits for the given
690 * deadline or a flush request (in which case it set *pi_reject to true.
692 static void DecoderWaitDate( decoder_t
*p_dec
,
693 bool *pb_reject
, mtime_t i_deadline
)
695 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
697 vlc_assert_locked( &p_owner
->lock
);
699 if( *pb_reject
|| i_deadline
< 0 )
704 if( p_owner
->b_flushing
)
710 while( vlc_cond_timedwait( &p_owner
->wait_request
, &p_owner
->lock
,
717 static int DecoderPlaySout( decoder_t
*p_dec
, block_t
*p_sout_block
)
719 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
721 assert( p_owner
->p_clock
);
722 assert( !p_sout_block
->p_next
);
724 vlc_mutex_lock( &p_owner
->lock
);
726 if( p_owner
->b_waiting
)
728 p_owner
->b_has_data
= true;
729 vlc_cond_signal( &p_owner
->wait_acknowledge
);
732 bool b_reject
= DecoderWaitUnblock( p_dec
);
734 DecoderFixTs( p_dec
, &p_sout_block
->i_dts
, &p_sout_block
->i_pts
,
735 &p_sout_block
->i_length
, NULL
, INT64_MAX
);
737 vlc_mutex_unlock( &p_owner
->lock
);
741 /* FIXME --VLC_TS_INVALID inspect stream_output*/
742 return sout_InputSendBuffer( p_owner
->p_sout_input
, p_sout_block
);
746 block_Release( p_sout_block
);
751 /* This function process a block for sout
753 static void DecoderProcessSout( decoder_t
*p_dec
, block_t
*p_block
)
755 decoder_owner_sys_t
*p_owner
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
756 block_t
*p_sout_block
;
758 while( ( p_sout_block
=
759 p_dec
->pf_packetize( p_dec
, p_block
? &p_block
: NULL
) ) )
761 if( p_owner
->p_sout_input
== NULL
)
763 vlc_mutex_lock( &p_owner
->lock
);
764 DecoderUpdateFormatLocked( p_dec
);
765 vlc_mutex_unlock( &p_owner
->lock
);
767 p_owner
->fmt
.i_group
= p_dec
->fmt_in
.i_group
;
768 p_owner
->fmt
.i_id
= p_dec
->fmt_in
.i_id
;
769 if( p_dec
->fmt_in
.psz_language
)
771 free( p_owner
->fmt
.psz_language
);
772 p_owner
->fmt
.psz_language
=
773 strdup( p_dec
->fmt_in
.psz_language
);
776 p_owner
->p_sout_input
=
777 sout_InputNew( p_owner
->p_sout
, &p_owner
->fmt
);
779 if( p_owner
->p_sout_input
== NULL
)
781 msg_Err( p_dec
, "cannot create packetizer output (%4.4s)",
782 (char *)&p_owner
->fmt
.i_codec
);
783 p_dec
->b_error
= true;
785 block_ChainRelease(p_sout_block
);
790 while( p_sout_block
)
792 block_t
*p_next
= p_sout_block
->p_next
;
794 p_sout_block
->p_next
= NULL
;
796 if( DecoderPlaySout( p_dec
, p_sout_block
) == VLC_EGENERIC
)
798 msg_Err( p_dec
, "cannot continue streaming due to errors" );
800 p_dec
->b_error
= true;
803 block_ChainRelease( p_next
);
807 p_sout_block
= p_next
;
813 static void DecoderGetCc( decoder_t
*p_dec
, decoder_t
*p_dec_cc
)
815 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
818 bool b_processed
= false;
822 assert( p_dec_cc
->pf_get_cc
!= NULL
);
824 /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
825 if( !p_owner
->cc
.b_supported
)
828 p_cc
= p_dec_cc
->pf_get_cc( p_dec_cc
, pb_present
);
832 vlc_mutex_lock( &p_owner
->lock
);
833 for( i
= 0, i_cc_decoder
= 0; i
< 4; i
++ )
835 p_owner
->cc
.pb_present
[i
] |= pb_present
[i
];
836 if( p_owner
->cc
.pp_decoder
[i
] )
840 for( i
= 0; i
< 4; i
++ )
842 if( !p_owner
->cc
.pp_decoder
[i
] )
845 block_FifoPut( p_owner
->cc
.pp_decoder
[i
]->p_owner
->p_fifo
,
846 (i_cc_decoder
> 1) ? block_Duplicate(p_cc
) : p_cc
);
851 vlc_mutex_unlock( &p_owner
->lock
);
854 block_Release( p_cc
);
857 static void DecoderPlayVideo( decoder_t
*p_dec
, picture_t
*p_picture
,
858 int *pi_played_sum
, int *pi_lost_sum
)
860 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
861 vout_thread_t
*p_vout
= p_owner
->p_vout
;
863 if( p_picture
->date
<= VLC_TS_INVALID
)
865 msg_Warn( p_dec
, "non-dated video buffer received" );
867 picture_Release( p_picture
);
872 vlc_mutex_lock( &p_owner
->lock
);
874 if( p_owner
->b_waiting
&& !p_owner
->b_first
)
876 p_owner
->b_has_data
= true;
877 vlc_cond_signal( &p_owner
->wait_acknowledge
);
879 bool b_first_after_wait
= p_owner
->b_waiting
&& p_owner
->b_has_data
;
881 bool b_reject
= DecoderWaitUnblock( p_dec
);
883 if( !b_reject
&& p_owner
->b_waiting
)
885 assert( p_owner
->b_first
);
886 msg_Dbg( p_dec
, "Received first picture" );
887 p_owner
->b_first
= false;
888 p_picture
->b_force
= true;
891 const bool b_dated
= p_picture
->date
> VLC_TS_INVALID
;
892 int i_rate
= INPUT_RATE_DEFAULT
;
893 DecoderFixTs( p_dec
, &p_picture
->date
, NULL
, NULL
,
894 &i_rate
, DECODER_BOGUS_VIDEO_DELAY
);
896 vlc_mutex_unlock( &p_owner
->lock
);
899 if( !p_picture
->b_force
&& p_picture
->date
<= VLC_TS_INVALID
) // FIXME --VLC_TS_INVALID verify video_output/*
904 if( i_rate
!= p_owner
->i_last_rate
|| b_first_after_wait
)
906 /* Be sure to not display old picture after our own */
907 vout_Flush( p_vout
, p_picture
->date
);
908 p_owner
->i_last_rate
= i_rate
;
910 vout_PutPicture( p_vout
, p_picture
);
915 msg_Warn( p_dec
, "early picture skipped" );
917 msg_Warn( p_dec
, "non-dated video buffer received" );
920 picture_Release( p_picture
);
924 vout_GetResetStatistic( p_vout
, &i_tmp_display
, &i_tmp_lost
);
926 *pi_played_sum
+= i_tmp_display
;
927 *pi_lost_sum
+= i_tmp_lost
;
930 static void DecoderDecodeVideo( decoder_t
*p_dec
, block_t
*p_block
)
932 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
938 while( (p_pic
= p_dec
->pf_decode_video( p_dec
, &p_block
)) )
940 vout_thread_t
*p_vout
= p_owner
->p_vout
;
941 if( DecoderIsFlushing( p_dec
) )
942 { /* It prevent freezing VLC in case of broken decoder */
943 picture_Release( p_pic
);
945 block_Release( p_block
);
951 if( p_owner
->i_preroll_end
> VLC_TS_INVALID
&& p_pic
->date
< p_owner
->i_preroll_end
)
953 picture_Release( p_pic
);
957 if( p_owner
->i_preroll_end
> VLC_TS_INVALID
)
959 msg_Dbg( p_dec
, "End of video preroll" );
961 vout_Flush( p_vout
, VLC_TS_INVALID
+1 );
963 p_owner
->i_preroll_end
= VLC_TS_INVALID
;
966 if( p_dec
->pf_get_cc
&&
967 ( !p_owner
->p_packetizer
|| !p_owner
->p_packetizer
->pf_get_cc
) )
968 DecoderGetCc( p_dec
, p_dec
);
970 DecoderPlayVideo( p_dec
, p_pic
, &i_displayed
, &i_lost
);
973 /* Update ugly stat */
974 input_thread_t
*p_input
= p_owner
->p_input
;
976 if( p_input
!= NULL
&& (i_decoded
> 0 || i_lost
> 0 || i_displayed
> 0) )
978 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
979 stats_Update( p_input
->p
->counters
.p_decoded_video
, i_decoded
, NULL
);
980 stats_Update( p_input
->p
->counters
.p_lost_pictures
, i_lost
, NULL
);
981 stats_Update( p_input
->p
->counters
.p_displayed_pictures
,
983 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
987 /* This function process a video block
989 static void DecoderProcessVideo( decoder_t
*p_dec
, block_t
*p_block
, bool b_flush
)
991 decoder_owner_sys_t
*p_owner
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
993 if( p_owner
->p_packetizer
)
995 block_t
*p_packetized_block
;
996 decoder_t
*p_packetizer
= p_owner
->p_packetizer
;
998 while( (p_packetized_block
=
999 p_packetizer
->pf_packetize( p_packetizer
, p_block
? &p_block
: NULL
)) )
1001 if( p_packetizer
->fmt_out
.i_extra
&& !p_dec
->fmt_in
.i_extra
)
1003 es_format_Clean( &p_dec
->fmt_in
);
1004 es_format_Copy( &p_dec
->fmt_in
, &p_packetizer
->fmt_out
);
1007 /* If the packetizer provides aspect ratio information, pass it
1008 * to the decoder as a hint if the decoder itself can't provide
1009 * it. Copy it regardless of the current value of the decoder input
1010 * format aspect ratio, to properly propagate changes in aspect
1012 if( p_packetizer
->fmt_out
.video
.i_sar_num
> 0 &&
1013 p_packetizer
->fmt_out
.video
.i_sar_den
> 0)
1015 p_dec
->fmt_in
.video
.i_sar_num
=
1016 p_packetizer
->fmt_out
.video
.i_sar_num
;
1017 p_dec
->fmt_in
.video
.i_sar_den
=
1018 p_packetizer
->fmt_out
.video
.i_sar_den
;
1021 if( p_packetizer
->pf_get_cc
)
1022 DecoderGetCc( p_dec
, p_packetizer
);
1024 while( p_packetized_block
)
1026 block_t
*p_next
= p_packetized_block
->p_next
;
1027 p_packetized_block
->p_next
= NULL
;
1029 DecoderDecodeVideo( p_dec
, p_packetized_block
);
1031 p_packetized_block
= p_next
;
1034 /* The packetizer does not output a block that tell the decoder to flush
1038 block_t
*p_null
= DecoderBlockFlushNew();
1040 DecoderDecodeVideo( p_dec
, p_null
);
1045 DecoderDecodeVideo( p_dec
, p_block
);
1048 if( b_flush
&& p_owner
->p_vout
)
1049 vout_Flush( p_owner
->p_vout
, VLC_TS_INVALID
+1 );
1052 static void DecoderPlayAudio( decoder_t
*p_dec
, block_t
*p_audio
,
1053 int *pi_played_sum
, int *pi_lost_sum
)
1055 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1058 if( p_audio
->i_pts
<= VLC_TS_INVALID
) // FIXME --VLC_TS_INVALID verify audio_output/*
1060 msg_Warn( p_dec
, "non-dated audio buffer received" );
1062 block_Release( p_audio
);
1067 vlc_mutex_lock( &p_owner
->lock
);
1069 if( p_owner
->b_waiting
)
1071 p_owner
->b_has_data
= true;
1072 vlc_cond_signal( &p_owner
->wait_acknowledge
);
1075 bool b_reject
= DecoderWaitUnblock( p_dec
);
1076 bool b_paused
= p_owner
->b_paused
;
1079 int i_rate
= INPUT_RATE_DEFAULT
;
1081 DecoderFixTs( p_dec
, &p_audio
->i_pts
, NULL
, &p_audio
->i_length
,
1082 &i_rate
, AOUT_MAX_ADVANCE_TIME
);
1084 if( p_audio
->i_pts
<= VLC_TS_INVALID
1085 || i_rate
< INPUT_RATE_DEFAULT
/AOUT_MAX_INPUT_RATE
1086 || i_rate
> INPUT_RATE_DEFAULT
*AOUT_MAX_INPUT_RATE
)
1089 DecoderWaitDate( p_dec
, &b_reject
,
1090 p_audio
->i_pts
- AOUT_MAX_PREPARE_TIME
);
1092 if( unlikely(p_owner
->b_paused
!= b_paused
) )
1093 goto race
; /* race with input thread? retry... */
1095 audio_output_t
*p_aout
= p_owner
->p_aout
;
1096 if( p_aout
== NULL
)
1101 assert( !p_owner
->b_paused
);
1102 if( !aout_DecPlay( p_aout
, p_audio
, i_rate
) )
1103 *pi_played_sum
+= 1;
1104 *pi_lost_sum
+= aout_DecGetResetLost( p_aout
);
1108 msg_Dbg( p_dec
, "discarded audio buffer" );
1110 block_Release( p_audio
);
1112 vlc_mutex_unlock( &p_owner
->lock
);
1115 static void DecoderDecodeAudio( decoder_t
*p_dec
, block_t
*p_block
)
1117 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1118 block_t
*p_aout_buf
;
1123 while( (p_aout_buf
= p_dec
->pf_decode_audio( p_dec
, &p_block
)) )
1125 if( DecoderIsFlushing( p_dec
) )
1127 /* It prevent freezing VLC in case of broken decoder */
1128 block_Release( p_aout_buf
);
1130 block_Release( p_block
);
1135 if( p_owner
->i_preroll_end
> VLC_TS_INVALID
&&
1136 p_aout_buf
->i_pts
< p_owner
->i_preroll_end
)
1138 block_Release( p_aout_buf
);
1142 if( p_owner
->i_preroll_end
> VLC_TS_INVALID
)
1144 msg_Dbg( p_dec
, "End of audio preroll" );
1145 if( p_owner
->p_aout
)
1146 aout_DecFlush( p_owner
->p_aout
, false );
1148 p_owner
->i_preroll_end
= VLC_TS_INVALID
;
1151 DecoderPlayAudio( p_dec
, p_aout_buf
, &i_played
, &i_lost
);
1154 /* Update ugly stat */
1155 input_thread_t
*p_input
= p_owner
->p_input
;
1157 if( p_input
!= NULL
&& (i_decoded
> 0 || i_lost
> 0 || i_played
> 0) )
1159 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
1160 stats_Update( p_input
->p
->counters
.p_lost_abuffers
, i_lost
, NULL
);
1161 stats_Update( p_input
->p
->counters
.p_played_abuffers
, i_played
, NULL
);
1162 stats_Update( p_input
->p
->counters
.p_decoded_audio
, i_decoded
, NULL
);
1163 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
1167 /* This function process a audio block
1169 static void DecoderProcessAudio( decoder_t
*p_dec
, block_t
*p_block
, bool b_flush
)
1171 decoder_owner_sys_t
*p_owner
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1173 if( p_owner
->p_packetizer
)
1175 block_t
*p_packetized_block
;
1176 decoder_t
*p_packetizer
= p_owner
->p_packetizer
;
1178 while( (p_packetized_block
=
1179 p_packetizer
->pf_packetize( p_packetizer
, p_block
? &p_block
: NULL
)) )
1181 if( p_packetizer
->fmt_out
.i_extra
&& !p_dec
->fmt_in
.i_extra
)
1183 es_format_Clean( &p_dec
->fmt_in
);
1184 es_format_Copy( &p_dec
->fmt_in
, &p_packetizer
->fmt_out
);
1187 while( p_packetized_block
)
1189 block_t
*p_next
= p_packetized_block
->p_next
;
1190 p_packetized_block
->p_next
= NULL
;
1192 DecoderDecodeAudio( p_dec
, p_packetized_block
);
1194 p_packetized_block
= p_next
;
1197 /* The packetizer does not output a block that tell the decoder to flush
1201 block_t
*p_null
= DecoderBlockFlushNew();
1203 DecoderDecodeAudio( p_dec
, p_null
);
1208 DecoderDecodeAudio( p_dec
, p_block
);
1211 if( b_flush
&& p_owner
->p_aout
)
1212 aout_DecFlush( p_owner
->p_aout
, false );
1215 static void DecoderPlaySpu( decoder_t
*p_dec
, subpicture_t
*p_subpic
)
1217 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1218 vout_thread_t
*p_vout
= p_owner
->p_spu_vout
;
1221 if( p_subpic
->i_start
<= VLC_TS_INVALID
)
1223 msg_Warn( p_dec
, "non-dated spu buffer received" );
1224 subpicture_Delete( p_subpic
);
1229 vlc_mutex_lock( &p_owner
->lock
);
1231 if( p_owner
->b_waiting
)
1233 p_owner
->b_has_data
= true;
1234 vlc_cond_signal( &p_owner
->wait_acknowledge
);
1237 bool b_reject
= DecoderWaitUnblock( p_dec
);
1239 DecoderFixTs( p_dec
, &p_subpic
->i_start
, &p_subpic
->i_stop
, NULL
,
1242 if( p_subpic
->i_start
<= VLC_TS_INVALID
)
1245 DecoderWaitDate( p_dec
, &b_reject
,
1246 p_subpic
->i_start
- SPU_MAX_PREPARE_TIME
);
1247 vlc_mutex_unlock( &p_owner
->lock
);
1250 vout_PutSubpicture( p_vout
, p_subpic
);
1252 subpicture_Delete( p_subpic
);
1255 /* This function process a subtitle block
1257 static void DecoderProcessSpu( decoder_t
*p_dec
, block_t
*p_block
, bool b_flush
)
1259 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1261 input_thread_t
*p_input
= p_owner
->p_input
;
1262 vout_thread_t
*p_vout
;
1263 subpicture_t
*p_spu
;
1265 while( (p_spu
= p_dec
->pf_decode_sub( p_dec
, p_block
? &p_block
: NULL
) ) )
1267 if( p_input
!= NULL
)
1269 vlc_mutex_lock( &p_input
->p
->counters
.counters_lock
);
1270 stats_Update( p_input
->p
->counters
.p_decoded_sub
, 1, NULL
);
1271 vlc_mutex_unlock( &p_input
->p
->counters
.counters_lock
);
1274 p_vout
= input_resource_HoldVout( p_owner
->p_resource
);
1275 if( p_vout
&& p_owner
->p_spu_vout
== p_vout
)
1277 /* Preroll does not work very well with subtitle */
1278 if( p_spu
->i_start
> VLC_TS_INVALID
&&
1279 p_spu
->i_start
< p_owner
->i_preroll_end
&&
1280 ( p_spu
->i_stop
<= VLC_TS_INVALID
|| p_spu
->i_stop
< p_owner
->i_preroll_end
) )
1282 subpicture_Delete( p_spu
);
1286 DecoderPlaySpu( p_dec
, p_spu
);
1291 subpicture_Delete( p_spu
);
1294 vlc_object_release( p_vout
);
1297 if( b_flush
&& p_owner
->p_spu_vout
)
1299 p_vout
= input_resource_HoldVout( p_owner
->p_resource
);
1301 if( p_vout
&& p_owner
->p_spu_vout
== p_vout
)
1302 vout_FlushSubpictureChannel( p_vout
, p_owner
->i_spu_channel
);
1305 vlc_object_release( p_vout
);
1310 static void DecoderProcessOnFlush( decoder_t
*p_dec
)
1312 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1314 vlc_mutex_lock( &p_owner
->lock
);
1316 if( p_owner
->b_flushing
)
1318 p_owner
->b_flushing
= false;
1319 vlc_cond_signal( &p_owner
->wait_acknowledge
);
1321 vlc_mutex_unlock( &p_owner
->lock
);
1327 * \param p_dec the decoder object
1328 * \param p_block the block to decode
1329 * \return VLC_SUCCESS or an error code
1331 static void DecoderProcess( decoder_t
*p_dec
, block_t
*p_block
)
1333 decoder_owner_sys_t
*p_owner
= (decoder_owner_sys_t
*)p_dec
->p_owner
;
1334 const bool b_flush_request
= p_block
&& (p_block
->i_flags
& BLOCK_FLAG_CORE_FLUSH
);
1336 if( p_dec
->b_error
)
1339 block_Release( p_block
);
1343 if( p_block
&& p_block
->i_buffer
<= 0 )
1345 assert( !b_flush_request
);
1346 block_Release( p_block
);
1351 if( p_owner
->b_packetizer
)
1354 p_block
->i_flags
&= ~BLOCK_FLAG_CORE_PRIVATE_MASK
;
1356 DecoderProcessSout( p_dec
, p_block
);
1361 bool b_flush
= false;
1365 const bool b_flushing
= p_owner
->i_preroll_end
== INT64_MAX
;
1366 DecoderUpdatePreroll( &p_owner
->i_preroll_end
, p_block
);
1368 b_flush
= !b_flushing
&& b_flush_request
;
1370 p_block
->i_flags
&= ~BLOCK_FLAG_CORE_PRIVATE_MASK
;
1373 if( p_dec
->fmt_out
.i_cat
== AUDIO_ES
)
1375 DecoderProcessAudio( p_dec
, p_block
, b_flush
);
1377 else if( p_dec
->fmt_out
.i_cat
== VIDEO_ES
)
1379 DecoderProcessVideo( p_dec
, p_block
, b_flush
);
1381 else if( p_dec
->fmt_out
.i_cat
== SPU_ES
)
1383 DecoderProcessSpu( p_dec
, p_block
, b_flush
);
1387 msg_Err( p_dec
, "unknown ES format" );
1388 p_dec
->b_error
= true;
1394 if( b_flush_request
)
1395 DecoderProcessOnFlush( p_dec
);
1400 * The decoding main loop
1402 * \param p_dec the decoder
1404 static void *DecoderThread( void *p_data
)
1406 decoder_t
*p_dec
= (decoder_t
*)p_data
;
1407 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1409 /* The decoder's main loop */
1410 vlc_mutex_lock( &p_owner
->lock
);
1415 vlc_fifo_Lock( p_owner
->p_fifo
);
1416 vlc_cond_signal( &p_owner
->wait_acknowledge
);
1417 vlc_mutex_unlock( &p_owner
->lock
);
1418 vlc_fifo_CleanupPush( p_owner
->p_fifo
);
1420 vlc_cond_signal( &p_owner
->wait_fifo
);
1422 while( vlc_fifo_IsEmpty( p_owner
->p_fifo
) )
1424 if( p_owner
->b_draining
)
1425 { /* We have emptied the FIFO and there is a pending request to
1426 * drain. Pass p_block = NULL to decoder just once. */
1427 p_owner
->b_draining
= false;
1431 p_owner
->b_idle
= true;
1432 vlc_fifo_Wait( p_owner
->p_fifo
);
1433 /* Make sure there is no cancellation point other than this one^^.
1434 * If you need one, be sure to push cleanup of p_block. */
1435 p_owner
->b_idle
= false;
1438 p_block
= vlc_fifo_DequeueUnlocked( p_owner
->p_fifo
);
1440 vlc_fifo_Unlock( p_owner
->p_fifo
);
1442 int canc
= vlc_savecancel();
1443 DecoderProcess( p_dec
, p_block
);
1445 vlc_mutex_lock( &p_owner
->lock
);
1446 if( p_block
== NULL
)
1447 { /* Draining: the decoder is drained and all decoded buffers are
1448 * queued to the output at this point. Now drain the output. */
1449 if( p_owner
->p_aout
!= NULL
)
1450 aout_DecFlush( p_owner
->p_aout
, true );
1452 p_owner
->b_drained
= (p_block
== NULL
);
1454 vlc_restorecancel( canc
);
1456 vlc_assert_unreachable();
1460 * Create a decoder object
1462 * \param p_input the input thread
1463 * \param p_es the es descriptor
1464 * \param b_packetizer instead of a decoder
1465 * \return the decoder object
1467 static decoder_t
* CreateDecoder( vlc_object_t
*p_parent
,
1468 input_thread_t
*p_input
,
1469 const es_format_t
*fmt
, bool b_packetizer
,
1470 input_resource_t
*p_resource
,
1471 sout_instance_t
*p_sout
)
1474 decoder_owner_sys_t
*p_owner
;
1475 es_format_t null_es_format
;
1477 p_dec
= vlc_custom_create( p_parent
, sizeof( *p_dec
), "decoder" );
1481 p_dec
->b_frame_drop_allowed
= true;
1482 p_dec
->pf_decode_audio
= NULL
;
1483 p_dec
->pf_decode_video
= NULL
;
1484 p_dec
->pf_decode_sub
= NULL
;
1485 p_dec
->pf_get_cc
= NULL
;
1486 p_dec
->pf_packetize
= NULL
;
1488 /* Initialize the decoder */
1489 p_dec
->p_module
= NULL
;
1491 memset( &null_es_format
, 0, sizeof(es_format_t
) );
1492 es_format_Copy( &p_dec
->fmt_in
, fmt
);
1493 es_format_Copy( &p_dec
->fmt_out
, &null_es_format
);
1495 p_dec
->p_description
= NULL
;
1497 /* Allocate our private structure for the decoder */
1498 p_dec
->p_owner
= p_owner
= malloc( sizeof( decoder_owner_sys_t
) );
1499 if( unlikely(p_owner
== NULL
) )
1501 vlc_object_release( p_dec
);
1504 p_owner
->i_preroll_end
= VLC_TS_INVALID
;
1505 p_owner
->i_last_rate
= INPUT_RATE_DEFAULT
;
1506 p_owner
->p_input
= p_input
;
1507 p_owner
->p_resource
= p_resource
;
1508 p_owner
->p_aout
= NULL
;
1509 p_owner
->p_vout
= NULL
;
1510 p_owner
->p_spu_vout
= NULL
;
1511 p_owner
->i_spu_channel
= 0;
1512 p_owner
->i_spu_order
= 0;
1513 p_owner
->p_sout
= p_sout
;
1514 p_owner
->p_sout_input
= NULL
;
1515 p_owner
->p_packetizer
= NULL
;
1516 p_owner
->b_packetizer
= b_packetizer
;
1518 p_owner
->b_fmt_description
= false;
1519 p_owner
->p_description
= NULL
;
1521 p_owner
->b_paused
= false;
1522 p_owner
->pause
.i_date
= VLC_TS_INVALID
;
1523 p_owner
->pause
.i_ignore
= 0;
1525 p_owner
->b_waiting
= false;
1526 p_owner
->b_first
= true;
1527 p_owner
->b_has_data
= false;
1529 p_owner
->b_flushing
= false;
1530 p_owner
->b_draining
= false;
1531 p_owner
->b_drained
= false;
1532 p_owner
->b_idle
= false;
1534 es_format_Init( &p_owner
->fmt
, UNKNOWN_ES
, 0 );
1537 p_owner
->p_fifo
= block_FifoNew();
1538 if( unlikely(p_owner
->p_fifo
== NULL
) )
1541 vlc_object_release( p_dec
);
1545 vlc_mutex_init( &p_owner
->lock
);
1546 vlc_cond_init( &p_owner
->wait_request
);
1547 vlc_cond_init( &p_owner
->wait_acknowledge
);
1548 vlc_cond_init( &p_owner
->wait_fifo
);
1550 /* Set buffers allocation callbacks for the decoders */
1551 p_dec
->pf_aout_format_update
= aout_update_format
;
1552 p_dec
->pf_vout_format_update
= vout_update_format
;
1553 p_dec
->pf_vout_buffer_new
= vout_new_buffer
;
1554 p_dec
->pf_spu_buffer_new
= spu_new_buffer
;
1556 p_dec
->pf_get_attachments
= DecoderGetInputAttachments
;
1557 p_dec
->pf_get_display_date
= DecoderGetDisplayDate
;
1558 p_dec
->pf_get_display_rate
= DecoderGetDisplayRate
;
1560 /* Find a suitable decoder/packetizer module */
1562 p_dec
->p_module
= module_need( p_dec
, "decoder", "$codec", false );
1564 p_dec
->p_module
= module_need( p_dec
, "packetizer", "$packetizer", false );
1566 /* Check if decoder requires already packetized data */
1567 if( !b_packetizer
&&
1568 p_dec
->b_need_packetized
&& !p_dec
->fmt_in
.b_packetized
)
1570 p_owner
->p_packetizer
=
1571 vlc_custom_create( p_parent
, sizeof( decoder_t
), "packetizer" );
1572 if( p_owner
->p_packetizer
)
1574 es_format_Copy( &p_owner
->p_packetizer
->fmt_in
,
1577 es_format_Copy( &p_owner
->p_packetizer
->fmt_out
,
1580 p_owner
->p_packetizer
->p_module
=
1581 module_need( p_owner
->p_packetizer
,
1582 "packetizer", "$packetizer", false );
1584 if( !p_owner
->p_packetizer
->p_module
)
1586 es_format_Clean( &p_owner
->p_packetizer
->fmt_in
);
1587 vlc_object_release( p_owner
->p_packetizer
);
1588 p_owner
->p_packetizer
= NULL
;
1593 /* Copy ourself the input replay gain */
1594 if( fmt
->i_cat
== AUDIO_ES
)
1596 for( unsigned i
= 0; i
< AUDIO_REPLAY_GAIN_MAX
; i
++ )
1598 if( !p_dec
->fmt_out
.audio_replay_gain
.pb_peak
[i
] )
1600 p_dec
->fmt_out
.audio_replay_gain
.pb_peak
[i
] = fmt
->audio_replay_gain
.pb_peak
[i
];
1601 p_dec
->fmt_out
.audio_replay_gain
.pf_peak
[i
] = fmt
->audio_replay_gain
.pf_peak
[i
];
1603 if( !p_dec
->fmt_out
.audio_replay_gain
.pb_gain
[i
] )
1605 p_dec
->fmt_out
.audio_replay_gain
.pb_gain
[i
] = fmt
->audio_replay_gain
.pb_gain
[i
];
1606 p_dec
->fmt_out
.audio_replay_gain
.pf_gain
[i
] = fmt
->audio_replay_gain
.pf_gain
[i
];
1612 p_owner
->cc
.b_supported
= false;
1615 if( p_owner
->p_packetizer
&& p_owner
->p_packetizer
->pf_get_cc
)
1616 p_owner
->cc
.b_supported
= true;
1617 if( p_dec
->pf_get_cc
)
1618 p_owner
->cc
.b_supported
= true;
1621 for( unsigned i
= 0; i
< 4; i
++ )
1623 p_owner
->cc
.pb_present
[i
] = false;
1624 p_owner
->cc
.pp_decoder
[i
] = NULL
;
1626 p_owner
->i_ts_delay
= 0;
1631 * Destroys a decoder object
1633 * \param p_dec the decoder object
1636 static void DeleteDecoder( decoder_t
* p_dec
)
1638 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1640 msg_Dbg( p_dec
, "killing decoder fourcc `%4.4s', %u PES in FIFO",
1641 (char*)&p_dec
->fmt_in
.i_codec
,
1642 (unsigned)block_FifoCount( p_owner
->p_fifo
) );
1644 /* Free all packets still in the decoder fifo. */
1645 block_FifoRelease( p_owner
->p_fifo
);
1648 if( p_owner
->p_aout
)
1650 /* TODO: REVISIT gap-less audio */
1651 aout_DecFlush( p_owner
->p_aout
, false );
1652 aout_DecDelete( p_owner
->p_aout
);
1653 input_resource_PutAout( p_owner
->p_resource
, p_owner
->p_aout
);
1654 if( p_owner
->p_input
!= NULL
)
1655 input_SendEventAout( p_owner
->p_input
);
1657 if( p_owner
->p_vout
)
1659 /* Hack to make sure all the the pictures are freed by the decoder
1660 * and that the vout is not paused anymore */
1661 vout_Reset( p_owner
->p_vout
);
1664 input_resource_RequestVout( p_owner
->p_resource
, p_owner
->p_vout
, NULL
,
1666 if( p_owner
->p_input
!= NULL
)
1667 input_SendEventVout( p_owner
->p_input
);
1671 if( p_owner
->p_sout_input
)
1673 sout_InputDelete( p_owner
->p_sout_input
);
1676 es_format_Clean( &p_owner
->fmt
);
1678 if( p_dec
->fmt_out
.i_cat
== SPU_ES
)
1680 vout_thread_t
*p_vout
= input_resource_HoldVout( p_owner
->p_resource
);
1683 if( p_owner
->p_spu_vout
== p_vout
)
1684 vout_FlushSubpictureChannel( p_vout
, p_owner
->i_spu_channel
);
1685 vlc_object_release( p_vout
);
1689 es_format_Clean( &p_dec
->fmt_in
);
1690 es_format_Clean( &p_dec
->fmt_out
);
1691 if( p_dec
->p_description
)
1692 vlc_meta_Delete( p_dec
->p_description
);
1693 if( p_owner
->p_description
)
1694 vlc_meta_Delete( p_owner
->p_description
);
1696 if( p_owner
->p_packetizer
)
1698 module_unneed( p_owner
->p_packetizer
,
1699 p_owner
->p_packetizer
->p_module
);
1700 es_format_Clean( &p_owner
->p_packetizer
->fmt_in
);
1701 es_format_Clean( &p_owner
->p_packetizer
->fmt_out
);
1702 if( p_owner
->p_packetizer
->p_description
)
1703 vlc_meta_Delete( p_owner
->p_packetizer
->p_description
);
1704 vlc_object_release( p_owner
->p_packetizer
);
1707 vlc_cond_destroy( &p_owner
->wait_fifo
);
1708 vlc_cond_destroy( &p_owner
->wait_acknowledge
);
1709 vlc_cond_destroy( &p_owner
->wait_request
);
1710 vlc_mutex_destroy( &p_owner
->lock
);
1712 vlc_object_release( p_dec
);
1718 static void DecoderUnsupportedCodec( decoder_t
*p_dec
, vlc_fourcc_t codec
)
1720 if (codec
!= VLC_FOURCC('u','n','d','f')) {
1721 const char *desc
= vlc_fourcc_GetDescription(p_dec
->fmt_in
.i_cat
, codec
);
1722 if (!desc
|| !*desc
)
1723 desc
= N_("No description for this codec");
1724 msg_Err( p_dec
, "Codec `%4.4s' (%s) is not supported.", (char*)&codec
, desc
);
1725 dialog_Fatal( p_dec
, _("Codec not supported"),
1726 _("VLC could not decode the format \"%4.4s\" (%s)"),
1727 (char*)&codec
, desc
);
1729 msg_Err( p_dec
, "could not identify codec" );
1730 dialog_Fatal( p_dec
, _("Unidentified codec"),
1731 _("VLC could not identify the audio or video codec" ) );
1735 /* TODO: pass p_sout through p_resource? -- Courmisch */
1736 static decoder_t
*decoder_New( vlc_object_t
*p_parent
, input_thread_t
*p_input
,
1737 const es_format_t
*fmt
, input_clock_t
*p_clock
,
1738 input_resource_t
*p_resource
,
1739 sout_instance_t
*p_sout
)
1741 decoder_t
*p_dec
= NULL
;
1742 const char *psz_type
= p_sout
? N_("packetizer") : N_("decoder");
1745 /* Create the decoder configuration structure */
1746 p_dec
= CreateDecoder( p_parent
, p_input
, fmt
,
1747 p_sout
!= NULL
, p_resource
, p_sout
);
1750 msg_Err( p_parent
, "could not create %s", psz_type
);
1751 dialog_Fatal( p_parent
, _("Streaming / Transcoding failed"),
1752 _("VLC could not open the %s module."),
1753 vlc_gettext( psz_type
) );
1757 if( !p_dec
->p_module
)
1759 DecoderUnsupportedCodec( p_dec
, fmt
->i_codec
);
1761 DeleteDecoder( p_dec
);
1765 p_dec
->p_owner
->p_clock
= p_clock
;
1766 assert( p_dec
->fmt_out
.i_cat
!= UNKNOWN_ES
);
1768 if( p_dec
->fmt_out
.i_cat
== AUDIO_ES
)
1769 i_priority
= VLC_THREAD_PRIORITY_AUDIO
;
1771 i_priority
= VLC_THREAD_PRIORITY_VIDEO
;
1773 /* Spawn the decoder thread */
1774 if( vlc_clone( &p_dec
->p_owner
->thread
, DecoderThread
, p_dec
, i_priority
) )
1776 msg_Err( p_dec
, "cannot spawn decoder thread" );
1777 module_unneed( p_dec
, p_dec
->p_module
);
1778 DeleteDecoder( p_dec
);
1787 * Spawns a new decoder thread from the input thread
1789 * \param p_input the input thread
1790 * \param p_es the es descriptor
1791 * \return the spawned decoder object
1793 decoder_t
*input_DecoderNew( input_thread_t
*p_input
,
1794 es_format_t
*fmt
, input_clock_t
*p_clock
,
1795 sout_instance_t
*p_sout
)
1797 return decoder_New( VLC_OBJECT(p_input
), p_input
, fmt
, p_clock
,
1798 p_input
->p
->p_resource
, p_sout
);
1802 * Spawn a decoder thread outside of the input thread.
1804 decoder_t
*input_DecoderCreate( vlc_object_t
*p_parent
, const es_format_t
*fmt
,
1805 input_resource_t
*p_resource
)
1807 return decoder_New( p_parent
, NULL
, fmt
, NULL
, p_resource
, NULL
);
1812 * Kills a decoder thread and waits until it's finished
1814 * \param p_input the input thread
1815 * \param p_es the es descriptor
1818 void input_DecoderDelete( decoder_t
*p_dec
)
1820 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1822 vlc_cancel( p_owner
->thread
);
1824 /* Make sure we aren't paused/waiting/decoding anymore */
1825 vlc_mutex_lock( &p_owner
->lock
);
1826 p_owner
->b_paused
= false;
1827 p_owner
->b_waiting
= false;
1828 p_owner
->b_flushing
= true;
1829 vlc_cond_signal( &p_owner
->wait_request
);
1830 vlc_mutex_unlock( &p_owner
->lock
);
1832 vlc_join( p_owner
->thread
, NULL
);
1834 module_unneed( p_dec
, p_dec
->p_module
);
1837 if( p_dec
->p_owner
->cc
.b_supported
)
1840 for( i
= 0; i
< 4; i
++ )
1841 input_DecoderSetCcState( p_dec
, false, i
);
1844 /* Delete decoder */
1845 DeleteDecoder( p_dec
);
1849 * Put a block_t in the decoder's fifo.
1850 * Thread-safe w.r.t. the decoder. May be a cancellation point.
1852 * \param p_dec the decoder object
1853 * \param p_block the data block
1855 void input_DecoderDecode( decoder_t
*p_dec
, block_t
*p_block
, bool b_do_pace
)
1857 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1859 vlc_fifo_Lock( p_owner
->p_fifo
);
1862 /* FIXME: ideally we would check the time amount of data
1863 * in the FIFO instead of its size. */
1864 /* 400 MiB, i.e. ~ 50mb/s for 60s */
1865 if( vlc_fifo_GetBytes( p_owner
->p_fifo
) > 400*1024*1024 )
1867 msg_Warn( p_dec
, "decoder/packetizer fifo full (data not "
1868 "consumed quickly enough), resetting fifo!" );
1869 block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner
->p_fifo
) );
1873 if( !p_owner
->b_waiting
)
1874 { /* The FIFO is not consumed when waiting, so pacing would deadlock VLC.
1875 * Locking is not necessary as b_waiting is only read, not written by
1876 * the decoder thread. */
1877 while( vlc_fifo_GetCount( p_owner
->p_fifo
) >= 10 )
1878 vlc_fifo_WaitCond( p_owner
->p_fifo
, &p_owner
->wait_fifo
);
1881 vlc_fifo_QueueUnlocked( p_owner
->p_fifo
, p_block
);
1882 vlc_fifo_Unlock( p_owner
->p_fifo
);
1885 bool input_DecoderIsEmpty( decoder_t
* p_dec
)
1887 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1889 assert( !p_owner
->b_waiting
);
1891 if( block_FifoCount( p_dec
->p_owner
->p_fifo
) > 0 )
1896 vlc_mutex_lock( &p_owner
->lock
);
1897 if( p_owner
->fmt
.i_cat
== VIDEO_ES
&& p_owner
->p_vout
!= NULL
)
1898 b_empty
= vout_IsEmpty( p_owner
->p_vout
);
1899 else if( p_owner
->fmt
.i_cat
== AUDIO_ES
)
1900 b_empty
= p_owner
->b_drained
;
1902 b_empty
= true; /* TODO subtitles support */
1903 vlc_mutex_unlock( &p_owner
->lock
);
1909 * Signals that there are no further blocks to decode, and requests that the
1910 * decoder drain all pending buffers. This is used to ensure that all
1911 * intermediate buffers empty and no samples get lost at the end of the stream.
1913 * @note The function does not actually wait for draining. It just signals that
1914 * draining should be performed once the decoder has emptied FIFO.
1916 void input_DecoderDrain( decoder_t
*p_dec
)
1918 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1920 vlc_fifo_Lock( p_owner
->p_fifo
);
1921 p_owner
->b_draining
= true;
1922 vlc_fifo_Signal( p_owner
->p_fifo
);
1923 vlc_fifo_Unlock( p_owner
->p_fifo
);
1926 static void DecoderFlush( decoder_t
*p_dec
)
1928 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1930 vlc_assert_locked( &p_owner
->lock
);
1932 vlc_fifo_Lock( p_owner
->p_fifo
);
1933 /* Empty the fifo */
1934 block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner
->p_fifo
) );
1935 p_owner
->b_draining
= false; /* flush supersedes drain */
1936 vlc_fifo_Unlock( p_owner
->p_fifo
);
1938 /* Monitor for flush end */
1939 p_owner
->b_flushing
= true;
1940 vlc_cond_signal( &p_owner
->wait_request
);
1942 /* Send a special block */
1943 block_t
*p_null
= DecoderBlockFlushNew();
1946 input_DecoderDecode( p_dec
, p_null
, false );
1949 while( p_owner
->b_flushing
)
1950 vlc_cond_wait( &p_owner
->wait_acknowledge
, &p_owner
->lock
);
1954 * Requests that the decoder immediately discard all pending buffers.
1955 * This is useful when seeking or when deselecting a stream.
1957 void input_DecoderFlush( decoder_t
*p_dec
)
1959 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1961 vlc_mutex_lock( &p_owner
->lock
);
1962 DecoderFlush( p_dec
);
1963 vlc_mutex_unlock( &p_owner
->lock
);
1966 void input_DecoderIsCcPresent( decoder_t
*p_dec
, bool pb_present
[4] )
1968 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1971 vlc_mutex_lock( &p_owner
->lock
);
1972 for( i
= 0; i
< 4; i
++ )
1973 pb_present
[i
] = p_owner
->cc
.pb_present
[i
];
1974 vlc_mutex_unlock( &p_owner
->lock
);
1977 int input_DecoderSetCcState( decoder_t
*p_dec
, bool b_decode
, int i_channel
)
1979 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
1981 //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel );
1983 if( i_channel
< 0 || i_channel
>= 4 || !p_owner
->cc
.pb_present
[i_channel
] )
1984 return VLC_EGENERIC
;
1988 static const vlc_fourcc_t fcc
[4] = {
1989 VLC_FOURCC('c', 'c', '1', ' '),
1990 VLC_FOURCC('c', 'c', '2', ' '),
1991 VLC_FOURCC('c', 'c', '3', ' '),
1992 VLC_FOURCC('c', 'c', '4', ' '),
1997 es_format_Init( &fmt
, SPU_ES
, fcc
[i_channel
] );
1998 p_cc
= input_DecoderNew( p_owner
->p_input
, &fmt
,
1999 p_dec
->p_owner
->p_clock
, p_owner
->p_sout
);
2002 msg_Err( p_dec
, "could not create decoder" );
2003 dialog_Fatal( p_dec
, _("Streaming / Transcoding failed"), "%s",
2004 _("VLC could not open the decoder module.") );
2005 return VLC_EGENERIC
;
2007 else if( !p_cc
->p_module
)
2009 DecoderUnsupportedCodec( p_dec
, fcc
[i_channel
] );
2010 input_DecoderDelete(p_cc
);
2011 return VLC_EGENERIC
;
2013 p_cc
->p_owner
->p_clock
= p_owner
->p_clock
;
2015 vlc_mutex_lock( &p_owner
->lock
);
2016 p_owner
->cc
.pp_decoder
[i_channel
] = p_cc
;
2017 vlc_mutex_unlock( &p_owner
->lock
);
2023 vlc_mutex_lock( &p_owner
->lock
);
2024 p_cc
= p_owner
->cc
.pp_decoder
[i_channel
];
2025 p_owner
->cc
.pp_decoder
[i_channel
] = NULL
;
2026 vlc_mutex_unlock( &p_owner
->lock
);
2029 input_DecoderDelete(p_cc
);
2034 int input_DecoderGetCcState( decoder_t
*p_dec
, bool *pb_decode
, int i_channel
)
2036 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2039 if( i_channel
< 0 || i_channel
>= 4 || !p_owner
->cc
.pb_present
[i_channel
] )
2040 return VLC_EGENERIC
;
2042 vlc_mutex_lock( &p_owner
->lock
);
2043 *pb_decode
= p_owner
->cc
.pp_decoder
[i_channel
] != NULL
;
2044 vlc_mutex_unlock( &p_owner
->lock
);
2045 return VLC_EGENERIC
;
2048 void input_DecoderChangePause( decoder_t
*p_dec
, bool b_paused
, mtime_t i_date
)
2050 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2052 /* Normally, p_owner->b_paused != b_paused here. But if a track is added
2053 * while the input is paused (e.g. add sub file), then b_paused is
2054 * (incorrectly) false. FIXME: This is a bug in the decoder owner. */
2055 if( unlikely(p_owner
->b_paused
== b_paused
) )
2058 vlc_mutex_lock( &p_owner
->lock
);
2059 p_owner
->b_paused
= b_paused
;
2060 p_owner
->pause
.i_date
= i_date
;
2061 p_owner
->pause
.i_ignore
= 0;
2062 vlc_cond_signal( &p_owner
->wait_request
);
2064 /* XXX only audio and video output have to be paused.
2065 * - for sout it is useless
2066 * - for subs, it is done by the vout
2068 if( p_owner
->fmt
.i_cat
== AUDIO_ES
)
2070 if( p_owner
->p_aout
)
2071 aout_DecChangePause( p_owner
->p_aout
, b_paused
, i_date
);
2073 else if( p_owner
->fmt
.i_cat
== VIDEO_ES
)
2075 if( p_owner
->p_vout
)
2076 vout_ChangePause( p_owner
->p_vout
, b_paused
, i_date
);
2078 vlc_mutex_unlock( &p_owner
->lock
);
2081 void input_DecoderChangeDelay( decoder_t
*p_dec
, mtime_t i_delay
)
2083 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2085 vlc_mutex_lock( &p_owner
->lock
);
2086 p_owner
->i_ts_delay
= i_delay
;
2087 vlc_mutex_unlock( &p_owner
->lock
);
2090 void input_DecoderStartWait( decoder_t
*p_dec
)
2092 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2094 assert( !p_owner
->b_waiting
);
2096 vlc_mutex_lock( &p_owner
->lock
);
2097 p_owner
->b_first
= true;
2098 p_owner
->b_has_data
= false;
2099 p_owner
->b_waiting
= true;
2100 vlc_cond_signal( &p_owner
->wait_request
);
2101 vlc_mutex_unlock( &p_owner
->lock
);
2104 void input_DecoderStopWait( decoder_t
*p_dec
)
2106 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2108 assert( p_owner
->b_waiting
);
2110 vlc_mutex_lock( &p_owner
->lock
);
2111 p_owner
->b_waiting
= false;
2112 vlc_cond_signal( &p_owner
->wait_request
);
2113 vlc_mutex_unlock( &p_owner
->lock
);
2116 void input_DecoderWait( decoder_t
*p_dec
)
2118 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2120 assert( p_owner
->b_waiting
);
2122 vlc_mutex_lock( &p_owner
->lock
);
2123 while( !p_owner
->b_has_data
)
2125 vlc_fifo_Lock( p_owner
->p_fifo
);
2126 if( p_owner
->b_idle
&& vlc_fifo_IsEmpty( p_owner
->p_fifo
) )
2128 msg_Warn( p_dec
, "can't wait without data to decode" );
2129 vlc_fifo_Unlock( p_owner
->p_fifo
);
2132 vlc_fifo_Unlock( p_owner
->p_fifo
);
2133 vlc_cond_wait( &p_owner
->wait_acknowledge
, &p_owner
->lock
);
2135 vlc_mutex_unlock( &p_owner
->lock
);
2138 void input_DecoderFrameNext( decoder_t
*p_dec
, mtime_t
*pi_duration
)
2140 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2144 vlc_mutex_lock( &p_owner
->lock
);
2145 if( p_owner
->fmt
.i_cat
== VIDEO_ES
)
2147 if( p_owner
->b_paused
&& p_owner
->p_vout
)
2149 vout_NextPicture( p_owner
->p_vout
, pi_duration
);
2150 p_owner
->pause
.i_ignore
++;
2151 vlc_cond_signal( &p_owner
->wait_request
);
2156 /* TODO subtitle should not be flushed */
2157 p_owner
->b_waiting
= false;
2158 DecoderFlush( p_dec
);
2160 vlc_mutex_unlock( &p_owner
->lock
);
2163 bool input_DecoderHasFormatChanged( decoder_t
*p_dec
, es_format_t
*p_fmt
, vlc_meta_t
**pp_meta
)
2165 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2168 vlc_mutex_lock( &p_owner
->lock
);
2169 b_changed
= p_owner
->b_fmt_description
;
2173 es_format_Copy( p_fmt
, &p_owner
->fmt
);
2178 if( p_owner
->p_description
)
2180 *pp_meta
= vlc_meta_New();
2182 vlc_meta_Merge( *pp_meta
, p_owner
->p_description
);
2185 p_owner
->b_fmt_description
= false;
2187 vlc_mutex_unlock( &p_owner
->lock
);
2191 size_t input_DecoderGetFifoSize( decoder_t
*p_dec
)
2193 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2195 return block_FifoSize( p_owner
->p_fifo
);
2198 void input_DecoderGetObjects( decoder_t
*p_dec
,
2199 vout_thread_t
**pp_vout
, audio_output_t
**pp_aout
)
2201 decoder_owner_sys_t
*p_owner
= p_dec
->p_owner
;
2203 vlc_mutex_lock( &p_owner
->lock
);
2205 *pp_vout
= p_owner
->p_vout
? vlc_object_hold( p_owner
->p_vout
) : NULL
;
2207 *pp_aout
= p_owner
->p_aout
? vlc_object_hold( p_owner
->p_aout
) : NULL
;
2208 vlc_mutex_unlock( &p_owner
->lock
);