From f1c6404e932673fbf9f0bd0d5e717f2527479fa2 Mon Sep 17 00:00:00 2001 From: kwy404 Date: Tue, 27 Oct 2026 11:31:47 -0300 Subject: [PATCH] Fix the Opus parser failing on mono Ogg streams When reading the OpusHead packet, OpusParser stored the channel mode in packet_count instead of channel_mode. For a mono stream this set packet_count back to 0 (ChannelMode.MONO), so the OpusTags packet was then checked as the identification header and the parser raised "first packet is not OpusHead". Stereo streams only worked because ChannelMode.STEREO happens to be 1, and channel_mode always stayed STEREO. --- bumble/a2dp.py | 2 +- tests/a2dp_test.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/bumble/a2dp.py b/bumble/a2dp.py index b16de874..9be306da 100644 --- a/bumble/a2dp.py +++ b/bumble/a2dp.py @@ -923,7 +923,7 @@ async def generate_frames() -> AsyncGenerator[OpusPacket, None]: logger.debug("first packet (header)") if packet[:8] != b"OpusHead": raise ValueError("first packet is not OpusHead") - packet_count = ( + channel_mode = ( OpusPacket.ChannelMode.MONO if packet[9] == 1 else OpusPacket.ChannelMode.STEREO diff --git a/tests/a2dp_test.py b/tests/a2dp_test.py index 54fb591c..a08a0a75 100644 --- a/tests/a2dp_test.py +++ b/tests/a2dp_test.py @@ -489,6 +489,33 @@ async def test_opus_parser(): assert packet.payload == audio_data_packet +# ----------------------------------------------------------------------------- +async def test_opus_parser_mono(): + page_header = ( + b'OggS' # Capture pattern + + b'\x00' # Version + + b'\x02' # Header type + + struct.pack("