* [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