Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size
@ 2023-07-17  0:26 Michael Niedermayer
  2023-07-17  0:26 ` [FFmpeg-devel] [PATCH 2/7] avradio/sdr: compensate for RTLSDR frequency limitations Michael Niedermayer
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:26 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdrdemux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 5a6a9b8894..a545e7cb4c 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1543,7 +1543,7 @@ int ff_sdr_common_init(AVFormatContext *s)
     sdr->fm_iside     = av_malloc(sizeof(*sdr->fm_iside)    * 2 * sdr->fm_block_size_p2);
     sdr->fm_block     = av_malloc(sizeof(*sdr->fm_block)    * 2 * sdr->fm_block_size);
     sdr->fm_iblock    = av_malloc(sizeof(*sdr->fm_iblock)   * 2 * sdr->fm_block_size);
-    sdr->fm_icarrier  = av_malloc(sizeof(*sdr->fm_icarrier) * 2 * sdr->fm_block_size);
+    sdr->fm_icarrier  = av_malloc(sizeof(*sdr->fm_icarrier) * 2 * sdr->fm_block_size_p2);
     sdr->fm_window    = av_malloc(sizeof(*sdr->fm_window)   * 2 * sdr->fm_block_size);
 
     if (!sdr->windowed_block || !sdr->len2block || !sdr->block || !sdr->window || !sdr->fm_window_p2 || !sdr->fm_iside ||
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 2/7] avradio/sdr: compensate for RTLSDR frequency limitations
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
@ 2023-07-17  0:26 ` Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 3/7] avradio/sdrinradio: Print all tunable elements Michael Niedermayer
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:26 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdr.h        |  2 +-
 libavradio/sdrdemux.c   |  9 ++++-----
 libavradio/sdrinradio.c | 10 ++++++++--
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/libavradio/sdr.h b/libavradio/sdr.h
index ac6b7dffe0..dc20415457 100644
--- a/libavradio/sdr.h
+++ b/libavradio/sdr.h
@@ -210,7 +210,7 @@ typedef struct SDRContext {
     /**
      * Setup the hardware for the requested frequency
      */
-    int (*set_frequency_callback)(struct SDRContext *sdr, int64_t frequency);
+    int64_t (*set_frequency_callback)(struct SDRContext *sdr, int64_t frequency);
 
     /**
      * Read from the hardware, block if nothing available with a reasonable timeout
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index a545e7cb4c..5a3af23a74 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1129,11 +1129,10 @@ ModulationDescriptor ff_sdr_modulation_descs[] = {
 int ff_sdr_set_freq(SDRContext *sdr, int64_t freq)
 {
     freq = av_clip64(freq, sdr->min_center_freq, sdr->max_center_freq);
-
     if (sdr->set_frequency_callback) {
-        int ret = sdr->set_frequency_callback(sdr, freq);
-        if (ret < 0)
-            return ret;
+        freq = sdr->set_frequency_callback(sdr, freq);
+        if (freq < 0)
+            return freq;
     }
 
     sdr->freq = freq;
@@ -1421,7 +1420,7 @@ static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
         if (sdr->seek_direction && block_counter > 5) {
             sdr->wanted_freq = snap2band(sdr, sdr->wanted_freq, sdr->seek_direction*sdr->bandwidth*0.5);
         }
-        if (sdr->wanted_freq != sdr->freq) {
+        if (fabs(sdr->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);
             //This shouldnt really cause any problem if we just continue on error except that we continue returning data with the previous target frequency range
diff --git a/libavradio/sdrinradio.c b/libavradio/sdrinradio.c
index 0e7442fddf..f078d27e7b 100644
--- a/libavradio/sdrinradio.c
+++ b/libavradio/sdrinradio.c
@@ -68,7 +68,7 @@ static int sdrindev_read_callback(SDRContext *sdr, FIFOElement *fifo_element, in
     return ret;
 }
 
-static int sdrindev_set_frequency_callback(SDRContext *sdr, int64_t freq)
+static int64_t sdrindev_set_frequency_callback(SDRContext *sdr, int64_t freq)
 {
     AVFormatContext *avfmt = sdr->avfmt;
     SoapySDRDevice *soapy = sdr->soapy;
@@ -83,6 +83,12 @@ static int sdrindev_set_frequency_callback(SDRContext *sdr, int64_t freq)
                 } else
                     sdr->current_direct_samp = value;
             }
+            //The R820T has a 16 bit fractional PLL which can do only multiplies of 439.45
+            //Its more complex but this approximation works
+            //It has to be noted that SOAPY does not tell us about this, instead saopy
+            //pretends whatever we ask for we get exactly, but we dont
+            //For more details see: michelebavaro.blogspot.com/2014/05/gnss-carrier-phase-rtlsdr-and.html
+            freq = lrint(freq / 439.45) * 439.45;
         }
 
         if (SoapySDRDevice_setFrequency(soapy, SOAPY_SDR_RX, 0, freq, NULL) != 0) {
@@ -90,7 +96,7 @@ static int sdrindev_set_frequency_callback(SDRContext *sdr, int64_t freq)
             return AVERROR_EXTERNAL;
         }
     }
-    return 0;
+    return freq;
 }
 
 static void print_and_free_list(AVFormatContext *s, char** names, size_t length, const char *title)
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 3/7] avradio/sdrinradio: Print all tunable elements
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
  2023-07-17  0:26 ` [FFmpeg-devel] [PATCH 2/7] avradio/sdr: compensate for RTLSDR frequency limitations Michael Niedermayer
@ 2023-07-17  0:27 ` Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 4/7] avradio/sdrdemux: Use a local noise floor in FM Probing Michael Niedermayer
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdrinradio.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libavradio/sdrinradio.c b/libavradio/sdrinradio.c
index f078d27e7b..3956c18375 100644
--- a/libavradio/sdrinradio.c
+++ b/libavradio/sdrinradio.c
@@ -184,6 +184,10 @@ static int sdrindev_initial_hw_setup(AVFormatContext *s)
     names = SoapySDRDevice_listAntennas(soapy, SOAPY_SDR_RX, 0, &length);
     print_and_free_list(s, names, length, "Antennas");
 
+    //Go over all tunable elements
+    names = SoapySDRDevice_listFrequencies(soapy, SOAPY_SDR_RX, 0, &length);
+    print_and_free_list(s, names, length, "Tunables");
+
     //Go over all Gain Elements and print them
     names = SoapySDRDevice_listGains(soapy, SOAPY_SDR_RX, 0, &length);
     print_and_free_list(s, names, length, "Rx Gain Elements");
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 4/7] avradio/sdrdemux: Use a local noise floor in FM Probing
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
  2023-07-17  0:26 ` [FFmpeg-devel] [PATCH 2/7] avradio/sdr: compensate for RTLSDR frequency limitations Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 3/7] avradio/sdrinradio: Print all tunable elements Michael Niedermayer
@ 2023-07-17  0:27 ` Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 5/7] avradio/sdrdemux: adjust bandwidth to 200khz for FM probing Michael Niedermayer
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

The global one caused problems when the spectrum is not flat

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdrdemux.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 5a3af23a74..a4c590acf2 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -861,17 +861,20 @@ static int probe_fm(SDRContext *sdr)
     int i;
     int bandwidth_f  = sdr->fm_bandwidth;
     int half_bw_i = bandwidth_f * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
+    int floor_bw_i = 10*1000 * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
     float last_score[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
     int border_i = (sdr->sdr_sample_rate - FFMIN(sdr->bandwidth, sdr->sdr_sample_rate*7/8)) * sdr->block_size / sdr->sdr_sample_rate;
-    double noise_floor = FLT_MAX;
 
     if (2*half_bw_i > 2*sdr->block_size)
         return 0;
 
-    for (int pass = 0; pass < 2; pass ++) {
+    {
         double avg[2] = {0}, tri = 0;
+        double floor[2] = {0};
         double mean = 0;
         double center = 0;
+        float floor_compensation = half_bw_i * half_bw_i / (float)floor_bw_i;
+
         for (i = 0; i<half_bw_i; i++) {
             avg[0] += sdr->len2block[i];
             tri    += i*sdr->len2block[i];
@@ -883,12 +886,19 @@ static int probe_fm(SDRContext *sdr)
             mean   += i*sdr->len2block[i];
         }
 
+        for (i=0; i<floor_bw_i; i++)
+            floor[0] += sdr->len2block[i];
+        for (i=2*half_bw_i - floor_bw_i; i<2*half_bw_i; i++)
+            floor[1] += sdr->len2block[i];
+
         for(i = half_bw_i; i<2*sdr->block_size - half_bw_i; i++) {
             double b = avg[0] + sdr->len2block[i];
             avg[0] += sdr->len2block[i] - sdr->len2block[i - half_bw_i];
             avg[1] -= sdr->len2block[i] - sdr->len2block[i + half_bw_i];
             b += avg[1];
             tri += avg[1] - avg[0];
+            floor[0] += sdr->len2block[i - half_bw_i + floor_bw_i] - sdr->len2block[i - half_bw_i];
+            floor[1] -= sdr->len2block[i + half_bw_i - floor_bw_i] - sdr->len2block[i + half_bw_i];
 
             mean += (i+half_bw_i)*sdr->len2block[i+half_bw_i];
             center = mean / b;
@@ -897,17 +907,24 @@ static int probe_fm(SDRContext *sdr)
             if (i < border_i || i > 2*sdr->block_size - border_i)
                 continue;
 
-            if (pass == 0) {
-                noise_floor = FFMIN(noise_floor, tri);
-            } else {
+            {
+                float noise_floor;
+                if (i - half_bw_i < border_i) {
+                    noise_floor = floor[1];
+                } else if (i + half_bw_i >= 2*sdr->block_size - border_i) {
+                    noise_floor = floor[0];
+                } else
+                    noise_floor = (floor[0] + floor[1])/2;
+                noise_floor *= floor_compensation;
+
                 last_score[2] = last_score[1];
                 last_score[1] = last_score[0];
-                last_score[0] = tri / (noise_floor);
+                last_score[0] = tri;
 
                 if (last_score[1] >= last_score[0] &&
                     last_score[1] > last_score[2] &&
-                    last_score[1] > sdr->fm_threshold) {
-                    double score = last_score[1];
+                    last_score[1] / noise_floor > sdr->fm_threshold) {
+                    double score = last_score[1] / noise_floor;
 
                     float rmax   = max_in_range(sdr, i-half_bw_i/4, i+half_bw_i/4);
                     int lowcount = countbelow(sdr, i-half_bw_i/4, i+half_bw_i/4, rmax / 100);
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 5/7] avradio/sdrdemux: adjust bandwidth to 200khz for FM probing
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
                   ` (2 preceding siblings ...)
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 4/7] avradio/sdrdemux: Use a local noise floor in FM Probing Michael Niedermayer
@ 2023-07-17  0:27 ` Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 6/7] avradio/sdr: Support setting gain value manually and automatic Michael Niedermayer
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

This improves the local noise floor value

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdrdemux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index a4c590acf2..a0b80785ef 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -860,7 +860,7 @@ static int probe_fm(SDRContext *sdr)
 {
     int i;
     int bandwidth_f  = sdr->fm_bandwidth;
-    int half_bw_i = bandwidth_f * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
+    int half_bw_i = 200*1000 * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
     int floor_bw_i = 10*1000 * (int64_t)sdr->block_size / sdr->sdr_sample_rate;
     float last_score[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
     int border_i = (sdr->sdr_sample_rate - FFMIN(sdr->bandwidth, sdr->sdr_sample_rate*7/8)) * sdr->block_size / sdr->sdr_sample_rate;
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 6/7] avradio/sdr: Support setting gain value manually and automatic
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
                   ` (3 preceding siblings ...)
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 5/7] avradio/sdrdemux: adjust bandwidth to 200khz for FM probing Michael Niedermayer
@ 2023-07-17  0:27 ` Michael Niedermayer
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 7/7] avradio/sdr: workaround inverted gain parameter on sdrplay Michael Niedermayer
  2023-07-18 21:26 ` [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdr.h        | 23 +++++++++++++++++-
 libavradio/sdrdemux.c   | 53 ++++++++++++++++++++++++++++++++++++++++-
 libavradio/sdrinradio.c | 41 +++++++++++++++++++++++++++++--
 3 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/libavradio/sdr.h b/libavradio/sdr.h
index dc20415457..395b056531 100644
--- a/libavradio/sdr.h
+++ b/libavradio/sdr.h
@@ -68,6 +68,12 @@ typedef enum Modulation {
     //QAM, PSK, ...
 } Modulation;
 
+typedef enum SDR_GAIN {
+    GAIN_DEFAULT = -3,
+    GAIN_SW_AGC = -2,
+    GAIN_SDR_AGC = -1,
+} SDR_GAIN;
+
 #define HISTOGRAMM_SIZE 9
 
 typedef struct Station {
@@ -105,6 +111,7 @@ typedef struct Station {
 
 typedef struct FIFOElement {
     int64_t center_frequency;
+    float gain;
     void *halfblock;
 } FIFOElement;
 
@@ -146,7 +153,15 @@ typedef struct SDRContext {
     int64_t min_center_freq;
     int64_t max_center_freq;
     int sdr_sample_rate;
-    int sdr_agc;
+    float min_gain;
+    float max_gain;
+    int sdr_gain;
+    float agc_min_headroom;
+    float agc_max_headroom;
+    float agc_max_headroom_time;
+    int agc_low_time;
+    float agc_gain;                         ///< current gain, should be accessed only by buffer thread after init
+    atomic_int wanted_gain;
     int sdr_adcc;
     int64_t bandwidth;
     int64_t last_pts;
@@ -212,6 +227,12 @@ typedef struct SDRContext {
      */
     int64_t (*set_frequency_callback)(struct SDRContext *sdr, int64_t frequency);
 
+    /**
+     * Setup the hardware for the requested gain
+     * This must only be called from the buffer thread after setup (or more mutex calls are needed)
+     */
+    int (*set_gain_callback)(struct SDRContext *sdr, float gain);
+
     /**
      * Read from the hardware, block if nothing available with a reasonable timeout
      *
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index a0b80785ef..5214aea7be 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -1409,6 +1409,7 @@ static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
         FIFOElement fifo_element;
         int remaining, ret;
         int empty_blocks, full_blocks;
+        float wanted_gain = atomic_load(&sdr->wanted_gain) / 65536.0;
 
         //i wish av_fifo was thread safe
         pthread_mutex_lock(&sdr->mutex);
@@ -1444,9 +1445,17 @@ static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
             //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
         }
+        if (sdr->sdr_gain == GAIN_SW_AGC &&
+            fabs(wanted_gain - sdr->agc_gain) > 0.001 &&
+            sdr->set_gain_callback
+        ) {
+            sdr->set_gain_callback(sdr, wanted_gain);
+            sdr->agc_gain = wanted_gain;
+        }
         pthread_mutex_unlock(&sdr->mutex);
 
         fifo_element.center_frequency = block_counter > 0 ? sdr->freq : 0;
+        fifo_element.gain             = sdr->agc_gain; //we make only small changes so slightly mixing should be ok
 
         remaining = sdr->block_size;
         while (remaining && !atomic_load(&sdr->close_requested)) {
@@ -1624,6 +1633,7 @@ 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->wanted_gain, lrint((sdr->min_gain + sdr->max_gain) * 65536 / 2));
     ret = pthread_mutex_init(&sdr->mutex, NULL);
     if (ret) {
         av_log(s, AV_LOG_ERROR, "pthread_mutex_init failed: %s\n", strerror(ret));
@@ -1886,6 +1896,37 @@ process_next_block:
         }
     }
 
+    float smaller_block_gain = FFMIN(fifo_element[0].gain, fifo_element[1].gain);
+    float  bigger_block_gain = FFMAX(fifo_element[0].gain, fifo_element[1].gain);
+
+    if (sdr->sdr_gain == GAIN_SW_AGC) {
+        float inmax = 0;
+        float wanted_gain = atomic_load(&sdr->wanted_gain) / 65536.0;
+        // We only check 25% of the data to safe computations
+        int start = 3*sdr->block_size / 4;
+        int end   = 5*sdr->block_size / 4;
+        for (i = start; i < end; i++) {
+            float v = fmaxf(fabsf(sdr->windowed_block[i].re), fabsf(sdr->windowed_block[i].im));
+            inmax = fmaxf(inmax, v);
+        }
+
+        if (inmax > 1.0 - sdr->agc_min_headroom && wanted_gain > sdr->min_gain) {
+            //according to docs this is a dB scale, in reality it beheaves differnt to that
+            //Because of this we will try to just make small changes and not assume too much
+            wanted_gain = FFMIN(wanted_gain, FFMAX(smaller_block_gain - 1.0, smaller_block_gain * 0.9));
+
+            sdr->agc_low_time = 0;
+        } else if (inmax < 1.0 - sdr->agc_max_headroom && wanted_gain < sdr->max_gain) {
+            sdr->agc_low_time += sdr->block_size;
+            if (sdr->agc_low_time > sdr->agc_max_headroom_time * sdr->sdr_sample_rate) {
+                sdr->agc_low_time = 0;
+                wanted_gain = FFMAX(wanted_gain, FFMIN(bigger_block_gain + 1.0, bigger_block_gain * 1.1));
+            }
+        } else
+            sdr->agc_low_time = 0;
+        atomic_store(&sdr->wanted_gain, (int)lrint(wanted_gain * 65536));
+    }
+
     inject_block_into_fifo(sdr, sdr->empty_block_fifo, &fifo_element[0], "Cannot pass next buffer, freeing it\n");
 #ifdef SYN_TEST //synthetic test signal
     static int64_t synp=0;
@@ -2141,7 +2182,17 @@ const AVOption ff_sdr_options[] = {
     { "rtlsdr_fixes" , "workaround rtlsdr issues", OFFSET(rtlsdr_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_agc" , "sdr automatic gain control",  OFFSET(sdr_agc),  AV_OPT_TYPE_BOOL , {.i64 =  1}, -1, 1, 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"},
+        { "default_gain", "Never touch gain", 0, AV_OPT_TYPE_CONST, {.i64 = GAIN_DEFAULT}, 0, 0, DEC, "gain"},
+
+    { "agc_min_headroom",  "AGC min headroom",  OFFSET(agc_min_headroom),  AV_OPT_TYPE_FLOAT, {.dbl = 0.4}, 0, 1.0, DEC},
+    { "agc_max_headroom",  "AGC max headroom",  OFFSET(agc_max_headroom),  AV_OPT_TYPE_FLOAT, {.dbl = 0.8}, 0, 1.0, DEC},
+    { "agc_max_headroom_time",  "AGC max headroom time",  OFFSET(agc_max_headroom_time),  AV_OPT_TYPE_FLOAT, {.dbl = 0.1}, 0, INT_MAX, DEC},
+    { "min_gain", "minimum gain", OFFSET(min_gain   ), AV_OPT_TYPE_FLOAT , {.dbl = 0}, 0, INT_MAX, DEC},
+    { "max_gain", "maximum gain", OFFSET(max_gain   ), AV_OPT_TYPE_FLOAT , {.dbl = 0}, 0, INT_MAX, DEC},
+
     { "sdr_adcc" ,"sdr automatic dc correction", OFFSET(sdr_adcc), AV_OPT_TYPE_BOOL , {.i64 = -1}, -1, 1, DEC},
     { "min_freq", "minimum frequency", OFFSET(min_freq   ), AV_OPT_TYPE_INT64 , {.i64 = 0}, 0, INT64_MAX, DEC},
     { "max_freq", "maximum frequency", OFFSET(max_freq   ), AV_OPT_TYPE_INT64 , {.i64 = 0}, 0, INT64_MAX, DEC},
diff --git a/libavradio/sdrinradio.c b/libavradio/sdrinradio.c
index 3956c18375..63a9cade78 100644
--- a/libavradio/sdrinradio.c
+++ b/libavradio/sdrinradio.c
@@ -68,6 +68,30 @@ static int sdrindev_read_callback(SDRContext *sdr, FIFOElement *fifo_element, in
     return ret;
 }
 
+static int sdrindev_set_gain_callback(SDRContext *sdr, float gain)
+{
+    AVFormatContext *avfmt = sdr->avfmt;
+    SoapySDRDevice *soapy = sdr->soapy;
+
+    if (sdr->sdr_gain == GAIN_DEFAULT)
+        return 0;
+
+    if (soapy) {
+        int ret = SoapySDRDevice_setGainMode(soapy, SOAPY_SDR_RX, 0, sdr->sdr_gain == GAIN_SDR_AGC);
+        if (ret) {
+            av_log(avfmt, AV_LOG_WARNING, "Failed to set gain mode %d (%s)\n", sdr->sdr_gain == GAIN_SDR_AGC, SoapySDRDevice_lastError());
+        }
+
+        if (sdr->sdr_gain != GAIN_SDR_AGC) {
+            ret = SoapySDRDevice_setGain(soapy, SOAPY_SDR_RX, 0, gain);
+            if (ret) {
+                av_log(avfmt, AV_LOG_WARNING, "Failed to set gain to %f (%s)\n", gain, SoapySDRDevice_lastError());
+            }
+        }
+    }
+    return 0;
+}
+
 static int64_t sdrindev_set_frequency_callback(SDRContext *sdr, int64_t freq)
 {
     AVFormatContext *avfmt = sdr->avfmt;
@@ -135,6 +159,7 @@ static int sdrindev_initial_hw_setup(AVFormatContext *s)
 
     sdr->read_callback          = sdrindev_read_callback;
     sdr->set_frequency_callback = sdrindev_set_frequency_callback;
+    sdr->set_gain_callback      = sdrindev_set_gain_callback;
 
     // Go over all available soapy devices
     // Print the usable ones, and choose one unless the user has choosen one
@@ -195,8 +220,10 @@ static int sdrindev_initial_hw_setup(AVFormatContext *s)
     //Inform the user if AGC is supported and setup AGC as requested by the user
     has_agc = SoapySDRDevice_hasGainMode(soapy, SOAPY_SDR_RX, 0);
     av_log(s, AV_LOG_INFO, "RX AGC Supported: %s\n", has_agc ? "yes" : "no");
-    if (has_agc && sdr->sdr_agc >= 0)
-        SoapySDRDevice_setGainMode(soapy, SOAPY_SDR_RX, 0, sdr->sdr_agc);
+    if (!has_agc &&  sdr->sdr_gain == GAIN_SDR_AGC) {
+        av_log(s, AV_LOG_WARNING, "hardware AGC unsupported switching to software AGC\n");
+        sdr->sdr_gain = GAIN_SW_AGC;
+    }
 
     //Inform the user if automatic DC correction is supported and setup DC correction as requested by the user
     has_adcc = SoapySDRDevice_hasDCOffsetMode(soapy, SOAPY_SDR_RX, 0);
@@ -208,6 +235,16 @@ static int sdrindev_initial_hw_setup(AVFormatContext *s)
     range = SoapySDRDevice_getGainRange(soapy, SOAPY_SDR_RX, 0);
     av_log(s, AV_LOG_INFO, "Rx Gain range: %f dB - %f dB\n", range.minimum, range.maximum);
 
+    if (!sdr->min_gain)
+        sdr->min_gain = range.minimum;
+
+    if (!sdr->max_gain)
+        sdr->max_gain = range.maximum;
+    if (sdr->min_gain > sdr->max_gain) {
+        av_log(s, AV_LOG_ERROR, "Invalid gain range\n");
+        return AVERROR(EINVAL);
+    }
+
     //Inform the user about the Frequency ranges available, verify the range requested by the user and set the range if the user has not specified one
     ranges = SoapySDRDevice_getFrequencyRange(soapy, SOAPY_SDR_RX, 0, &length);
     av_log(s, AV_LOG_INFO, "Rx freq ranges: ");
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [FFmpeg-devel] [PATCH 7/7] avradio/sdr: workaround inverted gain parameter on sdrplay
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
                   ` (4 preceding siblings ...)
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 6/7] avradio/sdr: Support setting gain value manually and automatic Michael Niedermayer
@ 2023-07-17  0:27 ` Michael Niedermayer
  2023-07-18 21:26 ` [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-17  0:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavradio/sdr.h        | 1 +
 libavradio/sdrdemux.c   | 1 +
 libavradio/sdrinradio.c | 7 +++++++
 3 files changed, 9 insertions(+)

diff --git a/libavradio/sdr.h b/libavradio/sdr.h
index 395b056531..27ec1db4f3 100644
--- a/libavradio/sdr.h
+++ b/libavradio/sdr.h
@@ -257,6 +257,7 @@ typedef struct SDRContext {
     int missing_streams;
 
     int rtlsdr_fixes;
+    int sdrplay_fixes;
 } SDRContext;
 
 typedef struct ModulationDescriptor {
diff --git a/libavradio/sdrdemux.c b/libavradio/sdrdemux.c
index 5214aea7be..1b3061a406 100644
--- a/libavradio/sdrdemux.c
+++ b/libavradio/sdrdemux.c
@@ -2180,6 +2180,7 @@ const AVOption ff_sdr_options[] = {
 
     { "driver"  , "sdr driver name"  , OFFSET(driver_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC},
     { "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},
     { "gain" , "sdr overall gain",  OFFSET(sdr_gain),  AV_OPT_TYPE_INT , {.i64 =  GAIN_SDR_AGC}, -3, INT_MAX, DEC, "gain"},
diff --git a/libavradio/sdrinradio.c b/libavradio/sdrinradio.c
index 63a9cade78..f824a1d190 100644
--- a/libavradio/sdrinradio.c
+++ b/libavradio/sdrinradio.c
@@ -76,6 +76,11 @@ static int sdrindev_set_gain_callback(SDRContext *sdr, float gain)
     if (sdr->sdr_gain == GAIN_DEFAULT)
         return 0;
 
+    //sdrplay has a inverted gain range, not using max_gain as this is a user parameter
+    if (sdr->sdrplay_fixes > 0) {
+        gain = FFMIN(48 - gain, 45);
+    }
+
     if (soapy) {
         int ret = SoapySDRDevice_setGainMode(soapy, SOAPY_SDR_RX, 0, sdr->sdr_gain == GAIN_SDR_AGC);
         if (ret) {
@@ -192,6 +197,8 @@ static int sdrindev_initial_hw_setup(AVFormatContext *s)
 
     if (sdr->rtlsdr_fixes < 0)
         sdr->rtlsdr_fixes = !strcmp(sdr->driver_name, "rtlsdr");
+    if (sdr->sdrplay_fixes < 0)
+        sdr->sdrplay_fixes = !strcmp(sdr->driver_name, "sdrplay");
 
     SoapySDRKwargs_set(&args, "driver", sdr->driver_name);
     sdr->soapy = soapy = SoapySDRDevice_make(&args);
-- 
2.31.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size
  2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
                   ` (5 preceding siblings ...)
  2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 7/7] avradio/sdr: workaround inverted gain parameter on sdrplay Michael Niedermayer
@ 2023-07-18 21:26 ` Michael Niedermayer
  6 siblings, 0 replies; 8+ messages in thread
From: Michael Niedermayer @ 2023-07-18 21:26 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 509 bytes --]

On Mon, Jul 17, 2023 at 02:26:58AM +0200, Michael Niedermayer wrote:
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
>  libavradio/sdrdemux.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

will apply patchset

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Homeopathy is like voting while filling the ballot out with transparent ink.
Sometimes the outcome one wanted occurs. Rarely its worse than filling out
a ballot properly.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-07-18 21:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-17  0:26 [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer
2023-07-17  0:26 ` [FFmpeg-devel] [PATCH 2/7] avradio/sdr: compensate for RTLSDR frequency limitations Michael Niedermayer
2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 3/7] avradio/sdrinradio: Print all tunable elements Michael Niedermayer
2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 4/7] avradio/sdrdemux: Use a local noise floor in FM Probing Michael Niedermayer
2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 5/7] avradio/sdrdemux: adjust bandwidth to 200khz for FM probing Michael Niedermayer
2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 6/7] avradio/sdr: Support setting gain value manually and automatic Michael Niedermayer
2023-07-17  0:27 ` [FFmpeg-devel] [PATCH 7/7] avradio/sdr: workaround inverted gain parameter on sdrplay Michael Niedermayer
2023-07-18 21:26 ` [FFmpeg-devel] [PATCH 1/7] avradio/sdrdemux: icarrier just needs phase 2 block size Michael Niedermayer

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git