From 1d833b718845b97a5b1d90f33b547b1772bc0708 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 08:49:29 +0100 Subject: Add new flowgraph path for metadata --- src/OutputFile.cpp | 56 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'src/OutputFile.cpp') 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 #include #include +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 {}; +} -- cgit v1.2.3 From 23b369e1145c5652778345827b7df9c33e09d0e8 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 09:21:25 +0100 Subject: Add metadata latency for all PipelinedModCodec --- src/DabMod.cpp | 6 ++++++ src/ModPlugin.cpp | 19 ++++++++++++++++--- src/ModPlugin.h | 52 +++++++++++++++++++++++++++++++--------------------- src/OutputFile.cpp | 22 +++++++++++++--------- src/OutputFile.h | 6 ++++++ 5 files changed, 72 insertions(+), 33 deletions(-) (limited to 'src/OutputFile.cpp') diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 25a93bf..4a4ea82 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -426,6 +426,12 @@ int launch_modulator(int argc, char* argv[]) } #endif + // TODO remove + auto output_as_file = dynamic_pointer_cast(output); + if (output_as_file) { + output_as_file->setETISource(modulator->getEtiSource()); + } + inputReader->PrintInfo(); run_modulator_state_t st = run_modulator(m); diff --git a/src/ModPlugin.cpp b/src/ModPlugin.cpp index c39d883..f86bfb2 100644 --- a/src/ModPlugin.cpp +++ b/src/ModPlugin.cpp @@ -74,9 +74,9 @@ int ModOutput::process( PipelinedModCodec::PipelinedModCodec() : ModCodec(), - m_number_of_runs(0), m_input_queue(), m_output_queue(), + m_metadata_fifo(), m_running(false), m_thread() { @@ -107,7 +107,7 @@ int PipelinedModCodec::process(Buffer* dataIn, Buffer* dataOut) m_input_queue.push(inbuffer); - if (m_number_of_runs > 0) { + if (m_ready_to_output_data) { std::shared_ptr outbuffer; m_output_queue.wait_and_pop(outbuffer); @@ -116,13 +116,26 @@ int PipelinedModCodec::process(Buffer* dataIn, Buffer* dataOut) else { dataOut->setLength(dataIn->getLength()); memset(dataOut->getData(), 0, dataOut->getLength()); - m_number_of_runs++; + m_ready_to_output_data = true; } return dataOut->getLength(); } +meta_vec_t PipelinedModCodec::process_metadata(const meta_vec_t& metadataIn) +{ + m_metadata_fifo.push_back(metadataIn); + if (m_metadata_fifo.size() == 2) { + auto r = std::move(m_metadata_fifo.front()); + m_metadata_fifo.pop_front(); + return r; + } + else { + return {}; + } +} + void PipelinedModCodec::process_thread() { set_thread_name(name()); diff --git a/src/ModPlugin.h b/src/ModPlugin.h index 3c3e8b3..c0f1c1a 100644 --- a/src/ModPlugin.h +++ b/src/ModPlugin.h @@ -30,16 +30,34 @@ # include #endif - #include "Buffer.h" #include "ThreadsafeQueue.h" - -#include +#include #include #include #include #include +// All flowgraph elements derive from ModPlugin, or a variant of it. +// Some ModPlugins also support handling metadata. + +struct frame_timestamp; +struct flowgraph_metadata { + std::shared_ptr ts; +}; + +using meta_vec_t = std::vector; + +/* ModPlugins that support metadata derive from ModMetadata */ +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; +}; + + +/* Abstract base class for all flowgraph elements */ class ModPlugin { public: @@ -69,7 +87,11 @@ public: virtual int process(Buffer* const dataIn, Buffer* dataOut) = 0; }; -class PipelinedModCodec : public ModCodec +/* Pipelined ModCodecs run their processing in a separate thread, and + * have a one-call-to-process() latency. Because of this latency, they + * must also handle the metadata + */ +class PipelinedModCodec : public ModCodec, public ModMetadata { public: PipelinedModCodec(); @@ -82,6 +104,8 @@ public: virtual int process(Buffer* const dataIn, Buffer* dataOut) final; virtual const char* name() = 0; + virtual meta_vec_t process_metadata(const meta_vec_t& metadataIn) final; + protected: // Once the instance implementing PipelinedModCodec has been constructed, // it must call start_pipeline_thread() @@ -89,11 +113,13 @@ protected: virtual int internal_process(Buffer* const dataIn, Buffer* dataOut) = 0; private: - size_t m_number_of_runs; + bool m_ready_to_output_data = false; ThreadsafeQueue > m_input_queue; ThreadsafeQueue > m_output_queue; + std::deque m_metadata_fifo; + std::atomic m_running; std::thread m_thread; void process_thread(void); @@ -120,19 +146,3 @@ public: virtual int process(Buffer* dataIn) = 0; }; -struct frame_timestamp; -struct flowgraph_metadata { - std::shared_ptr ts; -}; - - -using meta_vec_t = std::vector; - -/* 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 3bb45c4..481e858 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -77,22 +77,26 @@ meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) for (const auto& md : metadataIn) { if (md.ts) { - ss << "FCT=" << md.ts->fct << + 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, "; + ss << " void, "; } } + if (myEtiSource) { + frame_timestamp ts; + myEtiSource->calculateTimestamp(ts); + ss << " ETI FCT=" << ts.fct; + } + etiLog.level(debug) << "Output File got metadata: " << ss.str(); return {}; } + +void OutputFile::setETISource(EtiSource *etiSource) +{ + myEtiSource = etiSource; +} diff --git a/src/OutputFile.h b/src/OutputFile.h index 2b92369..97fdcb7 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -32,6 +32,7 @@ #include "ModPlugin.h" +#include "EtiReader.h" #include #include @@ -57,7 +58,12 @@ public: virtual meta_vec_t process_metadata( const meta_vec_t& metadataIn) override; + void setETISource(EtiSource *etiSource); + protected: + // TODO remove + EtiSource *myEtiSource = nullptr; + std::string myFilename; std::unique_ptr myFile; }; -- cgit v1.2.3 From 1e76247e059021ea52309ebd258b6eed033d6aee Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 11:11:12 +0100 Subject: Remove calculateTimestamp --- src/ConfigParser.h | 1 - src/DabMod.cpp | 38 ++------------------------ src/EtiReader.cpp | 20 +++----------- src/EtiReader.h | 11 ++------ src/OutputFile.cpp | 10 ------- src/OutputFile.h | 5 ---- src/TimestampDecoder.cpp | 70 ++---------------------------------------------- src/TimestampDecoder.h | 19 ++----------- src/output/SDR.cpp | 5 ---- src/output/SDR.h | 3 --- 10 files changed, 12 insertions(+), 170 deletions(-) (limited to 'src/OutputFile.cpp') diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 3f64883..0463470 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -58,7 +58,6 @@ struct mod_settings_t { float gainmodeVariance = 4.0f; // To handle the timestamp offset of the modulator - unsigned tist_delay_stages = 1; // because GainControl is pipelined double tist_offset_s = 0.0; bool loop = false; diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 9880938..31fa76d 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -269,12 +269,6 @@ int launch_modulator(int argc, char* argv[]) throw std::runtime_error("Configuration error"); } - // When using the FIRFilter, increase the modulator offset pipelining delay - // by the correct amount - if (not mod_settings.filterTapsFilename.empty()) { - mod_settings.tist_delay_stages += FIRFILTER_PIPELINE_DELAY; - } - printModSettings(mod_settings); modulator_data m; @@ -295,7 +289,7 @@ int launch_modulator(int argc, char* argv[]) set_thread_name("modulator"); if (mod_settings.inputTransport == "edi") { - EdiReader ediReader(mod_settings.tist_offset_s, mod_settings.tist_delay_stages); + EdiReader ediReader(mod_settings.tist_offset_s); EdiDecoder::ETIDecoder ediInput(ediReader, false); if (mod_settings.edi_max_delay_ms > 0.0f) { // setMaxDelay wants number of AF packets, which correspond to 24ms ETI frames @@ -320,17 +314,6 @@ int launch_modulator(int argc, char* argv[]) flowgraph.connect(modulator, output); } - if (false -#if defined(HAVE_OUTPUT_UHD) - or mod_settings.useUHDOutput -#endif -#if defined(HAVE_SOAPYSDR) - or mod_settings.useSoapyOutput -#endif - ) { - ((Output::SDR*)output.get())->setETISource(modulator->getEtiSource()); - } - size_t framecount = 0; while (running) { @@ -400,7 +383,7 @@ int launch_modulator(int argc, char* argv[]) m.flowgraph = &flowgraph; m.data.setLength(6144); - EtiReader etiReader(mod_settings.tist_offset_s, mod_settings.tist_delay_stages); + EtiReader etiReader(mod_settings.tist_offset_s); m.etiReader = &etiReader; auto input = make_shared(&m.data); @@ -414,23 +397,6 @@ int launch_modulator(int argc, char* argv[]) flowgraph.connect(modulator, output); } - if (false -#if defined(HAVE_OUTPUT_UHD) - or mod_settings.useUHDOutput -#endif -#if defined(HAVE_SOAPYSDR) - or mod_settings.useSoapyOutput -#endif - ) { - ((Output::SDR*)output.get())->setETISource(modulator->getEtiSource()); - } - - // TODO remove - auto output_as_file = dynamic_pointer_cast(output); - if (output_as_file) { - output_as_file->setETISource(modulator->getEtiSource()); - } - inputReader->PrintInfo(); run_modulator_state_t st = run_modulator(m); diff --git a/src/EtiReader.cpp b/src/EtiReader.cpp index dc5df84..17f4953 100644 --- a/src/EtiReader.cpp +++ b/src/EtiReader.cpp @@ -54,10 +54,9 @@ enum ETI_READER_STATE { EtiReader::EtiReader( - double& tist_offset_s, - unsigned tist_delay_stages) : + double& tist_offset_s) : state(EtiReaderStateSync), - myTimestampDecoder(tist_offset_s, tist_delay_stages), + myTimestampDecoder(tist_offset_s), eti_fc_valid(false) { rcs.enrol(&myTimestampDecoder); @@ -292,11 +291,6 @@ bool EtiReader::sourceContainsTimestamp() /* See ETS 300 799, Annex C.2.2 */ } -void EtiReader::calculateTimestamp(struct frame_timestamp& ts) -{ - myTimestampDecoder.calculateTimestamp(ts); -} - uint32_t EtiReader::getPPSOffset() { if (!sourceContainsTimestamp()) { @@ -311,9 +305,8 @@ uint32_t EtiReader::getPPSOffset() } EdiReader::EdiReader( - double& tist_offset_s, - unsigned tist_delay_stages) : - m_timestamp_decoder(tist_offset_s, tist_delay_stages) + double& tist_offset_s) : + m_timestamp_decoder(tist_offset_s) { rcs.enrol(&m_timestamp_decoder); } @@ -361,11 +354,6 @@ bool EdiReader::sourceContainsTimestamp() return m_fc.tsta != 0xFFFFFF; } -void EdiReader::calculateTimestamp(struct frame_timestamp& ts) -{ - m_timestamp_decoder.calculateTimestamp(ts); -} - bool EdiReader::isFrameReady() { return m_frameReady; diff --git a/src/EtiReader.h b/src/EtiReader.h index f3a9764..8270592 100644 --- a/src/EtiReader.h +++ b/src/EtiReader.h @@ -59,7 +59,6 @@ public: /* Returns true if we have valid time stamps in the ETI*/ virtual bool sourceContainsTimestamp() = 0; - virtual void calculateTimestamp(struct frame_timestamp& ts) = 0; /* Return the FIC source to be used for modulation */ virtual std::shared_ptr& getFic(void); @@ -75,9 +74,7 @@ protected: class EtiReader : public EtiSource { public: - EtiReader( - double& tist_offset_s, - unsigned tist_delay_stages); + EtiReader(double& tist_offset_s); virtual unsigned getMode(); virtual unsigned getFp(); @@ -88,7 +85,6 @@ public: int loadEtiData(const Buffer& dataIn); virtual bool sourceContainsTimestamp(); - virtual void calculateTimestamp(struct frame_timestamp& ts); virtual const std::vector > getSubchannels() const; @@ -118,14 +114,11 @@ private: class EdiReader : public EtiSource, public EdiDecoder::DataCollector { public: - EdiReader( - double& tist_offset_s, - unsigned tist_delay_stages); + EdiReader(double& tist_offset_s); virtual unsigned getMode(); virtual unsigned getFp(); virtual bool sourceContainsTimestamp(); - virtual void calculateTimestamp(struct frame_timestamp& ts); virtual const std::vector > getSubchannels() const; virtual bool isFrameReady(void); diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index 481e858..1c2f5ed 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -85,18 +85,8 @@ meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) } } - if (myEtiSource) { - frame_timestamp ts; - myEtiSource->calculateTimestamp(ts); - ss << " ETI FCT=" << ts.fct; - } - etiLog.level(debug) << "Output File got metadata: " << ss.str(); return {}; } -void OutputFile::setETISource(EtiSource *etiSource) -{ - myEtiSource = etiSource; -} diff --git a/src/OutputFile.h b/src/OutputFile.h index a586921..fedea40 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -50,12 +50,7 @@ public: virtual meta_vec_t process_metadata( const meta_vec_t& metadataIn) override; - void setETISource(EtiSource *etiSource); - protected: - // TODO remove - EtiSource *myEtiSource = nullptr; - std::string myFilename; struct FILEDeleter{ void operator()(FILE* fd){ if (fd) fclose(fd); }}; diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp index 6cf2875..523551c 100644 --- a/src/TimestampDecoder.cpp +++ b/src/TimestampDecoder.cpp @@ -37,10 +37,9 @@ //#define MDEBUG(fmt, args...) fprintf (LOG, "*****" fmt , ## args) #define MDEBUG(fmt, args...) PDEBUG(fmt, ## args) -TimestampDecoder::TimestampDecoder(double& offset_s, unsigned tist_delay_stages) : +TimestampDecoder::TimestampDecoder(double& offset_s) : RemoteControllable("tist"), - timestamp_offset(offset_s), - m_tist_delay_stages(tist_delay_stages) + timestamp_offset(offset_s) { // Properly initialise temp_time memset(&temp_time, 0, sizeof(temp_time)); @@ -54,71 +53,6 @@ TimestampDecoder::TimestampDecoder(double& offset_s, unsigned tist_delay_stages) timestamp_offset << " offset"; } -void TimestampDecoder::calculateTimestamp(frame_timestamp& ts) -{ - std::shared_ptr ts_queued = - std::make_shared(); - - /* Push new timestamp into queue */ - ts_queued->timestamp_valid = full_timestamp_received; - 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; - - MDEBUG("time_secs=%d, time_pps=%f\n", time_secs, - (double)time_pps / 16384000.0); - *ts_queued += timestamp_offset; - - queue_timestamps.push(ts_queued); - - /* Here, the queue size is one more than the pipeline delay, because - * we've just added a new element in the queue. - * - * Therefore, use <= and not < for comparison - */ - if (queue_timestamps.size() <= m_tist_delay_stages) { - //fprintf(stderr, "* %zu %u ", queue_timestamps.size(), m_tist_delay_stages); - /* Return invalid timestamp until the queue is full */ - ts.timestamp_valid = false; - ts.timestamp_sec = 0; - ts.timestamp_pps = 0; - ts.timestamp_refresh = false; - ts.fct = -1; - } - else { - //fprintf(stderr, ". %zu ", queue_timestamps.size()); - /* Return timestamp from queue */ - ts_queued = queue_timestamps.front(); - queue_timestamps.pop(); - /*fprintf(stderr, "ts_queued v:%d, sec:%d, pps:%f, ref:%d\n", - ts_queued->timestamp_valid, - ts_queued->timestamp_sec, - ts_queued->timestamp_pps_offset, - ts_queued->timestamp_refresh);*/ - ts = *ts_queued; - /*fprintf(stderr, "ts v:%d, sec:%d, pps:%f, ref:%d\n\n", - ts.timestamp_valid, - ts.timestamp_sec, - ts.timestamp_pps_offset, - ts.timestamp_refresh);*/ - } - - MDEBUG("Timestamp queue size %zu, delay_calc %u\n", - queue_timestamps.size(), - m_tist_delay_stages); - - if (queue_timestamps.size() > m_tist_delay_stages) { - etiLog.level(error) << "Error: Timestamp queue is too large : size " << - queue_timestamps.size() << "! This should not happen !"; - } - - //ts.print("calc2 "); -} - std::shared_ptr TimestampDecoder::getTimestamp() { std::shared_ptr ts = diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index 0953f76..000156d 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -2,7 +2,7 @@ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 @@ -119,15 +119,8 @@ class TimestampDecoder : public RemoteControllable public: /* 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); + TimestampDecoder(double& offset_s); std::shared_ptr getTimestamp(void); @@ -185,7 +178,6 @@ class TimestampDecoder : public RemoteControllable uint32_t latestFP = 0; uint32_t time_pps = 0; double& timestamp_offset; - unsigned m_tist_delay_stages; int inhibit_second_update = 0; bool offset_changed = false; @@ -196,12 +188,5 @@ class TimestampDecoder : public RemoteControllable /* Disable timstamps until full time has been received */ bool full_timestamp_received = false; - - /* when pipelining, we must shift the calculated timestamps - * through this queue. Otherwise, it would not be possible to - * synchronise two modulators if only one uses (for instance) the - * FIRFilter (1 stage pipeline) - */ - std::queue > queue_timestamps; }; diff --git a/src/output/SDR.cpp b/src/output/SDR.cpp index d7d777f..5290e5d 100644 --- a/src/output/SDR.cpp +++ b/src/output/SDR.cpp @@ -217,11 +217,6 @@ const char* SDR::name() return m_name.c_str(); } -void SDR::setETISource(EtiSource *etiSource) -{ - m_eti_source = etiSource; -} - void SDR::sleep_through_frame() { struct timespec now; diff --git a/src/output/SDR.h b/src/output/SDR.h index ea787c3..8affaf9 100644 --- a/src/output/SDR.h +++ b/src/output/SDR.h @@ -55,8 +55,6 @@ class SDR : public ModOutput, public ModMetadata, public RemoteControllable { virtual const char* name() override; - void setETISource(EtiSource *etiSource); - /*********** REMOTE CONTROL ***************/ /* Base function to set parameters. */ @@ -85,7 +83,6 @@ class SDR : public ModOutput, public ModMetadata, public RemoteControllable { std::shared_ptr m_dpd_feedback_server; - EtiSource *m_eti_source = nullptr; bool sourceContainsTimestamp = false; bool last_tx_time_initialised = false; uint32_t last_tx_second = 0; -- cgit v1.2.3 From 28d794ab7d47e4f2585ac73f8a69c9c68962b678 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 11:51:03 +0100 Subject: Make frame_timestamp movable --- src/Flowgraph.cpp | 3 ++- src/OutputFile.cpp | 17 ++++++++++++----- src/TimestampDecoder.h | 16 ---------------- 3 files changed, 14 insertions(+), 22 deletions(-) (limited to 'src/OutputFile.cpp') diff --git a/src/Flowgraph.cpp b/src/Flowgraph.cpp index e12ff1e..ae86417 100644 --- a/src/Flowgraph.cpp +++ b/src/Flowgraph.cpp @@ -151,8 +151,9 @@ int Node::process() 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(), + move(md_vec_sp->begin(), md_vec_sp->end(), back_inserter(all_input_mds)); + md_vec_sp->clear(); } } diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index 1c2f5ed..b7bf59a 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -71,21 +71,28 @@ 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 << ";"; + } + else { + ss << " No TS;"; + } } else { ss << " void, "; } } - etiLog.level(debug) << "Output File got metadata: " << ss.str(); + if (metadataIn.empty()) { + etiLog.level(debug) << "Output File got no mdIn"; + } + else { + etiLog.level(debug) << "Output File got metadata: " << ss.str(); + } return {}; } diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h index cffba2f..ff52e4c 100644 --- a/src/TimestampDecoder.h +++ b/src/TimestampDecoder.h @@ -47,22 +47,6 @@ struct frame_timestamp bool timestamp_valid = false; bool timestamp_refresh; - frame_timestamp() = default; - frame_timestamp(const frame_timestamp& other) = default; - frame_timestamp& operator=(const frame_timestamp &rhs) - { - if (this != &rhs) { - this->timestamp_sec = rhs.timestamp_sec; - this->timestamp_pps = rhs.timestamp_pps; - this->timestamp_valid = rhs.timestamp_valid; - this->timestamp_refresh = rhs.timestamp_refresh; - this->fct = rhs.fct; - this->fp = rhs.fp; - } - - return *this; - } - frame_timestamp& operator+=(const double& diff) { double offset_pps, offset_secs; -- cgit v1.2.3 From 770703c9c5c926be760af836bee26e554e81a71c Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 12:04:46 +0100 Subject: Add option to show metadata for file output --- doc/example.ini | 2 ++ src/ConfigParser.cpp | 14 ++++++++------ src/ConfigParser.h | 9 +++++---- src/DabMod.cpp | 6 +++--- src/OutputFile.cpp | 42 ++++++++++++++++++++++-------------------- src/OutputFile.h | 3 ++- 6 files changed, 42 insertions(+), 34 deletions(-) (limited to 'src/OutputFile.cpp') diff --git a/doc/example.ini b/doc/example.ini index d04c1a7..d919f4a 100644 --- a/doc/example.ini +++ b/doc/example.ini @@ -165,6 +165,8 @@ output=uhd ; The output file: filename=ofdm.iq +show_metadata=0 + [uhdoutput] ; The UHD output can be directly used with the Ettus USRP devices ; diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 0e641c0..a4219af 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -204,13 +204,15 @@ static void parse_configfile( if (output_selected == "file") { try { mod_settings.outputName = pt.get("fileoutput.filename"); + mod_settings.fileOutputShowMetadata = + (pt.get("fileoutput.show_metadata", 0) > 0); } catch (std::exception &e) { std::cerr << "Error: " << e.what() << "\n"; std::cerr << " Configuration does not specify file name for file output\n"; throw std::runtime_error("Configuration error"); } - mod_settings.useFileOutput = 1; + mod_settings.useFileOutput = true; mod_settings.fileOutputFormat = pt.get("fileoutput.format", mod_settings.fileOutputFormat); } @@ -283,7 +285,7 @@ static void parse_configfile( sdr_device_config.dpdFeedbackServerPort = pt.get("uhdoutput.dpd_port", 0); mod_settings.sdr_device_config = sdr_device_config; - mod_settings.useUHDOutput = 1; + mod_settings.useUHDOutput = true; } #endif #if defined(HAVE_SOAPYSDR) @@ -310,14 +312,14 @@ static void parse_configfile( throw std::runtime_error("Configuration error"); } - mod_settings.useSoapyOutput = 1; + mod_settings.useSoapyOutput = true; } #endif #if defined(HAVE_ZEROMQ) else if (output_selected == "zmq") { mod_settings.outputName = pt.get("zmqoutput.listen"); mod_settings.zmqOutputSocketType = pt.get("zmqoutput.socket_type"); - mod_settings.useZeroMQOutput = 1; + mod_settings.useZeroMQOutput = true; } #endif else { @@ -399,7 +401,7 @@ void parse_args(int argc, char **argv, mod_settings_t& mod_settings) } #endif mod_settings.outputName = optarg; - mod_settings.useFileOutput = 1; + mod_settings.useFileOutput = true; break; case 'F': #if defined(HAVE_OUTPUT_UHD) @@ -442,7 +444,7 @@ void parse_args(int argc, char **argv, mod_settings_t& mod_settings) mod_settings.sdr_device_config.refclk_src = "internal"; mod_settings.sdr_device_config.pps_src = "none"; mod_settings.sdr_device_config.pps_polarity = "pos"; - mod_settings.useUHDOutput = 1; + mod_settings.useUHDOutput = true; #endif break; case 'V': diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 0463470..dc5ac4f 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -42,12 +42,13 @@ struct mod_settings_t { std::string outputName; - int useZeroMQOutput = 0; + bool useZeroMQOutput = false; std::string zmqOutputSocketType = ""; - int useFileOutput = 0; + bool useFileOutput = false; std::string fileOutputFormat = "complexf"; - int useUHDOutput = 0; - int useSoapyOutput = 0; + bool fileOutputShowMetadata = false; + bool useUHDOutput = false; + bool useSoapyOutput = false; size_t outputRate = 2048000; size_t clockRate = 0; diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 31fa76d..ce2f249 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -177,7 +177,7 @@ static shared_ptr prepare_output( if (s.useFileOutput) { if (s.fileOutputFormat == "complexf") { - output = make_shared(s.outputName); + output = make_shared(s.outputName, s.fileOutputShowMetadata); } else if (s.fileOutputFormat == "complexf_normalised") { if (s.gainMode == GainMode::GAIN_FIX) @@ -186,7 +186,7 @@ static shared_ptr prepare_output( s.normalise = 1.0f / normalise_factor_file_max; else if (s.gainMode == GainMode::GAIN_VAR) s.normalise = 1.0f / normalise_factor_file_var; - output = make_shared(s.outputName); + output = make_shared(s.outputName, s.fileOutputShowMetadata); } else if (s.fileOutputFormat == "s8" or s.fileOutputFormat == "u8") { @@ -195,7 +195,7 @@ static shared_ptr prepare_output( // [0; 255] s.normalise = 127.0f / normalise_factor; - output = make_shared(s.outputName); + output = make_shared(s.outputName, s.fileOutputShowMetadata); } else { throw runtime_error("File output format " + s.fileOutputFormat + diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index b7bf59a..f5a1997 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -36,9 +36,9 @@ using namespace std; -OutputFile::OutputFile(std::string filename) : - ModOutput(), - ModMetadata(), +OutputFile::OutputFile(const std::string& filename, bool show_metadata) : + ModOutput(), ModMetadata(), + myShowMetadata(show_metadata), myFilename(filename) { PDEBUG("OutputFile::OutputFile(filename: %s) @ %p\n", @@ -69,31 +69,33 @@ int OutputFile::process(Buffer* dataIn) meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) { - stringstream ss; - - 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 << ";"; + if (myShowMetadata) { + stringstream ss; + + 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 << ";"; + } + else { + ss << " No TS;"; + } } else { - ss << " No TS;"; + ss << " void, "; } } + + if (metadataIn.empty()) { + etiLog.level(debug) << "Output File got no mdIn"; + } else { - ss << " void, "; + etiLog.level(debug) << "Output File got metadata: " << ss.str(); } - } - if (metadataIn.empty()) { - etiLog.level(debug) << "Output File got no mdIn"; } - else { - etiLog.level(debug) << "Output File got metadata: " << ss.str(); - } - return {}; } diff --git a/src/OutputFile.h b/src/OutputFile.h index fedea40..745e672 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -42,7 +42,7 @@ class OutputFile : public ModOutput, public ModMetadata { public: - OutputFile(std::string filename); + OutputFile(const std::string& filename, bool show_metadata); virtual int process(Buffer* dataIn) override; const char* name() override { return "OutputFile"; } @@ -51,6 +51,7 @@ public: const meta_vec_t& metadataIn) override; protected: + bool myShowMetadata = false; std::string myFilename; struct FILEDeleter{ void operator()(FILE* fd){ if (fd) fclose(fd); }}; -- cgit v1.2.3 From 8d4a68a3c5c2910f7868a54847e47e813664621b Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Tue, 16 Jan 2018 12:05:37 +0100 Subject: Show seconds and PPS in OutputFile metadata --- TODO | 4 ++++ src/OutputFile.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/OutputFile.cpp') diff --git a/TODO b/TODO index 5269614..53932ea 100644 --- a/TODO +++ b/TODO @@ -51,6 +51,10 @@ Tests, both with B200 and LimeSDR: - Proper teardown - DPD server +Replace all prints to stderr +---------------------------- +We have a nice logging subsystem, use it to avoid that fprintf(stderr, ...) and +logging to stderr messages collide. Finalise EDI input ------------------ diff --git a/src/OutputFile.cpp b/src/OutputFile.cpp index f5a1997..46a9ec9 100644 --- a/src/OutputFile.cpp +++ b/src/OutputFile.cpp @@ -77,10 +77,12 @@ meta_vec_t OutputFile::process_metadata(const meta_vec_t& metadataIn) ss << " FCT=" << md.ts->fct << " FP=" << (int)md.ts->fp; if (md.ts->timestamp_valid) { - ss << " TS=" << md.ts->timestamp_sec << ";"; + ss << " TS=" << md.ts->timestamp_sec << " + " << + std::fixed + << (double)md.ts->timestamp_pps / 163840000.0 << ";"; } else { - ss << " No TS;"; + ss << " TS invalid;"; } } else { -- cgit v1.2.3