From 3e32a5ebf2f27fb696e6cf2ba87821f83662ac50 Mon Sep 17 00:00:00 2001 From: ChandraChaan <53801679+ChandraChaan@users.noreply.github.com> Date: Tue, 3 Nov 2026 04:09:41 +0530 Subject: [PATCH 1/3] Test AudioFifo with a frame of a different channel layout --- tests/test_audiofifo.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_audiofifo.py b/tests/test_audiofifo.py index ce8be1273..25121e55c 100644 --- a/tests/test_audiofifo.py +++ b/tests/test_audiofifo.py @@ -1,5 +1,7 @@ from fractions import Fraction +import pytest + import av from .common import TestCase, fate_suite @@ -115,3 +117,14 @@ def test_missing_time_base(self) -> None: assert oframe is not None assert oframe.pts is None and not oframe.time_base assert oframe.sample_rate == iframe.sample_rate + + def test_layout_mismatch(self) -> None: + fifo = av.AudioFifo() + fifo.write(av.AudioFrame(format="s16", layout="mono", samples=1024)) + + # The FIFO was allocated for one channel, so a stereo frame would be + # read as mono and its samples scrambled. + with pytest.raises(ValueError): + fifo.write(av.AudioFrame(format="s16", layout="stereo", samples=1024)) + + assert fifo.samples == 1024 From 83fe3851e4bc3acfc2721721f02379cc677c4a03 Mon Sep 17 00:00:00 2001 From: ChandraChaan <53801679+ChandraChaan@users.noreply.github.com> Date: Tue, 3 Nov 2026 04:09:51 +0530 Subject: [PATCH 2/3] Reject AudioFifo frames with a different channel layout AudioFifo.write() checked that later frames had the same sample format, sample rate and time base as the first, but not the same channel layout. The FIFO is allocated with the first frame's channel count, so writing a stereo frame into a FIFO started with mono read only half of the data and scrambled the samples without an error, and a frame with fewer channels read past the end of its buffers. The channel layout is now compared too, as AudioResampler already does. --- av/audio/fifo.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/av/audio/fifo.py b/av/audio/fifo.py index a000711ab..c7f4ebbd1 100644 --- a/av/audio/fifo.py +++ b/av/audio/fifo.py @@ -76,6 +76,10 @@ def write(self, frame: AudioFrame | None): elif ( frame.ptr.format != self.template.ptr.format or frame.ptr.sample_rate != self.template.ptr.sample_rate + or lib.av_channel_layout_compare( + cython.address(frame.ptr.ch_layout), + cython.address(self.template.ptr.ch_layout), + ) or ( frame._time_base.num and self.template._time_base.num From 087f3513eea794b2624acea86afc0f60a5eaa3b8 Mon Sep 17 00:00:00 2001 From: ChandraChaan <53801679+ChandraChaan@users.noreply.github.com> Date: Tue, 3 Nov 2026 05:14:57 +0530 Subject: [PATCH 3/3] Add changelog entry for AudioFifo channel layout check --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 258a57d30..0232959d7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -52,6 +52,7 @@ Fixes: - Filters added or linked after ``Graph.configure()`` are now configured on the next push or pull instead of segfaulting. - ``SubtitleCodecContext.decode(None)`` flushes the decoder instead of raising ``RuntimeError``, so delayed decoders such as EIA-608 closed captions return their final subtitle. - ``AudioFrame.planes`` no longer counts one plane too many for 8-channel planar audio (e.g. ``fltp`` with ``7.1``), which made ``planes``, ``to_ndarray()``, and ``from_ndarray()`` raise ``ValueError``, and no longer reads past the end of ``extended_data`` for more channels. By :gh-user:`ChandraChaan` in (:pr:`2502`). +- ``AudioFifo.write()`` now raises ``ValueError`` for a frame whose channel layout differs from the first frame's, instead of reading the wrong number of channels and scrambling or over-reading the samples. By :gh-user:`ChandraChaan` in (:pr:`2505`). v19.0.2 -------