]> git.sesse.net Git - vlc/blob - src/input/input_dec.c
2c8bdeac7136a93a335b7c390e6ba784be229f01
[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.71 2003/11/18 22:48:46 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     sout_format_t           sout_format;
307
308     /* Current format in use by the output */
309     video_format_t video;
310     audio_format_t audio; 
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                     sout_format_t *p_format = &p_dec->p_owner->sout_format;
491
492                     p_format->i_cat = p_dec->fmt_out.i_cat;
493                     p_format->i_fourcc = p_dec->fmt_out.i_codec;
494                     p_format->i_sample_rate =
495                         p_dec->fmt_out.audio.i_rate;
496                     p_format->i_channels =
497                         p_dec->fmt_out.audio.i_channels;
498                     p_format->i_block_align =
499                         p_dec->fmt_out.audio.i_blockalign;
500                     p_format->i_width  =
501                         p_dec->fmt_out.video.i_width;
502                     p_format->i_height =
503                         p_dec->fmt_out.video.i_height;
504                     p_format->i_bitrate     = p_dec->fmt_out.i_bitrate;
505                     p_format->i_extra_data  = p_dec->fmt_out.i_extra;
506                     p_format->p_extra_data  = p_dec->fmt_out.p_extra;
507
508                     p_dec->p_owner->p_sout =
509                         sout_InputNew( p_dec, p_format );
510
511                     if( p_dec->p_owner->p_sout == NULL )
512                     {
513                         msg_Err( p_dec, "cannot create packetizer output" );
514                         break;
515                     }
516                 }
517
518                 while( p_sout_block )
519                 {
520                     block_t       *p_next = p_sout_block->p_next;
521                     sout_buffer_t *p_sout_buffer;
522
523                     p_sout_buffer =
524                         sout_BufferNew( p_dec->p_owner->p_sout->p_sout,
525                                         p_sout_block->i_buffer );
526                     if( p_sout_buffer == NULL )
527                     {
528                         msg_Err( p_dec, "cannot get sout buffer" );
529                         break;
530                     }
531
532                     memcpy( p_sout_buffer->p_buffer, p_sout_block->p_buffer,
533                             p_sout_block->i_buffer );
534
535                     p_sout_buffer->i_pts = p_sout_block->i_pts;
536                     p_sout_buffer->i_dts = p_sout_block->i_dts;
537                     p_sout_buffer->i_length = p_sout_block->i_length;
538
539                     block_Release( p_sout_block );
540
541                     sout_InputSendBuffer( p_dec->p_owner->p_sout, p_sout_buffer );
542
543                     p_sout_block = p_next;
544                 }
545             }
546         }
547         else if( p_dec->fmt_in.i_cat == AUDIO_ES )
548         {
549             aout_buffer_t *p_aout_buf;
550
551             while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
552             {
553                 aout_DecPlay( p_dec->p_owner->p_aout,
554                               p_dec->p_owner->p_aout_input, p_aout_buf );
555             }
556         }
557         else if( p_dec->fmt_in.i_cat == VIDEO_ES )
558         {
559             picture_t *p_pic;
560
561             while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
562             {
563                 vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date );
564                 vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
565             }
566         }
567         else if( p_dec->fmt_in.i_cat == SPU_ES )
568         {
569             p_dec->pf_decode_sub( p_dec, &p_block );
570         }
571         else
572         {
573             msg_Err( p_dec, "unknown ES format !!" );
574             p_dec->p_fifo->b_error = 1;
575             break;
576         }
577
578         input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_pes );
579     }
580
581     while( !p_dec->p_fifo->b_die )
582     {
583         /* Trash all received PES packets */
584         input_ExtractPES( p_dec->p_fifo, NULL );
585     }
586
587     return 0;
588 }
589
590 /*****************************************************************************
591  * DeleteDecoder: destroys a decoder object
592  *****************************************************************************/
593 static void DeleteDecoder( decoder_t * p_dec )
594 {
595     vlc_object_detach( p_dec );
596     vlc_object_detach( p_dec->p_fifo );
597
598     msg_Dbg( p_dec,
599              "killing decoder for 0x%x, fourcc `%4.4s', %d PES in FIFO",
600              p_dec->p_fifo->i_id, (char*)&p_dec->p_fifo->i_fourcc,
601              p_dec->p_fifo->i_depth );
602
603     /* Free all packets still in the decoder fifo. */
604     input_DeletePES( p_dec->p_fifo->p_packets_mgt,
605                      p_dec->p_fifo->p_first );
606
607     /* Destroy the lock and cond */
608     vlc_cond_destroy( &p_dec->p_fifo->data_wait );
609     vlc_mutex_destroy( &p_dec->p_fifo->data_lock );
610
611     /* Free fifo */
612     vlc_object_destroy( p_dec->p_fifo );
613
614     /* Cleanup */
615     if( p_dec->p_owner->p_aout_input )
616         aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
617
618     if( p_dec->p_owner->p_vout )
619     {
620         int i_pic;
621
622         /* Hack to make sure all the the pictures are freed by the decoder */
623         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
624              i_pic++ )
625         {
626             if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_status ==
627                 RESERVED_PICTURE )
628                 vout_DestroyPicture( p_dec->p_owner->p_vout,
629                     p_dec->p_owner->p_vout->render.pp_picture[i_pic] );
630             if( p_dec->p_owner->p_vout->render.pp_picture[i_pic]->i_refcount
631                 > 0 )
632                 vout_UnlinkPicture( p_dec->p_owner->p_vout,
633                     p_dec->p_owner->p_vout->render.pp_picture[i_pic] );
634         }
635
636         /* We are about to die. Reattach video output to p_vlc. */
637         vout_Request( p_dec, p_dec->p_owner->p_vout, 0, 0, 0, 0 );
638     }
639
640     if( p_dec->p_owner->p_sout )
641         sout_InputDelete( p_dec->p_owner->p_sout );
642
643     free( p_dec->p_owner );
644
645 }
646
647 /*****************************************************************************
648  * Buffers allocation callbacks for the decoders
649  *****************************************************************************/
650 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
651 {
652     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
653     aout_buffer_t *p_buffer;
654
655     if( p_sys->p_aout_input != NULL &&
656         ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate ||
657           p_dec->fmt_out.audio.i_original_channels !=
658               p_sys->audio.i_original_channels ||
659           p_dec->fmt_out.audio.i_bytes_per_frame !=
660               p_sys->audio.i_bytes_per_frame ) )
661     {
662         /* Parameters changed, restart the aout */
663         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
664         p_sys->p_aout_input = NULL;
665     }
666
667     if( p_sys->p_aout_input == NULL )
668     {
669         p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
670         p_sys->audio = p_dec->fmt_out.audio;
671         p_sys->p_aout_input =
672             aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->audio );
673         if( p_sys->p_aout_input == NULL )
674         {
675             msg_Err( p_dec, "failed to create audio output" );
676             return NULL;
677         }
678         p_dec->fmt_out.audio.i_bytes_per_frame =
679             p_sys->audio.i_bytes_per_frame;
680     }
681
682     p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
683                                   i_samples );
684
685     return p_buffer;
686 }
687
688 static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
689 {
690     aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
691                           p_dec->p_owner->p_aout_input, p_buffer );
692 }
693
694 static picture_t *vout_new_buffer( decoder_t *p_dec )
695 {
696     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
697     picture_t *p_pic;
698
699     if( p_sys->p_vout == NULL ||
700         p_dec->fmt_out.video.i_width != p_sys->video.i_width ||
701         p_dec->fmt_out.video.i_height != p_sys->video.i_height ||
702         p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma ||
703         p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect )
704     {
705         if( !p_dec->fmt_out.video.i_width ||
706             !p_dec->fmt_out.video.i_height )
707         {
708             /* Can't create a new vout without display size */
709             return NULL;
710         }
711
712         p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
713         p_sys->video = p_dec->fmt_out.video;
714
715         p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
716                                       p_sys->video.i_width,
717                                       p_sys->video.i_height,
718                                       p_sys->video.i_chroma,
719                                       p_sys->video.i_aspect );
720
721         if( p_sys->p_vout == NULL )
722         {
723             msg_Err( p_dec, "failed to create video output" );
724             return NULL;
725         }
726     }
727
728     /* Get a new picture */
729     while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
730     {
731         if( p_dec->b_die || p_dec->b_error )
732         {
733             return NULL;
734         }
735         msleep( VOUT_OUTMEM_SLEEP );
736     }
737
738     return p_pic;
739 }
740
741 static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
742 {
743     vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
744 }