]> git.sesse.net Git - vlc/blob - src/input/input_dec.c
* all: remove sout_format_t and use es_format_t instead.
[vlc] / src / input / input_dec.c
1 /*****************************************************************************
2  * input_dec.c: Functions for the management of decoders
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: input_dec.c,v 1.72 2003/11/21 15:32:08 fenrir Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29 #include <string.h>                                    /* memcpy(), memset() */
30
31 #include <vlc/vlc.h>
32 #include <vlc/decoder.h>
33 #include <vlc/vout.h>
34
35 #include "stream_output.h"
36
37 #include "input_ext-intf.h"
38 #include "input_ext-plugins.h"
39
40 #include "codecs.h"
41
42 static decoder_t * CreateDecoder( input_thread_t *, es_descriptor_t *, int );
43 static int         DecoderThread( decoder_t * );
44 static void        DeleteDecoder( decoder_t * );
45
46 /* Buffers allocation callbacks for the decoders */
47 static aout_buffer_t *aout_new_buffer( decoder_t *, int );
48 static void aout_del_buffer( decoder_t *, aout_buffer_t * );
49
50 static picture_t *vout_new_buffer( decoder_t * );
51 static void vout_del_buffer( decoder_t *, picture_t * );
52
53 static es_format_t null_es_format = {0};
54
55 /*****************************************************************************
56  * input_RunDecoder: spawns a new decoder thread
57  *****************************************************************************/
58 decoder_fifo_t * input_RunDecoder( input_thread_t * p_input,
59                                    es_descriptor_t * p_es )
60 {
61     vlc_value_t    val;
62     decoder_t      *p_dec = NULL;
63     int            i_priority;
64
65     /* If we are in sout mode, search for packetizer module */
66     var_Get( p_input, "sout", &val );
67     if( !p_es->b_force_decoder && val.psz_string && *val.psz_string )
68     {
69         free( val.psz_string );
70         val.b_bool = VLC_TRUE;
71
72         if( p_es->i_cat == AUDIO_ES )
73         {
74             var_Get( p_input, "sout-audio", &val );
75         }
76         else if( p_es->i_cat == VIDEO_ES )
77         {
78             var_Get( p_input, "sout-video", &val );
79         }
80
81         if( val.b_bool )
82         {
83             /* Create the decoder configuration structure */
84             p_dec = CreateDecoder( p_input, p_es, VLC_OBJECT_PACKETIZER );
85             if( p_dec == NULL )
86             {
87                 msg_Err( p_input, "could not create packetizer" );
88                 return NULL;
89             }
90
91             p_dec->p_module =
92                 module_Need( p_dec, "packetizer", "$packetizer" );
93         }
94     }
95     else
96     {
97         /* Create the decoder configuration structure */
98         p_dec = CreateDecoder( p_input, p_es, VLC_OBJECT_DECODER );
99         if( p_dec == NULL )
100         {
101             msg_Err( p_input, "could not create decoder" );
102             return NULL;
103         }
104
105         /* default Get a suitable decoder module */
106         p_dec->p_module = module_Need( p_dec, "decoder", "$codec" );
107
108         if( val.psz_string ) free( val.psz_string );
109     }
110
111     if( !p_dec || !p_dec->p_module )
112     {
113         msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
114                  "VLC probably does not support this sound or video format.",
115                  (char*)&p_dec->p_fifo->i_fourcc );
116
117         DeleteDecoder( p_dec );
118         vlc_object_destroy( p_dec );
119         return NULL;
120     }
121
122     if ( p_es->i_cat == AUDIO_ES )
123     {
124         i_priority = VLC_THREAD_PRIORITY_AUDIO;
125     }
126     else
127     {
128         i_priority = VLC_THREAD_PRIORITY_VIDEO;
129     }
130
131     /* Spawn the decoder thread */
132     if( vlc_thread_create( p_dec, "decoder", DecoderThread,
133                            i_priority, VLC_FALSE ) )
134     {
135         msg_Err( p_dec, "cannot spawn decoder thread \"%s\"",
136                          p_dec->p_module->psz_object_name );
137         module_Unneed( p_dec, p_dec->p_module );
138         DeleteDecoder( p_dec );
139         vlc_object_destroy( p_dec );
140         return NULL;
141     }
142
143     p_input->stream.b_changed = 1;
144
145     return p_dec->p_fifo;
146 }
147
148 /*****************************************************************************
149  * input_EndDecoder: kills a decoder thread and waits until it's finished
150  *****************************************************************************/
151 void input_EndDecoder( input_thread_t * p_input, es_descriptor_t * p_es )
152 {
153     int i_dummy;
154     decoder_t *p_dec = p_es->p_decoder_fifo->p_dec;
155
156     p_es->p_decoder_fifo->b_die = 1;
157
158     /* Make sure the thread leaves the NextDataPacket() function by
159      * sending it a few null packets. */
160     for( i_dummy = 0; i_dummy < PADDING_PACKET_NUMBER; i_dummy++ )
161     {
162         input_NullPacket( p_input, p_es );
163     }
164
165     if( p_es->p_pes != NULL )
166     {
167         input_DecodePES( p_es->p_decoder_fifo, p_es->p_pes );
168     }
169
170     /* Waiting for the thread to exit */
171     /* I thought that unlocking was better since thread join can be long
172      * but it actually creates late pictures and freezes --stef */
173     /* vlc_mutex_unlock( &p_input->stream.stream_lock ); */
174     vlc_thread_join( p_dec );
175     /* vlc_mutex_lock( &p_input->stream.stream_lock ); */
176
177     /* Unneed module */
178     module_Unneed( p_dec, p_dec->p_module );
179
180     /* Delete decoder configuration */
181     DeleteDecoder( p_dec );
182
183     /* Delete the decoder */
184     vlc_object_destroy( p_dec );
185
186     /* Tell the input there is no more decoder */
187     p_es->p_decoder_fifo = NULL;
188
189     p_input->stream.b_changed = 1;
190 }
191
192 /*****************************************************************************
193  * input_DecodePES
194  *****************************************************************************
195  * Put a PES in the decoder's fifo.
196  *****************************************************************************/
197 void input_DecodePES( decoder_fifo_t * p_decoder_fifo, pes_packet_t * p_pes )
198 {
199     vlc_mutex_lock( &p_decoder_fifo->data_lock );
200
201     p_pes->p_next = NULL;
202     *p_decoder_fifo->pp_last = p_pes;
203     p_decoder_fifo->pp_last = &p_pes->p_next;
204     p_decoder_fifo->i_depth++;
205
206     /* Warn the decoder that it's got work to do. */
207     vlc_cond_signal( &p_decoder_fifo->data_wait );
208     vlc_mutex_unlock( &p_decoder_fifo->data_lock );
209 }
210
211 /*****************************************************************************
212  * Create a NULL packet for padding in case of a data loss
213  *****************************************************************************/
214 void input_NullPacket( input_thread_t * p_input,
215                        es_descriptor_t * p_es )
216 {
217     data_packet_t *             p_pad_data;
218     pes_packet_t *              p_pes;
219
220     if( (p_pad_data = input_NewPacketForce( p_input->p_method_data,
221                     PADDING_PACKET_SIZE)) == NULL )
222     {
223         msg_Err( p_input, "no new packet" );
224         p_input->b_error = 1;
225         return;
226     }
227
228     memset( p_pad_data->p_payload_start, 0, PADDING_PACKET_SIZE );
229     p_pad_data->b_discard_payload = 1;
230     p_pes = p_es->p_pes;
231
232     if( p_pes != NULL )
233     {
234         p_pes->b_discontinuity = 1;
235         p_pes->p_last->p_next = p_pad_data;
236         p_pes->p_last = p_pad_data;
237         p_pes->i_nb_data++;
238     }
239     else
240     {
241         if( (p_pes = input_NewPES( p_input->p_method_data )) == NULL )
242         {
243             msg_Err( p_input, "no PES packet" );
244             p_input->b_error = 1;
245             return;
246         }
247
248         p_pes->i_rate = p_input->stream.control.i_rate;
249         p_pes->p_first = p_pes->p_last = p_pad_data;
250         p_pes->i_nb_data = 1;
251         p_pes->b_discontinuity = 1;
252         input_DecodePES( p_es->p_decoder_fifo, p_pes );
253     }
254 }
255
256 /*****************************************************************************
257  * input_EscapeDiscontinuity: send a NULL packet to the decoders
258  *****************************************************************************/
259 void input_EscapeDiscontinuity( input_thread_t * p_input )
260 {
261     unsigned int i_es, i;
262
263     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
264     {
265         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
266
267         if( p_es->p_decoder_fifo != NULL )
268         {
269             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
270             {
271                 input_NullPacket( p_input, p_es );
272             }
273         }
274     }
275 }
276
277 /*****************************************************************************
278  * input_EscapeAudioDiscontinuity: send a NULL packet to the audio decoders
279  *****************************************************************************/
280 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
281 {
282     unsigned int i_es, i;
283
284     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
285     {
286         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
287
288         if( p_es->p_decoder_fifo != NULL && p_es->i_cat == AUDIO_ES )
289         {
290             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
291             {
292                 input_NullPacket( p_input, p_es );
293             }
294         }
295     }
296 }
297
298 struct decoder_owner_sys_t
299 {
300     aout_instance_t *p_aout;
301     aout_input_t    *p_aout_input;
302
303     vout_thread_t   *p_vout;
304
305     sout_packetizer_input_t *p_sout;
306
307     /* Current format in use by the output */
308     video_format_t video;
309     audio_format_t audio;
310     es_format_t    sout;
311 };
312
313 /*****************************************************************************
314  * CreateDecoder: create a decoder object
315  *****************************************************************************/
316 static decoder_t * CreateDecoder( input_thread_t * p_input,
317                                   es_descriptor_t * p_es, int i_object_type )
318 {
319     decoder_t *p_dec;
320
321     p_dec = vlc_object_create( p_input, i_object_type );
322     if( p_dec == NULL )
323     {
324         msg_Err( p_input, "out of memory" );
325         return NULL;
326     }
327
328     p_dec->pf_decode = 0;
329     p_dec->pf_decode_audio = 0;
330     p_dec->pf_decode_video = 0;
331     p_dec->pf_decode_sub = 0;
332     p_dec->pf_packetize = 0;
333     p_dec->pf_run = 0;
334
335     /* Select a new ES */
336     INSERT_ELEM( p_input->stream.pp_selected_es,
337                  p_input->stream.i_selected_es_number,
338                  p_input->stream.i_selected_es_number,
339                  p_es );
340
341     /* Allocate the memory needed to store the decoder's fifo */
342     p_dec->p_fifo = vlc_object_create( p_input, VLC_OBJECT_DECODER_FIFO );
343     if( p_dec->p_fifo == NULL )
344     {
345         msg_Err( p_input, "out of memory" );
346         return NULL;
347     }
348
349     /* Initialize the decoder fifo */
350     p_dec->p_module = NULL;
351
352     p_dec->fmt_in = p_es->fmt;
353
354     if( p_es->p_waveformatex )
355     {
356 #define p_wf ((WAVEFORMATEX *)p_es->p_waveformatex)
357         p_dec->fmt_in.audio.i_channels = p_wf->nChannels;
358         p_dec->fmt_in.audio.i_rate = p_wf->nSamplesPerSec;
359         p_dec->fmt_in.i_bitrate = p_wf->nAvgBytesPerSec * 8;
360         p_dec->fmt_in.audio.i_blockalign = p_wf->nBlockAlign;
361         p_dec->fmt_in.audio.i_bitspersample = p_wf->wBitsPerSample;
362         p_dec->fmt_in.i_extra = p_wf->cbSize;
363         p_dec->fmt_in.p_extra = NULL;
364         if( p_wf->cbSize )
365         {
366             p_dec->fmt_in.p_extra = malloc( p_wf->cbSize );
367             memcpy( p_dec->fmt_in.p_extra, &p_wf[1], p_wf->cbSize );
368         }
369     }
370
371     if( p_es->p_bitmapinfoheader )
372     {
373 #define p_bih ((BITMAPINFOHEADER *) p_es->p_bitmapinfoheader)
374         p_dec->fmt_in.i_extra = p_bih->biSize - sizeof(BITMAPINFOHEADER);
375         p_dec->fmt_in.p_extra = NULL;
376         if( p_dec->fmt_in.i_extra )
377         {
378             p_dec->fmt_in.p_extra = malloc( p_dec->fmt_in.i_extra );
379             memcpy( p_dec->fmt_in.p_extra, &p_bih[1], p_dec->fmt_in.i_extra );
380         }
381
382         p_dec->fmt_in.video.i_width = p_bih->biWidth;
383         p_dec->fmt_in.video.i_height = p_bih->biHeight;
384     }
385
386     p_dec->fmt_in.i_cat = p_es->i_cat;
387     p_dec->fmt_in.i_codec = p_es->i_fourcc;
388
389     p_dec->fmt_out = null_es_format;
390
391     /* Allocate our private structure for the decoder */
392     p_dec->p_owner = (decoder_owner_sys_t*)malloc(sizeof(decoder_owner_sys_t));
393     if( p_dec->p_owner == NULL )
394     {
395         msg_Err( p_dec, "out of memory" );
396         return NULL;
397     }
398     p_dec->p_owner->p_aout = NULL;
399     p_dec->p_owner->p_aout_input = NULL;
400     p_dec->p_owner->p_vout = NULL;
401     p_dec->p_owner->p_sout = NULL;
402
403     /* Set buffers allocation callbacks for the decoders */
404     p_dec->pf_aout_buffer_new = aout_new_buffer;
405     p_dec->pf_aout_buffer_del = aout_del_buffer;
406     p_dec->pf_vout_buffer_new = vout_new_buffer;
407     p_dec->pf_vout_buffer_del = vout_del_buffer;
408
409     /* For old decoders only */
410     vlc_mutex_init( p_input, &p_dec->p_fifo->data_lock );
411     vlc_cond_init( p_input, &p_dec->p_fifo->data_wait );
412     p_es->p_decoder_fifo = p_dec->p_fifo;
413     p_dec->p_fifo->i_id = p_es->i_id;
414     p_dec->p_fifo->i_fourcc = p_es->i_fourcc;
415     p_dec->p_fifo->p_demux_data   = p_es->p_demux_data;
416     p_dec->p_fifo->p_waveformatex = p_es->p_waveformatex;
417     p_dec->p_fifo->p_bitmapinfoheader = p_es->p_bitmapinfoheader;
418     p_dec->p_fifo->p_spuinfo = p_es->p_spuinfo;
419     p_dec->p_fifo->p_stream_ctrl = &p_input->stream.control;
420     p_dec->p_fifo->p_sout = p_input->stream.p_sout;
421     p_dec->p_fifo->p_first = NULL;
422     p_dec->p_fifo->pp_last = &p_dec->p_fifo->p_first;
423     p_dec->p_fifo->i_depth = 0;
424     p_dec->p_fifo->b_die = p_dec->p_fifo->b_error = 0;
425     p_dec->p_fifo->p_packets_mgt = p_input->p_method_data;
426     p_dec->p_fifo->p_dec = p_dec;
427     vlc_object_attach( p_dec->p_fifo, p_input );
428
429     vlc_object_attach( p_dec, p_input );
430
431     return p_dec;
432 }
433
434 /*****************************************************************************
435  * DecoderThread: the decoding main loop
436  *****************************************************************************/
437 static int DecoderThread( decoder_t * p_dec )
438 {
439     pes_packet_t  *p_pes;
440     data_packet_t *p_data;
441     block_t       *p_block;
442
443     /* Temporary wrapper to keep old decoder api functional */
444     if( p_dec->pf_run )
445     {
446         p_dec->pf_run( p_dec->p_fifo );
447         return 0;
448     }
449
450     /* The decoder's main loop */
451     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
452     {
453         int i_size;
454
455         input_ExtractPES( p_dec->p_fifo, &p_pes );
456         if( !p_pes )
457         {
458             p_dec->p_fifo->b_error = 1;
459             break;
460         }
461
462         for( i_size = 0, p_data = p_pes->p_first;
463              p_data != NULL; p_data = p_data->p_next )
464         {
465             i_size += p_data->p_payload_end - p_data->p_payload_start;
466         }
467         p_block = block_New( p_dec, i_size );
468         for( i_size = 0, p_data = p_pes->p_first;
469              p_data != NULL; p_data = p_data->p_next )
470         {
471             if( p_data->p_payload_end == p_data->p_payload_start )
472                 continue;
473             memcpy( p_block->p_buffer + i_size, p_data->p_payload_start,
474                     p_data->p_payload_end - p_data->p_payload_start );
475             i_size += p_data->p_payload_end - p_data->p_payload_start;
476         }
477
478         p_block->i_pts = p_pes->i_pts;
479         p_block->i_dts = p_pes->i_dts;
480         p_block->b_discontinuity = p_pes->b_discontinuity;
481
482         if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
483         {
484             block_t *p_sout_block;
485
486             while( (p_sout_block = p_dec->pf_packetize( p_dec, &p_block )) )
487             {
488                 if( !p_dec->p_owner->p_sout )
489                 {
490                     es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
491
492                     p_dec->p_owner->p_sout =
493                         sout_InputNew( p_dec, &p_dec->p_owner->sout );
494
495                     if( p_dec->p_owner->p_sout == NULL )
496                     {
497                         msg_Err( p_dec, "cannot create packetizer output" );
498                         break;
499                     }
500                 }
501
502                 while( p_sout_block )
503                 {
504                     block_t       *p_next = p_sout_block->p_next;
505                     sout_buffer_t *p_sout_buffer;
506
507                     p_sout_buffer =
508                         sout_BufferNew( p_dec->p_owner->p_sout->p_sout,
509                                         p_sout_block->i_buffer );
510                     if( p_sout_buffer == NULL )
511                     {
512                         msg_Err( p_dec, "cannot get sout buffer" );
513                         break;
514                     }
515
516                     memcpy( p_sout_buffer->p_buffer, p_sout_block->p_buffer,
517                             p_sout_block->i_buffer );
518
519                     p_sout_buffer->i_pts = p_sout_block->i_pts;
520                     p_sout_buffer->i_dts = p_sout_block->i_dts;
521                     p_sout_buffer->i_length = p_sout_block->i_length;
522
523                     block_Release( p_sout_block );
524
525                     sout_InputSendBuffer( p_dec->p_owner->p_sout, p_sout_buffer );
526
527                     p_sout_block = p_next;
528                 }
529             }
530         }
531         else if( p_dec->fmt_in.i_cat == AUDIO_ES )
532         {
533             aout_buffer_t *p_aout_buf;
534
535             while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
536             {
537                 aout_DecPlay( p_dec->p_owner->p_aout,
538                               p_dec->p_owner->p_aout_input, p_aout_buf );
539             }
540         }
541         else if( p_dec->fmt_in.i_cat == VIDEO_ES )
542         {
543             picture_t *p_pic;
544
545             while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
546             {
547                 vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date );
548                 vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
549             }
550         }
551         else if( p_dec->fmt_in.i_cat == SPU_ES )
552         {
553             p_dec->pf_decode_sub( p_dec, &p_block );
554         }
555         else
556         {
557             msg_Err( p_dec, "unknown ES format !!" );
558             p_dec->p_fifo->b_error = 1;
559             break;
560         }
561
562         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
563     }
564
565     while( !p_dec->p_fifo->b_die )
566     {
567         /* Trash all received PES packets */
568         input_ExtractPES( p_dec->p_fifo, NULL );
569     }
570
571     return 0;
572 }
573
574 /*****************************************************************************
575  * DeleteDecoder: destroys a decoder object
576  *****************************************************************************/
577 static void DeleteDecoder( decoder_t * p_dec )
578 {
579     vlc_object_detach( p_dec );
580     vlc_object_detach( p_dec->p_fifo );
581
582     msg_Dbg( p_dec,
583              "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
584              p_dec->p_fifo->i_id, (char*)&p_dec->p_fifo->i_fourcc,
585              p_dec->p_fifo->i_depth );
586
587     /* Free all packets still in the decoder fifo. */
588     input_DeletePES( p_dec->p_fifo->p_packets_mgt,
589                      p_dec->p_fifo->p_first );
590
591     /* Destroy the lock and cond */
592     vlc_cond_destroy( &p_dec->p_fifo->data_wait );
593     vlc_mutex_destroy( &p_dec->p_fifo->data_lock );
594
595     /* Free fifo */
596     vlc_object_destroy( p_dec->p_fifo );
597
598     /* Cleanup */
599     if( p_dec->p_owner->p_aout_input )
600         aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
601
602     if( p_dec->p_owner->p_vout )
603     {
604         int i_pic;
605
606         /* Hack to make sure all the the pictures are freed by the decoder */
607         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
608              i_pic++ )
609         {
610             if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_status ==
611                 RESERVED_PICTURE )
612                 vout_DestroyPicture( p_dec->p_owner->p_vout,
613                     p_dec->p_owner->p_vout->render.pp_picture[i_pic] );
614             if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_refcount
615                 > 0 )
616                 vout_UnlinkPicture( p_dec->p_owner->p_vout,
617                     p_dec->p_owner->p_vout->render.pp_picture[i_pic] );
618         }
619
620         /* We are about to die. Reattach video output to p_vlc. */
621         vout_Request( p_dec, p_dec->p_owner->p_vout, 0, 0, 0, 0 );
622     }
623
624     if( p_dec->p_owner->p_sout )
625         sout_InputDelete( p_dec->p_owner->p_sout );
626
627     free( p_dec->p_owner );
628
629 }
630
631 /*****************************************************************************
632  * Buffers allocation callbacks for the decoders
633  *****************************************************************************/
634 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
635 {
636     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
637     aout_buffer_t *p_buffer;
638
639     if( p_sys->p_aout_input != NULL &&
640         ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate ||
641           p_dec->fmt_out.audio.i_original_channels !=
642               p_sys->audio.i_original_channels ||
643           p_dec->fmt_out.audio.i_bytes_per_frame !=
644               p_sys->audio.i_bytes_per_frame ) )
645     {
646         /* Parameters changed, restart the aout */
647         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
648         p_sys->p_aout_input = NULL;
649     }
650
651     if( p_sys->p_aout_input == NULL )
652     {
653         p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
654         p_sys->audio = p_dec->fmt_out.audio;
655         p_sys->p_aout_input =
656             aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->audio );
657         if( p_sys->p_aout_input == NULL )
658         {
659             msg_Err( p_dec, "failed to create audio output" );
660             return NULL;
661         }
662         p_dec->fmt_out.audio.i_bytes_per_frame =
663             p_sys->audio.i_bytes_per_frame;
664     }
665
666     p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
667                                   i_samples );
668
669     return p_buffer;
670 }
671
672 static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
673 {
674     aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
675                           p_dec->p_owner->p_aout_input, p_buffer );
676 }
677
678 static picture_t *vout_new_buffer( decoder_t *p_dec )
679 {
680     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
681     picture_t *p_pic;
682
683     if( p_sys->p_vout == NULL ||
684         p_dec->fmt_out.video.i_width != p_sys->video.i_width ||
685         p_dec->fmt_out.video.i_height != p_sys->video.i_height ||
686         p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma ||
687         p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect )
688     {
689         if( !p_dec->fmt_out.video.i_width ||
690             !p_dec->fmt_out.video.i_height )
691         {
692             /* Can't create a new vout without display size */
693             return NULL;
694         }
695
696         p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
697         p_sys->video = p_dec->fmt_out.video;
698
699         p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
700                                       p_sys->video.i_width,
701                                       p_sys->video.i_height,
702                                       p_sys->video.i_chroma,
703                                       p_sys->video.i_aspect );
704
705         if( p_sys->p_vout == NULL )
706         {
707             msg_Err( p_dec, "failed to create video output" );
708             return NULL;
709         }
710     }
711
712     /* Get a new picture */
713     while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
714     {
715         if( p_dec->b_die || p_dec->b_error )
716         {
717             return NULL;
718         }
719         msleep( VOUT_OUTMEM_SLEEP );
720     }
721
722     return p_pic;
723 }
724
725 static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
726 {
727     vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
728 }