public class

BasicVendorExtender

extends java.lang.Object

implements VendorExtender

 java.lang.Object

↳androidx.camera.extensions.internal.BasicVendorExtender

Gradle dependencies

compile group: 'androidx.camera', name: 'camera-extensions', version: '1.2.0-alpha01'

  • groupId: androidx.camera
  • artifactId: camera-extensions
  • version: 1.2.0-alpha01

Artifact androidx.camera:camera-extensions:1.2.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

Basic vendor interface implementation

Summary

Constructors
publicBasicVendorExtender(int mode)

Methods
public SessionProcessorcreateSessionProcessor(Context context)

public <any>getEstimatedCaptureLatencyRange(Size size)

public ImageCaptureExtenderImplgetImageCaptureExtenderImpl()

Return the instance which could be null if the implementation doesn't exist..

public PreviewExtenderImplgetPreviewExtenderImpl()

Return the instance which could be null if the implementation doesn't exist.

public java.util.List<>getSupportedCaptureOutputResolutions()

public java.util.List<>getSupportedPreviewOutputResolutions()

public SizegetSupportedYuvAnalysisResolutions()

public voidinit(CameraInfo cameraInfo)

public booleanisExtensionAvailable(java.lang.String cameraId, java.util.Map<java.lang.String, CameraCharacteristics> characteristicsMap)

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

Constructors

public BasicVendorExtender(int mode)

Methods

public PreviewExtenderImpl getPreviewExtenderImpl()

Return the instance which could be null if the implementation doesn't exist. This method will be removed once the existing basic extender implementation is migrated to the unified vendor extender.

public ImageCaptureExtenderImpl getImageCaptureExtenderImpl()

Return the instance which could be null if the implementation doesn't exist.. This method will be removed once the existing basic extender implementation is migrated to the unified vendor extender.

public boolean isExtensionAvailable(java.lang.String cameraId, java.util.Map<java.lang.String, CameraCharacteristics> characteristicsMap)

public void init(CameraInfo cameraInfo)

public <any> getEstimatedCaptureLatencyRange(Size size)

public java.util.List<> getSupportedPreviewOutputResolutions()

public java.util.List<> getSupportedCaptureOutputResolutions()

public Size getSupportedYuvAnalysisResolutions()

public SessionProcessor createSessionProcessor(Context context)

Source

/*
 * Copyright 2021 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.internal;

import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.util.Pair;
import android.util.Range;
import android.util.Size;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.annotation.RequiresApi;
import androidx.camera.camera2.interop.Camera2CameraInfo;
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.Logger;
import androidx.camera.core.impl.SessionProcessor;
import androidx.camera.extensions.ExtensionMode;
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.ImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.NightImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.NightPreviewExtenderImpl;
import androidx.camera.extensions.impl.PreviewExtenderImpl;
import androidx.camera.extensions.internal.compat.workaround.ExtensionDisabledValidator;
import androidx.core.util.Preconditions;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Basic vendor interface implementation
 */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
public class BasicVendorExtender implements VendorExtender {
    private static final String TAG = "BasicVendorExtender";
    private final ExtensionDisabledValidator mExtensionDisabledValidator =
            new ExtensionDisabledValidator();
    private final @ExtensionMode.Mode int mMode;
    private PreviewExtenderImpl mPreviewExtenderImpl = null;
    private ImageCaptureExtenderImpl mImageCaptureExtenderImpl = null;
    private CameraInfo mCameraInfo;

    public BasicVendorExtender(@ExtensionMode.Mode int mode) {
        mMode = mode;
        try {
            switch (mode) {
                case ExtensionMode.BOKEH:
                    mPreviewExtenderImpl = new BokehPreviewExtenderImpl();
                    mImageCaptureExtenderImpl = new BokehImageCaptureExtenderImpl();
                    break;
                case ExtensionMode.HDR:
                    mPreviewExtenderImpl = new HdrPreviewExtenderImpl();
                    mImageCaptureExtenderImpl = new HdrImageCaptureExtenderImpl();
                    break;
                case ExtensionMode.NIGHT:
                    mPreviewExtenderImpl = new NightPreviewExtenderImpl();
                    mImageCaptureExtenderImpl = new NightImageCaptureExtenderImpl();
                    break;
                case ExtensionMode.FACE_RETOUCH:
                    mPreviewExtenderImpl = new BeautyPreviewExtenderImpl();
                    mImageCaptureExtenderImpl = new BeautyImageCaptureExtenderImpl();
                    break;
                case ExtensionMode.AUTO:
                    mPreviewExtenderImpl = new AutoPreviewExtenderImpl();
                    mImageCaptureExtenderImpl = new AutoImageCaptureExtenderImpl();
                    break;
                case ExtensionMode.NONE:
                default:
                    throw new IllegalArgumentException("Should not activate ExtensionMode.NONE");
            }
        } catch (NoClassDefFoundError e) {
            Logger.e(TAG, "OEM implementation for extension mode " + mode + "does not exist!");
        }
    }

    /**
     * Return the {@link PreviewExtenderImpl} instance which could be null if the implementation
     * doesn't exist. This method will be removed once the existing basic extender implementation
     * is migrated to the unified vendor extender.
     */
    @Nullable
    public PreviewExtenderImpl getPreviewExtenderImpl() {
        return mPreviewExtenderImpl;
    }

    /**
     * Return the {@link ImageCaptureExtenderImpl} instance which could be null if the
     * implementation doesn't exist.. This method will be removed once the existing basic
     * extender implementation is migrated to the unified vendor extender.
     */
    @Nullable
    public ImageCaptureExtenderImpl getImageCaptureExtenderImpl() {
        return mImageCaptureExtenderImpl;
    }

