1 /*****************************************************************************
2 * input_dec.c: Functions for the management of decoders
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VideoLAN
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Gildas Bazin <gbazin@netcourrier.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
29 #include <string.h> /* memcpy(), memset() */
32 #include <vlc/decoder.h>
35 #include "stream_output.h"
37 #include "input_ext-intf.h"
38 #include "input_ext-plugins.h"
42 static void input_NullPacket( input_thread_t *, es_descriptor_t * );
44 static decoder_t * CreateDecoder( input_thread_t *, es_descriptor_t *, int );
45 static int DecoderThread( decoder_t * );
46 static int DecoderDecode( decoder_t * p_dec, block_t *p_block );
47 static void DeleteDecoder( decoder_t * );
49 /* Buffers allocation callbacks for the decoders */
50 static aout_buffer_t *aout_new_buffer( decoder_t *, int );
51 static void aout_del_buffer( decoder_t *, aout_buffer_t * );
53 static picture_t *vout_new_buffer( decoder_t * );
54 static void vout_del_buffer( decoder_t *, picture_t * );
55 static void vout_link_picture( decoder_t *, picture_t * );
56 static void vout_unlink_picture( decoder_t *, picture_t * );
58 static es_format_t null_es_format = {0};
60 struct decoder_owner_sys_t
62 vlc_bool_t b_own_thread;
64 input_thread_t *p_input;
66 aout_instance_t *p_aout;
67 aout_input_t *p_aout_input;
69 vout_thread_t *p_vout;
71 sout_instance_t *p_sout;
72 sout_packetizer_input_t *p_sout_input;
74 /* Some decoders require already packetized data (ie. not truncated) */
75 decoder_t *p_packetizer;
77 /* Current format in use by the output */
86 input_buffers_t *p_method_data;
87 es_descriptor_t *p_es_descriptor;
92 * Spawns a new decoder thread
94 * \param p_input the input thread
95 * \param p_es the es descriptor
96 * \return the spawned decoder object
98 decoder_t * input_RunDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
100 decoder_t *p_dec = NULL;
103 /* If we are in sout mode, search for packetizer module */
104 if( !p_es->b_force_decoder && p_input->stream.p_sout )
106 /* Create the decoder configuration structure */
107 p_dec = CreateDecoder( p_input, p_es, VLC_OBJECT_PACKETIZER );
110 msg_Err( p_input, "could not create packetizer" );
116 /* Create the decoder configuration structure */
117 p_dec = CreateDecoder( p_input, p_es, VLC_OBJECT_DECODER );
120 msg_Err( p_input, "could not create decoder" );
125 if( !p_dec->p_module )
127 msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
128 "VLC probably does not support this sound or video format.",
129 (char*)&p_dec->fmt_in.i_codec );
131 DeleteDecoder( p_dec );
132 vlc_object_destroy( p_dec );
136 var_Get( p_input, "minimize-threads", &val );
137 p_dec->p_owner->b_own_thread = val.b_bool ? VLC_FALSE : VLC_TRUE;
139 if( p_dec->p_owner->b_own_thread )
142 if ( p_es->i_cat == AUDIO_ES )
144 i_priority = VLC_THREAD_PRIORITY_AUDIO;
148 i_priority = VLC_THREAD_PRIORITY_VIDEO;
151 /* Spawn the decoder thread */
152 if( vlc_thread_create( p_dec, "decoder", DecoderThread,
153 i_priority, VLC_FALSE ) )
155 msg_Err( p_dec, "cannot spawn decoder thread \"%s\"",
156 p_dec->p_module->psz_object_name );
157 module_Unneed( p_dec, p_dec->p_module );
158 DeleteDecoder( p_dec );
159 vlc_object_destroy( p_dec );
164 /* Select a new ES */
165 INSERT_ELEM( p_input->stream.pp_selected_es,
166 p_input->stream.i_selected_es_number,
167 p_input->stream.i_selected_es_number,
170 p_input->stream.b_changed = 1;
176 * Kills a decoder thread and waits until it's finished
178 * \param p_input the input thread
179 * \param p_es the es descriptor
182 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
184 decoder_t *p_dec = p_es->p_dec;
187 p_dec->b_die = VLC_TRUE;
189 if( p_dec->p_owner->b_own_thread )
191 /* Make sure the thread leaves the NextDataPacket() function by
192 * sending it a few null packets. */
193 for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
195 input_NullPacket( p_input, p_es );
198 if( p_es->p_pes != NULL )
200 input_DecodePES( p_es->p_dec, p_es->p_pes );
203 /* Waiting for the thread to exit */
204 /* I thought that unlocking was better since thread join can be long
205 * but it actually creates late pictures and freezes --stef */
206 /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
207 vlc_thread_join( p_dec );
208 /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
210 /* XXX We don't do it here because of dll loader that want close in the
211 * same thread than open/decode */
213 module_Unneed( p_dec, p_dec->p_module );
218 module_Unneed( p_dec, p_dec->p_module );
221 /* Delete decoder configuration */
222 DeleteDecoder( p_dec );
224 /* Delete the decoder */
225 vlc_object_destroy( p_dec );
227 /* Tell the input there is no more decoder */
230 p_input->stream.b_changed = 1;
234 * Put a PES in the decoder's fifo.
236 * \param p_dec the decoder object
237 * \param p_pes the pes packet
240 void input_DecodePES( decoder_t * p_dec, pes_packet_t * p_pes )
242 data_packet_t *p_data;
245 for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next )
247 i_size += p_data->p_payload_end - p_data->p_payload_start;
251 block_t *p_block = block_New( p_dec, i_size );
254 uint8_t *p_buffer = p_block->p_buffer;
256 for( p_data = p_pes->p_first; p_data != NULL; p_data = p_data->p_next )
258 int i_copy = p_data->p_payload_end - p_data->p_payload_start;
260 memcpy( p_buffer, p_data->p_payload_start, i_copy );
264 p_block->i_pts = p_pes->i_pts;
265 p_block->i_dts = p_pes->i_dts;
266 if( p_pes->b_discontinuity )
267 p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
268 p_block->i_rate = p_pes->i_rate;
270 input_DecodeBlock( p_dec, p_block );
274 input_DeletePES( p_dec->p_owner->p_method_data, p_pes );
278 * Put a block_t in the decoder's fifo.
280 * \param p_dec the decoder object
281 * \param p_block the data block
283 void input_DecodeBlock( decoder_t * p_dec, block_t *p_block )
285 if( p_dec->p_owner->b_own_thread )
287 block_FifoPut( p_dec->p_owner->p_fifo, p_block );
289 if( p_dec->p_owner->p_input->b_out_pace_control )
292 while( !p_dec->b_die && !p_dec->b_error &&
293 p_dec->p_owner->p_fifo->i_depth > 10 )
301 if( p_dec->b_error || p_block->i_buffer <= 0 )
303 block_Release( p_block );
307 DecoderDecode( p_dec, p_block );
313 * Create a NULL packet for padding in case of a data loss
315 * \param p_input the input thread
316 * \param p_es es descriptor
319 static void input_NullPacket( input_thread_t * p_input,
320 es_descriptor_t * p_es )
322 block_t *p_block = block_New( p_input, PADDING_PACKET_SIZE );
325 memset( p_block->p_buffer, 0, PADDING_PACKET_SIZE );
326 p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
328 block_FifoPut( p_es->p_dec->p_owner->p_fifo, p_block );
333 * Send a NULL packet to the decoders
335 * \param p_input the input thread
338 void input_EscapeDiscontinuity( input_thread_t * p_input )
340 unsigned int i_es, i;
342 for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
344 es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
346 if( p_es->p_dec != NULL )
348 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
350 input_NullPacket( p_input, p_es );
357 * Send a NULL packet to the audio decoders
359 * \param p_input the input thread
362 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
364 unsigned int i_es, i;
366 for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
368 es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
370 if( p_es->p_dec != NULL && p_es->i_cat == AUDIO_ES )
372 for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
374 input_NullPacket( p_input, p_es );
381 * Create a decoder object
383 * \param p_input the input thread
384 * \param p_es the es descriptor
385 * \param i_object_type Object type as define in include/vlc_objects.h
386 * \return the decoder object
388 static decoder_t * CreateDecoder( input_thread_t * p_input,
389 es_descriptor_t * p_es, int i_object_type )
393 p_dec = vlc_object_create( p_input, i_object_type );
396 msg_Err( p_input, "out of memory" );
400 p_dec->pf_decode_audio = 0;
401 p_dec->pf_decode_video = 0;
402 p_dec->pf_decode_sub = 0;
403 p_dec->pf_packetize = 0;
405 /* Initialize the decoder fifo */
406 p_dec->p_module = NULL;
408 es_format_Copy( &p_dec->fmt_in, &p_es->fmt );
410 if( p_es->p_waveformatex )
412 #define p_wf ((WAVEFORMATEX *)p_es->p_waveformatex)
413 p_dec->fmt_in.audio.i_channels = p_wf->nChannels;
414 p_dec->fmt_in.audio.i_rate = p_wf->nSamplesPerSec;
415 p_dec->fmt_in.i_bitrate = p_wf->nAvgBytesPerSec * 8;
416 p_dec->fmt_in.audio.i_blockalign = p_wf->nBlockAlign;
417 p_dec->fmt_in.audio.i_bitspersample = p_wf->wBitsPerSample;
418 p_dec->fmt_in.i_extra = p_wf->cbSize;
419 p_dec->fmt_in.p_extra = NULL;
422 p_dec->fmt_in.p_extra = malloc( p_wf->cbSize );
423 memcpy( p_dec->fmt_in.p_extra, &p_wf[1], p_wf->cbSize );
427 if( p_es->p_bitmapinfoheader )
429 #define p_bih ((BITMAPINFOHEADER *) p_es->p_bitmapinfoheader)
430 p_dec->fmt_in.i_extra = p_bih->biSize - sizeof(BITMAPINFOHEADER);
431 p_dec->fmt_in.p_extra = NULL;
432 if( p_dec->fmt_in.i_extra )
434 p_dec->fmt_in.p_extra = malloc( p_dec->fmt_in.i_extra );
435 memcpy( p_dec->fmt_in.p_extra, &p_bih[1], p_dec->fmt_in.i_extra );
438 p_dec->fmt_in.video.i_width = p_bih->biWidth;
439 p_dec->fmt_in.video.i_height = p_bih->biHeight;
444 * - 2: I'm not sure there isn't any endian problem here (spu)... */
445 if( p_es->i_cat == SPU_ES && p_es->p_demux_data )
447 if( ( p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', ' ' ) ||
448 p_es->i_fourcc == VLC_FOURCC( 's', 'p', 'u', 'b' ) ) &&
449 *((uint32_t*)p_es->p_demux_data) == 0xBeef )
451 memcpy( p_dec->fmt_in.subs.spu.palette,
452 p_es->p_demux_data, 17 * 4 );
454 else if( p_es->i_fourcc == VLC_FOURCC( 'd', 'v', 'b', 's' ) )
456 dvb_spuinfo_t *p_dvbs = (dvb_spuinfo_t*)p_es->p_demux_data;
458 p_dec->fmt_in.subs.dvb.i_id = p_dvbs->i_id;
462 p_dec->fmt_in.i_cat = p_es->i_cat;
463 p_dec->fmt_in.i_codec = p_es->i_fourcc;
465 p_dec->fmt_out = null_es_format;
467 /* Allocate our private structure for the decoder */
468 p_dec->p_owner = (decoder_owner_sys_t*)malloc(sizeof(decoder_owner_sys_t));
469 if( p_dec->p_owner == NULL )
471 msg_Err( p_dec, "out of memory" );
474 p_dec->p_owner->b_own_thread = VLC_TRUE;
475 p_dec->p_owner->p_input = p_input;
476 p_dec->p_owner->p_aout = NULL;
477 p_dec->p_owner->p_aout_input = NULL;
478 p_dec->p_owner->p_vout = NULL;
479 p_dec->p_owner->p_sout = p_input->stream.p_sout;
480 p_dec->p_owner->p_sout_input = NULL;
481 p_dec->p_owner->p_packetizer = NULL;
482 p_dec->p_owner->p_es_descriptor = p_es;
486 if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL )
488 msg_Err( p_dec, "out of memory" );
491 p_dec->p_owner->p_method_data = p_input->p_method_data;
493 /* Set buffers allocation callbacks for the decoders */
494 p_dec->pf_aout_buffer_new = aout_new_buffer;
495 p_dec->pf_aout_buffer_del = aout_del_buffer;
496 p_dec->pf_vout_buffer_new = vout_new_buffer;
497 p_dec->pf_vout_buffer_del = vout_del_buffer;
498 p_dec->pf_picture_link = vout_link_picture;
499 p_dec->pf_picture_unlink = vout_unlink_picture;
501 vlc_object_attach( p_dec, p_input );
503 /* Find a suitable decoder/packetizer module */
504 if( i_object_type == VLC_OBJECT_DECODER )
505 p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );
507 p_dec->p_module = module_Need( p_dec, "packetizer", "$packetizer", 0 );
509 /* Check if decoder requires already packetized data */
510 if( i_object_type == VLC_OBJECT_DECODER &&
511 p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
513 p_dec->p_owner->p_packetizer =
514 vlc_object_create( p_input, VLC_OBJECT_PACKETIZER );
515 if( p_dec->p_owner->p_packetizer )
517 p_dec->p_owner->p_packetizer->fmt_in = null_es_format;
518 p_dec->p_owner->p_packetizer->fmt_out = null_es_format;
519 es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in,
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_destroy( p_dec->p_owner->p_packetizer );
541 * The decoding main loop
543 * \param p_dec the decoder
546 static int DecoderThread( decoder_t * p_dec )
550 /* The decoder's main loop */
551 while( !p_dec->b_die && !p_dec->b_error )
553 if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL )
558 if( p_block->i_buffer <= 0 )
560 block_Release( p_block );
563 if( DecoderDecode( p_dec, p_block ) )
569 while( !p_dec->b_die )
571 /* Trash all received PES packets */
572 p_block = block_FifoGet( p_dec->p_owner->p_fifo );
575 block_Release( p_block );
579 /* XXX We do it here because of dll loader that want close in the
580 * same thread than open/decode */
582 module_Unneed( p_dec, p_dec->p_module );
590 * \param p_dec the decoder object
591 * \param p_block the block to decode
592 * \return VLC_SUCCESS or an error code
594 static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
596 if( p_block->i_buffer <= 0 )
598 block_Release( p_block );
602 if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
604 block_t *p_sout_block;
606 while( (p_sout_block = p_dec->pf_packetize( p_dec, &p_block )) )
608 if( !p_dec->p_owner->p_sout_input )
610 es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
611 if( p_dec->p_owner->p_es_descriptor->p_pgrm )
613 p_dec->p_owner->sout.i_group =
614 p_dec->p_owner->p_es_descriptor->p_pgrm->i_number;
616 p_dec->p_owner->sout.i_id =
617 p_dec->p_owner->p_es_descriptor->i_id - 1;
618 if( p_dec->fmt_in.psz_language )
620 p_dec->p_owner->sout.psz_language =
621 strdup( p_dec->fmt_in.psz_language );
624 p_dec->p_owner->p_sout_input =
625 sout_InputNew( p_dec->p_owner->p_sout,
626 &p_dec->p_owner->sout );
628 if( p_dec->p_owner->p_sout_input == NULL )
630 msg_Err( p_dec, "cannot create packetizer output" );
631 p_dec->b_error = VLC_TRUE;
633 while( p_sout_block )
635 block_t *p_next = p_sout_block->p_next;
636 block_Release( p_sout_block );
637 p_sout_block = p_next;
643 while( p_sout_block )
645 block_t *p_next = p_sout_block->p_next;
646 sout_buffer_t *p_sout_buffer;
649 sout_BufferNew( p_dec->p_owner->p_sout_input->p_sout,
650 p_sout_block->i_buffer );
651 if( p_sout_buffer == NULL )
653 msg_Err( p_dec, "cannot get sout buffer" );
657 memcpy( p_sout_buffer->p_buffer, p_sout_block->p_buffer,
658 p_sout_block->i_buffer );
660 p_sout_buffer->i_pts = p_sout_block->i_pts;
661 p_sout_buffer->i_dts = p_sout_block->i_dts;
662 p_sout_buffer->i_length = p_sout_block->i_length;
663 p_sout_buffer->i_flags =
664 ( p_sout_block->i_flags << SOUT_BUFFER_FLAGS_BLOCK_SHIFT )
665 & SOUT_BUFFER_FLAGS_BLOCK_MASK;
667 block_Release( p_sout_block );
669 sout_InputSendBuffer( p_dec->p_owner->p_sout_input,
672 p_sout_block = p_next;
675 /* For now it's enough, as only sout inpact on this flag */
676 if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 &&
677 p_dec->p_owner->p_input->b_out_pace_control )
679 msg_Dbg( p_dec, "switching to synch mode" );
680 p_dec->p_owner->p_input->b_out_pace_control = VLC_FALSE;
682 else if( p_dec->p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
683 !p_dec->p_owner->p_input->b_out_pace_control )
685 msg_Dbg( p_dec, "switching to asynch mode" );
686 p_dec->p_owner->p_input->b_out_pace_control = VLC_TRUE;
690 else if( p_dec->fmt_in.i_cat == AUDIO_ES )
692 aout_buffer_t *p_aout_buf;
694 if( p_dec->p_owner->p_packetizer )
696 block_t *p_packetized_block;
697 decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
699 while( (p_packetized_block =
700 p_packetizer->pf_packetize( p_packetizer, &p_block )) )
703 p_dec->pf_decode_audio( p_dec, &p_packetized_block )) )
705 aout_DecPlay( p_dec->p_owner->p_aout,
706 p_dec->p_owner->p_aout_input, p_aout_buf );
710 else while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
712 aout_DecPlay( p_dec->p_owner->p_aout,
713 p_dec->p_owner->p_aout_input, p_aout_buf );
716 else if( p_dec->fmt_in.i_cat == VIDEO_ES )
720 if( p_dec->p_owner->p_packetizer )
722 block_t *p_packetized_block;
723 decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
725 while( (p_packetized_block =
726 p_packetizer->pf_packetize( p_packetizer, &p_block )) )
729 p_dec->pf_decode_video( p_dec, &p_packetized_block )) )
731 vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
733 vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
737 else while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
739 vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date );
740 vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
743 else if( p_dec->fmt_in.i_cat == SPU_ES )
745 p_dec->pf_decode_sub( p_dec, &p_block );
749 msg_Err( p_dec, "unknown ES format" );
753 return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
757 * Destroys a decoder object
759 * \param p_dec the decoder object
762 static void DeleteDecoder( decoder_t * p_dec )
764 vlc_object_detach( p_dec );
766 msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %d PES in FIFO",
767 (char*)&p_dec->fmt_in.i_codec,
768 p_dec->p_owner->p_fifo->i_depth );
770 /* Free all packets still in the decoder fifo. */
771 block_FifoEmpty( p_dec->p_owner->p_fifo );
772 block_FifoRelease( p_dec->p_owner->p_fifo );
775 if( p_dec->p_owner->p_aout_input )
776 aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
778 if( p_dec->p_owner->p_vout )
782 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
783 /* Hack to make sure all the the pictures are freed by the decoder */
784 for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
787 if( p_pic->i_status == RESERVED_PICTURE )
788 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
789 if( p_pic->i_refcount > 0 )
790 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
794 /* We are about to die. Reattach video output to p_vlc. */
795 vout_Request( p_dec, p_dec->p_owner->p_vout, 0, 0, 0, 0 );
798 if( p_dec->p_owner->p_sout_input )
800 sout_InputDelete( p_dec->p_owner->p_sout_input );
801 es_format_Clean( &p_dec->p_owner->sout );
804 es_format_Clean( &p_dec->fmt_in );
805 es_format_Clean( &p_dec->fmt_out );
807 if( p_dec->p_owner->p_packetizer )
809 module_Unneed( p_dec->p_owner->p_packetizer,
810 p_dec->p_owner->p_packetizer->p_module );
811 es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
812 es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_out );
813 vlc_object_detach( p_dec->p_owner->p_packetizer );
814 vlc_object_destroy( p_dec->p_owner->p_packetizer );
817 free( p_dec->p_owner );
820 /*****************************************************************************
821 * Buffers allocation callbacks for the decoders
822 *****************************************************************************/
823 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
825 decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
826 aout_buffer_t *p_buffer;
828 if( p_sys->p_aout_input != NULL &&
829 ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate ||
830 p_dec->fmt_out.audio.i_original_channels !=
831 p_sys->audio.i_original_channels ||
832 p_dec->fmt_out.audio.i_bytes_per_frame !=
833 p_sys->audio.i_bytes_per_frame ) )
835 /* Parameters changed, restart the aout */
836 aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
837 p_sys->p_aout_input = NULL;
840 if( p_sys->p_aout_input == NULL )
842 p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
843 p_sys->audio = p_dec->fmt_out.audio;
844 p_sys->p_aout_input =
845 aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->audio );
846 if( p_sys->p_aout_input == NULL )
848 msg_Err( p_dec, "failed to create audio output" );
849 p_dec->b_error = VLC_TRUE;
852 p_dec->fmt_out.audio.i_bytes_per_frame =
853 p_sys->audio.i_bytes_per_frame;
856 p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
862 static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
864 aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
865 p_dec->p_owner->p_aout_input, p_buffer );
868 static picture_t *vout_new_buffer( decoder_t *p_dec )
870 decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
873 if( p_sys->p_vout == NULL ||
874 p_dec->fmt_out.video.i_width != p_sys->video.i_width ||
875 p_dec->fmt_out.video.i_height != p_sys->video.i_height ||
876 p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma ||
877 p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect )
879 if( !p_dec->fmt_out.video.i_width ||
880 !p_dec->fmt_out.video.i_height )
882 /* Can't create a new vout without display size */
886 p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
887 p_sys->video = p_dec->fmt_out.video;
889 p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
890 p_sys->video.i_width,
891 p_sys->video.i_height,
892 p_sys->video.i_chroma,
893 p_sys->video.i_aspect );
895 if( p_sys->p_vout == NULL )
897 msg_Err( p_dec, "failed to create video output" );
898 p_dec->b_error = VLC_TRUE;
903 /* Get a new picture */
904 while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
906 int i_pic, i_ready_pic = 0;
908 if( p_dec->b_die || p_dec->b_error )
913 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
914 /* Check the decoder doesn't leak pictures */
915 for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
918 if( p_pic->i_status == READY_PICTURE && i_ready_pic++ > 0 ) break;
920 if( p_pic->i_status != DISPLAYED_PICTURE &&
921 p_pic->i_status != RESERVED_PICTURE &&
922 p_pic->i_status != READY_PICTURE ) break;
924 if( !p_pic->i_refcount ) break;
926 if( i_pic == p_dec->p_owner->p_vout->render.i_pictures )
928 msg_Err( p_dec, "decoder is leaking pictures, resetting the heap" );
930 /* Just free all the pictures */
931 for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
934 if( p_pic->i_status == RESERVED_PICTURE )
935 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
936 if( p_pic->i_refcount > 0 )
937 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
942 msleep( VOUT_OUTMEM_SLEEP );
948 static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
950 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
953 static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
955 vout_LinkPicture( p_dec->p_owner->p_vout, p_pic );
958 static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
960 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );