mirror of
https://github.com/facefusion/facefusion.git
synced 2026-09-15 20:15:28 +02:00
improve callbacks, prevent memory leak on close (#1231)
This commit is contained in:
@@ -5,7 +5,7 @@ from typing import Optional, Tuple
|
||||
import numpy
|
||||
|
||||
from facefusion import rtc
|
||||
from facefusion.apis.stream_event import create_receive_event
|
||||
from facefusion.apis.stream_event import create_receive_event, destroy_receive_event
|
||||
from facefusion.codecs import opus_decoder, opus_encoder
|
||||
from facefusion.types import AudioCodec, AudioFrame, Buffer, OpusDecoder, RtcPeer, RtcPeerAudio, Time
|
||||
|
||||
@@ -35,6 +35,7 @@ def receive_audio_frames(rtc_peer_audio : RtcPeerAudio, audio_queue : Queue[Tupl
|
||||
audio_frame_handler = partial(handle_audio_frame, audio_codec, audio_decoder, audio_queue)
|
||||
receive_event = create_receive_event(audio_track, audio_frame_handler)
|
||||
receive_event.wait()
|
||||
destroy_receive_event(audio_track)
|
||||
|
||||
empty_audio_frame = numpy.empty(0)
|
||||
audio_queue.put((0.0, empty_audio_frame))
|
||||
|
||||
@@ -10,8 +10,8 @@ def create_receive_event(track : int, frame_handler : FrameHandler) -> threading
|
||||
datachannel_library = datachannel_module.create_static_library()
|
||||
receive_event = threading.Event()
|
||||
|
||||
frame_callback = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p)(partial(dispatch_frame, frame_handler))
|
||||
close_callback = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p)(partial(dispatch_event, receive_event))
|
||||
frame_callback = datachannel_module.define_frame_callback()(partial(dispatch_frame, frame_handler))
|
||||
close_callback = datachannel_module.define_closed_callback()(partial(dispatch_event, receive_event))
|
||||
datachannel_library.rtcSetFrameCallback(track, frame_callback)
|
||||
datachannel_library.rtcSetClosedCallback(track, close_callback)
|
||||
receive_event.frame_callback = frame_callback # type: ignore[attr-defined]
|
||||
@@ -20,6 +20,12 @@ def create_receive_event(track : int, frame_handler : FrameHandler) -> threading
|
||||
return receive_event
|
||||
|
||||
|
||||
def destroy_receive_event(track : int) -> None:
|
||||
datachannel_library = datachannel_module.create_static_library()
|
||||
datachannel_library.rtcSetFrameCallback(track, datachannel_module.define_frame_callback()(0))
|
||||
datachannel_library.rtcSetClosedCallback(track, datachannel_module.define_closed_callback()(0))
|
||||
|
||||
|
||||
def dispatch_frame(frame_handler : FrameHandler, track : int, data : ctypes.c_void_p, size : int, info : ctypes.c_void_p, pointer : ctypes.c_void_p) -> None:
|
||||
frame_handler(ctypes.string_at(data, size), ctypes.cast(info, ctypes.POINTER(ctypes.c_uint32)).contents.value)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import cv2
|
||||
import numpy
|
||||
|
||||
from facefusion import rtc, state_manager, streamer
|
||||
from facefusion.apis.stream_event import create_receive_event
|
||||
from facefusion.apis.stream_event import create_receive_event, destroy_receive_event
|
||||
from facefusion.codecs import aom_decoder, aom_encoder, vpx_decoder, vpx_encoder
|
||||
from facefusion.content_analyser import analyse_stream
|
||||
from facefusion.types import AomDecoder, AomEncoder, BitRate, Buffer, BufferPack, Resolution, RtcPeer, RtcPeerVideo, Time, VideoCodec, VisionFrame, VpxDecoder, VpxEncoder
|
||||
@@ -66,6 +66,7 @@ def receive_video_frames(rtc_peer_video : RtcPeerVideo, video_queue : Queue[Tupl
|
||||
video_frame_handler = partial(handle_video_frame, source_vision_frames, video_codec, video_decoder, video_queue, video_executor)
|
||||
receive_event = create_receive_event(video_track, video_frame_handler)
|
||||
receive_event.wait()
|
||||
destroy_receive_event(video_track)
|
||||
|
||||
empty_future : Future[BufferPack] = Future()
|
||||
empty_future.set_result(BufferPack(buffer = bytes(), resolution = (0, 0)))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ctypes
|
||||
from _ctypes import CFuncPtr
|
||||
from functools import lru_cache
|
||||
from typing import Optional
|
||||
from typing import Optional, Type
|
||||
|
||||
from facefusion.common_helper import is_linux, is_macos, is_windows
|
||||
from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url_by_provider
|
||||
@@ -217,7 +218,7 @@ def init_ctypes(library : ctypes.CDLL) -> ctypes.CDLL:
|
||||
library.rtcChainRtcpReceivingSession.argtypes = [ ctypes.c_int ]
|
||||
library.rtcChainRtcpReceivingSession.restype = ctypes.c_int
|
||||
|
||||
library.rtcSetFrameCallback.argtypes = [ ctypes.c_int, ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p) ]
|
||||
library.rtcSetFrameCallback.argtypes = [ ctypes.c_int, define_frame_callback() ]
|
||||
library.rtcSetFrameCallback.restype = ctypes.c_int
|
||||
|
||||
library.rtcSetUserPointer.argtypes = [ ctypes.c_int, ctypes.c_void_p ]
|
||||
@@ -229,7 +230,7 @@ def init_ctypes(library : ctypes.CDLL) -> ctypes.CDLL:
|
||||
library.rtcRequestBitrate.argtypes = [ ctypes.c_int, ctypes.c_uint ]
|
||||
library.rtcRequestBitrate.restype = ctypes.c_int
|
||||
|
||||
library.rtcSetClosedCallback.argtypes = [ ctypes.c_int, ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p) ]
|
||||
library.rtcSetClosedCallback.argtypes = [ ctypes.c_int, define_closed_callback() ]
|
||||
library.rtcSetClosedCallback.restype = ctypes.c_int
|
||||
|
||||
return library
|
||||
@@ -292,3 +293,11 @@ def define_rtc_packetizer_init() -> ctypes.Structure:
|
||||
('obuPacketization', ctypes.c_int)
|
||||
]
|
||||
})()
|
||||
|
||||
|
||||
def define_frame_callback() -> Type[CFuncPtr]:
|
||||
return ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p)
|
||||
|
||||
|
||||
def define_closed_callback() -> Type[CFuncPtr]:
|
||||
return ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_void_p)
|
||||
|
||||
Reference in New Issue
Block a user