From 731d599df13d38fb49a86553616a3578d6eac9b7 Mon Sep 17 00:00:00 2001 From: havetc Date: Sat, 10 Jun 2023 18:01:20 +0200 Subject: [PATCH] [IMPROVEMENT] FPS increase Two way used to increase fps: -use of av resize integrated with "to_image" method. It's made to resize video stream and is far more optimized than PIL for this usecase -use of imagetk paste method. Display frame was creating a new PhotoImage each call, but a PhotoImage call is just a imagetk creation of the good dimension/type, then a paste of the content inside it. Now we create a new PhotoImage only if the dimension changes. It also seems that less call to the Tk event loop are made when we paste new content instead of creating a new PhotoImage --- tkVideoPlayer/tkvideoplayer.py | 38 ++++++++++++++++------------------ 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tkVideoPlayer/tkvideoplayer.py b/tkVideoPlayer/tkvideoplayer.py index b687381..10c228b 100644 --- a/tkVideoPlayer/tkvideoplayer.py +++ b/tkVideoPlayer/tkvideoplayer.py @@ -166,7 +166,20 @@ def _load(self, path): self._time_stamp = float(frame.pts * stream.time_base) - self._current_img = frame.to_image() + width = self._current_frame_size[0] + height = self._current_frame_size[1] + if self._keep_aspect_ratio: + im_ratio = frame.width / frame.height + dest_ratio = width / height + if im_ratio != dest_ratio: + if im_ratio > dest_ratio: + new_height = round(frame.height / frame.width * width) + height = new_height + else: + new_width = round(frame.width / frame.height * height) + width = new_width + + self._current_img = frame.to_image(width=width, height=height, interpolation="FAST_BILINEAR") self._frame_number += 1 @@ -249,25 +262,10 @@ def current_img(self) -> Image: def _display_frame(self, event): """ displays the frame on the label """ - if self.scaled or (len(self._current_frame_size) == 2 and all(self._current_frame_size)): - - if self._keep_aspect_ratio: - self._current_img = ImageOps.contain(self._current_img, self._current_frame_size, self._resampling_method) - - else: - self._current_img = self._current_img.resize(self._current_frame_size, self._resampling_method) - - else: - self._current_frame_size = self.video_info()["framesize"] if all(self.video_info()["framesize"]) else (1, 1) - - if self._keep_aspect_ratio: - self._current_img = ImageOps.contain(self._current_img, self._current_frame_size, self._resampling_method) - - else: - self._current_img = self._current_img.resize(self._current_frame_size, self._resampling_method) - - - self.current_imgtk = ImageTk.PhotoImage(self._current_img) + if self.current_imgtk.width() == self._current_img.width and self.current_imgtk.height() == self._current_img.height: + self.current_imgtk.paste(self._current_img) + else: + self.current_imgtk = ImageTk.PhotoImage(self._current_img) self.config(image=self.current_imgtk) def seek(self, sec: int):