blob: 187917af01632cd64c54cb417afc583de24b15bc [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)
Rucha Katakwar2c49c452022-05-19 14:29:03 -070077
78 if not len(key_frame_files):
79 raise AssertionError('No key frames extracted. Check source video.')
80
Rucha Katakwarb6847db2022-03-24 16:49:13 -070081 return key_frame_files
82
83
84def get_key_frame_to_process(key_frame_files):
Clemenz Portmann8d40e422022-04-28 10:29:01 -070085 """Returns the key frame file from the list of key_frame_files.
Rucha Katakwarb6847db2022-03-24 16:49:13 -070086
87 If the size of the list is 1 then the file in the list will be returned else
88 the file with highest frame_index will be returned for further processing.
89
90 Args:
91 key_frame_files: A list of key frame files.
92 Returns:
93 key_frame_file to be used for further processing.
94 """
95 key_frame_files.sort()
96 return key_frame_files[-1]
Avichal Rakeshf82d5262022-04-22 16:24:18 -070097
98
99def extract_all_frames_from_video(log_path, video_file_name, img_format):
Clemenz Portmann8d40e422022-04-28 10:29:01 -0700100 """Extracts and returns a list of all extracted frames.
Avichal Rakeshf82d5262022-04-22 16:24:18 -0700101
102 Ffmpeg tool is used to extract all frames from the video at path
103 <log_path>/<video_file_name>. The extracted key frames will have the name
104 video_file_name with "_frame" suffix to identify the frames for video of each
105 size. Each frame image will be differentiated with its frame index. All
106 extracted key frames will be available in the provided img_format format at
107 the same path as the video file.
108
109 Args:
110 log_path: str; path for video file directory
111 video_file_name: str; name of the video file.
112 img_format: str; type of image to export frames into. ex. 'png'
113 Returns:
114 key_frame_files: An ordered list of paths for each frame extracted from the
115 video
116 """
117 logging.debug('Extracting all frames')
118 ffmpeg_image_name = f"{video_file_name.split('.')[0]}_frame"
119 logging.debug('ffmpeg_image_name: %s', ffmpeg_image_name)
120 ffmpeg_image_file_names = (
121 f'{os.path.join(log_path, ffmpeg_image_name)}_%03d.{img_format}')
122 cmd = [
123 'ffmpeg', '-i', os.path.join(log_path, video_file_name),
124 ffmpeg_image_file_names
125 ]
126 _ = subprocess.call(cmd)
127
128 file_list = sorted(
129 [_ for _ in os.listdir(log_path) if (_.endswith(img_format)
130 and ffmpeg_image_name in _)])
Rucha Katakwar2c49c452022-05-19 14:29:03 -0700131 if not len(file_list):
132 raise AssertionError('No frames extracted. Check source video.')
133
Avichal Rakeshf82d5262022-04-22 16:24:18 -0700134 return file_list