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 #include <stdlib.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/input.h>
00032 #include <vlc/decoder.h>
00033
00034 #include "input_internal.h"
00035
00036 #include "vlc_playlist.h"
00037 #include "iso_lang.h"
00038
00039 #include "../misc/iso-639_def.h"
00040
00041
00042
00043
00044 typedef struct
00045 {
00046
00047 int i_id;
00048
00049
00050 int i_es;
00051
00052 vlc_bool_t b_selected;
00053
00054
00055 input_clock_t clock;
00056
00057 char *psz_now_playing;
00058
00059 } es_out_pgrm_t;
00060
00061 struct es_out_id_t
00062 {
00063
00064 int i_id;
00065 es_out_pgrm_t *p_pgrm;
00066
00067
00068 vlc_bool_t b_discontinuity;
00069
00070
00071 int64_t i_preroll_end;
00072
00073
00074 int i_channel;
00075 es_format_t fmt;
00076 char *psz_language;
00077 char *psz_language_code;
00078 decoder_t *p_dec;
00079 };
00080
00081 struct es_out_sys_t
00082 {
00083 input_thread_t *p_input;
00084
00085
00086 int i_pgrm;
00087 es_out_pgrm_t **pgrm;
00088 es_out_pgrm_t **pp_selected_pgrm;
00089 es_out_pgrm_t *p_pgrm;
00090
00091
00092 int i_id;
00093 int i_es;
00094 es_out_id_t **es;
00095
00096
00097 vlc_bool_t b_active;
00098 int i_mode;
00099
00100
00101 int i_audio;
00102 int i_video;
00103 int i_sub;
00104
00105
00106 int i_audio_last;
00107 int i_sub_last;
00108 char **ppsz_audio_language;
00109 char **ppsz_sub_language;
00110
00111
00112 es_out_id_t *p_es_audio;
00113 es_out_id_t *p_es_video;
00114 es_out_id_t *p_es_sub;
00115
00116
00117 int64_t i_audio_delay;
00118 int64_t i_spu_delay;
00119 };
00120
00121 static es_out_id_t *EsOutAdd ( es_out_t *, es_format_t * );
00122 static int EsOutSend ( es_out_t *, es_out_id_t *, block_t * );
00123 static void EsOutDel ( es_out_t *, es_out_id_t * );
00124 static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force );
00125 static int EsOutControl( es_out_t *, int i_query, va_list );
00126
00127 static void EsOutAddInfo( es_out_t *, es_out_id_t *es );
00128
00129 static void EsSelect( es_out_t *out, es_out_id_t *es );
00130 static void EsUnselect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_update );
00131 static char *LanguageGetName( const char *psz_code );
00132 static char *LanguageGetCode( const char *psz_lang );
00133 static char **LanguageSplit( const char *psz_langs );
00134 static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang );
00135
00136
00137
00138
00139 es_out_t *input_EsOutNew( input_thread_t *p_input )
00140 {
00141 es_out_t *out = malloc( sizeof( es_out_t ) );
00142 es_out_sys_t *p_sys = malloc( sizeof( es_out_sys_t ) );
00143 vlc_value_t val;
00144 int i;
00145
00146 out->pf_add = EsOutAdd;
00147 out->pf_send = EsOutSend;
00148 out->pf_del = EsOutDel;
00149 out->pf_control = EsOutControl;
00150 out->p_sys = p_sys;
00151
00152 p_sys->p_input = p_input;
00153
00154 p_sys->b_active = VLC_FALSE;
00155 p_sys->i_mode = ES_OUT_MODE_AUTO;
00156
00157
00158 p_sys->i_pgrm = 0;
00159 p_sys->pgrm = NULL;
00160 p_sys->p_pgrm = NULL;
00161
00162 p_sys->i_id = 0;
00163 p_sys->i_es = 0;
00164 p_sys->es = NULL;
00165
00166 p_sys->i_audio = 0;
00167 p_sys->i_video = 0;
00168 p_sys->i_sub = 0;
00169
00170
00171 var_Get( p_input, "audio-track", &val );
00172 p_sys->i_audio_last = val.i_int;
00173
00174 var_Get( p_input, "sub-track", &val );
00175 p_sys->i_sub_last = val.i_int;
00176
00177 var_Get( p_input, "audio-language", &val );
00178 p_sys->ppsz_audio_language = LanguageSplit(val.psz_string);
00179 if( p_sys->ppsz_audio_language )
00180 {
00181 for( i = 0; p_sys->ppsz_audio_language[i]; i++ )
00182 msg_Dbg( p_input, "select audio in language[%d] %s",
00183 i, p_sys->ppsz_audio_language[i] );
00184 }
00185 if( val.psz_string ) free( val.psz_string );
00186
00187 var_Get( p_input, "sub-language", &val );
00188 p_sys->ppsz_sub_language = LanguageSplit(val.psz_string);
00189 if( p_sys->ppsz_sub_language )
00190 {
00191 for( i = 0; p_sys->ppsz_sub_language[i]; i++ )
00192 msg_Dbg( p_input, "select subtitle in language[%d] %s",
00193 i, p_sys->ppsz_sub_language[i] );
00194 }
00195 if( val.psz_string ) free( val.psz_string );
00196
00197 p_sys->p_es_audio = NULL;
00198 p_sys->p_es_video = NULL;
00199 p_sys->p_es_sub = NULL;
00200
00201 p_sys->i_audio_delay= 0;
00202 p_sys->i_spu_delay = 0;
00203
00204 return out;
00205 }
00206
00207
00208
00209
00210 void input_EsOutDelete( es_out_t *out )
00211 {
00212 es_out_sys_t *p_sys = out->p_sys;
00213 int i;
00214
00215 for( i = 0; i < p_sys->i_es; i++ )
00216 {
00217 if( p_sys->es[i]->p_dec )
00218 {
00219 input_DecoderDelete( p_sys->es[i]->p_dec );
00220 }
00221 if( p_sys->es[i]->psz_language )
00222 free( p_sys->es[i]->psz_language );
00223 if( p_sys->es[i]->psz_language_code )
00224 free( p_sys->es[i]->psz_language_code );
00225 es_format_Clean( &p_sys->es[i]->fmt );
00226
00227 free( p_sys->es[i] );
00228 }
00229 if( p_sys->ppsz_audio_language )
00230 {
00231 for( i = 0; p_sys->ppsz_audio_language[i]; i++ )
00232 free( p_sys->ppsz_audio_language[i] );
00233 free( p_sys->ppsz_audio_language );
00234 }
00235 if( p_sys->ppsz_sub_language )
00236 {
00237 for( i = 0; p_sys->ppsz_sub_language[i]; i++ )
00238 free( p_sys->ppsz_sub_language[i] );
00239 free( p_sys->ppsz_sub_language );
00240 }
00241
00242 if( p_sys->es )
00243 free( p_sys->es );
00244
00245 for( i = 0; i < p_sys->i_pgrm; i++ )
00246 {
00247 if( p_sys->pgrm[i]->psz_now_playing )
00248 free( p_sys->pgrm[i]->psz_now_playing );
00249 free( p_sys->pgrm[i] );
00250 }
00251 if( p_sys->pgrm )
00252 free( p_sys->pgrm );
00253
00254 free( p_sys );
00255 free( out );
00256 }
00257
00258 es_out_id_t *input_EsOutGetFromID( es_out_t *out, int i_id )
00259 {
00260 int i;
00261 if( i_id < 0 )
00262 {
00263
00264 return (es_out_id_t*)((uint8_t*)NULL-i_id);
00265 }
00266
00267 for( i = 0; i < out->p_sys->i_es; i++ )
00268 {
00269 if( out->p_sys->es[i]->i_id == i_id )
00270 return out->p_sys->es[i];
00271 }
00272 return NULL;
00273 }
00274
00275 void input_EsOutDiscontinuity( es_out_t *out, vlc_bool_t b_audio )
00276 {
00277 es_out_sys_t *p_sys = out->p_sys;
00278 int i;
00279
00280 for( i = 0; i < p_sys->i_es; i++ )
00281 {
00282 es_out_id_t *es = p_sys->es[i];
00283 es->b_discontinuity = VLC_TRUE;
00284
00285
00286
00287 if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) )
00288 {
00289 input_DecoderDiscontinuity( es->p_dec );
00290 }
00291 }
00292 }
00293
00294 void input_EsOutSetDelay( es_out_t *out, int i_cat, int64_t i_delay )
00295 {
00296 es_out_sys_t *p_sys = out->p_sys;
00297
00298 if( i_cat == AUDIO_ES )
00299 p_sys->i_audio_delay = i_delay;
00300 else if( i_cat == SPU_ES )
00301 p_sys->i_spu_delay = i_delay;
00302 }
00303
00304 vlc_bool_t input_EsOutDecodersEmpty( es_out_t *out )
00305 {
00306 es_out_sys_t *p_sys = out->p_sys;
00307 int i;
00308
00309 for( i = 0; i < p_sys->i_es; i++ )
00310 {
00311 es_out_id_t *es = p_sys->es[i];
00312
00313 if( es->p_dec && !input_DecoderEmpty( es->p_dec ) )
00314 return VLC_FALSE;
00315 }
00316 return VLC_TRUE;
00317 }
00318
00319
00320
00321
00322 static void EsOutESVarUpdate( es_out_t *out, es_out_id_t *es,
00323 vlc_bool_t b_delete )
00324 {
00325 es_out_sys_t *p_sys = out->p_sys;
00326 input_thread_t *p_input = p_sys->p_input;
00327 vlc_value_t val, text;
00328
00329 char *psz_var;
00330
00331 if( es->fmt.i_cat == AUDIO_ES )
00332 psz_var = "audio-es";
00333 else if( es->fmt.i_cat == VIDEO_ES )
00334 psz_var = "video-es";
00335 else if( es->fmt.i_cat == SPU_ES )
00336 psz_var = "spu-es";
00337 else
00338 return;
00339
00340 if( b_delete )
00341 {
00342 val.i_int = es->i_id;
00343 var_Change( p_input, psz_var, VLC_VAR_DELCHOICE, &val, NULL );
00344 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00345 return;
00346 }
00347
00348
00349 var_Change( p_input, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
00350 if( val.i_int == 0 )
00351 {
00352 vlc_value_t val2;
00353
00354
00355 val2.i_int = -1; text.psz_string = _("Disable");
00356 var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val2, &text );
00357 val.i_int++;
00358 }
00359
00360
00361 if( es->fmt.psz_description && *es->fmt.psz_description )
00362 {
00363 if( es->psz_language && *es->psz_language )
00364 {
00365 text.psz_string = malloc( strlen( es->fmt.psz_description) + strlen( es->psz_language ) + 10 );
00366 sprintf( text.psz_string, "%s - [%s]", es->fmt.psz_description, es->psz_language );
00367 }
00368 else text.psz_string = strdup( es->fmt.psz_description );
00369 }
00370 else
00371 {
00372 if( es->psz_language && *es->psz_language )
00373 {
00374 char *temp;
00375 text.psz_string = malloc( strlen( _("Track %i") )+ strlen( es->psz_language ) + 30 );
00376 asprintf( &temp, _("Track %i"), val.i_int );
00377 sprintf( text.psz_string, "%s - [%s]", temp, es->psz_language );
00378 free( temp );
00379 }
00380 else
00381 {
00382 text.psz_string = malloc( strlen( _("Track %i") ) + 20 );
00383 sprintf( text.psz_string, _("Track %i"), val.i_int );
00384 }
00385 }
00386
00387 val.i_int = es->i_id;
00388 var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val, &text );
00389
00390 free( text.psz_string );
00391
00392 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00393 }
00394
00395
00396
00397
00398 static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
00399 {
00400 es_out_sys_t *p_sys = out->p_sys;
00401 input_thread_t *p_input = p_sys->p_input;
00402 vlc_value_t val;
00403 int i;
00404
00405 if( p_sys->p_pgrm == p_pgrm )
00406 return;
00407
00408 if( p_sys->p_pgrm )
00409 {
00410 es_out_pgrm_t *old = p_sys->p_pgrm;
00411 msg_Dbg( p_input, "unselecting program id=%d", old->i_id );
00412
00413 for( i = 0; i < p_sys->i_es; i++ )
00414 {
00415 if( p_sys->es[i]->p_pgrm == old && p_sys->es[i]->p_dec &&
00416 p_sys->i_mode != ES_OUT_MODE_ALL )
00417 EsUnselect( out, p_sys->es[i], VLC_TRUE );
00418 }
00419
00420 p_sys->p_es_audio = NULL;
00421 p_sys->p_es_sub = NULL;
00422 p_sys->p_es_video = NULL;
00423 }
00424
00425 msg_Dbg( p_input, "selecting program id=%d", p_pgrm->i_id );
00426
00427
00428 p_pgrm->b_selected = VLC_TRUE;
00429
00430
00431 if( p_sys->p_pgrm && p_sys->p_pgrm->clock.b_master )
00432 {
00433 p_sys->p_pgrm->clock.b_master = VLC_FALSE;
00434 }
00435 p_pgrm->clock.b_master = VLC_TRUE;
00436 p_sys->p_pgrm = p_pgrm;
00437
00438
00439 val.i_int = p_pgrm->i_id;
00440 var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
00441
00442
00443 var_Change( p_input, "audio-es", VLC_VAR_CLEARCHOICES, NULL, NULL );
00444 var_Change( p_input, "video-es", VLC_VAR_CLEARCHOICES, NULL, NULL );
00445 var_Change( p_input, "spu-es", VLC_VAR_CLEARCHOICES, NULL, NULL );
00446 for( i = 0; i < p_sys->i_es; i++ )
00447 {
00448 if( p_sys->es[i]->p_pgrm == p_sys->p_pgrm )
00449 EsOutESVarUpdate( out, p_sys->es[i], VLC_FALSE );
00450 EsOutSelect( out, p_sys->es[i], VLC_FALSE );
00451 }
00452
00453
00454 if( p_pgrm->psz_now_playing )
00455 {
00456 char *psz_cat = malloc( strlen(_("Program")) + 10 );
00457
00458 sprintf( psz_cat, "%s %d", _("Program"), p_pgrm->i_id );
00459 input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"),
00460 VLC_META_NOW_PLAYING, "%s", p_pgrm->psz_now_playing );
00461 free( psz_cat );
00462 }
00463
00464
00465 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00466 }
00467
00468
00469
00470
00471 static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
00472 {
00473 es_out_sys_t *p_sys = out->p_sys;
00474 input_thread_t *p_input = p_sys->p_input;
00475 vlc_value_t val;
00476
00477 es_out_pgrm_t *p_pgrm = malloc( sizeof( es_out_pgrm_t ) );
00478
00479
00480 p_pgrm->i_id = i_group;
00481 p_pgrm->i_es = 0;
00482 p_pgrm->b_selected = VLC_FALSE;
00483 p_pgrm->psz_now_playing = NULL;
00484 input_ClockInit( &p_pgrm->clock, VLC_FALSE, p_input->input.i_cr_average );
00485
00486
00487 TAB_APPEND( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
00488
00489
00490 val.i_int = i_group;
00491 var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, NULL );
00492
00493 if( i_group == var_GetInteger( p_input, "program" ) )
00494 {
00495 EsOutProgramSelect( out, p_pgrm );
00496 }
00497 else
00498 {
00499 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00500 }
00501 return p_pgrm;
00502 }
00503
00504
00505
00506
00507 static int EsOutProgramDel( es_out_t *out, int i_group )
00508 {
00509 es_out_sys_t *p_sys = out->p_sys;
00510 input_thread_t *p_input = p_sys->p_input;
00511 es_out_pgrm_t *p_pgrm = NULL;
00512 vlc_value_t val;
00513 int i;
00514
00515 for( i = 0; i < p_sys->i_pgrm; i++ )
00516 {
00517 if( p_sys->pgrm[i]->i_id == i_group )
00518 {
00519 p_pgrm = p_sys->pgrm[i];
00520 break;
00521 }
00522 }
00523
00524 if( p_pgrm == NULL )
00525 return VLC_EGENERIC;
00526
00527 if( p_pgrm->i_es )
00528 {
00529 msg_Dbg( p_input, "can't delete program %d which still has %i ES",
00530 i_group, p_pgrm->i_es );
00531 return VLC_EGENERIC;
00532 }
00533
00534 TAB_REMOVE( p_sys->i_pgrm, p_sys->pgrm, p_pgrm );
00535
00536
00537 if( p_sys->p_pgrm == p_pgrm ) p_sys->p_pgrm = 0;
00538
00539 if( p_pgrm->psz_now_playing ) free( p_pgrm->psz_now_playing );
00540 free( p_pgrm );
00541
00542
00543 val.i_int = i_group;
00544 var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
00545
00546 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00547
00548 return VLC_SUCCESS;
00549 }
00550
00551
00552
00553 static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
00554 {
00555 es_out_sys_t *p_sys = out->p_sys;
00556 es_out_pgrm_t *p_pgrm = NULL;
00557 input_thread_t *p_input = p_sys->p_input;
00558 char *psz_cat = malloc( strlen(_("Program")) + 10 );
00559 char *psz_name = NULL;
00560 char *psz_now_playing = NULL;
00561 char *psz_provider = NULL;
00562 int i;
00563
00564 msg_Dbg( p_input, "EsOutProgramMeta: number=%d", i_group );
00565 sprintf( psz_cat, "%s %d", _("Program"), i_group );
00566
00567 for( i = 0; i < p_meta->i_meta; i++ )
00568 {
00569 msg_Dbg( p_input, " - %s = %s", p_meta->name[i], p_meta->value[i] );
00570
00571 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
00572 _(p_meta->name[i]), "%s", p_meta->value[i] );
00573 if( !strcasecmp( p_meta->name[i], "Name" ) )
00574 psz_name = p_meta->value[i];
00575 else if( !strcasecmp( p_meta->name[i], "Provider" ) )
00576 psz_provider = p_meta->value[i];
00577 else if( !strcasecmp( p_meta->name[i], VLC_META_NOW_PLAYING ) )
00578 psz_now_playing = p_meta->value[i];
00579 }
00580
00581 if( !psz_name && !psz_now_playing )
00582 {
00583 free( psz_cat );
00584 return;
00585 }
00586
00587 for( i = 0; i < p_sys->i_pgrm; i++ )
00588 {
00589 if( p_sys->pgrm[i]->i_id == i_group )
00590 {
00591 p_pgrm = p_sys->pgrm[i];
00592 break;
00593 }
00594 }
00595
00596 if( p_pgrm == NULL )
00597 p_pgrm = EsOutProgramAdd( out, i_group );
00598
00599
00600 if( psz_name && *psz_name )
00601 {
00602 vlc_value_t val;
00603 vlc_value_t text;
00604
00605
00606 val.i_int = i_group;
00607 var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
00608
00609 if( psz_provider && *psz_provider )
00610 {
00611 asprintf( &text.psz_string, "%s [%s]", psz_name, psz_provider );
00612 var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text );
00613 free( text.psz_string );
00614 }
00615 else
00616 {
00617 text.psz_string = psz_name;
00618 var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, &text );
00619 }
00620 }
00621 if( psz_now_playing )
00622 {
00623 p_pgrm->psz_now_playing = strdup(psz_now_playing);
00624
00625 if( p_sys->p_pgrm == p_pgrm )
00626 {
00627 input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"),
00628 VLC_META_NOW_PLAYING, "%s", psz_now_playing );
00629 }
00630 }
00631 free( psz_cat );
00632 }
00633
00634
00635
00636
00637 static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
00638 {
00639 es_out_sys_t *p_sys = out->p_sys;
00640 input_thread_t *p_input = p_sys->p_input;
00641
00642 es_out_id_t *es = malloc( sizeof( es_out_id_t ) );
00643 es_out_pgrm_t *p_pgrm = NULL;
00644 int i;
00645
00646 if( fmt->i_group < 0 )
00647 {
00648 msg_Err( p_input, "invalid group number" );
00649 return NULL;
00650 }
00651
00652
00653 for( i = 0; i < p_sys->i_pgrm; i++ )
00654 {
00655 if( fmt->i_group == p_sys->pgrm[i]->i_id )
00656 {
00657 p_pgrm = p_sys->pgrm[i];
00658 break;
00659 }
00660 }
00661 if( p_pgrm == NULL )
00662 {
00663
00664 p_pgrm = EsOutProgramAdd( out, fmt->i_group );
00665 }
00666
00667
00668 p_pgrm->i_es++;
00669
00670
00671 if( fmt->i_id < 0 )
00672 fmt->i_id = out->p_sys->i_id;
00673 es->i_id = fmt->i_id;
00674 es->p_pgrm = p_pgrm;
00675 es_format_Copy( &es->fmt, fmt );
00676 es->i_preroll_end = -1;
00677 es->b_discontinuity = VLC_FALSE;
00678
00679 switch( fmt->i_cat )
00680 {
00681 case AUDIO_ES:
00682 es->i_channel = p_sys->i_audio;
00683 break;
00684
00685 case VIDEO_ES:
00686 es->i_channel = p_sys->i_video;
00687 if( fmt->video.i_frame_rate && fmt->video.i_frame_rate_base )
00688 vlc_ureduce( &es->fmt.video.i_frame_rate,
00689 &es->fmt.video.i_frame_rate_base,
00690 fmt->video.i_frame_rate,
00691 fmt->video.i_frame_rate_base, 0 );
00692 break;
00693
00694 case SPU_ES:
00695 es->i_channel = p_sys->i_sub;
00696 break;
00697
00698 default:
00699 es->i_channel = 0;
00700 break;
00701 }
00702 es->psz_language = LanguageGetName( fmt->psz_language );
00703 es->psz_language_code = LanguageGetCode( fmt->psz_language );
00704 es->p_dec = NULL;
00705
00706 if( es->p_pgrm == p_sys->p_pgrm )
00707 EsOutESVarUpdate( out, es, VLC_FALSE );
00708
00709
00710 EsOutSelect( out, es, VLC_FALSE );
00711
00712
00713 TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es );
00714 p_sys->i_id++;
00715 switch( fmt->i_cat )
00716 {
00717 case AUDIO_ES:
00718 p_sys->i_audio++;
00719 break;
00720 case SPU_ES:
00721 p_sys->i_sub++;
00722 break;
00723 case VIDEO_ES:
00724 p_sys->i_video++;
00725 break;
00726 }
00727
00728 EsOutAddInfo( out, es );
00729
00730 return es;
00731 }
00732
00733 static void EsSelect( es_out_t *out, es_out_id_t *es )
00734 {
00735 es_out_sys_t *p_sys = out->p_sys;
00736 input_thread_t *p_input = p_sys->p_input;
00737 vlc_value_t val;
00738 char *psz_var;
00739
00740 if( es->p_dec )
00741 {
00742 msg_Warn( p_input, "ES 0x%x is already selected", es->i_id );
00743 return;
00744 }
00745
00746 if( es->fmt.i_cat == VIDEO_ES || es->fmt.i_cat == SPU_ES )
00747 {
00748 if( !var_GetBool( p_input, "video" ) ||
00749 ( p_input->p_sout && !var_GetBool( p_input, "sout-video" ) ) )
00750 {
00751 msg_Dbg( p_input, "video is disabled, not selecting ES 0x%x",
00752 es->i_id );
00753 return;
00754 }
00755 }
00756 else if( es->fmt.i_cat == AUDIO_ES )
00757 {
00758 var_Get( p_input, "audio", &val );
00759 if( !var_GetBool( p_input, "audio" ) ||
00760 ( p_input->p_sout && !var_GetBool( p_input, "sout-audio" ) ) )
00761 {
00762 msg_Dbg( p_input, "audio is disabled, not selecting ES 0x%x",
00763 es->i_id );
00764 return;
00765 }
00766 }
00767
00768 es->i_preroll_end = -1;
00769 es->p_dec = input_DecoderNew( p_input, &es->fmt, VLC_FALSE );
00770 if( es->p_dec == NULL || es->p_pgrm != p_sys->p_pgrm )
00771 return;
00772
00773 if( es->fmt.i_cat == VIDEO_ES )
00774 psz_var = "video-es";
00775 else if( es->fmt.i_cat == AUDIO_ES )
00776 psz_var = "audio-es";
00777 else if( es->fmt.i_cat == SPU_ES )
00778 psz_var = "spu-es";
00779 else
00780 return;
00781
00782
00783 val.i_int = es->i_id;
00784 var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
00785
00786
00787 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00788 }
00789
00790 static void EsUnselect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_update )
00791 {
00792 es_out_sys_t *p_sys = out->p_sys;
00793 input_thread_t *p_input = p_sys->p_input;
00794 vlc_value_t val;
00795 char *psz_var;
00796
00797 if( es->p_dec == NULL )
00798 {
00799 msg_Warn( p_input, "ES 0x%x is already unselected", es->i_id );
00800 return;
00801 }
00802
00803 input_DecoderDelete( es->p_dec );
00804 es->p_dec = NULL;
00805
00806 if( !b_update )
00807 return;
00808
00809
00810 if( es->p_dec == NULL )
00811 return;
00812 if( es->fmt.i_cat == VIDEO_ES )
00813 psz_var = "video-es";
00814 else if( es->fmt.i_cat == AUDIO_ES )
00815 psz_var = "audio-es";
00816 else if( es->fmt.i_cat == SPU_ES )
00817 psz_var = "spu-es";
00818 else
00819 return;
00820
00821
00822 val.i_int = -1;
00823 var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
00824
00825 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
00826 }
00827
00837 static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
00838 {
00839 es_out_sys_t *p_sys = out->p_sys;
00840
00841 int i_cat = es->fmt.i_cat;
00842
00843 if( !p_sys->b_active ||
00844 ( !b_force && es->fmt.i_priority < 0 ) )
00845 {
00846 return;
00847 }
00848
00849 if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
00850 {
00851 if( !es->p_dec )
00852 EsSelect( out, es );
00853 }
00854 else if( p_sys->i_mode == ES_OUT_MODE_PARTIAL )
00855 {
00856 vlc_value_t val;
00857 int i;
00858 var_Get( p_sys->p_input, "programs", &val );
00859 for ( i = 0; i < val.p_list->i_count; i++ )
00860 {
00861 if ( val.p_list->p_values[i].i_int == es->p_pgrm->i_id || b_force )
00862 {
00863 if( !es->p_dec )
00864 EsSelect( out, es );
00865 break;
00866 }
00867 }
00868 var_Change( p_sys->p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
00869 }
00870 else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
00871 {
00872 int i_wanted = -1;
00873
00874 if( es->p_pgrm != p_sys->p_pgrm )
00875 return;
00876
00877 if( i_cat == AUDIO_ES )
00878 {
00879 int idx1 = LanguageArrayIndex( p_sys->ppsz_audio_language,
00880 es->psz_language_code );
00881
00882 if( p_sys->p_es_audio &&
00883 p_sys->p_es_audio->fmt.i_priority >= es->fmt.i_priority )
00884 {
00885 int idx2 = LanguageArrayIndex( p_sys->ppsz_audio_language,
00886 p_sys->p_es_audio->psz_language_code );
00887
00888 if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
00889 return;
00890 i_wanted = es->i_channel;
00891 }
00892 else
00893 {
00894
00895
00896
00897
00898 if( idx1 >= 0 ||
00899 !strcmp( es->psz_language_code, "??" ) ||
00900 !p_sys->ppsz_audio_language )
00901 i_wanted = es->i_channel;
00902 }
00903
00904 if( p_sys->i_audio_last >= 0 )
00905 i_wanted = p_sys->i_audio_last;
00906 }
00907 else if( i_cat == SPU_ES )
00908 {
00909 int idx1 = LanguageArrayIndex( p_sys->ppsz_sub_language,
00910 es->psz_language_code );
00911
00912 if( p_sys->p_es_sub &&
00913 p_sys->p_es_sub->fmt.i_priority >= es->fmt.i_priority )
00914 {
00915 int idx2 = LanguageArrayIndex( p_sys->ppsz_sub_language,
00916 p_sys->p_es_sub->psz_language_code );
00917
00918 msg_Dbg( p_sys->p_input, "idx1=%d(%s) idx2=%d(%s)",
00919 idx1, es->psz_language_code, idx2,
00920 p_sys->p_es_sub->psz_language_code );
00921
00922 if( idx1 < 0 || ( idx2 >= 0 && idx2 <= idx1 ) )
00923 return;
00924
00925 i_wanted = es->i_channel;
00926 }
00927 else if( idx1 >= 0 )
00928 {
00929 msg_Dbg( p_sys->p_input, "idx1=%d(%s)",
00930 idx1, es->psz_language_code );
00931
00932 i_wanted = es->i_channel;
00933 }
00934 if( p_sys->i_sub_last >= 0 )
00935 i_wanted = p_sys->i_sub_last;
00936 }
00937 else if( i_cat == VIDEO_ES )
00938 {
00939 i_wanted = es->i_channel;
00940 }
00941
00942 if( i_wanted == es->i_channel && es->p_dec == NULL )
00943 EsSelect( out, es );
00944 }
00945
00946
00947 if( es->p_dec )
00948 {
00949 if( i_cat == AUDIO_ES )
00950 {
00951 if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
00952 p_sys->p_es_audio &&
00953 p_sys->p_es_audio != es &&
00954 p_sys->p_es_audio->p_dec )
00955 {
00956 EsUnselect( out, p_sys->p_es_audio, VLC_FALSE );
00957 }
00958 p_sys->p_es_audio = es;
00959 }
00960 else if( i_cat == SPU_ES )
00961 {
00962 if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
00963 p_sys->p_es_sub &&
00964 p_sys->p_es_sub != es &&
00965 p_sys->p_es_sub->p_dec )
00966 {
00967 EsUnselect( out, p_sys->p_es_sub, VLC_FALSE );
00968 }
00969 p_sys->p_es_sub = es;
00970 }
00971 else if( i_cat == VIDEO_ES )
00972 {
00973 p_sys->p_es_video = es;
00974 }
00975 }
00976 }
00977
00985 static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
00986 {
00987 es_out_sys_t *p_sys = out->p_sys;
00988 input_thread_t *p_input = p_sys->p_input;
00989 es_out_pgrm_t *p_pgrm = es->p_pgrm;
00990 int64_t i_delay;
00991
00992 if( es->fmt.i_cat == AUDIO_ES )
00993 i_delay = p_sys->i_audio_delay;
00994 else if( es->fmt.i_cat == SPU_ES )
00995 i_delay = p_sys->i_spu_delay;
00996 else
00997 i_delay = 0;
00998
00999
01000 if( es->i_preroll_end >= 0 )
01001 {
01002 int64_t i_date = p_block->i_pts;
01003 if( i_date <= 0 )
01004 i_date = p_block->i_dts;
01005
01006 if( i_date < es->i_preroll_end )
01007 p_block->i_flags |= BLOCK_FLAG_PREROLL;
01008 else
01009 es->i_preroll_end = -1;
01010 }
01011
01012
01013 if( p_block->i_dts > 0 )
01014 {
01015 p_block->i_dts =
01016 input_ClockGetTS( p_input, &p_pgrm->clock,
01017 ( p_block->i_dts + 11 ) * 9 / 100 ) + i_delay;
01018 }
01019 if( p_block->i_pts > 0 )
01020 {
01021 p_block->i_pts =
01022 input_ClockGetTS( p_input, &p_pgrm->clock,
01023 ( p_block->i_pts + 11 ) * 9 / 100 ) + i_delay;
01024 }
01025 if ( es->fmt.i_codec == VLC_FOURCC( 't', 'e', 'l', 'x' ) )
01026 {
01027 mtime_t current_date = mdate();
01028 if( !p_block->i_pts
01029 || p_block->i_pts > current_date + 10000000
01030 || current_date > p_block->i_pts )
01031 {
01032
01033
01034 p_block->i_pts = current_date + 400000
01035 + p_input->i_pts_delay + i_delay;
01036 }
01037 }
01038
01039 p_block->i_rate = p_input->i_rate;
01040
01041
01042 if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES ||
01043 p_input->i_rate == INPUT_RATE_DEFAULT ) )
01044 {
01045 input_DecoderDecode( es->p_dec, p_block );
01046 }
01047 else
01048 {
01049 block_Release( p_block );
01050 }
01051
01052 return VLC_SUCCESS;
01053 }
01054
01055
01056
01057
01058 static void EsOutDel( es_out_t *out, es_out_id_t *es )
01059 {
01060 es_out_sys_t *p_sys = out->p_sys;
01061 vlc_bool_t b_reselect = VLC_FALSE;
01062 int i;
01063
01064
01065 if( es->p_dec )
01066 EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
01067
01068 if( es->p_pgrm == p_sys->p_pgrm )
01069 EsOutESVarUpdate( out, es, VLC_TRUE );
01070
01071 TAB_REMOVE( p_sys->i_es, p_sys->es, es );
01072
01073 es->p_pgrm->i_es--;
01074 if( es->p_pgrm->i_es == 0 )
01075 {
01076 msg_Dbg( p_sys->p_input, "Program doesn't contain anymore ES" );
01077 }
01078
01079 if( p_sys->p_es_audio == es || p_sys->p_es_video == es ||
01080 p_sys->p_es_sub == es ) b_reselect = VLC_TRUE;
01081
01082 if( p_sys->p_es_audio == es ) p_sys->p_es_audio = NULL;
01083 if( p_sys->p_es_video == es ) p_sys->p_es_video = NULL;
01084 if( p_sys->p_es_sub == es ) p_sys->p_es_sub = NULL;
01085
01086 switch( es->fmt.i_cat )
01087 {
01088 case AUDIO_ES:
01089 p_sys->i_audio--;
01090 break;
01091 case SPU_ES:
01092 p_sys->i_sub--;
01093 break;
01094 case VIDEO_ES:
01095 p_sys->i_video--;
01096 break;
01097 }
01098
01099
01100 if( b_reselect )
01101 for( i = 0; i < p_sys->i_es; i++ )
01102 {
01103 if( es->fmt.i_cat == p_sys->es[i]->fmt.i_cat )
01104 EsOutSelect( out, p_sys->es[i], VLC_FALSE );
01105 }
01106
01107 if( es->psz_language )
01108 free( es->psz_language );
01109 if( es->psz_language_code )
01110 free( es->psz_language_code );
01111
01112 es_format_Clean( &es->fmt );
01113
01114 free( es );
01115 }
01116
01125 static int EsOutControl( es_out_t *out, int i_query, va_list args )
01126 {
01127 es_out_sys_t *p_sys = out->p_sys;
01128 vlc_bool_t b, *pb;
01129 int i, *pi;
01130
01131 es_out_id_t *es;
01132
01133 switch( i_query )
01134 {
01135 case ES_OUT_SET_ES_STATE:
01136 es = (es_out_id_t*) va_arg( args, es_out_id_t * );
01137 b = (vlc_bool_t) va_arg( args, vlc_bool_t );
01138 if( b && es->p_dec == NULL )
01139 {
01140 EsSelect( out, es );
01141 return es->p_dec ? VLC_SUCCESS : VLC_EGENERIC;
01142 }
01143 else if( !b && es->p_dec )
01144 {
01145 EsUnselect( out, es, es->p_pgrm == p_sys->p_pgrm );
01146 return VLC_SUCCESS;
01147 }
01148 return VLC_SUCCESS;
01149
01150 case ES_OUT_GET_ES_STATE:
01151 es = (es_out_id_t*) va_arg( args, es_out_id_t * );
01152 pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
01153
01154 *pb = es->p_dec ? VLC_TRUE : VLC_FALSE;
01155 return VLC_SUCCESS;
01156
01157 case ES_OUT_SET_ACTIVE:
01158 {
01159 b = (vlc_bool_t) va_arg( args, vlc_bool_t );
01160 p_sys->b_active = b;
01161
01162 if( b )
01163 var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
01164 return VLC_SUCCESS;
01165 }
01166
01167 case ES_OUT_GET_ACTIVE:
01168 pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
01169 *pb = p_sys->b_active;
01170 return VLC_SUCCESS;
01171
01172 case ES_OUT_SET_MODE:
01173 i = (int) va_arg( args, int );
01174 if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL ||
01175 i == ES_OUT_MODE_AUTO || i == ES_OUT_MODE_PARTIAL )
01176 {
01177 p_sys->i_mode = i;
01178
01179
01180 for( i = 0; i < p_sys->i_es; i++ )
01181 {
01182 if( p_sys->es[i]->p_dec )
01183 {
01184 EsUnselect( out, p_sys->es[i],
01185 p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
01186 }
01187 }
01188 for( i = 0; i < p_sys->i_es; i++ )
01189 {
01190 EsOutSelect( out, p_sys->es[i], VLC_FALSE );
01191 }
01192 return VLC_SUCCESS;
01193 }
01194 return VLC_EGENERIC;
01195
01196 case ES_OUT_GET_MODE:
01197 pi = (int*) va_arg( args, int* );
01198 *pi = p_sys->i_mode;
01199 return VLC_SUCCESS;
01200
01201 case ES_OUT_SET_ES:
01202 es = (es_out_id_t*) va_arg( args, es_out_id_t * );
01203
01204 if( es == NULL )
01205 {
01206 for( i = 0; i < p_sys->i_es; i++ )
01207 {
01208 if( p_sys->es[i]->p_dec )
01209 EsUnselect( out, p_sys->es[i],
01210 p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
01211 }
01212 }
01213 else if( es == (es_out_id_t*)((uint8_t*)NULL+AUDIO_ES) )
01214 {
01215 for( i = 0; i < p_sys->i_es; i++ )
01216 {
01217 if( p_sys->es[i]->p_dec &&
01218 p_sys->es[i]->fmt.i_cat == AUDIO_ES )
01219 EsUnselect( out, p_sys->es[i],
01220 p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
01221 }
01222 }
01223 else if( es == (es_out_id_t*)((uint8_t*)NULL+VIDEO_ES) )
01224 {
01225 for( i = 0; i < p_sys->i_es; i++ )
01226 {
01227 if( p_sys->es[i]->p_dec &&
01228 p_sys->es[i]->fmt.i_cat == VIDEO_ES )
01229 EsUnselect( out, p_sys->es[i],
01230 p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
01231 }
01232 }
01233 else if( es == (es_out_id_t*)((uint8_t*)NULL+SPU_ES) )
01234 {
01235 for( i = 0; i < p_sys->i_es; i++ )
01236 {
01237 if( p_sys->es[i]->p_dec &&
01238 p_sys->es[i]->fmt.i_cat == SPU_ES )
01239 EsUnselect( out, p_sys->es[i],
01240 p_sys->es[i]->p_pgrm == p_sys->p_pgrm );
01241 }
01242 }
01243 else
01244 {
01245 for( i = 0; i < p_sys->i_es; i++ )
01246 {
01247 if( es == p_sys->es[i] )
01248 {
01249 EsOutSelect( out, es, VLC_TRUE );
01250 break;
01251 }
01252 }
01253 }
01254 return VLC_SUCCESS;
01255
01256 case ES_OUT_SET_PCR:
01257 case ES_OUT_SET_GROUP_PCR:
01258 {
01259 es_out_pgrm_t *p_pgrm = NULL;
01260 int i_group = 0;
01261 int64_t i_pcr;
01262
01263 if( i_query == ES_OUT_SET_PCR )
01264 {
01265 p_pgrm = p_sys->p_pgrm;
01266 }
01267 else
01268 {
01269 int i;
01270 i_group = (int)va_arg( args, int );
01271 for( i = 0; i < p_sys->i_pgrm; i++ )
01272 {
01273 if( p_sys->pgrm[i]->i_id == i_group )
01274 {
01275 p_pgrm = p_sys->pgrm[i];
01276 break;
01277 }
01278 }
01279 }
01280 if( p_pgrm == NULL )
01281 p_pgrm = EsOutProgramAdd( out, i_group );
01282
01283 i_pcr = (int64_t)va_arg( args, int64_t );
01284
01285
01286 input_ClockSetPCR( p_sys->p_input, &p_pgrm->clock,
01287 (i_pcr + 11 ) * 9 / 100);
01288 return VLC_SUCCESS;
01289 }
01290
01291 case ES_OUT_RESET_PCR:
01292 for( i = 0; i < p_sys->i_pgrm; i++ )
01293 {
01294 p_sys->pgrm[i]->clock.i_synchro_state = SYNCHRO_REINIT;
01295 p_sys->pgrm[i]->clock.last_pts = 0;
01296 }
01297 return VLC_SUCCESS;
01298
01299 case ES_OUT_GET_TS:
01300 if( p_sys->p_pgrm )
01301 {
01302 int64_t i_ts = (int64_t)va_arg( args, int64_t );
01303 int64_t *pi_ts = (int64_t *)va_arg( args, int64_t * );
01304 *pi_ts = input_ClockGetTS( p_sys->p_input,
01305 &p_sys->p_pgrm->clock,
01306 ( i_ts + 11 ) * 9 / 100 );
01307 return VLC_SUCCESS;
01308 }
01309 return VLC_EGENERIC;
01310
01311 case ES_OUT_GET_GROUP:
01312 pi = (int*) va_arg( args, int* );
01313 if( p_sys->p_pgrm )
01314 *pi = p_sys->p_pgrm->i_id;
01315 else
01316 *pi = -1;
01317 return VLC_SUCCESS;
01318
01319 case ES_OUT_SET_GROUP:
01320 {
01321 int j;
01322 i = (int) va_arg( args, int );
01323 for( j = 0; j < p_sys->i_pgrm; j++ )
01324 {
01325 es_out_pgrm_t *p_pgrm = p_sys->pgrm[j];
01326 if( p_pgrm->i_id == i )
01327 {
01328 EsOutProgramSelect( out, p_pgrm );
01329 return VLC_SUCCESS;
01330 }
01331 }
01332 return VLC_EGENERIC;
01333 }
01334
01335 case ES_OUT_SET_FMT:
01336 {
01337
01338
01339 es_format_t *p_fmt;
01340 es = (es_out_id_t*) va_arg( args, es_out_id_t * );
01341 p_fmt = (es_format_t*) va_arg( args, es_format_t * );
01342 if( es == NULL ) return VLC_EGENERIC;
01343
01344 if( p_fmt->i_extra )
01345 {
01346 es->fmt.i_extra = p_fmt->i_extra;
01347 es->fmt.p_extra = realloc( es->fmt.p_extra, p_fmt->i_extra );
01348 memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra );
01349
01350 if( !es->p_dec ) return VLC_SUCCESS;
01351
01352 #if 1
01353 input_DecoderDelete( es->p_dec );
01354 es->p_dec = input_DecoderNew( p_sys->p_input,
01355 &es->fmt, VLC_FALSE );
01356
01357 #else
01358 es->p_dec->fmt_in.i_extra = p_fmt->i_extra;
01359 es->p_dec->fmt_in.p_extra =
01360 realloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra );
01361 memcpy( es->p_dec->fmt_in.p_extra,
01362 p_fmt->p_extra, p_fmt->i_extra );
01363 #endif
01364 }
01365
01366 return VLC_SUCCESS;
01367 }
01368
01369 case ES_OUT_SET_NEXT_DISPLAY_TIME:
01370 {
01371 int64_t i_date;
01372
01373 es = (es_out_id_t*) va_arg( args, es_out_id_t * );
01374 i_date = (int64_t)va_arg( args, int64_t );
01375
01376 if( !es || !es->p_dec )
01377 return VLC_EGENERIC;
01378
01379 es->i_preroll_end = i_date;
01380 input_DecoderPreroll( es->p_dec, i_date );
01381
01382 return VLC_SUCCESS;
01383 }
01384 case ES_OUT_SET_GROUP_META:
01385 {
01386 int i_group = (int)va_arg( args, int );
01387 vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * );
01388
01389 EsOutProgramMeta( out, i_group, p_meta );
01390 return VLC_SUCCESS;
01391 }
01392 case ES_OUT_DEL_GROUP:
01393 {
01394 int i_group = (int)va_arg( args, int );
01395
01396 return EsOutProgramDel( out, i_group );
01397 }
01398
01399 default:
01400 msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
01401 return VLC_EGENERIC;
01402 }
01403 }
01404
01405
01406
01407
01408 static char *LanguageGetName( const char *psz_code )
01409 {
01410 const iso639_lang_t *pl;
01411
01412 if( psz_code == NULL )
01413 {
01414 return strdup( "" );
01415 }
01416
01417 if( strlen( psz_code ) == 2 )
01418 {
01419 pl = GetLang_1( psz_code );
01420 }
01421 else if( strlen( psz_code ) == 3 )
01422 {
01423 pl = GetLang_2B( psz_code );
01424 if( !strcmp( pl->psz_iso639_1, "??" ) )
01425 {
01426 pl = GetLang_2T( psz_code );
01427 }
01428 }
01429 else
01430 {
01431 return strdup( psz_code );
01432 }
01433
01434 if( !strcmp( pl->psz_iso639_1, "??" ) )
01435 {
01436 return strdup( psz_code );
01437 }
01438 else
01439 {
01440 if( *pl->psz_native_name )
01441 {
01442 return strdup( pl->psz_native_name );
01443 }
01444 return strdup( pl->psz_eng_name );
01445 }
01446 }
01447
01448
01449 static char *LanguageGetCode( const char *psz_lang )
01450 {
01451 const iso639_lang_t *pl;
01452
01453 if( psz_lang == NULL || *psz_lang == '\0' )
01454 return strdup("??");
01455
01456 for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ )
01457 {
01458 if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
01459 !strcasecmp( pl->psz_native_name, psz_lang ) ||
01460 !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
01461 !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
01462 !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
01463 break;
01464 }
01465
01466 if( pl->psz_iso639_1 != NULL )
01467 return strdup( pl->psz_iso639_1 );
01468
01469 return strdup("??");
01470 }
01471
01472 static char **LanguageSplit( const char *psz_langs )
01473 {
01474 char *psz_dup;
01475 char *psz_parser;
01476 char **ppsz = NULL;
01477 int i_psz = 0;
01478
01479 if( psz_langs == NULL ) return NULL;
01480
01481 psz_parser = psz_dup = strdup(psz_langs);
01482
01483 while( psz_parser && *psz_parser )
01484 {
01485 char *psz;
01486 char *psz_code;
01487
01488 psz = strchr(psz_parser, ',' );
01489 if( psz ) *psz++ = '\0';
01490
01491 psz_code = LanguageGetCode( psz_parser );
01492 if( strcmp( psz_code, "??" ) )
01493 {
01494 TAB_APPEND( i_psz, ppsz, psz_code );
01495 }
01496
01497 psz_parser = psz;
01498 }
01499
01500 if( i_psz )
01501 {
01502 TAB_APPEND( i_psz, ppsz, NULL );
01503 }
01504
01505 free( psz_dup );
01506 return ppsz;
01507 }
01508
01509 static int LanguageArrayIndex( char **ppsz_langs, char *psz_lang )
01510 {
01511 int i;
01512
01513 if( !ppsz_langs || !psz_lang ) return -1;
01514
01515 for( i = 0; ppsz_langs[i]; i++ )
01516 if( !strcasecmp( ppsz_langs[i], psz_lang ) ) return i;
01517
01518 return -1;
01519 }
01520
01521
01522
01523
01524
01525 static void EsOutAddInfo( es_out_t *out, es_out_id_t *es )
01526 {
01527 es_out_sys_t *p_sys = out->p_sys;
01528 input_thread_t *p_input = p_sys->p_input;
01529 es_format_t *fmt = &es->fmt;
01530 char *psz_cat;
01531
01532
01533 asprintf( &psz_cat, _("Stream %d"), out->p_sys->i_id - 1 );
01534
01535 input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Codec"),
01536 "%.4s", (char*)&fmt->i_codec );
01537
01538 input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Language"),
01539 "%s", es->psz_language );
01540
01541
01542 switch( fmt->i_cat )
01543 {
01544 case AUDIO_ES:
01545 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01546 _("Type"), _("Audio") );
01547
01548 if( fmt->audio.i_channels > 0 )
01549 input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Channels"),
01550 "%d", fmt->audio.i_channels );
01551
01552 if( fmt->audio.i_rate > 0 )
01553 input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Sample rate"),
01554 _("%d Hz"), fmt->audio.i_rate );
01555
01556 if( fmt->audio.i_bitspersample > 0 )
01557 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01558 _("Bits per sample"), "%d",
01559 fmt->audio.i_bitspersample );
01560
01561 if( fmt->i_bitrate > 0 )
01562 input_Control( p_input, INPUT_ADD_INFO, psz_cat, _("Bitrate"),
01563 _("%d kb/s"), fmt->i_bitrate / 1000 );
01564 break;
01565
01566 case VIDEO_ES:
01567 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01568 _("Type"), _("Video") );
01569
01570 if( fmt->video.i_width > 0 && fmt->video.i_height > 0 )
01571 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01572 _("Resolution"), "%dx%d",
01573 fmt->video.i_width, fmt->video.i_height );
01574
01575 if( fmt->video.i_visible_width > 0 &&
01576 fmt->video.i_visible_height > 0 )
01577 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01578 _("Display resolution"), "%dx%d",
01579 fmt->video.i_visible_width,
01580 fmt->video.i_visible_height);
01581 if( fmt->video.i_frame_rate > 0 &&
01582 fmt->video.i_frame_rate_base > 0 )
01583 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01584 _("Frame rate"), "%f",
01585 (float)fmt->video.i_frame_rate /
01586 fmt->video.i_frame_rate_base );
01587 break;
01588
01589 case SPU_ES:
01590 input_Control( p_input, INPUT_ADD_INFO, psz_cat,
01591 _("Type"), _("Subtitle") );
01592 break;
01593
01594 default:
01595 break;
01596 }
01597
01598 free( psz_cat );
01599 }