mirror of
https://github.com/ApfelTeeSaft/restream_playout.git
synced 2026-08-26 19:33:32 +00:00
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import tempfile
|
|
import threading
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from restream_playout import PlayoutEngine
|
|
from restream_playout.rtmp import RTMP_AUDIO, RTMP_DATA_AMF0, RTMP_VIDEO
|
|
|
|
from .mp4_builder import write_test_mp4
|
|
|
|
|
|
class _FakeSession:
|
|
messages: list[tuple[int, int, bytes]] = []
|
|
|
|
def __init__(self, rtmp_url: str, *, stop_event: asyncio.Event, state_callback: object, **kwargs: object) -> None:
|
|
self.stop_event = stop_event
|
|
self.state_callback = state_callback
|
|
self.generation = 1
|
|
self._announced = False
|
|
|
|
async def ensure_connected(self) -> int:
|
|
if not self._announced:
|
|
self._announced = True
|
|
await self.state_callback(True)
|
|
return self.generation
|
|
|
|
async def send_message(
|
|
self,
|
|
message_type: int,
|
|
timestamp: int,
|
|
payload: bytes,
|
|
*,
|
|
chunk_stream_id: int = 5,
|
|
) -> None:
|
|
self.messages.append((message_type, timestamp, payload))
|
|
|
|
async def close(self) -> None:
|
|
if self._announced:
|
|
await self.state_callback(False)
|
|
|
|
|
|
class EngineTests(unittest.TestCase):
|
|
def test_dynamic_insertion_switches_from_filler_and_finishes_clip(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
clip_path = Path(directory, "dynamic.mp4")
|
|
write_test_mp4(clip_path)
|
|
started = threading.Event()
|
|
finished = threading.Event()
|
|
connected = threading.Event()
|
|
_FakeSession.messages = []
|
|
|
|
with patch("restream_playout.engine.StreamSession", _FakeSession):
|
|
engine = PlayoutEngine("rtmp://localhost/live/key")
|
|
engine.on_clip_started(lambda path: started.set())
|
|
engine.on_clip_finished(lambda path: finished.set())
|
|
engine.on_stream_connected(lambda: connected.set())
|
|
engine.start()
|
|
self.assertTrue(connected.wait(2))
|
|
engine.enqueue(clip_path)
|
|
self.assertTrue(started.wait(2))
|
|
self.assertTrue(finished.wait(2))
|
|
engine.stop()
|
|
|
|
message_types = {message_type for message_type, _, _ in _FakeSession.messages}
|
|
self.assertEqual(message_types, {RTMP_AUDIO, RTMP_DATA_AMF0, RTMP_VIDEO})
|
|
timestamps = [timestamp for _, timestamp, _ in _FakeSession.messages]
|
|
self.assertEqual(timestamps, sorted(timestamps))
|
|
|