async def test_hls_playlist_view(hass, hls_stream, stream_worker_sync): """Test rendering the hls playlist with 1 and 2 output segments.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE) stream_worker_sync.pause() hls = stream.add_provider("hls") hls.put(Segment(1, INIT_BYTES, MOOF_BYTES, DURATION)) await hass.async_block_till_done() hls_client = await hls_stream(stream) resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist(sequence=1, segments=[make_segment(1)]) hls.put(Segment(2, INIT_BYTES, MOOF_BYTES, DURATION)) await hass.async_block_till_done() resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist( sequence=1, segments=[make_segment(1), make_segment(2)]) stream_worker_sync.resume() stream.stop()
async def test_hls_playlist_view_discontinuity(hass, hls_stream, stream_worker_sync): """Test a discontinuity across segments in the stream with 3 segments.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE) stream_worker_sync.pause() hls = stream.add_provider("hls") hls.put(Segment(1, INIT_BYTES, MOOF_BYTES, DURATION, stream_id=0)) hls.put(Segment(2, INIT_BYTES, MOOF_BYTES, DURATION, stream_id=0)) hls.put(Segment(3, INIT_BYTES, MOOF_BYTES, DURATION, stream_id=1)) await hass.async_block_till_done() hls_client = await hls_stream(stream) resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist( sequence=1, segments=[ make_segment(1), make_segment(2), make_segment(3, discontinuity=True), ], ) stream_worker_sync.resume() stream.stop()
async def test_recorder_discontinuity(tmpdir): """Test recorder save across a discontinuity.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run recorder_save_worker(filename, [Segment(1, source, 4, 0), Segment(2, source, 4, 1)]) # Assert assert os.path.exists(filename)
async def test_hls_max_segments_discontinuity(hass, hls_stream, stream_worker_sync): """Test a discontinuity with more segments than the segment deque can hold.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE) stream_worker_sync.pause() hls = stream.add_provider(HLS_PROVIDER) hls_client = await hls_stream(stream) hls.put( Segment( 1, INIT_BYTES, MOOF_BYTES, SEGMENT_DURATION, stream_id=0, start_time=FAKE_TIME, ) ) # Produce enough segments to overfill the output buffer by one for sequence in range(1, MAX_SEGMENTS + 2): hls.put( Segment( sequence, INIT_BYTES, MOOF_BYTES, SEGMENT_DURATION, stream_id=1, start_time=FAKE_TIME, ) ) await hass.async_block_till_done() resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 # Only NUM_PLAYLIST_SEGMENTS are returned in the playlist causing the # EXT-X-DISCONTINUITY tag to be omitted and EXT-X-DISCONTINUITY-SEQUENCE # returned instead. start = MAX_SEGMENTS + 2 - NUM_PLAYLIST_SEGMENTS segments = [] for sequence in range(start, MAX_SEGMENTS + 2): segments.append(make_segment(sequence)) assert await resp.text() == make_playlist( sequence=start, discontinuity_sequence=1, segments=segments, ) stream_worker_sync.resume() stream.stop()
async def test_hls_max_segments(hass, hls_stream, stream_worker_sync): """Test rendering the hls playlist with more segments than the segment deque can hold.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE, {}) stream_worker_sync.pause() hls = stream.add_provider(HLS_PROVIDER) hls_client = await hls_stream(stream) # Produce enough segments to overfill the output buffer by one for sequence in range(MAX_SEGMENTS + 1): segment = Segment(sequence=sequence, duration=SEGMENT_DURATION, start_time=FAKE_TIME) hls.put(segment) await hass.async_block_till_done() resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 # Only NUM_PLAYLIST_SEGMENTS are returned in the playlist. start = MAX_SEGMENTS + 1 - NUM_PLAYLIST_SEGMENTS segments = [] for sequence in range(start, MAX_SEGMENTS + 1): segments.append(make_segment(sequence)) assert await resp.text() == make_playlist(sequence=start, segments=segments) # Fetch the actual segments with a fake byte payload for segment in hls.get_segments(): segment.init = INIT_BYTES segment.parts = [ Part( duration=SEGMENT_DURATION, has_keyframe=True, data=FAKE_PAYLOAD, ) ] # The segment that fell off the buffer is not accessible segment_response = await hls_client.get("/segment/0.m4s") assert segment_response.status == 404 # However all segments in the buffer are accessible, even those that were not in the playlist. for sequence in range(1, MAX_SEGMENTS + 1): segment_response = await hls_client.get(f"/segment/{sequence}.m4s") assert segment_response.status == 200 stream_worker_sync.resume() stream.stop()
async def test_recorder_save(tmpdir): """Test recorder save.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run segment = Segment(sequence=1) add_parts_to_segment(segment, source) segment.duration = 4 recorder_save_worker(filename, [segment]) # Assert assert os.path.exists(filename)
async def test_recorder_discontinuity(tmpdir): """Test recorder save across a discontinuity.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run init, moof_data = get_init_and_moof_data(source.getbuffer()) recorder_save_worker( filename, [ Segment(1, init, moof_data, 4, 0), Segment(2, init, moof_data, 4, 1), ], ) # Assert assert os.path.exists(filename)
async def test_hls_playlist_view_discontinuity(hass, hls_stream, stream_worker_sync): """Test a discontinuity across segments in the stream with 3 segments.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE, {}) stream_worker_sync.pause() hls = stream.add_provider(HLS_PROVIDER) segment = Segment(sequence=0, stream_id=0, duration=SEGMENT_DURATION, start_time=FAKE_TIME) hls.put(segment) segment = Segment(sequence=1, stream_id=0, duration=SEGMENT_DURATION, start_time=FAKE_TIME) hls.put(segment) segment = Segment( sequence=2, stream_id=1, duration=SEGMENT_DURATION, start_time=FAKE_TIME, ) hls.put(segment) await hass.async_block_till_done() hls_client = await hls_stream(stream) resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist( sequence=0, segments=[ make_segment(0), make_segment(1), make_segment(2, discontinuity=True), ], ) stream_worker_sync.resume() stream.stop()
async def test_recorder_save(tmpdir): """Test recorder save.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run recorder_save_worker(filename, [Segment(1, source, 4)], "mp4") # Assert assert os.path.exists(filename)
async def test_recorder_save(tmpdir): """Test recorder save.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run recorder_save_worker( filename, [Segment(1, *get_init_and_moof_data(source.getbuffer()), 4)]) # Assert assert os.path.exists(filename)
async def test_recorder_save(): """Test recorder save.""" # Setup source = generate_h264_video() output = BytesIO() output.name = "test.mp4" # Run recorder_save_worker(output, [Segment(1, source, 4)]) # Assert assert output.getvalue()
async def test_hls_playlist_view(hass, hls_stream, stream_worker_sync): """Test rendering the hls playlist with 1 and 2 output segments.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE, {}) stream_worker_sync.pause() hls = stream.add_provider(HLS_PROVIDER) for i in range(2): segment = Segment(sequence=i, duration=SEGMENT_DURATION, start_time=FAKE_TIME) hls.put(segment) await hass.async_block_till_done() hls_client = await hls_stream(stream) resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist( sequence=0, segments=[make_segment(0), make_segment(1)]) segment = Segment(sequence=2, duration=SEGMENT_DURATION, start_time=FAKE_TIME) hls.put(segment) await hass.async_block_till_done() resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 assert await resp.text() == make_playlist( sequence=0, segments=[make_segment(0), make_segment(1), make_segment(2)]) stream_worker_sync.resume() stream.stop()
async def test_hls_max_segments(hass, hls_stream, stream_worker_sync): """Test rendering the hls playlist with more segments than the segment deque can hold.""" await async_setup_component(hass, "stream", {"stream": {}}) stream = create_stream(hass, STREAM_SOURCE) stream_worker_sync.pause() hls = stream.add_provider(HLS_PROVIDER) hls_client = await hls_stream(stream) # Produce enough segments to overfill the output buffer by one for sequence in range(1, MAX_SEGMENTS + 2): hls.put( Segment( sequence, INIT_BYTES, MOOF_BYTES, SEGMENT_DURATION, start_time=FAKE_TIME, ) ) await hass.async_block_till_done() resp = await hls_client.get("/playlist.m3u8") assert resp.status == 200 # Only NUM_PLAYLIST_SEGMENTS are returned in the playlist. start = MAX_SEGMENTS + 2 - NUM_PLAYLIST_SEGMENTS segments = [] for sequence in range(start, MAX_SEGMENTS + 2): segments.append(make_segment(sequence)) assert await resp.text() == make_playlist( sequence=start, segments=segments, ) # The segment that fell off the buffer is not accessible segment_response = await hls_client.get("/segment/1.m4s") assert segment_response.status == 404 # However all segments in the buffer are accessible, even those that were not in the playlist. for sequence in range(2, MAX_SEGMENTS + 2): segment_response = await hls_client.get(f"/segment/{sequence}.m4s") assert segment_response.status == 200 stream_worker_sync.resume() stream.stop()
async def test_recorder_discontinuity(tmpdir): """Test recorder save across a discontinuity.""" # Setup source = generate_h264_video() filename = f"{tmpdir}/test.mp4" # Run segment_1 = Segment(sequence=1, stream_id=0) add_parts_to_segment(segment_1, source) segment_1.duration = 4 segment_2 = Segment(sequence=2, stream_id=1) add_parts_to_segment(segment_2, source) segment_2.duration = 4 recorder_save_worker(filename, [segment_1, segment_2]) # Assert assert os.path.exists(filename)