Merge "Add ACameraMetadata_fromCameraMetadata."

gugelfrei
TreeHugger Robot 5 years ago committed by Android (Google) Code Review
commit 2c5b3c2f90

@ -57,6 +57,9 @@ cc_library_shared {
"libmediandk",
"libnativewindow",
],
header_libs: [
"jni_headers",
],
cflags: [
"-fvisibility=hidden",
"-DEXPORT=__attribute__ ((visibility (\"default\")))",
@ -121,7 +124,6 @@ cc_library_shared {
"android.frameworks.cameraservice.common@2.0",
"android.frameworks.cameraservice.service@2.0",
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
"libarect",

@ -26,6 +26,68 @@
using namespace android;
#ifndef __ANDROID_VNDK__
namespace {
constexpr const char* android_hardware_camera2_CameraMetadata_jniClassName =
"android/hardware/camera2/CameraMetadata";
constexpr const char* android_hardware_camera2_CameraCharacteristics_jniClassName =
"android/hardware/camera2/CameraCharacteristics";
constexpr const char* android_hardware_camera2_CaptureResult_jniClassName =
"android/hardware/camera2/CaptureResult";
jclass android_hardware_camera2_CameraCharacteristics_clazz = nullptr;
jclass android_hardware_camera2_CaptureResult_clazz = nullptr;
jmethodID android_hardware_camera2_CameraMetadata_getNativeMetadataPtr = nullptr;
// Called at most once to initializes global variables used by JNI.
bool InitJni(JNIEnv* env) {
// From C++11 onward, static initializers are guaranteed to be executed at most once,
// even if called from multiple threads.
static bool ok = [env]() -> bool {
const jclass cameraMetadataClazz = env->FindClass(
android_hardware_camera2_CameraMetadata_jniClassName);
if (cameraMetadataClazz == nullptr) {
return false;
}
android_hardware_camera2_CameraMetadata_getNativeMetadataPtr =
env->GetMethodID(cameraMetadataClazz, "getNativeMetadataPtr", "()J");
if (android_hardware_camera2_CameraMetadata_getNativeMetadataPtr == nullptr) {
return false;
}
android_hardware_camera2_CameraCharacteristics_clazz = env->FindClass(
android_hardware_camera2_CameraCharacteristics_jniClassName);
if (android_hardware_camera2_CameraCharacteristics_clazz == nullptr) {
return false;
}
android_hardware_camera2_CaptureResult_clazz = env->FindClass(
android_hardware_camera2_CaptureResult_jniClassName);
if (android_hardware_camera2_CaptureResult_clazz == nullptr) {
return false;
}
return true;
}();
return ok;
}
// Given cameraMetadata, an instance of android.hardware.camera2.CameraMetadata, invokes
// cameraMetadata.getNativeMetadataPtr() and returns it as a CameraMetadata*.
CameraMetadata* CameraMetadata_getNativeMetadataPtr(JNIEnv* env, jobject cameraMetadata) {
if (cameraMetadata == nullptr) {
ALOGE("%s: Invalid Java CameraMetadata object.", __FUNCTION__);
return nullptr;
}
jlong ret = env->CallLongMethod(cameraMetadata,
android_hardware_camera2_CameraMetadata_getNativeMetadataPtr);
return reinterpret_cast<CameraMetadata *>(ret);
}
} // namespace
#endif /* __ANDROID_VNDK__ */
EXPORT
camera_status_t ACameraMetadata_getConstEntry(
const ACameraMetadata* acm, uint32_t tag, ACameraMetadata_const_entry* entry) {
@ -58,7 +120,7 @@ ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
return nullptr;
}
ACameraMetadata* copy = new ACameraMetadata(*src);
copy->incStrong((void*) ACameraMetadata_copy);
copy->incStrong(/*id=*/(void*) ACameraMetadata_copy);
return copy;
}
@ -86,3 +148,34 @@ bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
}
#ifndef __ANDROID_VNDK__
EXPORT
ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata) {
ATRACE_CALL();
const bool ok = InitJni(env);
LOG_ALWAYS_FATAL_IF(!ok, "Failed to find CameraMetadata Java classes.");
if (cameraMetadata == nullptr) {
return nullptr;
}
ACameraMetadata::ACAMERA_METADATA_TYPE type;
if (env->IsInstanceOf(cameraMetadata,
android_hardware_camera2_CameraCharacteristics_clazz)) {
type = ACameraMetadata::ACM_CHARACTERISTICS;
} else if (env->IsInstanceOf(cameraMetadata,
android_hardware_camera2_CaptureResult_clazz)) {
type = ACameraMetadata::ACM_RESULT;
} else {
return nullptr;
}
CameraMetadata* src = CameraMetadata_getNativeMetadataPtr(env,
cameraMetadata);
ACameraMetadata* output = new ACameraMetadata(src, type);
output->incStrong(/*id=*/(void*) ACameraMetadata_fromCameraMetadata);
return output;
}
#endif /* __ANDROID_VNDK__ */

