blob: fca397bfc68d4a153bea331381c43bbc2792d79e [file] [log] [blame]
# 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()