| # Copyright 2014 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Verifies different combinations of output formats.""" |
| |
| |
| import logging |
| import os |
| |
| from mobly import test_runner |
| |
| import its_base_test |
| import camera_properties_utils |
| import capture_request_utils |
| import its_session_utils |
| import target_exposure_utils |
| |
| |
| _AUTO_REQUEST_MODE = 1 |
| _NAME = os.path.splitext(os.path.basename(__file__))[0] |
| _STOP_AT_FIRST_FAILURE = False # change to True to have test break @ 1st FAIL |
| |
| |
| class FormatCombosTest(its_base_test.ItsBaseTest): |
| """Test different combinations of output formats. |
| |
| Note the test does not require a specific target but does perform |
| both automatic and manual captures so it requires a fixed scene |
| where 3A can converge. |
| """ |
| |
| def test_format_combos(self): |
| with its_session_utils.ItsSession( |
| device_id=self.dut.serial, |
| camera_id=self.camera_id, |
| hidden_physical_id=self.hidden_physical_id) as cam: |
| |
| props = cam.get_camera_properties() |
| props = cam.override_with_hidden_physical_camera_props(props) |
| |
| # Load chart for scene |
| its_session_utils.load_scene( |
| cam, props, self.scene, self.tablet, self.chart_distance) |
| |
| successes = [] |
| failures = [] |
| |
| # Up to 2 possible request types: auto and manual |
| req_aut = capture_request_utils.auto_capture_request() |
| reqs = [req_aut] |
| if camera_properties_utils.compute_target_exposure(props): |
| e, s = target_exposure_utils.get_target_exposure_combos( |
| self.log_path, cam)['midExposureTime'] |
| req_man = capture_request_utils.manual_capture_request(s, e) |
| reqs.append(req_man) |
| |
| # Up to 10 different combos of output formats. |
| # Some are single surfaces and some are multiple surfaces. |
| wyuv, hyuv = capture_request_utils.get_available_output_sizes( |
| 'yuv', props)[-1] |
| wjpg, hjpg = capture_request_utils.get_available_output_sizes( |
| 'jpg', props)[-1] |
| fmt_yuv_prev = {'format': 'yuv', 'width': wyuv, 'height': hyuv} |
| fmt_yuv_full = {'format': 'yuv'} |
| fmt_jpg_prev = {'format': 'jpeg', 'width': wjpg, 'height': hjpg} |
| fmt_jpg_full = {'format': 'jpeg'} |
| fmt_combos = [ |
| [fmt_yuv_prev], |
| [fmt_yuv_full], |
| [fmt_jpg_prev], |
| [fmt_jpg_full], |
| [fmt_yuv_prev, fmt_jpg_prev], |
| [fmt_yuv_prev, fmt_jpg_full], |
| ] |
| if camera_properties_utils.raw16(props): |
| fmt_raw_full = {'format': 'raw'} |
| fmt_combos.extend([ |
| [fmt_raw_full], |
| [fmt_yuv_prev, fmt_raw_full], |
| [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full], |
| [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full]]) |
| |
| if camera_properties_utils.y8(props): |
| wy8, hy8 = capture_request_utils.get_available_output_sizes( |
| 'y8', props)[-1] |
| fmt_y8_prev = {'format': 'y8', 'width': wy8, 'height': hy8} |
| fmt_y8_full = {'format': 'y8'} |
| fmt_combos.extend([ |
| [fmt_y8_prev], |
| [fmt_y8_full]]) |
| |
| # Two different burst lengths: single frame and 3 frames. |
| burst_lens = [1, 3] |
| |
| # Run through 2xlen(fmt_combos)x2 different combinations. |
| n = 0 |
| for r, req in enumerate(reqs): |
| if req['android.control.mode'] == _AUTO_REQUEST_MODE: |
| req_str = 'auto' |
| else: |
| req_str = 'manual' |
| for f, fmt_combo in enumerate(fmt_combos): |
| for b, burst_len in enumerate(burst_lens): |
| try: |
| cam.do_capture([req] * burst_len, fmt_combo) |
| successes.append((n, r, f, b)) |
| logging.debug('Success[%02d]', n) |
| logging.debug('req: %s', req_str) |
| logging.debug('fmt: %s', str(fmt_combo)) |
| logging.debug('burst_len: %d\n', burst_len) |
| |
| except Exception as e: # pylint: disable=broad-except |
| logging.error(e) |
| logging.error('Failure[%02d]', n) |
| logging.debug('req: %s', req_str) |
| logging.error('fmt: %s', str(fmt_combo)) |
| logging.error('burst_len: %d\n', burst_len) |
| failures.append((n, r, f, b)) |
| if _STOP_AT_FIRST_FAILURE: |
| raise AssertionError( |
| f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, ' |
| f'burst: {burst_len}') from e |
| n += 1 |
| |
| num_fail = len(failures) |
| num_success = len(successes) |
| num_total = len(reqs)*len(fmt_combos)*len(burst_lens) |
| num_not_run = num_total - num_success - num_fail |
| |
| logging.debug('Success: %d / %d', num_success, num_total) |
| |
| # assert all combinations successfully capture |
| if num_fail != 0: |
| raise AssertionError(f'Number of fails: {num_fail} / {num_total}') |
| if num_not_run > 0: |
| raise AssertionError(f'Number of combos not run: {num_not_run}') |
| |
| if __name__ == '__main__': |
| test_runner.main() |