1 # Copyright 2014 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 15 import math 16 17 import its.caps 18 import its.device 19 import its.objects 20 import its.target 21 22 23 def main(): 24 """Test the validity of some metadata entries. 25 26 Looks at capture results and at the camera characteristics objects. 27 """ 28 global md, props, failed 29 30 with its.device.ItsSession() as cam: 31 # Arbitrary capture request exposure values; image content is not 32 # important for this test, only the metadata. 33 props = cam.get_camera_properties() 34 auto_req = its.objects.auto_capture_request() 35 cap = cam.do_capture(auto_req) 36 md = cap["metadata"] 37 38 print "Hardware level" 39 print " Legacy:", its.caps.legacy(props) 40 print " Limited:", its.caps.limited(props) 41 print " Full or better:", its.caps.full_or_better(props) 42 print "Capabilities" 43 print " Manual sensor:", its.caps.manual_sensor(props) 44 print " Manual post-proc:", its.caps.manual_post_proc(props) 45 print " Raw:", its.caps.raw(props) 46 print " Sensor fusion:", its.caps.sensor_fusion(props) 47 48 # Test: hardware level should be a valid value. 49 check('props.has_key("android.info.supportedHardwareLevel")') 50 check('props["android.info.supportedHardwareLevel"] is not None') 51 check('props["android.info.supportedHardwareLevel"] in [0,1,2,3]') 52 full = getval('props["android.info.supportedHardwareLevel"]') == 1 53 manual_sensor = its.caps.manual_sensor(props) 54 55 # Test: rollingShutterSkew, and frameDuration tags must all be present, 56 # and rollingShutterSkew must be greater than zero and smaller than all 57 # of the possible frame durations. 58 if manual_sensor: 59 check('md.has_key("android.sensor.frameDuration")') 60 check('md["android.sensor.frameDuration"] is not None') 61 check('md.has_key("android.sensor.rollingShutterSkew")') 62 check('md["android.sensor.rollingShutterSkew"] is not None') 63 if manual_sensor: 64 check('md["android.sensor.frameDuration"] > ' 65 'md["android.sensor.rollingShutterSkew"] > 0') 66 67 # Test: timestampSource must be a valid value. 68 check('props.has_key("android.sensor.info.timestampSource")') 69 check('props["android.sensor.info.timestampSource"] is not None') 70 check('props["android.sensor.info.timestampSource"] in [0,1]') 71 72 # Test: croppingType must be a valid value, and for full devices, it 73 # must be FREEFORM=1. 74 check('props.has_key("android.scaler.croppingType")') 75 check('props["android.scaler.croppingType"] is not None') 76 check('props["android.scaler.croppingType"] in [0,1]') 77 78 assert(not failed) 79 80 if not its.caps.legacy(props): 81 # Test: pixel_pitch, FOV, and hyperfocal distance are reasonable 82 fmts = props["android.scaler.streamConfigurationMap"]["availableStreamConfigurations"] 83 fmts = sorted(fmts, key=lambda k: k["width"]*k["height"], reverse=True) 84 sensor_size = props["android.sensor.info.physicalSize"] 85 pixel_pitch_h = (sensor_size["height"] / fmts[0]["height"] * 1E3) 86 pixel_pitch_w = (sensor_size["width"] / fmts[0]["width"] * 1E3) 87 print "Assert pixel_pitch WxH: %.2f um, %.2f um" % (pixel_pitch_w, 88 pixel_pitch_h) 89 assert 1.0 <= pixel_pitch_w <= 10 90 assert 1.0 <= pixel_pitch_h <= 10 91 assert 0.333 <= pixel_pitch_w/pixel_pitch_h <= 3.0 92 93 diag = math.sqrt(sensor_size["height"] ** 2 + 94 sensor_size["width"] ** 2) 95 fl = md["android.lens.focalLength"] 96 fov = 2 * math.degrees(math.atan(diag / (2 * fl))) 97 print "Assert field of view: %.1f degrees" % fov 98 assert 30 <= fov <= 130 99 100 if its.caps.lens_approx_calibrated(props): 101 diopter_hyperfocal = props["android.lens.info.hyperfocalDistance"] 102 if diopter_hyperfocal != 0.0: 103 hyperfocal = 1.0 / diopter_hyperfocal 104 print "Assert hyperfocal distance: %.2f m" % hyperfocal 105 assert 0.02 <= hyperfocal 106 107 108 def getval(expr, default=None): 109 try: 110 return eval(expr) 111 except: 112 return default 113 114 failed = False 115 116 117 def check(expr): 118 global md, props, failed 119 try: 120 if eval(expr): 121 print "Passed>", expr 122 else: 123 print "Failed>>", expr 124 failed = True 125 except: 126 print "Failed>>", expr 127 failed = True 128 129 if __name__ == '__main__': 130 main() 131 132