Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aeead926 authored by Yin-Chia Yeh's avatar Yin-Chia Yeh Committed by Android (Google) Code Review
Browse files

Merge "NDK: AImageReader implementation"

parents 5bae3d6b c360382b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ LOCAL_MODULE:= libcamera2ndk

LOCAL_C_INCLUDES := \
    system/media/camera/include \
    frameworks/av/include/camera/ndk
    frameworks/av/include/camera/ndk \
    frameworks/av/include/ndk \

LOCAL_CFLAGS += -fvisibility=hidden -D EXPORT='__attribute__ ((visibility ("default")))'

+71 −2
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#include "ACameraMetadata.h"
#include <utils/Vector.h>
#include <system/graphics.h>
#include "NdkImage.h"

using namespace android;

@@ -29,6 +31,7 @@ ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYP
        mData(buffer), mType(type) {
    if (mType == ACM_CHARACTERISTICS) {
        filterUnsupportedFeatures();
        filterStreamConfigurations();
    }
    // TODO: filter request/result keys
}
@@ -60,7 +63,7 @@ void
ACameraMetadata::filterUnsupportedFeatures() {
    // Hide unsupported capabilities (reprocessing)
    camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
    if (entry.count == 0 || entry.type != ACAMERA_TYPE_BYTE) {
    if (entry.count == 0 || entry.type != TYPE_BYTE) {
        ALOGE("%s: malformed available capability key! count %zu, type %d",
                __FUNCTION__, entry.count, entry.type);
        return;
@@ -75,7 +78,73 @@ ACameraMetadata::filterUnsupportedFeatures() {
        }
    }
    mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
    // TODO: Hide unsupported streams (input/bidirectional streams)
}


void
ACameraMetadata::filterStreamConfigurations() {
    const int STREAM_CONFIGURATION_SIZE = 4;
    const int STREAM_FORMAT_OFFSET = 0;
    const int STREAM_WIDTH_OFFSET = 1;
    const int STREAM_HEIGHT_OFFSET = 2;
    const int STREAM_IS_INPUT_OFFSET = 3;
    camera_metadata_entry entry = mData.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
    if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT32) {
        ALOGE("%s: malformed available stream configuration key! count %zu, type %d",
                __FUNCTION__, entry.count, entry.type);
        return;
    }

    Vector<int32_t> filteredStreamConfigs;
    filteredStreamConfigs.setCapacity(entry.count);

    for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
        int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
        int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
        int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
        int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
        if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
            // Hide input streams
            continue;
        }
        // Translate HAL formats to NDK format
        if (format == HAL_PIXEL_FORMAT_BLOB) {
            format = AIMAGE_FORMAT_JPEG;
        }
        filteredStreamConfigs.push_back(format);
        filteredStreamConfigs.push_back(width);
        filteredStreamConfigs.push_back(height);
        filteredStreamConfigs.push_back(isInput);
    }

    mData.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);

    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
    Vector<int32_t> filteredDepthStreamConfigs;
    filteredDepthStreamConfigs.setCapacity(entry.count);

    for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
        int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
        int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
        int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
        int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
        if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
            // Hide input streams
            continue;
        }
        // Translate HAL formats to NDK format
        if (format == HAL_PIXEL_FORMAT_BLOB) {
            format = AIMAGE_FORMAT_DEPTH_POINT_CLOUD;
        } else if (format == HAL_PIXEL_FORMAT_Y16) {
            format = AIMAGE_FORMAT_DEPTH16;
        }

        filteredDepthStreamConfigs.push_back(format);
        filteredDepthStreamConfigs.push_back(width);
        filteredDepthStreamConfigs.push_back(height);
        filteredDepthStreamConfigs.push_back(isInput);
    }
    mData.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, filteredDepthStreamConfigs);
}

