diff mbox series

[FFmpeg-devel,11/14] avradio/sdr: More atomics, less Mutexes

Message ID 20230718214542.685375-11-michael@niedermayer.cc
State New
Headers show
Series [FFmpeg-devel,01/14] avradio/sdrdemux: Add Mittelwelle / Mediumwave / Mediumfrequency band | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Michael Niedermayer July 18, 2023, 9:45 p.m. UTC
Maybe this is cleaner

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdr.h      |  5 +++--
 libavradio/sdrdemux.c | 38 +++++++++++++++++++++++---------------
 2 files changed, 26 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/libavradio/sdr.h b/libavradio/sdr.h
index 27ec1db4f3..3f76aec2a6 100644
--- a/libavradio/sdr.h
+++ b/libavradio/sdr.h
@@ -172,6 +172,7 @@  typedef struct SDRContext {
     AVComplexFloat *windowed_block;
     int64_t block_center_freq;              ///< center frequency the current block contains
     int64_t station_freq;
+    int64_t user_wanted_freq;
     int sample_size;
     double sample_scale;
 
@@ -218,8 +219,8 @@  typedef struct SDRContext {
     AVFifo *empty_block_fifo;
     AVFifo *full_block_fifo;
     atomic_int close_requested;
-    int64_t wanted_freq;                    ///< center frequency we want the hw to provide next
-    int seek_direction;                     ///< if a seek is requested this is -1 or 1 otherwise 0
+    atomic_int_least64_t wanted_freq;       ///< center frequency we want the hw to provide next, only written to by main thread
+    atomic_int seek_direction;              ///< if a seek is requested this is -1 or 1 otherwise 0, only written to by main thread
     int skip_probe;
 
     /**
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index d5ea2d85b4..a9ddf93733 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1351,14 +1351,12 @@  static int snap2station(SDRContext *sdr, int *seek_direction) {
             return ret;
         }
 
-        pthread_mutex_lock(&sdr->mutex);
-        *seek_direction     =
-        sdr->seek_direction = 0;
-        sdr->wanted_freq = wanted_freq;
+        *seek_direction     = 0;
+        atomic_store(&sdr->seek_direction, 0);
+        atomic_store(&sdr->wanted_freq, wanted_freq);
         //200*1000 had artifacts
 
-        av_log(avfmt, AV_LOG_DEBUG, "request f = %"PRId64"\n", sdr->wanted_freq);
-        pthread_mutex_unlock(&sdr->mutex);
+        av_log(avfmt, AV_LOG_DEBUG, "request f = %"PRId64"\n", atomic_load(&sdr->wanted_freq));
         return 1;
     }
 
@@ -1426,6 +1424,8 @@  static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
 {
     AVFormatContext *avfmt = sdr->avfmt;
     unsigned block_counter = 0;
+    int64_t local_wanted_freq = 0;
+    int64_t last_wanted_freq = 0;
 
     sdr->remaining_file_block_size = 0;
 
@@ -1436,6 +1436,8 @@  static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
         int remaining, ret;
         int empty_blocks, full_blocks;
         float wanted_gain = atomic_load(&sdr->wanted_gain) / 65536.0;
+        int64_t wanted_freq = atomic_load(&sdr->wanted_freq);
+        int seek_direction = atomic_load(&sdr->seek_direction);
 
         //i wish av_fifo was thread safe
         pthread_mutex_lock(&sdr->mutex);
@@ -1457,16 +1459,22 @@  static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
 
         block_counter ++;
         pthread_mutex_lock(&sdr->mutex);
+        // Has the main thread changed the wanted frequency ? if so lets reset our loop to it
+        if (wanted_freq != last_wanted_freq) {
+            local_wanted_freq =
+            last_wanted_freq = wanted_freq;
+        }
+
         // we try to get 2 clean blocks after windowing, to improve chances scanning doesnt miss too much
         // First block after parameter change is not reliable, we do not assign it any frequency
         // 2 blocks are needed with windowing to get a clean FFT output
         // Thus > 3 is the minimum for the next frequency update if we want to do something reliable with the data
-        if (sdr->seek_direction && block_counter > 5) {
-            sdr->wanted_freq = snap2band(sdr, sdr->wanted_freq, sdr->seek_direction*sdr->bandwidth*0.5);
+        if (seek_direction && block_counter > 5) {
+            local_wanted_freq = snap2band(sdr, local_wanted_freq, seek_direction*sdr->bandwidth*0.5);
         }
-        if (fabs(sdr->wanted_freq - sdr->freq) > 1500) {
+        if (fabs(local_wanted_freq - sdr->freq) > 1500) {
             //We could use a seperate MUTEX for the FIFO and for soapy
-            ff_sdr_set_freq(sdr, sdr->wanted_freq);
+            ff_sdr_set_freq(sdr, local_wanted_freq);
             //This shouldnt really cause any problem if we just continue on error except that we continue returning data with the previous target frequency range
             //And theres not much else we can do, an error message was already printed by ff_sdr_set_freq() in that case
             block_counter = 0; // we just changed the frequency, do not trust the next blocks content
@@ -1662,6 +1670,8 @@  int ff_sdr_common_init(AVFormatContext *s)
     av_fifo_auto_grow_limit(sdr-> full_block_fifo, sdr->sdr_sample_rate / sdr->block_size);
 
     atomic_init(&sdr->close_requested, 0);
+    atomic_init(&sdr->seek_direction, 0);
+    atomic_init(&sdr->wanted_freq, sdr->user_wanted_freq);
     atomic_init(&sdr->wanted_gain, lrint((sdr->min_gain + sdr->max_gain) * 65536 / 2));
     ret = pthread_mutex_init(&sdr->mutex, NULL);
     if (ret) {
@@ -1810,8 +1820,8 @@  process_next_block:
     ret = av_fifo_peek(sdr->full_block_fifo, &fifo_element, 2, 0);
     if (ret >= 0)
         av_fifo_drain2(sdr->full_block_fifo, 1);
-    seek_direction = sdr->seek_direction; //This doesnt need a mutex here at all but tools might complain
     pthread_mutex_unlock(&sdr->mutex);
+    seek_direction = atomic_load(&sdr->seek_direction);
 
     if (ret < 0) {
         av_log(s, AV_LOG_DEBUG, "EAGAIN on not enough data\n");
@@ -2094,9 +2104,7 @@  int ff_sdr_read_seek(AVFormatContext *s, int stream_index,
         return ret;
     //snap2station found no station lets command the thread to seek
     if (!ret) {
-        pthread_mutex_lock(&sdr->mutex);
-        sdr->seek_direction = dir;
-        pthread_mutex_unlock(&sdr->mutex);
+        atomic_store(&sdr->seek_direction, dir);
         flush_fifo(sdr, sdr->full_block_fifo);
     }
 
@@ -2207,7 +2215,7 @@  const AVOption ff_sdr_options[] = {
     { "rtlsdr_fixes" , "workaround rtlsdr issues", OFFSET(rtlsdr_fixes), AV_OPT_TYPE_INT , {.i64 = -1}, -1, 1, DEC},
     { "sdrplay_fixes" , "workaround sdrplay issues", OFFSET(sdrplay_fixes), AV_OPT_TYPE_INT , {.i64 = -1}, -1, 1, DEC},
     { "sdr_sr"  , "sdr sample rate"  , OFFSET(sdr_sample_rate ), AV_OPT_TYPE_INT , {.i64 = 0}, 0, INT_MAX, DEC},
-    { "sdr_freq", "sdr frequency"    , OFFSET(wanted_freq), AV_OPT_TYPE_INT64 , {.i64 = 9000000}, 0, INT64_MAX, DEC},
+    { "sdr_freq", "sdr frequency"    , OFFSET(user_wanted_freq), AV_OPT_TYPE_INT64 , {.i64 = 9000000}, 0, INT64_MAX, DEC},
     { "gain" , "sdr overall gain",  OFFSET(sdr_gain),  AV_OPT_TYPE_INT , {.i64 =  GAIN_SDR_AGC}, -3, INT_MAX, DEC, "gain"},
         { "sdr_agc", "SDR AGC (if supported)", 0, AV_OPT_TYPE_CONST, {.i64 = GAIN_SDR_AGC}, 0, 0, DEC, "gain"},
         { "sw_agc", "Software AGC", 0, AV_OPT_TYPE_CONST, {.i64 = GAIN_SW_AGC}, 0, 0, DEC, "gain"},