1*b7c941bbSAndroid Build Coastguard Worker# Copyright 2024 The Android Open Source Project 2*b7c941bbSAndroid Build Coastguard Worker# 3*b7c941bbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*b7c941bbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*b7c941bbSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*b7c941bbSAndroid Build Coastguard Worker# 7*b7c941bbSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*b7c941bbSAndroid Build Coastguard Worker# 9*b7c941bbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*b7c941bbSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*b7c941bbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*b7c941bbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*b7c941bbSAndroid Build Coastguard Worker# limitations under the License. 14*b7c941bbSAndroid Build Coastguard Worker"""Utility functions for verifying preview stabilization. 15*b7c941bbSAndroid Build Coastguard Worker""" 16*b7c941bbSAndroid Build Coastguard Worker 17*b7c941bbSAndroid Build Coastguard Workerimport cv2 18*b7c941bbSAndroid Build Coastguard Workerimport logging 19*b7c941bbSAndroid Build Coastguard Workerimport os 20*b7c941bbSAndroid Build Coastguard Workerimport threading 21*b7c941bbSAndroid Build Coastguard Workerimport time 22*b7c941bbSAndroid Build Coastguard Worker 23*b7c941bbSAndroid Build Coastguard Workerimport numpy as np 24*b7c941bbSAndroid Build Coastguard Worker 25*b7c941bbSAndroid Build Coastguard Workerimport its_session_utils 26*b7c941bbSAndroid Build Coastguard Workerimport sensor_fusion_utils 27*b7c941bbSAndroid Build Coastguard Workerimport video_processing_utils 28*b7c941bbSAndroid Build Coastguard Worker 29*b7c941bbSAndroid Build Coastguard Worker_AREA_720P_VIDEO = 1280 * 720 30*b7c941bbSAndroid Build Coastguard Worker_ASPECT_RATIO_16_9 = 16/9 # determine if preview fmt > 16:9 31*b7c941bbSAndroid Build Coastguard Worker_ASPECT_TOL = 0.01 32*b7c941bbSAndroid Build Coastguard Worker_GREEN_TOL = 200 # 200 out of 255 Green value in RGB 33*b7c941bbSAndroid Build Coastguard Worker_GREEN_PERCENT = 95 34*b7c941bbSAndroid Build Coastguard Worker_HIGH_RES_SIZE = '3840x2160' # Resolution for 4K quality 35*b7c941bbSAndroid Build Coastguard Worker_IMG_FORMAT = 'png' 36*b7c941bbSAndroid Build Coastguard Worker_MIN_PHONE_MOVEMENT_ANGLE = 5 # degrees 37*b7c941bbSAndroid Build Coastguard Worker_NATURAL_ORIENTATION_PORTRAIT = (90, 270) # orientation in "normal position" 38*b7c941bbSAndroid Build Coastguard Worker_NUM_ROTATIONS = 24 39*b7c941bbSAndroid Build Coastguard Worker_PREVIEW_DURATION = 400 # milliseconds 40*b7c941bbSAndroid Build Coastguard Worker_PREVIEW_MAX_TESTED_AREA = 1920 * 1440 41*b7c941bbSAndroid Build Coastguard Worker_PREVIEW_MIN_TESTED_AREA = 320 * 240 42*b7c941bbSAndroid Build Coastguard Worker_PREVIEW_STABILIZATION_FACTOR = 0.7 # 70% of gyro movement allowed 43*b7c941bbSAndroid Build Coastguard Worker_RED_BLUE_TOL = 20 # 20 out of 255 Red or Blue value in RGB 44*b7c941bbSAndroid Build Coastguard Worker_SKIP_INITIAL_FRAMES = 15 45*b7c941bbSAndroid Build Coastguard Worker_START_FRAME = 30 # give 3A some frames to warm up 46*b7c941bbSAndroid Build Coastguard Worker_VIDEO_DELAY_TIME = 5.5 # seconds 47*b7c941bbSAndroid Build Coastguard Worker_VIDEO_DURATION = 5.5 # seconds 48*b7c941bbSAndroid Build Coastguard Worker 49*b7c941bbSAndroid Build Coastguard Worker 50*b7c941bbSAndroid Build Coastguard Workerdef get_720p_or_above_size(supported_preview_sizes): 51*b7c941bbSAndroid Build Coastguard Worker """Returns the smallest size above or equal to 720p in preview and video. 52*b7c941bbSAndroid Build Coastguard Worker 53*b7c941bbSAndroid Build Coastguard Worker If the largest preview size is under 720P, returns the largest value. 54*b7c941bbSAndroid Build Coastguard Worker 55*b7c941bbSAndroid Build Coastguard Worker Args: 56*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes: list; preview sizes. 57*b7c941bbSAndroid Build Coastguard Worker e.g. ['1920x960', '1600x1200', '1920x1080'] 58*b7c941bbSAndroid Build Coastguard Worker Returns: 59*b7c941bbSAndroid Build Coastguard Worker smallest size >= 720p video format 60*b7c941bbSAndroid Build Coastguard Worker """ 61*b7c941bbSAndroid Build Coastguard Worker 62*b7c941bbSAndroid Build Coastguard Worker size_to_area = lambda s: int(s.split('x')[0])*int(s.split('x')[1]) 63*b7c941bbSAndroid Build Coastguard Worker smallest_area = float('inf') 64*b7c941bbSAndroid Build Coastguard Worker smallest_720p_or_above_size = '' 65*b7c941bbSAndroid Build Coastguard Worker largest_supported_preview_size = '' 66*b7c941bbSAndroid Build Coastguard Worker largest_area = 0 67*b7c941bbSAndroid Build Coastguard Worker for size in supported_preview_sizes: 68*b7c941bbSAndroid Build Coastguard Worker area = size_to_area(size) 69*b7c941bbSAndroid Build Coastguard Worker if smallest_area > area >= _AREA_720P_VIDEO: 70*b7c941bbSAndroid Build Coastguard Worker smallest_area = area 71*b7c941bbSAndroid Build Coastguard Worker smallest_720p_or_above_size = size 72*b7c941bbSAndroid Build Coastguard Worker else: 73*b7c941bbSAndroid Build Coastguard Worker if area > largest_area: 74*b7c941bbSAndroid Build Coastguard Worker largest_area = area 75*b7c941bbSAndroid Build Coastguard Worker largest_supported_preview_size = size 76*b7c941bbSAndroid Build Coastguard Worker 77*b7c941bbSAndroid Build Coastguard Worker if largest_area > _AREA_720P_VIDEO: 78*b7c941bbSAndroid Build Coastguard Worker logging.debug('Smallest 720p or above size: %s', 79*b7c941bbSAndroid Build Coastguard Worker smallest_720p_or_above_size) 80*b7c941bbSAndroid Build Coastguard Worker return smallest_720p_or_above_size 81*b7c941bbSAndroid Build Coastguard Worker else: 82*b7c941bbSAndroid Build Coastguard Worker logging.debug('Largest supported preview size: %s', 83*b7c941bbSAndroid Build Coastguard Worker largest_supported_preview_size) 84*b7c941bbSAndroid Build Coastguard Worker return largest_supported_preview_size 85*b7c941bbSAndroid Build Coastguard Worker 86*b7c941bbSAndroid Build Coastguard Worker 87*b7c941bbSAndroid Build Coastguard Workerdef collect_data(cam, tablet_device, preview_size, stabilize, rot_rig, 88*b7c941bbSAndroid Build Coastguard Worker zoom_ratio=None, fps_range=None, hlg10=False, ois=False): 89*b7c941bbSAndroid Build Coastguard Worker """Capture a new set of data from the device. 90*b7c941bbSAndroid Build Coastguard Worker 91*b7c941bbSAndroid Build Coastguard Worker Captures camera preview frames while the user is moving the device in 92*b7c941bbSAndroid Build Coastguard Worker the prescribed manner. 93*b7c941bbSAndroid Build Coastguard Worker 94*b7c941bbSAndroid Build Coastguard Worker Args: 95*b7c941bbSAndroid Build Coastguard Worker cam: camera object. 96*b7c941bbSAndroid Build Coastguard Worker tablet_device: boolean; based on config file. 97*b7c941bbSAndroid Build Coastguard Worker preview_size: str; preview stream resolution. ex. '1920x1080' 98*b7c941bbSAndroid Build Coastguard Worker stabilize: boolean; whether preview stabilization is ON. 99*b7c941bbSAndroid Build Coastguard Worker rot_rig: dict with 'cntl' and 'ch' defined. 100*b7c941bbSAndroid Build Coastguard Worker zoom_ratio: float; static zoom ratio. None if default zoom. 101*b7c941bbSAndroid Build Coastguard Worker fps_range: list; target fps range. 102*b7c941bbSAndroid Build Coastguard Worker hlg10: boolean; whether to capture hlg10 output. 103*b7c941bbSAndroid Build Coastguard Worker ois: boolean; whether optical image stabilization is ON. 104*b7c941bbSAndroid Build Coastguard Worker Returns: 105*b7c941bbSAndroid Build Coastguard Worker recording object; a dictionary containing output path, video size, etc. 106*b7c941bbSAndroid Build Coastguard Worker """ 107*b7c941bbSAndroid Build Coastguard Worker 108*b7c941bbSAndroid Build Coastguard Worker output_surfaces = cam.preview_surface(preview_size, hlg10) 109*b7c941bbSAndroid Build Coastguard Worker return collect_data_with_surfaces(cam, tablet_device, output_surfaces, 110*b7c941bbSAndroid Build Coastguard Worker stabilize, rot_rig, zoom_ratio, 111*b7c941bbSAndroid Build Coastguard Worker fps_range, ois) 112*b7c941bbSAndroid Build Coastguard Worker 113*b7c941bbSAndroid Build Coastguard Worker 114*b7c941bbSAndroid Build Coastguard Workerdef collect_data_with_surfaces(cam, tablet_device, output_surfaces, 115*b7c941bbSAndroid Build Coastguard Worker stabilize, rot_rig, zoom_ratio=None, 116*b7c941bbSAndroid Build Coastguard Worker fps_range=None, ois=False): 117*b7c941bbSAndroid Build Coastguard Worker """Capture a new set of data from the device. 118*b7c941bbSAndroid Build Coastguard Worker 119*b7c941bbSAndroid Build Coastguard Worker Captures camera preview frames while the user is moving the device in 120*b7c941bbSAndroid Build Coastguard Worker the prescribed manner. 121*b7c941bbSAndroid Build Coastguard Worker 122*b7c941bbSAndroid Build Coastguard Worker Args: 123*b7c941bbSAndroid Build Coastguard Worker cam: camera object. 124*b7c941bbSAndroid Build Coastguard Worker tablet_device: boolean; based on config file. 125*b7c941bbSAndroid Build Coastguard Worker output_surfaces: list of dict; The list of output surfaces configured for 126*b7c941bbSAndroid Build Coastguard Worker the recording. Only the first surface is used for recording; the rest are 127*b7c941bbSAndroid Build Coastguard Worker configured, but not requested. 128*b7c941bbSAndroid Build Coastguard Worker stabilize: boolean; whether preview stabilization is ON. 129*b7c941bbSAndroid Build Coastguard Worker rot_rig: dict with 'cntl' and 'ch' defined. 130*b7c941bbSAndroid Build Coastguard Worker zoom_ratio: float; static zoom ratio. None if default zoom. 131*b7c941bbSAndroid Build Coastguard Worker fps_range: list; target fps range. 132*b7c941bbSAndroid Build Coastguard Worker ois: boolean; whether optical image stabilization is ON. 133*b7c941bbSAndroid Build Coastguard Worker Returns: 134*b7c941bbSAndroid Build Coastguard Worker recording object; a dictionary containing output path, video size, etc. 135*b7c941bbSAndroid Build Coastguard Worker """ 136*b7c941bbSAndroid Build Coastguard Worker 137*b7c941bbSAndroid Build Coastguard Worker logging.debug('Starting sensor event collection') 138*b7c941bbSAndroid Build Coastguard Worker serial_port = None 139*b7c941bbSAndroid Build Coastguard Worker if rot_rig['cntl'].lower() == sensor_fusion_utils.ARDUINO_STRING.lower(): 140*b7c941bbSAndroid Build Coastguard Worker # identify port 141*b7c941bbSAndroid Build Coastguard Worker serial_port = sensor_fusion_utils.serial_port_def( 142*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.ARDUINO_STRING) 143*b7c941bbSAndroid Build Coastguard Worker # send test cmd to Arduino until cmd returns properly 144*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.establish_serial_comm(serial_port) 145*b7c941bbSAndroid Build Coastguard Worker # Start camera vibration 146*b7c941bbSAndroid Build Coastguard Worker if tablet_device: 147*b7c941bbSAndroid Build Coastguard Worker servo_speed = sensor_fusion_utils.ARDUINO_SERVO_SPEED_STABILIZATION_TABLET 148*b7c941bbSAndroid Build Coastguard Worker else: 149*b7c941bbSAndroid Build Coastguard Worker servo_speed = sensor_fusion_utils.ARDUINO_SERVO_SPEED_STABILIZATION 150*b7c941bbSAndroid Build Coastguard Worker p = threading.Thread( 151*b7c941bbSAndroid Build Coastguard Worker target=sensor_fusion_utils.rotation_rig, 152*b7c941bbSAndroid Build Coastguard Worker args=( 153*b7c941bbSAndroid Build Coastguard Worker rot_rig['cntl'], 154*b7c941bbSAndroid Build Coastguard Worker rot_rig['ch'], 155*b7c941bbSAndroid Build Coastguard Worker _NUM_ROTATIONS, 156*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.ARDUINO_ANGLES_STABILIZATION, 157*b7c941bbSAndroid Build Coastguard Worker servo_speed, 158*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.ARDUINO_MOVE_TIME_STABILIZATION, 159*b7c941bbSAndroid Build Coastguard Worker serial_port, 160*b7c941bbSAndroid Build Coastguard Worker ), 161*b7c941bbSAndroid Build Coastguard Worker ) 162*b7c941bbSAndroid Build Coastguard Worker p.start() 163*b7c941bbSAndroid Build Coastguard Worker 164*b7c941bbSAndroid Build Coastguard Worker cam.start_sensor_events() 165*b7c941bbSAndroid Build Coastguard Worker # Allow time for rig to start moving 166*b7c941bbSAndroid Build Coastguard Worker time.sleep(_VIDEO_DELAY_TIME) 167*b7c941bbSAndroid Build Coastguard Worker 168*b7c941bbSAndroid Build Coastguard Worker # Record video and return recording object 169*b7c941bbSAndroid Build Coastguard Worker min_fps = fps_range[0] if (fps_range is not None) else None 170*b7c941bbSAndroid Build Coastguard Worker max_fps = fps_range[1] if (fps_range is not None) else None 171*b7c941bbSAndroid Build Coastguard Worker recording_obj = cam.do_preview_recording_multiple_surfaces( 172*b7c941bbSAndroid Build Coastguard Worker output_surfaces, _VIDEO_DURATION, stabilize, ois, zoom_ratio=zoom_ratio, 173*b7c941bbSAndroid Build Coastguard Worker ae_target_fps_min=min_fps, ae_target_fps_max=max_fps) 174*b7c941bbSAndroid Build Coastguard Worker 175*b7c941bbSAndroid Build Coastguard Worker logging.debug('Recorded output path: %s', recording_obj['recordedOutputPath']) 176*b7c941bbSAndroid Build Coastguard Worker logging.debug('Tested quality: %s', recording_obj['quality']) 177*b7c941bbSAndroid Build Coastguard Worker 178*b7c941bbSAndroid Build Coastguard Worker # Wait for vibration to stop 179*b7c941bbSAndroid Build Coastguard Worker p.join() 180*b7c941bbSAndroid Build Coastguard Worker 181*b7c941bbSAndroid Build Coastguard Worker return recording_obj 182*b7c941bbSAndroid Build Coastguard Worker 183*b7c941bbSAndroid Build Coastguard Worker 184*b7c941bbSAndroid Build Coastguard Workerdef verify_preview_stabilization(recording_obj, gyro_events, 185*b7c941bbSAndroid Build Coastguard Worker test_name, log_path, facing, zoom_ratio=None): 186*b7c941bbSAndroid Build Coastguard Worker """Verify the returned recording is properly stabilized. 187*b7c941bbSAndroid Build Coastguard Worker 188*b7c941bbSAndroid Build Coastguard Worker Args: 189*b7c941bbSAndroid Build Coastguard Worker recording_obj: Camcorder recording object. 190*b7c941bbSAndroid Build Coastguard Worker gyro_events: Gyroscope events collected while recording. 191*b7c941bbSAndroid Build Coastguard Worker test_name: Name of the test. 192*b7c941bbSAndroid Build Coastguard Worker log_path: Path for the log file. 193*b7c941bbSAndroid Build Coastguard Worker facing: Facing of the camera device. 194*b7c941bbSAndroid Build Coastguard Worker zoom_ratio: Static zoom ratio. None if default zoom. 195*b7c941bbSAndroid Build Coastguard Worker 196*b7c941bbSAndroid Build Coastguard Worker Returns: 197*b7c941bbSAndroid Build Coastguard Worker A dictionary containing the maximum gyro angle, the maximum camera angle, 198*b7c941bbSAndroid Build Coastguard Worker and a failure message if the recorded video isn't properly stablilized. 199*b7c941bbSAndroid Build Coastguard Worker """ 200*b7c941bbSAndroid Build Coastguard Worker 201*b7c941bbSAndroid Build Coastguard Worker file_name = recording_obj['recordedOutputPath'].split('/')[-1] 202*b7c941bbSAndroid Build Coastguard Worker logging.debug('recorded file name: %s', file_name) 203*b7c941bbSAndroid Build Coastguard Worker video_size = recording_obj['videoSize'] 204*b7c941bbSAndroid Build Coastguard Worker logging.debug('video size: %s', video_size) 205*b7c941bbSAndroid Build Coastguard Worker 206*b7c941bbSAndroid Build Coastguard Worker # Get all frames from the video 207*b7c941bbSAndroid Build Coastguard Worker file_list = video_processing_utils.extract_all_frames_from_video( 208*b7c941bbSAndroid Build Coastguard Worker log_path, file_name, _IMG_FORMAT 209*b7c941bbSAndroid Build Coastguard Worker ) 210*b7c941bbSAndroid Build Coastguard Worker frames = [] 211*b7c941bbSAndroid Build Coastguard Worker 212*b7c941bbSAndroid Build Coastguard Worker logging.debug('Number of frames %d', len(file_list)) 213*b7c941bbSAndroid Build Coastguard Worker for file in file_list: 214*b7c941bbSAndroid Build Coastguard Worker img_bgr = cv2.imread(os.path.join(log_path, file)) 215*b7c941bbSAndroid Build Coastguard Worker img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) 216*b7c941bbSAndroid Build Coastguard Worker frames.append(img_rgb / 255) 217*b7c941bbSAndroid Build Coastguard Worker frame_h, frame_w, _ = frames[0].shape 218*b7c941bbSAndroid Build Coastguard Worker logging.debug('Frame size %d x %d', frame_w, frame_h) 219*b7c941bbSAndroid Build Coastguard Worker 220*b7c941bbSAndroid Build Coastguard Worker # Extract camera rotations 221*b7c941bbSAndroid Build Coastguard Worker if zoom_ratio: 222*b7c941bbSAndroid Build Coastguard Worker zoom_ratio_suffix = f'{zoom_ratio:.1f}' 223*b7c941bbSAndroid Build Coastguard Worker else: 224*b7c941bbSAndroid Build Coastguard Worker zoom_ratio_suffix = '1' 225*b7c941bbSAndroid Build Coastguard Worker file_name_stem = ( 226*b7c941bbSAndroid Build Coastguard Worker f'{os.path.join(log_path, test_name)}_{video_size}_{zoom_ratio_suffix}x') 227*b7c941bbSAndroid Build Coastguard Worker cam_rots = sensor_fusion_utils.get_cam_rotations( 228*b7c941bbSAndroid Build Coastguard Worker frames[_START_FRAME:], 229*b7c941bbSAndroid Build Coastguard Worker facing, 230*b7c941bbSAndroid Build Coastguard Worker frame_h, 231*b7c941bbSAndroid Build Coastguard Worker file_name_stem, 232*b7c941bbSAndroid Build Coastguard Worker _START_FRAME, 233*b7c941bbSAndroid Build Coastguard Worker stabilized_video=True 234*b7c941bbSAndroid Build Coastguard Worker ) 235*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.plot_camera_rotations(cam_rots, _START_FRAME, 236*b7c941bbSAndroid Build Coastguard Worker video_size, file_name_stem) 237*b7c941bbSAndroid Build Coastguard Worker max_camera_angle = sensor_fusion_utils.calc_max_rotation_angle( 238*b7c941bbSAndroid Build Coastguard Worker cam_rots, 'Camera') 239*b7c941bbSAndroid Build Coastguard Worker 240*b7c941bbSAndroid Build Coastguard Worker # Extract gyro rotations 241*b7c941bbSAndroid Build Coastguard Worker sensor_fusion_utils.plot_gyro_events( 242*b7c941bbSAndroid Build Coastguard Worker gyro_events, f'{test_name}_{video_size}_{zoom_ratio_suffix}x', 243*b7c941bbSAndroid Build Coastguard Worker log_path) 244*b7c941bbSAndroid Build Coastguard Worker gyro_rots = sensor_fusion_utils.conv_acceleration_to_movement( 245*b7c941bbSAndroid Build Coastguard Worker gyro_events, _VIDEO_DELAY_TIME) 246*b7c941bbSAndroid Build Coastguard Worker max_gyro_angle = sensor_fusion_utils.calc_max_rotation_angle( 247*b7c941bbSAndroid Build Coastguard Worker gyro_rots, 'Gyro') 248*b7c941bbSAndroid Build Coastguard Worker logging.debug( 249*b7c941bbSAndroid Build Coastguard Worker 'Max deflection (degrees) %s: video: %.3f, gyro: %.3f ratio: %.4f', 250*b7c941bbSAndroid Build Coastguard Worker video_size, max_camera_angle, max_gyro_angle, 251*b7c941bbSAndroid Build Coastguard Worker max_camera_angle / max_gyro_angle) 252*b7c941bbSAndroid Build Coastguard Worker 253*b7c941bbSAndroid Build Coastguard Worker # Assert phone is moved enough during test 254*b7c941bbSAndroid Build Coastguard Worker if max_gyro_angle < _MIN_PHONE_MOVEMENT_ANGLE: 255*b7c941bbSAndroid Build Coastguard Worker raise AssertionError( 256*b7c941bbSAndroid Build Coastguard Worker f'Phone not moved enough! Movement: {max_gyro_angle}, ' 257*b7c941bbSAndroid Build Coastguard Worker f'THRESH: {_MIN_PHONE_MOVEMENT_ANGLE} degrees') 258*b7c941bbSAndroid Build Coastguard Worker 259*b7c941bbSAndroid Build Coastguard Worker w_x_h = video_size.split('x') 260*b7c941bbSAndroid Build Coastguard Worker if int(w_x_h[0])/int(w_x_h[1]) > _ASPECT_RATIO_16_9: 261*b7c941bbSAndroid Build Coastguard Worker preview_stabilization_factor = _PREVIEW_STABILIZATION_FACTOR * 1.1 262*b7c941bbSAndroid Build Coastguard Worker else: 263*b7c941bbSAndroid Build Coastguard Worker preview_stabilization_factor = _PREVIEW_STABILIZATION_FACTOR 264*b7c941bbSAndroid Build Coastguard Worker 265*b7c941bbSAndroid Build Coastguard Worker failure_msg = None 266*b7c941bbSAndroid Build Coastguard Worker if max_camera_angle >= max_gyro_angle * preview_stabilization_factor: 267*b7c941bbSAndroid Build Coastguard Worker failure_msg = ( 268*b7c941bbSAndroid Build Coastguard Worker f'{video_size} preview not stabilized enough! ' 269*b7c941bbSAndroid Build Coastguard Worker f'Max preview angle: {max_camera_angle:.3f}, ' 270*b7c941bbSAndroid Build Coastguard Worker f'Max gyro angle: {max_gyro_angle:.3f}, ' 271*b7c941bbSAndroid Build Coastguard Worker f'ratio: {max_camera_angle/max_gyro_angle:.3f} ' 272*b7c941bbSAndroid Build Coastguard Worker f'THRESH: {preview_stabilization_factor}.') 273*b7c941bbSAndroid Build Coastguard Worker # Delete saved frames if the format is a PASS 274*b7c941bbSAndroid Build Coastguard Worker else: 275*b7c941bbSAndroid Build Coastguard Worker for file in file_list: 276*b7c941bbSAndroid Build Coastguard Worker try: 277*b7c941bbSAndroid Build Coastguard Worker os.remove(os.path.join(log_path, file)) 278*b7c941bbSAndroid Build Coastguard Worker except FileNotFoundError: 279*b7c941bbSAndroid Build Coastguard Worker logging.debug('File Not Found: %s', str(file)) 280*b7c941bbSAndroid Build Coastguard Worker logging.debug('Format %s passes, frame images removed', video_size) 281*b7c941bbSAndroid Build Coastguard Worker 282*b7c941bbSAndroid Build Coastguard Worker return {'gyro': max_gyro_angle, 'cam': max_camera_angle, 283*b7c941bbSAndroid Build Coastguard Worker 'failure': failure_msg} 284*b7c941bbSAndroid Build Coastguard Worker 285*b7c941bbSAndroid Build Coastguard Worker 286*b7c941bbSAndroid Build Coastguard Workerdef collect_preview_data_with_zoom(cam, preview_size, zoom_start, 287*b7c941bbSAndroid Build Coastguard Worker zoom_end, step_size, recording_duration_ms, 288*b7c941bbSAndroid Build Coastguard Worker padded_frames=False): 289*b7c941bbSAndroid Build Coastguard Worker """Captures a preview video from the device. 290*b7c941bbSAndroid Build Coastguard Worker 291*b7c941bbSAndroid Build Coastguard Worker Captures camera preview frames from the passed device. 292*b7c941bbSAndroid Build Coastguard Worker 293*b7c941bbSAndroid Build Coastguard Worker Args: 294*b7c941bbSAndroid Build Coastguard Worker cam: camera object. 295*b7c941bbSAndroid Build Coastguard Worker preview_size: str; preview resolution. ex. '1920x1080'. 296*b7c941bbSAndroid Build Coastguard Worker zoom_start: (float) is the starting zoom ratio during recording. 297*b7c941bbSAndroid Build Coastguard Worker zoom_end: (float) is the ending zoom ratio during recording. 298*b7c941bbSAndroid Build Coastguard Worker step_size: (float) is the step for zoom ratio during recording. 299*b7c941bbSAndroid Build Coastguard Worker recording_duration_ms: preview recording duration in ms. 300*b7c941bbSAndroid Build Coastguard Worker padded_frames: boolean; Whether to add additional frames at the beginning 301*b7c941bbSAndroid Build Coastguard Worker and end of recording to workaround issue with MediaRecorder. 302*b7c941bbSAndroid Build Coastguard Worker 303*b7c941bbSAndroid Build Coastguard Worker Returns: 304*b7c941bbSAndroid Build Coastguard Worker recording object as described by cam.do_preview_recording_with_dynamic_zoom. 305*b7c941bbSAndroid Build Coastguard Worker """ 306*b7c941bbSAndroid Build Coastguard Worker recording_obj = cam.do_preview_recording_with_dynamic_zoom( 307*b7c941bbSAndroid Build Coastguard Worker preview_size, 308*b7c941bbSAndroid Build Coastguard Worker stabilize=False, 309*b7c941bbSAndroid Build Coastguard Worker sweep_zoom=(zoom_start, zoom_end, step_size, recording_duration_ms), 310*b7c941bbSAndroid Build Coastguard Worker padded_frames=padded_frames 311*b7c941bbSAndroid Build Coastguard Worker ) 312*b7c941bbSAndroid Build Coastguard Worker logging.debug('Recorded output path: %s', recording_obj['recordedOutputPath']) 313*b7c941bbSAndroid Build Coastguard Worker logging.debug('Tested quality: %s', recording_obj['quality']) 314*b7c941bbSAndroid Build Coastguard Worker return recording_obj 315*b7c941bbSAndroid Build Coastguard Worker 316*b7c941bbSAndroid Build Coastguard Worker 317*b7c941bbSAndroid Build Coastguard Workerdef is_aspect_ratio_match(size_str, target_ratio): 318*b7c941bbSAndroid Build Coastguard Worker """Checks if a resolution string matches the target aspect ratio.""" 319*b7c941bbSAndroid Build Coastguard Worker width, height = map(int, size_str.split('x')) 320*b7c941bbSAndroid Build Coastguard Worker return abs(width / height - target_ratio) < _ASPECT_TOL 321*b7c941bbSAndroid Build Coastguard Worker 322*b7c941bbSAndroid Build Coastguard Worker 323*b7c941bbSAndroid Build Coastguard Workerdef get_max_preview_test_size(cam, camera_id, aspect_ratio=None, 324*b7c941bbSAndroid Build Coastguard Worker max_tested_area=_PREVIEW_MAX_TESTED_AREA): 325*b7c941bbSAndroid Build Coastguard Worker """Finds the max preview size to be tested. 326*b7c941bbSAndroid Build Coastguard Worker 327*b7c941bbSAndroid Build Coastguard Worker If the device supports the _HIGH_RES_SIZE preview size then 328*b7c941bbSAndroid Build Coastguard Worker it uses that for testing, otherwise uses the max supported 329*b7c941bbSAndroid Build Coastguard Worker preview size capped at max_tested_area. 330*b7c941bbSAndroid Build Coastguard Worker 331*b7c941bbSAndroid Build Coastguard Worker Args: 332*b7c941bbSAndroid Build Coastguard Worker cam: camera object 333*b7c941bbSAndroid Build Coastguard Worker camera_id: str; camera device id under test 334*b7c941bbSAndroid Build Coastguard Worker aspect_ratio: preferred aspect_ratio For example: '4/3' 335*b7c941bbSAndroid Build Coastguard Worker max_tested_area: area of max preview resolution 336*b7c941bbSAndroid Build Coastguard Worker 337*b7c941bbSAndroid Build Coastguard Worker Returns: 338*b7c941bbSAndroid Build Coastguard Worker preview_test_size: str; wxh resolution of the size to be tested 339*b7c941bbSAndroid Build Coastguard Worker """ 340*b7c941bbSAndroid Build Coastguard Worker resolution_to_area = lambda s: int(s.split('x')[0])*int(s.split('x')[1]) 341*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes = cam.get_all_supported_preview_sizes( 342*b7c941bbSAndroid Build Coastguard Worker camera_id, filter_recordable=True) 343*b7c941bbSAndroid Build Coastguard Worker logging.debug('Resolutions supported by preview and MediaRecorder: %s', 344*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes) 345*b7c941bbSAndroid Build Coastguard Worker 346*b7c941bbSAndroid Build Coastguard Worker if aspect_ratio is None: 347*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes = [size for size in supported_preview_sizes 348*b7c941bbSAndroid Build Coastguard Worker if resolution_to_area(size) 349*b7c941bbSAndroid Build Coastguard Worker >= video_processing_utils.LOWEST_RES_TESTED_AREA] 350*b7c941bbSAndroid Build Coastguard Worker else: 351*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes = [size for size in supported_preview_sizes 352*b7c941bbSAndroid Build Coastguard Worker if resolution_to_area(size) 353*b7c941bbSAndroid Build Coastguard Worker >= video_processing_utils.LOWEST_RES_TESTED_AREA 354*b7c941bbSAndroid Build Coastguard Worker and is_aspect_ratio_match(size, aspect_ratio)] 355*b7c941bbSAndroid Build Coastguard Worker 356*b7c941bbSAndroid Build Coastguard Worker logging.debug('Supported preview resolutions: %s', supported_preview_sizes) 357*b7c941bbSAndroid Build Coastguard Worker 358*b7c941bbSAndroid Build Coastguard Worker if _HIGH_RES_SIZE in supported_preview_sizes: 359*b7c941bbSAndroid Build Coastguard Worker preview_test_size = _HIGH_RES_SIZE 360*b7c941bbSAndroid Build Coastguard Worker else: 361*b7c941bbSAndroid Build Coastguard Worker capped_supported_preview_sizes = [ 362*b7c941bbSAndroid Build Coastguard Worker size 363*b7c941bbSAndroid Build Coastguard Worker for size in supported_preview_sizes 364*b7c941bbSAndroid Build Coastguard Worker if ( 365*b7c941bbSAndroid Build Coastguard Worker resolution_to_area(size) <= max_tested_area 366*b7c941bbSAndroid Build Coastguard Worker and resolution_to_area(size) >= _PREVIEW_MIN_TESTED_AREA 367*b7c941bbSAndroid Build Coastguard Worker ) 368*b7c941bbSAndroid Build Coastguard Worker ] 369*b7c941bbSAndroid Build Coastguard Worker logging.debug('Capped preview resolutions: %s', 370*b7c941bbSAndroid Build Coastguard Worker capped_supported_preview_sizes) 371*b7c941bbSAndroid Build Coastguard Worker preview_test_size = capped_supported_preview_sizes[-1] 372*b7c941bbSAndroid Build Coastguard Worker 373*b7c941bbSAndroid Build Coastguard Worker logging.debug('Selected preview resolution: %s', preview_test_size) 374*b7c941bbSAndroid Build Coastguard Worker 375*b7c941bbSAndroid Build Coastguard Worker return preview_test_size 376*b7c941bbSAndroid Build Coastguard Worker 377*b7c941bbSAndroid Build Coastguard Worker 378*b7c941bbSAndroid Build Coastguard Workerdef get_max_extension_preview_test_size(cam, camera_id, extension): 379*b7c941bbSAndroid Build Coastguard Worker """Finds the max preview size for an extension to be tested. 380*b7c941bbSAndroid Build Coastguard Worker 381*b7c941bbSAndroid Build Coastguard Worker If the device supports the _HIGH_RES_SIZE preview size then 382*b7c941bbSAndroid Build Coastguard Worker it uses that for testing, otherwise uses the max supported 383*b7c941bbSAndroid Build Coastguard Worker preview size capped at _PREVIEW_MAX_TESTED_AREA. 384*b7c941bbSAndroid Build Coastguard Worker 385*b7c941bbSAndroid Build Coastguard Worker Args: 386*b7c941bbSAndroid Build Coastguard Worker cam: camera object 387*b7c941bbSAndroid Build Coastguard Worker camera_id: str; camera device id under test 388*b7c941bbSAndroid Build Coastguard Worker extension: int; camera extension mode under test 389*b7c941bbSAndroid Build Coastguard Worker 390*b7c941bbSAndroid Build Coastguard Worker Returns: 391*b7c941bbSAndroid Build Coastguard Worker preview_test_size: str; wxh resolution of the size to be tested 392*b7c941bbSAndroid Build Coastguard Worker """ 393*b7c941bbSAndroid Build Coastguard Worker resolution_to_area = lambda s: int(s.split('x')[0])*int(s.split('x')[1]) 394*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes = ( 395*b7c941bbSAndroid Build Coastguard Worker cam.get_supported_extension_preview_sizes(camera_id, extension)) 396*b7c941bbSAndroid Build Coastguard Worker supported_preview_sizes = [size for size in supported_preview_sizes 397*b7c941bbSAndroid Build Coastguard Worker if resolution_to_area(size) 398*b7c941bbSAndroid Build Coastguard Worker >= video_processing_utils.LOWEST_RES_TESTED_AREA] 399*b7c941bbSAndroid Build Coastguard Worker logging.debug('Supported preview resolutions for extension %d: %s', 400*b7c941bbSAndroid Build Coastguard Worker extension, supported_preview_sizes) 401*b7c941bbSAndroid Build Coastguard Worker 402*b7c941bbSAndroid Build Coastguard Worker if _HIGH_RES_SIZE in supported_preview_sizes: 403*b7c941bbSAndroid Build Coastguard Worker preview_test_size = _HIGH_RES_SIZE 404*b7c941bbSAndroid Build Coastguard Worker else: 405*b7c941bbSAndroid Build Coastguard Worker capped_supported_preview_sizes = [ 406*b7c941bbSAndroid Build Coastguard Worker size 407*b7c941bbSAndroid Build Coastguard Worker for size in supported_preview_sizes 408*b7c941bbSAndroid Build Coastguard Worker if ( 409*b7c941bbSAndroid Build Coastguard Worker resolution_to_area(size) <= _PREVIEW_MAX_TESTED_AREA 410*b7c941bbSAndroid Build Coastguard Worker and resolution_to_area(size) >= _PREVIEW_MIN_TESTED_AREA 411*b7c941bbSAndroid Build Coastguard Worker ) 412*b7c941bbSAndroid Build Coastguard Worker ] 413*b7c941bbSAndroid Build Coastguard Worker preview_test_size = capped_supported_preview_sizes[-1] 414*b7c941bbSAndroid Build Coastguard Worker 415*b7c941bbSAndroid Build Coastguard Worker logging.debug('Selected preview resolution: %s', preview_test_size) 416*b7c941bbSAndroid Build Coastguard Worker 417*b7c941bbSAndroid Build Coastguard Worker return preview_test_size 418*b7c941bbSAndroid Build Coastguard Worker 419*b7c941bbSAndroid Build Coastguard Worker 420*b7c941bbSAndroid Build Coastguard Workerdef mirror_preview_image_by_sensor_orientation( 421*b7c941bbSAndroid Build Coastguard Worker sensor_orientation, input_preview_img): 422*b7c941bbSAndroid Build Coastguard Worker """If testing front camera, mirror preview image to match camera capture. 423*b7c941bbSAndroid Build Coastguard Worker 424*b7c941bbSAndroid Build Coastguard Worker Preview are flipped on device's natural orientation, so for sensor 425*b7c941bbSAndroid Build Coastguard Worker orientation 90 or 270, it is up or down. Sensor orientation 0 or 180 426*b7c941bbSAndroid Build Coastguard Worker is left or right. 427*b7c941bbSAndroid Build Coastguard Worker 428*b7c941bbSAndroid Build Coastguard Worker Args: 429*b7c941bbSAndroid Build Coastguard Worker sensor_orientation: integer; display orientation in natural position. 430*b7c941bbSAndroid Build Coastguard Worker input_preview_img: numpy array; image extracted from preview recording. 431*b7c941bbSAndroid Build Coastguard Worker Returns: 432*b7c941bbSAndroid Build Coastguard Worker output_preview_img: numpy array; flipped according to natural orientation. 433*b7c941bbSAndroid Build Coastguard Worker """ 434*b7c941bbSAndroid Build Coastguard Worker if sensor_orientation in _NATURAL_ORIENTATION_PORTRAIT: 435*b7c941bbSAndroid Build Coastguard Worker # Opencv expects a numpy array but np.flip generates a 'view' which 436*b7c941bbSAndroid Build Coastguard Worker # doesn't work with opencv. ndarray.copy forces copy instead of view. 437*b7c941bbSAndroid Build Coastguard Worker output_preview_img = np.ndarray.copy(np.flipud(input_preview_img)) 438*b7c941bbSAndroid Build Coastguard Worker logging.debug( 439*b7c941bbSAndroid Build Coastguard Worker 'Found sensor orientation %d, flipping up down', sensor_orientation) 440*b7c941bbSAndroid Build Coastguard Worker else: 441*b7c941bbSAndroid Build Coastguard Worker output_preview_img = np.ndarray.copy(np.fliplr(input_preview_img)) 442*b7c941bbSAndroid Build Coastguard Worker logging.debug( 443*b7c941bbSAndroid Build Coastguard Worker 'Found sensor orientation %d, flipping left right', sensor_orientation) 444*b7c941bbSAndroid Build Coastguard Worker 445*b7c941bbSAndroid Build Coastguard Worker return output_preview_img 446*b7c941bbSAndroid Build Coastguard Worker 447*b7c941bbSAndroid Build Coastguard Worker 448*b7c941bbSAndroid Build Coastguard Workerdef is_image_green(image_path): 449*b7c941bbSAndroid Build Coastguard Worker """Checks if an image is mostly green. 450*b7c941bbSAndroid Build Coastguard Worker 451*b7c941bbSAndroid Build Coastguard Worker Checks if an image is mostly green by ensuring green is dominant 452*b7c941bbSAndroid Build Coastguard Worker and red/blue values are low. 453*b7c941bbSAndroid Build Coastguard Worker 454*b7c941bbSAndroid Build Coastguard Worker Args: 455*b7c941bbSAndroid Build Coastguard Worker image_path: str; The path to the image file. 456*b7c941bbSAndroid Build Coastguard Worker 457*b7c941bbSAndroid Build Coastguard Worker Returns: 458*b7c941bbSAndroid Build Coastguard Worker bool: True if mostly green, False otherwise. 459*b7c941bbSAndroid Build Coastguard Worker """ 460*b7c941bbSAndroid Build Coastguard Worker 461*b7c941bbSAndroid Build Coastguard Worker image = cv2.imread(image_path) 462*b7c941bbSAndroid Build Coastguard Worker 463*b7c941bbSAndroid Build Coastguard Worker green_pixels = ((image[:, :, 1] > _GREEN_TOL) & 464*b7c941bbSAndroid Build Coastguard Worker (image[:, :, 0] < _RED_BLUE_TOL) & 465*b7c941bbSAndroid Build Coastguard Worker (image[:, :, 2] < _RED_BLUE_TOL)).sum() 466*b7c941bbSAndroid Build Coastguard Worker 467*b7c941bbSAndroid Build Coastguard Worker green_percentage = (green_pixels / (image.shape[0] * image.shape[1])) * 100 468*b7c941bbSAndroid Build Coastguard Worker 469*b7c941bbSAndroid Build Coastguard Worker if green_percentage >= _GREEN_PERCENT: 470*b7c941bbSAndroid Build Coastguard Worker return True 471*b7c941bbSAndroid Build Coastguard Worker else: 472*b7c941bbSAndroid Build Coastguard Worker return False 473*b7c941bbSAndroid Build Coastguard Worker 474*b7c941bbSAndroid Build Coastguard Worker 475*b7c941bbSAndroid Build Coastguard Workerdef preview_over_zoom_range(dut, cam, preview_size, z_min, z_max, z_step_size, 476*b7c941bbSAndroid Build Coastguard Worker log_path): 477*b7c941bbSAndroid Build Coastguard Worker """Captures a preview video from the device over zoom range. 478*b7c941bbSAndroid Build Coastguard Worker 479*b7c941bbSAndroid Build Coastguard Worker Captures camera preview frames at various zoom level in zoom range. 480*b7c941bbSAndroid Build Coastguard Worker 481*b7c941bbSAndroid Build Coastguard Worker Args: 482*b7c941bbSAndroid Build Coastguard Worker dut: device under test 483*b7c941bbSAndroid Build Coastguard Worker cam: camera object 484*b7c941bbSAndroid Build Coastguard Worker preview_size: str; preview resolution. ex. '1920x1080' 485*b7c941bbSAndroid Build Coastguard Worker z_min: minimum zoom for preview capture 486*b7c941bbSAndroid Build Coastguard Worker z_max: maximum zoom for preview capture 487*b7c941bbSAndroid Build Coastguard Worker z_step_size: zoom step size from min to max 488*b7c941bbSAndroid Build Coastguard Worker log_path: str; path for video file directory 489*b7c941bbSAndroid Build Coastguard Worker 490*b7c941bbSAndroid Build Coastguard Worker Returns: 491*b7c941bbSAndroid Build Coastguard Worker capture_results: total capture results of each frame 492*b7c941bbSAndroid Build Coastguard Worker file_list: file name for each frame 493*b7c941bbSAndroid Build Coastguard Worker """ 494*b7c941bbSAndroid Build Coastguard Worker logging.debug('z_min : %.2f, z_max = %.2f, z_step_size = %.2f', 495*b7c941bbSAndroid Build Coastguard Worker z_min, z_max, z_step_size) 496*b7c941bbSAndroid Build Coastguard Worker 497*b7c941bbSAndroid Build Coastguard Worker # Converge 3A 498*b7c941bbSAndroid Build Coastguard Worker cam.do_3a() 499*b7c941bbSAndroid Build Coastguard Worker 500*b7c941bbSAndroid Build Coastguard Worker # recording preview 501*b7c941bbSAndroid Build Coastguard Worker # TODO: b/350821827 - encode time stamps in camera frames instead of 502*b7c941bbSAndroid Build Coastguard Worker # padded green frams 503*b7c941bbSAndroid Build Coastguard Worker # MediaRecorder on some devices drop last few frames. To solve this issue 504*b7c941bbSAndroid Build Coastguard Worker # add green frames as padding at the end of recorded camera frames. This way 505*b7c941bbSAndroid Build Coastguard Worker # green buffer frames would be droped by MediaRecorder instead of actual 506*b7c941bbSAndroid Build Coastguard Worker # frames. Later these green padded frames are removed. 507*b7c941bbSAndroid Build Coastguard Worker preview_rec_obj = collect_preview_data_with_zoom( 508*b7c941bbSAndroid Build Coastguard Worker cam, preview_size, z_min, z_max, z_step_size, 509*b7c941bbSAndroid Build Coastguard Worker _PREVIEW_DURATION, padded_frames=True) 510*b7c941bbSAndroid Build Coastguard Worker 511*b7c941bbSAndroid Build Coastguard Worker preview_file_name = its_session_utils.pull_file_from_dut( 512*b7c941bbSAndroid Build Coastguard Worker dut, preview_rec_obj['recordedOutputPath'], log_path) 513*b7c941bbSAndroid Build Coastguard Worker 514*b7c941bbSAndroid Build Coastguard Worker logging.debug('recorded video size : %s', 515*b7c941bbSAndroid Build Coastguard Worker str(preview_rec_obj['videoSize'])) 516*b7c941bbSAndroid Build Coastguard Worker 517*b7c941bbSAndroid Build Coastguard Worker # Extract frames as png from mp4 preview recording 518*b7c941bbSAndroid Build Coastguard Worker file_list = video_processing_utils.extract_all_frames_from_video( 519*b7c941bbSAndroid Build Coastguard Worker log_path, preview_file_name, _IMG_FORMAT 520*b7c941bbSAndroid Build Coastguard Worker ) 521*b7c941bbSAndroid Build Coastguard Worker 522*b7c941bbSAndroid Build Coastguard Worker first_camera_frame_idx = 0 523*b7c941bbSAndroid Build Coastguard Worker last_camera_frame_idx = len(file_list) 524*b7c941bbSAndroid Build Coastguard Worker 525*b7c941bbSAndroid Build Coastguard Worker # Find index of the first-non green frame 526*b7c941bbSAndroid Build Coastguard Worker for (idx, file_name) in enumerate(file_list): 527*b7c941bbSAndroid Build Coastguard Worker file_path = os.path.join(log_path, file_name) 528*b7c941bbSAndroid Build Coastguard Worker if is_image_green(file_path): 529*b7c941bbSAndroid Build Coastguard Worker its_session_utils.remove_file(file_path) 530*b7c941bbSAndroid Build Coastguard Worker logging.debug('Removed green file %s', file_name) 531*b7c941bbSAndroid Build Coastguard Worker else: 532*b7c941bbSAndroid Build Coastguard Worker logging.debug('First camera frame: %s', file_name) 533*b7c941bbSAndroid Build Coastguard Worker first_camera_frame_idx = idx 534*b7c941bbSAndroid Build Coastguard Worker break 535*b7c941bbSAndroid Build Coastguard Worker 536*b7c941bbSAndroid Build Coastguard Worker # Find index of last non-green frame 537*b7c941bbSAndroid Build Coastguard Worker for (idx, file_name) in reversed(list(enumerate(file_list))): 538*b7c941bbSAndroid Build Coastguard Worker file_path = os.path.join(log_path, file_name) 539*b7c941bbSAndroid Build Coastguard Worker if is_image_green(file_path): 540*b7c941bbSAndroid Build Coastguard Worker its_session_utils.remove_file(file_path) 541*b7c941bbSAndroid Build Coastguard Worker logging.debug('Removed green file %s', file_name) 542*b7c941bbSAndroid Build Coastguard Worker else: 543*b7c941bbSAndroid Build Coastguard Worker logging.debug('Last camera frame: %s', file_name) 544*b7c941bbSAndroid Build Coastguard Worker last_camera_frame_idx = idx 545*b7c941bbSAndroid Build Coastguard Worker break 546*b7c941bbSAndroid Build Coastguard Worker 547*b7c941bbSAndroid Build Coastguard Worker logging.debug('start idx = %d -- end idx = %d', first_camera_frame_idx, 548*b7c941bbSAndroid Build Coastguard Worker last_camera_frame_idx) 549*b7c941bbSAndroid Build Coastguard Worker file_list = file_list[first_camera_frame_idx:last_camera_frame_idx+1] 550*b7c941bbSAndroid Build Coastguard Worker 551*b7c941bbSAndroid Build Coastguard Worker # Raise error if capture result and frame count doesn't match 552*b7c941bbSAndroid Build Coastguard Worker capture_results = preview_rec_obj['captureMetadata'] 553*b7c941bbSAndroid Build Coastguard Worker extra_capture_result_count = len(capture_results) - len(file_list) 554*b7c941bbSAndroid Build Coastguard Worker logging.debug('Number of frames %d', len(file_list)) 555*b7c941bbSAndroid Build Coastguard Worker if extra_capture_result_count != 0: 556*b7c941bbSAndroid Build Coastguard Worker its_session_utils.remove_frame_files(log_path) 557*b7c941bbSAndroid Build Coastguard Worker e_msg = (f'Number of CaptureResult ({len(capture_results)}) ' 558*b7c941bbSAndroid Build Coastguard Worker f'vs number of Frames ({len(file_list)}) count mismatch.' 559*b7c941bbSAndroid Build Coastguard Worker ' Retry Test.') 560*b7c941bbSAndroid Build Coastguard Worker raise AssertionError(e_msg) 561*b7c941bbSAndroid Build Coastguard Worker 562*b7c941bbSAndroid Build Coastguard Worker # skip frames which might not have 3A converged 563*b7c941bbSAndroid Build Coastguard Worker capture_results = capture_results[_SKIP_INITIAL_FRAMES:] 564*b7c941bbSAndroid Build Coastguard Worker skipped_files = file_list[:_SKIP_INITIAL_FRAMES] 565*b7c941bbSAndroid Build Coastguard Worker file_list = file_list[_SKIP_INITIAL_FRAMES:] 566*b7c941bbSAndroid Build Coastguard Worker 567*b7c941bbSAndroid Build Coastguard Worker # delete skipped files 568*b7c941bbSAndroid Build Coastguard Worker for file_name in skipped_files: 569*b7c941bbSAndroid Build Coastguard Worker its_session_utils.remove_file(os.path.join(log_path, file_name)) 570*b7c941bbSAndroid Build Coastguard Worker 571*b7c941bbSAndroid Build Coastguard Worker return capture_results, file_list 572