public class

Extensions

extends java.lang.Object

 java.lang.Object

↳androidx.camera.extensions.Extensions

Overview

A class for querying and controlling the extensions that are enable for individual Camera instances.

The typical usages is to check whether or not a Camera and/or the UseCase combinations support the extension by using Extensions.isExtensionAvailable(Camera, int) and Extensions.checkUseCases(Camera, List, int). Then after it has been determined that the extension can be enable then a Extensions.setExtension(Camera, int) call can be used to set the specified extension on the camera.

When the Camera has been set to a particular extension it might require the camera to restart which can cause the preview to temporarily stop. Once the extension has been enable for a Camera instance then it will stay in that extension mode until the extension has been disabled. Setting extension modes is separate for each camera instance.

Summary

Fields
public static final intEXTENSION_MODE_AUTO

Auto mode is used for taking still capture images that automatically adjust to the surrounding scenery.

public static final intEXTENSION_MODE_BEAUTY

Beauty mode is used for taking still capture images that incorporate facial changes like skin tone, geometry, or retouching.

public static final intEXTENSION_MODE_BOKEH

Bokeh mode that is often applied as portrait mode for people pictures.

public static final intEXTENSION_MODE_HDR

HDR mode that may get source pictures with different AE settings to generate a best result.

public static final intEXTENSION_MODE_NIGHT

Night mode is used for taking better still capture images under low-light situations, typically at night time.

public static final intEXTENSION_MODE_NONE

Normal mode without any specific effect applied.

Methods
public java.util.List<java.util.List>checkUseCases(Camera camera, java.util.List<UseCase> useCases, int mode)

Checks if the list of UseCases attached to the Camera can support the extension.

public intgetExtension(Camera camera)

Returns the extension mode that is currently set on the camera.

public booleanisExtensionAvailable(Camera camera, int mode)

Returns true if the particular extension mode is available for the specified Camera.

public voidsetExtension(Camera camera, int mode)

Sets the specified extension mode for the Camera.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final int EXTENSION_MODE_NONE

Normal mode without any specific effect applied.

public static final int EXTENSION_MODE_BOKEH

Bokeh mode that is often applied as portrait mode for people pictures.

public static final int EXTENSION_MODE_HDR

HDR mode that may get source pictures with different AE settings to generate a best result.

public static final int EXTENSION_MODE_NIGHT

Night mode is used for taking better still capture images under low-light situations, typically at night time.

public static final int EXTENSION_MODE_BEAUTY

Beauty mode is used for taking still capture images that incorporate facial changes like skin tone, geometry, or retouching.

public static final int EXTENSION_MODE_AUTO

Auto mode is used for taking still capture images that automatically adjust to the surrounding scenery.

Methods

public void setExtension(Camera camera, int mode)

Sets the specified extension mode for the Camera. To return to a non-extensions mode Camera set the extension mode as NONE. For full list of extensions see Extension Modes

Parameters:

camera: The camera that the UseCases are attached to
mode: The extension mode to set. Setting this to EXTENSION_NONE will remove the current extension and will always succeed.

public int getExtension(Camera camera)

Returns the extension mode that is currently set on the camera.

public boolean isExtensionAvailable(Camera camera, int mode)

Returns true if the particular extension mode is available for the specified Camera.

This check is independent of the UseCase which are currently attached to the Camera. To check whether the Camera can support the attached UseCases use Extensions.checkUseCases(Camera, List, int).

Parameters:

camera: The Camera to check if it supports the extension.
mode: The extension mode to check

public java.util.List<java.util.List> checkUseCases(Camera camera, java.util.List<UseCase> useCases, int mode)

Checks if the list of UseCases attached to the Camera can support the extension. If the list of UseCases exceeds the capacity of Surfaces for the Camera then it returns a list of UseCase lists that can be removed in order to allow for the extension to be enabled. Any of the individual lists can be removed.

Returns:

null if the Camera supports the extension using the list of UseCases, otherwise a list of UseCase list to remove.

Source

/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.camera.extensions;

