[FFmpeg-devel] [PATCH 02/12] avradio/avformat/sdrdemux: Move Software AGC into buffer thread
Michael Niedermayer
michael at niedermayer.cc
Mon Jul 31 01:11:21 EEST 2023
This allows the AGC to act with less latency
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
libavformat/sdr.h | 1 -
libavformat/sdrdemux.c | 77 ++++++++++++++++++++++++------------------
2 files changed, 44 insertions(+), 34 deletions(-)
diff --git a/libavformat/sdr.h b/libavformat/sdr.h
index 1f2d3a49ab..1bf8fbef79 100644
--- a/libavformat/sdr.h
+++ b/libavformat/sdr.h
@@ -161,7 +161,6 @@ typedef struct SDRContext {
float agc_max_headroom;
float agc_max_headroom_time;
int agc_low_time;
- atomic_int wanted_gain;
int sdr_adcc;
int64_t bandwidth;
int64_t last_pts;
diff --git a/libavformat/sdrdemux.c b/libavformat/sdrdemux.c
index 4bde431e17..e5ee4e80f5 100644
--- a/libavformat/sdrdemux.c
+++ b/libavformat/sdrdemux.c
@@ -1475,6 +1475,7 @@ static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
unsigned block_counter = 0;
int64_t local_wanted_freq = 0;
int64_t last_wanted_freq = 0;
+ float wanted_gain = (sdr->min_gain + sdr->max_gain) / 2;
float agc_gain = 0;
sdr->remaining_file_block_size = 0;
@@ -1485,7 +1486,6 @@ 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;
int64_t wanted_freq = atomic_load(&sdr->wanted_freq);
int seek_direction = atomic_load(&sdr->seek_direction);
@@ -1551,6 +1551,49 @@ static void *soapy_needs_bigger_buffers_worker(SDRContext *sdr)
remaining -= ret;
}
+ if (sdr->sdr_gain == GAIN_SW_AGC) {
+ float inmax = 0;
+ int inmax1 = 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;
+ if (sdr->sample_size == 2) {
+ const int8_t *halfblock = fifo_element.halfblock;
+ for (int i = start; i < end; i++) {
+ int v = FFMAX(FFABS(halfblock[i]), FFABS(halfblock[i]));
+ inmax1 = FFMAX(inmax1, v);
+ }
+ } else if (sdr->sample_size == 4) {
+ const int16_t *halfblock = fifo_element.halfblock;
+ for (int i = start; i < end; i++) {
+ int v = FFMAX(FFABS(halfblock[i]), FFABS(halfblock[i]));
+ inmax1 = FFMAX(inmax1, v);
+ }
+ } else {
+ const float *halfblock = fifo_element.halfblock;
+ for (int i = start; i < end; i++) {
+ float v = fmaxf(fabsf(halfblock[i]), fabsf(halfblock[i]));
+ inmax = fmaxf(inmax, v);
+ }
+ }
+ inmax = fmaxf(inmax, inmax1 / sdr->sample_scale);
+
+ 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(agc_gain - 1.0, agc_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(agc_gain + 1.0, agc_gain * 1.1));
+ }
+ } else
+ sdr->agc_low_time = 0;
+ }
+
inject_block_into_fifo(sdr, sdr->full_block_fifo, &fifo_element, "block fifo overflow, discarding block\n");
}
av_assert0(atomic_load(&sdr->close_requested) == 1);
@@ -1724,7 +1767,6 @@ int avpriv_sdr_common_init(AVFormatContext *s)
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) {
av_log(s, AV_LOG_ERROR, "pthread_mutex_init failed: %s\n", strerror(ret));
@@ -2021,37 +2063,6 @@ 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;
--
2.31.1
More information about the ffmpeg-devel
mailing list