fix per frame rpc gc churn

This commit is contained in:
Koushik Dutta
2023-05-12 20:26:11 -07:00
parent d8f3edee1e
commit 205fdb0222
18 changed files with 150 additions and 95 deletions

View File

@@ -0,0 +1,14 @@
import scrypted_sdk
import time
async def flush():
pass
def createVideoFrame(image) -> scrypted_sdk.VideoFrame:
return {
'__json_copy_serialize_children': True,
'image': image,
'queued': 0,
'timestamp': time.time() * 1000,
'flush': flush,
}

View File

@@ -6,6 +6,7 @@ from urllib.parse import urlparse
import vipsimage
import pilimage
import platform
from generator_common import createVideoFrame
Gst = None
try:
@@ -87,6 +88,11 @@ async def generateVideoFramesGstreamer(mediaObject: scrypted_sdk.MediaObject, op
videosrc += ' ! {decoder} ! queue leaky=downstream max-size-buffers=0 ! videoconvert ! {videorate} {videocaps}'.format(decoder=decoder, videocaps=videocaps, videorate=videorate)
gst, gen = await createPipelineIterator(videosrc)
vipsImage: vipsimage.VipsImage = None
pilImage: pilimage.PILImage = None
mo: scrypted_sdk.MediaObject = None
async for gstsample in gen():
caps = gstsample.get_caps()
height = caps.get_structure(0).get_value('height')
@@ -99,19 +105,27 @@ async def generateVideoFramesGstreamer(mediaObject: scrypted_sdk.MediaObject, op
try:
if vipsimage.pyvips:
vips = vipsimage.new_from_memory(info.data, width, height, bands)
vipsImage = vipsimage.VipsImage(vips)
try:
if not mo:
vipsImage = vipsimage.VipsImage(vips)
mo = await vipsimage.createVipsMediaObject(vipsImage)
yield mo
vipsImage.vipsImage = vips
try:
yield createVideoFrame(mo)
finally:
vipsImage.vipsImage = None
vips.invalidate()
else:
pil = pilimage.new_from_memory(info.data, width, height, bands)
pilImage = pilimage.PILImage(pil)
try:
if not mo:
pilImage = pilimage.PILImage(pil)
mo = await pilimage.createPILMediaObject(pilImage)
yield mo
pilImage.pilImage = pil
try:
yield createVideoFrame(mo)
finally:
pilImage.pilImage = None
pil.close()

View File

@@ -3,6 +3,7 @@ import scrypted_sdk
from typing import Any
import vipsimage
import pilimage
from generator_common import createVideoFrame
av = None
try:
@@ -30,6 +31,10 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option
start = 0
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:
@@ -46,10 +51,14 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option
vips = vipsimage.pyvips.Image.new_from_array(frame.to_ndarray(format='gray'))
else:
vips = vipsimage.pyvips.Image.new_from_array(frame.to_ndarray(format='rgb24'))
vipsImage = vipsimage.VipsImage(vips)
try:
if not mo:
vipsImage = vipsimage.VipsImage(vips)
mo = await vipsimage.createVipsMediaObject(vipsImage)
yield mo
vipsImage.vipsImage = vips
try:
yield createVideoFrame(mo)
finally:
vipsImage.vipsImage = None
vips.invalidate()
@@ -64,10 +73,14 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option
rgb.close()
else:
pil = frame.to_image()
pilImage = pilimage.PILImage(pil)
try:
if not mo:
pilImage = pilimage.PILImage(pil)
mo = await pilimage.createPILMediaObject(pilImage)
yield mo
pilImage.pilImage = pil
try:
yield createVideoFrame(mo)
finally:
pilImage.pilImage = None
pil.close()

View File

@@ -2,7 +2,6 @@ import scrypted_sdk
from typing import Any
from thread import to_thread
import io
import time
try:
from PIL import Image
@@ -10,7 +9,7 @@ except:
# Image = None
pass
class PILImage(scrypted_sdk.VideoFrame):
class PILImage(scrypted_sdk.Image):
def __init__(self, pilImage: Image.Image) -> None:
super().__init__()
self.pilImage = pilImage
@@ -91,7 +90,6 @@ def toPILImage(pilImageWrapper: PILImage, options: scrypted_sdk.ImageOptions = N
async def createPILMediaObject(image: PILImage):
ret = await scrypted_sdk.mediaManager.createMediaObject(image, scrypted_sdk.ScryptedMimeTypes.Image.value, {
'timestamp': time.time() * 1000,
'format': None,
'width': image.width,
'height': image.height,

View File

@@ -1,4 +1,5 @@
import scrypted_sdk
import asyncio
from typing import Any
try:
import pyvips
@@ -7,9 +8,8 @@ except:
Image = None
pyvips = None
from thread import to_thread
import time
class VipsImage(scrypted_sdk.VideoFrame):
class VipsImage(scrypted_sdk.Image):
def __init__(self, vipsImage: Image) -> None:
super().__init__()
self.vipsImage = vipsImage
@@ -91,7 +91,6 @@ def toVipsImage(vipsImageWrapper: VipsImage, options: scrypted_sdk.ImageOptions
async def createVipsMediaObject(image: VipsImage):
ret = await scrypted_sdk.mediaManager.createMediaObject(image, scrypted_sdk.ScryptedMimeTypes.Image.value, {
'timestamp': time.time() * 1000,
'format': None,
'width': image.width,
'height': image.height,