Fix exit on window close and ffmpeg with vfr

This commit is contained in:
Ruben van de Ven 2024-06-25 09:31:02 +02:00
parent 5f5855e4ed
commit e4de59be6c

View file

@ -212,19 +212,22 @@ class FrameWriter:
"""Actually write the video""" """Actually write the video"""
# ffmpeg -f image2 -ts_from_file 2 -i %d.png out.mp4 # ffmpeg -f image2 -ts_from_file 2 -i %d.png out.mp4
logger.info(f"Write frames from {self.tmp_dir.name} to {self.filename}") logger.info(f"Write frames from {self.tmp_dir.name} to {self.filename}")
( encode = (
ffmpeg ffmpeg
# the magic here is in --ts_from_file which uses the mtime of the file for the interval # the magic here is in --ts_from_file which uses the mtime of the file for the interval
# this makes it possible to have non-constant intervals between frames, which is usefull # this makes it possible to have non-constant intervals between frames, which is usefull
# since we render frames when we get them # since we render frames when we get them
.input(self.tmp_dir.name + "/%07d.png", format="image2", ts_from_file=2) .input(self.tmp_dir.name + "/%07d.png", format="image2", ts_from_file=2)
.output(self.filename, framerate=self.fps) .output(self.filename, vsync="vfr" ) # framerate=self.fps)
.run()
) )
logger.info(encode.compile())
encode.run()
logger.info(f"Rm frame directory: {self.tmp_dir.name}") logger.info(f"Rm frame directory: {self.tmp_dir.name}")
# logger.warning(f"RM DISABLED!")
self.tmp_dir.cleanup() self.tmp_dir.cleanup()
class Renderer: class Renderer:
def __init__(self, config: Namespace, is_running: BaseEvent): def __init__(self, config: Namespace, is_running: BaseEvent):
self.config = config self.config = config
@ -247,19 +250,21 @@ class Renderer:
# TODO: get FPS from frame_emitter # TODO: get FPS from frame_emitter
# self.out = cv2.VideoWriter(str(filename), fourcc, 23.97, (1280,720)) # self.out = cv2.VideoWriter(str(filename), fourcc, 23.97, (1280,720))
self.fps = 10 self.fps = 60
self.frame_size = (1280,720) self.frame_size = (1280,720)
self.hide_stats = False self.hide_stats = False
self.out_writer = self.start_writer() if self.config.render_file else None self.out_writer = self.start_writer() if self.config.render_file else None
self.streaming_process = self.start_streaming() if self.config.render_url else None self.streaming_process = self.start_streaming() if self.config.render_url else None
if self.config.render_window: if self.config.render_window:
cv2.namedWindow("frame", cv2.WND_PROP_FULLSCREEN) pass
cv2.setWindowProperty("frame",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN) # cv2.namedWindow("frame", cv2.WND_PROP_FULLSCREEN)
# cv2.setWindowProperty("frame",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
else: else:
pyglet.options["headless"] = True pyglet.options["headless"] = True
config = pyglet.gl.Config(sample_buffers=1, samples=4) config = pyglet.gl.Config(sample_buffers=1, samples=4)
# , fullscreen=self.config.render_window
self.window = pyglet.window.Window(width=self.frame_size[0], height=self.frame_size[1], config=config) self.window = pyglet.window.Window(width=self.frame_size[0], height=self.frame_size[1], config=config)
self.window.set_handler('on_draw', self.on_draw) self.window.set_handler('on_draw', self.on_draw)
self.window.set_handler('on_refresh', self.on_refresh) self.window.set_handler('on_refresh', self.on_refresh)
@ -438,6 +443,7 @@ class Renderer:
def check_running(self, dt): def check_running(self, dt):
if not self.is_running.is_set(): if not self.is_running.is_set():
self.window.close() self.window.close()
self.event_loop.exit()
def on_close(self): def on_close(self):
self.is_running.clear() self.is_running.clear()
@ -479,21 +485,24 @@ class Renderer:
self.fps_display.draw() self.fps_display.draw()
# if streaming, capture buffer and send # if streaming, capture buffer and send
if self.streaming_process or self.out_writer: try:
buf = pyglet.image.get_buffer_manager().get_color_buffer() if self.streaming_process or self.out_writer:
img_data = buf.get_image_data() buf = pyglet.image.get_buffer_manager().get_color_buffer()
data = img_data.get_data() img_data = buf.get_image_data()
img = np.asanyarray(data).reshape((img_data.height, img_data.width, 4)) data = img_data.get_data() # alternative: .get_data("RGBA", image_data.pitch)
img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGB) img = np.asanyarray(data).reshape((img_data.height, img_data.width, 4))
img = np.flip(img, 0) img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGB)
# img = cv2.flip(img, cv2.0) img = np.flip(img, 0)
# img = cv2.flip(img, cv2.0)
# cv2.imshow('frame', img) # cv2.imshow('frame', img)
# cv2.waitKey(1) # cv2.waitKey(1)
if self.streaming_process: if self.streaming_process:
self.streaming_process.stdin.write(img.tobytes()) self.streaming_process.stdin.write(img.tobytes())
if self.out_writer: if self.out_writer:
self.out_writer.write(img) self.out_writer.write(img)
except Exception as e:
logger.exception(e)
def start_writer(self): def start_writer(self):
@ -543,10 +552,11 @@ class Renderer:
i=0 i=0
first_time = None first_time = None
event_loop = pyglet.app.EventLoop() self.event_loop = pyglet.app.EventLoop()
pyglet.clock.schedule_interval(self.check_running, 0.1) pyglet.clock.schedule_interval(self.check_running, 0.1)
pyglet.clock.schedule(self.check_frames) pyglet.clock.schedule(self.check_frames)
event_loop.run() self.event_loop.run()
# while self.is_running.is_set(): # while self.is_running.is_set():