1# Copyright 2014 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"""Verifies different combinations of output formats.""" 15 16 17import logging 18import os 19 20from mobly import test_runner 21 22import its_base_test 23import camera_properties_utils 24import capture_request_utils 25import its_session_utils 26import target_exposure_utils 27 28 29_AUTO_REQUEST_MODE = 1 30_NAME = os.path.splitext(os.path.basename(__file__))[0] 31_STOP_AT_FIRST_FAILURE = False # change to True to have test break @ 1st FAIL 32 33 34class FormatCombosTest(its_base_test.ItsBaseTest): 35 """Test different combinations of output formats. 36 37 Note the test does not require a specific target but does perform 38 both automatic and manual captures so it requires a fixed scene 39 where 3A can converge. 40 """ 41 42 def test_format_combos(self): 43 with its_session_utils.ItsSession( 44 device_id=self.dut.serial, 45 camera_id=self.camera_id, 46 hidden_physical_id=self.hidden_physical_id) as cam: 47 48 props = cam.get_camera_properties() 49 props = cam.override_with_hidden_physical_camera_props(props) 50 51 # Load chart for scene 52 its_session_utils.load_scene( 53 cam, props, self.scene, self.tablet, self.chart_distance) 54 55 successes = [] 56 failures = [] 57 58 # Up to 2 possible request types: auto and manual 59 req_aut = capture_request_utils.auto_capture_request() 60 reqs = [req_aut] 61 if camera_properties_utils.compute_target_exposure(props): 62 e, s = target_exposure_utils.get_target_exposure_combos( 63 self.log_path, cam)['midExposureTime'] 64 req_man = capture_request_utils.manual_capture_request(s, e) 65 reqs.append(req_man) 66 67 # Up to 10 different combos of output formats. 68 # Some are single surfaces and some are multiple surfaces. 69 wyuv, hyuv = capture_request_utils.get_available_output_sizes( 70 'yuv', props)[-1] 71 wjpg, hjpg = capture_request_utils.get_available_output_sizes( 72 'jpg', props)[-1] 73 fmt_yuv_prev = {'format': 'yuv', 'width': wyuv, 'height': hyuv} 74 fmt_yuv_full = {'format': 'yuv'} 75 fmt_jpg_prev = {'format': 'jpeg', 'width': wjpg, 'height': hjpg} 76 fmt_jpg_full = {'format': 'jpeg'} 77 fmt_combos = [ 78 [fmt_yuv_prev], 79 [fmt_yuv_full], 80 [fmt_jpg_prev], 81 [fmt_jpg_full], 82 [fmt_yuv_prev, fmt_jpg_prev], 83 [fmt_yuv_prev, fmt_jpg_full], 84 ] 85 if camera_properties_utils.raw16(props): 86 fmt_raw_full = {'format': 'raw'} 87 fmt_combos.extend([ 88 [fmt_raw_full], 89 [fmt_yuv_prev, fmt_raw_full], 90 [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full], 91 [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]]) 92 93 if camera_properties_utils.y8(props): 94 wy8, hy8 = capture_request_utils.get_available_output_sizes( 95 'y8', props)[-1] 96 fmt_y8_prev = {'format': 'y8', 'width': wy8, 'height': hy8} 97 fmt_y8_full = {'format': 'y8'} 98 fmt_combos.extend([ 99 [fmt_y8_prev], 100 [fmt_y8_full]]) 101 102 # Two different burst lengths: single frame and 3 frames. 103 burst_lens = [1, 3] 104 105 # Run through 2xlen(fmt_combos)x2 different combinations. 106 n = 0 107 for r, req in enumerate(reqs): 108 if req['android.control.mode'] == _AUTO_REQUEST_MODE: 109 req_str = 'auto' 110 else: 111 req_str = 'manual' 112 for f, fmt_combo in enumerate(fmt_combos): 113 for b, burst_len in enumerate(burst_lens): 114 try: 115 cam.do_capture([req] * burst_len, fmt_combo) 116 successes.append((n, r, f, b)) 117 logging.debug('Success[%02d]', n) 118 logging.debug('req: %s', req_str) 119 logging.debug('fmt: %s', str(fmt_combo)) 120 logging.debug('burst_len: %d\n', burst_len) 121 122 except Exception as e: # pylint: disable=broad-except 123 logging.error(e) 124 logging.error('Failure[%02d]', n) 125 logging.debug('req: %s', req_str) 126 logging.error('fmt: %s', str(fmt_combo)) 127 logging.error('burst_len: %d\n', burst_len) 128 failures.append((n, r, f, b)) 129 if _STOP_AT_FIRST_FAILURE: 130 raise AssertionError( 131 f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, ' 132 f'burst: {burst_len}') from e 133 n += 1 134 135 num_fail = len(failures) 136 num_success = len(successes) 137 num_total = len(reqs)*len(fmt_combos)*len(burst_lens) 138 num_not_run = num_total - num_success - num_fail 139 140 logging.debug('Success: %d / %d', num_success, num_total) 141 142 # assert all combinations successfully capture 143 if num_fail != 0: 144 raise AssertionError(f'Number of fails: {num_fail} / {num_total}') 145 if num_not_run > 0: 146 raise AssertionError(f'Number of combos not run: {num_not_run}') 147 148if __name__ == '__main__': 149 test_runner.main() 150