From 0e797c6ac6072e6f5c1121a0c8ca2287a244014f Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Mon, 23 Oct 2023 09:08:56 -0700 Subject: [PATCH] python-codecs: improve pyav for zero latency --- plugins/python-codecs/src/libav.py | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/plugins/python-codecs/src/libav.py b/plugins/python-codecs/src/libav.py index a7225d6dce..7a287c2473 100644 --- a/plugins/python-codecs/src/libav.py +++ b/plugins/python-codecs/src/libav.py @@ -4,6 +4,8 @@ import vipsimage import pilimage from generator_common import createVideoFrame, createImageMediaObject +import threading +import asyncio av = None try: @@ -29,21 +31,33 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option gray = options and options.get('format') == 'gray' - start = 0 + sampleQueue = asyncio.Queue(1) + loop = asyncio.get_event_loop() + + def threadMain(): + try: + for idx, frame in enumerate(container.decode(stream)): + try: + # non blocking put may fail if queue is not empty + sampleQueue.put_nowait(frame) + except: + pass + except: + asyncio.run_coroutine_threadsafe(sampleQueue.put(None), loop = loop) + + thread = threading.Thread(target=threadMain) + thread.start() + try: vipsImage: vipsimage.VipsImage = None pilImage: pilimage.PILImage = None mo: scrypted_sdk.MediaObject = None - for idx, frame in enumerate(container.decode(stream)): - now = time.time() - if not start: - start = now - elapsed = now - start - if (frame.time or 0) < elapsed - 0.500: - # print('too slow, skipping frame') - continue - # print(frame) + while True: + frame = await sampleQueue.get() + if not frame: + break + if vipsimage.pyvips: if gray and frame.format.name.startswith('yuv') and frame.planes and len(frame.planes): vips = vipsimage.new_from_memory(memoryview(frame.planes[0]), frame.width, frame.height, 1)