| # 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 |
| import sys |
| |
| from mobly import test_runner |
| |
| import its_base_test |
| import camera_properties_utils |
| import capture_request_utils |
| import image_processing_utils |
| import its_session_utils |
| import target_exposure_utils |
| |
| |
| 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): |
| logging.debug('Starting %s', NAME) |
| 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) |
| |
| # Check skip conditions |
| camera_properties_utils.skip_unless( |
| camera_properties_utils.compute_target_exposure(props) and |
| camera_properties_utils.raw16(props)) |
| |
| successes = [] |
| failures = [] |
| debug = self.debug_mode |
| |
| # Two different requests: auto, and manual. |
| e, s = target_exposure_utils.get_target_exposure_combos( |
| self.log_path, cam)['midExposureTime'] |
| req_aut = capture_request_utils.auto_capture_request() |
| req_man = capture_request_utils.manual_capture_request(s, e) |
| reqs = [req_aut, # R0 |
| req_man] # R1 |
| |
| # 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_raw_full = {'format': 'raw'} |
| fmt_combos = [ |
| [fmt_yuv_prev], # F0 |
| [fmt_yuv_full], # F1 |
| [fmt_jpg_prev], # F2 |
| [fmt_jpg_full], # F3 |
| [fmt_raw_full], # F4 |
| [fmt_yuv_prev, fmt_jpg_prev], # F5 |
| [fmt_yuv_prev, fmt_jpg_full], # F6 |
| [fmt_yuv_prev, fmt_raw_full], # F7 |
| [fmt_yuv_prev, fmt_jpg_prev, fmt_raw_full], # F8 |
| [fmt_yuv_prev, fmt_jpg_full, fmt_raw_full] # F9 |
| ] |
| |
| 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.append([fmt_y8_prev]) |
| fmt_combos.append([fmt_y8_full]) |
| |
| # Two different burst lengths: single frame, and 3 frames. |
| burst_lens = [ |
| 1, # B0 |
| 3 # B1 |
| ] |
| |
| # There are 2xlen(fmt_combos)x2 different combinations. |
| # Run through them all. |
| n = 0 |
| for r, req in enumerate(reqs): |
| for f, fmt_combo in enumerate(fmt_combos): |
| for b, burst_len in enumerate(burst_lens): |
| try: |
| caps = cam.do_capture([req] * burst_len, fmt_combo) |
| successes.append((n, r, f, b)) |
| logging.debug('==> Success[%02d]: R%d F%d B%d', n, r, f, b) |
| |
| # Dump the captures out to jpegs in debug mode. |
| if debug: |
| if not isinstance(caps, list): |
| caps = [caps] |
| elif isinstance(caps[0], list): |
| caps = sum(caps, []) |
| for c, cap in enumerate(caps): |
| img = image_processing_utils.convert_capture_to_rgb_image( |
| cap, props=props) |
| img_name = '%s_n%02d_r%d_f%d_b%d_c%d.jpg' % (os.path.join( |
| self.log_path, NAME), n, r, f, b, c) |
| image_processing_utils.write_image(img, img_name) |
| # pylint: disable=broad-except |
| except Exception as e: |
| logging.error(e) |
| logging.error('==> Failure[%02d]: R%d F%d B%d', n, r, f, b) |
| failures.append((n, r, f, b)) |
| if STOP_AT_FIRST_FAILURE: |
| sys.exit(1) |
| 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('Failures (%d / %d):', num_fail, num_total) |
| for (n, r, f, b) in failures: |
| logging.debug(' %02d: R%d F%d B%d', n, r, f, b) |
| logging.debug('Successes (%d / %d)', num_success, num_total) |
| for (n, r, f, b) in successes: |
| logging.debug(' %02d: R%d F%d B%d', n, r, f, b) |
| if num_not_run > 0: |
| logging.debug('Number of tests not run: %d / %d', |
| num_not_run, num_total) |
| |
| # The test passes if all the combinations successfully capture. |
| assert num_fail == 0 |
| assert num_success == num_total |
| |
| if __name__ == '__main__': |
| test_runner.main() |