PR #21522 opened by realies
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21522
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21522.patch
## Summary
Implements incremental crossfade processing that reduces peak memory usage by
~78% for long crossfades and improves CPU performance by up to 30%.
**Key changes:**
- Process crossfade samples incrementally as input 1 delivers them, instead of
buffering all samples first
- Modified fade curve calculation to accept offset parameter for correct gain
at any position
- Removes 60-second duration limit (memory now scales efficiently)
- Updates `fate-filter-acrossfade` reference (frame boundaries change, audio
samples unchanged)
## Approach
The current implementation waits for ALL `nb_samples` from input 1 before
processing:
```
Input 0 FIFO: [========= nb_samples =========]
Input 1 FIFO: [========= nb_samples =========]
Output frame: [========= nb_samples =========]
Peak memory: ~3 × nb_samples
```
This patch consumes from input 1 incrementally as samples arrive:
```
Input 0 FIFO: [========= nb_samples =========] <- draining as we process
Input 1 FIFO: [~4K] <- small, consumed immediately
Output frame: [~4K] <- small chunks
Peak memory: ~1 × nb_samples
```
The smaller output frames cause `fate-filter-acrossfade` to report different
frame CRCs, but the audio samples are identical (verified via MD5 on final WAV
output).
## Benchmark Results
All results measured using the reproduction script below.
### Memory
| Duration | Baseline | Incremental | Reduction |
|----------|----------|-------------|-----------|
| 1 min | 42 MB | 17 MB | 58% |
| 10 min | 327 MB | 69 MB | 78% |
| 30 min | 833 MB | 184 MB | 77% |
| 60 min | 1668 MB | 357 MB | 78% |
### CPU (3 runs averaged)
| Duration | Baseline | Incremental | Change |
|----------|----------|-------------|--------|
| 1 min | 0.21s | 0.19s | -9% |
| 10 min | 0.34s | 0.27s | -20% |
| 30 min | 0.58s | 0.42s | -27% |
| 60 min | 0.95s | 0.66s | -30% |
## Notes
- **Multi-input support**: Incremental mode is only used for the final
crossfade (last two inputs). Earlier crossfades use the original approach since
intermediate clips need buffering for the next crossfade.
- **Short input handling**: If input duration is shorter than crossfade
duration, the crossfade is gracefully shortened with a warning (matching
original behavior).
- **Large sample counts**: Tested with >UINT32_MAX samples (6.5h crossfade at
192kHz) to verify int64 handling.
<details>
<summary><b>Reproduction Script</b></summary>
```bash
#!/bin/bash
# Reproduces all benchmark results. Requires: Docker, git
set -e
WORKDIR=$(mktemp -d)
trap "rm -rf $WORKDIR" EXIT
cd "$WORKDIR"
git clone --depth 1 -b acrossfade-incremental-memory \
https://github.com/realies/FFmpeg.git ffmpeg-pr
docker run --rm -i \
-v "$WORKDIR/ffmpeg-pr":/src:ro \
-w /build \
ghcr.io/btbn/ffmpeg-builds/linux64-gpl:latest \
bash -c '
set -e
apt-get update -qq && apt-get install -qq -y time bc >/dev/null 2>&1
echo "=== Building INCREMENTAL (this PR) ==="
cp -r /src/* .
./configure --enable-gpl --disable-doc --disable-network --disable-autodetect
--disable-debug --quiet
make -j$(nproc) 2>&1 | tail -1
cp ffmpeg /ffmpeg-incr
echo "=== Building BASELINE (stock + limit removed) ==="
curl -sL
"https://raw.githubusercontent.com/FFmpeg/FFmpeg/master/libavfilter/af_afade.c"
-o libavfilter/af_afade.c
sed -i "s/60000000/INT64_MAX\/2/" libavfilter/af_afade.c
make -j$(nproc) 2>&1 | tail -1
cp ffmpeg /ffmpeg-base
echo "=== Creating test audio (65 min mono 44.1kHz) ==="
/ffmpeg-base -y -f lavfi -i "sine=frequency=440:duration=3900" -ar 44100
/tmp/in1.wav 2>/dev/null
/ffmpeg-base -y -f lavfi -i "sine=frequency=880:duration=3900" -ar 44100
/tmp/in2.wav 2>/dev/null
echo ""
echo "=== OUTPUT VERIFICATION (MD5) ==="
for d in 60 600 1800 3600; do
/ffmpeg-base -y -i /tmp/in1.wav -i /tmp/in2.wav -filter_complex
"acrossfade=d=${d}:c1=tri:c2=tri" /tmp/b.wav 2>/dev/null
/ffmpeg-incr -y -i /tmp/in1.wav -i /tmp/in2.wav -filter_complex
"acrossfade=d=${d}:c1=tri:c2=tri" /tmp/i.wav 2>/dev/null
[ "$(md5sum /tmp/b.wav | cut -d" " -f1)" = "$(md5sum /tmp/i.wav | cut -d" "
-f1)" ] && echo "$((d/60)) min: IDENTICAL" || echo "$((d/60)) min: DIFFER"
done
echo ""
echo "=== EDGE CASE: Short input (10s input, 20s crossfade) ==="
/ffmpeg-base -y -f lavfi -i "sine=frequency=440:duration=10" -ar 44100
/tmp/short.wav 2>/dev/null
/ffmpeg-incr -i /tmp/short.wav -i /tmp/in2.wav -filter_complex
"acrossfade=d=20" -f null - 2>&1 | grep -o "Input.*shorter.*"
echo ""
echo "=== MEMORY ==="
echo "| Duration | Baseline | Incremental | Reduction |"
echo "|----------|----------|-------------|-----------|"
for d in 60 600 1800 3600; do
mem_b=$(/usr/bin/time -v /ffmpeg-base -y -i /tmp/in1.wav -i /tmp/in2.wav
-filter_complex "acrossfade=d=${d}:c1=tri:c2=tri" -f null - 2>&1 | grep
"Maximum resident" | awk "{print \$6}")
mem_i=$(/usr/bin/time -v /ffmpeg-incr -y -i /tmp/in1.wav -i /tmp/in2.wav
-filter_complex "acrossfade=d=${d}:c1=tri:c2=tri" -f null - 2>&1 | grep
"Maximum resident" | awk "{print \$6}")
printf "| %s min | %d MB | %d MB | %d%% |\n" "$((d/60))" "$((mem_b/1024))"
"$((mem_i/1024))" "$(((mem_b-mem_i)*100/mem_b))"
done
echo ""
echo "=== CPU (3 runs averaged) ==="
echo "| Duration | Baseline | Incremental | Change |"
echo "|----------|----------|-------------|--------|"
for d in 60 600 1800 3600; do
tb=0; ti=0
for i in 1 2 3; do
tb=$(echo "$tb + $(/usr/bin/time -f "%e" /ffmpeg-base -y -i
/tmp/in1.wav -i /tmp/in2.wav -filter_complex "acrossfade=d=${d}:c1=tri:c2=tri"
-f null - 2>&1 | tail -1)" | bc)
ti=$(echo "$ti + $(/usr/bin/time -f "%e" /ffmpeg-incr -y -i
/tmp/in1.wav -i /tmp/in2.wav -filter_complex "acrossfade=d=${d}:c1=tri:c2=tri"
-f null - 2>&1 | tail -1)" | bc)
done
ab=$(echo "scale=2; $tb/3" | bc); ai=$(echo "scale=2; $ti/3" | bc)
ch=$(echo "scale=0; (($ai-$ab)*100)/$ab" | bc); [ $ch -gt 0 ] && ch="+$ch"
printf "| %s min | %ss | %ss | %s%% |\n" "$((d/60))" "$ab" "$ai" "$ch"
done
'
```
</details>
<details>
<summary><b>Test Environment</b></summary>
```
Docker: ghcr.io/btbn/ffmpeg-builds/linux64-gpl:latest
GCC: 15 (Ubuntu 15.2.0-4ubuntu4)
Audio: PCM S16LE, 44100 Hz, mono sine waves
```
</details>
From 7457f228c1bd8d2d0855bd5daeec2d30173de867 Mon Sep 17 00:00:00 2001
From: realies <[email protected]>
Date: Thu, 15 Jan 2026 00:23:26 +0200
Subject: [PATCH] avfilter/af_afade: incremental crossfade for memory
efficiency
Process crossfade samples incrementally as input 1 delivers them,
instead of waiting for all samples to buffer. This reduces peak
memory usage by 58-78% for long crossfades.
- Add crossfade_in_progress, crossfade_offset, crossfade_total state
- Add pass_crossfade_chunk() for incremental processing
- Modify activate() to use incremental mode for overlap crossfades
- Update crossfade macros to accept offset/total parameters
- Handle short input gracefully (crossfade shortened with warning)
- Remove 60-second duration limit (memory now scales efficiently)
Validated:
- Audio output byte-identical to baseline (MD5 verified)
- Memory: 42 MB -> 17 MB for 1 min crossfade (58% reduction)
1668 MB -> 357 MB for 60 min crossfade (78% reduction)
- Tested with >UINT32_MAX samples (6.5h crossfade at 192kHz)
---
libavfilter/af_afade.c | 194 ++++++++++++++++++++++++++++---
tests/ref/fate/filter-acrossfade | 22 +++-
2 files changed, 201 insertions(+), 15 deletions(-)
diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c
index 055f234f7c..c2c63a5639 100644
--- a/libavfilter/af_afade.c
+++ b/libavfilter/af_afade.c
@@ -47,6 +47,11 @@ typedef struct AudioFadeContext {
int64_t pts;
int xfade_idx;
+ /* Incremental crossfade state */
+ int crossfade_in_progress;
+ int64_t crossfade_offset;
+ int64_t crossfade_total;
+
void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
int nb_samples, int channels, int direction,
int64_t start, int64_t range, int curve,
@@ -55,7 +60,8 @@ typedef struct AudioFadeContext {
int nb_samples, int channels, double unity);
void (*crossfade_samples)(uint8_t **dst, uint8_t * const *cf0,
uint8_t * const *cf1,
- int nb_samples, int channels,
+ int nb_samples, int64_t total_samples,
+ int64_t offset, int channels,
int curve0, int curve1);
} AudioFadeContext;
@@ -457,8 +463,8 @@ static const AVOption acrossfade_options[] = {
{ "n", "set number of input files to cross fade",
OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT32_MAX, FLAGS },
{ "nb_samples", "set number of samples for cross fade duration",
OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT32_MAX/10,
FLAGS },
{ "ns", "set number of samples for cross fade duration",
OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT32_MAX/10,
FLAGS },
- { "duration", "set cross fade duration",
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS },
- { "d", "set cross fade duration",
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS },
+ { "duration", "set cross fade duration",
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX/2, FLAGS
},
+ { "d", "set cross fade duration",
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX/2, FLAGS
},
{ "overlap", "overlap 1st stream end with 2nd stream start",
OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS },
{ "o", "overlap 1st stream end with 2nd stream start",
OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS },
{ "curve1", "set fade curve type for 1st stream",
OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1,
FLAGS, .unit = "curve" },
@@ -497,14 +503,15 @@ AVFILTER_DEFINE_CLASS(acrossfade);
#define CROSSFADE_PLANAR(name, type)
\
static void crossfade_samples_## name ##p(uint8_t **dst, uint8_t * const *cf0,
\
uint8_t * const *cf1,
\
- int nb_samples, int channels,
\
+ int nb_samples, int64_t total,
\
+ int64_t offset, int channels,
\
int curve0, int curve1)
\
{
\
int i, c;
\
\
for (i = 0; i < nb_samples; i++) {
\
- double gain0 = fade_gain(curve0, nb_samples - 1 - i,
nb_samples,0.,1.);\
- double gain1 = fade_gain(curve1, i, nb_samples, 0., 1.);
\
+ double gain0 = fade_gain(curve0, total - 1 - (offset + i),
total,0.,1.);\
+ double gain1 = fade_gain(curve1, offset + i, total, 0., 1.);
\
for (c = 0; c < channels; c++) {
\
type *d = (type *)dst[c];
\
const type *s0 = (type *)cf0[c];
\
@@ -518,7 +525,8 @@ static void crossfade_samples_## name ##p(uint8_t **dst,
uint8_t * const *cf0, \
#define CROSSFADE(name, type) \
static void crossfade_samples_## name (uint8_t **dst, uint8_t * const *cf0, \
uint8_t * const *cf1, \
- int nb_samples, int channels, \
+ int nb_samples, int64_t total, \
+ int64_t offset, int channels, \
int curve0, int curve1) \
{ \
type *d = (type *)dst[0]; \
@@ -527,8 +535,8 @@ static void crossfade_samples_## name (uint8_t **dst,
uint8_t * const *cf0, \
int i, c, k = 0; \
\
for (i = 0; i < nb_samples; i++) { \
- double gain0 = fade_gain(curve0, nb_samples - 1-i,nb_samples,0.,1.);\
- double gain1 = fade_gain(curve1, i, nb_samples, 0., 1.); \
+ double gain0 = fade_gain(curve0, total - 1 - (offset+i), total,0.,1.);\
+ double gain1 = fade_gain(curve1, offset + i, total, 0., 1.); \
for (c = 0; c < channels; c++, k++) \
d[k] = s0[k] * gain0 + s1[k] * gain1; \
} \
@@ -570,6 +578,64 @@ static int pass_samples(AVFilterLink *inlink, AVFilterLink
*outlink, unsigned nb
return ff_filter_frame(outlink, in);
}
+/* Process a chunk of crossfade samples incrementally.
+ * This consumes samples as they become available, reducing peak memory usage
+ * by not waiting for all input 1 samples to be buffered. */
+static int pass_crossfade_chunk(AVFilterContext *ctx, const int idx0, const
int idx1,
+ int chunk_samples, int64_t total_samples)
+{
+ AudioFadeContext *s = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ AVFrame *out, *cf[2] = { NULL };
+ int ret;
+
+ AVFilterLink *in0 = ctx->inputs[idx0];
+ AVFilterLink *in1 = ctx->inputs[idx1];
+
+ out = ff_get_audio_buffer(outlink, chunk_samples);
+ if (!out)
+ return AVERROR(ENOMEM);
+
+ ret = ff_inlink_consume_samples(in0, chunk_samples, chunk_samples, &cf[0]);
+ if (ret < 0) {
+ av_frame_free(&out);
+ return ret;
+ }
+ av_assert1(ret);
+
+ ret = ff_inlink_consume_samples(in1, chunk_samples, chunk_samples, &cf[1]);
+ if (ret < 0) {
+ av_frame_free(&out);
+ av_frame_free(&cf[0]);
+ return ret;
+ }
+ av_assert1(ret);
+
+ s->crossfade_samples(out->extended_data, cf[0]->extended_data,
+ cf[1]->extended_data,
+ chunk_samples, total_samples, s->crossfade_offset,
+ out->ch_layout.nb_channels,
+ s->curve, s->curve2);
+ out->pts = s->pts;
+ s->pts += av_rescale_q(chunk_samples,
+ (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
+
+ s->crossfade_offset += chunk_samples;
+
+ /* Check if crossfade is complete */
+ if (s->crossfade_offset >= total_samples) {
+ s->crossfade_in_progress = 0;
+ s->crossfade_offset = 0;
+ s->crossfade_total = 0;
+ s->xfade_idx++;
+ ff_filter_set_ready(ctx, 10);
+ }
+
+ av_frame_free(&cf[0]);
+ av_frame_free(&cf[1]);
+ return ff_filter_frame(outlink, out);
+}
+
static int pass_crossfade(AVFilterContext *ctx, const int idx0, const int idx1)
{
AudioFadeContext *s = ctx->priv;
@@ -626,7 +692,7 @@ static int pass_crossfade(AVFilterContext *ctx, const int
idx0, const int idx1)
}
s->crossfade_samples(out->extended_data, cf[0]->extended_data,
- cf[1]->extended_data, nb_samples,
+ cf[1]->extended_data, nb_samples, nb_samples, 0,
out->ch_layout.nb_channels, s->curve, s->curve2);
out->pts = s->pts;
s->pts += av_rescale_q(nb_samples,
@@ -706,6 +772,49 @@ static int activate(AVFilterContext *ctx)
FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
+ /* Handle incremental crossfade in progress (overlap mode only) */
+ if (s->crossfade_in_progress) {
+ AVFilterLink *in1 = ctx->inputs[idx1];
+ int64_t remaining = s->crossfade_total - s->crossfade_offset;
+ int available0 = ff_inlink_queued_samples(in0);
+ int available1 = ff_inlink_queued_samples(in1);
+ int chunk = FFMIN3(available0, available1, remaining);
+
+ if (chunk > 0) {
+ int ret = pass_crossfade_chunk(ctx, idx0, idx1, chunk,
s->crossfade_total);
+ if (ret < 0) {
+ s->crossfade_in_progress = 0;
+ s->crossfade_offset = 0;
+ s->crossfade_total = 0;
+ }
+ return ret;
+ } else if (ff_outlink_frame_wanted(outlink)) {
+ /* Check if input 1 ended prematurely */
+ if (ff_outlink_get_status(in1)) {
+ int64_t remaining = s->crossfade_total - s->crossfade_offset;
+ if (remaining > 0 && available0 > 0) {
+ int to_pass = FFMIN(remaining, available0);
+ av_log(ctx, AV_LOG_WARNING, "Input %d ended prematurely, "
+ "passing %d of %"PRId64" remaining samples from
input %d.\n",
+ idx1, to_pass, remaining, idx0);
+ int ret = pass_samples(in0, outlink, to_pass, &s->pts);
+ if (ret < 0)
+ return ret;
+ }
+ s->crossfade_in_progress = 0;
+ s->crossfade_offset = 0;
+ s->crossfade_total = 0;
+ s->xfade_idx++;
+ ff_filter_set_ready(ctx, 10);
+ return 0;
+ }
+ /* Need more samples from input 1 */
+ ff_inlink_request_frame(in1);
+ return 0;
+ }
+ return 0;
+ }
+
if (idx0 == s->nb_inputs - 1) {
/* Last active input, read until EOF */
if (ff_inlink_queued_frames(in0))
@@ -740,11 +849,68 @@ static int activate(AVFilterContext *ctx)
/* If this clip is sandwiched between two other clips, buffer at least
* twice the total crossfade duration to ensure that we won't reach EOF
* during the second fade (in which case we would shorten the fade) */
- int needed_samples = s->nb_samples;
- if (idx1 < s->nb_inputs - 1)
- needed_samples *= 2;
+ int64_t needed_samples = s->nb_samples;
+ if (idx1 < s->nb_inputs - 1) {
+ if (needed_samples > INT64_MAX / 2)
+ needed_samples = INT64_MAX;
+ else
+ needed_samples *= 2;
+ }
- if (queued_samples1 >= needed_samples || ff_outlink_get_status(in1)) {
+ /* For overlap mode, use incremental crossfade to reduce memory */
+ if (s->overlap && idx1 == s->nb_inputs - 1) {
+ /* Check if input 1 ended before crossfade could start */
+ if (ff_outlink_get_status(in1) && queued_samples1 == 0) {
+ if (queued_samples0 > 0) {
+ av_log(ctx, AV_LOG_WARNING, "Input %d ended before crossfade, "
+ "passing remaining %d samples from input %d.\n",
+ idx1, queued_samples0, idx0);
+ int ret = pass_samples(in0, outlink, queued_samples0, &s->pts);
+ if (ret < 0)
+ return ret;
+ }
+ s->xfade_idx++;
+ ff_filter_set_ready(ctx, 10);
+ return 0;
+ }
+ if (queued_samples0 == 0) {
+ /* Input 0 is empty, no crossfade possible - skip to next input */
+ av_log(ctx, AV_LOG_WARNING, "Input %d is empty, skipping
crossfade.\n", idx0);
+ s->xfade_idx++;
+ ff_filter_set_ready(ctx, 10);
+ return 0;
+ }
+ if (queued_samples1 > 0) {
+ /* Start incremental crossfade */
+ int64_t total = FFMIN(queued_samples0, s->nb_samples);
+ if (total < s->nb_samples) {
+ av_log(ctx, AV_LOG_WARNING, "Input %d duration (%d samples) "
+ "is shorter than crossfade duration (%"PRId64"
samples), "
+ "crossfade will be shorter.\n",
+ idx0, queued_samples0, s->nb_samples);
+ }
+ int chunk = FFMIN3(queued_samples0, queued_samples1, total);
+ s->crossfade_in_progress = 1;
+ s->crossfade_offset = 0;
+ s->crossfade_total = total;
+ int ret = pass_crossfade_chunk(ctx, idx0, idx1, chunk, total);
+ if (ret < 0) {
+ s->crossfade_in_progress = 0;
+ s->crossfade_offset = 0;
+ s->crossfade_total = 0;
+ }
+ return ret;
+ }
+ if (ff_outlink_frame_wanted(outlink)) {
+ /* Need samples from input 1 to start crossfade */
+ ff_inlink_request_frame(in1);
+ return 0;
+ }
+ return FFERROR_NOT_READY;
+ }
+
+ /* Non-overlap mode or sandwiched clips: use original blocking behavior */
+ if ((int64_t)queued_samples1 >= needed_samples ||
ff_outlink_get_status(in1)) {
/* The first filter may EOF before delivering any samples, in which
* case it's possible for pass_crossfade() to be a no-op. Just ensure
* the activate() function runs again after incrementing the index to
diff --git a/tests/ref/fate/filter-acrossfade b/tests/ref/fate/filter-acrossfade
index fe45d4ec10..5834d61a49 100644
--- a/tests/ref/fate/filter-acrossfade
+++ b/tests/ref/fate/filter-acrossfade
@@ -108,6 +108,26 @@
0, 495888, 495888, 4096, 16384, 0xe24fa60b
0, 499984, 499984, 4096, 16384, 0x96b1bf9e
0, 504080, 504080, 3070, 12280, 0x1368a641
-0, 507150, 507150, 88200, 352800, 0xfdb19b5d
+0, 507150, 507150, 8192, 32768, 0x6e4fefd7
+0, 515342, 515342, 4096, 16384, 0x3160bc60
+0, 519438, 519438, 4096, 16384, 0x0132d456
+0, 523534, 523534, 4096, 16384, 0x1f870aad
+0, 527630, 527630, 4096, 16384, 0x47308b7e
+0, 531726, 531726, 4096, 16384, 0xc9bb5754
+0, 535822, 535822, 4096, 16384, 0x433c129e
+0, 539918, 539918, 4096, 16384, 0x9bf9eb4a
+0, 544014, 544014, 4096, 16384, 0x85ed7e14
+0, 548110, 548110, 4096, 16384, 0x8c676835
+0, 552206, 552206, 4096, 16384, 0x59f79880
+0, 556302, 556302, 4096, 16384, 0x07b8e07f
+0, 560398, 560398, 4096, 16384, 0x4c647cfb
+0, 564494, 564494, 4096, 16384, 0x6e6e963e
+0, 568590, 568590, 4096, 16384, 0x37bc21ca
+0, 572686, 572686, 4096, 16384, 0xc7fba16c
+0, 576782, 576782, 4096, 16384, 0x71d47685
+0, 580878, 580878, 4096, 16384, 0x22196728
+0, 584974, 584974, 4096, 16384, 0x86cb6524
+0, 589070, 589070, 4096, 16384, 0x3293cf52
+0, 593166, 593166, 2184, 8736, 0xd045e6ea
0, 595350, 595350, 1912, 7648, 0x5d71938c
0, 597262, 597262, 3097, 12388, 0xd852f4c5
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]