• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15import its.image
16import its.device
17import its.objects
18import os.path
19import numpy
20import pylab
21import matplotlib
22import matplotlib.pyplot
23
24def main():
25    """Test 3A lock + YUV burst (using auto settings).
26
27    This is a test that is designed to pass even on limited devices that
28    don't have MANUAL_SENSOR or PER_FRAME_CONTROLS. (They must be able to
29    capture bursts with full res @ full frame rate to pass, however).
30    """
31    NAME = os.path.basename(__file__).split(".")[0]
32
33    BURST_LEN = 10
34    SPREAD_THRESH = 0.005
35    FPS_MAX_DIFF = 2.0
36
37    with its.device.ItsSession() as cam:
38        props = cam.get_camera_properties()
39
40        # Converge 3A prior to capture.
41        cam.do_3a(do_af=False, lock_ae=True, lock_awb=True)
42
43        # After 3A has converged, lock AE+AWB for the duration of the test.
44        req = its.objects.auto_capture_request()
45        req["android.control.awbLock"] = True
46        req["android.control.aeLock"] = True
47
48        # Capture bursts of YUV shots.
49        # Get the mean values of a center patch for each.
50        r_means = []
51        g_means = []
52        b_means = []
53        caps = cam.do_capture([req]*BURST_LEN)
54        for i,cap in enumerate(caps):
55            img = its.image.convert_capture_to_rgb_image(cap)
56            its.image.write_image(img, "%s_frame%d.jpg"%(NAME,i))
57            tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
58            means = its.image.compute_image_means(tile)
59            r_means.append(means[0])
60            g_means.append(means[1])
61            b_means.append(means[2])
62
63        # Pass/fail based on center patch similarity.
64        for means in [r_means, g_means, b_means]:
65            spread = max(means) - min(means)
66            print "Patch mean spread", spread
67            assert(spread < SPREAD_THRESH)
68
69        # Also ensure that the burst was at full frame rate.
70        fmt_code = 0x23
71        configs = props['android.scaler.streamConfigurationMap']\
72                       ['availableStreamConfigurations']
73        min_duration = None
74        for cfg in configs:
75            if cfg['format'] == fmt_code and cfg['input'] == False and \
76                    cfg['width'] == caps[0]["width"] and \
77                    cfg['height'] == caps[0]["height"]:
78                min_duration = cfg["minFrameDuration"]
79        assert(min_duration is not None)
80        tstamps = [c['metadata']['android.sensor.timestamp'] for c in caps]
81        deltas = [tstamps[i]-tstamps[i-1] for i in range(1,len(tstamps))]
82        actual_fps = 1.0 / (max(deltas) / 1000000000.0)
83        max_fps = 1.0 / (min_duration / 1000000000.0)
84        print "FPS measured %.1f, max advertized %.1f" %(actual_fps, max_fps)
85        assert(max_fps - FPS_MAX_DIFF <= actual_fps <= max_fps)
86
87if __name__ == '__main__':
88    main()
89
90