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.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src/OutputFile.h') 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 #include #include +#include +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 myFile; }; -- 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.h') 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 0315433aef00644085d2278af405eaedbc184c5c Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 7 Jan 2018 09:40:06 +0100 Subject: use unique_ptr to handle FILE* in Log --- src/Log.cpp | 39 ++++++++++++++++++++++++++------------- src/Log.h | 41 ++++++++++++----------------------------- src/OutputFile.h | 10 ++-------- 3 files changed, 40 insertions(+), 50 deletions(-) (limited to 'src/OutputFile.h') diff --git a/src/Log.cpp b/src/Log.cpp index 0792fcf..f2219eb 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -109,6 +109,17 @@ LogLine Logger::level(log_level_t level) return LogLine(this, level); } +LogToFile::LogToFile(const std::string& filename) : name("FILE") +{ + FILE* fd = fopen(filename.c_str(), "a"); + if (fd == nullptr) { + fprintf(stderr, "Cannot open log file !"); + throw std::runtime_error("Cannot open log file !"); + } + + log_file.reset(fd); +} + void LogToFile::log(log_level_t level, const std::string& message) { if (level != log_level_t::trace) { @@ -116,9 +127,9 @@ void LogToFile::log(log_level_t level, const std::string& message) "DEBUG", "INFO", "WARN", "ERROR", "ALERT", "EMERG"}; // fprintf is thread-safe - fprintf(log_file, SYSLOG_IDENT ": %s: %s\n", + fprintf(log_file.get(), SYSLOG_IDENT ": %s: %s\n", log_level_text[(size_t)level], message.c_str()); - fflush(log_file); + fflush(log_file.get()); } } @@ -142,31 +153,33 @@ void LogToSyslog::log(log_level_t level, const std::string& message) } } -LogTracer::LogTracer(const string& trace_filename) +LogTracer::LogTracer(const string& trace_filename) : name("TRACE") { - name = "TRACE"; etiLog.level(info) << "Setting up TRACE to " << trace_filename; - m_trace_file = fopen(trace_filename.c_str(), "a"); - if (m_trace_file == NULL) { + FILE* fd = fopen(trace_filename.c_str(), "a"); + if (fd == nullptr) { fprintf(stderr, "Cannot open trace file !"); throw std::runtime_error("Cannot open trace file !"); } + m_trace_file.reset(fd); - auto now = chrono::steady_clock::now().time_since_epoch(); - m_trace_micros_startup = - chrono::duration_cast(now).count(); + using namespace std::chrono; + auto now = steady_clock::now().time_since_epoch(); + m_trace_micros_startup = duration_cast(now).count(); - fprintf(m_trace_file, "0,TRACER,startup at %ld\n", m_trace_micros_startup); + fprintf(m_trace_file.get(), + "0,TRACER,startup at %ld\n", m_trace_micros_startup); } void LogTracer::log(log_level_t level, const std::string& message) { if (level == log_level_t::trace) { - const auto now = chrono::steady_clock::now().time_since_epoch(); - const auto micros = chrono::duration_cast(now).count(); + using namespace std::chrono; + const auto now = steady_clock::now().time_since_epoch(); + const auto micros = duration_cast(now).count(); - fprintf(m_trace_file, "%ld,%s\n", + fprintf(m_trace_file.get(), "%ld,%s\n", micros - m_trace_micros_startup, message.c_str()); } diff --git a/src/Log.h b/src/Log.h index ae252a6..0e09bc9 100644 --- a/src/Log.h +++ b/src/Log.h @@ -57,7 +57,7 @@ static const std::string levels_as_str[] = class LogBackend { public: virtual void log(log_level_t level, const std::string& message) = 0; - virtual std::string get_name() = 0; + virtual std::string get_name() const = 0; }; /** A Logging backend for Syslog */ @@ -73,7 +73,7 @@ class LogToSyslog : public LogBackend { void log(log_level_t level, const std::string& message); - std::string get_name() { return name; } + std::string get_name() const { return name; } private: const std::string name; @@ -84,27 +84,15 @@ class LogToSyslog : public LogBackend { class LogToFile : public LogBackend { public: - LogToFile(const std::string& filename) : name("FILE") { - log_file = fopen(filename.c_str(), "a"); - if (log_file == NULL) { - fprintf(stderr, "Cannot open log file !"); - throw std::runtime_error("Cannot open log file !"); - } - } - - ~LogToFile() { - if (log_file != NULL) { - fclose(log_file); - } - } - + LogToFile(const std::string& filename); void log(log_level_t level, const std::string& message); - - std::string get_name() { return name; } + std::string get_name() const { return name; } private: const std::string name; - FILE* log_file; + + struct FILEDeleter{ void operator()(FILE* fd){ if(fd) fclose(fd);}}; + std::unique_ptr log_file; LogToFile(const LogToFile& other) = delete; const LogToFile& operator=(const LogToFile& other) = delete; @@ -113,19 +101,14 @@ class LogToFile : public LogBackend { class LogTracer : public LogBackend { public: LogTracer(const std::string& filename); - - ~LogTracer() { - if (m_trace_file != NULL) { - fclose(m_trace_file); - } - } - void log(log_level_t level, const std::string& message); - std::string get_name() { return name; } + std::string get_name() const { return name; } private: std::string name; - uint64_t m_trace_micros_startup; - FILE* m_trace_file; + uint64_t m_trace_micros_startup = 0; + + struct FILEDeleter{ void operator()(FILE* fd){ if(fd) fclose(fd);}}; + std::unique_ptr m_trace_file; LogTracer(const LogTracer& other) = delete; const LogTracer& operator=(const LogTracer& other) = delete; diff --git a/src/OutputFile.h b/src/OutputFile.h index 97fdcb7..a586921 100644 --- a/src/OutputFile.h +++ b/src/OutputFile.h @@ -39,14 +39,6 @@ #include #include -struct FILEDeleter { - void operator()(FILE* fd) { - if (fd) { - fclose(fd); - } - } -}; - class OutputFile : public ModOutput, public ModMetadata { public: @@ -65,6 +57,8 @@ protected: EtiSource *myEtiSource = nullptr; std::string myFilename; + + struct FILEDeleter{ void operator()(FILE* fd){ if (fd) fclose(fd); }}; 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.h') 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 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.h') 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