diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-01-06 16:22:40 +0100 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-01-06 16:22:40 +0100 | 
| commit | 2dac8f5fa6d63a71a726ec373af9bf45f22de8b7 (patch) | |
| tree | 3ba060598ad471018d324dff427490ab681c57df | |
| parent | 3633bcc99aedda5d9ea36c143fa339139c763d3e (diff) | |
| download | dabmod-2dac8f5fa6d63a71a726ec373af9bf45f22de8b7.tar.gz dabmod-2dac8f5fa6d63a71a726ec373af9bf45f22de8b7.tar.bz2 dabmod-2dac8f5fa6d63a71a726ec373af9bf45f22de8b7.zip | |
EDI: handle pseq resync and SIGINT
| -rw-r--r-- | lib/edi/ETIDecoder.cpp | 2 | ||||
| -rw-r--r-- | lib/edi/PFT.cpp | 43 | ||||
| -rw-r--r-- | lib/edi/PFT.hpp | 15 | ||||
| -rw-r--r-- | src/DabMod.cpp | 69 | ||||
| -rw-r--r-- | src/EtiReader.cpp | 16 | ||||
| -rw-r--r-- | src/EtiReader.h | 6 | 
6 files changed, 78 insertions, 73 deletions
| diff --git a/lib/edi/ETIDecoder.cpp b/lib/edi/ETIDecoder.cpp index baede11..939706b 100644 --- a/lib/edi/ETIDecoder.cpp +++ b/lib/edi/ETIDecoder.cpp @@ -331,7 +331,6 @@ bool ETIDecoder::decode_deti(const vector<uint8_t> &value)                 to_string(expected_length));      } -    etiLog.level(debug) << "EDI DETI";      m_data_collector.update_err(stat);      m_data_collector.update_mnsc(mnsc); @@ -402,7 +401,6 @@ bool ETIDecoder::decode_estn(const vector<uint8_t> &value, uint8_t n)              value.end(),              back_inserter(stc.mst)); -    etiLog.level(debug) << "EDI ESTn " << (int)stc.stream_index;      m_data_collector.add_subchannel(stc);      return true; diff --git a/lib/edi/PFT.cpp b/lib/edi/PFT.cpp index fa5840c..4bd1030 100644 --- a/lib/edi/PFT.cpp +++ b/lib/edi/PFT.cpp @@ -1,6 +1,6 @@  /* ------------------------------------------------------------------   * Copyright (C) 2017 AVT GmbH - Fabien Vercasson - * Copyright (C) 2016 Matthias P. Braendli + * Copyright (C) 2017 Matthias P. Braendli   *                    matthias.braendli@mpb.li   *   * http://opendigitalradio.org @@ -35,7 +35,6 @@ extern "C" {  }  namespace EdiDecoder { -  namespace PFT {  using namespace std; @@ -191,10 +190,11 @@ size_t Fragment::loadData(const std::vector<uint8_t> &buf)  } -AFBuilder::AFBuilder(pseq_t Pseq, findex_t Fcount, int lifetime) +AFBuilder::AFBuilder(pseq_t Pseq, findex_t Fcount, size_t lifetime)  {      _Pseq = Pseq;      _Fcount = Fcount; +    assert(lifetime > 0);      lifeTime = lifetime;  } @@ -459,7 +459,7 @@ void PFT::pushPFTFrag(const Fragment &fragment)          // The AFBuilder wants to know the lifetime in number of fragments,          // we know the delay in number of AF packets. Every AF packet          // is cut into Fcount fragments. -        const int lifetime = fragment.Fcount() * m_max_delay; +        const size_t lifetime = fragment.Fcount() * m_max_delay;          // Build the afbuilder in the map in-place          m_afbuilders.emplace(std::piecewise_construct, @@ -485,26 +485,34 @@ void PFT::pushPFTFrag(const Fragment &fragment)  std::vector<uint8_t> PFT::getNextAFPacket()  {      if (m_afbuilders.count(m_next_pseq) == 0) { -        assert(m_afbuilders.empty()); +        if (m_afbuilders.size() > m_max_delay) { +            m_afbuilders.clear(); +            etiLog.level(debug) << " Reinit"; +        } +          return {};      }      auto &builder = m_afbuilders.at(m_next_pseq); -    //const auto lt = builder.lifeTime;      //const auto nf = builder.numberOfFragments();      using dar_t = AFBuilder::decode_attempt_result_t;      if (builder.canAttemptToDecode() == dar_t::yes) { -        //etiLog.log(debug, "pseq %d (%d %d/%d) yes\n", m_next_pseq, lt, nf.first, nf.second); +        //etiLog.log(debug, "pseq %d (%d %d/%d) yes\n", +        //           m_next_pseq, lt, nf.first, nf.second);          auto afpacket = builder.extractAF();          assert(not afpacket.empty());          incrementNextPseq();          return afpacket;      }      else if (builder.canAttemptToDecode() == dar_t::maybe) { -        //etiLog.log(debug, "pseq %d (%d %d/%d) maybe\n", m_next_pseq, lt, nf.first, nf.second); -        builder.lifeTime--; +        //etiLog.log(debug, "pseq %d (%d %d/%d) maybe\n", +        //           m_next_pseq, lt, nf.first, nf.second); +        if (builder.lifeTime > 0) { +            builder.lifeTime--; +        } +          if (builder.lifeTime == 0) {              // Attempt Reed-Solomon decoding              auto afpacket = builder.extractAF(); @@ -517,8 +525,12 @@ std::vector<uint8_t> PFT::getNextAFPacket()          }      }      else { -        //etiLog.log(debug, "pseq %d (%d %d/%d) no\n", m_next_pseq, lt, nf.first, nf.second); -        builder.lifeTime--; +        //etiLog.log(debug, "pseq %d (%d %d/%d) no\n", +        //           m_next_pseq, lt, nf.first, nf.second); +        if (builder.lifeTime > 0) { +            builder.lifeTime--; +        } +          if (builder.lifeTime == 0) {              etiLog.log(debug, "pseq %d timed out\n", m_next_pseq);              incrementNextPseq(); @@ -528,17 +540,11 @@ std::vector<uint8_t> PFT::getNextAFPacket()      return {};  } -void PFT::setMaxDelay(int num_af_packets) +void PFT::setMaxDelay(size_t num_af_packets)  {      m_max_delay = num_af_packets;  } -bool PFT::isPacketBuildable(pseq_t pseq) const -{ -    return m_afbuilders.count(pseq) > 0 and -        not m_afbuilders.at(pseq).extractAF().empty(); -} -  void PFT::incrementNextPseq()  {      if (m_afbuilders.count(m_next_pseq - NUM_AFBUILDERS_TO_KEEP) > 0) { @@ -549,5 +555,4 @@ void PFT::incrementNextPseq()  }  } -  } diff --git a/lib/edi/PFT.hpp b/lib/edi/PFT.hpp index 9ab14ae..9fb96a7 100644 --- a/lib/edi/PFT.hpp +++ b/lib/edi/PFT.hpp @@ -1,6 +1,6 @@  /* ------------------------------------------------------------------   * Copyright (C) 2017 AVT GmbH - Fabien Vercasson - * Copyright (C) 2016 Matthias P. Braendli + * Copyright (C) 2017 Matthias P. Braendli   *                    matthias.braendli@mpb.li   *   * http://opendigitalradio.org @@ -22,7 +22,6 @@  #pragma once  #include <stdio.h> -#include <cassert>  #include <vector>  #include <map>  #include <stdint.h> @@ -84,7 +83,7 @@ class AFBuilder              no,    // Not enough fragments present to permit RS          }; -        AFBuilder(pseq_t Pseq, findex_t Fcount, int lifetime); +        AFBuilder(pseq_t Pseq, findex_t Fcount, size_t lifetime);          void pushPFTFrag(const Fragment &frag); @@ -105,7 +104,7 @@ class AFBuilder          /* The user of this instance can keep track of the lifetime of this           * builder           */ -        int lifeTime; +        size_t lifeTime;      private: @@ -125,7 +124,7 @@ class PFT          void pushPFTFrag(const Fragment &fragment);          /* Try to build the AF packet for the next pseq. This might -         * skip one pseq according to the maximum delay setting. +         * skip one or more pseq according to the maximum delay setting.           *           * \return an empty vector if building the AF is not possible           */ @@ -134,15 +133,13 @@ class PFT          /* Set the maximum delay in number of AF Packets before we           * abandon decoding a given pseq.           */ -        void setMaxDelay(int num_af_packets); +        void setMaxDelay(size_t num_af_packets);      private: -        bool isPacketBuildable(pseq_t pseq) const; -          void incrementNextPseq(void);          pseq_t m_next_pseq; -        int m_max_delay = 10; +        size_t m_max_delay = 10;          // Keep one AFBuilder for each Pseq          std::map<pseq_t, AFBuilder> m_afbuilders; diff --git a/src/DabMod.cpp b/src/DabMod.cpp index e48e748..a5c0de6 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -3,7 +3,7 @@     Her Majesty the Queen in Right of Canada (Communications Research     Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2017     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -777,51 +777,46 @@ int launch_modulator(int argc, char* argv[])      set_thread_name("modulator");      if (ediUdpInput.isEnabled()) { -        while (run_again) { -            Flowgraph flowgraph; +        Flowgraph flowgraph; -            etiLog.level(debug) << "Build mod"; -            auto modulator = make_shared<DabModulator>( -                    ediReader, tiiConfig, outputRate, clockRate, -                    dabMode, gainMode, digitalgain, normalise, -                    filterTapsFilename); - -            etiLog.level(debug) << "Connect"; -            if (format_converter) { -                flowgraph.connect(modulator, format_converter); -                flowgraph.connect(format_converter, output); -            } -            else { -                flowgraph.connect(modulator, output); -            } +        auto modulator = make_shared<DabModulator>( +                ediReader, tiiConfig, outputRate, clockRate, +                dabMode, gainMode, digitalgain, normalise, +                filterTapsFilename); -            etiLog.level(debug) << "SetETISource"; +        if (format_converter) { +            flowgraph.connect(modulator, format_converter); +            flowgraph.connect(format_converter, output); +        } +        else { +            flowgraph.connect(modulator, output); +        }  #if defined(HAVE_OUTPUT_UHD) -            if (useUHDOutput) { -                ((OutputUHD*)output.get())->setETISource(modulator->getEtiSource()); -            } +        if (useUHDOutput) { +            ((OutputUHD*)output.get())->setETISource(modulator->getEtiSource()); +        }  #endif -            etiLog.level(debug) << "Loop"; -            size_t framecount = 0; -            while (true) { -                while (not ediReader.isFrameReady()) { -                    ediUdpInput.rxPacket(); -                } -                etiLog.level(debug) << "Frame Ready"; -                framecount++; -                flowgraph.run(); -                etiLog.level(debug) << "now clear"; -                ediReader.clearFrame(); - -                /* Check every once in a while if the remote control -                 * is still working */ -                if ((framecount % 250) == 0) { -                    rcs.check_faults(); +        size_t framecount = 0; +        bool running = true; +        while (running) { +            while (not ediReader.isFrameReady()) { +                bool success = ediUdpInput.rxPacket(); +                if (not success) { +                    running = false; +                    break;                  }              } +            framecount++; +            flowgraph.run(); +            ediReader.clearFrame(); +            /* Check every once in a while if the remote control +             * is still working */ +            if ((framecount % 250) == 0) { +                rcs.check_faults(); +            }          }      }      else { diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index 3207a1f..e646392 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -308,7 +308,6 @@ uint32_t EtiReader::getPPSOffset()  unsigned EdiReader::getMode()  {      if (not m_fc_valid) { -        assert(false);          throw std::runtime_error("Trying to access Mode before it is ready!");      }      return m_fc.mid; @@ -463,7 +462,6 @@ void EdiReader::add_subchannel(const EdiDecoder::eti_stc_data& stc)  void EdiReader::assemble()  { -    etiLog.level(debug) << "Calling assemble";      if (not m_proto_valid) {          throw std::logic_error("Cannot assemble EDI data before protocol");      } @@ -529,7 +527,7 @@ int EdiUdpInput::Open(const std::string& uri)      return ret;  } -void EdiUdpInput::rxPacket() +bool EdiUdpInput::rxPacket()  {      const size_t packsize = 8192;      UdpPacket packet(packsize); @@ -538,13 +536,21 @@ void EdiUdpInput::rxPacket()      if (ret == 0) {          const auto &buf = packet.getBuffer();          if (packet.getSize() == packsize) { -            fprintf(stderr, "Warning, possible UDP truncation\n"); +            etiLog.log(warn, "Warning, possible UDP truncation");          }          m_decoder.push_packet(buf); +        return true;      }      else { -        fprintf(stderr, "Socket error: %s\n", inetErrMsg); +        if (inetErrNo == EINTR) { +            return false; +        } +        else { +            stringstream ss; +            ss << "EDI UDP Socket error: " << inetErrMsg; +            throw std::runtime_error(ss.str()); +        }      }  } diff --git a/src/EtiReader.h b/src/EtiReader.h index 04d627d..78f0d3d 100644 --- a/src/EtiReader.h +++ b/src/EtiReader.h @@ -176,7 +176,11 @@ class EdiUdpInput {          bool isEnabled(void) const { return m_enabled; } -        void rxPacket(void); +        /* Receive a packet and give it to the decoder. Returns +         * true if a packet was received, false in case of socket +         * read was interrupted by a signal. +         */ +        bool rxPacket(void);      private:          bool m_enabled; | 
