diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-07-13 13:54:24 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2020-07-13 13:54:24 +0200 |
commit | f8ee21192238bb5858db9c473dde711e4584dc6a (patch) | |
tree | 930f8619c460b7484fe9d5420aaaf2f5d834e3ad /src/fig/FIG0_13.cpp | |
parent | 56b5c6ae12136c1c24a8e8f6d001d72bf01b0967 (diff) | |
download | dabmux-f8ee21192238bb5858db9c473dde711e4584dc6a.tar.gz dabmux-f8ee21192238bb5858db9c473dde711e4584dc6a.tar.bz2 dabmux-f8ee21192238bb5858db9c473dde711e4584dc6a.zip |
Add possibility to set several user application types in FIG0/13
Diffstat (limited to 'src/fig/FIG0_13.cpp')
-rw-r--r-- | src/fig/FIG0_13.cpp | 119 |
1 files changed, 71 insertions, 48 deletions
diff --git a/src/fig/FIG0_13.cpp b/src/fig/FIG0_13.cpp index 314c6e1..582e28e 100644 --- a/src/fig/FIG0_13.cpp +++ b/src/fig/FIG0_13.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2020 Matthias P. Braendli, matthias.braendli@mpb.li */ /* @@ -92,9 +92,14 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size) const auto type = (*subchannel)->type; if ( m_transmit_programme and (type == subchannel_type_t::DABPlusAudio or type == subchannel_type_t::DABAudio) and - (*componentFIG0_13)->audio.uaType != 0xffff) { + (*componentFIG0_13)->audio.uaTypes.size() != 0) { - const int required_size = 3+4+11; + const size_t num_apps = (*componentFIG0_13)->audio.uaTypes.size(); + + const size_t app_length = 2; + static_assert(sizeof(FIG0_13_shortAppInfo) == 3); + static_assert(sizeof(FIG0_13_app) == 4); + const int required_size = sizeof(FIG0_13_shortAppInfo) + num_apps * (sizeof(FIG0_13_app) + app_length); if (fig0 == NULL) { if (remaining < 2 + required_size) { @@ -117,34 +122,42 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size) FIG0_13_shortAppInfo* info = (FIG0_13_shortAppInfo*)buf; info->SId = htonl((*componentFIG0_13)->serviceId) >> 16; info->SCIdS = (*componentFIG0_13)->SCIdS; - info->No = 1; - buf += 3; - remaining -= 3; - fig0->Length += 3; - - FIG0_13_app* app = (FIG0_13_app*)buf; - 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) - */ - - buf += 2 + app->length; - remaining -= 2 + app->length; - fig0->Length += 2 + app->length; + info->No = num_apps; + buf += sizeof(FIG0_13_shortAppInfo); + remaining -= sizeof(FIG0_13_shortAppInfo); + fig0->Length += sizeof(FIG0_13_shortAppInfo); + + for (const auto& ua : (*componentFIG0_13)->audio.uaTypes) { + FIG0_13_app* app = (FIG0_13_app*)buf; + app->setType(ua.uaType); + app->length = app_length; + + const uint8_t dscty = 60; // TS 101 756 Table 2b (MOT) + app->xpad = htons((ua.xpadAppType << 8) | dscty); + /* xpad meaning + CA = 0 + CAOrg = 0 (CAOrg field absent) + Rfu = 0 + AppTy(5) = depending on config + DG = 0 (MSC data groups used) + Rfu = 0 + DSCTy(6) = 60 (MOT) + */ + + buf += sizeof(FIG0_13_app); + remaining -= sizeof(FIG0_13_app); + fig0->Length += sizeof(FIG0_13_app); + } } - else if (!m_transmit_programme && - (*subchannel)->type == subchannel_type_t::Packet && - (*componentFIG0_13)->packet.appType != 0xffff) { + else if (not m_transmit_programme and + (*subchannel)->type == subchannel_type_t::Packet and + (*componentFIG0_13)->packet.uaTypes.size() != 0) { - const int required_size = 5+2+2; + const size_t num_apps = (*componentFIG0_13)->audio.uaTypes.size(); + + const size_t app_length = 2; + const int required_size = sizeof(FIG0_13_longAppInfo) + num_apps * (sizeof(FIG0_13_app) + app_length); + /* is conservative because app_length can be 0 */ if (fig0 == NULL) { if (remaining < 2 + required_size) { @@ -167,26 +180,36 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size) FIG0_13_longAppInfo* info = (FIG0_13_longAppInfo*)buf; info->SId = htonl((*componentFIG0_13)->serviceId); info->SCIdS = (*componentFIG0_13)->SCIdS; - info->No = 1; - buf += 5; - remaining -= 5; - fig0->Length += 5; - - FIG0_13_app* app = (FIG0_13_app*)buf; - app->setType((*componentFIG0_13)->packet.appType); - if (app->typeLow == FIG0_13_APPTYPE_EPG) { - app->length = 2; - app->xpad = htons(0x0100); - /* xpad used to hold two bytes of EPG profile information - 01 = basic profile - 00 = list terminator */ - } - else { - app->length = 0; + info->No = num_apps; + buf += sizeof(FIG0_13_longAppInfo); + remaining -= sizeof(FIG0_13_longAppInfo); + fig0->Length += sizeof(FIG0_13_longAppInfo); + + for (const auto& ua : (*componentFIG0_13)->audio.uaTypes) { + FIG0_13_app* app = (FIG0_13_app*)buf; + app->setType(ua.uaType); + + size_t effective_length = sizeof(FIG0_13_app); + + if (ua.uaType == FIG0_13_APPTYPE_SPI) { + // TODO This should probably be user configurable... + app->length = app_length; + app->xpad = htons(0x0100); + /* xpad is actually not the "X-PAD data" as in Figure 25, but is the actual user application data. + * We just recycle the same structure, even though it's a bit ugly. + * It holds two bytes of EPG profile information: + * 01 = basic profile + * 00 = list terminator */ + } + else { + app->length = 0; + effective_length = 1; // FIG0_13_app without xpad + } + + buf += effective_length; + remaining -= effective_length; + fig0->Length += effective_length; } - buf += 2 + app->length; - remaining -= 2 + app->length; - fig0->Length += 2 + app->length; } } |