19c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin/*
29c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * Copyright (C) 2014 The Android Open Source Project
39c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
49c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
59c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * you may not use this file except in compliance with the License.
69c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * You may obtain a copy of the License at
79c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
89c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
99c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * Unless required by applicable law or agreed to in writing, software
119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * See the License for the specific language governing permissions and
149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * limitations under the License.
159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin */
169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinpackage android.hardware.camera2.params;
189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.graphics.ImageFormat;
209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.graphics.PixelFormat;
219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.CameraCharacteristics;
229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.CameraDevice;
239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.CaptureRequest;
249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.hardware.camera2.utils.HashCodeHelpers;
25fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvalaimport android.hardware.camera2.legacy.LegacyCameraDevice;
26fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvalaimport android.hardware.camera2.legacy.LegacyMetadataMapper;
27fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvalaimport android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.view.Surface;
299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.util.Log;
3012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yehimport android.util.Range;
319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport android.util.Size;
329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport java.util.Arrays;
349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport java.util.HashMap;
359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport java.util.Objects;
36b0056642cab30647d1f72190d864622bf4728ea0Yin-Chia Yehimport java.util.Set;
379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinimport static com.android.internal.util.Preconditions.*;
399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin/**
419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * Immutable class to store the available stream
42b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP configurations} to set up
43b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * {@link android.view.Surface Surfaces} for creating a
44b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * {@link android.hardware.camera2.CameraCaptureSession capture session} with
45b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * {@link android.hardware.camera2.CameraDevice#createCaptureSession}.
469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * <!-- TODO: link to input stream configuration -->
479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * for that format) that are supported by a camera device.</p>
509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * <p>This also contains the minimum frame durations and stall durations for each format/size
529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * combination that can be used to calculate effective frame rate when submitting multiple captures.
539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * </p>
549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * <p>An instance of this object is available from {@link CameraCharacteristics} using
569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP} key and the
579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * {@link CameraCharacteristics#get} method.</p>
589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * <pre><code>{@code
609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * StreamConfigurationMap configs = characteristics.get(
629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *         CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * }</code></pre>
649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin *
659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
66b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala * @see CameraDevice#createCaptureSession
679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin */
689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkinpublic final class StreamConfigurationMap {
699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final String TAG = "StreamConfigurationMap";
713e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk
723e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk    /**
739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Create a new {@link StreamConfigurationMap}.
749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The array parameters ownership is passed to this object after creation; do not
769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * write to them after this constructor is invoked.</p>
779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param configurations a non-{@code null} array of {@link StreamConfiguration}
799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration}
809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration}
8112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if
8212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *        camera device does not support high speed video recording
839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations
8512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *         were {@code null} or any subelements were {@code null}
869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @hide
889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public StreamConfigurationMap(
909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            StreamConfiguration[] configurations,
919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            StreamConfigurationDuration[] minFrameDurations,
9212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            StreamConfigurationDuration[] stallDurations,
9312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            HighSpeedVideoConfiguration[] highSpeedVideoConfigurations) {
949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations");
979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations");
9812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        if (highSpeedVideoConfigurations == null) {
9912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0];
10012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        } else {
10112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            mHighSpeedVideoConfigurations = checkArrayElementsNotNull(
10212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    highSpeedVideoConfigurations, "highSpeedVideoConfigurations");
10312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
1049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // For each format, track how many sizes there are available to configure
1069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (StreamConfiguration config : configurations) {
1079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            HashMap<Integer, Integer> map = config.isOutput() ? mOutputFormats : mInputFormats;
1089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            Integer count = map.get(config.getFormat());
1109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (count == null) {
1129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                count = 0;
1139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
1149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            count = count + 1;
1159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            map.put(config.getFormat(), count);
1179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
1189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
1209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new AssertionError(
1219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    "At least one stream configuration for IMPLEMENTATION_DEFINED must exist");
1229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
12312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
12412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        // For each Size/FPS range, track how many FPS range/Size there are available
12512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
12612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            Size size = config.getSize();
12712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            Range<Integer> fpsRange = config.getFpsRange();
12812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            Integer fpsRangeCount = mHighSpeedVideoSizeMap.get(size);
12912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            if (fpsRangeCount == null) {
13012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                fpsRangeCount = 0;
13112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            }
13212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            mHighSpeedVideoSizeMap.put(size, fpsRangeCount + 1);
13312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            Integer sizeCount = mHighSpeedVideoFpsRangeMap.get(fpsRange);
13412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            if (sizeCount == null) {
13512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                sizeCount = 0;
13612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            }
13712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            mHighSpeedVideoFpsRangeMap.put(fpsRange, sizeCount + 1);
13812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
1399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
1409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
1429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the image {@code format} output formats in this stream configuration.
1439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
1459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * or in {@link PixelFormat} (and there is no possibility of collision).</p>
1469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Formats listed in this array are guaranteed to return true if queried with
148f3621f3a5c5fd16ebedd3ce1ae1b0100d0f64152Eino-Ville Talvala     * {@link #isOutputSupportedFor(int)}.</p>
1499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return an array of integer format
1519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
1539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
1549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
1559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public final int[] getOutputFormats() {
1569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getPublicFormats(/*output*/true);
1579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
1589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
1609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the image {@code format} input formats in this stream configuration.
1619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
1639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * or in {@link PixelFormat} (and there is no possibility of collision).</p>
1649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return an array of integer format
1669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
1689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
1699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @hide
1719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
1729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public final int[] getInputFormats() {
1739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getPublicFormats(/*output*/false);
1749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
1759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
1779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the supported input sizes for this input format.
1789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The format must have come from {@link #getInputFormats}; otherwise
1809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code null} is returned.</p>
1819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format a format from {@link #getInputFormats}
1839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return a non-empty array of sizes, or {@code null} if the format was not available.
1849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @hide
1869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
1879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public Size[] getInputSizes(final int format) {
1889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getPublicFormatSizes(format, /*output*/false);
1899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
1909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
1919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
192b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * Determine whether or not output surfaces with a particular user-defined format can be passed
193b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * {@link CameraDevice#createCaptureSession createCaptureSession}.
1949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This method determines that the output {@code format} is supported by the camera device;
1969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * each output {@code surface} target may or may not itself support that {@code format}.
1979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Refer to the class which provides the surface for additional documentation.</p>
1989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
1999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Formats for which this returns {@code true} are guaranteed to exist in the result
2009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * returned by {@link #getOutputSizes}.</p>
2019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
2039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return
2049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          {@code true} iff using a {@code surface} with this {@code format} will be
205b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     *          supported with {@link CameraDevice#createCaptureSession}
2069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException
2089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          if the image format was not a defined named constant
2099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          from either {@link ImageFormat} or {@link PixelFormat}
2109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
2129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
213b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * @see CameraDevice#createCaptureSession
2149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
2159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public boolean isOutputSupportedFor(int format) {
2169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkArgumentFormat(format);
2179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
2189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        format = imageFormatToInternal(format);
2199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getFormatsMap(/*output*/true).containsKey(format);
2209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
2219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
2229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
2239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Determine whether or not output streams can be configured with a particular class
2249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * as a consumer.
2259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The following list is generally usable for outputs:
2279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
2289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.media.ImageReader} -
2299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for image processing or streaming to external resources (such as a file or
2309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * network)
2319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.media.MediaRecorder} -
2329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for recording video (simple to use)
2339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.media.MediaCodec} -
2349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for recording video (more complicated to use, with more flexibility)
2359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.renderscript.Allocation} -
2369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for image processing with {@link android.renderscript RenderScript}
2379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.view.SurfaceHolder} -
2389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for low-power camera preview with {@link android.view.SurfaceView}
2399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link android.graphics.SurfaceTexture} -
2409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Recommended for OpenGL-accelerated preview processing or compositing with
2419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link android.view.TextureView}
2429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
2439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
2449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
2469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * provide a producer endpoint that is suitable to be used with
247b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * {@link CameraDevice#createCaptureSession}.</p>
2489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Since not all of the above classes support output of all format and size combinations,
2509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
2519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param klass a non-{@code null} {@link Class} object reference
2539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return {@code true} if this class is supported as an output, {@code false} otherwise
2549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code klass} was {@code null}
2569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
257b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * @see CameraDevice#createCaptureSession
2589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #isOutputSupportedFor(Surface)
2599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
2609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public static <T> boolean isOutputSupportedFor(Class<T> klass) {
2619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkNotNull(klass, "klass must not be null");
2629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
2639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (klass == android.media.ImageReader.class) {
2649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else if (klass == android.media.MediaRecorder.class) {
2669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else if (klass == android.media.MediaCodec.class) {
2689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else if (klass == android.renderscript.Allocation.class) {
2709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else if (klass == android.view.SurfaceHolder.class) {
2729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } else if (klass == android.graphics.SurfaceTexture.class) {
2749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
2759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
2769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
2779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return false;
2789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
2799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
2809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
281b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * Determine whether or not the {@code surface} in its current state is suitable to be included
282b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * in a {@link CameraDevice#createCaptureSession capture session} as an output.
2839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
2859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * of that {@code surface} are compatible. Some classes that provide the {@code surface} are
2869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * compatible with the {@link CameraDevice} in general
2879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * (see {@link #isOutputSupportedFor(Class)}, but it is the caller's responsibility to put the
2889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code surface} into a state that will be compatible with the {@link CameraDevice}.</p>
2899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
2909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Reasons for a {@code surface} being specifically incompatible might be:
2919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
2929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>Using a format that's not listed by {@link #getOutputFormats}
2939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>Using a format/size combination that's not listed by {@link #getOutputSizes}
2949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>The {@code surface} itself is not in a state where it can service a new producer.</p>
2959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </li>
2969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
2979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
298fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * <p>Surfaces from flexible sources will return true even if the exact size of the Surface does
299fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * not match a camera-supported size, as long as the format (or class) is supported and the
300fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * camera device supports a size that is equal to or less than 1080p in that format. If such as
301fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * Surface is used to create a capture session, it will have its size rounded to the nearest
302fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * supported size, below or equal to 1080p. Flexible sources include SurfaceView, SurfaceTexture,
303fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * and ImageReader.</p>
304fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     *
305fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * <p>This is not an exhaustive list; see the particular class's documentation for further
3069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * possible reasons of incompatibility.</p>
3079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param surface a non-{@code null} {@link Surface} object reference
3099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return {@code true} if this is supported, {@code false} otherwise
3109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code surface} was {@code null}
312fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala     * @throws IllegalArgumentException if the Surface endpoint is no longer valid
3139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
314b67a3b36fd569e63c1b8ca6b2701c34c7a3927c1Eino-Ville Talvala     * @see CameraDevice#createCaptureSession
3159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #isOutputSupportedFor(Class)
3169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
3179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public boolean isOutputSupportedFor(Surface surface) {
3189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkNotNull(surface, "surface must not be null");
3199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
320fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        Size surfaceSize;
321fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        int surfaceFormat = -1;
322fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        try {
323fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            surfaceSize = LegacyCameraDevice.getSurfaceSize(surface);
324fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            surfaceFormat = LegacyCameraDevice.detectSurfaceType(surface);
325fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        } catch(BufferQueueAbandonedException e) {
326fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            throw new IllegalArgumentException("Abandoned surface", e);
327fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        }
328fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala
329fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        // See if consumer is flexible.
330fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        boolean isFlexible = LegacyCameraDevice.isFlexibleConsumer(surface);
3319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
332fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482
333fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
334fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                        surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
335fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            surfaceFormat = LegacyMetadataMapper.HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
336fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        }
337fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala
338fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        for (StreamConfiguration config : mConfigurations) {
339fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            if (config.getFormat() == surfaceFormat && config.isOutput()) {
340fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                // Mathing format, either need exact size match, or a flexible consumer
341fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                // and a size no bigger than MAX_DIMEN_FOR_ROUNDING
342fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                if (config.getSize().equals(surfaceSize)) {
343fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                    return true;
344fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                } else if (isFlexible &&
345fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                        (config.getSize().getWidth() <= LegacyCameraDevice.MAX_DIMEN_FOR_ROUNDING)) {
346fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                    return true;
347fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                }
348fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            }
349fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        }
350fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        return false;
3519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
3529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
3549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get a list of sizes compatible with {@code klass} to use as an output.
3559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Since some of the supported classes may support additional formats beyond
3579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * an opaque/implementation-defined (under-the-hood) format; this function only returns
3589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * sizes for the implementation-defined format.</p>
3599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Some classes such as {@link android.media.ImageReader} may only support user-defined
3619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * formats; in particular {@link #isOutputSupportedFor(Class)} will return {@code true} for
3629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * that class and this method will return an empty array (but not {@code null}).</p>
3639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>If a well-defined format such as {@code NV21} is required, use
3659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(int)} instead.</p>
3669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The {@code klass} should be a supported output, that querying
3689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code #isOutputSupportedFor(Class)} should return {@code true}.</p>
3699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param klass
3719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          a non-{@code null} {@link Class} object reference
3729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return
3739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          an array of supported sizes for implementation-defined formats,
3749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          or {@code null} iff the {@code klass} is not a supported output
3759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code klass} was {@code null}
3779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #isOutputSupportedFor(Class)
3799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
3809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public <T> Size[] getOutputSizes(Class<T> klass) {
381517b74533afe53c740400bff3b85806884286344Igor Murashkin        // Image reader is "supported", but never for implementation-defined formats; return empty
382517b74533afe53c740400bff3b85806884286344Igor Murashkin        if (android.media.ImageReader.class.isAssignableFrom(klass)) {
383517b74533afe53c740400bff3b85806884286344Igor Murashkin            return new Size[0];
384517b74533afe53c740400bff3b85806884286344Igor Murashkin        }
385517b74533afe53c740400bff3b85806884286344Igor Murashkin
3869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (isOutputSupportedFor(klass) == false) {
3879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return null;
3889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
3899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /*output*/true);
3919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
3929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
3939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
3949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get a list of sizes compatible with the requested image {@code format}.
3959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The {@code format} should be a supported format (one of the formats returned by
3979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputFormats}).</p>
3989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
3999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
4009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return
4019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          an array of supported sizes,
4029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          or {@code null} if the {@code format} is not a supported output
4039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
4049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
4059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
4069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #getOutputFormats
4079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
4089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public Size[] getOutputSizes(int format) {
4099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getPublicFormatSizes(format, /*output*/true);
4109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
4119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
4129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
41312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Get a list of supported high speed video recording sizes.
41412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
41512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> When HIGH_SPEED_VIDEO is supported in
41612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
41712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * method will list the supported high speed video size configurations. All the sizes listed
41812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * will be a subset of the sizes reported by {@link #getOutputSizes} for processed non-stalling
41912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * formats (typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12)</p>
42012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
42112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> To enable high speed video recording, application must set
42212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
42312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
42412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * requests and select the video size from this method and
42512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
42612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link #getHighSpeedVideoFpsRangesFor} to configure the recording and preview streams and
42712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * setup the recording requests. For example, if the application intends to do high speed
42812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * recording, it can select the maximum size reported by this method to configure output
42912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * streams. Note that for the use case of multiple output streams, application must select one
43012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * unique size from this method to use. Otherwise a request error might occur. Once the size is
43112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * selected, application can get the supported FPS ranges by
43212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link #getHighSpeedVideoFpsRangesFor}, and use these FPS ranges to setup the recording
43312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * requests.</p>
43412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
43512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @return
43612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          an array of supported high speed video recording sizes
43712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
43812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @see #getHighSpeedVideoFpsRangesFor(Size)
43912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     */
44012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    public Size[] getHighSpeedVideoSizes() {
441b0056642cab30647d1f72190d864622bf4728ea0Yin-Chia Yeh        Set<Size> keySet = mHighSpeedVideoSizeMap.keySet();
442b0056642cab30647d1f72190d864622bf4728ea0Yin-Chia Yeh        return keySet.toArray(new Size[keySet.size()]);
44312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
44412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
44512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /**
44612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size.
44712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
44812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> See {@link #getHighSpeedVideoSizes} for how to enable high speed recording.</p>
44912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
45012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> For normal video recording use case, where some application will NOT set
45112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
45212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
45312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
45412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * this method must not be used to setup capture requests, or it will cause request error.</p>
45512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
45612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()}
45712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @return
45812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          An array of FPS range to use with
45912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE TARGET_FPS_RANGE} when using
46012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
46112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          mode.
46212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          The upper bound of returned ranges is guaranteed to be larger or equal to 60.
46312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
46412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @throws IllegalArgumentException if input size does not exist in the return value of
46512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *         getHighSpeedVideoSizes
46612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @see #getHighSpeedVideoSizes()
46712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     */
46812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    public Range<Integer>[] getHighSpeedVideoFpsRangesFor(Size size) {
46912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        Integer fpsRangeCount = mHighSpeedVideoSizeMap.get(size);
47012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        if (fpsRangeCount == null || fpsRangeCount == 0) {
47112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            throw new IllegalArgumentException(String.format(
47212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    "Size %s does not support high speed video recording", size));
47312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
47412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
47512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        @SuppressWarnings("unchecked")
47612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        Range<Integer>[] fpsRanges = new Range[fpsRangeCount];
47712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        int i = 0;
47812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
47912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            if (size.equals(config.getSize())) {
48012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                fpsRanges[i++] = config.getFpsRange();
48112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            }
48212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
48312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        return fpsRanges;
48412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
48512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
48612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /**
48712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Get a list of supported high speed video recording FPS ranges.
48812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
48912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> When HIGH_SPEED_VIDEO is supported in
49012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
49112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * method will list the supported high speed video FPS range configurations. Application can
49212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * then use {@link #getHighSpeedVideoSizesFor} to query available sizes for one of returned
49312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * FPS range.</p>
49412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
49512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> To enable high speed video recording, application must set
49612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
49712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
49812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * requests and select the video size from {@link #getHighSpeedVideoSizesFor} and
49912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
50012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * this method to configure the recording and preview streams and setup the recording requests.
50112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * For example, if the application intends to do high speed recording, it can select one FPS
50212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * range reported by this method, query the video sizes corresponding to this FPS range  by
50312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link #getHighSpeedVideoSizesFor} and select one of reported sizes to configure output
50412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * streams. Note that for the use case of multiple output streams, application must select one
50512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * unique size from {@link #getHighSpeedVideoSizesFor}, and use it for all output streams.
50612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Otherwise a request error might occur when attempting to enable
50712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}.
50812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Once the stream is configured, application can set the FPS range in the recording requests.
50912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * </p>
51012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
51112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @return
51212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          an array of supported high speed video recording FPS ranges
51312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          The upper bound of returned ranges is guaranteed to be larger or equal to 60.
51412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
51512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @see #getHighSpeedVideoSizesFor
51612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     */
51712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    @SuppressWarnings("unchecked")
51812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    public Range<Integer>[] getHighSpeedVideoFpsRanges() {
519b0056642cab30647d1f72190d864622bf4728ea0Yin-Chia Yeh        Set<Range<Integer>> keySet = mHighSpeedVideoFpsRangeMap.keySet();
520b0056642cab30647d1f72190d864622bf4728ea0Yin-Chia Yeh        return keySet.toArray(new Range[keySet.size()]);
52112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
52212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
52312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /**
52412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * Get the supported video sizes for input FPS range.
52512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
52612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> See {@link #getHighSpeedVideoFpsRanges} for how to enable high speed recording.</p>
52712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
52812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * <p> For normal video recording use case, where the application will NOT set
52912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
53012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
53112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
53212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * this method must not be used to setup capture requests, or it will cause request error.</p>
53312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
53412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()}
53512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @return
53612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          An array of video sizes to configure output stream when using
53712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
53812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *          mode.
53912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *
54012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @throws IllegalArgumentException if input FPS range does not exist in the return value of
54112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     *         getHighSpeedVideoFpsRanges
54212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     * @see #getHighSpeedVideoFpsRanges()
54312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh     */
54412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    public Size[] getHighSpeedVideoSizesFor(Range<Integer> fpsRange) {
54512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        Integer sizeCount = mHighSpeedVideoFpsRangeMap.get(fpsRange);
54612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        if (sizeCount == null || sizeCount == 0) {
54712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            throw new IllegalArgumentException(String.format(
54812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    "FpsRange %s does not support high speed video recording", fpsRange));
54912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
55012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
55112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        Size[] sizes = new Size[sizeCount];
55212da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        int i = 0;
55312da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        for (HighSpeedVideoConfiguration config : mHighSpeedVideoConfigurations) {
55412da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            if (fpsRange.equals(config.getFpsRange())) {
55512da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                sizes[i++] = config.getSize();
55612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            }
55712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        }
55812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        return sizes;
55912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    }
56012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh
56112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /**
5629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
5639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * for the format/size combination (in nanoseconds).
5649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
5669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code size} should be one of the ones returned by
5679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(int)}.</p>
5689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This should correspond to the frame duration when only that stream is active, with all
5709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * processing (typically in {@code android.*.mode}) set to either {@code OFF} or {@code FAST}.
5719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
5729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>When multiple streams are used in a request, the minimum frame duration will be
5749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code max(individual stream min durations)}.</p>
5759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
57608bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     * <p>For devices that do not support manual sensor control
57708bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     * ({@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR}),
578abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala     * this function may return 0.</p>
57908bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     *
5809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <!--
5819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * TODO: uncomment after adding input stream support
5829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The minimum frame duration of a stream (of a particular format, size) is the same
5839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * regardless of whether the stream is input or output.</p>
5849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * -->
5859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
5879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param size an output-compatible size
5883e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk     * @return a minimum frame duration {@code >} 0 in nanoseconds, or
589abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala     *          0 if the minimum frame duration is not available.
5909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
5929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code size} was {@code null}
5939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
5949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see CaptureRequest#SENSOR_FRAME_DURATION
5959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #getOutputStallDuration(int, Size)
5969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
5979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
5989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
5999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public long getOutputMinFrameDuration(int format, Size size) {
6009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkNotNull(size, "size must not be null");
6019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkArgumentFormatSupported(format, /*output*/true);
6029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
6039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatDuration(imageFormatToInternal(format), size, DURATION_MIN_FRAME);
6049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
6059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
6069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
6079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
6089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * for the class/size combination (in nanoseconds).
6099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
6119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
6129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code klass} should be one of the ones which is supported by
6149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #isOutputSupportedFor(Class)}.</p>
6159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code size} should be one of the ones returned by
6179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(int)}.</p>
6189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This should correspond to the frame duration when only that stream is active, with all
6209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * processing (typically in {@code android.*.mode}) set to either {@code OFF} or {@code FAST}.
6219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
6229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>When multiple streams are used in a request, the minimum frame duration will be
6249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code max(individual stream min durations)}.</p>
6259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
62608bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     * <p>For devices that do not support manual sensor control
62708bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     * ({@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR}),
628abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala     * this function may return 0.</p>
62908bc3b0f0299a02d00004f4b2886469c1ed75569Eino-Ville Talvala     *
6309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <!--
6319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * TODO: uncomment after adding input stream support
6329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The minimum frame duration of a stream (of a particular format, size) is the same
6339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * regardless of whether the stream is input or output.</p>
6349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * -->
6359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param klass
6379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
6389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          non-empty array returned by {@link #getOutputSizes(Class)}
6399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param size an output-compatible size
6403e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk     * @return a minimum frame duration {@code >} 0 in nanoseconds, or
641abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala     *          0 if the minimum frame duration is not available.
6429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
6449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
6459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see CaptureRequest#SENSOR_FRAME_DURATION
6479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
6489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
6499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
6509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
6519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!isOutputSupportedFor(klass)) {
6529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException("klass was not supported");
6539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
6549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
6559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
6569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                size, DURATION_MIN_FRAME);
6579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
6589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
6599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
6609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the stall duration for the format/size combination (in nanoseconds).
6619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
6639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code size} should be one of the ones returned by
6649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(int)}.</p>
6659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>
6679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * A stall duration is how much extra time would get added to the normal minimum frame duration
6689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * for a repeating request that has streams with non-zero stall.
6699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>For example, consider JPEG captures which have the following characteristics:
6719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
6739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>JPEG streams act like processed YUV streams in requests for which they are not included;
6749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * in requests in which they are directly referenced, they act as JPEG streams.
6759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * This is because supporting a JPEG stream requires the underlying YUV data to always be ready
6769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * for use by a JPEG encoder, but the encoder will only be used (and impact frame duration) on
6779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * requests that actually reference a JPEG stream.
6789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>The JPEG processor can run concurrently to the rest of the camera pipeline, but cannot
6799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * process more than 1 capture at a time.
6809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
6819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>In other words, using a repeating YUV request would result in a steady frame rate
6839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * (let's say it's 30 FPS). If a single JPEG request is submitted periodically,
6849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * the frame rate will stay at 30 FPS (as long as we wait for the previous JPEG to return each
6859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * time). If we try to submit a repeating YUV + JPEG request, then the frame rate will drop from
6869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * 30 FPS.</p>
6879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>In general, submitting a new request with a non-0 stall time stream will <em>not</em> cause a
6899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * frame rate drop unless there are still outstanding buffers for that stream from previous
6909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * requests.</p>
6919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Submitting a repeating request with streams (call this {@code S}) is the same as setting
6939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * the minimum frame duration from the normal minimum frame duration corresponding to {@code S},
6949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * added with the maximum stall duration for {@code S}.</p>
6959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>If interleaving requests with and without a stall duration, a request will stall by the
6979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * maximum of the remaining times for each can-stall stream with outstanding buffers.</p>
6989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
6999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This means that a stalling request will not have an exposure start until the stall has
7009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * completed.</p>
7019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This should correspond to the stall duration when only that stream is active, with all
7039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * processing (typically in {@code android.*.mode}) set to {@code FAST} or {@code OFF}.
7049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Setting any of the processing modes to {@code HIGH_QUALITY} effectively results in an
7059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * indeterminate stall duration for all streams in a request (the regular stall calculation
7069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * rules are ignored).</p>
7079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The following formats may always have a stall duration:
7099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
7109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link ImageFormat#JPEG JPEG}
7119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link ImageFormat#RAW_SENSOR RAW16}
7129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
7139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
7149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>The following formats will never have a stall duration:
7169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
7179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link ImageFormat#YUV_420_888 YUV_420_888}
7189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>{@link #isOutputSupportedFor(Class) Implementation-Defined}
7199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul></p>
7209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>
7229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * All other formats may or may not have an allowed stall duration on a per-capability basis;
7239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
7249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * android.request.availableCapabilities} for more details.</p>
7259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
7269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}
7289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * for more information about calculating the max frame rate (absent stalls).</p>
7299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
7319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param size an output-compatible size
7329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return a stall duration {@code >=} 0 in nanoseconds
7339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
7359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code size} was {@code null}
7369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see CaptureRequest#SENSOR_FRAME_DURATION
7389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
7399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
7409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
7419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public long getOutputStallDuration(int format, Size size) {
7429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkArgumentFormatSupported(format, /*output*/true);
7439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
7449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatDuration(imageFormatToInternal(format),
7459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                size, DURATION_STALL);
7469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
7479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
7489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
7499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the stall duration for the class/size combination (in nanoseconds).
7509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
7529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
7539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code klass} should be one of the ones with a non-empty array returned by
7559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(Class)}.</p>
7569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>{@code size} should be one of the ones returned by
7589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link #getOutputSizes(Class)}.</p>
7599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>See {@link #getOutputStallDuration(int, Size)} for a definition of a
7619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <em>stall duration</em>.</p>
7629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param klass
7649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
7659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          non-empty array returned by {@link #getOutputSizes(Class)}
7669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param size an output-compatible size
7679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return a minimum frame duration {@code >=} 0 in nanoseconds
7689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
7709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
7719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see CaptureRequest#SENSOR_FRAME_DURATION
7739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
7749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
7759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
7769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
7779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!isOutputSupportedFor(klass)) {
7789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException("klass was not supported");
7799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
7809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
7819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
7829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                size, DURATION_STALL);
7839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
7849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
7859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
7869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Check if this {@link StreamConfigurationMap} is equal to another
7879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link StreamConfigurationMap}.
7889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
7909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
7919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return {@code true} if the objects were equal, {@code false} otherwise
7929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
7939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    @Override
7949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public boolean equals(final Object obj) {
7959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (obj == null) {
7969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return false;
7979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
7989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (this == obj) {
7999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return true;
8009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
8019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (obj instanceof StreamConfigurationMap) {
8029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            final StreamConfigurationMap other = (StreamConfigurationMap) obj;
8039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            // XX: do we care about order?
8049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return Arrays.equals(mConfigurations, other.mConfigurations) &&
8059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) &&
80612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    Arrays.equals(mStallDurations, other.mStallDurations) &&
80712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                    Arrays.equals(mHighSpeedVideoConfigurations,
80812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                            other.mHighSpeedVideoConfigurations);
8099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
8109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return false;
8119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
8129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
8149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@inheritDoc}
8159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
8169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    @Override
8179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public int hashCode() {
8189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // XX: do we care about order?
81912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh        return HashCodeHelpers.hashCode(
82012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                mConfigurations, mMinFrameDurations,
82112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh                mStallDurations, mHighSpeedVideoConfigurations);
8229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
8239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    // Check that the argument is supported by #getOutputFormats or #getInputFormats
8259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private int checkArgumentFormatSupported(int format, boolean output) {
8269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        checkArgumentFormat(format);
8279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] formats = output ? getOutputFormats() : getInputFormats();
8299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < formats.length; ++i) {
8309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (format == formats[i]) {
8319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return format;
8329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
8339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
8349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        throw new IllegalArgumentException(String.format(
8369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                "format %x is not supported by this stream configuration map", format));
8379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
8389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
8409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Ensures that the format is either user-defined or implementation defined.
8419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>If a format has a different internal representation than the public representation,
8439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * passing in the public representation here will fail.</p>
8449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>For example if trying to use {@link ImageFormat#JPEG}:
8469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * it has a different public representation than the internal representation
8479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@code HAL_PIXEL_FORMAT_BLOB}, this check will fail.</p>
8489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Any invalid/undefined formats will raise an exception.</p>
8509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format image format
8529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return the format
8539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if the format was invalid
8559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
8569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    static int checkArgumentFormatInternal(int format) {
8579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (format) {
8589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
8599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case HAL_PIXEL_FORMAT_BLOB:
860d3b85f69a811113826933c8abf591f20e9b3c8ffEino-Ville Talvala            case HAL_PIXEL_FORMAT_RAW_OPAQUE:
8619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return format;
8629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case ImageFormat.JPEG:
8639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new IllegalArgumentException(
8649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        "ImageFormat.JPEG is an unknown internal format");
8659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
8669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return checkArgumentFormat(format);
8679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
8689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
8699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
8719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Ensures that the format is publicly user-defined in either ImageFormat or PixelFormat.
8729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>If a format has a different public representation than the internal representation,
8749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * passing in the internal representation here will fail.</p>
8759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>For example if trying to use {@code HAL_PIXEL_FORMAT_BLOB}:
8779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * it has a different internal representation than the public representation
8789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * {@link ImageFormat#JPEG}, this check will fail.</p>
8799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Any invalid/undefined formats will raise an exception, including implementation-defined.
8819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
8829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Note that {@code @hide} and deprecated formats will not pass this check.</p>
8849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format image format
8869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return the format
8879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
8889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException if the format was not user-defined
8899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
8909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    static int checkArgumentFormat(int format) {
8919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
8929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException(String.format(
8939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    "format 0x%x was not defined in either ImageFormat or PixelFormat", format));
8949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
8959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return format;
8979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
8989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
8999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
9009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Convert a public-visible {@code ImageFormat} into an internal format
9019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * compatible with {@code graphics.h}.
9029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>In particular these formats are converted:
9049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
9059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>HAL_PIXEL_FORMAT_BLOB => ImageFormat.JPEG
9069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
9079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
9089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Passing in an implementation-defined format which has no public equivalent will fail;
9109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * as will passing in a public format which has a different internal format equivalent.
9119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
9129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>All other formats are returned as-is, no further invalid check is performed.</p>
9149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This function is the dual of {@link #imageFormatToInternal}.</p>
9169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format image format from {@link ImageFormat} or {@link PixelFormat}
9189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return the converted image formats
9199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException
9219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          if {@code format} is {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED} or
9229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *          {@link ImageFormat#JPEG}
9239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
9259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
9269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #checkArgumentFormat
9279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
9289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    static int imageFormatToPublic(int format) {
9299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (format) {
9309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case HAL_PIXEL_FORMAT_BLOB:
9319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return ImageFormat.JPEG;
9329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case ImageFormat.JPEG:
9339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new IllegalArgumentException(
9349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        "ImageFormat.JPEG is an unknown internal format");
9359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
9369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new IllegalArgumentException(
9379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        "IMPLEMENTATION_DEFINED must not leak to public API");
9389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
9399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return format;
9409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
9419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
9429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
9449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Convert image formats from internal to public formats (in-place).
9459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param formats an array of image formats
9479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return {@code formats}
9489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #imageFormatToPublic
9509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
9519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    static int[] imageFormatToPublic(int[] formats) {
9529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (formats == null) {
9539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return null;
9549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
9559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < formats.length; ++i) {
9579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            formats[i] = imageFormatToPublic(formats[i]);
9589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
9599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return formats;
9619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
9629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
9639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
9649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Convert a public format compatible with {@code ImageFormat} to an internal format
9659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * from {@code graphics.h}.
9669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>In particular these formats are converted:
9689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <ul>
9699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <li>ImageFormat.JPEG => HAL_PIXEL_FORMAT_BLOB
9709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </ul>
9719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * </p>
9729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>Passing in an implementation-defined format here will fail (it's not a public format);
9749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * as will passing in an internal format which has a different public format equivalent.
9759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
9769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>All other formats are returned as-is, no invalid check is performed.</p>
9789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * <p>This function is the dual of {@link #imageFormatToPublic}.</p>
9809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param format public image format from {@link ImageFormat} or {@link PixelFormat}
9829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return the converted image formats
9839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see ImageFormat
9859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see PixelFormat
9869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
9879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @throws IllegalArgumentException
9889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *              if {@code format} was {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}
9899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
9909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    static int imageFormatToInternal(int format) {
9919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (format) {
9929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case ImageFormat.JPEG:
9939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return HAL_PIXEL_FORMAT_BLOB;
9949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
9959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new IllegalArgumentException(
9969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                        "IMPLEMENTATION_DEFINED is not allowed via public API");
9979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
9989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return format;
9999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
10039c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Convert image formats from public to internal formats (in-place).
10049c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
10059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @param formats an array of image formats
10069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @return {@code formats}
10079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
10089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #imageFormatToInternal
10099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
10109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @hide
10119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
10129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    public static int[] imageFormatToInternal(int[] formats) {
10139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (formats == null) {
10149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return null;
10159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int i = 0; i < formats.length; ++i) {
10189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            formats[i] = imageFormatToInternal(formats[i]);
10199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return formats;
10229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private Size[] getPublicFormatSizes(int format, boolean output) {
10259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        try {
10269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            checkArgumentFormatSupported(format, output);
10279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        } catch (IllegalArgumentException e) {
10289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return null;
10299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        format = imageFormatToInternal(format);
10329c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10339c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return getInternalFormatSizes(format, output);
10349c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10359c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private Size[] getInternalFormatSizes(int format, boolean output) {
10379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
10389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Integer sizesCount = formatsMap.get(format);
10409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (sizesCount == null) {
10419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException("format not available");
10429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int len = sizesCount;
10459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        Size[] sizes = new Size[len];
10469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int sizeIndex = 0;
10479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (StreamConfiguration config : mConfigurations) {
10499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (config.getFormat() == format && config.isOutput() == output) {
10509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                sizes[sizeIndex++] = config.getSize();
10519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
10529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (sizeIndex != len) {
10559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new AssertionError(
10569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    "Too few sizes (expected " + len + ", actual " + sizeIndex + ")");
10579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return sizes;
10609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /** Get the list of publically visible output formats; does not include IMPL_DEFINED */
10639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private int[] getPublicFormats(boolean output) {
10649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int[] formats = new int[getPublicFormatCount(output)];
10659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int i = 0;
10679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10689c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (int format : getFormatsMap(output).keySet()) {
1069fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
1070fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala                format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
10719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                formats[i++] = format;
10729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
10739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (formats.length != i) {
10769c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new AssertionError("Too few formats " + i + ", expected " + formats.length);
10779c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10789c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10799c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return imageFormatToPublic(formats);
10809c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10819c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /** Get the format -> size count map for either output or input formats */
10839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private HashMap<Integer, Integer> getFormatsMap(boolean output) {
10849c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return output ? mOutputFormats : mInputFormats;
10859c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
10869c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10879c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private long getInternalFormatDuration(int format, Size size, int duration) {
10889c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        // assume format is already checked, since its internal
10899c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10909c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (!arrayContains(getInternalFormatSizes(format, /*output*/true), size)) {
10919c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            throw new IllegalArgumentException("size was not supported");
10929c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
10939c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10949c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        StreamConfigurationDuration[] durations = getDurations(duration);
10959c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
10969c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (StreamConfigurationDuration configurationDuration : durations) {
10979c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (configurationDuration.getFormat() == format &&
10989c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    configurationDuration.getWidth() == size.getWidth() &&
10999c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                    configurationDuration.getHeight() == size.getHeight()) {
11009c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return configurationDuration.getDuration();
11019c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
11029c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
1103abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala        // Default duration is '0' (unsupported/no extra stall)
1104abd9d3c5c7100c45812ee80975ac59f5b1902a71Eino-Ville Talvala        return 0;
11059c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
11069c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11079c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
11089c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * Get the durations array for the kind of duration
11099c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     *
11109c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #DURATION_MIN_FRAME
11119c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #DURATION_STALL
11129c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * */
11139c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private StreamConfigurationDuration[] getDurations(int duration) {
11149c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        switch (duration) {
11159c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case DURATION_MIN_FRAME:
11169c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return mMinFrameDurations;
11179c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            case DURATION_STALL:
11189c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return mStallDurations;
11199c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            default:
11209c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                throw new IllegalArgumentException("duration was invalid");
11219c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
11229c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
11239c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11249c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /** Count the number of publicly-visible output formats */
11259c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private int getPublicFormatCount(boolean output) {
11269c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
11279c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11289c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        int size = formatsMap.size();
11299c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (formatsMap.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
11309c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            size -= 1;
11319c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
1132fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
1133fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala            size -= 1;
1134fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala        }
1135fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala
11369c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return size;
11379c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
11389c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11399c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static <T> boolean arrayContains(T[] array, T element) {
11409c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        if (array == null) {
11419c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            return false;
11429c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
11439c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11449c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        for (T el : array) {
11459c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            if (Objects.equals(el, element)) {
11469c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin                return true;
11479c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            }
11489c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        }
11499c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11509c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin        return false;
11519c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    }
11529c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11539c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    // from system/core/include/system/graphics.h
11549c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
11559c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
11569c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24;
11579c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11589c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /**
11599c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #getDurations(int)
11609c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     * @see #getDurationDefault(int)
11619c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin     */
11629c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int DURATION_MIN_FRAME = 0;
11639c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private static final int DURATION_STALL = 1;
11649c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11659c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private final StreamConfiguration[] mConfigurations;
11669c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private final StreamConfigurationDuration[] mMinFrameDurations;
11679c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private final StreamConfigurationDuration[] mStallDurations;
116812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
11699c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11709c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /** ImageFormat -> num output sizes mapping */
11719c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mOutputFormats =
11729c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            new HashMap<Integer, Integer>();
11739c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    /** ImageFormat -> num input sizes mapping */
11749c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats =
11759c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin            new HashMap<Integer, Integer>();
117612da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /** High speed video Size -> FPS range count mapping*/
117712da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
117812da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            new HashMap<Size, Integer>();
117912da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    /** High speed video FPS range -> Size count mapping*/
118012da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh    private final HashMap</*HighSpeedVideoFpsRange*/Range<Integer>, /*Count*/Integer>
118112da140082323d9aa048b3e928505a0a2adfdda7Yin-Chia Yeh            mHighSpeedVideoFpsRangeMap = new HashMap<Range<Integer>, Integer>();
11829c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin
11839c595174ccaaf3d36315c4a100e47ee4369073f6Igor Murashkin}
1184