| # Copyright 2020 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. |
| """Utility functions for scene change test.""" |
| |
| |
| import logging |
| import unittest |
| |
| _DARK_SCENE_THRESH = 0.2 |
| _FPS = 30 # Frames Per Second |
| _FRAME_SHIFT_SMALL = 5 # Num of frames to shift if scene or brightness change. |
| _FRAME_SHIFT_LARGE = 30 # Num of frames to shift if no change in capture. |
| SCENE_CHANGE_FAIL_CODE = -1001 |
| SCENE_CHANGE_PASS_CODE = 1001 |
| |
| |
| def calc_timing_adjustment(converged, scene_change_flag, |
| bright_change_flag, bright_final): |
| """Calculate timing adjustment based on converged frame and flags. |
| |
| Args: |
| converged: Boolean on whether 3A converged or not. |
| scene_change_flag: Boolean for if afSceneChanged triggered. |
| bright_change_flag: Boolean for if image brightness changes. |
| bright_final: Float for average value of center patch of final frame. |
| Returns: |
| scene_change_timing_shift: Timing shift in frames. |
| |
| Does timing adjustment based on input values from captured frames. |
| Truth table for 3A frame, Change flag, Bright flag, Last frame brightness |
| 3, C, B, L |
| 1, 1, 1, X --> PASS: 3A settled, scene and brightness change |
| 1, 1, 0, X --> FAIL: 3A settled, scene change, but no brightness change |
| 1, 0, 1, X --> shift FRAME_SHIFT_SMALL earlier |
| 1, 0, 0, 1 --> shift FRAME_SHIFT_LARGE earlier |
| 1, 0, 0, 0 --> shift FRAME_SHIFT_LARGE later |
| 0, X, 1, X --> shift FRAME_SHIFT_SMALL later |
| 0, X, 0, X --> FAIL: Check results of scene2/test_continuous_picture. |
| Note: these values have been found empirically for 4 different phone |
| models and 8 cameras. It is possible they may need to be tweaked as |
| more phone models become available. |
| """ |
| if converged: # 3A converges |
| if scene_change_flag: |
| if bright_change_flag: # scene_change_flag & brightness change --> PASS |
| logging.debug('Scene & brightness change: PASS.') |
| return SCENE_CHANGE_PASS_CODE |
| else: # scene_change_flag & no brightness change --> FAIL |
| scene_change_frame_shift = SCENE_CHANGE_FAIL_CODE |
| logging.error('Scene change, but no brightness change.') |
| else: # No scene change flag: shift timing |
| if bright_change_flag: |
| scene_change_frame_shift = -1 * _FRAME_SHIFT_SMALL |
| logging.debug('No scene change flag, but brightness change.') |
| else: |
| logging.debug('No scene change flag, no brightness change.') |
| if bright_final < _DARK_SCENE_THRESH: |
| scene_change_frame_shift = _FRAME_SHIFT_LARGE |
| logging.debug('Scene dark entire capture.') |
| else: |
| scene_change_frame_shift = -1 * _FRAME_SHIFT_LARGE |
| logging.debug('Scene light entire capture.') |
| else: # 3A does not converge. |
| if bright_change_flag: |
| scene_change_frame_shift = _FRAME_SHIFT_SMALL |
| logging.debug('3A does not converge, but brightness changes.') |
| else: |
| scene_change_frame_shift = SCENE_CHANGE_FAIL_CODE |
| logging.error('3A does not converge, and brightness does not change.') |
| if scene_change_frame_shift >= 0: |
| logging.debug('Shift +%d frames.', scene_change_frame_shift) |
| else: |
| logging.debug('Shift %d frames.', scene_change_frame_shift) |
| return scene_change_frame_shift |
| |
| |
| class ItsSessionUtilsTests(unittest.TestCase): |
| """Unit tests for this module.""" |
| |
| def test_calc_timing_adjustment_shift(self): |
| results = {} |
| expected_results = {'1111': SCENE_CHANGE_PASS_CODE, |
| '1110': SCENE_CHANGE_PASS_CODE, |
| '1101': SCENE_CHANGE_FAIL_CODE, |
| '1100': SCENE_CHANGE_FAIL_CODE, |
| '1011': -1*_FRAME_SHIFT_SMALL, |
| '1010': -1*_FRAME_SHIFT_SMALL, |
| '1001': -1*_FRAME_SHIFT_LARGE, |
| '1000': _FRAME_SHIFT_LARGE, |
| '0111': _FRAME_SHIFT_SMALL, |
| '0110': _FRAME_SHIFT_SMALL, |
| '0101': SCENE_CHANGE_FAIL_CODE, |
| '0100': SCENE_CHANGE_FAIL_CODE, |
| '0011': _FRAME_SHIFT_SMALL, |
| '0010': _FRAME_SHIFT_SMALL, |
| '0001': SCENE_CHANGE_FAIL_CODE, |
| '0000': SCENE_CHANGE_FAIL_CODE, |
| } |
| converged_list = [1, 0] |
| scene_change_flag_list = [1, 0] |
| bright_change_flag_list = [1, 0] |
| bright_final_list = [1, 0] |
| for converged in converged_list: |
| for scene_flag in scene_change_flag_list: |
| for bright_flag in bright_change_flag_list: |
| for bright_final in bright_final_list: |
| key = f'{converged}{scene_flag}{bright_flag}{bright_final}' |
| results[key] = calc_timing_adjustment(converged, scene_flag, |
| bright_flag, bright_final) |
| self.assertEqual(results, expected_results) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |