ITS: Create function to extract 4 frames with equal interval

1. Avoid flakiness from extract_key_frames(), which could extract
wrong number of frames from preview recording.

2. Modified extract_all_frames_from_video() to handle forced fps
for stability.

Bug: 350867245
Test: run scene7 and scene8
Flag: TEST_ONLY
Change-Id: Idf87e5356e81d5cd40aab94a24b0411d9ad472e8
diff --git a/apps/CameraITS/utils/video_processing_utils.py b/apps/CameraITS/utils/video_processing_utils.py
index 2b9343a..308c2f0 100644
--- a/apps/CameraITS/utils/video_processing_utils.py
+++ b/apps/CameraITS/utils/video_processing_utils.py
@@ -235,50 +235,57 @@
   return key_frame_files[-1]
 
 
-def extract_all_frames_from_video(log_path, video_file_name, img_format):
-  """Extracts and returns a list of all extracted frames.
+def extract_all_frames_from_video(
+    log_path, video_file_name, img_format, video_fps=None):
+  """Extracts and returns a list of frames from a video using FFmpeg.
 
-  Ffmpeg tool is used to extract all frames from the video at path
-  <log_path>/<video_file_name>. The extracted key frames will have the name
-  video_file_name with "_frame" suffix to identify the frames for video of each
-  size. Each frame image will be differentiated with its frame index. All
-  extracted key frames will be available in the provided img_format format at
-  the same path as the video file.
+  Extract all frames from the video at path <log_path>/<video_file_name>.
+  The extracted frames will have the name video_file_name with "_frame"
+  suffix to identify the frames for video of each size. Each frame image
+  will be differentiated with its frame index. All extracted rames will be
+  available in the provided img_format format at the same path as the video.
 
   The run time flag '-loglevel quiet' hides the information from terminal.
   In order to see the detailed output of ffmpeg command change the loglevel
   option to 'info'.
 
   Args:
-    log_path: str; path for video file directory
+    log_path: str; directory containing video file.
     video_file_name: str; name of the video file.
-    img_format: str; type of image to export frames into. ex. 'png'
+    img_format: str; desired image format for export frames. ex. 'png'
+    video_fps: str; fps of imported video.
   Returns:
-    key_frame_files: An ordered list of paths for each frame extracted from the
-                     video
+    an ordered list of paths to the extracted frame images.
   """
   logging.debug('Extracting all frames')
   ffmpeg_image_name = f"{video_file_name.split('.')[0]}_frame"
   logging.debug('ffmpeg_image_name: %s', ffmpeg_image_name)
   ffmpeg_image_file_names = (
       f'{os.path.join(log_path, ffmpeg_image_name)}_%04d.{img_format}')
-  cmd = [
-      'ffmpeg', '-i', os.path.join(log_path, video_file_name),
-      '-vsync', 'passthrough',  # prevents frame drops during decoding
-      ffmpeg_image_file_names, '-loglevel', 'quiet'
-  ]
-  _ = subprocess.call(cmd,
-                      stdin=subprocess.DEVNULL,
-                      stdout=subprocess.DEVNULL,
-                      stderr=subprocess.DEVNULL)
+  if video_fps:
+    cmd = [
+        'ffmpeg', '-i', os.path.join(log_path, video_file_name),
+        '-r', video_fps,  # force a constant frame rate for reliability
+        ffmpeg_image_file_names, '-loglevel', 'quiet'
+    ]
+  else:
+    cmd = [
+        'ffmpeg', '-i', os.path.join(log_path, video_file_name),
+        '-vsync', 'passthrough',  # prevents frame drops during decoding
+        ffmpeg_image_file_names, '-loglevel', 'quiet'
+    ]
+  subprocess.call(cmd,
+                  stdin=subprocess.DEVNULL,
+                  stdout=subprocess.DEVNULL,
+                  stderr=subprocess.DEVNULL)
 
-  file_list = sorted(
-      [_ for _ in os.listdir(log_path) if (_.endswith(img_format)
-                                           and ffmpeg_image_name in _)])
-  if not file_list:
+  files = sorted(
+      [file for file in os.listdir(log_path) if
+       (file.endswith(img_format) and ffmpeg_image_name in file)])
+  if not files:
     raise AssertionError('No frames extracted. Check source video.')
 
-  return file_list
+  return files
 
 
 def extract_last_key_frame_from_recording(log_path, file_name):