mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Disable audio stream when ADTS AAC detected (#47441)
* Disable audio stream when ADTS AAC detected * Use context manager for memoryview * Fix tests * Add test * Fix tests * Change FakePacket bytearray size to 3
This commit is contained in:
parent
2f9d03d115
commit
14f85d8731
@ -208,6 +208,16 @@ def stream_worker(source, options, segment_buffer, quit_event):
|
||||
missing_dts += 1
|
||||
continue
|
||||
if packet.stream == audio_stream:
|
||||
# detect ADTS AAC and disable audio
|
||||
if audio_stream.codec.name == "aac" and packet.size > 2:
|
||||
with memoryview(packet) as packet_view:
|
||||
if packet_view[0] == 0xFF and packet_view[1] & 0xF0 == 0xF0:
|
||||
_LOGGER.warning(
|
||||
"ADTS AAC detected - disabling audio stream"
|
||||
)
|
||||
container_packets = container.demux(video_stream)
|
||||
audio_stream = None
|
||||
continue
|
||||
found_audio = True
|
||||
elif (
|
||||
segment_start_pts is None
|
||||
|
@ -57,6 +57,11 @@ class FakePyAvStream:
|
||||
self.time_base = fractions.Fraction(1, rate)
|
||||
self.profile = "ignored-profile"
|
||||
|
||||
class FakeCodec:
|
||||
name = "aac"
|
||||
|
||||
self.codec = FakeCodec()
|
||||
|
||||
|
||||
VIDEO_STREAM = FakePyAvStream(VIDEO_STREAM_FORMAT, VIDEO_FRAME_RATE)
|
||||
AUDIO_STREAM = FakePyAvStream(AUDIO_STREAM_FORMAT, AUDIO_SAMPLE_RATE)
|
||||
@ -87,13 +92,18 @@ class PacketSequence:
|
||||
raise StopIteration
|
||||
self.packet += 1
|
||||
|
||||
class FakePacket:
|
||||
class FakePacket(bytearray):
|
||||
# Be a bytearray so that memoryview works
|
||||
def __init__(self):
|
||||
super().__init__(3)
|
||||
|
||||
time_base = fractions.Fraction(1, VIDEO_FRAME_RATE)
|
||||
dts = self.packet * PACKET_DURATION / time_base
|
||||
pts = self.packet * PACKET_DURATION / time_base
|
||||
duration = PACKET_DURATION / time_base
|
||||
stream = VIDEO_STREAM
|
||||
is_keyframe = True
|
||||
size = 3
|
||||
|
||||
return FakePacket()
|
||||
|
||||
@ -107,8 +117,8 @@ class FakePyAvContainer:
|
||||
self.packets = PacketSequence(0)
|
||||
|
||||
class FakePyAvStreams:
|
||||
video = video_stream
|
||||
audio = audio_stream
|
||||
video = [video_stream] if video_stream else []
|
||||
audio = [audio_stream] if audio_stream else []
|
||||
|
||||
self.streams = FakePyAvStreams()
|
||||
|
||||
@ -171,8 +181,8 @@ class MockPyAv:
|
||||
|
||||
def __init__(self, video=True, audio=False):
|
||||
"""Initialize the MockPyAv."""
|
||||
video_stream = [VIDEO_STREAM] if video else []
|
||||
audio_stream = [AUDIO_STREAM] if audio else []
|
||||
video_stream = VIDEO_STREAM if video else None
|
||||
audio_stream = AUDIO_STREAM if audio else None
|
||||
self.container = FakePyAvContainer(
|
||||
video_stream=video_stream, audio_stream=audio_stream
|
||||
)
|
||||
@ -413,6 +423,23 @@ async def test_audio_packets_not_found(hass):
|
||||
assert len(decoded_stream.audio_packets) == 0
|
||||
|
||||
|
||||
async def test_adts_aac_audio(hass):
|
||||
"""Set up an ADTS AAC audio stream and disable audio."""
|
||||
py_av = MockPyAv(audio=True)
|
||||
|
||||
num_packets = PACKETS_TO_WAIT_FOR_AUDIO + 1
|
||||
packets = list(PacketSequence(num_packets))
|
||||
packets[1].stream = AUDIO_STREAM
|
||||
packets[1].dts = packets[0].dts / VIDEO_FRAME_RATE * AUDIO_SAMPLE_RATE
|
||||
packets[1].pts = packets[0].pts / VIDEO_FRAME_RATE * AUDIO_SAMPLE_RATE
|
||||
# The following is packet data is a sign of ADTS AAC
|
||||
packets[1][0] = 255
|
||||
packets[1][1] = 241
|
||||
|
||||
decoded_stream = await async_decode_stream(hass, iter(packets), py_av=py_av)
|
||||
assert len(decoded_stream.audio_packets) == 0
|
||||
|
||||
|
||||
async def test_audio_is_first_packet(hass):
|
||||
"""Set up an audio stream and audio packet is the first packet in the stream."""
|
||||
py_av = MockPyAv(audio=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user