import android.content.Context;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.annotation.experimental.UseExperimental;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraFilter;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.ExperimentalCameraFilter;
import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CameraFilters;
import androidx.camera.core.internal.CameraUseCaseAdapter;
import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.BeautyPreviewExtenderImpl;
import androidx.camera.extensions.impl.BokehImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.BokehPreviewExtenderImpl;
import androidx.camera.extensions.impl.HdrImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.HdrPreviewExtenderImpl;
import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
import androidx.camera.extensions.internal.ExtensionsUseCaseConfigFactory;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.LinkedHashSet;
import java.util.List;

/**
 * A class for querying and controlling the extensions that are enable for individual
 * {@link Camera} instances.
 *
 * <p> The typical usages is to check whether or not a Camera and/or the {@link UseCase}
 * combinations support the extension by using {@link #isExtensionAvailable(Camera, int)} and
 * {@link #checkUseCases(Camera, List, int)}. Then after it has been determined that the
 * extension can be enable then a {@link #setExtension(Camera, int)} call can be used to set the
 * specified extension on the camera.
 *
 * <p> When the Camera has been set to a particular extension it might require the camera to
 * restart which can cause the preview to temporarily stop. Once the extension has been enable
 * for a Camera instance then it will stay in that extension mode until the extension has been
 * disabled. Setting extension modes is separate for each camera instance.
 *
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class Extensions {
    private static final String TAG = "Extensions";

    /** Normal mode without any specific effect applied. */
    public static final int EXTENSION_MODE_NONE = 0;
    /** Bokeh mode that is often applied as portrait mode for people pictures. */
    public static final int EXTENSION_MODE_BOKEH = 1;
    /**
     * HDR mode that may get source pictures with different AE settings to generate a best
     * result.
     */
    public static final int EXTENSION_MODE_HDR = 2;
    /**
     * Night mode is used for taking better still capture images under low-light situations,
     * typically at night time.
     */
    public static final int EXTENSION_MODE_NIGHT = 3;
    /**
     * Beauty mode is used for taking still capture images that incorporate facial changes
     * like skin tone, geometry, or retouching.
     */
    public static final int EXTENSION_MODE_BEAUTY = 4;
    /**
     * Auto mode is used for taking still capture images that automatically adjust to the
     * surrounding scenery.
     */
    public static final int EXTENSION_MODE_AUTO = 5;

    private final Context mContext;

    /**
     * The different extension modes that a {@link Camera} can be configured for.
     *
     * <p>Not all devices and camera support the different extension modes. To query whether or
     * not a specific Camera supports an extension mode use
     * {@link Extensions#isExtensionAvailable(Camera, int)}.
     *
     * @hide
     */
    @IntDef({EXTENSION_MODE_NONE, EXTENSION_MODE_BOKEH, EXTENSION_MODE_HDR, EXTENSION_MODE_NIGHT,
            EXTENSION_MODE_BEAUTY, EXTENSION_MODE_AUTO})
    @Retention(RetentionPolicy.SOURCE)
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    public @interface ExtensionMode {
    }

    Extensions(@NonNull Context context) {
        mContext = context;
    }

    /**
     * Sets the specified extension mode for the Camera.
     *
     * To return to a non-extensions mode Camera set the extension mode as NONE.
     * For full list of extensions see Extension Modes
     *
     * @param camera The camera that the UseCases are attached to
     * @param mode   The extension mode to set. Setting this to EXTENSION_NONE will
     *               remove the current extension and will always succeed.
     * @throws IllegalArgumentException if the specified extension mode can not be set on the
     *                                  Camera. This can happen if the extension is not supported
     *                                  on this camera. This might also
     *                                  because the combination of UseCases attached to the
     *                                  Camera. Use {@link
     *                                  #checkUseCases(Camera, List, int)} to verify that the
     *                                  Camera can support the list of
     *                                  UseCases for the extension.
     */
    @UseExperimental(markerClass = ExperimentalCameraFilter.class)
    public void setExtension(@NonNull Camera camera, @ExtensionMode int mode) {
        if (!isExtensionAvailable(camera, mode)) {
            throw new IllegalArgumentException("Extension mode not supported on camera: " + mode);
        }

        CameraFilter extensionsFilter = getFilter(mode);
        Camera extensionCamera =
                extensionsFilter.filter(
                        new LinkedHashSet<>(camera.getCameraInternals())).iterator().next();
        CameraInfo extensionsCameraInfo = extensionCamera.getCameraInfo();

        ExtensionsUseCaseConfigFactory factory = new ExtensionsUseCaseConfigFactory(mode,
                extensionsCameraInfo, mContext);

        // Set the Camera
        ExtensionsConfig extensionsConfig =
                new ExtensionsConfig.Builder()
                        .setExtensionMode(mode)
                        .setCameraFilter(getFilter(mode))
                        .setUseCaseConfigFactory(factory)
                        .build();

        // Set the config on the camera
        try {
            camera.setExtendedConfig(extensionsConfig);
        } catch (CameraUseCaseAdapter.CameraException e) {
            throw new IllegalArgumentException("Camera unable to support the extension with the "
                    + "attached UseCases. " + e);
        }
    }

    /**
     * Returns the extension mode that is currently set on the camera.
     */
    public @ExtensionMode int getExtension(@NonNull Camera camera) {
        Object extensionsConfigObject = camera.getExtendedConfig();

        if (extensionsConfigObject instanceof ExtensionsConfig) {
            ExtensionsConfig extensionsConfig = (ExtensionsConfig) extensionsConfigObject;
            return extensionsConfig.getExtensionMode();
        }
        return EXTENSION_MODE_NONE;
    }

    /**
     * Returns true if the particular extension mode is available for the specified
     * Camera.
     *
     * <p> This check is independent of the {@link UseCase} which are currently attached to the
     * {@link Camera}. To check whether the Camera can support the attached UseCases use {@link
     * #checkUseCases(Camera, List, int)}.
     *
     * @param camera The Camera to check if it supports the extension.
     * @param mode   The extension mode to check
     */
    @UseExperimental(markerClass = ExperimentalCameraFilter.class)
    public boolean isExtensionAvailable(@NonNull Camera camera, @ExtensionMode int mode) {
        CameraFilter filter = getFilter(mode);

        // Extension is available for the camera if it contains a CameraInternal which supports
        // the extension
        return !filter.filter(new LinkedHashSet<>(camera.getCameraInternals())).isEmpty();
    }

    @UseExperimental(markerClass = ExperimentalCameraFilter.class)
    private CameraFilter getFilter(@ExtensionMode int mode) {
        CameraFilter filter;
        try {
            switch (mode) {
                case EXTENSION_MODE_BOKEH:
                    filter = new ExtensionCameraFilter(new BokehPreviewExtenderImpl(),
                            new BokehImageCaptureExtenderImpl());
                    break;
                case EXTENSION_MODE_HDR:
                    filter = new ExtensionCameraFilter(new HdrPreviewExtenderImpl(),
                            new HdrImageCaptureExtenderImpl());
                    break;
                case EXTENSION_MODE_NIGHT:
                    filter = new ExtensionCameraFilter(new NightPreviewExtenderImpl(),
                            new NightImageCaptureExtenderImpl());
                    break;
                case EXTENSION_MODE_BEAUTY:
                    filter = new ExtensionCameraFilter(new BeautyPreviewExtenderImpl(),
                            new BeautyImageCaptureExtenderImpl());
                    break;
                case EXTENSION_MODE_AUTO:
                    filter = new ExtensionCameraFilter(new AutoPreviewExtenderImpl(),
                            new AutoImageCaptureExtenderImpl());
                    break;
                case EXTENSION_MODE_NONE:
                default:
                    filter = CameraFilters.ANY;
            }
        } catch (NoClassDefFoundError e) {
            filter = CameraFilters.NONE;
        }

        return filter;
    }

    /**
     * Checks if the list of UseCases attached to the Camera can support the
     * extension.
     *
     * If the list of UseCases exceeds the capacity of Surfaces for the Camera then
     * it returns a list of UseCase lists that can be removed in order to allow for
     * the extension to be enabled. Any of the individual lists can be removed.
     *
     * @return null if the Camera supports the extension using the list of UseCases, otherwise a
     * list of UseCase list to remove.
     */
    @NonNull
    public List<List<UseCase>> checkUseCases(@NonNull Camera camera,
            @NonNull List<UseCase> useCases,
            @ExtensionMode int mode) {
        throw new UnsupportedOperationException("not yet implemented");
    }
}