This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.
Baffo32 0xloem at gmail.comFrom: Karl Semich <0xloem at gmail.com> Previously overflow was handled by outputting "O" on stderr and placing the extra data at the start of the buffer queue. This had a number of issues: - as only 1 buffer advanced on overflow, many overflows could occur in sequence, as only small amounts of data was allowed to drain - if the work function was partway through reading the head of the queue, it would continue reading at the same offset from the new head rather than from the start, causing extra loss of data - buffer processing in work function is not guarded with a lock, so it was possible for overflow to overwrite data while it was being copied, resulting in garbage passed on This patch rewrites overflow handling such that streaming is paused until the work function can catch up. This resolves all 3 issues. --- lib/rtl/rtl_source_c.cc | 32 ++++++++++++++++++++++++++------ lib/rtl/rtl_source_c.h | 2 ++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/rtl/rtl_source_c.cc b/lib/rtl/rtl_source_c.cc index a371464..0d26831 100644 --- a/lib/rtl/rtl_source_c.cc +++ b/lib/rtl/rtl_source_c.cc @@ -48,6 +48,7 @@ using namespace boost::assign; #define BUF_LEN (16 * 32 * 512) /* must be multiple of 512 */ #define BUF_NUM 15 #define BUF_SKIP 1 // buffers to skip due to initial garbage +#define BUF_MIN 3 /* minimum buffers to run work function */ #define BYTES_PER_SAMPLE 2 // rtl device delivers 8 bit unsigned IQ data @@ -87,8 +88,7 @@ rtl_source_c::rtl_source_c (const std::string &args) _running(false), _no_tuner(false), _auto_gain(false), - _if_gain(0), - _skipped(0) + _if_gain(0) { int ret; int index; @@ -297,6 +297,9 @@ void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len) return; } + if (_overflow) + return; + { boost::mutex::scoped_lock lock( _buf_mutex ); @@ -304,8 +307,9 @@ void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len) memcpy(_buf[buf_tail], buf, len); if (_buf_used == _buf_num) { - std::cerr << "O" << std::flush; - _buf_head = (_buf_head + 1) % _buf_num; + std::cerr << "OVERFLOW: rtl-sdr stream restarting after draining unread buffers" << std::endl; + _overflow = true; + rtlsdr_cancel_async( _dev ); } else { _buf_used++; } @@ -321,7 +325,20 @@ void rtl_source_c::_rtlsdr_wait(rtl_source_c *obj) void rtl_source_c::rtlsdr_wait() { - int ret = rtlsdr_read_async( _dev, _rtlsdr_callback, (void *)this, _buf_num, _buf_len ); + int ret; + + do { + { + boost::mutex::scoped_lock lock( _buf_mutex ); + // let unread buffers from last run drain + while ( _buf_used >= BUF_MIN ) + _work_cond.wait( lock ); + } + + _overflow = false; + _skipped = 0; + ret = rtlsdr_read_async( _dev, _rtlsdr_callback, (void *)this, _buf_num, _buf_len ); + } while ( _overflow ); _running = false; @@ -340,7 +357,7 @@ int rtl_source_c::work( int noutput_items, { boost::mutex::scoped_lock lock( _buf_mutex ); - while (_buf_used < 3 && _running) // collect at least 3 buffers + while (_buf_used < BUF_MIN && _running) // collect at least BUF_MIN buffers _buf_cond.wait( lock ); } @@ -364,6 +381,9 @@ int rtl_source_c::work( int noutput_items, _buf_head = (_buf_head + 1) % _buf_num; _buf_used--; } + + _work_cond.notify_one(); + _samp_avail = _buf_len / BYTES_PER_SAMPLE; _buf_offset = 0; } else { diff --git a/lib/rtl/rtl_source_c.h b/lib/rtl/rtl_source_c.h index 902b386..aafea5f 100644 --- a/lib/rtl/rtl_source_c.h +++ b/lib/rtl/rtl_source_c.h @@ -133,6 +133,8 @@ private: unsigned int _buf_used; boost::mutex _buf_mutex; boost::condition_variable _buf_cond; + boost::condition_variable _work_cond; + bool _overflow; bool _running; unsigned int _buf_offset; -- 2.11.0