diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fig/FIG0.cpp | 131 | ||||
| -rw-r--r-- | src/fig/FIGCarousel.cpp | 53 | 
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) {  | 
