Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

decoder.c

00001 /*****************************************************************************
00002  * decoder.c: Functions for the management of decoders
00003  *****************************************************************************
00004  * Copyright (C) 1999-2004 the VideoLAN team
00005  * $Id: decoder.c 13055 2005-10-31 13:14:23Z md $
00006  *
00007  * Authors: Christophe Massiot <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *          Laurent Aimar <[email protected]>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027  * Preamble
00028  *****************************************************************************/
00029 #include <stdlib.h>
00030 #include <vlc/vlc.h>
00031 
00032 #include <vlc/decoder.h>
00033 #include <vlc/vout.h>
00034 #include <vlc/input.h>
00035 
00036 #include "stream_output.h"
00037 #include "input_internal.h"
00038 
00039 static decoder_t * CreateDecoder( input_thread_t *, es_format_t *, int );
00040 static void        DeleteDecoder( decoder_t * );
00041 
00042 static int         DecoderThread( decoder_t * );
00043 static int         DecoderDecode( decoder_t * p_dec, block_t *p_block );
00044 
00045 /* Buffers allocation callbacks for the decoders */
00046 static aout_buffer_t *aout_new_buffer( decoder_t *, int );
00047 static void aout_del_buffer( decoder_t *, aout_buffer_t * );
00048 
00049 static picture_t *vout_new_buffer( decoder_t * );
00050 static void vout_del_buffer( decoder_t *, picture_t * );
00051 static void vout_link_picture( decoder_t *, picture_t * );
00052 static void vout_unlink_picture( decoder_t *, picture_t * );
00053 
00054 static subpicture_t *spu_new_buffer( decoder_t * );
00055 static void spu_del_buffer( decoder_t *, subpicture_t * );
00056 
00057 static es_format_t null_es_format = {0};
00058 
00059 struct decoder_owner_sys_t
00060 {
00061     vlc_bool_t      b_own_thread;
00062 
00063     int64_t         i_preroll_end;
00064 
00065     input_thread_t  *p_input;
00066 
00067     aout_instance_t *p_aout;
00068     aout_input_t    *p_aout_input;
00069 
00070     vout_thread_t   *p_vout;
00071 
00072     vout_thread_t   *p_spu_vout;
00073     int              i_spu_channel;
00074 
00075     sout_instance_t         *p_sout;
00076     sout_packetizer_input_t *p_sout_input;
00077 
00078     /* Some decoders require already packetized data (ie. not truncated) */
00079     decoder_t *p_packetizer;
00080 
00081     /* Current format in use by the output */
00082     video_format_t video;
00083     audio_format_t audio;
00084     es_format_t    sout;
00085 
00086     /* fifo */
00087     block_fifo_t *p_fifo;
00088 };
00089 
00090 
00098 decoder_t *input_DecoderNew( input_thread_t *p_input,
00099                              es_format_t *fmt, vlc_bool_t b_force_decoder )
00100 {
00101     decoder_t   *p_dec = NULL;
00102     vlc_value_t val;
00103 
00104     /* If we are in sout mode, search for packetizer module */
00105     if( p_input->p_sout && !b_force_decoder )
00106     {
00107         /* Create the decoder configuration structure */
00108         p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_PACKETIZER );
00109         if( p_dec == NULL )
00110         {
00111             msg_Err( p_input, "could not create packetizer" );
00112             return NULL;
00113         }
00114     }
00115     else
00116     {
00117         /* Create the decoder configuration structure */
00118         p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_DECODER );
00119         if( p_dec == NULL )
00120         {
00121             msg_Err( p_input, "could not create decoder" );
00122             return NULL;
00123         }
00124     }
00125 
00126     if( !p_dec->p_module )
00127     {
00128         msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
00129                  "VLC probably does not support this sound or video format.",
00130                  (char*)&p_dec->fmt_in.i_codec );
00131 
00132         DeleteDecoder( p_dec );
00133         vlc_object_destroy( p_dec );
00134         return NULL;
00135     }
00136 
00137     if( p_input->p_sout && p_input->input.b_can_pace_control &&
00138         !b_force_decoder )
00139     {
00140         msg_Dbg( p_input, "stream out mode -> no decoder thread" );
00141         p_dec->p_owner->b_own_thread = VLC_FALSE;
00142     }
00143     else
00144     {
00145         var_Get( p_input, "minimize-threads", &val );
00146         p_dec->p_owner->b_own_thread = !val.b_bool;
00147     }
00148 
00149     if( p_dec->p_owner->b_own_thread )
00150     {
00151         int i_priority;
00152         if( fmt->i_cat == AUDIO_ES )
00153             i_priority = VLC_THREAD_PRIORITY_AUDIO;
00154         else
00155             i_priority = VLC_THREAD_PRIORITY_VIDEO;
00156 
00157         /* Spawn the decoder thread */
00158         if( vlc_thread_create( p_dec, "decoder", DecoderThread,
00159                                i_priority, VLC_FALSE ) )
00160         {
00161             msg_Err( p_dec, "cannot spawn decoder thread \"%s\"",
00162                              p_dec->p_module->psz_object_name );
00163             module_Unneed( p_dec, p_dec->p_module );
00164             DeleteDecoder( p_dec );
00165             vlc_object_destroy( p_dec );
00166             return NULL;
00167         }
00168     }
00169 
00170     return p_dec;
00171 }
00172 
00180 void input_DecoderDelete( decoder_t *p_dec )
00181 {
00182     p_dec->b_die = VLC_TRUE;
00183 
00184     if( p_dec->p_owner->b_own_thread )
00185     {
00186         /* Make sure the thread leaves the function by
00187          * sending it an empty block. */
00188         block_t *p_block = block_New( p_dec, 0 );
00189         input_DecoderDecode( p_dec, p_block );
00190 
00191         vlc_thread_join( p_dec );
00192 
00193         /* Don't module_Unneed() here because of the dll loader that wants
00194          * close() in the same thread than open()/decode() */
00195     }
00196     else
00197     {
00198         /* Flush */
00199         input_DecoderDecode( p_dec, NULL );
00200 
00201         module_Unneed( p_dec, p_dec->p_module );
00202     }
00203 
00204     /* Delete decoder configuration */
00205     DeleteDecoder( p_dec );
00206 
00207     /* Delete the decoder */
00208     vlc_object_destroy( p_dec );
00209 }
00210 
00217 void input_DecoderDecode( decoder_t * p_dec, block_t *p_block )
00218 {
00219     if( p_dec->p_owner->b_own_thread )
00220     {
00221         if( p_dec->p_owner->p_input->b_out_pace_control )
00222         {
00223             /* FIXME !!!!! */
00224             while( !p_dec->b_die && !p_dec->b_error &&
00225                    p_dec->p_owner->p_fifo->i_depth > 10 )
00226             {
00227                 msleep( 1000 );
00228             }
00229         }
00230         else if( p_dec->p_owner->p_fifo->i_size > 50000000 /* 50 MB */ )
00231         {
00232             /* FIXME: ideally we would check the time amount of data
00233              * in the fifo instead of its size. */
00234             msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
00235                       "consummed quickly enough), resetting fifo!" );
00236             block_FifoEmpty( p_dec->p_owner->p_fifo );
00237         }
00238 
00239         block_FifoPut( p_dec->p_owner->p_fifo, p_block );
00240     }
00241     else
00242     {
00243         if( p_dec->b_error || (p_block && p_block->i_buffer <= 0) )
00244         {
00245             if( p_block ) block_Release( p_block );
00246         }
00247         else
00248         {
00249             DecoderDecode( p_dec, p_block );
00250         }
00251     }
00252 }
00253 
00254 void input_DecoderDiscontinuity( decoder_t * p_dec )
00255 {
00256     block_t *p_null;
00257 
00258     /* Empty the fifo */
00259     if( p_dec->p_owner->b_own_thread )
00260     {
00261         block_FifoEmpty( p_dec->p_owner->p_fifo );
00262     }
00263 
00264     /* Send a special block */
00265     p_null = block_New( p_dec, 128 );
00266     p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
00267     memset( p_null->p_buffer, 0, p_null->i_buffer );
00268 
00269     input_DecoderDecode( p_dec, p_null );
00270 }
00271 
00272 vlc_bool_t input_DecoderEmpty( decoder_t * p_dec )
00273 {
00274     if( p_dec->p_owner->b_own_thread && p_dec->p_owner->p_fifo->i_depth > 0 )
00275     {
00276         return VLC_FALSE;
00277     }
00278     return VLC_TRUE;
00279 }
00280 
00281 void input_DecoderPreroll( decoder_t *p_dec, int64_t i_preroll_end )
00282 {
00283     p_dec->p_owner->i_preroll_end = i_preroll_end;
00284 }
00285 
00286 #if 0
00287 
00294 static void input_NullPacket( input_thread_t * p_input,
00295                               es_descriptor_t * p_es )
00296 {
00297 #if 0
00298     block_t *p_block = block_New( p_input, PADDING_PACKET_SIZE );
00299     if( p_block )
00300     {
00301         memset( p_block->p_buffer, 0, PADDING_PACKET_SIZE );
00302         p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
00303 
00304         block_FifoPut( p_es->p_dec->p_owner->p_fifo, p_block );
00305     }
00306 #endif
00307 }
00308 
00315 void input_EscapeDiscontinuity( input_thread_t * p_input )
00316 {
00317 #if 0
00318     unsigned int i_es, i;
00319 
00320     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
00321     {
00322         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
00323 
00324         if( p_es->p_dec != NULL )
00325         {
00326             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
00327             {
00328                 input_NullPacket( p_input, p_es );
00329             }
00330         }
00331     }
00332 #endif
00333 }
00334 
00341 void input_EscapeAudioDiscontinuity( input_thread_t * p_input )
00342 {
00343 #if 0
00344     unsigned int i_es, i;
00345 
00346     for( i_es = 0; i_es < p_input->stream.i_selected_es_number; i_es++ )
00347     {
00348         es_descriptor_t * p_es = p_input->stream.pp_selected_es[i_es];
00349 
00350         if( p_es->p_dec != NULL && p_es->i_cat == AUDIO_ES )
00351         {
00352             for( i = 0; i < PADDING_PACKET_NUMBER; i++ )
00353             {
00354                 input_NullPacket( p_input, p_es );
00355             }
00356         }
00357     }
00358 #endif
00359 }
00360 #endif
00361 
00370 static decoder_t * CreateDecoder( input_thread_t *p_input,
00371                                   es_format_t *fmt, int i_object_type )
00372 {
00373     decoder_t *p_dec;
00374 
00375     p_dec = vlc_object_create( p_input, i_object_type );
00376     if( p_dec == NULL )
00377     {
00378         msg_Err( p_input, "out of memory" );
00379         return NULL;
00380     }
00381 
00382     p_dec->pf_decode_audio = 0;
00383     p_dec->pf_decode_video = 0;
00384     p_dec->pf_decode_sub = 0;
00385     p_dec->pf_packetize = 0;
00386 
00387     /* Initialize the decoder fifo */
00388     p_dec->p_module = NULL;
00389 
00390 
00391     es_format_Copy( &p_dec->fmt_in, fmt );
00392     es_format_Copy( &p_dec->fmt_out, &null_es_format );
00393 
00394     /* Allocate our private structure for the decoder */
00395     p_dec->p_owner = malloc( sizeof( decoder_owner_sys_t ) );
00396     if( p_dec->p_owner == NULL )
00397     {
00398         msg_Err( p_dec, "out of memory" );
00399         return NULL;
00400     }
00401     p_dec->p_owner->b_own_thread = VLC_TRUE;
00402     p_dec->p_owner->i_preroll_end = -1;
00403     p_dec->p_owner->p_input = p_input;
00404     p_dec->p_owner->p_aout = NULL;
00405     p_dec->p_owner->p_aout_input = NULL;
00406     p_dec->p_owner->p_vout = NULL;
00407     p_dec->p_owner->p_spu_vout = NULL;
00408     p_dec->p_owner->i_spu_channel = 0;
00409     p_dec->p_owner->p_sout = p_input->p_sout;
00410     p_dec->p_owner->p_sout_input = NULL;
00411     p_dec->p_owner->p_packetizer = NULL;
00412 
00413     /* decoder fifo */
00414     if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL )
00415     {
00416         msg_Err( p_dec, "out of memory" );
00417         return NULL;
00418     }
00419 
00420     /* Set buffers allocation callbacks for the decoders */
00421     p_dec->pf_aout_buffer_new = aout_new_buffer;
00422     p_dec->pf_aout_buffer_del = aout_del_buffer;
00423     p_dec->pf_vout_buffer_new = vout_new_buffer;
00424     p_dec->pf_vout_buffer_del = vout_del_buffer;
00425     p_dec->pf_picture_link    = vout_link_picture;
00426     p_dec->pf_picture_unlink  = vout_unlink_picture;
00427     p_dec->pf_spu_buffer_new  = spu_new_buffer;
00428     p_dec->pf_spu_buffer_del  = spu_del_buffer;
00429 
00430     vlc_object_attach( p_dec, p_input );
00431 
00432     /* Find a suitable decoder/packetizer module */
00433     if( i_object_type == VLC_OBJECT_DECODER )
00434         p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );
00435     else
00436         p_dec->p_module = module_Need( p_dec, "packetizer", "$packetizer", 0 );
00437 
00438     /* Check if decoder requires already packetized data */
00439     if( i_object_type == VLC_OBJECT_DECODER &&
00440         p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
00441     {
00442         p_dec->p_owner->p_packetizer =
00443             vlc_object_create( p_input, VLC_OBJECT_PACKETIZER );
00444         if( p_dec->p_owner->p_packetizer )
00445         {
00446             es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in,
00447                             &p_dec->fmt_in );
00448 
00449             es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_out,
00450                             &null_es_format );
00451 
00452             vlc_object_attach( p_dec->p_owner->p_packetizer, p_input );
00453 
00454             p_dec->p_owner->p_packetizer->p_module =
00455                 module_Need( p_dec->p_owner->p_packetizer,
00456                              "packetizer", "$packetizer", 0 );
00457 
00458             if( !p_dec->p_owner->p_packetizer->p_module )
00459             {
00460                 es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
00461                 vlc_object_detach( p_dec->p_owner->p_packetizer );
00462                 vlc_object_destroy( p_dec->p_owner->p_packetizer );
00463             }
00464         }
00465     }
00466 
00467     return p_dec;
00468 }
00469 
00476 static int DecoderThread( decoder_t * p_dec )
00477 {
00478     block_t *p_block;
00479 
00480     /* The decoder's main loop */
00481     while( !p_dec->b_die && !p_dec->b_error )
00482     {
00483         if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL )
00484         {
00485             p_dec->b_error = 1;
00486             break;
00487         }
00488         if( DecoderDecode( p_dec, p_block ) != VLC_SUCCESS )
00489         {
00490             break;
00491         }
00492     }
00493 
00494     while( !p_dec->b_die )
00495     {
00496         /* Trash all received PES packets */
00497         p_block = block_FifoGet( p_dec->p_owner->p_fifo );
00498         if( p_block ) block_Release( p_block );
00499     }
00500 
00501     /* We do it here because of the dll loader that wants close() in the
00502      * same thread than open()/decode() */
00503     module_Unneed( p_dec, p_dec->p_module );
00504 
00505     return 0;
00506 }
00507 
00515 static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
00516 {
00517     int i_rate = p_block ? p_block->i_rate : 1000;
00518 
00519     if( p_block && p_block->i_buffer <= 0 )
00520     {
00521         block_Release( p_block );
00522         return VLC_SUCCESS;
00523     }
00524 
00525     if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
00526     {
00527         block_t *p_sout_block;
00528 
00529         while( ( p_sout_block =
00530                      p_dec->pf_packetize( p_dec, p_block ? &p_block : 0 ) ) )
00531         {
00532             if( !p_dec->p_owner->p_sout_input )
00533             {
00534                 es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
00535 
00536                 p_dec->p_owner->sout.i_group = p_dec->fmt_in.i_group;
00537                 p_dec->p_owner->sout.i_id = p_dec->fmt_in.i_id;
00538                 if( p_dec->fmt_in.psz_language )
00539                 {
00540                     if( p_dec->p_owner->sout.psz_language )
00541                         free( p_dec->p_owner->sout.psz_language );
00542                     p_dec->p_owner->sout.psz_language =
00543                         strdup( p_dec->fmt_in.psz_language );
00544                 }
00545 
00546                 p_dec->p_owner->p_sout_input =
00547                     sout_InputNew( p_dec->p_owner->p_sout,
00548                                    &p_dec->p_owner->sout );
00549 
00550                 if( p_dec->p_owner->p_sout_input == NULL )
00551                 {
00552                     msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
00553                              (char *)&p_dec->p_owner->sout.i_codec );
00554                     p_dec->b_error = VLC_TRUE;
00555 
00556                     while( p_sout_block )
00557                     {
00558                         block_t *p_next = p_sout_block->p_next;
00559                         block_Release( p_sout_block );
00560                         p_sout_block = p_next;
00561                     }
00562                     break;
00563                 }
00564             }
00565 
00566             while( p_sout_block )
00567             {
00568                 block_t *p_next = p_sout_block->p_next;
00569 
00570                 p_sout_block->p_next = NULL;
00571                 p_sout_block->i_rate = i_rate;
00572 
00573                 sout_InputSendBuffer( p_dec->p_owner->p_sout_input,
00574                                       p_sout_block );
00575 
00576                 p_sout_block = p_next;
00577             }
00578 
00579             /* For now it's enough, as only sout inpact on this flag */
00580             if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 &&
00581                 p_dec->p_owner->p_input->b_out_pace_control )
00582             {
00583                 msg_Dbg( p_dec, "switching to synch mode" );
00584                 p_dec->p_owner->p_input->b_out_pace_control = VLC_FALSE;
00585             }
00586             else if( p_dec->p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
00587                      !p_dec->p_owner->p_input->b_out_pace_control )
00588             {
00589                 msg_Dbg( p_dec, "switching to asynch mode" );
00590                 p_dec->p_owner->p_input->b_out_pace_control = VLC_TRUE;
00591             }
00592         }
00593     }
00594     else if( p_dec->fmt_in.i_cat == AUDIO_ES )
00595     {
00596         aout_buffer_t *p_aout_buf;
00597 
00598         if( p_dec->p_owner->p_packetizer )
00599         {
00600             block_t *p_packetized_block;
00601             decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
00602 
00603             while( (p_packetized_block =
00604                     p_packetizer->pf_packetize( p_packetizer, &p_block )) )
00605             {
00606                 if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
00607                 {
00608                     p_dec->fmt_in.i_extra = p_packetizer->fmt_out.i_extra;
00609                     p_dec->fmt_in.p_extra = malloc( p_dec->fmt_in.i_extra );
00610                     memcpy( p_dec->fmt_in.p_extra,
00611                             p_packetizer->fmt_out.p_extra,
00612                             p_dec->fmt_in.i_extra );
00613                 }
00614 
00615                 while( p_packetized_block )
00616                 {
00617                     block_t *p_next = p_packetized_block->p_next;
00618                     p_packetized_block->p_next = NULL;
00619                     p_packetized_block->i_rate = i_rate;
00620 
00621                     while( (p_aout_buf = p_dec->pf_decode_audio( p_dec,
00622                                                        &p_packetized_block )) )
00623                     {
00624                         /* FIXME the best would be to handle the case start_date < preroll < end_date
00625                          * but that's not easy with non raw audio stream */
00626                         if( p_dec->p_owner->i_preroll_end > 0 &&
00627                             p_aout_buf->start_date < p_dec->p_owner->i_preroll_end )
00628                         {
00629                             aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
00630                                                   p_dec->p_owner->p_aout_input, p_aout_buf );
00631                         }
00632                         else
00633                         {
00634                             p_dec->p_owner->i_preroll_end = -1;
00635                             aout_DecPlay( p_dec->p_owner->p_aout,
00636                                           p_dec->p_owner->p_aout_input,
00637                                           p_aout_buf );
00638                         }
00639                     }
00640 
00641                     p_packetized_block = p_next;
00642                 }
00643             }
00644         }
00645         else while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
00646         {
00647             if( p_dec->p_owner->i_preroll_end > 0 &&
00648                 p_aout_buf->start_date < p_dec->p_owner->i_preroll_end )
00649             {
00650                 aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
00651                                       p_dec->p_owner->p_aout_input, p_aout_buf );
00652             }
00653             else
00654             {
00655                 p_dec->p_owner->i_preroll_end = -1;
00656                 aout_DecPlay( p_dec->p_owner->p_aout,
00657                               p_dec->p_owner->p_aout_input,
00658                               p_aout_buf );
00659             }
00660         }
00661     }
00662     else if( p_dec->fmt_in.i_cat == VIDEO_ES )
00663     {
00664         picture_t *p_pic;
00665 
00666         if( p_dec->p_owner->p_packetizer )
00667         {
00668             block_t *p_packetized_block;
00669             decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;
00670 
00671             while( (p_packetized_block =
00672                     p_packetizer->pf_packetize( p_packetizer, &p_block )) )
00673             {
00674                 if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
00675                 {
00676                     p_dec->fmt_in.i_extra = p_packetizer->fmt_out.i_extra;
00677                     p_dec->fmt_in.p_extra = malloc( p_dec->fmt_in.i_extra );
00678                     memcpy( p_dec->fmt_in.p_extra,
00679                             p_packetizer->fmt_out.p_extra,
00680                             p_dec->fmt_in.i_extra );
00681                 }
00682 
00683                 while( p_packetized_block )
00684                 {
00685                     block_t *p_next = p_packetized_block->p_next;
00686                     p_packetized_block->p_next = NULL;
00687                     p_packetized_block->i_rate = i_rate;
00688 
00689                     while( (p_pic = p_dec->pf_decode_video( p_dec,
00690                                                        &p_packetized_block )) )
00691                     {
00692                         if( p_dec->p_owner->i_preroll_end > 0 &&
00693                             p_pic->date < p_dec->p_owner->i_preroll_end )
00694                         {
00695                             vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
00696                         }
00697                         else
00698                         {
00699                             p_dec->p_owner->i_preroll_end = -1;
00700                             vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
00701                                               p_pic->date );
00702                             vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
00703                         }
00704                     }
00705 
00706                     p_packetized_block = p_next;
00707                 }
00708             }
00709         }
00710         else while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
00711         {
00712             if( p_dec->p_owner->i_preroll_end > 0 &&
00713                 p_pic->date < p_dec->p_owner->i_preroll_end )
00714             {
00715                 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
00716             }
00717             else
00718             {
00719                 p_dec->p_owner->i_preroll_end = -1;
00720                 vout_DatePicture( p_dec->p_owner->p_vout, p_pic, p_pic->date );
00721                 vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
00722             }
00723         }
00724     }
00725     else if( p_dec->fmt_in.i_cat == SPU_ES )
00726     {
00727         vout_thread_t *p_vout;
00728         subpicture_t *p_spu;
00729         while( (p_spu = p_dec->pf_decode_sub( p_dec, &p_block ) ) )
00730         {
00731             if( p_dec->p_owner->i_preroll_end > 0 &&
00732                 p_spu->i_start < p_dec->p_owner->i_preroll_end &&
00733                 ( p_spu->i_stop <= 0 || p_spu->i_stop <= p_dec->p_owner->i_preroll_end ) )
00734             {
00735                 spu_DestroySubpicture( p_dec->p_owner->p_vout->p_spu, p_spu );
00736                 continue;
00737             }
00738 
00739             p_dec->p_owner->i_preroll_end = -1;
00740             p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
00741             if( p_vout )
00742             {
00743                 spu_DisplaySubpicture( p_vout->p_spu, p_spu );
00744                 vlc_object_release( p_vout );
00745             }
00746         }
00747     }
00748     else
00749     {
00750         msg_Err( p_dec, "unknown ES format" );
00751         p_dec->b_error = 1;
00752     }
00753 
00754     return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;
00755 }
00756 
00763 static void DeleteDecoder( decoder_t * p_dec )
00764 {
00765     msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %d PES in FIFO",
00766              (char*)&p_dec->fmt_in.i_codec,
00767              p_dec->p_owner->p_fifo->i_depth );
00768 
00769     /* Free all packets still in the decoder fifo. */
00770     block_FifoEmpty( p_dec->p_owner->p_fifo );
00771     block_FifoRelease( p_dec->p_owner->p_fifo );
00772 
00773     /* Cleanup */
00774     if( p_dec->p_owner->p_aout_input )
00775         aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
00776 
00777     if( p_dec->p_owner->p_vout )
00778     {
00779         int i_pic;
00780 
00781 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
00782         /* Hack to make sure all the the pictures are freed by the decoder */
00783         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
00784              i_pic++ )
00785         {
00786             if( p_pic->i_status == RESERVED_PICTURE )
00787                 vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
00788             if( p_pic->i_refcount > 0 )
00789                 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
00790         }
00791 #undef p_pic
00792 
00793         /* We are about to die. Reattach video output to p_vlc. */
00794         vout_Request( p_dec, p_dec->p_owner->p_vout, 0 );
00795     }
00796 
00797     if( p_dec->p_owner->p_sout_input )
00798     {
00799         sout_InputDelete( p_dec->p_owner->p_sout_input );
00800         es_format_Clean( &p_dec->p_owner->sout );
00801     }
00802 
00803     if( p_dec->fmt_in.i_cat == SPU_ES )
00804     {
00805         vout_thread_t *p_vout;
00806 
00807         p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
00808         if( p_vout )
00809         {
00810             spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
00811                          p_dec->p_owner->i_spu_channel );
00812             vlc_object_release( p_vout );
00813         }
00814     }
00815 
00816     es_format_Clean( &p_dec->fmt_in );
00817     es_format_Clean( &p_dec->fmt_out );
00818 
00819     if( p_dec->p_owner->p_packetizer )
00820     {
00821         module_Unneed( p_dec->p_owner->p_packetizer,
00822                        p_dec->p_owner->p_packetizer->p_module );
00823         es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
00824         es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_out );
00825         vlc_object_detach( p_dec->p_owner->p_packetizer );
00826         vlc_object_destroy( p_dec->p_owner->p_packetizer );
00827     }
00828 
00829     vlc_object_detach( p_dec );
00830 
00831     free( p_dec->p_owner );
00832 }
00833 
00834 /*****************************************************************************
00835  * Buffers allocation callbacks for the decoders
00836  *****************************************************************************/
00837 static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
00838 {
00839     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
00840     aout_buffer_t *p_buffer;
00841 
00842     if( p_sys->p_aout_input != NULL &&
00843         ( p_dec->fmt_out.audio.i_rate != p_sys->audio.i_rate ||
00844           p_dec->fmt_out.audio.i_original_channels !=
00845               p_sys->audio.i_original_channels ||
00846           p_dec->fmt_out.audio.i_bytes_per_frame !=
00847               p_sys->audio.i_bytes_per_frame ) )
00848     {
00849         /* Parameters changed, restart the aout */
00850         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
00851         p_sys->p_aout_input = NULL;
00852     }
00853 
00854     if( p_sys->p_aout_input == NULL )
00855     {
00856         audio_sample_format_t format;
00857         int i_force_dolby = config_GetInt( p_dec, "force-dolby-surround" );
00858 
00859         p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
00860         p_sys->audio = p_dec->fmt_out.audio;
00861 
00862         memcpy( &format, &p_sys->audio, sizeof( audio_sample_format_t ) );
00863         if ( i_force_dolby && (format.i_original_channels&AOUT_CHAN_PHYSMASK)
00864                                     == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
00865         {
00866             if ( i_force_dolby == 1 )
00867             {
00868                 format.i_original_channels = format.i_original_channels |
00869                                              AOUT_CHAN_DOLBYSTEREO;
00870             }
00871             else /* i_force_dolby == 2 */
00872             {
00873                 format.i_original_channels = format.i_original_channels &
00874                                              ~AOUT_CHAN_DOLBYSTEREO;
00875             }
00876         }
00877 
00878         p_sys->p_aout_input =
00879             aout_DecNew( p_dec, &p_sys->p_aout, &format );
00880         if( p_sys->p_aout_input == NULL )
00881         {
00882             msg_Err( p_dec, "failed to create audio output" );
00883             p_dec->b_error = VLC_TRUE;
00884             return NULL;
00885         }
00886         p_dec->fmt_out.audio.i_bytes_per_frame =
00887             p_sys->audio.i_bytes_per_frame;
00888     }
00889 
00890     p_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
00891                                   i_samples );
00892 
00893     return p_buffer;
00894 }
00895 
00896 static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer )
00897 {
00898     aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
00899                           p_dec->p_owner->p_aout_input, p_buffer );
00900 }
00901 
00902 static picture_t *vout_new_buffer( decoder_t *p_dec )
00903 {
00904     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
00905     picture_t *p_pic;
00906 
00907     if( p_sys->p_vout == NULL ||
00908         p_dec->fmt_out.video.i_width != p_sys->video.i_width ||
00909         p_dec->fmt_out.video.i_height != p_sys->video.i_height ||
00910         p_dec->fmt_out.video.i_chroma != p_sys->video.i_chroma ||
00911         p_dec->fmt_out.video.i_aspect != p_sys->video.i_aspect )
00912     {
00913         if( !p_dec->fmt_out.video.i_width ||
00914             !p_dec->fmt_out.video.i_height )
00915         {
00916             /* Can't create a new vout without display size */
00917             return NULL;
00918         }
00919 
00920         if( !p_dec->fmt_out.video.i_visible_width ||
00921             !p_dec->fmt_out.video.i_visible_height )
00922         {
00923             p_dec->fmt_out.video.i_visible_width =
00924                 p_dec->fmt_out.video.i_width;
00925             p_dec->fmt_out.video.i_visible_height =
00926                 p_dec->fmt_out.video.i_height;
00927         }
00928 
00929         if( p_dec->fmt_out.video.i_visible_height == 1088 &&
00930             var_CreateGetBool( p_dec, "hdtv-fix" ) )
00931         {
00932             p_dec->fmt_out.video.i_visible_height = 1080;
00933             p_dec->fmt_out.video.i_sar_num *= 135; 
00934             p_dec->fmt_out.video.i_sar_den *= 136; 
00935             msg_Warn( p_dec, "Fixing broken HDTV stream (display_height=1088)");
00936         }
00937 
00938         if( !p_dec->fmt_out.video.i_sar_num ||
00939             !p_dec->fmt_out.video.i_sar_den )
00940         {
00941             p_dec->fmt_out.video.i_sar_num = p_dec->fmt_out.video.i_aspect * 
00942               p_dec->fmt_out.video.i_visible_height;
00943 
00944             p_dec->fmt_out.video.i_sar_den = VOUT_ASPECT_FACTOR *
00945               p_dec->fmt_out.video.i_visible_width;
00946         }
00947 
00948         vlc_ureduce( &p_dec->fmt_out.video.i_sar_num,
00949                      &p_dec->fmt_out.video.i_sar_den,
00950                      p_dec->fmt_out.video.i_sar_num,
00951                      p_dec->fmt_out.video.i_sar_den, 50000 );
00952 
00953         p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
00954         p_sys->video = p_dec->fmt_out.video;
00955 
00956         p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
00957                                       &p_dec->fmt_out.video );
00958         if( p_sys->p_vout == NULL )
00959         {
00960             msg_Err( p_dec, "failed to create video output" );
00961             p_dec->b_error = VLC_TRUE;
00962             return NULL;
00963         }
00964 
00965         if( p_sys->video.i_rmask )
00966             p_sys->p_vout->render.i_rmask = p_sys->video.i_rmask;
00967         if( p_sys->video.i_gmask )
00968             p_sys->p_vout->render.i_gmask = p_sys->video.i_gmask;
00969         if( p_sys->video.i_bmask )
00970             p_sys->p_vout->render.i_bmask = p_sys->video.i_bmask;
00971     }
00972 
00973     /* Get a new picture */
00974     while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
00975     {
00976         int i_pic, i_ready_pic = 0;
00977 
00978         if( p_dec->b_die || p_dec->b_error )
00979         {
00980             return NULL;
00981         }
00982 
00983 #define p_pic p_dec->p_owner->p_vout->render.pp_picture[i_pic]
00984         /* Check the decoder doesn't leak pictures */
00985         for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
00986              i_pic++ )
00987         {
00988             if( p_pic->i_status == READY_PICTURE )
00989             {
00990                 if( i_ready_pic++ > 0 ) break;
00991                 else continue;
00992             }
00993 
00994             if( p_pic->i_status != DISPLAYED_PICTURE &&
00995                 p_pic->i_status != RESERVED_PICTURE &&
00996                 p_pic->i_status != READY_PICTURE ) break;
00997 
00998             if( !p_pic->i_refcount && p_pic->i_status != RESERVED_PICTURE )
00999                 break;
01000         }
01001         if( i_pic == p_dec->p_owner->p_vout->render.i_pictures )
01002         {
01003             msg_Err( p_dec, "decoder is leaking pictures, resetting the heap" );
01004 
01005             /* Just free all the pictures */
01006             for( i_pic = 0; i_pic < p_dec->p_owner->p_vout->render.i_pictures;
01007                  i_pic++ )
01008             {
01009                 if( p_pic->i_status == RESERVED_PICTURE )
01010                     vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
01011                 if( p_pic->i_refcount > 0 )
01012                 vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
01013             }
01014         }
01015 #undef p_pic
01016 
01017         msleep( VOUT_OUTMEM_SLEEP );
01018     }
01019 
01020     return p_pic;
01021 }
01022 
01023 static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
01024 {
01025     vout_DestroyPicture( p_dec->p_owner->p_vout, p_pic );
01026 }
01027 
01028 static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
01029 {
01030     vout_LinkPicture( p_dec->p_owner->p_vout, p_pic );
01031 }
01032 
01033 static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
01034 {
01035     vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
01036 }
01037 
01038 static subpicture_t *spu_new_buffer( decoder_t *p_dec )
01039 {
01040     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
01041     vout_thread_t *p_vout = NULL;
01042     subpicture_t *p_subpic;
01043     int i_attempts = 30;
01044 
01045     while( i_attempts-- )
01046     {
01047         if( p_dec->b_die || p_dec->b_error ) break;
01048 
01049         p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
01050         if( p_vout ) break;
01051 
01052         msleep( VOUT_DISPLAY_DELAY );
01053     }
01054 
01055     if( !p_vout )
01056     {
01057         msg_Warn( p_dec, "no vout found, dropping subpicture" );
01058         return NULL;
01059     }
01060 
01061     if( p_sys->p_spu_vout != p_vout )
01062     {
01063         spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER,
01064                      &p_sys->i_spu_channel );
01065         p_sys->p_spu_vout = p_vout;
01066     }
01067 
01068     p_subpic = spu_CreateSubpicture( p_vout->p_spu );
01069     if( p_subpic )
01070     {
01071         p_subpic->i_channel = p_sys->i_spu_channel;
01072     }
01073 
01074     vlc_object_release( p_vout );
01075 
01076     return p_subpic;
01077 }
01078 
01079 static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
01080 {
01081     decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
01082     vout_thread_t *p_vout = NULL;
01083 
01084     p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
01085     if( !p_vout || p_sys->p_spu_vout != p_vout )
01086     {
01087         if( p_vout )
01088             vlc_object_release( p_vout );
01089         msg_Warn( p_dec, "no vout found, leaking subpicture" );
01090         return;
01091     }
01092 
01093     spu_DestroySubpicture( p_vout->p_spu, p_subpic );
01094 
01095     vlc_object_release( p_vout );
01096 }
01097 

Generated on Tue Dec 20 10:14:48 2005 for vlc-0.8.4a by  doxygen 1.4.2