Commit a594a47b authored by François Cartegnie's avatar François Cartegnie 🤞

access: dvb: scan: fix NIT/SDT processing

We can't focuse on both own network and other network
without using our transponder configuration, otherwise
we also end up with zero freq zero everything service for
our network if the nit appears before sdt, and for other
networks if the descriptors order isn't the expected one.

Services are stream_id/network/program
parent 41e4d492
......@@ -214,7 +214,7 @@ static block_t *BlockScan( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
scan_t *p_scan = p_sys->scan;
scan_configuration_t cfg;
scan_tuner_config_t cfg;
/* */
if( scan_Next( p_scan, &cfg ) )
......
......@@ -54,6 +54,11 @@
#include "../../demux/dvb-text.h"
#include "../../mux/mpeg/dvbpsi_compat.h"
#define NIT_CURRENT_NETWORK_TABLE_ID 0x40
#define NIT_OTHER_NETWORK_TABLE_ID 0x41
#define SDT_CURRENT_TS_TABLE_ID 0x42
#define SDT_OTHER_TS_TABLE_ID 0x46
typedef enum
{
SERVICE_UNKNOWN = 0,
......@@ -65,8 +70,9 @@ typedef enum
typedef struct
{
int i_program; /* program number (service id) */
scan_configuration_t cfg;
uint16_t i_ts_id;
uint16_t i_program; /* program number (service id) */
scan_tuner_config_t cfg;
int i_snr;
scan_service_type_t type;
......@@ -75,6 +81,7 @@ typedef struct
bool b_crypted; /* True if potentially crypted */
int i_network_id;
char *psz_network_name;
int i_nit_version;
int i_sdt_version;
......@@ -89,7 +96,7 @@ struct scan_t
scan_parameter_t parameter;
int64_t i_time_start;
int i_service;
size_t i_service;
scan_service_t **pp_service;
scan_list_entry_t *p_scanlist;
......@@ -101,28 +108,40 @@ struct scan_session_t
{
vlc_object_t *p_obj;
scan_configuration_t cfg;
scan_tuner_config_t cfg;
int i_snr;
dvbpsi_t *pat;
dvbpsi_pat_t *p_pat;
int i_nit_pid;
struct
{
dvbpsi_pat_t *p_pat;
dvbpsi_sdt_t *p_sdt;
dvbpsi_nit_t *p_nit;
} local;
struct
{
dvbpsi_sdt_t **pp_sdt;
size_t i_sdt;
dvbpsi_nit_t **pp_nit;
size_t i_nit;
} others;
dvbpsi_t *sdt;
dvbpsi_sdt_t *p_sdt;
uint16_t i_nit_pid;
dvbpsi_t *nit;
dvbpsi_nit_t *p_nit;
dvbpsi_t *p_pathandle;
dvbpsi_t *p_sdthandle;
dvbpsi_t *p_nithandle;
};
/* */
static scan_service_t *scan_service_New( int i_program,
const scan_configuration_t *p_cfg )
static scan_service_t *scan_service_New( uint16_t i_ts_id, uint16_t i_program,
const scan_tuner_config_t *p_cfg )
{
scan_service_t *p_srv = malloc( sizeof(*p_srv) );
if( !p_srv )
return NULL;
p_srv->i_ts_id = i_ts_id;
p_srv->i_program = i_program;
p_srv->cfg = *p_cfg;
p_srv->i_snr = -1;
......@@ -136,11 +155,14 @@ static scan_service_t *scan_service_New( int i_program,
p_srv->i_nit_version = -1;
p_srv->i_sdt_version = -1;
p_srv->psz_network_name = NULL;
return p_srv;
}
static void scan_service_Delete( scan_service_t *p_srv )
{
free( p_srv->psz_network_name );
free( p_srv->psz_name );
free( p_srv );
}
......@@ -272,7 +294,7 @@ void scan_Destroy( scan_t *p_scan )
scan_parameter_Clean( &p_scan->parameter );
for( int i = 0; i < p_scan->i_service; i++ )
for( size_t i = 0; i < p_scan->i_service; i++ )
scan_service_Delete( p_scan->pp_service[i] );
TAB_CLEAN( p_scan->i_service, p_scan->pp_service );
......@@ -281,7 +303,7 @@ void scan_Destroy( scan_t *p_scan )
free( p_scan );
}
static int ScanDvbv5NextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbv5NextFast( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
if( !p_scan->p_current )
return VLC_EGENERIC;
......@@ -315,14 +337,14 @@ static int ScanDvbv5NextFast( scan_t *p_scan, scan_configuration_t *p_cfg, doubl
return VLC_SUCCESS;
}
static int ScanDvbSNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbSNextFast( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
const scan_list_entry_t *p_entry = p_scan->p_current;
if( !p_entry )
return VLC_EGENERIC;
/* setup params for scan */
p_cfg->i_symbol_rate = p_entry->i_rate / 1000;
p_cfg->i_symbolrate = p_entry->i_rate / 1000;
p_cfg->i_frequency = p_entry->i_freq;
p_cfg->i_fec = p_entry->i_fec;
p_cfg->c_polarization = ( p_entry->polarization == POLARIZATION_HORIZONTAL ) ? 'H' : 'V';
......@@ -332,7 +354,7 @@ static int ScanDvbSNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double
p_scan->i_index + 1,
p_scan->i_scanlist,
p_cfg->i_frequency,
p_cfg->i_symbol_rate,
p_cfg->i_symbolrate,
p_cfg->i_fec,
p_cfg->c_polarization );
......@@ -343,7 +365,7 @@ static int ScanDvbSNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double
return VLC_SUCCESS;
}
static int ScanDvbCNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbCNextFast( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
msg_Dbg( p_scan->p_obj, "Scan index %"PRId64, p_scan->i_index );
/* Values taken from dvb-scan utils frequency-files, sorted by how
......@@ -381,7 +403,7 @@ static int ScanDvbCNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double
return VLC_EGENERIC;
}
static int ScanDvbNextExhaustive( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbNextExhaustive( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
if( p_scan->i_index > p_scan->parameter.frequency.i_count * p_scan->parameter.bandwidth.i_count )
return VLC_EGENERIC;
......@@ -396,7 +418,7 @@ static int ScanDvbNextExhaustive( scan_t *p_scan, scan_configuration_t *p_cfg, d
return VLC_SUCCESS;
}
static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbTNextFast( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
static const int i_band_count = 2;
static const struct
......@@ -468,7 +490,7 @@ static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double
}
}
static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbCNext( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
bool b_servicefound = false;
/* We iterate frequencies/modulations/symbolrates until we get first hit and find NIT,
......@@ -476,7 +498,7 @@ static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf
pp_services for all that doesn't have name yet (tune to that cfg and get SDT and name
for channel).
*/
for( int i = 0; i < p_scan->i_service; i++ )
for( size_t i = 0; i < p_scan->i_service; i++ )
{
/* We found radio/tv config that doesn't have a name,
lets tune to that mux
......@@ -488,7 +510,7 @@ static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf
p_cfg->i_modulation = p_scan->pp_service[i]->cfg.i_modulation;
p_scan->i_index = i+1;
msg_Dbg( p_scan->p_obj, "iterating to freq: %u, symbolrate %u, "
"modulation %u index %"PRId64"/%d",
"modulation %u index %"PRId64"/%ld",
p_cfg->i_frequency, p_cfg->i_symbolrate, p_cfg->i_modulation, p_scan->i_index, p_scan->i_service );
*pf_pos = (double)i/p_scan->i_service;
return VLC_SUCCESS;
......@@ -552,7 +574,7 @@ static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf
return ScanDvbCNextFast( p_scan, p_cfg, pf_pos );
}
static int ScanDvbTNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbTNext( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
if( p_scan->parameter.b_exhaustive )
return ScanDvbNextExhaustive( p_scan, p_cfg, pf_pos );
......@@ -562,7 +584,7 @@ static int ScanDvbTNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf
return ScanDvbTNextFast( p_scan, p_cfg, pf_pos );
}
static int ScanDvbSNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
static int ScanDvbSNext( scan_t *p_scan, scan_tuner_config_t *p_cfg, double *pf_pos )
{
if( p_scan->parameter.b_exhaustive )
msg_Dbg( p_scan->p_obj, "no exhaustive svb-d scan mode" );
......@@ -570,7 +592,7 @@ static int ScanDvbSNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf
return ScanDvbSNextFast( p_scan, p_cfg, pf_pos );
}
int scan_Next( scan_t *p_scan, scan_configuration_t *p_cfg )
int scan_Next( scan_t *p_scan, scan_tuner_config_t *p_cfg )
{
double f_position;
int i_ret;
......@@ -600,7 +622,7 @@ int scan_Next( scan_t *p_scan, scan_configuration_t *p_cfg )
int i_service = 0;
for( int i = 0; i < p_scan->i_service; i++ )
for( size_t i = 0; i < p_scan->i_service; i++ )
{
if( p_scan->pp_service[i]->psz_name )
i_service++;
......@@ -643,30 +665,81 @@ bool scan_IsCancelled( scan_t *p_scan )
return vlc_dialog_is_cancelled( p_scan->p_obj, p_scan->p_dialog_id );
}
static scan_service_t *ScanFindService( scan_t *p_scan, int i_service_start, int i_program )
static scan_service_t *ScanFindService( scan_t *p_scan, size_t i_service_start,
uint16_t i_program, uint16_t i_ts_id )
{
for( int i = i_service_start; i < p_scan->i_service; i++ )
for( size_t i = i_service_start; i < p_scan->i_service; i++ )
{
if( p_scan->pp_service[i]->i_program == i_program )
if( p_scan->pp_service[i]->i_program == i_program &&
p_scan->pp_service[i]->i_ts_id == i_ts_id )
return p_scan->pp_service[i];
}
return NULL;
}
static bool GetOtherNetworkNIT( scan_session_t *p_session, uint16_t i_network_id,
dvbpsi_nit_t ***ppp_nit )
{
for( size_t i=0; i<p_session->others.i_nit; i++ )
{
if( p_session->others.pp_nit[i]->i_network_id == i_network_id )
{
*ppp_nit = &p_session->others.pp_nit[i];
return true;
}
}
return false;
}
static bool GetOtherTsSDT( scan_session_t *p_session, uint16_t i_ts_id,
dvbpsi_sdt_t ***ppp_sdt )
{
for( size_t i=0; i<p_session->others.i_sdt; i++ )
{
if( p_session->others.pp_sdt[i]->i_extension == i_ts_id )
{
*ppp_sdt = &p_session->others.pp_sdt[i];
return true;
}
}
return false;
}
static void ParsePAT( vlc_object_t *p_obj, scan_t *p_scan,
const dvbpsi_pat_t *p_pat, const scan_tuner_config_t *p_cfg )
{
VLC_UNUSED(p_obj);
const dvbpsi_pat_program_t *p_program;
for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
{
if( p_program->i_number == 0 ) /* NIT */
continue;
/* PAT must not create new service without proper config ( local ) */
scan_service_t *s = ScanFindService( p_scan, 0, p_program->i_number, p_pat->i_ts_id );
if( s == NULL && p_cfg )
{
s = scan_service_New( p_pat->i_ts_id, p_program->i_number, p_cfg );
if( likely(s) )
TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
}
}
}
/* FIXME handle properly string (convert to utf8) */
static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
{
vlc_object_t *p_obj = p_session->p_obj;
msg_Dbg( p_obj, "PATCallBack" );
/* */
if( p_session->p_pat && p_session->p_pat->b_current_next )
if( p_session->local.p_pat && p_session->local.p_pat->b_current_next )
{
dvbpsi_pat_delete( p_session->p_pat );
p_session->p_pat = NULL;
dvbpsi_pat_delete( p_session->local.p_pat );
p_session->local.p_pat = NULL;
}
if( p_session->p_pat )
if( p_session->local.p_pat )
{
dvbpsi_pat_delete( p_pat );
return;
......@@ -675,7 +748,7 @@ static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
dvbpsi_pat_program_t *p_program;
/* */
p_session->p_pat = p_pat;
p_session->local.p_pat = p_pat;
/* */
msg_Dbg( p_obj, "new PAT ts_id=%d version=%d current_next=%d",
......@@ -687,33 +760,93 @@ static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
p_session->i_nit_pid = p_program->i_pid;
}
}
static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
static void ParseSDT( vlc_object_t *p_obj, scan_t *p_scan,
const dvbpsi_sdt_t *p_sdt, const scan_tuner_config_t *p_cfg )
{
vlc_object_t *p_obj = p_session->p_obj;
VLC_UNUSED(p_obj);
for( const dvbpsi_sdt_service_t *p_srv = p_sdt->p_first_service;
p_srv; p_srv = p_srv->p_next )
{
scan_service_t *s = ScanFindService( p_scan, 0, p_srv->i_service_id, p_sdt->i_extension );
if( s == NULL )
{
/* SDT must not create new service without proper config ( local )
or it must has been created by another network NIT (providing freq) */
if( p_cfg )
s = scan_service_New( p_sdt->i_extension, p_srv->i_service_id, p_cfg );
if( s == NULL )
continue;
TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
}
s->b_crypted = p_srv->b_free_ca;
for( dvbpsi_descriptor_t *p_dr = p_srv->p_first_descriptor;
p_dr; p_dr = p_dr->p_next )
{
if( p_dr->i_tag != 0x48 )
continue;
dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
if( pD )
{
if( !s->psz_name )
s->psz_name = vlc_from_EIT( pD->i_service_name,
pD->i_service_name_length );
msg_Dbg( p_obj, "SDTCallBack" );
if( s->type == SERVICE_UNKNOWN )
s->type = scan_service_type( pD->i_service_type );
}
}
}
}
if( p_session->p_sdt && p_session->p_sdt->b_current_next )
static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
{
vlc_object_t *p_obj = p_session->p_obj;
dvbpsi_sdt_t **pp_stored_sdt = NULL;
if( p_sdt->i_table_id == SDT_OTHER_TS_TABLE_ID )
{
dvbpsi_sdt_delete( p_session->p_sdt );
p_session->p_sdt = NULL;
if( !GetOtherTsSDT( p_session, p_sdt->i_extension, &pp_stored_sdt ) )
{
dvbpsi_sdt_t **pp_realloc = realloc( p_session->others.pp_sdt,
(p_session->others.i_sdt + 1) * sizeof( *pp_realloc ) );
if( !pp_realloc ) /* oom */
{
dvbpsi_sdt_delete( p_sdt );
return;
}
pp_stored_sdt = &pp_realloc[p_session->others.i_sdt];
p_session->others.pp_sdt = pp_realloc;
p_session->others.i_sdt++;
}
}
if( p_session->p_sdt )
else /* SDT_CURRENT_TS_TABLE_ID */
{
dvbpsi_sdt_delete( p_sdt );
return;
pp_stored_sdt = &p_session->local.p_sdt;
}
/* */
p_session->p_sdt = p_sdt;
/* Store, replace, or discard */
if( *pp_stored_sdt )
{
if( (*pp_stored_sdt)->i_version == p_sdt->i_version ||
(*pp_stored_sdt)->b_current_next > p_sdt->b_current_next )
{
/* Duplicate or stored one isn't current */
dvbpsi_sdt_delete( p_sdt );
return;
}
dvbpsi_sdt_delete( *pp_stored_sdt );
}
*pp_stored_sdt = p_sdt;
/* */
msg_Dbg( p_obj, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
p_sdt->i_extension,
p_sdt->i_version, p_sdt->b_current_next,
msg_Dbg( p_obj, "new SDT %s ts_id=%d version=%d current_next=%d network_id=%d",
( p_sdt->i_table_id == SDT_CURRENT_TS_TABLE_ID ) ? "local" : "other",
p_sdt->i_extension, p_sdt->i_version, p_sdt->b_current_next,
p_sdt->i_network_id );
dvbpsi_sdt_service_t *p_srv;
for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
{
......@@ -747,97 +880,31 @@ static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
}
}
static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
static void ParseNIT( vlc_object_t *p_obj, scan_t *p_scan,
const dvbpsi_nit_t *p_nit, const scan_tuner_config_t *p_cfg )
{
vlc_object_t *p_obj = p_session->p_obj;
access_t *p_access = (access_t*)p_obj;
access_sys_t *p_sys = p_access->p_sys;
scan_t *p_scan = p_sys->scan;
msg_Dbg( p_obj, "NITCallBack" );
msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next );
/* */
if( p_session->p_nit && p_session->p_nit->b_current_next )
{
dvbpsi_nit_delete( p_session->p_nit );
p_session->p_nit = NULL;
}
if( p_session->p_nit )
{
dvbpsi_nit_delete( p_nit );
return;
}
/* */
p_session->p_nit = p_nit;
dvbpsi_descriptor_t *p_dsc;
for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
{
if( p_dsc->i_tag == 0x40 && p_dsc->i_length > 0 )
{
msg_Dbg( p_obj, " * network name descriptor" );
char str1[257];
memcpy( str1, p_dsc->p_data, p_dsc->i_length );
str1[p_dsc->i_length] = '\0';
msg_Dbg( p_obj, " * name %s", str1 );
}
else if( p_dsc->i_tag == 0x4a )
{
dvbpsi_linkage_dr_t *p_l = dvbpsi_DecodeLinkageDr( p_dsc );
if( p_l )
{
msg_Dbg( p_obj, " * linkage descriptor" );
msg_Dbg( p_obj, " * ts_id %" PRIu16, p_l->i_transport_stream_id );
msg_Dbg( p_obj, " * on_id %" PRIu16, p_l->i_original_network_id );
msg_Dbg( p_obj, " * service_id %" PRIu16, p_l->i_service_id );
msg_Dbg( p_obj, " * linkage_type %" PRIu8, p_l->i_linkage_type );
}
}
else
{
msg_Dbg( p_obj, " * dsc 0x%x", p_dsc->i_tag );
}
}
dvbpsi_nit_ts_t *p_ts;
for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
for( const dvbpsi_nit_ts_t *p_ts = p_nit->p_first_ts;
p_ts != NULL; p_ts = p_ts->p_next )
{
msg_Dbg( p_obj, " * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id );
uint32_t i_private_data_id = 0;
dvbpsi_descriptor_t *p_dsc;
scan_configuration_t cfg = { 0 };
scan_tuner_config_t tscfg = { 0 };
if( p_cfg != NULL ) // p_nit->i_table_id != NIT_CURRENT_NETWORK_TABLE_ID
tscfg = *p_cfg;
dvbpsi_service_list_dr_t *p_sl = NULL;
dvbpsi_lcn_dr_t *p_lc = NULL;
dvbpsi_descriptor_t *p_nn = NULL;
for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
{
if( p_dsc->i_tag == 0x41 )
{
dvbpsi_service_list_dr_t *p_sl = dvbpsi_DecodeServiceListDr( p_dsc );
msg_Dbg( p_obj, " * service list descriptor" );
for( uint8_t i = 0; p_sl && i < p_sl->i_service_count; i++ )
{
const uint16_t i_service_id = p_sl->i_service[i].i_service_id;
const uint8_t i_service_type = p_sl->i_service[i].i_service_type;
msg_Dbg( p_obj, " * service_id=%" PRIu16 " type=%" PRIu8,
i_service_id, i_service_type );
if( (ScanFindService( p_scan, 0, i_service_id ) == NULL) &&
scan_service_type( i_service_type ) != SERVICE_UNKNOWN )
{
scan_service_t *s = scan_service_New( i_service_id, &cfg );
if( likely(s) )
{
s->type = scan_service_type( i_service_type );
s->i_network_id = p_nit->i_network_id;
s->i_nit_version = p_nit->i_version;
TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
}
}
}
/* Store it and process it after signal config
* (required for NIT describing other networks) */
p_sl = dvbpsi_DecodeServiceListDr( p_dsc );
}
else if( p_dsc->i_tag == 0x5a )
{
......@@ -860,14 +927,13 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
dvbpsi_cable_deliv_sys_dr_t *p_t = dvbpsi_DecodeCableDelivSysDr( p_dsc );
if( p_t )
{
tscfg.i_frequency = decode_BCD( p_t->i_frequency ) * 100;
tscfg.i_symbolrate = decode_BCD( p_t->i_symbol_rate ) * 100;
tscfg.i_modulation = (8 << p_t->i_modulation);
msg_Dbg( p_obj, " * Cable delivery system");
cfg.i_frequency = decode_BCD( p_t->i_frequency ) * 100;
msg_Dbg( p_obj, " * frequency %d", cfg.i_frequency );
cfg.i_symbolrate = decode_BCD( p_t->i_symbol_rate ) * 100;
msg_Dbg( p_obj, " * symbolrate %u", cfg.i_symbolrate );
cfg.i_modulation = (8 << p_t->i_modulation);
msg_Dbg( p_obj, " * modulation %u", cfg.i_modulation );
msg_Dbg( p_obj, " * frequency %d", tscfg.i_frequency );
msg_Dbg( p_obj, " * symbolrate %u", tscfg.i_symbolrate );
msg_Dbg( p_obj, " * modulation %u", tscfg.i_modulation );
}
}
else if( p_dsc->i_tag == 0x5f )
......@@ -879,36 +945,162 @@ static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
{
msg_Dbg( p_obj, " * logical channel descriptor (EICTA)" );
dvbpsi_lcn_dr_t *p_lc = dvbpsi_DecodeLCNDr( p_dsc );
for( int i = 0; p_lc && i < p_lc->i_number_of_entries; i++ )
p_lc = dvbpsi_DecodeLCNDr( p_dsc );
}
else if( p_dsc->i_tag == 0x40 && p_dsc->i_length > 0 ) /* Network Name */
{
p_nn = p_dsc;
}
else
{
msg_Warn( p_obj, " * dsc 0x%x", p_dsc->i_tag );
}
}
/* Now process service list, and create them if tuner config is known */
if( p_sl )
{
msg_Dbg( p_obj, " * service list descriptor" );
for( uint8_t i = 0; p_sl && i < p_sl->i_service_count; i++ )
{
const uint16_t i_service_id = p_sl->i_service[i].i_service_id;
const uint8_t i_service_type = p_sl->i_service[i].i_service_type;
msg_Dbg( p_obj, " * service_id=%" PRIu16 " type=%" PRIu8,
i_service_id, i_service_type );
if( p_cfg->i_frequency == 0 )
{
const uint16_t i_service_id = p_lc->p_entries[i].i_service_id;
const uint16_t i_channel_number = p_lc->p_entries[i].i_logical_channel_number;
msg_Dbg( p_obj, " * service_id=%" PRIu16 " channel_number=%" PRIu16,
i_service_id, i_channel_number );
scan_service_t *s = ScanFindService( p_scan, 0, i_service_id );
if( s && s->i_channel < 0 ) s->i_channel = i_channel_number;
msg_Warn( p_obj, "cannot create service_id=%" PRIu16 " ts_id=%" PRIu16 " (no config)",
i_service_id, p_ts->i_ts_id );
continue;
}
if( scan_service_type( i_service_type ) == SERVICE_UNKNOWN )
continue;
scan_service_t *s = ScanFindService( p_scan, 0, i_service_id, p_ts->i_ts_id );
if( s == NULL )
{
s = scan_service_New( p_ts->i_ts_id, i_service_id, &tscfg );
if( likely(s) )
{
s->type = scan_service_type( i_service_type );
s->i_network_id = p_nit->i_network_id;
s->i_nit_version = p_nit->i_version;
TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
}
}
if ( s && s->psz_network_name == NULL && p_nn )
s->psz_network_name = strndup( (const char*) p_nn->p_data, p_dsc->i_length );