@ -28,7 +28,37 @@ using namespace android;
* ACameraMetadata Implementation
*/
ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
mData(buffer), mType(type) {
mData(new CameraMetadata(buffer)),
mOwnsData(true),
mType(type) {
init();
}
ACameraMetadata::ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type) :
mData(cameraMetadata),
mOwnsData(false),
mType(type) {
init();
}
ACameraMetadata::ACameraMetadata(const ACameraMetadata& other) :
mOwnsData(other.mOwnsData),
mType(other.mType) {
if (other.mOwnsData) {
mData = new CameraMetadata(*(other.mData));
} else {
mData = other.mData;
}
}
ACameraMetadata::~ACameraMetadata() {
if (mOwnsData) {
delete mData;
}
}
void
ACameraMetadata::init() {
if (mType == ACM_CHARACTERISTICS) {
filterUnsupportedFeatures();
filterStreamConfigurations();
@ -61,7 +91,7 @@ ACameraMetadata::isNdkSupportedCapability(int32_t capability) {
void
ACameraMetadata::filterUnsupportedFeatures() {
// Hide unsupported capabilities (reprocessing)
camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
camera_metadata_entry entry = mData->find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
if (entry.count == 0 || entry.type != TYPE_BYTE) {
ALOGE("%s: malformed available capability key! count %zu, type %d",
__FUNCTION__, entry.count, entry.type);
@ -80,7 +110,7 @@ ACameraMetadata::filterUnsupportedFeatures() {
}
}
}
mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
mData->update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
}
void
@ -118,7 +148,7 @@ ACameraMetadata::filterDurations(uint32_t tag) {
const int STREAM_WIDTH_OFFSET = 1;
const int STREAM_HEIGHT_OFFSET = 2;
const int STREAM_DURATION_OFFSET = 3;
camera_metadata_entry entry = mData.find(tag);
camera_metadata_entry entry = mData->find(tag);
if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT64) {
ALOGE("%s: malformed duration key %d! count %zu, type %d",
__FUNCTION__, tag, entry.count, entry.type);
@ -194,7 +224,7 @@ ACameraMetadata::filterDurations(uint32_t tag) {
}
}
mData.update(tag, filteredDurations);
mData->update(tag, filteredDurations);
}
void
@ -204,7 +234,7 @@ ACameraMetadata::filterStreamConfigurations() {
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);
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);
@ -234,10 +264,10 @@ ACameraMetadata::filterStreamConfigurations() {
}
if (filteredStreamConfigs.size() > 0) {
mData.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
mData->update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
}
entry = mData.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
entry = mData->find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
if (entry.count > 0 && (entry.count % 4 || entry.type != TYPE_INT32)) {
ALOGE("%s: malformed available depth stream configuration key! count %zu, type %d",
__FUNCTION__, entry.count, entry.type);
@ -270,11 +300,11 @@ ACameraMetadata::filterStreamConfigurations() {
}
if (filteredDepthStreamConfigs.size() > 0) {
mData.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
mData->update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
filteredDepthStreamConfigs);
}
entry = mData.find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
entry = mData->find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
Vector<int32_t> filteredHeicStreamConfigs;
filteredHeicStreamConfigs.setCapacity(entry.count);
@ -297,9 +327,9 @@ ACameraMetadata::filterStreamConfigurations() {
filteredHeicStreamConfigs.push_back(height);
filteredHeicStreamConfigs.push_back(isInput);
}
mData.update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
mData->update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
entry = mData.find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
entry = mData->find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
Vector<int32_t> filteredDynamicDepthStreamConfigs;
filteredDynamicDepthStreamConfigs.setCapacity(entry.count);
@ -322,7 +352,7 @@ ACameraMetadata::filterStreamConfigurations() {
filteredDynamicDepthStreamConfigs.push_back(height);
filteredDynamicDepthStreamConfigs.push_back(isInput);
}
mData.update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
mData->update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
filteredDynamicDepthStreamConfigs);
}
@ -343,7 +373,7 @@ ACameraMetadata::getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry)
Mutex::Autolock _l(mLock);
camera_metadata_ro_entry rawEntry = mData.find(tag);
camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData)->find(tag);
if (rawEntry.count == 0) {
ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
return ACAMERA_ERROR_METADATA_NOT_FOUND;
@ -390,9 +420,9 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,
/*out*/const uint32_t** tags) const {
Mutex::Autolock _l(mLock);
if (mTags.size() == 0) {
size_t entry_count = mData.entryCount();
size_t entry_count = mData->entryCount();
mTags.setCapacity(entry_count);
const camera_metadata_t* rawMetadata = mData.getAndLock();
const camera_metadata_t* rawMetadata = mData->getAndLock();
for (size_t i = 0; i < entry_count; i++) {
camera_metadata_ro_entry_t entry;
int ret = get_camera_metadata_ro_entry(rawMetadata, i, &entry);
@ -405,7 +435,7 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,
mTags.push_back(entry.tag);
}
}
mData.unlock(rawMetadata);
mData->unlock(rawMetadata);
}
*numTags = mTags.size();
@ -415,7 +445,7 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,
const CameraMetadata&
ACameraMetadata::getInternalData() const {
return mData;
return (*mData);
}
bool

