Camera: Import gralloc buffers before metadata queries

Raw buffer handles do not support metadata queries and need
to be imported first.
Additionally map the result buffer ids to the inflight
buffers and queue the maximum amount of inflight buffers
as advertised by Hal. Since we will be streaming a set
of buffers, use an appropriate preview size.

Bug: 237576060
Test: adb shell
/data/nativetest64/VtsAidlHalCameraProvider_TargetTest/VtsAidlHalCameraProvider_TargetTest
--gtest_filter=PerInstance/CameraAidlTest.process10BitDynamicRangeRequest/0_android_hardware_camera_provider_ICameraProvider_internal_0

Change-Id: Id854c2a8d1588a151240d1b32197dbace7e1a057
This commit is contained in:
Emilian Peev
2022-07-28 16:37:40 -07:00
parent a71fffd754
commit dda1eb771c
6 changed files with 120 additions and 59 deletions

View File

@@ -18,6 +18,7 @@
#include "HandleImporter.h"
#include <gralloctypes/Gralloc4.h>
#include "aidl/android/hardware/graphics/common/Smpte2086.h"
#include <log/log.h>
namespace android {
@@ -30,6 +31,7 @@ namespace helper {
using aidl::android::hardware::graphics::common::PlaneLayout;
using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
using aidl::android::hardware::graphics::common::Smpte2086;
using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
@@ -127,16 +129,35 @@ YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_
bool isMetadataPesent(const sp<IMapperV4> mapper, const buffer_handle_t& buf,
MetadataType metadataType) {
auto buffer = const_cast<native_handle_t*>(buf);
mapper->get(buffer, metadataType, [] (const auto& tmpError,
bool ret = false;
hidl_vec<uint8_t> vec;
mapper->get(buffer, metadataType, [&] (const auto& tmpError,
const auto& tmpMetadata) {
if (tmpError == MapperErrorV4::NONE) {
return tmpMetadata.size() > 0;
vec = tmpMetadata;
} else {
ALOGE("%s: failed to get metadata %d!", __FUNCTION__, tmpError);
return false;
}});
return false;
if (vec.size() > 0) {
if (metadataType == gralloc4::MetadataType_Smpte2086){
std::optional<Smpte2086> realSmpte2086;
gralloc4::decodeSmpte2086(vec, &realSmpte2086);
ret = realSmpte2086.has_value();
} else if (metadataType == gralloc4::MetadataType_Smpte2094_10) {
std::optional<std::vector<uint8_t>> realSmpte2094_10;
gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10);
ret = realSmpte2094_10.has_value();
} else if (metadataType == gralloc4::MetadataType_Smpte2094_40) {
std::optional<std::vector<uint8_t>> realSmpte2094_40;
gralloc4::decodeSmpte2094_40(vec, &realSmpte2094_40);
ret = realSmpte2094_40.has_value();
} else {
ALOGE("%s: Unknown metadata type!", __FUNCTION__);
}
}
return ret;
}
std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {

View File

@@ -1739,6 +1739,10 @@ TEST_P(CameraAidlTest, processUltraHighResolutionRequest) {
std::list<PixelFormat> pixelFormats = {PixelFormat::YCBCR_420_888, PixelFormat::RAW16};
for (PixelFormat format : pixelFormats) {
previewStream.usage =
static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
GRALLOC1_CONSUMER_USAGE_CPU_READ);
previewStream.dataSpace = Dataspace::UNKNOWN;
configureStreams(name, mProvider, format, &mSession, &previewStream, &halStreams,
&supportsPartialResults, &partialResultCount, &useHalBufManager, &cb,
0, /*maxResolution*/ true);
@@ -1843,7 +1847,6 @@ TEST_P(CameraAidlTest, processUltraHighResolutionRequest) {
TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
int64_t bufferId = 1;
int32_t frameNumber = 1;
CameraMetadata settings;
for (const auto& name : cameraDeviceNames) {
@@ -1866,7 +1869,7 @@ TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
CameraMetadata req;
android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
ndk::ScopedAStatus ret =
mSession->constructDefaultRequestSettings(RequestTemplate::STILL_CAPTURE, &req);
mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &req);
ASSERT_TRUE(ret.isOk());
const camera_metadata_t* metadata =
@@ -1896,6 +1899,10 @@ TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
Stream previewStream;
std::shared_ptr<DeviceCb> cb;
for (const auto& profile : profileList) {
previewStream.usage =
static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
&previewStream, &halStreams, &supportsPartialResults,
&partialResultCount, &useHalBufManager, &cb, 0,
@@ -1916,63 +1923,75 @@ TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
// Don't use the queue onwards.
}
std::vector<buffer_handle_t> graphicBuffers;
graphicBuffers.reserve(halStreams.size());
mInflightMap.clear();
// Stream as long as needed to fill the Hal inflight queue
std::vector<CaptureRequest> requests(halStreams[0].maxBuffers);
std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
partialResultCount, std::unordered_set<std::string>(), resultQueue);
for (int32_t frameNumber = 0; frameNumber < requests.size(); frameNumber++) {
std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
partialResultCount, std::unordered_set<std::string>(), resultQueue);
std::vector<CaptureRequest> requests(1);
CaptureRequest& request = requests[0];
std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
outputBuffers.resize(halStreams.size());
CaptureRequest& request = requests[frameNumber];
std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
outputBuffers.resize(halStreams.size());
size_t k = 0;
for (const auto& halStream : halStreams) {
buffer_handle_t buffer_handle;
if (useHalBufManager) {
outputBuffers[k] = {halStream.id, 0,
NativeHandle(), BufferStatus::OK,
NativeHandle(), NativeHandle()};
} else {
allocateGraphicBuffer(previewStream.width, previewStream.height,
android_convertGralloc1To0Usage(
static_cast<uint64_t>(halStream.producerUsage),
static_cast<uint64_t>(halStream.consumerUsage)),
halStream.overrideFormat, &buffer_handle);
size_t k = 0;
inflightReq->mOutstandingBufferIds.resize(halStreams.size());
std::vector<buffer_handle_t> graphicBuffers;
graphicBuffers.reserve(halStreams.size());
graphicBuffers.push_back(buffer_handle);
outputBuffers[k] = {
halStream.id, bufferId, android::makeToAidl(buffer_handle),
BufferStatus::OK, NativeHandle(), NativeHandle()};
bufferId++;
for (const auto& halStream : halStreams) {
buffer_handle_t buffer_handle;
if (useHalBufManager) {
outputBuffers[k] = {halStream.id, 0,
NativeHandle(), BufferStatus::OK,
NativeHandle(), NativeHandle()};
} else {
auto usage = android_convertGralloc1To0Usage(
static_cast<uint64_t>(halStream.producerUsage),
static_cast<uint64_t>(halStream.consumerUsage));
allocateGraphicBuffer(previewStream.width, previewStream.height, usage,
halStream.overrideFormat, &buffer_handle);
inflightReq->mOutstandingBufferIds[halStream.id][bufferId] = buffer_handle;
graphicBuffers.push_back(buffer_handle);
outputBuffers[k] = {halStream.id, bufferId,
android::makeToAidl(buffer_handle), BufferStatus::OK, NativeHandle(),
NativeHandle()};
bufferId++;
}
k++;
}
k++;
}
request.inputBuffer = {
-1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
request.frameNumber = frameNumber;
request.fmqSettingsSize = 0;
request.settings = settings;
request.inputWidth = 0;
request.inputHeight = 0;
request.inputBuffer = {
-1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
request.frameNumber = frameNumber;
request.fmqSettingsSize = 0;
request.settings = settings;
request.inputWidth = 0;
request.inputHeight = 0;
{
std::unique_lock<std::mutex> l(mLock);
mInflightMap[frameNumber] = inflightReq;
}
{
std::unique_lock<std::mutex> l(mLock);
mInflightMap.clear();
mInflightMap[frameNumber] = inflightReq;
}
int32_t numRequestProcessed = 0;
std::vector<BufferCache> cachesToRemove;
ndk::ScopedAStatus returnStatus =
mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
ASSERT_TRUE(returnStatus.isOk());
ASSERT_EQ(numRequestProcessed, 1u);
ASSERT_EQ(numRequestProcessed, requests.size());
{
returnStatus = mSession->repeatingRequestEnd(requests.size() - 1,
std::vector<int32_t> {halStreams[0].id});
ASSERT_TRUE(returnStatus.isOk());
for (int32_t frameNumber = 0; frameNumber < requests.size(); frameNumber++) {
const auto& inflightReq = mInflightMap[frameNumber];
std::unique_lock<std::mutex> l(mLock);
while (!inflightReq->errorCodeValid &&
((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
@@ -1985,6 +2004,7 @@ TEST_P(CameraAidlTest, process10BitDynamicRangeRequest) {
ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
verify10BitMetadata(mHandleImporter, *inflightReq, profile);
}
if (useHalBufManager) {
std::vector<int32_t> streamIds(halStreams.size());
for (size_t i = 0; i < streamIds.size(); i++) {

View File

@@ -2639,8 +2639,20 @@ void CameraAidlTest::configureStreams(const std::string& name,
outputStreams.clear();
Size maxSize;
auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution);
ASSERT_EQ(Status::OK, rc);
if (maxResolution) {
auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution);
ASSERT_EQ(Status::OK, rc);
} else {
AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
static_cast<int32_t>(format)};
auto rc = getAvailableOutputStreams(staticMeta, outputStreams, &previewThreshold);
ASSERT_EQ(Status::OK, rc);
ASSERT_FALSE(outputStreams.empty());
maxSize.width = outputStreams[0].width;
maxSize.height = outputStreams[0].height;
}
std::vector<Stream> streams(1);
streams[0] = {0,
@@ -2648,9 +2660,8 @@ void CameraAidlTest::configureStreams(const std::string& name,
maxSize.width,
maxSize.height,
format,
static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(
GRALLOC1_CONSUMER_USAGE_CPU_READ),
Dataspace::UNKNOWN,
previewStream->usage,
previewStream->dataSpace,
StreamRotation::ROTATION_0,
"",
0,
@@ -2736,7 +2747,8 @@ void CameraAidlTest::verify10BitMetadata(
HandleImporter& importer, const InFlightRequest& request,
aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap
profile) {
for (const auto& b : request.resultOutputBuffers) {
for (auto b : request.resultOutputBuffers) {
importer.importBuffer(b.buffer.buffer);
bool smpte2086Present = importer.isSmpte2086Present(b.buffer.buffer);
bool smpte2094_10Present = importer.isSmpte2094_10Present(b.buffer.buffer);
bool smpte2094_40Present = importer.isSmpte2094_40Present(b.buffer.buffer);
@@ -2753,7 +2765,6 @@ void CameraAidlTest::verify10BitMetadata(
ASSERT_FALSE(smpte2094_40Present);
break;
case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
ASSERT_FALSE(smpte2086Present);
ASSERT_FALSE(smpte2094_10Present);
ASSERT_TRUE(smpte2094_40Present);
break;
@@ -2774,6 +2785,7 @@ void CameraAidlTest::verify10BitMetadata(
profile);
ADD_FAILURE();
}
importer.freeBuffer(b.buffer.buffer);
}
}

View File

@@ -399,6 +399,10 @@ class CameraAidlTest : public ::testing::TestWithParam<std::string> {
// Result metadata
::android::hardware::camera::common::V1_0::helper::CameraMetadata collectedResult;
// Inflight buffers
using OutstandingBuffers = std::unordered_map<uint64_t, buffer_handle_t>;
std::vector<OutstandingBuffers> mOutstandingBufferIds;
// A copy-able StreamBuffer using buffer_handle_t instead of AIDLs NativeHandle
struct NativeStreamBuffer {
int32_t streamId;

View File

@@ -155,7 +155,7 @@ ScopedAStatus DeviceCb::requestStreamBuffers(const std::vector<BufferRequest>& b
BufferStatus::OK, NativeHandle(), NativeHandle(),
};
mOutstandingBufferIds[idx][mNextBufferId++] = ::android::dupToAidl(handle);
mOutstandingBufferIds[idx][mNextBufferId++] = handle;
}
atLeastOneStreamOk = true;
bufRets[i].streamId = stream.id;
@@ -427,9 +427,13 @@ bool DeviceCb::processCaptureResultLocked(
}
CameraAidlTest::InFlightRequest::StreamBufferAndTimestamp streamBufferAndTimestamp;
auto outstandingBuffers = mUseHalBufManager ? mOutstandingBufferIds :
request->mOutstandingBufferIds;
auto outputBuffer = outstandingBuffers.empty() ? ::android::makeFromAidl(buffer.buffer) :
outstandingBuffers[buffer.streamId][buffer.bufferId];
streamBufferAndTimestamp.buffer = {buffer.streamId,
buffer.bufferId,
::android::makeFromAidl(buffer.buffer),
outputBuffer,
buffer.status,
::android::makeFromAidl(buffer.acquireFence),
::android::makeFromAidl(buffer.releaseFence)};

View File

@@ -73,7 +73,7 @@ class DeviceCb : public BnCameraDeviceCallback {
std::vector<Stream> mStreams;
std::vector<HalStream> mHalStreams;
int64_t mNextBufferId = 1;
using OutstandingBuffers = std::unordered_map<uint64_t, NativeHandle>;
using OutstandingBuffers = std::unordered_map<uint64_t, buffer_handle_t>;
// size == mStreams.size(). Tracking each streams outstanding buffers
std::vector<OutstandingBuffers> mOutstandingBufferIds;
std::condition_variable mFlushedCondition;