diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-04-01 13:07:50 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-04-01 13:07:50 +0200 |
commit | 09430fc4ffa8dfb3ba73163d848e066fab74136f (patch) | |
tree | 702d94874685c34f1a3582e0e4f58478c6c9a59c /src | |
parent | 665989a46f97a90c1c601514caeaf0f079da0275 (diff) | |
download | dabmux-09430fc4ffa8dfb3ba73163d848e066fab74136f.tar.gz dabmux-09430fc4ffa8dfb3ba73163d848e066fab74136f.tar.bz2 dabmux-09430fc4ffa8dfb3ba73163d848e066fab74136f.zip |
Remove old carousel
Diffstat (limited to 'src')
-rw-r--r-- | src/DabMultiplexer.cpp | 1094 | ||||
-rw-r--r-- | src/DabMultiplexer.h | 397 | ||||
-rw-r--r-- | src/MuxElements.h | 14 | ||||
-rw-r--r-- | src/fig/FIG0.cpp | 2 | ||||
-rw-r--r-- | src/fig/FIG0.h | 305 | ||||
-rw-r--r-- | src/fig/FIG1.cpp | 1 | ||||
-rw-r--r-- | src/fig/FIG1.h | 72 |
7 files changed, 393 insertions, 1492 deletions
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index 8002fe1..a557db0 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -31,14 +31,6 @@ using namespace std; -static const unsigned char Padding_FIB[] = { - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - // Protection levels and bitrates for UEP. const unsigned char ProtectionLevelTable[64] = { 4, 3, 2, 1, 0, @@ -84,8 +76,6 @@ DabMultiplexer::DabMultiplexer( MNSC_increment_time(false), sync(0x49C5F8), currentFrame(0), - insertFIG(0), - rotateFIB(0), ensemble(std::make_shared<dabEnsemble>()), fig_carousel(ensemble) { @@ -166,7 +156,6 @@ void DabMultiplexer::set_edi_config(const edi_configuration_t& new_edi_conf) void DabMultiplexer::prepare() { parse_ptree(m_pt, ensemble, m_rc); - m_use_new_fig_carousel = m_pt.get("general.new_fig_carousel", true); this->enrol_at(m_rc); ensemble->enrol_at(m_rc); @@ -189,23 +178,6 @@ void DabMultiplexer::prepare() throw MuxInitException(); } - /* These iterators are used to fill the respective FIG. - * It is necessary to cycle through all the FIGs that have - * to be transmitted because they do not fit in a single - * FIB. - * - * ETSI EN 300 799 Clauses 5.2 and 8.1 - */ - serviceProgFIG0_2 = ensemble->services.end(); - serviceDataFIG0_2 = ensemble->services.end(); - componentProgFIG0_8 = ensemble->components.end(); - componentDataFIG0_8 = ensemble->components.end(); - componentFIG0_13 = ensemble->components.end(); - transmitFIG0_13programme = false; - serviceFIG0_17 = ensemble->services.end(); - subchannelFIG0_1 = ensemble->subchannels.end(); - - /* TODO: * In a SFN, when reconfiguring the ensemble, the multiplexer * has to be restarted (odr-dabmux doesn't support reconfiguration). @@ -425,7 +397,6 @@ void DabMultiplexer::prepare_data_inputs() /* Each call creates one ETI frame */ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs) { - int cur; time_t date; unsigned char etiFrame[6144]; unsigned short index = 0; @@ -622,1061 +593,10 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs edi_tagDETI.fic_data = &etiFrame[index]; edi_tagDETI.fic_length = FICL * 4; - // FIC Insertion - FIGtype0* fig0; - FIGtype0_0 *fig0_0; - FIGtype0_1 *figtype0_1; - - FIG_01_SubChannel_ShortF *fig0_1subchShort; - FIG_01_SubChannel_LongF *fig0_1subchLong1; - - FIGtype0_2 *fig0_2; - - FIGtype0_2_Service *fig0_2serviceAudio; - FIGtype0_2_Service_data *fig0_2serviceData; - FIGtype0_2_audio_component* audio_description; - FIGtype0_2_data_component* data_description; - FIGtype0_2_packet_component* packet_description; - - FIGtype0_3_header *fig0_3_header; - FIGtype0_3_data *fig0_3_data; - FIGtype0_9 *fig0_9; - FIGtype0_10 *fig0_10; - FIGtype0_17_programme *programme; - - FIGtype1_0 *fig1_0; - FIGtype1_1 *fig1_1; - FIGtype1_5 *fig1_5; - - tm* timeData; - // Insert all FIBs - if (m_use_new_fig_carousel) { - fig_carousel.update(currentFrame, date); - const bool fib3_present = ensemble->mode == 3; - index += fig_carousel.write_fibs(&etiFrame[index], currentFrame % 4, fib3_present); - } - else { - unsigned char figSize = 0; - // FIB 0 Insertion - switch (insertFIG) { - - case 0: - case 4: - case 8: - case 12: - // FIG type 0/0, Multiplex Configuration Info (MCI), - // Ensemble information - fig0_0 = (FIGtype0_0 *) & etiFrame[index]; - - fig0_0->FIGtypeNumber = 0; - fig0_0->Length = 5; - fig0_0->CN = 0; - fig0_0->OE = 0; - fig0_0->PD = 0; - fig0_0->Extension = 0; - - fig0_0->EId = htons(ensemble->id); - fig0_0->Change = 0; - fig0_0->Al = 0; - fig0_0->CIFcnt_hight = (currentFrame / 250) % 20; - fig0_0->CIFcnt_low = (currentFrame % 250); - index = index + 6; - figSize += 6; - - break; - - case 1: - case 6: - case 10: - case 13: - // FIG type 0/1, MIC, Sub-Channel Organization, - // one instance of the part for each subchannel - figtype0_1 = (FIGtype0_1 *) & etiFrame[index]; - - figtype0_1->FIGtypeNumber = 0; - figtype0_1->Length = 1; - figtype0_1->CN = 0; - figtype0_1->OE = 0; - figtype0_1->PD = 0; - figtype0_1->Extension = 1; - index = index + 2; - figSize += 2; - - // Rotate through the subchannels until there is no more - // space in the FIG0/1 - if (subchannelFIG0_1 == ensemble->subchannels.end()) { - subchannelFIG0_1 = ensemble->subchannels.begin(); - } - - for (; subchannelFIG0_1 != ensemble->subchannels.end(); - ++subchannelFIG0_1) { - dabProtection* protection = &(*subchannelFIG0_1)->protection; - - if ( (protection->form == UEP && figSize > 27) || - (protection->form == EEP && figSize > 26) ) { - break; - } - - if (protection->form == UEP) { - fig0_1subchShort = - (FIG_01_SubChannel_ShortF*) &etiFrame[index]; - fig0_1subchShort->SubChId = (*subchannelFIG0_1)->id; - - fig0_1subchShort->StartAdress_high = - (*subchannelFIG0_1)->startAddress / 256; - fig0_1subchShort->StartAdress_low = - (*subchannelFIG0_1)->startAddress % 256; - - fig0_1subchShort->Short_Long_form = 0; - fig0_1subchShort->TableSwitch = 0; - fig0_1subchShort->TableIndex = - protection->uep.tableIndex; - - index = index + 3; - figSize += 3; - figtype0_1->Length += 3; - } - else if (protection->form == EEP) { - fig0_1subchLong1 = - (FIG_01_SubChannel_LongF*) &etiFrame[index]; - fig0_1subchLong1->SubChId = (*subchannelFIG0_1)->id; - - fig0_1subchLong1->StartAdress_high = - (*subchannelFIG0_1)->startAddress / 256; - fig0_1subchLong1->StartAdress_low = - (*subchannelFIG0_1)->startAddress % 256; - - fig0_1subchLong1->Short_Long_form = 1; - fig0_1subchLong1->Option = protection->eep.GetOption(); - fig0_1subchLong1->ProtectionLevel = - protection->level; - - fig0_1subchLong1->Sub_ChannelSize_high = - getSizeCu(*subchannelFIG0_1) / 256; - fig0_1subchLong1->Sub_ChannelSize_low = - getSizeCu(*subchannelFIG0_1) % 256; - - index = index + 4; - figSize += 4; - figtype0_1->Length += 4; - } - } - break; - - case 2: - case 9: - case 11: - case 14: - // FIG type 0/2, MCI, Service Organization, one instance of - // FIGtype0_2_Service for each subchannel - fig0_2 = NULL; - cur = 0; - - // Rotate through the subchannels until there is no more - // space in the FIG0/1 - if (serviceProgFIG0_2 == ensemble->services.end()) { - serviceProgFIG0_2 = ensemble->services.begin(); - } - - for (; serviceProgFIG0_2 != ensemble->services.end(); - ++serviceProgFIG0_2) { - if (!(*serviceProgFIG0_2)->nbComponent(ensemble->components)) { - continue; - } - - if ((*serviceProgFIG0_2)->getType(ensemble) != subchannel_type_t::Audio) { - continue; - } - - ++cur; - - if (fig0_2 == NULL) { - fig0_2 = (FIGtype0_2 *) & etiFrame[index]; - - fig0_2->FIGtypeNumber = 0; - fig0_2->Length = 1; - fig0_2->CN = 0; - fig0_2->OE = 0; - fig0_2->PD = 0; - fig0_2->Extension = 2; - index = index + 2; - figSize += 2; - } - - if (figSize + 3 - + (*serviceProgFIG0_2)->nbComponent(ensemble->components) - * 2 > 30) { - break; - } - - fig0_2serviceAudio = (FIGtype0_2_Service*) &etiFrame[index]; - - fig0_2serviceAudio->SId = htons((*serviceProgFIG0_2)->id); - fig0_2serviceAudio->Local_flag = 0; - fig0_2serviceAudio->CAId = 0; - fig0_2serviceAudio->NbServiceComp = - (*serviceProgFIG0_2)->nbComponent(ensemble->components); - index += 3; - fig0_2->Length += 3; - figSize += 3; - - int curCpnt = 0; - for (component = getComponent(ensemble->components, - (*serviceProgFIG0_2)->id); - component != ensemble->components.end(); - component = getComponent(ensemble->components, - (*serviceProgFIG0_2)->id, component)) { - subchannel = getSubchannel(ensemble->subchannels, - (*component)->subchId); - - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*component)->subchId, (*component)->serviceId); - throw MuxInitException(); - } - - switch ((*subchannel)->type) { - case subchannel_type_t::Audio: - audio_description = - (FIGtype0_2_audio_component*)&etiFrame[index]; - audio_description->TMid = 0; - audio_description->ASCTy = (*component)->type; - audio_description->SubChId = (*subchannel)->id; - audio_description->PS = ((curCpnt == 0) ? 1 : 0); - audio_description->CA_flag = 0; - break; - case subchannel_type_t::DataDmb: - data_description = - (FIGtype0_2_data_component*)&etiFrame[index]; - data_description->TMid = 1; - data_description->DSCTy = (*component)->type; - data_description->SubChId = (*subchannel)->id; - data_description->PS = ((curCpnt == 0) ? 1 : 0); - data_description->CA_flag = 0; - break; - case subchannel_type_t::Packet: - packet_description = - (FIGtype0_2_packet_component*)&etiFrame[index]; - packet_description->TMid = 3; - packet_description->setSCId((*component)->packet.id); - packet_description->PS = ((curCpnt == 0) ? 1 : 0); - packet_description->CA_flag = 0; - break; - default: - etiLog.log(error, - "Component type not supported\n"); - throw MuxInitException(); - } - index += 2; - fig0_2->Length += 2; - figSize += 2; - if (figSize > 30) { - etiLog.log(error, - "Sorry, no space left in FIG 0/2 to insert " - "component %i of program service %i.\n", - curCpnt, cur); - throw MuxInitException(); - } - ++curCpnt; - } - } - break; - - case 3: - fig0_2 = NULL; - cur = 0; - - if (serviceDataFIG0_2 == ensemble->services.end()) { - serviceDataFIG0_2 = ensemble->services.begin(); - } - for (; serviceDataFIG0_2 != ensemble->services.end(); - ++serviceDataFIG0_2) { - if (!(*serviceDataFIG0_2)->nbComponent(ensemble->components)) { - continue; - } - - auto type = (*serviceDataFIG0_2)->getType(ensemble); - if ( type == subchannel_type_t::Audio || - type == subchannel_type_t::Fidc ) { - continue; - } - - ++cur; - - if (fig0_2 == NULL) { - fig0_2 = (FIGtype0_2 *) & etiFrame[index]; - - fig0_2->FIGtypeNumber = 0; - fig0_2->Length = 1; - fig0_2->CN = 0; - fig0_2->OE = 0; - fig0_2->PD = 1; - fig0_2->Extension = 2; - index = index + 2; - figSize += 2; - } - - if (figSize + 5 - + (*serviceDataFIG0_2)->nbComponent(ensemble->components) - * 2 > 30) { - break; - } - - fig0_2serviceData = - (FIGtype0_2_Service_data*) &etiFrame[index]; - - fig0_2serviceData->SId = htonl((*serviceDataFIG0_2)->id); - fig0_2serviceData->Local_flag = 0; - fig0_2serviceData->CAId = 0; - fig0_2serviceData->NbServiceComp = - (*serviceDataFIG0_2)->nbComponent(ensemble->components); - fig0_2->Length += 5; - index += 5; - figSize += 5; - - int curCpnt = 0; - for (component = getComponent(ensemble->components, - (*serviceDataFIG0_2)->id); - component != ensemble->components.end(); - component = getComponent(ensemble->components, - (*serviceDataFIG0_2)->id, component)) { - subchannel = getSubchannel(ensemble->subchannels, - (*component)->subchId); - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*component)->subchId, (*component)->serviceId); - throw MuxInitException(); - } - - switch ((*subchannel)->type) { - case subchannel_type_t::Audio: - audio_description = - (FIGtype0_2_audio_component*)&etiFrame[index]; - audio_description->TMid = 0; - audio_description->ASCTy = (*component)->type; - audio_description->SubChId = (*subchannel)->id; - audio_description->PS = ((curCpnt == 0) ? 1 : 0); - audio_description->CA_flag = 0; - break; - case subchannel_type_t::DataDmb: - data_description = - (FIGtype0_2_data_component*)&etiFrame[index]; - data_description->TMid = 1; - data_description->DSCTy = (*component)->type; - data_description->SubChId = (*subchannel)->id; - data_description->PS = ((curCpnt == 0) ? 1 : 0); - data_description->CA_flag = 0; - break; - case subchannel_type_t::Packet: - packet_description = - (FIGtype0_2_packet_component*)&etiFrame[index]; - packet_description->TMid = 3; - packet_description->setSCId((*component)->packet.id); - packet_description->PS = ((curCpnt == 0) ? 1 : 0); - packet_description->CA_flag = 0; - break; - default: - etiLog.log(error, - "Component type not supported\n"); - throw MuxInitException(); - } - index += 2; - fig0_2->Length += 2; - figSize += 2; - if (figSize > 30) { - etiLog.log(error, - "Sorry, no place left in FIG 0/2 to insert " - "component %i of data service %i.\n", - curCpnt, cur); - throw MuxInitException(); - } - ++curCpnt; - } - } - break; - - case 5: - fig0_3_header = NULL; - - for (component = ensemble->components.begin(); - component != ensemble->components.end(); - ++component) { - subchannel = getSubchannel(ensemble->subchannels, - (*component)->subchId); - - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*component)->subchId, (*component)->serviceId); - throw MuxInitException(); - } - - if ((*subchannel)->type != subchannel_type_t::Packet) - continue; - - if (fig0_3_header == NULL) { - fig0_3_header = (FIGtype0_3_header*)&etiFrame[index]; - fig0_3_header->FIGtypeNumber = 0; - fig0_3_header->Length = 1; - fig0_3_header->CN = 0; - fig0_3_header->OE = 0; - fig0_3_header->PD = 0; - fig0_3_header->Extension = 3; - - index += 2; - figSize += 2; - } - - bool factumAnalyzer = m_pt.get("general.writescca", false); - - /* Warning: When bit SCCA_flag is unset(0), the multiplexer - * R&S does not send the SCCA field. But, in the Factum ETI - * analyzer, if this field is not there, it is an error. - */ - fig0_3_data = (FIGtype0_3_data*)&etiFrame[index]; - fig0_3_data->setSCId((*component)->packet.id); - fig0_3_data->rfa = 0; - fig0_3_data->SCCA_flag = 0; - // if 0, datagroups are used - fig0_3_data->DG_flag = !(*component)->packet.datagroup; - fig0_3_data->rfu = 0; - fig0_3_data->DSCTy = (*component)->type; - fig0_3_data->SubChId = (*subchannel)->id; - fig0_3_data->setPacketAddress((*component)->packet.address); - if (factumAnalyzer) { - fig0_3_data->SCCA = 0; - } - - fig0_3_header->Length += 5; - index += 5; - figSize += 5; - if (factumAnalyzer) { - fig0_3_header->Length += 2; - index += 2; - figSize += 2; - } - - if (figSize > 30) { - etiLog.log(error, - "can't add to Fic Fig 0/3, " - "too much packet service\n"); - throw MuxInitException(); - } - } - break; - - case 7: - fig0 = NULL; - if (serviceFIG0_17 == ensemble->services.end()) { - serviceFIG0_17 = ensemble->services.begin(); - } - for (; serviceFIG0_17 != ensemble->services.end(); - ++serviceFIG0_17) { - - if ( (*serviceFIG0_17)->pty == 0 && - (*serviceFIG0_17)->language == 0) { - continue; - } - - if (fig0 == NULL) { - fig0 = (FIGtype0*)&etiFrame[index]; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 0; - fig0->OE = 0; - fig0->PD = 0; - fig0->Extension = 17; - index += 2; - figSize += 2; - } - - if ((*serviceFIG0_17)->language == 0) { - if (figSize + 4 > 30) { - break; - } - } - else { - if (figSize + 5 > 30) { - break; - } - } - - programme = - (FIGtype0_17_programme*)&etiFrame[index]; - programme->SId = htons((*serviceFIG0_17)->id); - programme->SD = 1; - programme->PS = 0; - programme->L = (*serviceFIG0_17)->language != 0; - programme->CC = 0; - programme->Rfa = 0; - programme->NFC = 0; - if ((*serviceFIG0_17)->language == 0) { - etiFrame[index + 3] = (*serviceFIG0_17)->pty; - fig0->Length += 4; - index += 4; - figSize += 4; - } - else { - etiFrame[index + 3] = (*serviceFIG0_17)->language; - etiFrame[index + 4] = (*serviceFIG0_17)->pty; - fig0->Length += 5; - index += 5; - figSize += 5; - } - } - break; - } - - if (figSize > 30) { - etiLog.log(error, - "FIB0 overload (%i > 30)\n", figSize); - throw MuxInitException(); - } - - memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); - index += 30 - figSize; - - CRCtmp = 0xffff; - CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); - CRCtmp ^= 0xffff; - etiFrame[index++] = ((char *) &CRCtmp)[1]; - etiFrame[index++] = ((char *) &CRCtmp)[0]; - - figSize = 0; - // FIB 1 insertion - switch (rotateFIB) { - case 0: // FIG 0/8 program - fig0 = NULL; - - if (componentProgFIG0_8 == ensemble->components.end()) { - componentProgFIG0_8 = ensemble->components.begin(); - } - for (; componentProgFIG0_8 != ensemble->components.end(); - ++componentProgFIG0_8) { - service = getService(*componentProgFIG0_8, - ensemble->services); - subchannel = getSubchannel(ensemble->subchannels, - (*componentProgFIG0_8)->subchId); - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*componentProgFIG0_8)->subchId, - (*componentProgFIG0_8)->serviceId); - throw MuxInitException(); - } - - if (!(*service)->program) - continue; - - if (fig0 == NULL) { - fig0 = (FIGtype0*)&etiFrame[index]; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 0; - fig0->OE = 0; - fig0->PD = 0; - fig0->Extension = 8; - index += 2; - figSize += 2; - } - - if ((*subchannel)->type == subchannel_type_t::Packet) { - // Data packet - - if (figSize > 30 - 5) { - break; - } - etiFrame[index] = - ((*componentProgFIG0_8)->serviceId >> 8) & 0xFF; - etiFrame[index+1] = - ((*componentProgFIG0_8)->serviceId) & 0xFF; - fig0->Length += 2; - index += 2; - figSize += 2; - - FIGtype0_8_long* definition = - (FIGtype0_8_long*)&etiFrame[index]; - memset(definition, 0, 3); - definition->ext = 0; // no rfa - definition->SCIdS = (*componentProgFIG0_8)->SCIdS; - definition->LS = 1; - definition->setSCId((*componentProgFIG0_8)->packet.id); - fig0->Length += 3; - index += 3; // 8 minus rfa - figSize += 3; - } - else { // Audio, data stream or FIDC - if (figSize > 30 - 4) { - break; - } - etiFrame[index] = - ((*componentProgFIG0_8)->serviceId >> 8) & 0xFF; - etiFrame[index+1] = - ((*componentProgFIG0_8)->serviceId) & 0xFF; - - fig0->Length += 2; - index += 2; - figSize += 2; - - FIGtype0_8_short* definition = - (FIGtype0_8_short*)&etiFrame[index]; - memset(definition, 0, 2); - definition->ext = 0; // no rfa - definition->SCIdS = (*componentProgFIG0_8)->SCIdS; - definition->LS = 0; - definition->MscFic = 0; - definition->Id = (*componentProgFIG0_8)->subchId; - fig0->Length += 2; - index += 2; // 4 minus rfa - figSize += 2; - } - } - break; - - case 1: // FIG 0/8 data - fig0 = NULL; - - if (componentDataFIG0_8 == ensemble->components.end()) { - componentDataFIG0_8 = ensemble->components.begin(); - } - for (; componentDataFIG0_8 != ensemble->components.end(); - ++componentDataFIG0_8) { - service = getService(*componentDataFIG0_8, - ensemble->services); - - subchannel = getSubchannel(ensemble->subchannels, - (*componentDataFIG0_8)->subchId); - - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*componentDataFIG0_8)->subchId, - (*componentDataFIG0_8)->serviceId); - throw MuxInitException(); - } - - if ((*service)->program) - continue; - - if (fig0 == NULL) { - fig0 = (FIGtype0*)&etiFrame[index]; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 0; - fig0->OE = 0; - fig0->PD = 1; - fig0->Extension = 8; - index += 2; - figSize += 2; - } - - if ((*subchannel)->type == subchannel_type_t::Packet) { - // Data packet - - if (figSize > 30 - 7) { - break; - } - etiFrame[index] = - ((*componentDataFIG0_8)->serviceId >> 8) & 0xFF; - etiFrame[index+1] = - ((*componentDataFIG0_8)->serviceId) & 0xFF; - fig0->Length += 4; - index += 4; - figSize += 4; - - FIGtype0_8_long* definition = - (FIGtype0_8_long*)&etiFrame[index]; - memset(definition, 0, 3); - definition->ext = 0; // no rfa - definition->SCIdS = (*componentDataFIG0_8)->SCIdS; - definition->LS = 1; - definition->setSCId((*componentDataFIG0_8)->packet.id); - fig0->Length += 3; - index += 3; // 8 minus rfa - figSize += 3; - } - else { // Audio, data stream or FIDC - if (figSize > 30 - 6) { - break; - } - etiFrame[index] = - ((*componentDataFIG0_8)->serviceId >> 8) & 0xFF; - etiFrame[index+1] = - ((*componentDataFIG0_8)->serviceId) & 0xFF; - fig0->Length += 4; - index += 4; - figSize += 4; - - FIGtype0_8_short* definition = - (FIGtype0_8_short*)&etiFrame[index]; - memset(definition, 0, 2); - definition->ext = 0; // no rfa - definition->SCIdS = (*componentDataFIG0_8)->SCIdS; - definition->LS = 0; - definition->MscFic = 0; - definition->Id = (*componentDataFIG0_8)->subchId; - fig0->Length += 2; - index += 2; // 4 minus rfa - figSize += 2; - } - } - break; - - case 3: - // FIG type 1/0, Service Information (SI), Ensemble Label - fig1_0 = (FIGtype1_0 *) & etiFrame[index]; - - fig1_0->Length = 21; - fig1_0->FIGtypeNumber = 1; - fig1_0->Extension = 0; - fig1_0->OE = 0; - fig1_0->Charset = 0; - fig1_0->EId = htons(ensemble->id); - index = index + 4; - - ensemble->label.writeLabel(&etiFrame[index]); - index = index + 16; - - etiFrame[index++] = ensemble->label.flag() >> 8; - etiFrame[index++] = ensemble->label.flag() & 0xFF; - - figSize += 22; - break; - - case 5: - case 6: - // FIG 0 / 13 - fig0 = NULL; - - if (componentFIG0_13 == ensemble->components.end()) { - componentFIG0_13 = ensemble->components.begin(); - - transmitFIG0_13programme = !transmitFIG0_13programme; - // Alternate between data and and programme FIG0/13, - // do not mix fig0 with PD=0 with extension 13 stuff - // that actually needs PD=1, and vice versa - } - - for (; componentFIG0_13 != ensemble->components.end(); - ++componentFIG0_13) { - - subchannel = getSubchannel(ensemble->subchannels, - (*componentFIG0_13)->subchId); - - if (subchannel == ensemble->subchannels.end()) { - etiLog.log(error, - "Subchannel %i does not exist for component " - "of service %i\n", - (*componentFIG0_13)->subchId, - (*componentFIG0_13)->serviceId); - throw MuxInitException(); - } - - if ( transmitFIG0_13programme && - (*subchannel)->type == subchannel_type_t::Audio && - (*componentFIG0_13)->audio.uaType != 0xffff) { - if (fig0 == NULL) { - fig0 = (FIGtype0*)&etiFrame[index]; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 0; - fig0->OE = 0; - fig0->PD = 0; - fig0->Extension = 13; - index += 2; - figSize += 2; - } - - if (figSize > 30 - (3+4+11)) { - break; - } - - FIG0_13_shortAppInfo* info = - (FIG0_13_shortAppInfo*)&etiFrame[index]; - info->SId = htonl((*componentFIG0_13)->serviceId) >> 16; - info->SCIdS = (*componentFIG0_13)->SCIdS; - info->No = 1; - index += 3; - figSize += 3; - fig0->Length += 3; - - FIG0_13_app* app = (FIG0_13_app*)&etiFrame[index]; - app->setType((*componentFIG0_13)->audio.uaType); - app->length = 2; - app->xpad = htons(0x0c3c); - /* xpad meaning - CA = 0 - CAOrg = 0 - Rfu = 0 - AppTy(5) = 12 (MOT, start of X-PAD data group) - DG = 0 (MSC data groups used) - Rfu = 0 - DSCTy(6) = 60 (MOT) - */ - - index += 2 + app->length; - figSize += 2 + app->length; - fig0->Length += 2 + app->length; - } - else if (!transmitFIG0_13programme && - (*subchannel)->type == subchannel_type_t::Packet && - (*componentFIG0_13)->packet.appType != 0xffff) { - - if (fig0 == NULL) { - fig0 = (FIGtype0*)&etiFrame[index]; - fig0->FIGtypeNumber = 0; - fig0->Length = 1; - fig0->CN = 0; - fig0->OE = 0; - fig0->PD = 1; - fig0->Extension = 13; - index += 2; - figSize += 2; - } - - if (figSize > 30 - (5+2)) { - break; - } - - FIG0_13_longAppInfo* info = - (FIG0_13_longAppInfo*)&etiFrame[index]; - info->SId = htonl((*componentFIG0_13)->serviceId); - info->SCIdS = (*componentFIG0_13)->SCIdS; - info->No = 1; - index += 5; - figSize += 5; - fig0->Length += 5; - - FIG0_13_app* app = (FIG0_13_app*)&etiFrame[index]; - app->setType((*componentFIG0_13)->packet.appType); - app->length = 0; - index += 2; - figSize += 2; - fig0->Length += 2; - } - } - break; - - case 7: - //Time and country identifier - fig0_10 = (FIGtype0_10 *) & etiFrame[index]; - - fig0_10->FIGtypeNumber = 0; - fig0_10->Length = 5; - fig0_10->CN = 0; - fig0_10->OE = 0; - fig0_10->PD = 0; - fig0_10->Extension = 10; - index = index + 2; - - timeData = gmtime(&date); - - fig0_10->RFU = 0; - fig0_10->setMJD(gregorian2mjd(timeData->tm_year + 1900, - timeData->tm_mon + 1, - timeData->tm_mday)); - fig0_10->LSI = 0; - fig0_10->ConfInd = 1; - fig0_10->UTC = 0; - fig0_10->setHours(timeData->tm_hour); - fig0_10->Minutes = timeData->tm_min; - index = index + 4; - figSize += 6; - - fig0_9 = (FIGtype0_9*)&etiFrame[index]; - fig0_9->FIGtypeNumber = 0; - fig0_9->Length = 4; - fig0_9->CN = 0; - fig0_9->OE = 0; - fig0_9->PD = 0; - fig0_9->Extension = 9; - - fig0_9->ext = 0; - fig0_9->lto = 0; // Unique LTO for ensemble - - if (ensemble->lto_auto) { - time_t now = time(NULL); - struct tm* ltime = localtime(&now); - time_t now2 = timegm(ltime); - ensemble->lto = (now2 - now) / 1800; - } - - if (ensemble->lto >= 0) { - fig0_9->ensembleLto = ensemble->lto; - } - else { - /* Convert to 1-complement representation */ - fig0_9->ensembleLto = (-ensemble->lto) | (1<<5); - } - - fig0_9->ensembleEcc = ensemble->ecc; - fig0_9->tableId = ensemble->international_table; - index += 5; - figSize += 5; - - break; - } - - if (figSize > 30) { - etiLog.log(error, - "FIB1 overload (%i > 30)\n", figSize); - throw MuxInitException(); - } - - memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); - index += 30 - figSize; - - CRCtmp = 0xffff; - CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); - CRCtmp ^= 0xffff; - etiFrame[index++] = ((char *) &CRCtmp)[1]; - etiFrame[index++] = ((char *) &CRCtmp)[0]; - - - figSize = 0; - // FIB 2 insertion - if (rotateFIB < ensemble->services.size()) { - service = ensemble->services.begin() + rotateFIB; - - // FIG type 1/1, SI, Service label, one instance per subchannel - if ((*service)->getType(ensemble) == subchannel_type_t::Audio) { - fig1_1 = (FIGtype1_1 *) & etiFrame[index]; - - fig1_1->FIGtypeNumber = 1; - fig1_1->Length = 21; - fig1_1->Charset = 0; - fig1_1->OE = 0; - fig1_1->Extension = 1; - - fig1_1->Sld = htons((*service)->id); - index += 4; - figSize += 4; - } - else { - fig1_5 = (FIGtype1_5 *) & etiFrame[index]; - fig1_5->FIGtypeNumber = 1; - fig1_5->Length = 23; - fig1_5->Charset = 0; - fig1_5->OE = 0; - fig1_5->Extension = 5; - - fig1_5->SId = htonl((*service)->id); - index += 6; - figSize += 6; - } - (*service)->label.writeLabel(&etiFrame[index]); - index += 16; - figSize += 16; - etiFrame[index++] = (*service)->label.flag() >> 8; - etiFrame[index++] = (*service)->label.flag() & 0xFF; - figSize += 2; - } - else if (rotateFIB < - ensemble->services.size() + ensemble->components.size()) { - component = ensemble->components.begin() + - (rotateFIB - ensemble->services.size()); - - service = getService(*component, ensemble->services); - - subchannel = - getSubchannel(ensemble->subchannels, (*component)->subchId); - - if (not (*component)->label.long_label().empty() ) { - if ((*service)->getType(ensemble) == subchannel_type_t::Audio) { - // Programme - FIGtype1_4_programme *fig1_4; - fig1_4 = (FIGtype1_4_programme*)&etiFrame[index]; - - fig1_4->FIGtypeNumber = 1; - fig1_4->Length = 22; - fig1_4->Charset = 0; - fig1_4->OE = 0; - fig1_4->Extension = 4; - fig1_4->PD = 0; - fig1_4->rfa = 0; - fig1_4->SCIdS = (*component)->SCIdS; - - fig1_4->SId = htons((*service)->id); - index += 5; - figSize += 5; - } - else { // Data - FIGtype1_4_data *fig1_4; - fig1_4 = (FIGtype1_4_data *) & etiFrame[index]; - fig1_4->FIGtypeNumber = 1; - fig1_4->Length = 24; - fig1_4->Charset = 0; - fig1_4->OE = 0; - fig1_4->Extension = 4; - fig1_4->PD = 1; - fig1_4->rfa = 0; - fig1_4->SCIdS = (*component)->SCIdS; - - fig1_4->SId = htonl((*service)->id); - index += 7; - figSize += 7; - } - (*component)->label.writeLabel(&etiFrame[index]); - index += 16; - figSize += 16; - - etiFrame[index++] = (*component)->label.flag() >> 8; - etiFrame[index++] = (*component)->label.flag() & 0xFF; - figSize += 2; - } - } - - if (figSize > 30) { - etiLog.log(error, - "FIB2 overload (%i > 30)\n", figSize); - throw MuxInitException(); - } - memcpy(&etiFrame[index], Padding_FIB, 30 - figSize); - index += 30 - figSize; - - CRCtmp = 0xffff; - CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); - CRCtmp ^= 0xffff; - etiFrame[index++] = ((char *) &CRCtmp)[1]; - etiFrame[index++] = ((char *) &CRCtmp)[0]; - - /* ETSI EN 300 799 Table 2: - * Only TM3 has a FIB count to CIF count that is - * not 3 to 1. - */ - if (ensemble->mode == 3) { - memcpy(&etiFrame[index], Padding_FIB, 30); - /* Fill FIB3 with padding */ - index += 30; - - CRCtmp = 0xffff; - CRCtmp = crc16(CRCtmp, &etiFrame[(index - 30)], 30); - CRCtmp ^= 0xffff; - etiFrame[index++] = ((char *) &CRCtmp)[1]; - etiFrame[index++] = ((char *) &CRCtmp)[0]; - } - - if (ensemble->services.size() > 30) { - etiLog.log(error, - "Sorry, but this software currently can't write " - "Service Label of more than 30 services.\n"); - throw MuxInitException(); - } - - // counter for FIG 0/0 - insertFIG = (insertFIG + 1) % 16; - - // We rotate through the FIBs every 30 frames - rotateFIB = (rotateFIB + 1) % 30; - } + fig_carousel.update(currentFrame, date); + const bool fib3_present = ensemble->mode == 3; + index += fig_carousel.write_fibs(&etiFrame[index], currentFrame % 4, fib3_present); /********************************************************************** ****** Input Data Reading ******************************************* @@ -1910,10 +830,7 @@ void DabMultiplexer::print_info(void) void DabMultiplexer::set_parameter(const std::string& parameter, const std::string& value) { - if (parameter == "carousel") { - std::stringstream ss; - ss << value; - ss >> m_use_new_fig_carousel; + if (0) { } else { stringstream ss; @@ -1927,8 +844,7 @@ void DabMultiplexer::set_parameter(const std::string& parameter, const std::string DabMultiplexer::get_parameter(const std::string& parameter) const { stringstream ss; - if (parameter == "carousel") { - ss << m_use_new_fig_carousel; + if (0) { } else { ss << "Parameter '" << parameter << diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index 3e16141..a312b5b 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -46,7 +46,6 @@ #include "RemoteControl.h" #include "Eti.h" #include "ClockTAI.h" -#include <exception> #include <vector> #include <chrono> #include <memory> @@ -54,18 +53,6 @@ #include <memory> #include <boost/property_tree/ptree.hpp> -class MuxInitException : public std::exception -{ - public: - MuxInitException(const std::string m = "ODR-DabMux initialisation error") - throw() - : msg(m) {} - ~MuxInitException(void) throw() {} - const char* what() const throw() { return msg.c_str(); } - private: - std::string msg; -}; - class DabMultiplexer : public RemoteControllable { public: DabMultiplexer( @@ -109,23 +96,6 @@ class DabMultiplexer : public RemoteControllable { uint32_t sync; unsigned long currentFrame; - /* FIG carousel logic and iterators */ - unsigned int insertFIG; - unsigned int rotateFIB; - - std::vector<std::shared_ptr<DabService> >::iterator serviceProgFIG0_2; - std::vector<std::shared_ptr<DabService> >::iterator serviceDataFIG0_2; - std::vector<std::shared_ptr<DabService> >::iterator serviceFIG0_17; - - std::vector<DabComponent*>::iterator componentProgFIG0_8; - std::vector<DabComponent*>::iterator componentDataFIG0_8; - std::vector<DabComponent*>::iterator componentFIG0_13; - // Alternate between programme and data - bool transmitFIG0_13programme; - - - std::vector<dabSubchannel*>::iterator subchannelFIG0_1; - std::shared_ptr<dabEnsemble> ensemble; // Multiplex reconfiguration requires two sets of configurations @@ -145,7 +115,6 @@ class DabMultiplexer : public RemoteControllable { #endif // HAVE_OUTPUT_EDI /* New FIG Carousel */ - bool m_use_new_fig_carousel; FIC::FIGCarousel fig_carousel; }; @@ -171,371 +140,5 @@ class DabMultiplexer : public RemoteControllable { #define DEFAULT_SERVICE_ID 50 #define DEFAULT_PACKET_ADDRESS 0 - -/***************************************************************************** - ***************** Definition of FIG structures **************************** - *****************************************************************************/ - -#ifdef _WIN32 -# pragma pack(push) -#endif - -struct FIGtype0 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIGtype0_0 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint16_t EId; - uint8_t CIFcnt_hight:5; - uint8_t Al:1; - uint8_t Change:2; - uint8_t CIFcnt_low:8; -} PACKED; - - -struct FIGtype0_2 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIGtype0_2_Service { - uint16_t SId; - uint8_t NbServiceComp:4; - uint8_t CAId:3; - uint8_t Local_flag:1; -} PACKED; - - -struct FIGtype0_2_Service_data { - uint32_t SId; - uint8_t NbServiceComp:4; - uint8_t CAId:3; - uint8_t Local_flag:1; -} PACKED; - - -struct FIGtype0_2_audio_component { - uint8_t ASCTy:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SubChId:6; -} PACKED; - - -struct FIGtype0_2_data_component { - uint8_t DSCTy:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SubChId:6; -} PACKED; - - -struct FIGtype0_2_packet_component { - uint8_t SCId_high:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SCId_low:6; - void setSCId(uint16_t SCId) { - SCId_high = SCId >> 6; - SCId_low = SCId & 0x3f; - } -} PACKED; - - -struct FIGtype0_3_header { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -/* Warning: When bit SCCA_flag is unset(0), the multiplexer R&S does not send - * the SCCA field. But, in the Factum ETI analyzer, if this field is not there, - * it is an error. - */ -struct FIGtype0_3_data { - uint8_t SCId_high; - uint8_t SCCA_flag:1; - uint8_t rfa:3; - uint8_t SCId_low:4; - uint8_t DSCTy:6; - uint8_t rfu:1; - uint8_t DG_flag:1; - uint8_t Packet_address_high:2; - uint8_t SubChId:6; - uint8_t Packet_address_low; - uint16_t SCCA; - void setSCId(uint16_t SCId) { - SCId_high = SCId >> 4; - SCId_low = SCId & 0xf; - } - void setPacketAddress(uint16_t address) { - Packet_address_high = address >> 8; - Packet_address_low = address & 0xff; - } -} PACKED; - - -struct FIGtype0_8_short { - uint8_t SCIdS:4; - uint8_t rfa_1:3; - uint8_t ext:1; - uint8_t Id:6; - uint8_t MscFic:1; - uint8_t LS:1; - uint8_t rfa_2; -} PACKED; - - -struct FIGtype0_8_long { - uint8_t SCIdS:4; - uint8_t rfa_1:3; - uint8_t ext:1; - uint8_t SCId_high:4; - uint8_t rfa:3; - uint8_t LS:1; - uint8_t SCId_low; - uint8_t rfa_2; - void setSCId(uint16_t id) { - SCId_high = id >> 8; - SCId_low = id & 0xff; - } - uint16_t getSCid() { - return (SCId_high << 8) | SCId_low; - } -} PACKED; - - -struct FIGtype0_9 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint8_t ensembleLto:6; - uint8_t lto:1; - uint8_t ext:1; - uint8_t ensembleEcc; - uint8_t tableId; -} PACKED; - - -struct FIGtype0_10 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint8_t MJD_high:7; - uint8_t RFU:1; - uint8_t MJD_med; - uint8_t Hours_high:3; - uint8_t UTC:1; - uint8_t ConfInd:1; - uint8_t LSI:1; - uint8_t MJD_low:2; - uint8_t Minutes:6; - uint8_t Hours_low:2; - void setMJD(uint32_t date) { - MJD_high = (date >> 10) & 0x7f; - MJD_med = (date >> 2) & 0xff; - MJD_low = date & 0x03; - } - void setHours(uint16_t hours) { - Hours_high = (hours >> 2) & 0x07; - Hours_low = hours & 0x03; - } -} PACKED; - - -struct FIGtype0_17_programme { - uint16_t SId; - uint8_t NFC:2; - uint8_t Rfa:2; - uint8_t CC:1; // Complimentary code - uint8_t L:1; // Signals presence of language field - uint8_t PS:1; // Primary/Secondary - // PS==0: language refers to primary service component - // PS==1: language refers to secondary service component - uint8_t SD:1; // Static/Dynamic - // SD==0: PTy and language may not represent the current programme contents - // SD==1: PTy and language represent the current programme contents -} PACKED; - -struct FIGtype0_18 { - uint16_t SId; - uint16_t ASu; - uint8_t NumClusters:5; - uint8_t Rfa:3; - /* Followed by uint8_t Cluster IDs */ -} PACKED; - -struct FIGtype0_19 { - uint8_t ClusterId; - uint16_t ASw; - uint8_t SubChId:6; - uint8_t RegionFlag:1; // shall be zero - uint8_t NewFlag:1; - // Region and RFa not supported -} PACKED; - -struct FIGtype0_1 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIG_01_SubChannel_ShortF { - uint8_t StartAdress_high:2; - uint8_t SubChId:6; - uint8_t StartAdress_low:8; - uint8_t TableIndex:6; - uint8_t TableSwitch:1; - uint8_t Short_Long_form:1; -} PACKED; - - -struct FIG_01_SubChannel_LongF { - uint8_t StartAdress_high:2; - uint8_t SubChId:6; - uint8_t StartAdress_low:8; - uint8_t Sub_ChannelSize_high:2; - uint8_t ProtectionLevel:2; - uint8_t Option:3; - uint8_t Short_Long_form:1; - uint8_t Sub_ChannelSize_low:8; -} PACKED; - - -// See EN 300 401, Clause 8.1.20 for the FIG0_13 description -struct FIG0_13_shortAppInfo { - uint16_t SId; - uint8_t No:4; - uint8_t SCIdS:4; -} PACKED; - - -struct FIG0_13_longAppInfo { - uint32_t SId; - uint8_t No:4; - uint8_t SCIdS:4; -} PACKED; - - -struct FIG0_13_app { - uint8_t typeHigh; - uint8_t length:5; - uint8_t typeLow:3; - void setType(uint16_t type) { - typeHigh = type >> 3; - typeLow = type & 0x1f; - } - uint16_t xpad; -} PACKED; - -#define FIG0_13_APPTYPE_SLIDESHOW 0x2 -#define FIG0_13_APPTYPE_WEBSITE 0x3 -#define FIG0_13_APPTYPE_TPEG 0x4 -#define FIG0_13_APPTYPE_DGPS 0x5 -#define FIG0_13_APPTYPE_TMC 0x6 -#define FIG0_13_APPTYPE_EPG 0x7 -#define FIG0_13_APPTYPE_DABJAVA 0x8 -#define FIG0_13_APPTYPE_JOURNALINE 0x441 - - -struct FIGtype1_0 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:3; - uint8_t OE:1; - uint8_t Charset:4; - - uint16_t EId; -} PACKED; - - -struct FIGtype1_1 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:3; - uint8_t OE:1; - uint8_t Charset:4; - - uint16_t Sld; -} PACKED; - - -struct FIGtype1_5 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:3; - uint8_t OE:1; - uint8_t Charset:4; - uint32_t SId; -} PACKED; - - -struct FIGtype1_4_programme { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:3; - uint8_t OE:1; - uint8_t Charset:4; - uint8_t SCIdS:4; - uint8_t rfa:3; - uint8_t PD:1; - uint16_t SId; -} PACKED; - - -struct FIGtype1_4_data { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:3; - uint8_t OE:1; - uint8_t Charset:4; - uint8_t SCIdS:4; - uint8_t rfa:3; - uint8_t PD:1; - uint32_t SId; -} PACKED; - - -#ifdef _WIN32 -# pragma pack(pop) -#endif - #endif diff --git a/src/MuxElements.h b/src/MuxElements.h index 97b1390..44af574 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -32,6 +32,7 @@ #include <memory> #include <string> #include <functional> +#include <exception> #include <algorithm> #include <stdint.h> #include "dabOutput/dabOutput.h" @@ -39,6 +40,19 @@ #include "RemoteControl.h" #include "Eti.h" +class MuxInitException : public std::exception +{ + public: + MuxInitException(const std::string m = "ODR-DabMux initialisation error") + throw() + : msg(m) {} + ~MuxInitException(void) throw() {} + const char* what() const throw() { return msg.c_str(); } + private: + std::string msg; +}; + + enum class subchannel_type_t { Audio = 0, DataDmb = 1, diff --git a/src/fig/FIG0.cpp b/src/fig/FIG0.cpp index f3c409e..986e301 100644 --- a/src/fig/FIG0.cpp +++ b/src/fig/FIG0.cpp @@ -26,7 +26,7 @@ */ #include "fig/FIG0.h" -#include "DabMultiplexer.h" +#include "dabUtils.h" namespace FIC { diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h index 927a7f5..56b7d98 100644 --- a/src/fig/FIG0.h +++ b/src/fig/FIG0.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2015, 2016 + Copyright (C) 2016 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -254,6 +254,309 @@ class FIG0_19 : public IFIG std::shared_ptr<AnnouncementCluster>,int> m_disabled_announcements; }; +#ifdef _WIN32 +# pragma pack(push) +#endif + +struct FIGtype0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIGtype0_0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint16_t EId; + uint8_t CIFcnt_hight:5; + uint8_t Al:1; + uint8_t Change:2; + uint8_t CIFcnt_low:8; +} PACKED; + + +struct FIGtype0_2 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIGtype0_2_Service { + uint16_t SId; + uint8_t NbServiceComp:4; + uint8_t CAId:3; + uint8_t Local_flag:1; +} PACKED; + + +struct FIGtype0_2_Service_data { + uint32_t SId; + uint8_t NbServiceComp:4; + uint8_t CAId:3; + uint8_t Local_flag:1; +} PACKED; + + +struct FIGtype0_2_audio_component { + uint8_t ASCTy:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SubChId:6; +} PACKED; + + +struct FIGtype0_2_data_component { + uint8_t DSCTy:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SubChId:6; +} PACKED; + + +struct FIGtype0_2_packet_component { + uint8_t SCId_high:6; + uint8_t TMid:2; + uint8_t CA_flag:1; + uint8_t PS:1; + uint8_t SCId_low:6; + void setSCId(uint16_t SCId) { + SCId_high = SCId >> 6; + SCId_low = SCId & 0x3f; + } +} PACKED; + + +struct FIGtype0_3_header { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +/* Warning: When bit SCCA_flag is unset(0), the multiplexer R&S does not send + * the SCCA field. But, in the Factum ETI analyzer, if this field is not there, + * it is an error. + */ +struct FIGtype0_3_data { + uint8_t SCId_high; + uint8_t SCCA_flag:1; + uint8_t rfa:3; + uint8_t SCId_low:4; + uint8_t DSCTy:6; + uint8_t rfu:1; + uint8_t DG_flag:1; + uint8_t Packet_address_high:2; + uint8_t SubChId:6; + uint8_t Packet_address_low; + uint16_t SCCA; + void setSCId(uint16_t SCId) { + SCId_high = SCId >> 4; + SCId_low = SCId & 0xf; + } + void setPacketAddress(uint16_t address) { + Packet_address_high = address >> 8; + Packet_address_low = address & 0xff; + } +} PACKED; + + +struct FIGtype0_8_short { + uint8_t SCIdS:4; + uint8_t rfa_1:3; + uint8_t ext:1; + uint8_t Id:6; + uint8_t MscFic:1; + uint8_t LS:1; + uint8_t rfa_2; +} PACKED; + + +struct FIGtype0_8_long { + uint8_t SCIdS:4; + uint8_t rfa_1:3; + uint8_t ext:1; + uint8_t SCId_high:4; + uint8_t rfa:3; + uint8_t LS:1; + uint8_t SCId_low; + uint8_t rfa_2; + void setSCId(uint16_t id) { + SCId_high = id >> 8; + SCId_low = id & 0xff; + } + uint16_t getSCid() { + return (SCId_high << 8) | SCId_low; + } +} PACKED; + + +struct FIGtype0_9 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint8_t ensembleLto:6; + uint8_t lto:1; + uint8_t ext:1; + uint8_t ensembleEcc; + uint8_t tableId; +} PACKED; + + +struct FIGtype0_10 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; + + uint8_t MJD_high:7; + uint8_t RFU:1; + uint8_t MJD_med; + uint8_t Hours_high:3; + uint8_t UTC:1; + uint8_t ConfInd:1; + uint8_t LSI:1; + uint8_t MJD_low:2; + uint8_t Minutes:6; + uint8_t Hours_low:2; + void setMJD(uint32_t date) { + MJD_high = (date >> 10) & 0x7f; + MJD_med = (date >> 2) & 0xff; + MJD_low = date & 0x03; + } + void setHours(uint16_t hours) { + Hours_high = (hours >> 2) & 0x07; + Hours_low = hours & 0x03; + } +} PACKED; + + +struct FIGtype0_17_programme { + uint16_t SId; + uint8_t NFC:2; + uint8_t Rfa:2; + uint8_t CC:1; // Complimentary code + uint8_t L:1; // Signals presence of language field + uint8_t PS:1; // Primary/Secondary + // PS==0: language refers to primary service component + // PS==1: language refers to secondary service component + uint8_t SD:1; // Static/Dynamic + // SD==0: PTy and language may not represent the current programme contents + // SD==1: PTy and language represent the current programme contents +} PACKED; + +struct FIGtype0_18 { + uint16_t SId; + uint16_t ASu; + uint8_t NumClusters:5; + uint8_t Rfa:3; + /* Followed by uint8_t Cluster IDs */ +} PACKED; + +struct FIGtype0_19 { + uint8_t ClusterId; + uint16_t ASw; + uint8_t SubChId:6; + uint8_t RegionFlag:1; // shall be zero + uint8_t NewFlag:1; + // Region and RFa not supported +} PACKED; + +struct FIGtype0_1 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:5; + uint8_t PD:1; + uint8_t OE:1; + uint8_t CN:1; +} PACKED; + + +struct FIG_01_SubChannel_ShortF { + uint8_t StartAdress_high:2; + uint8_t SubChId:6; + uint8_t StartAdress_low:8; + uint8_t TableIndex:6; + uint8_t TableSwitch:1; + uint8_t Short_Long_form:1; +} PACKED; + + +struct FIG_01_SubChannel_LongF { + uint8_t StartAdress_high:2; + uint8_t SubChId:6; + uint8_t StartAdress_low:8; + uint8_t Sub_ChannelSize_high:2; + uint8_t ProtectionLevel:2; + uint8_t Option:3; + uint8_t Short_Long_form:1; + uint8_t Sub_ChannelSize_low:8; +} PACKED; + + +// See EN 300 401, Clause 8.1.20 for the FIG0_13 description +struct FIG0_13_shortAppInfo { + uint16_t SId; + uint8_t No:4; + uint8_t SCIdS:4; +} PACKED; + + +struct FIG0_13_longAppInfo { + uint32_t SId; + uint8_t No:4; + uint8_t SCIdS:4; +} PACKED; + + +struct FIG0_13_app { + uint8_t typeHigh; + uint8_t length:5; + uint8_t typeLow:3; + void setType(uint16_t type) { + typeHigh = type >> 3; + typeLow = type & 0x1f; + } + uint16_t xpad; +} PACKED; + +#define FIG0_13_APPTYPE_SLIDESHOW 0x2 +#define FIG0_13_APPTYPE_WEBSITE 0x3 +#define FIG0_13_APPTYPE_TPEG 0x4 +#define FIG0_13_APPTYPE_DGPS 0x5 +#define FIG0_13_APPTYPE_TMC 0x6 +#define FIG0_13_APPTYPE_EPG 0x7 +#define FIG0_13_APPTYPE_DABJAVA 0x8 +#define FIG0_13_APPTYPE_JOURNALINE 0x441 + + +#ifdef _WIN32 +# pragma pack(pop) +#endif + } // namespace FIC #endif // __FIG0_H_ diff --git a/src/fig/FIG1.cpp b/src/fig/FIG1.cpp index 46e7c4b..86c717e 100644 --- a/src/fig/FIG1.cpp +++ b/src/fig/FIG1.cpp @@ -26,7 +26,6 @@ */ #include "fig/FIG1.h" -#include "DabMultiplexer.h" namespace FIC { diff --git a/src/fig/FIG1.h b/src/fig/FIG1.h index 786dae9..9910320 100644 --- a/src/fig/FIG1.h +++ b/src/fig/FIG1.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2015 + Copyright (C) 2016 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -103,7 +103,73 @@ class FIG1_5 : public IFIG std::vector<std::shared_ptr<DabService> >::iterator service; }; -} -#endif // __FIG1_H_ +#ifdef _WIN32 +# pragma pack(push) +#endif + +struct FIGtype1_0 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + + uint16_t EId; +} PACKED; + + +struct FIGtype1_1 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + + uint16_t Sld; +} PACKED; + + +struct FIGtype1_5 { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint32_t SId; +} PACKED; + + +struct FIGtype1_4_programme { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint8_t SCIdS:4; + uint8_t rfa:3; + uint8_t PD:1; + uint16_t SId; +} PACKED; + + +struct FIGtype1_4_data { + uint8_t Length:5; + uint8_t FIGtypeNumber:3; + uint8_t Extension:3; + uint8_t OE:1; + uint8_t Charset:4; + uint8_t SCIdS:4; + uint8_t rfa:3; + uint8_t PD:1; + uint32_t SId; +} PACKED; + + +#ifdef _WIN32 +# pragma pack(pop) +#endif + +} // namespace FIC +#endif // __FIG1_H_ |