@ -36,8 +36,8 @@ using CameraMetadata = android::hardware::camera::common::V1_0::helper::CameraMe
using namespace android;
/**
* ACameraMetadata opaque struct definition
* Leave outside of android namespace because it's NDK struct
* ACameraMetadata is an opaque struct definition.
* It is intentionally left outside of the android namespace because it's NDK struct.
*/
struct ACameraMetadata : public RefBase {
public:
@ -47,11 +47,20 @@ struct ACameraMetadata : public RefBase {
ACM_RESULT, // Read only
} ACAMERA_METADATA_TYPE;
// Takes ownership of pass-in buffer
ACameraMetadata(camera_metadata_t *buffer, ACAMERA_METADATA_TYPE type);
// Clone
ACameraMetadata(const ACameraMetadata& other) :
mData(other.mData), mType(other.mType) {};
// Constructs a ACameraMetadata that takes ownership of `buffer`.
ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type);
// Constructs a ACameraMetadata that is a view of `cameraMetadata`.
// `cameraMetadata` will not be deleted by ~ACameraMetadata().
ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type);
// Copy constructor.
//
// If `other` owns its CameraMetadata, then makes a deep copy.
// Otherwise, the new instance is also a view of the same data.
ACameraMetadata(const ACameraMetadata& other);
~ACameraMetadata();
camera_status_t getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const;
@ -70,6 +79,9 @@ struct ACameraMetadata : public RefBase {
private:
// Common code called by constructors.
void init();
// This function does not check whether the capability passed to it is valid.
// The caller must make sure that it is.
bool isNdkSupportedCapability(const int32_t capability);
@ -95,11 +107,11 @@ struct ACameraMetadata : public RefBase {
status_t ret = OK;
if (count == 0 && data == nullptr) {
ret = mData.erase(tag);
ret = mData->erase(tag);
} else {
// Here we have to use reinterpret_cast because the NDK data type is
// exact copy of internal data type but they do not inherit from each other
ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
ret = mData->update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
}
if (ret == OK) {
@ -110,10 +122,14 @@ struct ACameraMetadata : public RefBase {
}
}
// guard access of public APIs: get/update/getTags
mutable Mutex mLock;
CameraMetadata mData;
mutable Vector<uint32_t> mTags; // updated in getTags, cleared by update
// Guard access of public APIs: get/update/getTags.
mutable Mutex mLock;
CameraMetadata* mData;
// If true, has ownership of mData. Otherwise, mData is a view of an external instance.
bool mOwnsData;
mutable Vector<uint32_t> mTags; // Updated by `getTags()`, cleared by `update()`.
const ACAMERA_METADATA_TYPE mType;
static std::unordered_set<uint32_t> sSystemTags;

@ -39,6 +39,12 @@
#include <stdint.h>
#include <sys/cdefs.h>
#ifndef __ANDROID_VNDK__
#if __ANDROID_API__ >= 30
#include "jni.h"
#endif /* __ANDROID_API__ >= 30 */
#endif /* __ANDROID_VNDK__ */
#include "NdkCameraError.h"
#include "NdkCameraMetadataTags.h"
@ -255,8 +261,40 @@ bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
#endif /* __ANDROID_API__ >= 29 */
#ifndef __ANDROID_VNDK__
#if __ANDROID_API__ >= 30
/**
* Return a {@link ACameraMetadata} that references the same data as
* {@link cameraMetadata}, which is an instance of
* {@link android.hardware.camera2.CameraMetadata} (e.g., a
* {@link android.hardware.camera2.CameraCharacteristics} or
* {@link android.hardware.camera2.CaptureResult}).
*
* <p>The returned ACameraMetadata must be freed by the application by {@link ACameraMetadata_free}
* after application is done using it.</p>
*
* <p>This function does not affect the lifetime of {@link cameraMetadata}. Attempting to use the
* returned ACameraMetadata object after {@link cameraMetadata} has been garbage collected is
* unsafe. To manage the lifetime beyond the current JNI function call, use
* {@code env->NewGlobalRef()} and {@code env->DeleteGlobalRef()}.
*
* @param env the JNI environment.
* @param cameraMetadata the source {@link android.hardware.camera2.CameraMetadata} from which the
* returned {@link ACameraMetadata} is a view.
*
* @return a valid ACameraMetadata pointer or NULL if {@link cameraMetadata} is null or not a valid
* instance of {@link android.hardware.camera2.CameraMetadata}.
*
*/
ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata)
__INTRODUCED_IN(30);
#endif /* __ANDROID_API__ >= 30 */
#endif /* __ANDROID_VNDK__ */
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_H */
/** @} */
/** @} */

@ -31,6 +31,7 @@ LIBCAMERA2NDK {
ACameraMetadata_getAllTags;
ACameraMetadata_getConstEntry;
ACameraMetadata_isLogicalMultiCamera; # introduced=29
ACameraMetadata_fromCameraMetadata; # introduced=30
ACameraOutputTarget_create;
ACameraOutputTarget_free;
ACaptureRequest_addTarget;

Loading…
Cancel
Save