diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-01-07 08:49:29 +0100 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-01-07 08:49:29 +0100 | 
| commit | 1d833b718845b97a5b1d90f33b547b1772bc0708 (patch) | |
| tree | bd34f1a8d25e150858e3bba5cbc7c0915d23f948 | |
| parent | 1dadf3b7856940911724d02613085d57535da474 (diff) | |
| download | dabmod-1d833b718845b97a5b1d90f33b547b1772bc0708.tar.gz dabmod-1d833b718845b97a5b1d90f33b547b1772bc0708.tar.bz2 dabmod-1d833b718845b97a5b1d90f33b547b1772bc0708.zip | |
Add new flowgraph path for metadata
| -rw-r--r-- | src/BlockPartitioner.cpp | 45 | ||||
| -rw-r--r-- | src/BlockPartitioner.h | 21 | ||||
| -rw-r--r-- | src/DabModulator.cpp | 13 | ||||
| -rw-r--r-- | src/DabModulator.h | 9 | ||||
| -rw-r--r-- | src/EtiReader.cpp | 7 | ||||
| -rw-r--r-- | src/FicSource.cpp | 24 | ||||
| -rw-r--r-- | src/FicSource.h | 11 | ||||
| -rw-r--r-- | src/Flowgraph.cpp | 68 | ||||
| -rw-r--r-- | src/Flowgraph.h | 14 | ||||
| -rw-r--r-- | src/ModPlugin.h | 17 | ||||
| -rw-r--r-- | src/OutputFile.cpp | 56 | ||||
| -rw-r--r-- | src/OutputFile.h | 22 | ||||
| -rw-r--r-- | src/OutputMemory.cpp | 14 | ||||
| -rw-r--r-- | src/OutputMemory.h | 16 | ||||
| -rw-r--r-- | src/TimestampDecoder.cpp | 48 | ||||
| -rw-r--r-- | src/TimestampDecoder.h | 71 | 
16 files changed, 341 insertions, 115 deletions
| diff --git a/src/BlockPartitioner.cpp b/src/BlockPartitioner.cpp index 9e9f80b..54405d9 100644 --- a/src/BlockPartitioner.cpp +++ b/src/BlockPartitioner.cpp @@ -1,6 +1,11 @@  /*     Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty     the Queen in Right of Canada (Communications Research Center Canada) + +   Copyright (C) 2018 +   Matthias P. Braendli, matthias.braendli@mpb.li + +    http://opendigitalradio.org   */  /*     This file is part of ODR-DabMod. @@ -21,6 +26,8 @@  #include "BlockPartitioner.h"  #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h"  #include <stdio.h>  #include <stdexcept> @@ -31,6 +38,7 @@  BlockPartitioner::BlockPartitioner(unsigned mode, unsigned phase) :      ModMux(), +    ModMetadata(),      d_mode(mode)  {      PDEBUG("BlockPartitioner::BlockPartitioner(%i)\n", mode); @@ -68,17 +76,11 @@ BlockPartitioner::BlockPartitioner(unsigned mode, unsigned phase) :      d_cifNb = 0;      // For Synchronisation purpose, count nb of CIF to drop      d_cifPhase = phase % d_cifCount; +    d_metaPhase = phase % d_cifCount;      d_cifSize = 864 * 8;  } -BlockPartitioner::~BlockPartitioner() -{ -    PDEBUG("BlockPartitioner::~BlockPartitioner()\n"); - -} - -  // dataIn[0] -> FIC  // dataIn[1] -> CIF  int BlockPartitioner::process(std::vector<Buffer*> dataIn, Buffer* dataOut) @@ -124,10 +126,10 @@ int BlockPartitioner::process(std::vector<Buffer*> dataIn, Buffer* dataOut)      uint8_t* out = reinterpret_cast<uint8_t*>(dataOut->getData());      // Copy FIC data -    PDEBUG("Writting FIC %zu bytes to %zu\n", d_ficSize, d_cifNb * d_ficSize); +    PDEBUG("Writing FIC %zu bytes to %zu\n", d_ficSize, d_cifNb * d_ficSize);      memcpy(out + (d_cifNb * d_ficSize), fic, d_ficSize);      // Copy CIF data -    PDEBUG("Writting CIF %u bytes to %zu\n", 864 * 8, +    PDEBUG("Writing CIF %u bytes to %zu\n", 864 * 8,              (d_cifCount * d_ficSize) + (d_cifNb * 864 * 8));      memcpy(out + (d_cifCount * d_ficSize) + (d_cifNb * 864 * 8), cif, 864 * 8); @@ -137,3 +139,28 @@ int BlockPartitioner::process(std::vector<Buffer*> dataIn, Buffer* dataOut)      return d_cifNb == 0;  } + +meta_vec_t BlockPartitioner::process_metadata(const meta_vec_t& metadataIn) +{ +    // Synchronize CIF phase +    if (d_metaPhase != 0) { +        if (++d_metaPhase == d_cifCount) { +            d_metaPhase = 0; +        } +        // Drop this metadata +        return {}; +    } + +    if (d_cifNb == 1) { +        d_meta.clear(); +    } + +    std::copy(metadataIn.begin(), metadataIn.end(), std::back_inserter(d_meta)); + +    if (d_cifNb == 0) { +        return d_meta; +    } +    else { +        return {}; +    } +} diff --git a/src/BlockPartitioner.h b/src/BlockPartitioner.h index 90cffa3..a4656a1 100644 --- a/src/BlockPartitioner.h +++ b/src/BlockPartitioner.h @@ -1,6 +1,11 @@  /*     Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty     the Queen in Right of Canada (Communications Research Center Canada) + +   Copyright (C) 2018 +   Matthias P. Braendli, matthias.braendli@mpb.li + +    http://opendigitalradio.org   */  /*     This file is part of ODR-DabMod. @@ -25,32 +30,32 @@  #   include <config.h>  #endif -  #include "ModPlugin.h"  #include <vector> +#include <cstddef> -#include <sys/types.h> - - -class BlockPartitioner : public ModMux +class BlockPartitioner : public ModMux, public ModMetadata  {  public:      BlockPartitioner(unsigned mode, unsigned phase); -    virtual ~BlockPartitioner(); -    BlockPartitioner(const BlockPartitioner&); -    BlockPartitioner& operator=(const BlockPartitioner&);      int process(std::vector<Buffer*> dataIn, Buffer* dataOut);      const char* name() { return "BlockPartitioner"; } +    // The implementation assumes process_metadata is always called after process +    virtual meta_vec_t process_metadata(const meta_vec_t& metadataIn); +  protected:      int d_mode;      size_t d_ficSize;      size_t d_cifCount;      size_t d_cifNb;      size_t d_cifPhase; +    size_t d_metaPhase;      size_t d_cifSize;      size_t d_outputFramesize;      size_t d_outputFramecount; + +    meta_vec_t d_meta;  }; diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 0818f4f..f1ea071 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -3,7 +3,7 @@     Her Majesty the Queen in Right of Canada (Communications Research     Center Canada) -   Copyright (C) 2017 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -218,7 +218,7 @@ int DabModulator::process(Buffer* dataOut)              rcs.enrol(cifPoly.get());          } -        auto myOutput = make_shared<OutputMemory>(dataOut); +        myOutput = make_shared<OutputMemory>(dataOut);          shared_ptr<Resampler> cifRes;          if (m_settings.outputRate != 2048000) { @@ -392,3 +392,12 @@ int DabModulator::process(Buffer* dataOut)      return myFlowgraph->run();  } +meta_vec_t DabModulator::process_metadata(const meta_vec_t& metadataIn) +{ +    if (myOutput) { +        return myOutput->get_latest_metadata(); +    } + +    return {}; +} + diff --git a/src/DabModulator.h b/src/DabModulator.h index 6878853..e806c92 100644 --- a/src/DabModulator.h +++ b/src/DabModulator.h @@ -3,7 +3,7 @@     Her Majesty the Queen in Right of Canada (Communications Research     Center Canada) -   Copyright (C) 2017 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -46,7 +46,7 @@  #include "TII.h" -class DabModulator : public ModInput +class DabModulator : public ModInput, public ModMetadata  {  public:      DabModulator(EtiSource& etiSource, @@ -55,6 +55,9 @@ public:      int process(Buffer* dataOut);      const char* name() { return "DabModulator"; } +    virtual meta_vec_t process_metadata( +            const meta_vec_t& metadataIn); +      /* Required to get the timestamp */      EtiSource* getEtiSource() { return &myEtiSource; } @@ -73,5 +76,7 @@ protected:      size_t mySymSize;      size_t myFicSizeOut;      size_t myFicSizeIn; + +    std::shared_ptr<OutputMemory> myOutput;  }; diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index d84ed1f..dc5df84 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -281,6 +281,8 @@ int EtiReader::loadEtiData(const Buffer& dataIn)      myTimestampDecoder.updateTimestampEti(eti_fc.FP & 0x3,              eti_eoh.MNSC, getPPSOffset(), eti_fc.FCT); +    myFicSource->loadTimestamp(myTimestampDecoder.getTimestamp()); +      return dataIn.getLength() - input_size;  } @@ -533,8 +535,9 @@ void EdiReader::assemble()      const std::time_t posix_timestamp_1_jan_2000 = 946684800;      auto utc_ts = posix_timestamp_1_jan_2000 + m_seconds - m_utco; -    m_timestamp_decoder.updateTimestampEdi( -            utc_ts, m_fc.tsta, m_fc.fct()); +    m_timestamp_decoder.updateTimestampEdi(utc_ts, m_fc.tsta, m_fc.fct(), m_fc.fp); + +    myFicSource->loadTimestamp(m_timestamp_decoder.getTimestamp());      m_frameReady = true;  } diff --git a/src/FicSource.cpp b/src/FicSource.cpp index 04197db..2b95085 100644 --- a/src/FicSource.cpp +++ b/src/FicSource.cpp @@ -2,7 +2,7 @@     Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty     the Queen in Right of Canada (Communications Research Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -26,6 +26,8 @@  #include "FicSource.h"  #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h"  #include <stdexcept>  #include <string> @@ -92,3 +94,23 @@ int FicSource::process(Buffer* outputData)      return outputData->getLength();  } +void FicSource::loadTimestamp(const std::shared_ptr<struct frame_timestamp>& ts) +{ +    d_ts = ts; +} + + +meta_vec_t FicSource::process_metadata(const meta_vec_t& metadataIn) +{ +    if (not d_ts) { +        return {}; +    } + +    using namespace std; +    meta_vec_t md_vec; +    flowgraph_metadata meta; +    meta.ts = d_ts; +    md_vec.push_back(meta); +    return md_vec; +} + diff --git a/src/FicSource.h b/src/FicSource.h index 77ac741..93c1a7f 100644 --- a/src/FicSource.h +++ b/src/FicSource.h @@ -36,7 +36,7 @@  #include <vector>  #include <sys/types.h> -class FicSource : public ModInput +class FicSource : public ModInput, public ModMetadata  {  public:      FicSource(unsigned ficf, unsigned mid); @@ -45,12 +45,17 @@ public:      const std::vector<PuncturingRule>& get_rules();      void loadFicData(const Buffer& fic); -    int process(Buffer* outputData); -    const char* name() { return "FicSource"; } +    int process(Buffer* outputData) override; +    const char* name() override { return "FicSource"; } + +    void loadTimestamp(const std::shared_ptr<struct frame_timestamp>& ts); +    virtual meta_vec_t process_metadata( +            const meta_vec_t& metadataIn) override;  private:      size_t d_framesize;      Buffer d_buffer; +    std::shared_ptr<struct frame_timestamp> d_ts;      std::vector<PuncturingRule> d_puncturing_rules;  }; diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index 465ef41..0b80a8c 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -26,6 +26,8 @@  #include "Flowgraph.h"  #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h"  #include <string>  #include <memory>  #include <algorithm> @@ -57,9 +59,10 @@ Node::~Node()      assert(myOutputBuffers.size() == 0);  } -void Node::addOutputBuffer(Buffer::sptr& buffer) +void Node::addOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md)  {      myOutputBuffers.push_back(buffer); +    myOutputMetadata.push_back(md);  #if DEBUG      std::string fname = string(myPlugin->name()) +          "-" + to_string(myDebugFiles.size()) + @@ -71,7 +74,7 @@ void Node::addOutputBuffer(Buffer::sptr& buffer)  #endif  } -void Node::removeOutputBuffer(Buffer::sptr& buffer) +void Node::removeOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md)  {      auto it = std::find(              myOutputBuffers.begin(), @@ -89,14 +92,23 @@ void Node::removeOutputBuffer(Buffer::sptr& buffer)  #endif          myOutputBuffers.erase(it);      } + +    auto mdit = std::find( +            myOutputMetadata.begin(), +            myOutputMetadata.end(), +            md); +    if (mdit != myOutputMetadata.end()) { +        myOutputMetadata.erase(mdit); +    }  } -void Node::addInputBuffer(Buffer::sptr& buffer) +void Node::addInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md)  {      myInputBuffers.push_back(buffer); +    myInputMetadata.push_back(md);  } -void Node::removeInputBuffer(Buffer::sptr& buffer) +void Node::removeInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md)  {      auto it = std::find(              myInputBuffers.begin(), @@ -105,6 +117,14 @@ void Node::removeInputBuffer(Buffer::sptr& buffer)      if (it != myInputBuffers.end()) {          myInputBuffers.erase(it);      } + +    auto mdit = std::find( +            myInputMetadata.begin(), +            myInputMetadata.end(), +            md); +    if (mdit != myInputMetadata.end()) { +        myInputMetadata.erase(mdit); +    }  }  int Node::process() @@ -127,6 +147,36 @@ int Node::process()      }      int ret = myPlugin->process(inBuffers, outBuffers); + +    // Collect all incoming metadata into a single vector +    meta_vec_t all_input_mds; +    for (auto& md_vec_sp : myInputMetadata) { +        if (md_vec_sp) { +            copy(md_vec_sp->begin(), md_vec_sp->end(), +                    back_inserter(all_input_mds)); +        } +    } + +    auto mod_meta = dynamic_pointer_cast<ModMetadata>(myPlugin); +    if (mod_meta) { +        auto outputMetadata = mod_meta->process_metadata(all_input_mds); +        // Distribute the result metadata to all outputs +        for (auto& out_md : myOutputMetadata) { +            out_md->clear(); +            std::move(outputMetadata.begin(), outputMetadata.end(), +                    std::back_inserter(*out_md)); +        } +    } +    else { +        // Propagate the unmodified input metadata to all outputs +        for (auto& out_md : myOutputMetadata) { +            out_md->clear(); +            std::move(all_input_mds.begin(), all_input_mds.end(), +                    std::back_inserter(*out_md)); +        } +    } + +  #if DEBUG      assert(myDebugFiles.size() == myOutputBuffers.size()); @@ -158,8 +208,10 @@ Edge::Edge(shared_ptr<Node>& srcNode, shared_ptr<Node>& dstNode) :              this);      myBuffer = make_shared<Buffer>(); -    srcNode->addOutputBuffer(myBuffer); -    dstNode->addInputBuffer(myBuffer); +    myMetadata = make_shared<vector<flowgraph_metadata> >(); + +    srcNode->addOutputBuffer(myBuffer, myMetadata); +    dstNode->addInputBuffer(myBuffer, myMetadata);  } @@ -168,8 +220,8 @@ Edge::~Edge()      PDEBUG("Edge::~Edge() @ %p\n", this);      if (myBuffer) { -        mySrcNode->removeOutputBuffer(myBuffer); -        myDstNode->removeInputBuffer(myBuffer); +        mySrcNode->removeOutputBuffer(myBuffer, myMetadata); +        myDstNode->removeInputBuffer(myBuffer, myMetadata);      }  } diff --git a/src/Flowgraph.h b/src/Flowgraph.h index ebb7314..2742824 100644 --- a/src/Flowgraph.h +++ b/src/Flowgraph.h @@ -39,6 +39,8 @@  #include <list>  #include <cstdio> +using Metadata_vec_sptr = std::shared_ptr<std::vector<flowgraph_metadata> >; +  class Node  {  public: @@ -55,15 +57,18 @@ public:          myProcessTime += processTime;      } -    void addOutputBuffer(Buffer::sptr& buffer); -    void removeOutputBuffer(Buffer::sptr& buffer); +    void addOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); +    void removeOutputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); -    void addInputBuffer(Buffer::sptr& buffer); -    void removeInputBuffer(Buffer::sptr& buffer); +    void addInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md); +    void removeInputBuffer(Buffer::sptr& buffer, Metadata_vec_sptr& md);  protected:      std::list<Buffer::sptr> myInputBuffers;      std::list<Buffer::sptr> myOutputBuffers; +    std::list<Metadata_vec_sptr> myInputMetadata; +    std::list<Metadata_vec_sptr> myOutputMetadata; +  #if DEBUG      std::list<FILE*> myDebugFiles;  #endif @@ -85,6 +90,7 @@ protected:      std::shared_ptr<Node> mySrcNode;      std::shared_ptr<Node> myDstNode;      std::shared_ptr<Buffer> myBuffer; +    std::shared_ptr<std::vector<flowgraph_metadata> > myMetadata;  }; diff --git a/src/ModPlugin.h b/src/ModPlugin.h index d3aa780..3c3e8b3 100644 --- a/src/ModPlugin.h +++ b/src/ModPlugin.h @@ -119,3 +119,20 @@ public:              std::vector<Buffer*> dataOut);      virtual int process(Buffer* dataIn) = 0;  }; + +struct frame_timestamp; +struct flowgraph_metadata { +    std::shared_ptr<struct frame_timestamp> ts; +}; + + +using meta_vec_t = std::vector<flowgraph_metadata>; + +/* Some ModPlugins also support metadata */ +class ModMetadata { +    public: +        // Receives metadata from all inputs, and process them, and output +        // a sequence of metadata. +        virtual meta_vec_t process_metadata(const meta_vec_t& metadataIn) = 0; +}; + diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index 23d5523..3bb45c4 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -2,7 +2,7 @@     Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty     the Queen in Right of Canada (Communications Research Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -26,47 +26,73 @@  #include "OutputFile.h"  #include "PcDebug.h" +#include "Log.h" +#include "TimestampDecoder.h"  #include <string>  #include <assert.h>  #include <stdexcept> +using namespace std; +  OutputFile::OutputFile(std::string filename) :      ModOutput(), +    ModMetadata(),      myFilename(filename)  {      PDEBUG("OutputFile::OutputFile(filename: %s) @ %p\n",              filename.c_str(), this); -    myFile = fopen(filename.c_str(), "w"); -    if (myFile == NULL) { +    FILE* fd = fopen(filename.c_str(), "w"); +    if (fd == nullptr) {          perror(filename.c_str());          throw std::runtime_error(                  "OutputFile::OutputFile() unable to open file!");      } -} - - -OutputFile::~OutputFile() -{ -    PDEBUG("OutputFile::~OutputFile() @ %p\n", this); - -    if (myFile != NULL) { -        fclose(myFile); -    } +    myFile.reset(fd);  }  int OutputFile::process(Buffer* dataIn)  {      PDEBUG("OutputFile::process(%p)\n", dataIn); -    assert(dataIn != NULL); +    assert(dataIn != nullptr); -    if (fwrite(dataIn->getData(), dataIn->getLength(), 1, myFile) == 0) { +    if (fwrite(dataIn->getData(), dataIn->getLength(), 1, myFile.get()) == 0) {          throw std::runtime_error(                  "OutputFile::process() unable to write to file!");      }      return dataIn->getLength();  } + +meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) +{ +    stringstream ss; + +    if (metadataIn.empty()) { +        etiLog.level(debug) << "OutputFile: no mdIn"; +    } + +    for (const auto& md : metadataIn) { +        if (md.ts) { +            ss << "FCT=" << md.ts->fct << +                " FP=" << (int)md.ts->fp; +            if (md.ts->timestamp_valid) { +                ss << " ts=" << md.ts->timestamp_sec << +                    "+" << md.ts->timestamp_pps << ", "; +            } +            else { +                ss << " no ts"; +            } +        } +        else { +            ss << "void, "; +        } +    } + +    etiLog.level(debug) << "Output File got metadata: " << ss.str(); + +    return {}; +} diff --git a/src/OutputFile.h b/src/OutputFile.h index 7121ef3..2b92369 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -2,7 +2,7 @@     Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty     the Queen in Right of Canada (Communications Research Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -36,19 +36,29 @@  #include <string>  #include <stdio.h>  #include <sys/types.h> +#include <memory> +struct FILEDeleter { +    void operator()(FILE* fd) { +        if (fd) { +            fclose(fd); +        } +    } +}; -class OutputFile : public ModOutput +class OutputFile : public ModOutput, public ModMetadata  {  public:      OutputFile(std::string filename); -    virtual ~OutputFile(); -    virtual int process(Buffer* dataIn); -    const char* name() { return "OutputFile"; } +    virtual int process(Buffer* dataIn) override; +    const char* name() override { return "OutputFile"; } + +    virtual meta_vec_t process_metadata( +            const meta_vec_t& metadataIn) override;  protected:      std::string myFilename; -    FILE* myFile; +    std::unique_ptr<FILE, FILEDeleter> myFile;  }; diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index 6e2fd49..5f24095 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -2,7 +2,7 @@     Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in     Right of Canada (Communications Research Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -26,6 +26,7 @@  #include "OutputMemory.h"  #include "PcDebug.h" +#include "Log.h"  #include <stdexcept>  #include <string.h> @@ -94,3 +95,14 @@ int OutputMemory::process(Buffer* dataIn)      return myDataOut->getLength();  } +meta_vec_t OutputMemory::process_metadata(const meta_vec_t& metadataIn) +{ +    myMetadata = metadataIn; +    return {}; +} + +meta_vec_t OutputMemory::get_latest_metadata() +{ +    return myMetadata; +} + diff --git a/src/OutputMemory.h b/src/OutputMemory.h index 715cb2d..f0a5fbb 100644 --- a/src/OutputMemory.h +++ b/src/OutputMemory.h @@ -2,7 +2,7 @@     Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in     Right of Canada (Communications Research Center Canada) -   Copyright (C) 2016 +   Copyright (C) 2018     Matthias P. Braendli, matthias.braendli@mpb.li      http://opendigitalradio.org @@ -46,18 +46,26 @@  #include "ModPlugin.h" -class OutputMemory : public ModOutput +class OutputMemory : public ModOutput, public ModMetadata  {  public:      OutputMemory(Buffer* dataOut);      virtual ~OutputMemory(); -    virtual int process(Buffer* dataIn); -    const char* name() { return "OutputMemory"; } +    OutputMemory(OutputMemory& other) = delete; +    OutputMemory& operator=(OutputMemory& other) = delete; + +    virtual int process(Buffer* dataIn) override; +    const char* name() override { return "OutputMemory"; } +    virtual meta_vec_t process_metadata( +            const meta_vec_t& metadataIn) override; + +    meta_vec_t get_latest_metadata(void);      void setOutput(Buffer* dataOut);  protected:      Buffer* myDataOut; +    meta_vec_t myMetadata;  #if OUTPUT_MEM_HISTOGRAM      // keep track of max value diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index 26deb60..6cf2875 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -37,6 +37,22 @@  //#define MDEBUG(fmt, args...) fprintf (LOG, "*****" fmt , ## args)  #define MDEBUG(fmt, args...) PDEBUG(fmt, ## args) +TimestampDecoder::TimestampDecoder(double& offset_s, unsigned tist_delay_stages) : +        RemoteControllable("tist"), +        timestamp_offset(offset_s), +        m_tist_delay_stages(tist_delay_stages) +{ +    // Properly initialise temp_time +    memset(&temp_time, 0, sizeof(temp_time)); +    const time_t timep = 0; +    gmtime_r(&timep, &temp_time); + +    RC_ADD_PARAMETER(offset, "TIST offset [s]"); +    RC_ADD_PARAMETER(timestamp, "FCT and timestamp [s]"); + +    etiLog.level(info) << "Setting up timestamp decoder with " << +        timestamp_offset << " offset"; +}  void TimestampDecoder::calculateTimestamp(frame_timestamp& ts)  { @@ -48,6 +64,7 @@ void TimestampDecoder::calculateTimestamp(frame_timestamp& ts)      ts_queued->timestamp_sec = time_secs;      ts_queued->timestamp_pps = time_pps;      ts_queued->fct = latestFCT; +    ts_queued->fp = latestFP;      ts_queued->timestamp_refresh = offset_changed;      offset_changed = false; @@ -102,7 +119,29 @@ void TimestampDecoder::calculateTimestamp(frame_timestamp& ts)      //ts.print("calc2 ");  } -void TimestampDecoder::pushMNSCData(int framephase, uint16_t mnsc) +std::shared_ptr<frame_timestamp> TimestampDecoder::getTimestamp() +{ +    std::shared_ptr<frame_timestamp> ts = +        std::make_shared<frame_timestamp>(); + +    /* Push new timestamp into queue */ +    ts->timestamp_valid = full_timestamp_received; +    ts->timestamp_sec = time_secs; +    ts->timestamp_pps = time_pps; +    ts->fct = latestFCT; +    ts->fp = latestFP; + +    ts->timestamp_refresh = offset_changed; +    offset_changed = false; + +    MDEBUG("time_secs=%d, time_pps=%f\n", time_secs, +            (double)time_pps / 16384000.0); +    *ts += timestamp_offset; + +    return ts; +} + +void TimestampDecoder::pushMNSCData(uint8_t framephase, uint16_t mnsc)  {      struct eti_MNSC_TIME_0 *mnsc0;      struct eti_MNSC_TIME_1 *mnsc1; @@ -190,7 +229,7 @@ void TimestampDecoder::updateTimestampPPS(uint32_t pps)  }  void TimestampDecoder::updateTimestampEti( -        int framephase, +        uint8_t framephase,          uint16_t mnsc,          uint32_t pps, // In units of 1/16384000 s          int32_t fct) @@ -198,16 +237,19 @@ void TimestampDecoder::updateTimestampEti(      updateTimestampPPS(pps);      pushMNSCData(framephase, mnsc);      latestFCT = fct; +    latestFP = framephase;  }  void TimestampDecoder::updateTimestampEdi(          uint32_t seconds_utc,          uint32_t pps, // In units of 1/16384000 s -        int32_t fct) +        int32_t fct, +        uint8_t framephase)  {      time_secs = seconds_utc;      time_pps  = pps;      latestFCT = fct; +    latestFP = framephase;      full_timestamp_received = true;  } diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index 943b241..4bbf5cc 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -40,6 +40,7 @@ struct frame_timestamp  {      // Which frame count does this timestamp apply to      int32_t fct; +    uint8_t fp; // Frame Phase      uint32_t timestamp_sec;      uint32_t timestamp_pps; // In units of 1/16384000 s @@ -56,6 +57,7 @@ struct frame_timestamp              this->timestamp_valid = rhs.timestamp_valid;              this->timestamp_refresh = rhs.timestamp_refresh;              this->fct = rhs.fct; +            this->fp = rhs.fp;          }          return *this; @@ -103,49 +105,23 @@ struct frame_timestamp  class TimestampDecoder : public RemoteControllable  {      public: -        TimestampDecoder( -                /* The modulator adds this offset to the TIST to define time of -                 * frame transmission -                 */ -                double& offset_s, - -                /* Specifies by how many stages the timestamp must be delayed. -                 * (e.g. The FIRFilter is pipelined, therefore we must increase -                 * tist_delay_stages by one if the filter is used -                 */ -                unsigned tist_delay_stages) : -            RemoteControllable("tist"), -            timestamp_offset(offset_s) -        { -            m_tist_delay_stages = tist_delay_stages; -            inhibit_second_update = 0; -            time_pps = 0.0; -            time_secs = 0; -            latestFCT = 0; -            enableDecode = false; -            full_timestamp_received = false; - -            // Properly initialise temp_time -            memset(&temp_time, 0, sizeof(temp_time)); -            const time_t timep = 0; -            gmtime_r(&timep, &temp_time); - -            offset_changed = false; - -            RC_ADD_PARAMETER(offset, "TIST offset [s]"); -            RC_ADD_PARAMETER(timestamp, "FCT and timestamp [s]"); - -            etiLog.level(info) << "Setting up timestamp decoder with " << -                timestamp_offset << " offset"; - -        }; +        /* offset_s: The modulator adds this offset to the TIST to define time of +         * frame transmission +         * +         * tist_delay_stages: Specifies by how many stages the timestamp must +         * be delayed.  (e.g. The FIRFilter is pipelined, therefore we must +         * increase tist_delay_stages by one if the filter is used +         */ +        TimestampDecoder(double& offset_s, unsigned tist_delay_stages);          /* Calculate the timestamp for the current frame. */          void calculateTimestamp(frame_timestamp& ts); +        std::shared_ptr<frame_timestamp> getTimestamp(void); +          /* Update timestamp data from ETI */          void updateTimestampEti( -                int framephase, +                uint8_t framephase,                  uint16_t mnsc,                  uint32_t pps, // In units of 1/16384000 s                  int32_t fct); @@ -154,7 +130,8 @@ class TimestampDecoder : public RemoteControllable          void updateTimestampEdi(                  uint32_t seconds_utc,                  uint32_t pps, // In units of 1/16384000 s -                int32_t fct); +                int32_t fct, +                uint8_t framephase);          /*********** REMOTE CONTROL ***************/ @@ -171,7 +148,7 @@ class TimestampDecoder : public RemoteControllable      protected:          /* Push a new MNSC field into the decoder */ -        void pushMNSCData(int framephase, uint16_t mnsc); +        void pushMNSCData(uint8_t framephase, uint16_t mnsc);          /* Each frame contains the TIST field with the PPS offset.           * For each frame, this function must be called to update @@ -191,21 +168,22 @@ class TimestampDecoder : public RemoteControllable          void updateTimestampSeconds(uint32_t secs);          struct tm temp_time; -        uint32_t time_secs; -        int32_t latestFCT; -        uint32_t time_pps; +        uint32_t time_secs = 0; +        int32_t latestFCT = 0; +        uint32_t latestFP = 0; +        uint32_t time_pps = 0;          double& timestamp_offset;          unsigned m_tist_delay_stages; -        int inhibit_second_update; -        bool offset_changed; +        int inhibit_second_update = 0; +        bool offset_changed = false;          /* When the type or identifier don't match, the decoder must           * be disabled           */ -        bool enableDecode; +        bool enableDecode = false;          /* Disable timstamps until full time has been received */ -        bool full_timestamp_received; +        bool full_timestamp_received = false;          /* when pipelining, we must shift the calculated timestamps           * through this queue. Otherwise, it would not be possible to @@ -213,6 +191,5 @@ class TimestampDecoder : public RemoteControllable           * FIRFilter (1 stage pipeline)           */          std::queue<std::shared_ptr<frame_timestamp> > queue_timestamps; -  }; | 
