1# Copyright 2018 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 15import os.path 16 17import its.caps 18import its.device 19import its.image 20import its.objects 21 22NAME = os.path.basename(__file__).split('.')[0] 23RTOL_EXP_GAIN = 0.97 24TEST_EXP_RANGE = [6E6, 1E9] # ns [6ms, 1s] 25 26 27def main(): 28 """Test that the device will write/read correct exp/gain values.""" 29 30 with its.device.ItsSession() as cam: 31 props = cam.get_camera_properties() 32 props = cam.override_with_hidden_physical_camera_props(props) 33 its.caps.skip_unless(its.caps.manual_sensor(props) and 34 its.caps.per_frame_control(props)) 35 36 valid_formats = ['yuv', 'jpg'] 37 if its.caps.raw16(props): 38 valid_formats.insert(0, 'raw') 39 # grab exp/gain ranges from camera 40 sensor_exp_range = props['android.sensor.info.exposureTimeRange'] 41 sens_range = props['android.sensor.info.sensitivityRange'] 42 print 'sensor e range:', sensor_exp_range 43 print 'sensor s range:', sens_range 44 45 # determine if exposure test range is within sensor reported range 46 assert sensor_exp_range[0] != 0 47 exp_range = [] 48 if sensor_exp_range[0] < TEST_EXP_RANGE[0]: 49 exp_range.append(TEST_EXP_RANGE[0]) 50 else: 51 exp_range.append(sensor_exp_range[0]) 52 if sensor_exp_range[1] > TEST_EXP_RANGE[1]: 53 exp_range.append(TEST_EXP_RANGE[1]) 54 else: 55 exp_range.append(sensor_exp_range[1]) 56 57 data = {} 58 # build requests 59 for fmt in valid_formats: 60 print 'format: %s' % fmt 61 size = its.objects.get_available_output_sizes(fmt, props)[-1] 62 out_surface = {'width': size[0], 'height': size[1], 'format': fmt} 63 if cam._hidden_physical_id: 64 out_surface['physicalCamera'] = cam._hidden_physical_id 65 reqs = [] 66 index_list = [] 67 for exp in exp_range: 68 for sens in sens_range: 69 reqs.append(its.objects.manual_capture_request(sens, exp)) 70 index_list.append((fmt, exp, sens)) 71 print 'exp_write: %d, sens_write: %d' % (exp, sens) 72 73 # take shots 74 caps = cam.do_capture(reqs, out_surface) 75 76 # extract exp/sensitivity data 77 for i, cap in enumerate(caps): 78 e_read = cap['metadata']['android.sensor.exposureTime'] 79 s_read = cap['metadata']['android.sensor.sensitivity'] 80 data[index_list[i]] = (fmt, e_read, s_read) 81 82 # check read/write match across all shots 83 e_failed = [] 84 s_failed = [] 85 for fmt_write in valid_formats: 86 for e_write in exp_range: 87 for s_write in sens_range: 88 fmt_read, e_read, s_read = data[( 89 fmt_write, e_write, s_write)] 90 if (e_write < e_read or 91 e_read/float(e_write) <= RTOL_EXP_GAIN): 92 e_failed.append({'format': fmt_read, 93 'e_write': e_write, 94 'e_read': e_read, 95 's_write': s_write, 96 's_read': s_read}) 97 if (s_write < s_read or 98 s_read/float(s_write) <= RTOL_EXP_GAIN): 99 s_failed.append({'format': fmt_read, 100 'e_write': e_write, 101 'e_read': e_read, 102 's_write': s_write, 103 's_read': s_read}) 104 105 # print results 106 if e_failed: 107 print '\nFAILs for exposure time' 108 for fail in e_failed: 109 print ' format: %s, e_write: %d, e_read: %d, RTOL: %.2f, ' % ( 110 fail['format'], fail['e_write'], fail['e_read'], 111 RTOL_EXP_GAIN), 112 print 's_write: %d, s_read: %d, RTOL: %.2f' % ( 113 fail['s_write'], fail['s_read'], RTOL_EXP_GAIN) 114 if s_failed: 115 print 'FAILs for sensitivity(ISO)' 116 for fail in s_failed: 117 print ' format: %s, s_write: %d, s_read: %d, RTOL: %.2f, ' % ( 118 fail['format'], fail['s_write'], fail['s_read'], 119 RTOL_EXP_GAIN), 120 print 'e_write: %d, e_read: %d, RTOL: %.2f' % ( 121 fail['e_write'], fail['e_read'], RTOL_EXP_GAIN) 122 123 # assert PASS/FAIL 124 assert not e_failed+s_failed 125 126 127if __name__ == '__main__': 128 main() 129