diff options
| -rw-r--r-- | src/DabMultiplexer.cpp | 1 | ||||
| -rw-r--r-- | src/Makefile.am | 5 | ||||
| -rw-r--r-- | src/fig/FIG.h | 64 | ||||
| -rw-r--r-- | src/fig/FIG0.cpp | 148 | ||||
| -rw-r--r-- | src/fig/FIG0.h | 61 | ||||
| -rw-r--r-- | src/fig/FIGCarousel.cpp | 520 | ||||
| -rw-r--r-- | src/fig/FIGCarousel.h | 50 | 
7 files changed, 848 insertions, 1 deletions
diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index a894621..57a4abb 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -26,6 +26,7 @@  #include "DabMultiplexer.h"  #include "ConfigParser.h"  #include <boost/make_shared.hpp> +#include "fic/FIG.h"  using namespace std;  using namespace boost; diff --git a/src/Makefile.am b/src/Makefile.am index 0e55b52..2762788 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -97,7 +97,10 @@ odr_dabmux_SOURCES  =DabMux.cpp DabMux.h \                       ManagementServer.h ManagementServer.cpp \                       TcpServer.h TcpServer.cpp \                       TcpSocket.h TcpSocket.cpp \ -                     zmq.hpp +                     zmq.hpp \ +                     fig/FIG0.cpp fig/FIG0.h \ +                     fig/FIGCarousel.cpp fig/FIGCarousel.h \ +                     fig/FIG.h  odr_bridgetest_CFLAGS   =-DBRIDGE_TEST  odr_bridgetest_SOURCES  =bridge.c \ diff --git a/src/fig/FIG.h b/src/fig/FIG.h new file mode 100644 index 0000000..70b9316 --- /dev/null +++ b/src/fig/FIG.h @@ -0,0 +1,64 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Copyright (C) 2015 +   Matthias P. Braendli, matthias.braendli@mpb.li + +   */ +/* +   This file is part of ODR-DabMux. + +   ODR-DabMux is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   ODR-DabMux is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with ODR-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FIG_H_ +#define __FIG_H_ + +#include <boost/shared_ptr.hpp> +#include "MuxElements.h" + +struct FIGRuntimeInformation { +    unsigned long currentFrame; +    boost::shared_ptr<dabEnsemble> ensemble; +}; + +// Recommended FIG rates according to ETSI TR 101 496-2 Table 3.6.1 +enum class FIG_rate { +    FIG0_0, /* Special repetition rate for FIG0/0, EN 300 401 Clause 6.4 +        In any 96 ms period, the FIG 0/0 should be transmitted in a fixed time +        position. In transmission mode I, this should be the first FIB (of the three) +        associated with the first CIF (of the four) in the transmission frame (see +        clause 5.1). In transmission modes II and III, this should be the first FIB of +        every fourth transmission frame. In transmission mode IV, this should be the +        first FIB (of the three) associated with the first CIF (of the two) in every +        alternate transmission frame (see clause 5.1). */ +    A, // at least 10 times per second +    B, // once per second +    C, // once every 10 seconds +    D, // less than once every 10 seconds +    E, // all in two minutes +}; + +class IFIG +{ +    public: +        virtual size_t fill(uint8_t *buf, size_t max_size) = 0; + +        virtual FIG_rate repetition_rate(void) = 0; +}; + +#endif // __FIG_H_ + diff --git a/src/fig/FIG0.cpp b/src/fig/FIG0.cpp new file mode 100644 index 0000000..85a06b5 --- /dev/null +++ b/src/fig/FIG0.cpp @@ -0,0 +1,148 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Copyright (C) 2015 +   Matthias P. Braendli, matthias.braendli@mpb.li + +   Implementation of FIG0 +   */ +/* +   This file is part of ODR-DabMux. + +   ODR-DabMux is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   ODR-DabMux is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with ODR-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fig/FIG0.h" +#include "DabMultiplexer.h" + +#define PACKED __attribute__ ((packed)) + +//=========== FIG 0/0 =========== + + +size_t FIG0_0::fill(uint8_t *buf, size_t max_size) +{ +    if (max_size < 6) { +        return 0; +    } + +    FIGtype0_0 *fig0_0; +    fig0_0 = (FIGtype0_0 *)buf; + +    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(m_rti->ensemble->id); +    fig0_0->Change = 0; +    fig0_0->Al = 0; +    fig0_0->CIFcnt_hight = (m_rti->currentFrame / 250) % 20; +    fig0_0->CIFcnt_low = (m_rti->currentFrame % 250); + +    return 6; +} + +//=========== FIG 0/1 =========== +// + +FIG0_1::FIG0_1(FIGRuntimeInformation *rti) : m_rti(rti) +{ +    subchannelFIG0_1 = m_rti->ensemble->subchannels.end(); +} + +size_t FIG0_1::fill(uint8_t *buf, size_t max_size) +{ +    size_t remaining = max_size; +    if (max_size < 6) { +        return 0; +    } +    FIGtype0_1 *fig0_1; +    figtype0_1 = (FIGtype0_1 *)buf; + +    figtype0_1->FIGtypeNumber = 0; +    figtype0_1->Length = 1; +    figtype0_1->CN = 0; +    figtype0_1->OE = 0; +    figtype0_1->PD = 0; +    figtype0_1->Extension = 1; +    buf += 2; +    remaining -= 2; + +    // Rotate through the subchannels until there is no more +    // space in the FIG0/1 +    if (subchannelFIG0_1 == m_rti->ensemble->subchannels.end()) { +        subchannelFIG0_1 = m_rti->ensemble->subchannels.begin(); +    } + +    for (; subchannelFIG0_1 != m_rti->ensemble->subchannels.end(); +            ++subchannelFIG0_1) { +        dabProtection* protection = &(*subchannelFIG0_1)->protection; + +        if ( (protection->form == UEP && remaining < 3) || +             (protection->form == EEP && remaining < 4) ) { +            break; +        } + +        if (protection->form == UEP) { +            fig0_1subchShort = +                (FIG_01_SubChannel_ShortF*)buf; +            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; + +            buf += 3; +            remaining -= 3; +            figtype0_1->Length += 3; +        } +        else if (protection->form == EEP) { +            fig0_1subchLong1 = +                (FIG_01_SubChannel_LongF*)buf; +            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; + +            buf += 4; +            remaining -= 4; +            figtype0_1->Length += 4; +        } +    } + +    return max_size - remaining; +} diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h new file mode 100644 index 0000000..502ce7e --- /dev/null +++ b/src/fig/FIG0.h @@ -0,0 +1,61 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Copyright (C) 2015 +   Matthias P. Braendli, matthias.braendli@mpb.li +   */ +/* +   This file is part of ODR-DabMux. + +   ODR-DabMux is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   ODR-DabMux is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with ODR-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FIG0_H_ +#define __FIG0_H_ + +#include <cstdint> + +#include "fig/FIG.h" + +// FIG type 0/0, Multiplex Configuration Info (MCI), +// Ensemble information +class FIG0_0 : public IFIG +{ +    public: +        FIG0_0(FIGRuntimeInformation* rti) : m_rti(rti) {} +        virtual size_t fill(uint8_t *buf, size_t max_size); +        virtual FIG_rate repetition_rate(void) { return FIG_rate::A; } + +    private: +        FIGRuntimeInformation *m_rti; +}; + +// FIG type 0/1, MIC, Sub-Channel Organization, +// one instance of the part for each subchannel +class FIG0_1 : public IFIG +{ +    public: +        FIG0_1(FIGRuntimeInformation* rti); +        virtual size_t fill(uint8_t *buf, size_t max_size); +        virtual FIG_rate repetition_rate(void) { return FIG_rate::A; } + +    private: +        FIGRuntimeInformation *m_rti; +        std::vector<dabSubchannel*>::iterator subchannelFIG0_1; +}; + +#endif // __FIG0_H_ + diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp new file mode 100644 index 0000000..4e53ef5 --- /dev/null +++ b/src/fig/FIGCarousel.cpp @@ -0,0 +1,520 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Copyright (C) 2015 +   Matthias P. Braendli, matthias.braendli@mpb.li + +   Implementation of the FIG carousel to schedule the FIGs into the +   FIBs. +   */ +/* +   This file is part of ODR-DabMux. + +   ODR-DabMux is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   ODR-DabMux is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with ODR-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fig/FIGCarousel.h" +#include "fig/FIG0.h" + +FIGCarousel::FIGCarousel(boost::shared_ptr<dabEnsemble> ensemble) +{ +    m_rti.ensemble = ensemble; +    m_rti.currentFrame = 0; +    m_figs.emplace_back<FIG0_0>(&m_rti); +    m_figs.emplace_back<FIG0_1>(&m_rti); +} + +void FIGCarousel::set_currentFrame(unsigned long currentFrame) +{ +    m_rti.currentFrame = currentFrame; +} + +#if 0 +void fib0 { +    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) != 0) { +                    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 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 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 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; +                } + +                unsigned char type = (*serviceDataFIG0_2)->getType(ensemble); +                if ((type == 0) || (type == 2)) { +                    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 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 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 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 != 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; +    } +} +#endif diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h new file mode 100644 index 0000000..cbb6868 --- /dev/null +++ b/src/fig/FIGCarousel.h @@ -0,0 +1,50 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Copyright (C) 2015 +   Matthias P. Braendli, matthias.braendli@mpb.li + +   Implementation of the FIG carousel to schedule the FIGs into the +   FIBs. +   */ +/* +   This file is part of ODR-DabMux. + +   ODR-DabMux is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   ODR-DabMux is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with ODR-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FIG_CAROUSEL_H_ +#define __FIG_CAROUSEL_H_ + +#include "fig/FIG.h" +#include <list> +#include <boost/shared_ptr.hpp> +#include "MuxElements.h" + +class FIGCarousel { +    public: +        FIGCarousel(boost::shared_ptr<dabEnsemble> ensemble); + +        void set_currentFrame(unsigned long currentFrame); + +    private: +        FIGRuntimeInformation m_rti; +        std::list<IFIG> m_figs; + +}; + +#endif // __FIG_CAROUSEL_H_ +  | 
