Add caching for video transformations to improve performance during auto-repeat seeking
???
This commit is contained in:
@@ -152,6 +152,11 @@ class VideoEditor:
|
||||
self.display_needs_update = True
|
||||
self.last_display_state = None
|
||||
|
||||
# Cached transformations for performance
|
||||
self.cached_transformed_frame = None
|
||||
self.cached_frame_number = None
|
||||
self.cached_transform_hash = None
|
||||
|
||||
def _get_state_file_path(self) -> Path:
|
||||
"""Get the state file path for the current media file"""
|
||||
if not hasattr(self, 'video_path') or not self.video_path:
|
||||
@@ -660,13 +665,29 @@ class VideoEditor:
|
||||
if frame is None:
|
||||
return None
|
||||
|
||||
# Create a hash of the transformation parameters for caching
|
||||
transform_hash = hash((
|
||||
self.crop_rect,
|
||||
self.zoom_factor,
|
||||
self.rotation_angle,
|
||||
self.brightness,
|
||||
self.contrast,
|
||||
self.display_offset
|
||||
))
|
||||
|
||||
# Check if we can use cached transformation during auto-repeat seeking
|
||||
if (self.auto_repeat_active and
|
||||
self.cached_transformed_frame is not None and
|
||||
self.cached_frame_number == self.current_frame and
|
||||
self.cached_transform_hash == transform_hash):
|
||||
return self.cached_transformed_frame.copy()
|
||||
|
||||
# Work in-place when possible to avoid unnecessary copying
|
||||
processed_frame = frame
|
||||
|
||||
# Apply brightness/contrast first (to original frame for best quality)
|
||||
processed_frame = self.apply_brightness_contrast(processed_frame)
|
||||
|
||||
|
||||
# Apply crop
|
||||
if self.crop_rect:
|
||||
x, y, w, h = self.crop_rect
|
||||
@@ -701,8 +722,20 @@ class VideoEditor:
|
||||
end_y = min(new_height, start_y + self.window_height)
|
||||
processed_frame = processed_frame[start_y:end_y, start_x:end_x]
|
||||
|
||||
# Cache the result for auto-repeat seeking performance
|
||||
if self.auto_repeat_active:
|
||||
self.cached_transformed_frame = processed_frame.copy()
|
||||
self.cached_frame_number = self.current_frame
|
||||
self.cached_transform_hash = transform_hash
|
||||
|
||||
return processed_frame
|
||||
|
||||
def clear_transformation_cache(self):
|
||||
"""Clear the cached transformation to force recalculation"""
|
||||
self.cached_transformed_frame = None
|
||||
self.cached_frame_number = None
|
||||
self.cached_transform_hash = None
|
||||
|
||||
def apply_rotation(self, frame):
|
||||
"""Apply rotation to frame"""
|
||||
if self.rotation_angle == 0:
|
||||
@@ -718,6 +751,7 @@ class VideoEditor:
|
||||
def rotate_clockwise(self):
|
||||
"""Rotate video 90 degrees clockwise"""
|
||||
self.rotation_angle = (self.rotation_angle + 90) % 360
|
||||
self.clear_transformation_cache()
|
||||
|
||||
def apply_brightness_contrast(self, frame):
|
||||
"""Apply brightness and contrast adjustments to frame"""
|
||||
@@ -736,11 +770,13 @@ class VideoEditor:
|
||||
def adjust_brightness(self, delta: int):
|
||||
"""Adjust brightness by delta (-100 to 100)"""
|
||||
self.brightness = max(-100, min(100, self.brightness + delta))
|
||||
self.clear_transformation_cache()
|
||||
self.display_needs_update = True
|
||||
|
||||
def adjust_contrast(self, delta: float):
|
||||
"""Adjust contrast by delta (0.1 to 3.0)"""
|
||||
self.contrast = max(0.1, min(3.0, self.contrast + delta))
|
||||
self.clear_transformation_cache()
|
||||
self.display_needs_update = True
|
||||
|
||||
def show_progress_bar(self, text: str = "Processing..."):
|
||||
@@ -1326,6 +1362,7 @@ class VideoEditor:
|
||||
self.zoom_factor = max(
|
||||
self.MIN_ZOOM, self.zoom_factor - self.ZOOM_INCREMENT
|
||||
)
|
||||
self.clear_transformation_cache()
|
||||
|
||||
def set_crop_from_screen_coords(self, screen_rect):
|
||||
"""Convert screen coordinates to video frame coordinates and set crop"""
|
||||
@@ -1445,6 +1482,7 @@ class VideoEditor:
|
||||
if self.crop_rect:
|
||||
self.crop_history.append(self.crop_rect)
|
||||
self.crop_rect = (original_x, original_y, original_w, original_h)
|
||||
self.clear_transformation_cache()
|
||||
self.save_state() # Save state when crop is set
|
||||
|
||||
def seek_to_timeline_position(self, mouse_x, bar_x_start, bar_width):
|
||||
@@ -1460,6 +1498,7 @@ class VideoEditor:
|
||||
self.crop_rect = self.crop_history.pop()
|
||||
else:
|
||||
self.crop_rect = None
|
||||
self.clear_transformation_cache()
|
||||
self.save_state() # Save state when crop is undone
|
||||
|
||||
def toggle_marker_looping(self):
|
||||
@@ -1557,6 +1596,7 @@ class VideoEditor:
|
||||
new_w = w - amount
|
||||
self.crop_rect = (new_x, y, new_w, h)
|
||||
|
||||
self.clear_transformation_cache()
|
||||
self.save_state() # Save state when crop is adjusted
|
||||
|
||||
def render_video(self, output_path: str):
|
||||
@@ -2170,6 +2210,7 @@ class VideoEditor:
|
||||
self.crop_history.append(self.crop_rect)
|
||||
self.crop_rect = None
|
||||
self.zoom_factor = 1.0
|
||||
self.clear_transformation_cache()
|
||||
self.save_state() # Save state when crop is cleared
|
||||
elif key == ord("1"):
|
||||
# Cut markers only for videos
|
||||
|
Reference in New Issue
Block a user