From 8166d7777de15266cf97de3e43ef7125a9c26761 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 17 Aug 2015 17:39:05 +0200 Subject: Add ability to map FIG to any FIB Move CRC calculation into FIGCarousel --- src/DabMultiplexer.cpp | 32 +++++-------- src/fig/FIGCarousel.cpp | 122 ++++++++++++++++++++++++++++++++++-------------- src/fig/FIGCarousel.h | 35 ++++++++++---- 3 files changed, 124 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index c7a5554..ea5a582 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -32,7 +32,7 @@ using namespace std; using namespace boost; -static unsigned char Padding_FIB[] = { +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, @@ -635,17 +635,16 @@ void DabMultiplexer::mux_frame(std::vector >& outpu tm* timeData; - unsigned char figSize = 0; - - // FIB 0 Insertion + // Insert all FIBs if (m_use_new_fig_carousel) { fig_carousel.update(currentFrame, date); - figSize += fig_carousel.carousel(0, &etiFrame[index], 30, currentFrame % 4); - index += figSize; + const bool fib3_present = ensemble->mode == 3; + index += fig_carousel.write_fibs(&etiFrame[index], currentFrame % 4, fib3_present); } - // Skip creating a block for the else because - // I don't want to reindent the whole switch block - else switch (insertFIG) { + else { + unsigned char figSize = 0; + // FIB 0 Insertion + switch (insertFIG) { case 0: case 4: @@ -1136,10 +1135,7 @@ void DabMultiplexer::mux_frame(std::vector >& outpu figSize = 0; // FIB 1 insertion - if (m_use_new_fig_carousel) { - figSize += fig_carousel.carousel(1, &etiFrame[index], 30, currentFrame % 4); - index += figSize; - } else switch (rotateFIB) { + switch (rotateFIB) { case 0: // FIG 0/8 program fig0 = NULL; @@ -1536,11 +1532,7 @@ void DabMultiplexer::mux_frame(std::vector >& outpu figSize = 0; // FIB 2 insertion - if (m_use_new_fig_carousel) { - figSize += fig_carousel.carousel(2, &etiFrame[index], 30, currentFrame % 4); - index += figSize; - } - else if (rotateFIB < ensemble->services.size()) { + if (rotateFIB < ensemble->services.size()) { service = ensemble->services.begin() + rotateFIB; // FIG type 1/1, SI, Service label, one instance per subchannel @@ -1661,8 +1653,7 @@ void DabMultiplexer::mux_frame(std::vector >& outpu etiFrame[index++] = ((char *) &CRCtmp)[0]; } - if ( !m_use_new_fig_carousel and - ensemble->services.size() > 30) { + if (ensemble->services.size() > 30) { etiLog.log(error, "Sorry, but this software currently can't write " "Service Label of more than 30 services.\n"); @@ -1674,6 +1665,7 @@ void DabMultiplexer::mux_frame(std::vector >& outpu // We rotate through the FIBs every 30 frames rotateFIB = (rotateFIB + 1) % 30; + } /********************************************************************** ****** Input Data Reading ******************************************* diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp index 1d79f2d..106e78e 100644 --- a/src/fig/FIGCarousel.cpp +++ b/src/fig/FIGCarousel.cpp @@ -26,6 +26,7 @@ along with ODR-DabMux. If not, see . */ +#include "crc.h" #include "Log.h" #include "fig/FIGCarousel.h" #include @@ -73,25 +74,26 @@ FIGCarousel::FIGCarousel(boost::shared_ptr ensemble) : m_fig0_18(&m_rti), m_fig0_19(&m_rti) { - load_and_allocate(m_fig0_0, 0); - load_and_allocate(m_fig0_1, 0); - load_and_allocate(m_fig0_2, 0); - load_and_allocate(m_fig0_3, 0); - load_and_allocate(m_fig0_17, 0); - - load_and_allocate(m_fig0_8, 1); - load_and_allocate(m_fig1_0, 1); - load_and_allocate(m_fig0_13, 1); - load_and_allocate(m_fig0_10, 1); - load_and_allocate(m_fig0_9, 1); - - load_and_allocate(m_fig1_1, 2); - load_and_allocate(m_fig1_5, 2); - load_and_allocate(m_fig0_18, 2); - load_and_allocate(m_fig0_19, 2); + load_and_allocate(m_fig0_1, FIBAllocation::FIB_ANY); + load_and_allocate(m_fig0_2, FIBAllocation::FIB_ANY); + + load_and_allocate(m_fig0_0, FIBAllocation::FIB0); + load_and_allocate(m_fig0_3, FIBAllocation::FIB0); + load_and_allocate(m_fig0_17, FIBAllocation::FIB0); + + load_and_allocate(m_fig0_8, FIBAllocation::FIB1); + load_and_allocate(m_fig1_0, FIBAllocation::FIB1); + load_and_allocate(m_fig0_13, FIBAllocation::FIB1); + load_and_allocate(m_fig0_10, FIBAllocation::FIB1); + load_and_allocate(m_fig0_9, FIBAllocation::FIB1); + + load_and_allocate(m_fig1_1, FIBAllocation::FIB2); + load_and_allocate(m_fig1_5, FIBAllocation::FIB2); + load_and_allocate(m_fig0_18, FIBAllocation::FIB2); + load_and_allocate(m_fig0_19, FIBAllocation::FIB2); } -void FIGCarousel::load_and_allocate(IFIG& fig, int fib) +void FIGCarousel::load_and_allocate(IFIG& fig, FIBAllocation fib) { int type = fig.figtype(); int extension = fig.figextension(); @@ -106,12 +108,8 @@ void FIGCarousel::update(unsigned long currentFrame, time_t dabTime) m_rti.date = dabTime; } -void FIGCarousel::allocate_fig_to_fib(int figtype, int extension, int fib) +void FIGCarousel::allocate_fig_to_fib(int figtype, int extension, FIBAllocation fib) { - if (fib < 0 or fib >= 3) { - throw std::out_of_range("Invalid FIB"); - } - auto fig = m_figs_available.find(std::make_pair(figtype, extension)); if (fig != m_figs_available.end()) { @@ -136,23 +134,76 @@ void dumpfib(const uint8_t *buf, size_t bufsize) { std::cerr << std::endl; } +size_t FIGCarousel::write_fibs( + uint8_t *buf, + int framephase, + bool fib3_present) +{ + /* Decrement all deadlines of all figs */ + for (auto& fib_fig : m_fibs) { + auto fig = fib_fig.second; + for (auto fig_el : fig) { + fig_el.reduce_deadline(); + } + } + + const int fibCount = fib3_present ? 4 : 3; + + for (int fib = 0; fib < fibCount; fib++) { + memset(buf, 0x00, 30); + size_t figSize = carousel(fib, buf, 30, framephase); + + if (figSize < 30) { + buf[figSize] = 0xff; // end marker + } + else if (figSize > 30) { + std::stringstream ss; + ss << "FIB" << fib << " overload (" << figSize << "> 30)"; + throw std::runtime_error(ss.str()); + } + + uint16_t CRCtmp = 0xffff; + CRCtmp = crc16(CRCtmp, buf, 30); + CRCtmp ^= 0xffff; + + buf += 30; + *(buf++) = ((char *) &CRCtmp)[1]; + *(buf++) = ((char *) &CRCtmp)[0]; + } + + return 32 * fibCount; +} + size_t FIGCarousel::carousel( - size_t fib, + int fib, uint8_t *buf, const size_t bufsize, int framephase) { uint8_t *pbuf = buf; - std::list& figs = m_fibs[fib]; + FIBAllocation fibix; - std::deque sorted_figs; - - /* Decrement all deadlines */ - for (auto& fig_el : figs) { - fig_el.reduce_deadline(); + if (fib == 0) { + fibix = FIBAllocation::FIB0; + } + else if (fib == 1) { + fibix = FIBAllocation::FIB1; + } + else if (fib == 2) { + fibix = FIBAllocation::FIB2; + } + else { + throw std::invalid_argument("FIGCarousel::carousel called with invalid fib"); + } - sorted_figs.push_back(&fig_el); + // Create our list of FIGs to consider for this FIB + std::deque sorted_figs; + for (auto& fig : m_fibs[fibix]) { + sorted_figs.push_back(&fig); + } + for (auto& fig : m_fibs[FIBAllocation::FIB_ANY]) { + sorted_figs.push_back(&fig); } /* Sort the FIGs in the FIB according to their deadline */ @@ -190,7 +241,7 @@ size_t FIGCarousel::carousel( pbuf += written; #if CAROUSELDEBUG - std::cerr << " ****** FIG0/0 wrote\t" << written << " bytes" + std::cerr << " ****** FIG0/0(special) wrote\t" << written << " bytes" << std::endl; if ( (*fig0_0)->fig->figtype() != 0 or @@ -240,12 +291,13 @@ size_t FIGCarousel::carousel( if (written > 2) { available_size -= written; pbuf += written; + } #if CAROUSELDEBUG - std::cerr << " ****** FIG" << fig_el->fig->figtype() << "/" << - fig_el->fig->figextension() << " wrote\t" << written << - " bytes" << std::endl; + std::cerr << " ****** FIG" << fig_el->fig->figtype() << "/" << + fig_el->fig->figextension() << " wrote\t" << written << + " bytes" << (status.complete_fig_transmitted ? ", complete" : + ", incomplete") << std::endl; #endif - } if (status.complete_fig_transmitted) { fig_el->increase_deadline(); diff --git a/src/fig/FIGCarousel.h b/src/fig/FIGCarousel.h index f7a839c..bb6b546 100644 --- a/src/fig/FIGCarousel.h +++ b/src/fig/FIGCarousel.h @@ -48,40 +48,55 @@ struct FIGCarouselElement { void increase_deadline(void); }; +enum class FIBAllocation { + FIB0, + FIB1, + FIB2, + FIB3, + FIB_ANY +}; + class FIGCarousel { public: FIGCarousel(boost::shared_ptr ensemble); void update(unsigned long currentFrame, time_t dabTime); - void allocate_fig_to_fib(int figtype, int extension, int fib); + void allocate_fig_to_fib(int figtype, int extension, FIBAllocation fib); + + /* Write all FIBs to the buffer, including correct padding and crc. + * Returns number of bytes written. + * + * The buffer buf must be large enough to accomodate the FIBs, i.e. + * 32 bytes per FIB. + */ + size_t write_fibs( + uint8_t *buf, + int framephase, + bool fib3_present); - size_t carousel(size_t fib, uint8_t *buf, size_t bufsize, int framephase); private: + size_t carousel(int fib, uint8_t *buf, size_t bufsize, int framephase); - void load_and_allocate(IFIG& fig, int fib); + void load_and_allocate(IFIG& fig, FIBAllocation fib); FIGRuntimeInformation m_rti; std::map, IFIG*> m_figs_available; - // Each FIB contains a list of carousel elements - std::map > m_fibs; + // Some FIGs can be mapped to a specific FIB or to FIB_ANY + std::map > m_fibs; - // FIB 0 figs + // See in ctor for allocation to FIBs FIG0_0 m_fig0_0; FIG0_1 m_fig0_1; FIG0_2 m_fig0_2; FIG0_3 m_fig0_3; FIG0_17 m_fig0_17; - - // FIB 1 figs FIG0_8 m_fig0_8; FIG1_0 m_fig1_0; FIG0_13 m_fig0_13; FIG0_10 m_fig0_10; FIG0_9 m_fig0_9; - - // FIB 2 figs FIG1_1 m_fig1_1; FIG1_4 m_fig1_4; FIG1_5 m_fig1_5; -- cgit v1.2.3