summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2015-08-17 13:11:26 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2015-08-17 13:11:26 +0200
commitdbac3d701cded9545f555dde41d8e29a4d38c020 (patch)
tree3fde9ad808ee8a66d7f614f134254527a19988b4
parent2edd4076bc0e55177cedc57945b780dc35c9938f (diff)
downloaddabmux-dbac3d701cded9545f555dde41d8e29a4d38c020.tar.gz
dabmux-dbac3d701cded9545f555dde41d8e29a4d38c020.tar.bz2
dabmux-dbac3d701cded9545f555dde41d8e29a4d38c020.zip
FIG Carousel fixes
Respect remaining size also for header insertion, solves a bug. Make sure FIGs don't insert only a header and then run out of remaining space. Make warning message more explicit. FIX FIG0/3 for non-program services.
-rw-r--r--src/fig/FIG0.cpp131
-rw-r--r--src/fig/FIGCarousel.cpp53
2 files changed, 116 insertions, 68 deletions
diff --git a/src/fig/FIG0.cpp b/src/fig/FIG0.cpp
index 9d728dd..57321ed 100644
--- a/src/fig/FIG0.cpp
+++ b/src/fig/FIG0.cpp
@@ -87,17 +87,7 @@ FillStatus FIG0_1::fill(uint8_t *buf, size_t max_size)
auto ensemble = m_rti->ensemble;
- FIGtype0_1 *figtype0_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;
+ FIGtype0_1 *figtype0_1 = NULL;
// Rotate through the subchannels until there is no more
// space in the FIG0/1
@@ -105,7 +95,24 @@ FillStatus FIG0_1::fill(uint8_t *buf, size_t max_size)
++subchannelFIG0_1) {
dabProtection* protection = &(*subchannelFIG0_1)->protection;
- if ( (protection->form == UEP && remaining < 3) ||
+ if (figtype0_1 == NULL) {
+ if ( (protection->form == UEP && remaining < 2 + 3) ||
+ (protection->form == EEP && remaining < 2 + 4) ) {
+ break;
+ }
+
+ 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;
+ }
+ else if ( (protection->form == UEP && remaining < 3) ||
(protection->form == EEP && remaining < 4) ) {
break;
}
@@ -205,7 +212,14 @@ FillStatus FIG0_2::fill(uint8_t *buf, size_t max_size)
++cur;
+ const int required_size = (type == subchannel_type_t::Audio) ?
+ 3 + 2 * (*serviceFIG0_2)->nbComponent(ensemble->components) :
+ 5 + 2 * (*serviceFIG0_2)->nbComponent(ensemble->components);
+
if (fig0_2 == NULL) {
+ if (remaining < 2 + required_size) {
+ break;
+ }
fig0_2 = (FIGtype0_2 *)buf;
fig0_2->FIGtypeNumber = 0;
@@ -217,16 +231,7 @@ FillStatus FIG0_2::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
-
- if (type == subchannel_type_t::Audio and
- remaining < 3 + 2 *
- (*serviceFIG0_2)->nbComponent(ensemble->components)) {
- break;
- }
-
- if (type != subchannel_type_t::Audio and
- remaining < 5 + 2 *
- (*serviceFIG0_2)->nbComponent(ensemble->components)) {
+ else if (remaining < required_size) {
break;
}
@@ -350,6 +355,7 @@ FillStatus FIG0_3::fill(uint8_t *buf, size_t max_size)
FIGtype0_3_header *fig0_3_header = NULL;
FIGtype0_3_data *fig0_3_data = NULL;
+ // TODO: implement component carousel
for (auto& component : ensemble->components) {
auto subchannel = getSubchannel(ensemble->subchannels,
component->subchId);
@@ -454,10 +460,14 @@ FillStatus FIG0_8::fill(uint8_t *buf, size_t max_size)
throw MuxInitException();
}
- if (!(*service)->program)
- continue;
+ const int required_size = (*service)->program ?
+ ((*subchannel)->type == subchannel_type_t::Packet ? 5 : 4) :
+ ((*subchannel)->type == subchannel_type_t::Packet ? 7 : 6);
if (fig0 == NULL) {
+ if (remaining < 2 + required_size) {
+ break;
+ }
fig0 = (FIGtype0*)buf;
fig0->FIGtypeNumber = 0;
fig0->Length = 1;
@@ -468,12 +478,12 @@ FillStatus FIG0_8::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
+ else if (remaining < required_size) {
+ break;
+ }
if ((*service)->program) {
if ((*subchannel)->type == subchannel_type_t::Packet) { // Data packet
- if (remaining < 5) {
- break;
- }
buf[0] = ((*componentFIG0_8)->serviceId >> 8) & 0xFF;
buf[1] = ((*componentFIG0_8)->serviceId) & 0xFF;
fig0->Length += 2;
@@ -491,9 +501,6 @@ FillStatus FIG0_8::fill(uint8_t *buf, size_t max_size)
remaining -= 3;
}
else { // Audio, data stream or FIDC
- if (remaining < 4) {
- break;
- }
buf[0] = ((*componentFIG0_8)->serviceId >> 8) & 0xFF;
buf[1] = ((*componentFIG0_8)->serviceId) & 0xFF;
@@ -515,9 +522,6 @@ FillStatus FIG0_8::fill(uint8_t *buf, size_t max_size)
}
else { // Data
if ((*subchannel)->type == subchannel_type_t::Packet) { // Data packet
- if (remaining < 7) {
- break;
- }
buf[0] = ((*componentFIG0_8)->serviceId >> 8) & 0xFF;
buf[1] = ((*componentFIG0_8)->serviceId) & 0xFF;
fig0->Length += 4;
@@ -535,9 +539,6 @@ FillStatus FIG0_8::fill(uint8_t *buf, size_t max_size)
remaining -= 3;
}
else { // Audio, data stream or FIDC
- if (remaining < 6 ) {
- break;
- }
buf[0] = ((*componentFIG0_8)->serviceId >> 8) & 0xFF;
buf[1] = ((*componentFIG0_8)->serviceId) & 0xFF;
fig0->Length += 4;
@@ -675,6 +676,7 @@ FillStatus FIG0_10::fill(uint8_t *buf, size_t max_size)
fig0_10->PD = 0;
fig0_10->Extension = 10;
buf += 2;
+ remaining -= 2;
tm* timeData;
timeData = gmtime(&m_rti->date);
@@ -693,7 +695,7 @@ FillStatus FIG0_10::fill(uint8_t *buf, size_t max_size)
fig0_10->setHours(timeData->tm_hour);
fig0_10->Minutes = timeData->tm_min;
buf += 4;
- remaining -= 6;
+ remaining -= 4;
fs.num_bytes_written = max_size - remaining;
fs.complete_fig_transmitted = true;
@@ -740,7 +742,13 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size)
if ( m_transmit_programme &&
(*subchannel)->type == subchannel_type_t::Audio &&
(*componentFIG0_13)->audio.uaType != 0xffff) {
+
+ const int required_size = 3+4+11;
+
if (fig0 == NULL) {
+ if (remaining < 2 + required_size) {
+ break;
+ }
fig0 = (FIGtype0*)buf;
fig0->FIGtypeNumber = 0;
fig0->Length = 1;
@@ -751,8 +759,7 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
-
- if (remaining < 3+4+11) {
+ else if (remaining < required_size) {
break;
}
@@ -786,7 +793,12 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size)
(*subchannel)->type == subchannel_type_t::Packet &&
(*componentFIG0_13)->packet.appType != 0xffff) {
+ const int required_size = 5+2;
+
if (fig0 == NULL) {
+ if (remaining < 2 + required_size) {
+ break;
+ }
fig0 = (FIGtype0*)buf;
fig0->FIGtypeNumber = 0;
fig0->Length = 1;
@@ -797,8 +809,7 @@ FillStatus FIG0_13::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
-
- if (remaining < 5+2) {
+ else if (remaining < required_size) {
break;
}
@@ -865,7 +876,13 @@ FillStatus FIG0_17::fill(uint8_t *buf, size_t max_size)
continue;
}
+ const int required_size = (*serviceFIG0_17)->language == 0 ? 4 : 5;
+
+
if (fig0 == NULL) {
+ if (remaining < 2 + required_size) {
+ break;
+ }
fig0 = (FIGtype0*)buf;
fig0->FIGtypeNumber = 0;
fig0->Length = 1;
@@ -876,16 +893,8 @@ FillStatus FIG0_17::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
-
- if ((*serviceFIG0_17)->language == 0) {
- if (remaining < 4) {
- break;
- }
- }
- else {
- if (remaining < 5) {
- break;
- }
+ else if (remaining < required_size) {
+ break;
}
auto programme = (FIGtype0_17_programme*)buf;
@@ -951,12 +960,11 @@ FillStatus FIG0_18::fill(uint8_t *buf, size_t max_size)
const ssize_t numclusters = (*service)->clusters.size();
- if (remaining < 5 + numclusters) {
- break;
- }
+ const int required_size = 5 + numclusters;
+
if (fig0 == NULL) {
- if (remaining < 2 + 5 + numclusters) {
+ if (remaining < 2 + required_size) {
break;
}
@@ -970,6 +978,9 @@ FillStatus FIG0_18::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
+ else if (remaining < required_size) {
+ break;
+ }
auto programme = (FIGtype0_18*)buf;
programme->SId = htons((*service)->id);
@@ -1030,11 +1041,6 @@ FillStatus FIG0_19::fill(uint8_t *buf, size_t max_size)
fs.complete_fig_transmitted = true;
for (const auto& cluster : allclusters) {
- if (remaining < length_0_19) {
- fs.complete_fig_transmitted = false;
- break;
- }
-
if (fig0 == NULL) {
if (remaining < 2 + length_0_19) {
fs.complete_fig_transmitted = false;
@@ -1051,6 +1057,11 @@ FillStatus FIG0_19::fill(uint8_t *buf, size_t max_size)
buf += 2;
remaining -= 2;
}
+ else if (remaining < length_0_19) {
+ fs.complete_fig_transmitted = false;
+ break;
+ }
+
auto fig0_19 = (FIGtype0_19*)buf;
fig0_19->ClusterId = cluster->cluster_id;
diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp
index d565c23..1d79f2d 100644
--- a/src/fig/FIGCarousel.cpp
+++ b/src/fig/FIGCarousel.cpp
@@ -32,6 +32,8 @@
#include <iostream>
#include <deque>
+#define CAROUSELDEBUG 0
+
namespace FIC {
/**************** FIGCarouselElement ****************/
@@ -40,8 +42,8 @@ void FIGCarouselElement::reduce_deadline()
deadline -= 24; //ms
if (deadline < 0) {
- etiLog.level(warn) << "FIG " << fig->name() <<
- " has negative scheduling deadline";
+ etiLog.level(warn) << "Could not respect repetition rate for FIG " <<
+ fig->name() << " (" << deadline << "ms late)";
}
}
@@ -160,13 +162,14 @@ size_t FIGCarousel::carousel(
return left->deadline < right->deadline;
});
- /* Carousel debugging help
- std::cerr << " Sorted figs in FIB" << fib << ":" << std::endl;
+#if CAROUSELDEBUG
+ // Carousel debugging help
+ std::cerr << " ***** Sorted figs in FIB" << fib << ":" << std::endl;
for (auto& fig_el : sorted_figs) {
std::cerr << " " << fig_el->fig->name() <<
" d:" << fig_el->deadline << std::endl;
}
- // */
+#endif
/* Data structure to carry FIB */
size_t available_size = bufsize;
@@ -178,8 +181,6 @@ size_t FIGCarousel::carousel(
});
if (fig0_0 != sorted_figs.end()) {
- sorted_figs.erase(fig0_0);
-
if (framephase == 0) { // TODO check for all TM
FillStatus status = (*fig0_0)->fig->fill(pbuf, available_size);
size_t written = status.num_bytes_written;
@@ -187,6 +188,24 @@ size_t FIGCarousel::carousel(
if (written > 0) {
available_size -= written;
pbuf += written;
+
+#if CAROUSELDEBUG
+ std::cerr << " ****** FIG0/0 wrote\t" << written << " bytes"
+ << std::endl;
+
+ if ( (*fig0_0)->fig->figtype() != 0 or
+ (*fig0_0)->fig->figextension() != 0 or
+ written != 6) {
+
+ std::stringstream ss;
+ ss << "Assertion error: FIG 0/0 is actually " <<
+ (*fig0_0)->fig->figtype()
+ << "/" << (*fig0_0)->fig->figextension() <<
+ " and wrote " << written << " bytes";
+
+ throw std::runtime_error(ss.str());
+ }
+#endif
}
else {
throw std::runtime_error("Failed to write FIG0/0");
@@ -196,6 +215,8 @@ size_t FIGCarousel::carousel(
(*fig0_0)->increase_deadline();
}
}
+
+ sorted_figs.erase(fig0_0);
}
@@ -205,9 +226,25 @@ size_t FIGCarousel::carousel(
FillStatus status = fig_el->fig->fill(pbuf, available_size);
size_t written = status.num_bytes_written;
- if (written > 0) {
+ // If exactly two bytes were written, it's because the FIG did
+ // only write the header, but no content.
+ // Writing only one byte is not allowed
+ if (written == 1 or written == 2) {
+ std::stringstream ss;
+ ss << "Assertion error: FIG" << fig_el->fig->figtype() << "/" <<
+ fig_el->fig->figextension() << " wrote not enough data (" <<
+ written << ")";
+ throw std::runtime_error(ss.str());
+ }
+
+ 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;
+#endif
}
if (status.complete_fig_transmitted) {