bool
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct ACameraMetadata : public RefBase {
    inline bool isVendorTag(const uint32_t tag);
    bool isCaptureRequestTag(const uint32_t tag);
    void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
    void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats

    template<typename INTERNAL_T, typename NDK_T>
    camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {

include/ndk/NdkImage.h

0 → 100644
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

/*
 * This file defines an NDK API.
 * Do not remove methods.
 * Do not change method signatures.
 * Do not change the value of constants.
 * Do not change the size of any of the classes defined in here.
 * Do not reference types that are not part of the NDK.
 * Do not #include files that aren't part of the NDK.
 */

#ifndef _NDK_IMAGE_H
#define _NDK_IMAGE_H

#include "NdkMediaError.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct AImage AImage;

// Formats not listed here will not be supported by AImageReader
enum {
    AIMAGE_FORMAT_YUV_420_888       = 0x23,
    AIMAGE_FORMAT_JPEG              = 0x100,
    AIMAGE_FORMAT_RAW16             = 0x20,
    AIMAGE_FORMAT_RAW_PRIVATE       = 0x24,
    AIMAGE_FORMAT_RAW10             = 0x25,
    AIMAGE_FORMAT_RAW12             = 0x26,
    AIMAGE_FORMAT_DEPTH16           = 0x44363159,
    AIMAGE_FORMAT_DEPTH_POINT_CLOUD = 0x101
};

typedef struct AImageCropRect {
    int32_t left;
    int32_t top;
    int32_t right;
    int32_t bottom;
} AImageCropRect;

// Return the image back to system and delete the AImage from memory
// Do NOT use `image` after this call
void AImage_delete(AImage* image);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getWidth(const AImage* image, /*out*/int32_t* width);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getHeight(const AImage* image, /*out*/int32_t* height);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getFormat(const AImage* image, /*out*/int32_t* format);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getCropRect(const AImage* image, /*out*/AImageCropRect* rect);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getTimestamp(const AImage* image, /*out*/int64_t* timestampNs);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getNumberOfPlanes(const AImage* image, /*out*/int32_t* numPlanes);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getPlanePixelStride(
        const AImage* image, int planeIdx, /*out*/int32_t* pixelStride);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
media_status_t AImage_getPlaneRowStride(
        const AImage* image, int planeIdx, /*out*/int32_t* rowStride);

// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
// Note that once the AImage or the parent AImageReader is deleted, the `*data` returned from
// previous AImage_getPlaneData call becomes dangling pointer. Do NOT use it after
// AImage or AImageReader is deleted
media_status_t AImage_getPlaneData(
        const AImage* image, int planeIdx,
        /*out*/uint8_t** data, /*out*/int* dataLength);

#ifdef __cplusplus
} // extern "C"
#endif

#endif //_NDK_IMAGE_H
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

/*
 * This file defines an NDK API.
 * Do not remove methods.
 * Do not change method signatures.
 * Do not change the value of constants.
 * Do not change the size of any of the classes defined in here.
 * Do not reference types that are not part of the NDK.
 * Do not #include files that aren't part of the NDK.
 */

#ifndef _NDK_IMAGE_READER_H
#define _NDK_IMAGE_READER_H

#include <android/native_window.h>
#include "NdkMediaError.h"
#include "NdkImage.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct AImageReader AImageReader;

media_status_t AImageReader_new(
        int32_t width, int32_t height, int32_t format, int32_t maxImages,
        /*out*/AImageReader** reader);

// Return all images acquired from this AImageReader back to system and delete
// the AImageReader instance from memory
// Do NOT use `reader` after this call
void AImageReader_delete(AImageReader* reader);

// Do NOT call ANativeWindow_release on the output. Just use AImageReader_delete.
media_status_t AImageReader_getWindow(AImageReader*, /*out*/ANativeWindow** window);

media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width);
media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height);
media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format);
media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages);

media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image);

media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image);

// The callback happens on one dedicated thread per AImageReader instance
// It's okay to use AImageReader_*/AImage_* APIs within the callback
typedef void (*AImageReader_ImageCallback)(void* context, AImageReader* reader);

typedef struct AImageReader_ImageListener {
    void*                      context; // optional application context.
    AImageReader_ImageCallback onImageAvailable;
} AImageReader_ImageListener;

media_status_t AImageReader_setImageListener(
        AImageReader* reader, AImageReader_ImageListener* listener);

#ifdef __cplusplus
} // extern "C"
#endif

#endif //_NDK_IMAGE_READER_H
Loading