1# Copyright 2020 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 scene change test.""" 15 16 17import logging 18import unittest 19 20_DARK_SCENE_THRESH = 0.2 21_FPS = 30 # Frames Per Second 22_FRAME_SHIFT_SMALL = 5 # Num of frames to shift if scene or brightness change. 23_FRAME_SHIFT_LARGE = 30 # Num of frames to shift if no change in capture. 24SCENE_CHANGE_FAIL_CODE = -1001 25SCENE_CHANGE_PASS_CODE = 1001 26 27 28def calc_timing_adjustment(converged, scene_change_flag, 29 bright_change_flag, bright_final): 30 """Calculate timing adjustment based on converged frame and flags. 31 32 Args: 33 converged: Boolean on whether 3A converged or not. 34 scene_change_flag: Boolean for if afSceneChanged triggered. 35 bright_change_flag: Boolean for if image brightness changes. 36 bright_final: Float for average value of center patch of final frame. 37 Returns: 38 scene_change_timing_shift: Timing shift in frames. 39 40 Does timing adjustment based on input values from captured frames. 41 Truth table for 3A frame, Change flag, Bright flag, Last frame brightness 42 3, C, B, L 43 1, 1, 1, X --> PASS: 3A settled, scene and brightness change 44 1, 1, 0, X --> FAIL: 3A settled, scene change, but no brightness change 45 1, 0, 1, X --> shift FRAME_SHIFT_SMALL earlier 46 1, 0, 0, 1 --> shift FRAME_SHIFT_LARGE earlier 47 1, 0, 0, 0 --> shift FRAME_SHIFT_LARGE later 48 0, X, 1, X --> shift FRAME_SHIFT_SMALL later 49 0, X, 0, X --> FAIL: Check results of scene2/test_continuous_picture. 50 Note: these values have been found empirically for 4 different phone 51 models and 8 cameras. It is possible they may need to be tweaked as 52 more phone models become available. 53 """ 54 if converged: # 3A converges 55 if scene_change_flag: 56 if bright_change_flag: # scene_change_flag & brightness change --> PASS 57 logging.debug('Scene & brightness change: PASS.') 58 return SCENE_CHANGE_PASS_CODE 59 else: # scene_change_flag & no brightness change --> FAIL 60 scene_change_frame_shift = SCENE_CHANGE_FAIL_CODE 61 logging.error('Scene change, but no brightness change.') 62 else: # No scene change flag: shift timing 63 if bright_change_flag: 64 scene_change_frame_shift = -1 * _FRAME_SHIFT_SMALL 65 logging.debug('No scene change flag, but brightness change.') 66 else: 67 logging.debug('No scene change flag, no brightness change.') 68 if bright_final < _DARK_SCENE_THRESH: 69 scene_change_frame_shift = _FRAME_SHIFT_LARGE 70 logging.debug('Scene dark entire capture.') 71 else: 72 scene_change_frame_shift = -1 * _FRAME_SHIFT_LARGE 73 logging.debug('Scene light entire capture.') 74 else: # 3A does not converge. 75 if bright_change_flag: 76 scene_change_frame_shift = _FRAME_SHIFT_SMALL 77 logging.debug('3A does not converge, but brightness changes.') 78 else: 79 scene_change_frame_shift = SCENE_CHANGE_FAIL_CODE 80 logging.error('3A does not converge, and brightness does not change.') 81 if scene_change_frame_shift >= 0: 82 logging.debug('Shift +%d frames.', scene_change_frame_shift) 83 else: 84 logging.debug('Shift %d frames.', scene_change_frame_shift) 85 return scene_change_frame_shift 86 87 88class ItsSessionUtilsTests(unittest.TestCase): 89 """Unit tests for this module.""" 90 91 def test_calc_timing_adjustment_shift(self): 92 results = {} 93 expected_results = {'1111': SCENE_CHANGE_PASS_CODE, 94 '1110': SCENE_CHANGE_PASS_CODE, 95 '1101': SCENE_CHANGE_FAIL_CODE, 96 '1100': SCENE_CHANGE_FAIL_CODE, 97 '1011': -1*_FRAME_SHIFT_SMALL, 98 '1010': -1*_FRAME_SHIFT_SMALL, 99 '1001': -1*_FRAME_SHIFT_LARGE, 100 '1000': _FRAME_SHIFT_LARGE, 101 '0111': _FRAME_SHIFT_SMALL, 102 '0110': _FRAME_SHIFT_SMALL, 103 '0101': SCENE_CHANGE_FAIL_CODE, 104 '0100': SCENE_CHANGE_FAIL_CODE, 105 '0011': _FRAME_SHIFT_SMALL, 106 '0010': _FRAME_SHIFT_SMALL, 107 '0001': SCENE_CHANGE_FAIL_CODE, 108 '0000': SCENE_CHANGE_FAIL_CODE, 109 } 110 converged_list = [1, 0] 111 scene_change_flag_list = [1, 0] 112 bright_change_flag_list = [1, 0] 113 bright_final_list = [1, 0] 114 for converged in converged_list: 115 for scene_flag in scene_change_flag_list: 116 for bright_flag in bright_change_flag_list: 117 for bright_final in bright_final_list: 118 key = f'{converged}{scene_flag}{bright_flag}{bright_final}' 119 results[key] = calc_timing_adjustment(converged, scene_flag, 120 bright_flag, bright_final) 121 self.assertEqual(results, expected_results) 122 123 124if __name__ == '__main__': 125 unittest.main() 126