    @Override
    public boolean isExtensionAvailable(@NonNull String cameraId,
            @NonNull Map<String, CameraCharacteristics> characteristicsMap) {

        if (mExtensionDisabledValidator.shouldDisableExtension(cameraId, mMode)) {
            return false;
        }

        // Returns false if implementation classes do not exist.
        if (mPreviewExtenderImpl == null || mImageCaptureExtenderImpl == null) {
            return false;
        }

        CameraCharacteristics cameraCharacteristics = characteristicsMap.get(cameraId);
        return mPreviewExtenderImpl.isExtensionAvailable(cameraId, cameraCharacteristics)
                && mImageCaptureExtenderImpl.isExtensionAvailable(cameraId, cameraCharacteristics);
    }

    @OptIn(markerClass = ExperimentalCamera2Interop.class)
    @Override
    public void init(@NonNull CameraInfo cameraInfo) {
        mCameraInfo = cameraInfo;

        if (mPreviewExtenderImpl == null || mImageCaptureExtenderImpl == null) {
            return;
        }

        String cameraId = Camera2CameraInfo.from(cameraInfo).getCameraId();
        CameraCharacteristics cameraCharacteristics =
                Camera2CameraInfo.extractCameraCharacteristics(cameraInfo);
        mPreviewExtenderImpl.init(cameraId, cameraCharacteristics);
        mImageCaptureExtenderImpl.init(cameraId, cameraCharacteristics);

        Logger.d(TAG, "Extension init Mode = " + mMode);
        Logger.d(TAG, "PreviewExtender processorType= " + mPreviewExtenderImpl.getProcessorType());
        Logger.d(TAG, "ImageCaptureExtender processor= "
                + mImageCaptureExtenderImpl.getCaptureProcessor());
    }

    @Nullable
    @Override
    public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size size) {
        Preconditions.checkNotNull(mCameraInfo, "VendorExtender#init() must be called first");
        if (mImageCaptureExtenderImpl != null && ExtensionVersion.getRuntimeVersion().compareTo(
                Version.VERSION_1_2) >= 0) {
            try {
                return mImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange(size);
            } catch (NoSuchMethodError e) {
            }
        }
        return null;
    }

    @OptIn(markerClass = ExperimentalCamera2Interop.class)
    private Size[] getOutputSizes(int imageFormat) {
        StreamConfigurationMap map = Camera2CameraInfo.from(mCameraInfo)
                .getCameraCharacteristic(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

        return map.getOutputSizes(imageFormat);
    }

    private int getPreviewOutputImageFormat() {
        return ImageFormat.PRIVATE;
    }

    private int getCaptureOutputImageFormat() {
        if (mImageCaptureExtenderImpl != null
                && mImageCaptureExtenderImpl.getCaptureProcessor() != null) {
            return ImageFormat.YUV_420_888;
        } else {
            return ImageFormat.JPEG;
        }
    }

    @NonNull
    @Override
    public List<Pair<Integer, Size[]>> getSupportedPreviewOutputResolutions() {
        Preconditions.checkNotNull(mCameraInfo, "VendorExtender#init() must be called first");

        if (mPreviewExtenderImpl != null && ExtensionVersion.getRuntimeVersion().compareTo(
                Version.VERSION_1_1) >= 0) {
            try {
                List<Pair<Integer, Size[]>> result =
                        mPreviewExtenderImpl.getSupportedResolutions();
                if (result != null) {
                    return result;
                }
            } catch (NoSuchMethodError e) {
            }
        }

        // Returns output sizes from stream configuration map if OEM returns null or OEM does not
        // implement the function. It is required to return all supported sizes so it must fetch
        // all sizes from the stream configuration map here.
        int imageformat = getPreviewOutputImageFormat();
        return Arrays.asList(new Pair<>(imageformat, getOutputSizes(imageformat)));
    }


    @NonNull
    @Override
    public List<Pair<Integer, Size[]>> getSupportedCaptureOutputResolutions() {
        Preconditions.checkNotNull(mCameraInfo, "VendorExtender#init() must be called first");
        if (mImageCaptureExtenderImpl != null && ExtensionVersion.getRuntimeVersion().compareTo(
                Version.VERSION_1_1) >= 0) {
            try {
                List<Pair<Integer, Size[]>> result =
                        mImageCaptureExtenderImpl.getSupportedResolutions();
                if (result != null) {
                    return result;
                }
            } catch (NoSuchMethodError e) {
            }
        }

        // Returns output sizes from stream configuration map if OEM returns null or OEM does not
        // implement the function. It is required to return all supported sizes so it must fetch
        // all sizes from the stream configuration map here.
        int imageFormat = getCaptureOutputImageFormat();
        return Arrays.asList(new Pair<>(imageFormat, getOutputSizes(imageFormat)));
    }

    @NonNull
    @Override
    public Size[] getSupportedYuvAnalysisResolutions() {
        Preconditions.checkNotNull(mCameraInfo, "VendorExtender#init() must be called first");
        return getOutputSizes(ImageFormat.YUV_420_888);
    }

    @Nullable
    @Override
    public SessionProcessor createSessionProcessor(@NonNull Context context) {
        Preconditions.checkNotNull(mCameraInfo, "VendorExtender#init() must be called first");
        /* Return null to keep using existing flow for basic extender to ensure compatibility for
         * now. We will switch to SessionProcessor implementation once compatibility is ensured.
         */
        return null;
    }
}