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