blob: 894729c6c7c44df7215e2561e431ef6c8f109d44 [file] [log] [blame]
Rucha Katakwar222c5312022-03-21 14:17:01 -07001# Copyright 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Utility functions for processing video recordings.
15"""
16# Each item in this list corresponds to quality levels defined per
17# CamcorderProfile. For Video ITS, we will currently test below qualities
18# only if supported by the camera device.
Rucha Katakwarb6847db2022-03-24 16:49:13 -070019import logging
20import os.path
21import subprocess
Rucha Katakwarb6847db2022-03-24 16:49:13 -070022
23
Rucha Katakwar089e6092022-03-30 11:19:26 -070024ITS_SUPPORTED_QUALITIES = (
Rucha Katakwar41133f92022-03-22 13:44:09 -070025 'HIGH',
26 '2160P',
27 '1080P',
28 '720P',
29 '480P',
30 'CIF',
31 'QCIF',
32 'QVGA',
33 'LOW',
34 'VGA'
Rucha Katakwar222c5312022-03-21 14:17:01 -070035)
Rucha Katakwarb6847db2022-03-24 16:49:13 -070036
37
Rucha Katakwar932bded2022-04-04 14:29:52 -070038def extract_key_frames_from_video(log_path, video_file_name):
Clemenz Portmann8d40e422022-04-28 10:29:01 -070039 """Returns a list of extracted key frames.
Rucha Katakwarb6847db2022-03-24 16:49:13 -070040
41 Ffmpeg tool is used to extract key frames from the video at path
Rucha Katakwar932bded2022-04-04 14:29:52 -070042 os.path.join(log_path, video_file_name).
43 The extracted key frames will have the name video_file_name with "_key_frame"
Rucha Katakwarb6847db2022-03-24 16:49:13 -070044 suffix to identify the frames for video of each quality.Since there can be
45 multiple key frames, each key frame image will be differentiated with it's
46 frame index.All the extracted key frames will be available in jpeg format
47 at the same path as the video file.
48
49 Args:
50 log_path: path for video file directory
Rucha Katakwar932bded2022-04-04 14:29:52 -070051 video_file_name: name of the video file.
Rucha Katakwarb6847db2022-03-24 16:49:13 -070052 Returns:
53 key_frame_files: A list of paths for each key frame extracted from the
Clemenz Portmann8d40e422022-04-28 10:29:01 -070054 video. Ex: VID_20220325_050918_0_CIF_352x288.mp4
Rucha Katakwarb6847db2022-03-24 16:49:13 -070055 """
Rucha Katakwar932bded2022-04-04 14:29:52 -070056 ffmpeg_image_name = f"{video_file_name.split('.')[0]}_key_frame"
Clemenz Portmann8d40e422022-04-28 10:29:01 -070057 ffmpeg_image_file_path = os.path.join(
58 log_path, ffmpeg_image_name + '_%02d.png')
Rucha Katakwarb6847db2022-03-24 16:49:13 -070059 cmd = ['ffmpeg',
Clemenz Portmann8d40e422022-04-28 10:29:01 -070060 '-skip_frame',
61 'nokey',
62 '-i',
63 os.path.join(log_path, video_file_name),
64 '-vsync',
65 'vfr',
66 '-frame_pts',
67 'true',
68 ffmpeg_image_file_path,
69 ]
70 logging.debug('Extracting key frames from: %s', video_file_name)
71 _ = subprocess.call(cmd)
Rucha Katakwarb6847db2022-03-24 16:49:13 -070072 arr = os.listdir(os.path.join(log_path))
73 key_frame_files = []
74 for file in arr:
75 if '.png' in file and not os.path.isdir(file) and ffmpeg_image_name in file:
76 key_frame_files.append(file)
77 return key_frame_files
78
79
80def get_key_frame_to_process(key_frame_files):
Clemenz Portmann8d40e422022-04-28 10:29:01 -070081 """Returns the key frame file from the list of key_frame_files.
Rucha Katakwarb6847db2022-03-24 16:49:13 -070082
83 If the size of the list is 1 then the file in the list will be returned else
84 the file with highest frame_index will be returned for further processing.
85
86 Args:
87 key_frame_files: A list of key frame files.
88 Returns:
89 key_frame_file to be used for further processing.
90 """
91 key_frame_files.sort()
92 return key_frame_files[-1]
Avichal Rakeshf82d5262022-04-22 16:24:18 -070093
94
95def extract_all_frames_from_video(log_path, video_file_name, img_format):
Clemenz Portmann8d40e422022-04-28 10:29:01 -070096 """Extracts and returns a list of all extracted frames.
Avichal Rakeshf82d5262022-04-22 16:24:18 -070097
98 Ffmpeg tool is used to extract all frames from the video at path
99 <log_path>/<video_file_name>. The extracted key frames will have the name
100 video_file_name with "_frame" suffix to identify the frames for video of each
101 size. Each frame image will be differentiated with its frame index. All
102 extracted key frames will be available in the provided img_format format at
103 the same path as the video file.
104
105 Args:
106 log_path: str; path for video file directory
107 video_file_name: str; name of the video file.
108 img_format: str; type of image to export frames into. ex. 'png'
109 Returns:
110 key_frame_files: An ordered list of paths for each frame extracted from the
111 video
112 """
113 logging.debug('Extracting all frames')
114 ffmpeg_image_name = f"{video_file_name.split('.')[0]}_frame"
115 logging.debug('ffmpeg_image_name: %s', ffmpeg_image_name)
116 ffmpeg_image_file_names = (
117 f'{os.path.join(log_path, ffmpeg_image_name)}_%03d.{img_format}')
118 cmd = [
119 'ffmpeg', '-i', os.path.join(log_path, video_file_name),
120 ffmpeg_image_file_names
121 ]
122 _ = subprocess.call(cmd)
123
124 file_list = sorted(
125 [_ for _ in os.listdir(log_path) if (_.endswith(img_format)
126 and ffmpeg_image_name in _)])
127 return file_list