00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
00079 decoder_t *p_packetizer;
00080
00081
00082 video_format_t video;
00083 audio_format_t audio;
00084 es_format_t sout;
00085
00086
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
00105 if( p_input->p_sout && !b_force_decoder )
00106 {
00107
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
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
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
00187
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
00194
00195 }
00196 else
00197 {
00198
00199 input_DecoderDecode( p_dec, NULL );
00200
00201 module_Unneed( p_dec, p_dec->p_module );
00202 }
00203
00204
00205 DeleteDecoder( p_dec );
00206
00207
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
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 )
00231 {
00232
00233
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
00259 if( p_dec->p_owner->b_own_thread )
00260 {
00261 block_FifoEmpty( p_dec->p_owner->p_fifo );
00262 }
00263
00264
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
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
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
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
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
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
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
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
00497 p_block = block_FifoGet( p_dec->p_owner->p_fifo );
00498 if( p_block ) block_Release( p_block );
00499 }
00500
00501
00502
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
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
00625
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
00770 block_FifoEmpty( p_dec->p_owner->p_fifo );
00771 block_FifoRelease( p_dec->p_owner->p_fifo );
00772
00773
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
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
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
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
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
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
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
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
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
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