ts.c
资源名称:vlc-1.0.5.zip [点击查看]
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:136k
源码类别:
midi
开发平台:
Unix_Linux
- return( i_len );
- }
- static int IODGetByte( int *pi_data, uint8_t **pp_data )
- {
- if( *pi_data > 0 )
- {
- const int i_b = **pp_data;
- (*pp_data)++;
- (*pi_data)--;
- return( i_b );
- }
- return( 0 );
- }
- static int IODGetWord( int *pi_data, uint8_t **pp_data )
- {
- const int i1 = IODGetByte( pi_data, pp_data );
- const int i2 = IODGetByte( pi_data, pp_data );
- return( ( i1 << 8 ) | i2 );
- }
- static int IODGet3Bytes( int *pi_data, uint8_t **pp_data )
- {
- const int i1 = IODGetByte( pi_data, pp_data );
- const int i2 = IODGetByte( pi_data, pp_data );
- const int i3 = IODGetByte( pi_data, pp_data );
- return( ( i1 << 16 ) | ( i2 << 8) | i3 );
- }
- static uint32_t IODGetDWord( int *pi_data, uint8_t **pp_data )
- {
- const uint32_t i1 = IODGetWord( pi_data, pp_data );
- const uint32_t i2 = IODGetWord( pi_data, pp_data );
- return( ( i1 << 16 ) | i2 );
- }
- static char* IODGetURL( int *pi_data, uint8_t **pp_data )
- {
- char *url;
- int i_url_len, i;
- i_url_len = IODGetByte( pi_data, pp_data );
- url = malloc( i_url_len + 1 );
- if( !url ) return NULL;
- for( i = 0; i < i_url_len; i++ )
- {
- url[i] = IODGetByte( pi_data, pp_data );
- }
- url[i_url_len] = ' ';
- return( url );
- }
- static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
- {
- iod_descriptor_t *p_iod;
- int i;
- int i_es_index;
- uint8_t i_flags, i_iod_tag, byte1, byte2, byte3;
- bool b_url;
- int i_iod_length;
- p_iod = malloc( sizeof( iod_descriptor_t ) );
- if( !p_iod ) return NULL;
- memset( p_iod, 0, sizeof( iod_descriptor_t ) );
- #ifdef TS_DEBUG
- fprintf( stderr, "n************ IOD ************" );
- #endif
- for( i = 0; i < 255; i++ )
- {
- p_iod->es_descr[i].b_ok = 0;
- }
- i_es_index = 0;
- if( i_data < 3 )
- {
- return p_iod;
- }
- byte1 = IODGetByte( &i_data, &p_data );
- byte2 = IODGetByte( &i_data, &p_data );
- byte3 = IODGetByte( &i_data, &p_data );
- if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor
- {
- p_iod->i_iod_label_scope = 0x11;
- p_iod->i_iod_label = byte1;
- i_iod_tag = byte2;
- }
- else //correct implementation of the IOD_descriptor
- {
- p_iod->i_iod_label_scope = byte1;
- p_iod->i_iod_label = byte2;
- i_iod_tag = byte3;
- }
- #ifdef TS_DEBUG
- fprintf( stderr, "n* iod_label:%d", p_iod->i_iod_label );
- fprintf( stderr, "n* ===========" );
- fprintf( stderr, "n* tag:0x%x", i_iod_tag );
- #endif
- if( i_iod_tag != 0x02 )
- {
- #ifdef TS_DEBUG
- fprintf( stderr, "n ERR: tag %02x != 0x02", i_iod_tag );
- #endif
- return p_iod;
- }
- i_iod_length = IODDescriptorLength( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* length:%d", i_iod_length );
- #endif
- if( i_iod_length > i_data )
- {
- i_iod_length = i_data;
- }
- p_iod->i_od_id = ( IODGetByte( &i_data, &p_data ) << 2 );
- i_flags = IODGetByte( &i_data, &p_data );
- p_iod->i_od_id |= i_flags >> 6;
- b_url = ( i_flags >> 5 )&0x01;
- #ifdef TS_DEBUG
- fprintf( stderr, "n* od_id:%d", p_iod->i_od_id );
- fprintf( stderr, "n* url flag:%d", b_url );
- fprintf( stderr, "n* includeInlineProfileLevel flag:%d", ( i_flags >> 4 )&0x01 );
- #endif
- if( b_url )
- {
- p_iod->psz_url = IODGetURL( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* url string:%s", p_iod->psz_url );
- fprintf( stderr, "n*****************************n" );
- #endif
- return p_iod;
- }
- else
- {
- p_iod->psz_url = NULL;
- }
- p_iod->i_ODProfileLevelIndication = IODGetByte( &i_data, &p_data );
- p_iod->i_sceneProfileLevelIndication = IODGetByte( &i_data, &p_data );
- p_iod->i_audioProfileLevelIndication = IODGetByte( &i_data, &p_data );
- p_iod->i_visualProfileLevelIndication = IODGetByte( &i_data, &p_data );
- p_iod->i_graphicsProfileLevelIndication = IODGetByte( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* ODProfileLevelIndication:%d", p_iod->i_ODProfileLevelIndication );
- fprintf( stderr, "n* sceneProfileLevelIndication:%d", p_iod->i_sceneProfileLevelIndication );
- fprintf( stderr, "n* audioProfileLevelIndication:%d", p_iod->i_audioProfileLevelIndication );
- fprintf( stderr, "n* visualProfileLevelIndication:%d", p_iod->i_visualProfileLevelIndication );
- fprintf( stderr, "n* graphicsProfileLevelIndication:%d", p_iod->i_graphicsProfileLevelIndication );
- #endif
- while( i_data > 0 && i_es_index < 255)
- {
- int i_tag, i_length;
- int i_data_sav;
- uint8_t *p_data_sav;
- i_tag = IODGetByte( &i_data, &p_data );
- i_length = IODDescriptorLength( &i_data, &p_data );
- i_data_sav = i_data;
- p_data_sav = p_data;
- i_data = i_length;
- switch( i_tag )
- {
- case 0x03:
- {
- #define es_descr p_iod->es_descr[i_es_index]
- int i_decoderConfigDescr_length;
- #ifdef TS_DEBUG
- fprintf( stderr, "n* - ES_Descriptor length:%d", i_length );
- #endif
- es_descr.b_ok = 1;
- es_descr.i_es_id = IODGetWord( &i_data, &p_data );
- i_flags = IODGetByte( &i_data, &p_data );
- es_descr.b_streamDependenceFlag = ( i_flags >> 7 )&0x01;
- b_url = ( i_flags >> 6 )&0x01;
- es_descr.b_OCRStreamFlag = ( i_flags >> 5 )&0x01;
- es_descr.i_streamPriority = i_flags & 0x1f;
- #ifdef TS_DEBUG
- fprintf( stderr, "n* * streamDependenceFlag:%d", es_descr.b_streamDependenceFlag );
- fprintf( stderr, "n* * OCRStreamFlag:%d", es_descr.b_OCRStreamFlag );
- fprintf( stderr, "n* * streamPriority:%d", es_descr.i_streamPriority );
- #endif
- if( es_descr.b_streamDependenceFlag )
- {
- es_descr.i_dependOn_es_id = IODGetWord( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* * dependOn_es_id:%d", es_descr.i_dependOn_es_id );
- #endif
- }
- if( b_url )
- {
- es_descr.psz_url = IODGetURL( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* url string:%s", es_descr.psz_url );
- #endif
- }
- else
- {
- es_descr.psz_url = NULL;
- }
- if( es_descr.b_OCRStreamFlag )
- {
- es_descr.i_OCR_es_id = IODGetWord( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* * OCR_es_id:%d", es_descr.i_OCR_es_id );
- #endif
- }
- if( IODGetByte( &i_data, &p_data ) != 0x04 )
- {
- #ifdef TS_DEBUG
- fprintf( stderr, "n* ERR missing DecoderConfigDescr" );
- #endif
- es_descr.b_ok = 0;
- break;
- }
- i_decoderConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* - DecoderConfigDesc length:%d", i_decoderConfigDescr_length );
- #endif
- #define dec_descr es_descr.dec_descr
- dec_descr.i_objectTypeIndication = IODGetByte( &i_data, &p_data );
- i_flags = IODGetByte( &i_data, &p_data );
- dec_descr.i_streamType = i_flags >> 2;
- dec_descr.b_upStream = ( i_flags >> 1 )&0x01;
- dec_descr.i_bufferSizeDB = IODGet3Bytes( &i_data, &p_data );
- dec_descr.i_maxBitrate = IODGetDWord( &i_data, &p_data );
- dec_descr.i_avgBitrate = IODGetDWord( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* * objectTypeIndication:0x%x", dec_descr.i_objectTypeIndication );
- fprintf( stderr, "n* * streamType:0x%x", dec_descr.i_streamType );
- fprintf( stderr, "n* * upStream:%d", dec_descr.b_upStream );
- fprintf( stderr, "n* * bufferSizeDB:%d", dec_descr.i_bufferSizeDB );
- fprintf( stderr, "n* * maxBitrate:%d", dec_descr.i_maxBitrate );
- fprintf( stderr, "n* * avgBitrate:%d", dec_descr.i_avgBitrate );
- #endif
- if( i_decoderConfigDescr_length > 13 && IODGetByte( &i_data, &p_data ) == 0x05 )
- {
- int i;
- dec_descr.i_decoder_specific_info_len =
- IODDescriptorLength( &i_data, &p_data );
- if( dec_descr.i_decoder_specific_info_len > 0 )
- {
- dec_descr.p_decoder_specific_info =
- malloc( dec_descr.i_decoder_specific_info_len );
- }
- for( i = 0; i < dec_descr.i_decoder_specific_info_len; i++ )
- {
- dec_descr.p_decoder_specific_info[i] = IODGetByte( &i_data, &p_data );
- }
- }
- else
- {
- dec_descr.i_decoder_specific_info_len = 0;
- dec_descr.p_decoder_specific_info = NULL;
- }
- }
- #undef dec_descr
- #define sl_descr es_descr.sl_descr
- {
- int i_SLConfigDescr_length;
- int i_predefined;
- if( IODGetByte( &i_data, &p_data ) != 0x06 )
- {
- #ifdef TS_DEBUG
- fprintf( stderr, "n* ERR missing SLConfigDescr" );
- #endif
- es_descr.b_ok = 0;
- break;
- }
- i_SLConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* - SLConfigDescr length:%d", i_SLConfigDescr_length );
- #endif
- i_predefined = IODGetByte( &i_data, &p_data );
- #ifdef TS_DEBUG
- fprintf( stderr, "n* * i_predefined:0x%x", i_predefined );
- #endif
- switch( i_predefined )
- {
- case 0x01:
- {
- sl_descr.b_useAccessUnitStartFlag = 0;
- sl_descr.b_useAccessUnitEndFlag = 0;
- sl_descr.b_useRandomAccessPointFlag = 0;
- //sl_descr.b_useRandomAccessUnitsOnlyFlag = 0;
- sl_descr.b_usePaddingFlag = 0;
- sl_descr.b_useTimeStampsFlags = 0;
- sl_descr.b_useIdleFlag = 0;
- sl_descr.b_durationFlag = 0; // FIXME FIXME
- sl_descr.i_timeStampResolution = 1000;
- sl_descr.i_OCRResolution = 0; // FIXME FIXME
- sl_descr.i_timeStampLength = 32;
- sl_descr.i_OCRLength = 0; // FIXME FIXME
- sl_descr.i_AU_Length = 0;
- sl_descr.i_instantBitrateLength= 0; // FIXME FIXME
- sl_descr.i_degradationPriorityLength= 0;
- sl_descr.i_AU_seqNumLength = 0;
- sl_descr.i_packetSeqNumLength = 0;
- if( sl_descr.b_durationFlag )
- {
- sl_descr.i_timeScale = 0; // FIXME FIXME
- sl_descr.i_accessUnitDuration = 0; // FIXME FIXME
- sl_descr.i_compositionUnitDuration= 0; // FIXME FIXME
- }
- if( !sl_descr.b_useTimeStampsFlags )
- {
- sl_descr.i_startDecodingTimeStamp = 0; // FIXME FIXME
- sl_descr.i_startCompositionTimeStamp= 0; // FIXME FIXME
- }
- }
- break;
- default:
- #ifdef TS_DEBUG
- fprintf( stderr, "n* ERR unsupported SLConfigDescr predefined" );
- #endif
- es_descr.b_ok = 0;
- break;
- }
- }
- break;
- #undef sl_descr
- #undef es_descr
- default:
- #ifdef TS_DEBUG
- fprintf( stderr, "n* - OD tag:0x%x length:%d (Unsupported)", i_tag, i_length );
- #endif
- break;
- }
- p_data = p_data_sav + i_length;
- i_data = i_data_sav - i_length;
- i_es_index++;
- }
- #ifdef TS_DEBUG
- fprintf( stderr, "n*****************************n" );
- #endif
- return p_iod;
- }
- static void IODFree( iod_descriptor_t *p_iod )
- {
- int i;
- if( p_iod->psz_url )
- {
- free( p_iod->psz_url );
- p_iod->psz_url = NULL;
- free( p_iod );
- return;
- }
- for( i = 0; i < 255; i++ )
- {
- #define es_descr p_iod->es_descr[i]
- if( es_descr.b_ok )
- {
- if( es_descr.psz_url )
- {
- free( es_descr.psz_url );
- es_descr.psz_url = NULL;
- }
- else
- {
- free( es_descr.dec_descr.p_decoder_specific_info );
- es_descr.dec_descr.p_decoder_specific_info = NULL;
- es_descr.dec_descr.i_decoder_specific_info_len = 0;
- }
- }
- es_descr.b_ok = 0;
- #undef es_descr
- }
- free( p_iod );
- }
- /****************************************************************************
- ****************************************************************************
- ** libdvbpsi callbacks
- ****************************************************************************
- ****************************************************************************/
- static bool ProgramIsSelected( demux_t *p_demux, uint16_t i_pgrm )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- if( !p_sys->b_access_control )
- return false;
- if( ( p_sys->i_current_program == -1 && p_sys->p_programs_list == NULL ) ||
- p_sys->i_current_program == 0 )
- return true;
- if( p_sys->i_current_program == i_pgrm )
- return true;
- if( p_sys->p_programs_list != NULL )
- {
- for( int i = 0; i < p_sys->p_programs_list->i_count; i++ )
- {
- if( i_pgrm == p_sys->p_programs_list->p_values[i].i_int )
- return true;
- }
- }
- return false;
- }
- static void ValidateDVBMeta( demux_t *p_demux, int i_pid )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- if( !p_sys->b_dvb_meta || ( i_pid != 0x11 && i_pid != 0x12 ) )
- return;
- msg_Warn( p_demux, "Switching to non DVB mode" );
- /* This doesn't look like a DVB stream so don't try
- * parsing the SDT/EDT */
- for( int i = 0x11; i <= 0x12; i++ )
- {
- ts_pid_t *p_pid = &p_sys->pid[i];
- if( p_pid->psi )
- {
- dvbpsi_DetachDemux( p_pid->psi->handle );
- free( p_pid->psi );
- p_pid->psi = NULL;
- p_pid->b_valid = false;
- }
- if( p_sys->b_access_control )
- stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE, i, false );
- }
- p_sys->b_dvb_meta = false;
- }
- #ifdef TS_USE_DVB_SI
- /* FIXME same than dvbsi_to_utf8 from dvb access */
- static char *EITConvertToUTF8( const unsigned char *psz_instring,
- size_t i_length )
- {
- const char *psz_encoding;
- char *psz_outstring;
- char psz_encbuf[sizeof( "ISO_8859-123" )];
- size_t i_in, i_out, offset = 1;
- vlc_iconv_t iconv_handle;
- if( i_length < 1 ) return NULL;
- if( psz_instring[0] >= 0x20 )
- {
- /* According to ETSI EN 300 468 Annex A, this should be ISO6937,
- * but some broadcasters use different charset... */
- if ( i_broken_epg == 1 )
- {
- psz_encoding = "ISO_8859-1";
- }
- else
- {
- psz_encoding = "ISO_6937";
- }
- offset = 0;
- }
- else switch( psz_instring[0] )
- {
- case 0x01:
- psz_encoding = "ISO_8859-5";
- break;
- case 0x02:
- psz_encoding = "ISO_8859-6";
- break;
- case 0x03:
- psz_encoding = "ISO_8859-7";
- break;
- case 0x04:
- psz_encoding = "ISO_8859-8";
- break;
- case 0x05:
- psz_encoding = "ISO_8859-9";
- break;
- case 0x06:
- psz_encoding = "ISO_8859-10";
- break;
- case 0x07:
- psz_encoding = "ISO_8859-11";
- break;
- case 0x08:
- psz_encoding = "ISO_8859-12";
- break;
- case 0x09:
- psz_encoding = "ISO_8859-13";
- break;
- case 0x0a:
- psz_encoding = "ISO_8859-14";
- break;
- case 0x0b:
- psz_encoding = "ISO_8859-15";
- break;
- case 0x10:
- #warning Is Latin-10 (psz_instring[2] == 16) really illegal?
- if( i_length < 3 || psz_instring[1] != 0x00 || psz_instring[2] > 15
- || psz_instring[2] == 0 )
- {
- psz_encoding = "UTF-8";
- offset = 0;
- }
- else
- {
- sprintf( psz_encbuf, "ISO_8859-%u", psz_instring[2] );
- psz_encoding = psz_encbuf;
- offset = 3;
- }
- break;
- case 0x11:
- #warning Is there a BOM or do we use a fixed endianess?
- psz_encoding = "UTF-16";
- break;
- case 0x12:
- psz_encoding = "KSC5601-1987";
- break;
- case 0x13:
- psz_encoding = "GB2312"; /* GB-2312-1980 */
- break;
- case 0x14:
- psz_encoding = "BIG-5";
- break;
- case 0x15:
- psz_encoding = "UTF-8";
- break;
- default:
- /* invalid */
- psz_encoding = "UTF-8";
- offset = 0;
- }
- i_in = i_length - offset;
- i_out = i_in * 6 + 1;
- psz_outstring = malloc( i_out );
- if( !psz_outstring )
- {
- return NULL;
- }
- iconv_handle = vlc_iconv_open( "UTF-8", psz_encoding );
- if( iconv_handle == (vlc_iconv_t)(-1) )
- {
- /* Invalid character set (e.g. ISO_8859-12) */
- memcpy( psz_outstring, &psz_instring[offset], i_in );
- psz_outstring[i_in] = ' ';
- EnsureUTF8( psz_outstring );
- }
- else
- {
- const char *psz_in = (const char *)&psz_instring[offset];
- char *psz_out = psz_outstring;
- while( vlc_iconv( iconv_handle, &psz_in, &i_in,
- &psz_out, &i_out ) == (size_t)(-1) )
- {
- /* skip naughty byte. This may fail terribly for multibyte stuff,
- * but what can we do anyway? */
- psz_in++;
- i_in--;
- vlc_iconv( iconv_handle, NULL, NULL, NULL, NULL ); /* reset */
- }
- vlc_iconv_close( iconv_handle );
- *psz_out = ' ';
- }
- return psz_outstring;
- }
- static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- ts_pid_t *sdt = &p_sys->pid[0x11];
- dvbpsi_sdt_service_t *p_srv;
- msg_Dbg( p_demux, "SDTCallBack called" );
- if( sdt->psi->i_sdt_version != -1 &&
- ( !p_sdt->b_current_next ||
- p_sdt->i_version == sdt->psi->i_sdt_version ) )
- {
- dvbpsi_DeleteSDT( p_sdt );
- return;
- }
- msg_Dbg( p_demux, "new SDT ts_id=%d version=%d current_next=%d "
- "network_id=%d",
- p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next,
- p_sdt->i_network_id );
- i_broken_epg = 0;
- for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
- {
- vlc_meta_t *p_meta;
- dvbpsi_descriptor_t *p_dr;
- const char *psz_type = NULL;
- const char *psz_status = NULL;
- msg_Dbg( p_demux, " * service id=%d eit schedule=%d present=%d "
- "running=%d free_ca=%d",
- p_srv->i_service_id, p_srv->b_eit_schedule,
- p_srv->b_eit_present, p_srv->i_running_status,
- p_srv->b_free_ca );
- if( p_sys->i_current_program != -1 && p_sys->i_current_program != p_srv->i_service_id )
- continue;
- p_meta = vlc_meta_New();
- for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
- {
- if( p_dr->i_tag == 0x48 )
- {
- static const char *ppsz_type[17] = {
- "Reserved",
- "Digital television service",
- "Digital radio sound service",
- "Teletext service",
- "NVOD reference service",
- "NVOD time-shifted service",
- "Mosaic service",
- "PAL coded signal",
- "SECAM coded signal",
- "D/D2-MAC",
- "FM Radio",
- "NTSC coded signal",
- "Data broadcast service",
- "Reserved for Common Interface Usage",
- "RCS Map (see EN 301 790 [35])",
- "RCS FLS (see EN 301 790 [35])",
- "DVB MHP service"
- };
- dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
- char *str1 = NULL;
- char *str2 = NULL;
- /* Workarounds for broadcasters with broken EPG */
- if ( p_sdt->i_network_id == 133 )
- i_broken_epg = 1; /* SKY DE & BetaDigital use ISO8859-1 */
- if ( (pD->i_service_provider_name_length == 4) &&
- !strncmp(pD->i_service_provider_name, "CSAT", 4) )
- i_broken_epg = 1; /* CanalSat FR uses ISO8859-1 */
- /* FIXME: Digital+ ES also uses ISO8859-1 */
- str1 = EITConvertToUTF8(pD->i_service_provider_name,
- pD->i_service_provider_name_length);
- str2 = EITConvertToUTF8(pD->i_service_name,
- pD->i_service_name_length);
- msg_Dbg( p_demux, " - type=%d provider=%s name=%s",
- pD->i_service_type, str1, str2 );
- vlc_meta_SetTitle( p_meta, str2 );
- vlc_meta_SetPublisher( p_meta, str1 );
- if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 )
- psz_type = ppsz_type[pD->i_service_type];
- free( str1 );
- free( str2 );
- }
- }
- if( p_srv->i_running_status >= 0x01 && p_srv->i_running_status <= 0x04 )
- {
- static const char *ppsz_status[5] = {
- "Unknown",
- "Not running",
- "Starts in a few seconds",
- "Pausing",
- "Running"
- };
- psz_status = ppsz_status[p_srv->i_running_status];
- }
- if( psz_type )
- vlc_meta_AddExtra( p_meta, "Type", psz_type );
- if( psz_status )
- vlc_meta_AddExtra( p_meta, "Status", psz_status );
- es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
- p_srv->i_service_id, p_meta );
- vlc_meta_Delete( p_meta );
- }
- sdt->psi->i_sdt_version = p_sdt->i_version;
- dvbpsi_DeleteSDT( p_sdt );
- }
- /* i_year: year - 1900 i_month: 0-11 i_mday: 1-31 i_hour: 0-23 i_minute: 0-59 i_second: 0-59 */
- static int64_t vlc_timegm( int i_year, int i_month, int i_mday, int i_hour, int i_minute, int i_second )
- {
- static const int pn_day[12+1] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
- int64_t i_day;
- int i;
- if( i_year < 70 ||
- i_month < 0 || i_month > 11 || i_mday < 1 || i_mday > 31 ||
- i_hour < 0 || i_hour > 23 || i_minute < 0 || i_minute > 59 || i_second < 0 || i_second > 59 )
- return -1;
- /* Count the number of days */
- i_day = 365 * (i_year-70) + pn_day[i_month] + i_mday - 1;
- #define LEAP(y) ( ((y)%4) == 0 && (((y)%100) != 0 || ((y)%400) == 0) ? 1 : 0)
- for( i = 70; i < i_year; i++ )
- i_day += LEAP(1900+i);
- if( i_month > 1 )
- i_day += LEAP(1900+i_year);
- #undef LEAP
- /**/
- return ((24*i_day + i_hour)*60 + i_minute)*60 + i_second;
- }
- static void EITDecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d )
- {
- const int yp = (int)( ( (double)i_mjd - 15078.2)/365.25 );
- const int mp = (int)( ((double)i_mjd - 14956.1 - (int)(yp * 365.25)) / 30.6001 );
- const int c = ( mp == 14 || mp == 15 ) ? 1 : 0;
- *p_y = 1900 + yp + c*1;
- *p_m = mp - 1 - c*12;
- *p_d = i_mjd - 14956 - (int)(yp*365.25) - (int)(mp*30.6001);
- }
- #define CVT_FROM_BCD(v) ((((v) >> 4)&0xf)*10 + ((v)&0xf))
- static int64_t EITConvertStartTime( uint64_t i_date )
- {
- const int i_mjd = i_date >> 24;
- const int i_hour = CVT_FROM_BCD(i_date >> 16);
- const int i_minute = CVT_FROM_BCD(i_date >> 8);
- const int i_second = CVT_FROM_BCD(i_date );
- int i_year;
- int i_month;
- int i_day;
- /* if all 40 bits are 1, the start is unknown */
- if( i_date == UINT64_C(0xffffffffff) )
- return -1;
- EITDecodeMjd( i_mjd, &i_year, &i_month, &i_day );
- return vlc_timegm( i_year - 1900, i_month - 1, i_day, i_hour, i_minute, i_second );
- }
- static int EITConvertDuration( uint32_t i_duration )
- {
- return CVT_FROM_BCD(i_duration >> 16) * 3600 +
- CVT_FROM_BCD(i_duration >> 8 ) * 60 +
- CVT_FROM_BCD(i_duration );
- }
- #undef CVT_FROM_BCD
- static void EITCallBack( demux_t *p_demux,
- dvbpsi_eit_t *p_eit, bool b_current_following )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- dvbpsi_eit_event_t *p_evt;
- vlc_epg_t *p_epg;
- msg_Dbg( p_demux, "EITCallBack called" );
- if( !p_eit->b_current_next || ( p_sys->i_current_program != -1 && p_sys->i_current_program != p_eit->i_service_id ) )
- {
- dvbpsi_DeleteEIT( p_eit );
- return;
- }
- msg_Dbg( p_demux, "new EIT service_id=%d version=%d current_next=%d "
- "ts_id=%d network_id=%d segment_last_section_number=%d "
- "last_table_id=%d",
- p_eit->i_service_id, p_eit->i_version, p_eit->b_current_next,
- p_eit->i_ts_id, p_eit->i_network_id,
- p_eit->i_segment_last_section_number, p_eit->i_last_table_id );
- p_epg = vlc_epg_New( NULL );
- for( p_evt = p_eit->p_first_event; p_evt; p_evt = p_evt->p_next )
- {
- dvbpsi_descriptor_t *p_dr;
- char *psz_name = NULL;
- char *psz_text = NULL;
- char *psz_extra = strdup("");
- int64_t i_start;
- int i_duration;
- i_start = EITConvertStartTime( p_evt->i_start_time );
- i_duration = EITConvertDuration( p_evt->i_duration );
- msg_Dbg( p_demux, " * event id=%d start_time:%d duration=%d "
- "running=%d free_ca=%d",
- p_evt->i_event_id, (int)i_start, (int)i_duration,
- p_evt->i_running_status, p_evt->b_free_ca );
- for( p_dr = p_evt->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
- {
- if( p_dr->i_tag == 0x4d )
- {
- dvbpsi_short_event_dr_t *pE = dvbpsi_DecodeShortEventDr( p_dr );
- if( pE )
- {
- psz_name = EITConvertToUTF8( pE->i_event_name, pE->i_event_name_length);
- psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length );
- msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'",
- pE->i_iso_639_code, psz_name, psz_text );
- }
- }
- else if( p_dr->i_tag == 0x4e )
- {
- dvbpsi_extended_event_dr_t *pE = dvbpsi_DecodeExtendedEventDr( p_dr );
- if( pE )
- {
- msg_Dbg( p_demux, " - extended event lang=%3.3s [%d/%d]",
- pE->i_iso_639_code,
- pE->i_descriptor_number, pE->i_last_descriptor_number );
- if( pE->i_text_length > 0 )
- {
- char *psz_text = EITConvertToUTF8( pE->i_text, pE->i_text_length );
- if( psz_text )
- {
- msg_Dbg( p_demux, " - text='%s'", psz_text );
- psz_extra = realloc( psz_extra, strlen(psz_extra) + strlen(psz_text) + 1 );
- strcat( psz_extra, psz_text );
- free( psz_text );
- }
- }
- for( int i = 0; i < pE->i_entry_count; i++ )
- {
- char *psz_dsc = EITConvertToUTF8( pE->i_item_description[i],
- pE->i_item_description_length[i] );
- char *psz_itm = EITConvertToUTF8( pE->i_item[i], pE->i_item_length[i] );
- if( psz_dsc && psz_itm )
- {
- msg_Dbg( p_demux, " - desc='%s' item='%s'", psz_dsc, psz_itm );
- #if 0
- psz_extra = realloc( psz_extra, strlen(psz_extra) + strlen(psz_dsc) + strlen(psz_itm) + 3 + 1 );
- strcat( psz_extra, "(" );
- strcat( psz_extra, psz_dsc );
- strcat( psz_extra, " " );
- strcat( psz_extra, psz_itm );
- strcat( psz_extra, ")" );
- #endif
- }
- free( psz_dsc );
- free( psz_itm );
- }
- }
- }
- else
- {
- msg_Dbg( p_demux, " - tag=0x%x(%d)", p_dr->i_tag, p_dr->i_tag );
- }
- }
- /* */
- if( i_start > 0 )
- vlc_epg_AddEvent( p_epg, i_start, i_duration, psz_name, psz_text,
- *psz_extra ? psz_extra : NULL );
- /* Update "now playing" field */
- if( p_evt->i_running_status == 0x04 && i_start > 0 )
- vlc_epg_SetCurrent( p_epg, i_start );
- free( psz_name );
- free( psz_text );
- free( psz_extra );
- }
- if( p_epg->i_event > 0 )
- {
- if( p_eit->i_service_id == p_sys->i_current_program && b_current_following )
- {
- p_sys->i_dvb_length = 0;
- p_sys->i_dvb_start = 0;
- if( p_epg->p_current )
- {
- p_sys->i_dvb_start = p_epg->p_current->i_start;
- p_sys->i_dvb_length = p_epg->p_current->i_duration;
- }
- }
- es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG, p_eit->i_service_id, p_epg );
- }
- vlc_epg_Delete( p_epg );
- dvbpsi_DeleteEIT( p_eit );
- }
- static void EITCallBackCurrentFollowing( demux_t *p_demux, dvbpsi_eit_t *p_eit )
- {
- EITCallBack( p_demux, p_eit, true );
- }
- static void EITCallBackSchedule( demux_t *p_demux, dvbpsi_eit_t *p_eit )
- {
- EITCallBack( p_demux, p_eit, false );
- }
- static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h,
- uint8_t i_table_id, uint16_t i_extension )
- {
- #if 0
- msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
- i_table_id, i_table_id, i_extension, i_extension );
- #endif
- if( p_demux->p_sys->pid[0].psi->i_pat_version != -1 && i_table_id == 0x42 )
- {
- msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
- i_table_id, i_table_id, i_extension, i_extension );
- dvbpsi_AttachSDT( h, i_table_id, i_extension,
- (dvbpsi_sdt_callback)SDTCallBack, p_demux );
- }
- else if( p_demux->p_sys->pid[0x11].psi->i_sdt_version != -1 &&
- ( i_table_id == 0x4e || /* Current/Following */
- (i_table_id >= 0x50 && i_table_id <= 0x5f) ) ) /* Schedule */
- {
- msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
- i_table_id, i_table_id, i_extension, i_extension );
- dvbpsi_eit_callback cb = i_table_id == 0x4e ?
- (dvbpsi_eit_callback)EITCallBackCurrentFollowing :
- (dvbpsi_eit_callback)EITCallBackSchedule;
- dvbpsi_AttachEIT( h, i_table_id, i_extension, cb, p_demux );
- }
- }
- #endif
- /*****************************************************************************
- * PMT callback and helpers
- *****************************************************************************/
- static dvbpsi_descriptor_t *PMTEsFindDescriptor( const dvbpsi_pmt_es_t *p_es,
- int i_tag )
- {
- dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;;
- while( p_dr && ( p_dr->i_tag != i_tag ) )
- p_dr = p_dr->p_next;
- return p_dr;
- }
- static bool PMTEsHasRegistration( demux_t *p_demux,
- const dvbpsi_pmt_es_t *p_es,
- const char *psz_tag )
- {
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x05 );
- if( !p_dr )
- return false;
- if( p_dr->i_length < 4 )
- {
- msg_Warn( p_demux, "invalid Registration Descriptor" );
- return false;
- }
- assert( strlen(psz_tag) == 4 );
- return !memcmp( p_dr->p_data, psz_tag, 4 );
- }
- static void PMTSetupEsISO14496( demux_t *p_demux, ts_pid_t *pid,
- const ts_prg_psi_t *prg, const dvbpsi_pmt_es_t *p_es )
- {
- es_format_t *p_fmt = &pid->es->fmt;
- /* MPEG-4 stream: search SL_DESCRIPTOR */
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x1f );
- if( p_dr && p_dr->i_length == 2 )
- {
- const int i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1];
- msg_Warn( p_demux, "found SL_descriptor es_id=%d", i_es_id );
- pid->es->p_mpeg4desc = NULL;
- for( int i = 0; i < 255; i++ )
- {
- iod_descriptor_t *iod = prg->iod;
- if( iod->es_descr[i].b_ok &&
- iod->es_descr[i].i_es_id == i_es_id )
- {
- pid->es->p_mpeg4desc = &iod->es_descr[i];
- break;
- }
- }
- }
- if( !pid->es->p_mpeg4desc )
- {
- msg_Err( p_demux, "MPEG-4 descriptor not found" );
- return;
- }
- const decoder_config_descriptor_t *dcd = &pid->es->p_mpeg4desc->dec_descr;
- if( dcd->i_streamType == 0x04 ) /* VisualStream */
- {
- p_fmt->i_cat = VIDEO_ES;
- switch( dcd->i_objectTypeIndication )
- {
- case 0x0B: /* mpeg4 sub */
- p_fmt->i_cat = SPU_ES;
- p_fmt->i_codec = VLC_FOURCC('s','u','b','t');
- break;
- case 0x20: /* mpeg4 */
- p_fmt->i_codec = VLC_FOURCC('m','p','4','v');
- break;
- case 0x21: /* h264 */
- p_fmt->i_codec = VLC_FOURCC('h','2','6','4');
- break;
- case 0x60:
- case 0x61:
- case 0x62:
- case 0x63:
- case 0x64:
- case 0x65: /* mpeg2 */
- p_fmt->i_codec = VLC_FOURCC( 'm','p','g','v' );
- break;
- case 0x6a: /* mpeg1 */
- p_fmt->i_codec = VLC_FOURCC( 'm','p','g','v' );
- break;
- case 0x6c: /* mpeg1 */
- p_fmt->i_codec = VLC_FOURCC( 'j','p','e','g' );
- break;
- default:
- p_fmt->i_cat = UNKNOWN_ES;
- break;
- }
- }
- else if( dcd->i_streamType == 0x05 ) /* AudioStream */
- {
- p_fmt->i_cat = AUDIO_ES;
- switch( dcd->i_objectTypeIndication )
- {
- case 0x40: /* mpeg4 */
- p_fmt->i_codec = VLC_FOURCC('m','p','4','a');
- break;
- case 0x66:
- case 0x67:
- case 0x68: /* mpeg2 aac */
- p_fmt->i_codec = VLC_FOURCC('m','p','4','a');
- break;
- case 0x69: /* mpeg2 */
- p_fmt->i_codec = VLC_FOURCC('m','p','g','a');
- break;
- case 0x6b: /* mpeg1 */
- p_fmt->i_codec = VLC_FOURCC('m','p','g','a');
- break;
- default:
- p_fmt->i_cat = UNKNOWN_ES;
- break;
- }
- }
- else
- {
- p_fmt->i_cat = UNKNOWN_ES;
- }
- if( p_fmt->i_cat != UNKNOWN_ES )
- {
- p_fmt->i_extra = dcd->i_decoder_specific_info_len;
- if( p_fmt->i_extra > 0 )
- {
- p_fmt->p_extra = malloc( p_fmt->i_extra );
- if( p_fmt->p_extra )
- memcpy( p_fmt->p_extra,
- dcd->p_decoder_specific_info,
- p_fmt->i_extra );
- else
- p_fmt->i_extra = 0;
- }
- }
- }
- typedef struct
- {
- int i_type;
- int i_magazine;
- int i_page;
- char p_iso639[3];
- } ts_teletext_page_t;
- static void PMTSetupEsTeletext( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- es_format_t *p_fmt = &pid->es->fmt;
- ts_teletext_page_t p_page[2 * 64 + 20];
- int i_page = 0;
- /* Gather pages informations */
- #if defined _DVBPSI_DR_56_H_ &&
- defined DVBPSI_VERSION && DVBPSI_VERSION_INT > ((0<<16)+(1<<8)+5)
- for( int i_tag_idx = 0; i_tag_idx < 2; i_tag_idx++ )
- {
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, i_tag_idx == 0 ? 0x46 : 0x56 );
- if( !p_dr )
- continue;
- dvbpsi_teletext_dr_t *p_sub = dvbpsi_DecodeTeletextDr( p_dr );
- if( !p_sub )
- continue;
- for( int i = 0; i < p_sub->i_pages_number; i++ )
- {
- const dvbpsi_teletextpage_t *p_src = &p_sub->p_pages[i];
- if( p_src->i_teletext_type < 0 || p_src->i_teletext_type >= 0x06 )
- continue;
- assert( i_page < sizeof(p_page)/sizeof(*p_page) );
- ts_teletext_page_t *p_dst = &p_page[i_page++];
- p_dst->i_type = p_src->i_teletext_type;
- p_dst->i_magazine = p_src->i_teletext_magazine_number
- ? p_src->i_teletext_magazine_number : 8;
- p_dst->i_page = p_src->i_teletext_page_number;
- memcpy( p_dst->p_iso639, p_src->i_iso6392_language_code, 3 );
- }
- }
- #endif
- #ifdef _DVBPSI_DR_59_H_
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x59 );
- if( p_dr )
- {
- dvbpsi_subtitling_dr_t *p_sub = dvbpsi_DecodeSubtitlingDr( p_dr );
- for( int i = 0; p_sub && i < p_sub->i_subtitles_number; i++ )
- {
- dvbpsi_subtitle_t *p_src = &p_sub->p_subtitle[i];
- if( p_src->i_subtitling_type < 0x01 || p_src->i_subtitling_type > 0x03 )
- continue;
- assert( i_page < sizeof(p_page)/sizeof(*p_page) );
- ts_teletext_page_t *p_dst = &p_page[i_page++];
- switch( p_src->i_subtitling_type )
- {
- case 0x01:
- p_dst->i_type = 0x02;
- break;
- default:
- p_dst->i_type = 0x03;
- break;
- }
- /* FIXME check if it is the right split */
- p_dst->i_magazine = (p_src->i_composition_page_id >> 8)
- ? (p_src->i_composition_page_id >> 8) : 8;
- p_dst->i_page = p_src->i_composition_page_id & 0xff;
- memcpy( p_dst->p_iso639, p_src->i_iso6392_language_code, 3 );
- }
- }
- #endif
- /* */
- es_format_Init( p_fmt, SPU_ES, VLC_FOURCC( 't', 'e', 'l', 'x' ) );
- /* In stream output mode, do not separate the stream by page */
- if( p_demux->out->b_sout || i_page <= 0 )
- {
- p_fmt->subs.teletext.i_magazine = -1;
- p_fmt->subs.teletext.i_page = 0;
- p_fmt->psz_description = strdup( vlc_gettext(ppsz_teletext_type[1]) );
- dvbpsi_descriptor_t *p_dr;
- p_dr = PMTEsFindDescriptor( p_es, 0x46 );
- if( !p_dr )
- p_dr = PMTEsFindDescriptor( p_es, 0x56 );
- if( p_demux->out->b_sout && p_dr && p_dr->i_length > 0 )
- {
- /* Descriptor pass-through for sout */
- p_fmt->p_extra = malloc( p_dr->i_length );
- if( p_fmt->p_extra )
- {
- p_fmt->i_extra = p_dr->i_length;
- memcpy( p_fmt->p_extra, p_dr->p_data, p_dr->i_length );
- }
- }
- }
- else
- {
- for( int i = 0; i < i_page; i++ )
- {
- ts_es_t *p_es;
- /* */
- if( i == 0 )
- {
- p_es = pid->es;
- }
- else
- {
- p_es = malloc( sizeof(*p_es) );
- if( !p_es )
- break;
- es_format_Copy( &p_es->fmt, &pid->es->fmt );
- free( p_es->fmt.psz_language );
- free( p_es->fmt.psz_description );
- p_es->fmt.psz_language = NULL;
- p_es->fmt.psz_description = NULL;
- p_es->id = NULL;
- p_es->p_pes = NULL;
- p_es->i_pes_size = 0;
- p_es->i_pes_gathered = 0;
- p_es->pp_last = &p_es->p_pes;
- p_es->p_mpeg4desc = NULL;
- p_es->b_gather = false;
- TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es );
- }
- /* */
- const ts_teletext_page_t *p = &p_page[i];
- p_es->fmt.psz_language = strndup( p->p_iso639, 3 );
- p_es->fmt.psz_description = strdup(vlc_gettext(ppsz_teletext_type[p->i_type]));
- p_es->fmt.subs.teletext.i_magazine = p->i_magazine;
- p_es->fmt.subs.teletext.i_page = p->i_page;
- msg_Dbg( p_demux,
- " * ttxt type=%s lan=%s page=%d%02x",
- p_es->fmt.psz_description,
- p_es->fmt.psz_language,
- p->i_magazine, p->i_page );
- }
- }
- }
- static void PMTSetupEsDvbSubtitle( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- es_format_t *p_fmt = &pid->es->fmt;
- es_format_Init( p_fmt, SPU_ES, VLC_FOURCC( 'd', 'v', 'b', 's' ) );
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x59 );
- int i_page = 0;
- #ifdef _DVBPSI_DR_59_H_
- dvbpsi_subtitling_dr_t *p_sub = dvbpsi_DecodeSubtitlingDr( p_dr );
- for( int i = 0; p_sub && i < p_sub->i_subtitles_number; i++ )
- {
- const int i_type = p_sub->p_subtitle[i].i_subtitling_type;
- if( ( i_type >= 0x10 && i_type <= 0x13 ) ||
- ( i_type >= 0x20 && i_type <= 0x23 ) )
- i_page++;
- }
- #endif
- /* In stream output mode, do not separate the stream by page */
- if( p_demux->out->b_sout || i_page <= 0 )
- {
- p_fmt->subs.dvb.i_id = -1;
- p_fmt->psz_description = strdup( _("DVB subtitles") );
- if( p_demux->out->b_sout && p_dr && p_dr->i_length > 0 )
- {
- /* Descriptor pass-through for sout */
- p_fmt->p_extra = malloc( p_dr->i_length );
- if( p_fmt->p_extra )
- {
- p_fmt->i_extra = p_dr->i_length;
- memcpy( p_fmt->p_extra, p_dr->p_data, p_dr->i_length );
- }
- }
- }
- else
- {
- #ifdef _DVBPSI_DR_59_H_
- for( int i = 0; i < p_sub->i_subtitles_number; i++ )
- {
- ts_es_t *p_es;
- /* */
- if( i == 0 )
- {
- p_es = pid->es;
- }
- else
- {
- p_es = malloc( sizeof(*p_es) );
- if( !p_es )
- break;
- es_format_Copy( &p_es->fmt, &pid->es->fmt );
- free( p_es->fmt.psz_language );
- free( p_es->fmt.psz_description );
- p_es->fmt.psz_language = NULL;
- p_es->fmt.psz_description = NULL;
- p_es->id = NULL;
- p_es->p_pes = NULL;
- p_es->i_pes_size = 0;
- p_es->i_pes_gathered = 0;
- p_es->pp_last = &p_es->p_pes;
- p_es->p_mpeg4desc = NULL;
- p_es->b_gather = false;
- TAB_APPEND( pid->i_extra_es, pid->extra_es, p_es );
- }
- /* */
- const dvbpsi_subtitle_t *p = &p_sub->p_subtitle[i];
- p_es->fmt.psz_language = strndup( p->i_iso6392_language_code, 3 );
- switch( p->i_subtitling_type )
- {
- case 0x10: /* unspec. */
- case 0x11: /* 4:3 */
- case 0x12: /* 16:9 */
- case 0x13: /* 2.21:1 */
- p_es->fmt.psz_description = strdup( _("DVB subtitles") );
- break;
- case 0x20: /* Hearing impaired unspec. */
- case 0x21: /* h.i. 4:3 */
- case 0x22: /* h.i. 16:9 */
- case 0x23: /* h.i. 2.21:1 */
- p_es->fmt.psz_description = strdup( _("DVB subtitles: hearing impaired") );
- break;
- default:
- break;
- }
- /* Hack, FIXME */
- p_es->fmt.subs.dvb.i_id = ( p->i_composition_page_id << 0 ) |
- ( p->i_ancillary_page_id << 16 );
- }
- #endif
- }
- }
- static void PMTSetupEs0x06( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- es_format_t *p_fmt = &pid->es->fmt;
- if( PMTEsHasRegistration( p_demux, p_es, "AC-3" ) ||
- PMTEsFindDescriptor( p_es, 0x6a ) ||
- PMTEsFindDescriptor( p_es, 0x81 ) )
- {
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC('a','5','2',' ');
- }
- else if( PMTEsFindDescriptor( p_es, 0x7a ) )
- {
- /* DVB with stream_type 0x06 (ETS EN 300 468) */
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' );
- }
- else if( PMTEsHasRegistration( p_demux, p_es, "DTS1" ) ||
- PMTEsHasRegistration( p_demux, p_es, "DTS2" ) ||
- PMTEsHasRegistration( p_demux, p_es, "DTS3" ) ||
- PMTEsFindDescriptor( p_es, 0x73 ) )
- {
- /*registration descriptor(ETSI TS 101 154 Annex F)*/
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC('d','t','s',' ');
- }
- else if( PMTEsHasRegistration( p_demux, p_es, "BSSD" ) )
- {
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->b_packetized = true;
- p_fmt->i_codec = VLC_FOURCC('a','e','s','3');
- }
- else
- {
- /* Subtitle/Teletext/VBI fallbacks */
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x59 );
- #ifdef _DVBPSI_DR_59_H_
- dvbpsi_subtitling_dr_t *p_sub;
- if( p_dr && ( p_sub = dvbpsi_DecodeSubtitlingDr( p_dr ) ) )
- {
- for( int i = 0; i < p_sub->i_subtitles_number; i++ )
- {
- if( p_fmt->i_cat != UNKNOWN_ES )
- break;
- switch( p_sub->p_subtitle[i].i_subtitling_type )
- {
- case 0x01: /* EBU Teletext subtitles */
- case 0x02: /* Associated EBU Teletext */
- case 0x03: /* VBI data */
- PMTSetupEsTeletext( p_demux, pid, p_es );
- break;
- case 0x10: /* DVB Subtitle (normal) with no monitor AR critical */
- case 0x11: /* ... on 4:3 AR monitor */
- case 0x12: /* ... on 16:9 AR monitor */
- case 0x13: /* ... on 2.21:1 AR monitor */
- case 0x14: /* ... for display on a high definition monitor */
- case 0x20: /* DVB Subtitle (impaired) with no monitor AR critical */
- case 0x21: /* ... on 4:3 AR monitor */
- case 0x22: /* ... on 16:9 AR monitor */
- case 0x23: /* ... on 2.21:1 AR monitor */
- case 0x24: /* ... for display on a high definition monitor */
- PMTSetupEsDvbSubtitle( p_demux, pid, p_es );
- break;
- default:
- msg_Err( p_demux, "Unrecognized DVB subtitle type" );
- break;
- }
- }
- }
- #else
- if( p_fmt->i_cat == UNKNOWN_ES && p_dr )
- PMTSetupEsDvbSubtitle( p_demux, pid, p_es );
- #endif
- if( p_fmt->i_cat == UNKNOWN_ES &&
- ( PMTEsFindDescriptor( p_es, 0x45 ) || /* VBI Data descriptor */
- PMTEsFindDescriptor( p_es, 0x46 ) || /* VBI Teletext descriptor */
- PMTEsFindDescriptor( p_es, 0x56 ) ) ) /* EBU Teletext descriptor */
- {
- /* Teletext/VBI */
- PMTSetupEsTeletext( p_demux, pid, p_es );
- }
- }
- #ifdef _DVBPSI_DR_52_H_
- /* FIXME is it usefull ? */
- if( PMTEsFindDescriptor( p_es, 0x52 ) )
- {
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x52 );
- dvbpsi_stream_identifier_dr_t *p_si = dvbpsi_DecodeStreamIdentifierDr( p_dr );
- msg_Dbg( p_demux, " * Stream Component Identifier: %d", p_si->i_component_tag );
- }
- #endif
- }
- static void PMTSetupEs0xEA( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- /* Registration Descriptor */
- if( !PMTEsHasRegistration( p_demux, p_es, "VC-1" ) )
- {
- msg_Err( p_demux, "Registration descriptor not found or invalid" );
- return;
- }
- es_format_t *p_fmt = &pid->es->fmt;
- /* registration descriptor for VC-1 (SMPTE rp227) */
- p_fmt->i_cat = VIDEO_ES;
- p_fmt->i_codec = VLC_FOURCC('W','V','C','1');
- /* XXX With Simple and Main profile the SEQUENCE
- * header is modified: video width and height are
- * inserted just after the start code as 2 int16_t
- * The packetizer will take care of that. */
- }
- static void PMTSetupEs0xD1( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- /* Registration Descriptor */
- if( !PMTEsHasRegistration( p_demux, p_es, "drac" ) )
- {
- msg_Err( p_demux, "Registration descriptor not found or invalid" );
- return;
- }
- es_format_t *p_fmt = &pid->es->fmt;
- /* registration descriptor for Dirac
- * (backwards compatable with VC-2 (SMPTE Sxxxx:2008)) */
- p_fmt->i_cat = VIDEO_ES;
- p_fmt->i_codec = VLC_FOURCC('d','r','a','c');
- }
- static void PMTSetupEs0xA0( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- /* MSCODEC sent by vlc */
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0xa0 );
- if( !p_dr || p_dr->i_length < 10 )
- {
- msg_Warn( p_demux,
- "private MSCODEC (vlc) without bih private descriptor" );
- return;
- }
- es_format_t *p_fmt = &pid->es->fmt;
- p_fmt->i_cat = VIDEO_ES;
- p_fmt->i_codec = VLC_FOURCC( p_dr->p_data[0], p_dr->p_data[1],
- p_dr->p_data[2], p_dr->p_data[3] );
- p_fmt->video.i_width = GetWBE( &p_dr->p_data[4] );
- p_fmt->video.i_height = GetWBE( &p_dr->p_data[6] );
- p_fmt->i_extra = GetWBE( &p_dr->p_data[8] );
- if( p_fmt->i_extra > 0 )
- {
- p_fmt->p_extra = malloc( p_fmt->i_extra );
- if( p_fmt->p_extra )
- memcpy( p_fmt->p_extra, &p_dr->p_data[10],
- __MIN( p_fmt->i_extra, p_dr->i_length - 10 ) );
- else
- p_fmt->i_extra = 0;
- }
- /* For such stream we will gather them ourself and don't launch a
- * packetizer.
- * Yes it's ugly but it's the only way to have DIV3 working */
- p_fmt->b_packetized = true;
- }
- static void PMTSetupEsHDMV( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- es_format_t *p_fmt = &pid->es->fmt;
- /* Blu-Ray mapping */
- switch( p_es->i_type )
- {
- case 0x80:
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC( 'b', 'p', 'c', 'm' );
- break;
- case 0x82:
- case 0x85: /* DTS-HD High resolution audio */
- case 0x86: /* DTS-HD Master audio */
- case 0xA2: /* Secondary DTS audio */
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC( 'd', 't', 's', ' ' );
- break;
- case 0x83: /* TrueHD AC3 */
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC( 't', 'r', 'h', 'd' );
- break;
- case 0x84: /* E-AC3 */
- case 0xA1: /* Secondary E-AC3 */
- p_fmt->i_cat = AUDIO_ES;
- p_fmt->i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' );
- break;
- case 0x90: /* Presentation graphics */
- case 0x91: /* Interactive graphics */
- case 0x92: /* Subtitle */
- default:
- break;
- }
- }
- static void PMTParseEsIso639( demux_t *p_demux, ts_pid_t *pid,
- const dvbpsi_pmt_es_t *p_es )
- {
- /* get language descriptor */
- dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_es, 0x0a );
- if( !p_dr )
- return;
- dvbpsi_iso639_dr_t *p_decoded = dvbpsi_DecodeISO639Dr( p_dr );
- if( !p_decoded )
- {
- msg_Err( p_demux, "Failed to decode a ISO 639 descriptor" );
- return;
- }
- #if defined(DR_0A_API_VER) && (DR_0A_API_VER >= 2)
- pid->es->fmt.psz_language = malloc( 4 );
- if( pid->es->fmt.psz_language )
- {
- memcpy( pid->es->fmt.psz_language,
- p_decoded->code[0].iso_639_code, 3 );
- pid->es->fmt.psz_language[3] = 0;
- msg_Dbg( p_demux, "found language: %s", pid->es->fmt.psz_language);
- }
- switch( p_decoded->code[0].i_audio_type )
- {
- case 0:
- pid->es->fmt.psz_description = NULL;
- break;
- case 1:
- pid->es->fmt.psz_description =
- strdup(_("clean effects"));
- break;
- case 2:
- pid->es->fmt.psz_description =
- strdup(_("hearing impaired"));
- break;
- case 3:
- pid->es->fmt.psz_description =
- strdup(_("visual impaired commentary"));
- break;
- default:
- msg_Dbg( p_demux, "unknown audio type: %d",
- p_decoded->code[0].i_audio_type);
- pid->es->fmt.psz_description = NULL;
- break;
- }
- pid->es->fmt.i_extra_languages = p_decoded->i_code_count-1;
- if( pid->es->fmt.i_extra_languages > 0 )
- pid->es->fmt.p_extra_languages =
- malloc( sizeof(*pid->es->fmt.p_extra_languages) *
- pid->es->fmt.i_extra_languages );
- if( pid->es->fmt.p_extra_languages )
- {
- for( int i = 0; i < pid->es->fmt.i_extra_languages; i++ )
- {
- msg_Dbg( p_demux, "bang" );
- pid->es->fmt.p_extra_languages[i].psz_language =
- malloc(4);
- if( pid->es->fmt.p_extra_languages[i].psz_language )
- {
- memcpy( pid->es->fmt.p_extra_languages[i].psz_language,
- p_decoded->code[i+1].iso_639_code, 3 );
- pid->es->fmt.p_extra_languages[i].psz_language[3] = ' ';
- }
- switch( p_decoded->code[i].i_audio_type )
- {
- case 0:
- pid->es->fmt.p_extra_languages[i].psz_description =
- NULL;
- break;
- case 1:
- pid->es->fmt.p_extra_languages[i].psz_description =
- strdup(_("clean effects"));
- break;
- case 2:
- pid->es->fmt.p_extra_languages[i].psz_description =
- strdup(_("hearing impaired"));
- break;
- case 3:
- pid->es->fmt.p_extra_languages[i].psz_description =
- strdup(_("visual impaired commentary"));
- break;
- default:
- msg_Dbg( p_demux, "unknown audio type: %d",
- p_decoded->code[i].i_audio_type);
- pid->es->fmt.psz_description = NULL;
- break;
- }
- }
- }
- #else
- pid->es->fmt.psz_language = malloc( 4 );
- if( pid->es->fmt.psz_language )
- {
- memcpy( pid->es->fmt.psz_language,
- p_decoded->i_iso_639_code, 3 );
- pid->es->fmt.psz_language[3] = 0;
- }
- #endif
- }
- static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- dvbpsi_descriptor_t *p_dr;
- dvbpsi_pmt_es_t *p_es;
- ts_pid_t *pmt = NULL;
- ts_prg_psi_t *prg = NULL;
- ts_pid_t **pp_clean = NULL;
- int i_clean = 0;
- bool b_hdmv = false;
- msg_Dbg( p_demux, "PMTCallBack called" );
- /* First find this PMT declared in PAT */
- for( int i = 0; i < p_sys->i_pmt; i++ )
- {
- int i_prg;
- for( i_prg = 0; i_prg < p_sys->pmt[i]->psi->i_prg; i_prg++ )
- {
- const int i_pmt_number = p_sys->pmt[i]->psi->prg[i_prg]->i_number;
- if( i_pmt_number != TS_USER_PMT_NUMBER && i_pmt_number == p_pmt->i_program_number )
- {
- pmt = p_sys->pmt[i];
- prg = p_sys->pmt[i]->psi->prg[i_prg];
- break;
- }
- }
- if( pmt )
- break;
- }
- if( pmt == NULL )
- {
- msg_Warn( p_demux, "unreferenced program (broken stream)" );
- dvbpsi_DeletePMT(p_pmt);
- return;
- }
- if( prg->i_version != -1 &&
- ( !p_pmt->b_current_next || prg->i_version == p_pmt->i_version ) )
- {
- dvbpsi_DeletePMT( p_pmt );
- return;
- }
- /* Clean this program (remove all es) */
- for( int i = 0; i < 8192; i++ )
- {
- ts_pid_t *pid = &p_sys->pid[i];
- if( pid->b_valid && pid->p_owner == pmt->psi &&
- pid->i_owner_number == prg->i_number && pid->psi == NULL )
- {
- TAB_APPEND( i_clean, pp_clean, pid );
- }
- }
- if( prg->iod )
- {
- IODFree( prg->iod );
- prg->iod = NULL;
- }
- msg_Dbg( p_demux, "new PMT program number=%d version=%d pid_pcr=%d",
- p_pmt->i_program_number, p_pmt->i_version, p_pmt->i_pcr_pid );
- prg->i_pid_pcr = p_pmt->i_pcr_pid;
- prg->i_version = p_pmt->i_version;
- ValidateDVBMeta( p_demux, prg->i_pid_pcr );
- if( ProgramIsSelected( p_demux, prg->i_number ) )
- {
- /* Set demux filter */
- stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE, prg->i_pid_pcr,
- true );
- }
- else if ( p_sys->b_access_control )
- {
- msg_Warn( p_demux, "skipping program (not selected)" );
- dvbpsi_DeletePMT(p_pmt);
- return;
- }
- /* Parse descriptor */
- for( p_dr = p_pmt->p_first_descriptor; p_dr != NULL; p_dr = p_dr->p_next )
- {
- if( p_dr->i_tag == 0x1d )
- {
- /* We have found an IOD descriptor */
- msg_Dbg( p_demux, " * descriptor : IOD (0x1d)" );
- prg->iod = IODNew( p_dr->i_length, p_dr->p_data );
- }
- else if( p_dr->i_tag == 0x9 )
- {
- uint16_t i_sysid = ((uint16_t)p_dr->p_data[0] << 8)
- | p_dr->p_data[1];
- msg_Dbg( p_demux, " * descriptor : CA (0x9) SysID 0x%x", i_sysid );
- }
- else if( p_dr->i_tag == 0x05 )
- {
- if( p_dr->i_tag == 0x05 )
- {
- /* Registration Descriptor */
- if( p_dr->i_length != 4 )
- {
- msg_Warn( p_demux, "invalid Registration Descriptor" );
- }
- else
- {
- msg_Dbg( p_demux, " * descriptor : registration %4.4s", p_dr->p_data );
- if( !memcmp( p_dr->p_data, "HDMV", 4 ) )
- {
- /* Blu-Ray */
- b_hdmv = true;
- }
- }
- }
- }
- else
- {
- msg_Dbg( p_demux, " * descriptor : unknown (0x%x)", p_dr->i_tag );
- }
- }
- for( p_es = p_pmt->p_first_es; p_es != NULL; p_es = p_es->p_next )
- {
- ts_pid_t tmp_pid, *old_pid = 0, *pid = &tmp_pid;
- /* Find out if the PID was already declared */
- for( int i = 0; i < i_clean; i++ )
- {
- if( pp_clean[i] == &p_sys->pid[p_es->i_pid] )
- {
- old_pid = pp_clean[i];
- break;
- }
- }
- ValidateDVBMeta( p_demux, p_es->i_pid );
- if( !old_pid && p_sys->pid[p_es->i_pid].b_valid )
- {
- msg_Warn( p_demux, "pmt error: pid=%d already defined",
- p_es->i_pid );
- continue;
- }
- for( p_dr = p_es->p_first_descriptor; p_dr != NULL;
- p_dr = p_dr->p_next )
- {
- msg_Dbg( p_demux, " * es pid=%d type=%d dr->i_tag=0x%x",
- p_es->i_pid, p_es->i_type, p_dr->i_tag );
- }
- PIDInit( pid, false, pmt->psi );
- PIDFillFormat( pid, p_es->i_type );
- pid->i_owner_number = prg->i_number;
- pid->i_pid = p_es->i_pid;
- pid->b_seen = p_sys->pid[p_es->i_pid].b_seen;
- if( p_es->i_type == 0x10 || p_es->i_type == 0x11 ||
- p_es->i_type == 0x12 || p_es->i_type == 0x0f )
- {
- PMTSetupEsISO14496( p_demux, pid, prg, p_es );
- }
- else if( p_es->i_type == 0x06 )
- {
- PMTSetupEs0x06( p_demux, pid, p_es );
- }
- else if( p_es->i_type == 0xEA )
- {
- PMTSetupEs0xEA( p_demux, pid, p_es );
- }
- else if( p_es->i_type == 0xd1 )
- {
- PMTSetupEs0xD1( p_demux, pid, p_es );
- }
- else if( p_es->i_type == 0xa0 )
- {
- PMTSetupEs0xA0( p_demux, pid, p_es );
- }
- else if( b_hdmv )
- {
- PMTSetupEsHDMV( p_demux, pid, p_es );
- }
- if( pid->es->fmt.i_cat == AUDIO_ES ||
- ( pid->es->fmt.i_cat == SPU_ES &&
- pid->es->fmt.i_codec != VLC_FOURCC('d','v','b','s') &&
- pid->es->fmt.i_codec != VLC_FOURCC('t','e','l','x') ) )
- {
- PMTParseEsIso639( p_demux, pid, p_es );
- }
- pid->es->fmt.i_group = p_pmt->i_program_number;
- for( int i = 0; i < pid->i_extra_es; i++ )
- pid->extra_es[i]->fmt.i_group = p_pmt->i_program_number;
- if( pid->es->fmt.i_cat == UNKNOWN_ES )
- {
- msg_Dbg( p_demux, " * es pid=%d type=%d *unknown*",
- p_es->i_pid, p_es->i_type );
- }
- else if( !p_sys->b_udp_out )
- {
- msg_Dbg( p_demux, " * es pid=%d type=%d fcc=%4.4s",
- p_es->i_pid, p_es->i_type, (char*)&pid->es->fmt.i_codec );
- if( p_sys->b_es_id_pid ) pid->es->fmt.i_id = p_es->i_pid;
- /* Check if we can avoid restarting the ES */
- if( old_pid &&
- pid->es->fmt.i_codec == old_pid->es->fmt.i_codec &&
- pid->es->fmt.i_extra == old_pid->es->fmt.i_extra &&
- pid->es->fmt.i_extra == 0 &&
- pid->i_extra_es == old_pid->i_extra_es &&
- ( ( !pid->es->fmt.psz_language &&
- !old_pid->es->fmt.psz_language ) ||
- ( pid->es->fmt.psz_language &&
- old_pid->es->fmt.psz_language &&
- !strcmp( pid->es->fmt.psz_language,
- old_pid->es->fmt.psz_language ) ) ) )
- {
- pid->es->id = old_pid->es->id;
- old_pid->es->id = NULL;
- for( int i = 0; i < pid->i_extra_es; i++ )
- {
- pid->extra_es[i]->id = old_pid->extra_es[i]->id;
- old_pid->extra_es[i]->id = NULL;
- }
- }
- else
- {
- if( old_pid )
- {
- PIDClean( p_demux->out, old_pid );
- TAB_REMOVE( i_clean, pp_clean, old_pid );
- old_pid = 0;
- }
- pid->es->id = es_out_Add( p_demux->out, &pid->es->fmt );
- for( int i = 0; i < pid->i_extra_es; i++ )
- {
- pid->extra_es[i]->id =
- es_out_Add( p_demux->out, &pid->extra_es[i]->fmt );
- }
- }
- }
- /* Add ES to the list */
- if( old_pid )
- {
- PIDClean( p_demux->out, old_pid );
- TAB_REMOVE( i_clean, pp_clean, old_pid );
- }
- p_sys->pid[p_es->i_pid] = *pid;
- p_dr = PMTEsFindDescriptor( p_es, 0x09 );
- if( p_dr && p_dr->i_length >= 2 )
- {
- uint16_t i_sysid = (p_dr->p_data[0] << 8) | p_dr->p_data[1];
- msg_Dbg( p_demux, " * descriptor : CA (0x9) SysID 0x%x",
- i_sysid );
- }
- if( ProgramIsSelected( p_demux, prg->i_number ) &&
- ( pid->es->id != NULL || p_sys->b_udp_out ) )
- {
- /* Set demux filter */
- stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE, p_es->i_pid,
- true );
- }
- }
- if( ProgramIsSelected( p_demux, prg->i_number ) )
- {
- /* Set CAM descrambling */
- stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_CA, p_pmt );
- }
- else
- {
- dvbpsi_DeletePMT( p_pmt );
- }
- for( int i = 0; i < i_clean; i++ )
- {
- if( ProgramIsSelected( p_demux, prg->i_number ) )
- {
- stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE, pp_clean[i]->i_pid,
- false );
- }
- PIDClean( p_demux->out, pp_clean[i] );
- }
- if( i_clean )
- free( pp_clean );
- }
- static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat )
- {
- demux_sys_t *p_sys = p_demux->p_sys;
- dvbpsi_pat_program_t *p_program;
- ts_pid_t *pat = &p_sys->pid[0];
- msg_Dbg( p_demux, "PATCallBack called" );
- if( ( pat->psi->i_pat_version != -1 &&
- ( !p_pat->b_current_next ||
- p_pat->i_version == pat->psi->i_pat_version ) ) ||
- p_sys->b_user_pmt )
- {
- dvbpsi_DeletePAT( p_pat );
- return;
- }
- msg_Dbg( p_demux, "new PAT ts_id=%d version=%d current_next=%d",
- p_pat->i_ts_id, p_pat->i_version, p_pat->b_current_next );
- /* Clean old */
- if( p_sys->i_pmt > 0 )
- {
- int i_pmt_rm = 0;
- ts_pid_t **pmt_rm = NULL;
- /* Search pmt to be deleted */
- for( int i = 0; i < p_sys->i_pmt; i++ )
- {
- ts_pid_t *pmt = p_sys->pmt[i];
- bool b_keep = false;
- for( p_program = p_pat->p_first_program; p_program != NULL;
- p_program = p_program->p_next )
- {
- if( p_program->i_pid == pmt->i_pid )
- {
- for( int i_prg = 0; i_prg < pmt->psi->i_prg; i_prg++ )
- {
- if( p_program->i_number ==
- pmt->psi->prg[i_prg]->i_number )
- {
- b_keep = true;
- break;
- }
- }
- if( b_keep )
- break;
- }
- }
- if( !b_keep )
- {
- TAB_APPEND( i_pmt_rm, pmt_rm, pmt );
- }
- }
- /* Delete all ES attached to thoses PMT */
- for( int i = 2; i < 8192; i++ )
- {
- ts_pid_t *pid = &p_sys->pid[i];
- if( !pid->b_valid || pid->psi )
- continue;
- for( int j = 0; j < i_pmt_rm && pid->b_valid; j++ )
- {
- for( int i_prg = 0; i_prg < pid->p_owner->i_prg; i_prg++ )
- {
- /* We only remove es that aren't defined by extra pmt */
- if( pid->p_owner->prg[i_prg]->i_pid_pmt != pmt_rm[j]->i_pid )
- continue;
- if( p_sys->b_access_control && pid->es->id )
- {
- if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE, i,
- false ) )
- p_sys->b_access_control = false;
- }
- PIDClean( p_demux->out, pid );
- break;
- }
- }
- }
- /* Delete PMT pid */
- for( int i = 0; i < i_pmt_rm; i++ )
- {
- if( p_sys->b_access_control )
- {
- if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE,
- pmt_rm[i]->i_pid, false ) )
- p_sys->b_access_control = false;
- }
- for( int i_prg = 0; i_prg < pmt_rm[i]->psi->i_prg; i_prg++ )
- {
- const int i_number = pmt_rm[i]->psi->prg[i_prg]->i_number;
- es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, i_number );
- }
- PIDClean( p_demux->out, &p_sys->pid[pmt_rm[i]->i_pid] );
- TAB_REMOVE( p_sys->i_pmt, p_sys->pmt, pmt_rm[i] );
- }
- free( pmt_rm );
- }
- /* now create programs */
- for( p_program = p_pat->p_first_program; p_program != NULL;
- p_program = p_program->p_next )
- {
- msg_Dbg( p_demux, " * number=%d pid=%d", p_program->i_number,
- p_program->i_pid );
- if( p_program->i_number != 0 )
- {
- ts_pid_t *pmt = &p_sys->pid[p_program->i_pid];
- bool b_add = true;
- ValidateDVBMeta( p_demux, p_program->i_pid );
- if( pmt->b_valid )
- {
- int i_prg;
- for( i_prg = 0; i_prg < pmt->psi->i_prg; i_prg++ )
- {
- if( pmt->psi->prg[i_prg]->i_number == p_program->i_number )
- {
- b_add = false;
- break;
- }
- }
- }
- else
- {
- TAB_APPEND( p_sys->i_pmt, p_sys->pmt, pmt );
- }
- if( b_add )
- {
- PIDInit( pmt, true, pat->psi );
- pmt->psi->prg[pmt->psi->i_prg-1]->handle =
- dvbpsi_AttachPMT( p_program->i_number,
- (dvbpsi_pmt_callback)PMTCallBack,
- p_demux );
- pmt->psi->prg[pmt->psi->i_prg-1]->i_number =
- p_program->i_number;
- pmt->psi->prg[pmt->psi->i_prg-1]->i_pid_pmt =
- p_program->i_pid;
- /* Now select PID at access level */
- if( p_sys->b_access_control )
- {
- if( ProgramIsSelected( p_demux, p_program->i_number ) )
- {
- if( p_sys->i_current_program == 0 )
- p_sys->i_current_program = p_program->i_number;
- if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
- ACCESS_SET_PRIVATE_ID_STATE,
- p_program->i_pid, true ) )
- p_sys->b_access_control = false;
- }
- }
- }
- }
- }
- pat->psi->i_pat_version = p_pat->i_version;
- dvbpsi_DeletePAT( p_pat );
- }