Camera: Add stream use case API

- Add availableStreamUseCase static metadata tag
- Add STREAM_USE_CASE camera capability
- Add useCase flag in camera stream interface

Test: atest VtsHalCameraProviderV2_4TargetTest
Bug: 200307880
Change-Id: I4e473edcb52a97fa0e1b27cf94603cf9f9984f82
This commit is contained in:
Shuzhen Wang 2021-12-14 20:12:08 -08:00
parent 1bbd78efcd
commit 7267abff25
5 changed files with 234 additions and 14 deletions

View file

@ -113,7 +113,8 @@ interface ICameraDevice extends @3.7::ICameraDevice {
*
* Identical to @3.7::ICameraDevice.isStreamCombinationSupported, except
* that it takes a @3.8::StreamConfiguration parameter, which could contain
* additional information about a specific 10-bit dynamic range profile.
* additional information about a specific 10-bit dynamic range profile or
* stream use case.
*
*/
isStreamCombinationSupported_3_8(StreamConfiguration streams)

View file

@ -35,6 +35,8 @@ interface ICameraDeviceSession extends @3.7::ICameraDeviceSession {
*
* - The requestedConfiguration allows the camera framework to configure
* 10-bit dynamic range profile.
* - The requestedConfiguration allows the camera framework to configure
* stream use cases.
*
* @return status Status code for the operation, one of:
* OK:
@ -61,6 +63,7 @@ interface ICameraDeviceSession extends @3.7::ICameraDeviceSession {
* input stream.
* - Invalid combination between a 10-bit dynamic range profile
* and none impl. defined 8-bit format for a particular stream.
* - Unsupported stream use case
* The camera service cannot filter out all possible illegal stream
* configurations, since some devices may support more simultaneous
* streams or larger stream resolutions than the minimum required

View file

@ -17,6 +17,7 @@
package android.hardware.camera.device@3.8;
import @3.2::ErrorMsg;
import @3.2::CameraMetadata;
import @3.2::MsgType;
import @3.2::ShutterMsg;
import @3.2::CameraMetadata;
@ -24,6 +25,7 @@ import @3.2::StreamConfigurationMode;
import @3.7::Stream;
import android.hardware.camera.metadata@3.8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
import android.hardware.camera.metadata@3.8::CameraMetadataEnumAndroidScalerAvailableStreamUseCases;
/**
* ShutterMsg:
@ -80,7 +82,8 @@ struct NotifyMsg {
* by the framework by its buffer resolution and format, and additionally by the
* HAL with the gralloc usage flags and the maximum in-flight buffer count.
*
* This version extends the @3.7 Stream with the dynamic range profile field.
* This version extends the @3.7 Stream with the dynamic range profile and the
* stream use case field.
*/
struct Stream {
/**
@ -98,6 +101,25 @@ struct Stream {
*
*/
CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap dynamicRangeProfile;
/**
* The stream use case describing the stream's purpose
*
* This flag provides the camera device a hint on what user scenario this
* stream is intended for. With this flag, the camera device can optimize
* camera pipeline parameters, such as tuning, sensor mode, and ISP settings,
* for the intended use case.
*
* When this field is set to DEFAULT, the camera device should behave in
* the same way as in previous HAL versions, and optimize the camera pipeline
* based on stream format, data space, usage flag, and other stream properties.
*
* The HAL reports supported stream use cases in
* ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES. If the HAL doesn't support
* setting stream use cases, the camera framework leaves this field as
* DEFAULT.
*/
CameraMetadataEnumAndroidScalerAvailableStreamUseCases useCase;
};
/**
@ -115,7 +137,6 @@ struct StreamConfiguration {
/**
* The definition of operation mode from prior version.
*
*/
@3.2::StreamConfigurationMode operationMode;
@ -130,17 +151,7 @@ struct StreamConfiguration {
uint32_t streamConfigCounter;
/**
* If an input stream is configured, whether the input stream is expected to
* receive variable resolution images.
*
* This flag can only be set to true if the camera device supports
* multi-resolution input streams by advertising input stream configurations in
* physicalCameraMultiResolutionStreamConfigurations in its physical cameras'
* characteristics.
*
* When this flag is set to true, the input stream's width and height can be
* any one of the supported multi-resolution input stream sizes.
* The definition of multi-resolution input image flag from prior version.
*/
bool multiResolutionInputImage;
};

View file

@ -68,6 +68,14 @@ enum CameraMetadataTag : @3.7::CameraMetadataTag {
ANDROID_REQUEST_END_3_8,
/** android.scaler.availableStreamUseCases [static, enum[], public]
*
* <p>The stream use cases supported by this camera device.</p>
*/
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES = android.hardware.camera.metadata@3.6::CameraMetadataTag:ANDROID_SCALER_END_3_6,
ANDROID_SCALER_END_3_8,
};
/*
@ -88,6 +96,7 @@ enum CameraMetadataEnumAndroidControlVideoStabilizationMode :
enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
@3.6::CameraMetadataEnumAndroidRequestAvailableCapabilities {
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE,
};
/** android.request.availableDynamicRangeProfilesMap enumeration values
@ -129,3 +138,17 @@ enum CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations :
ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8
= 0x9,
};
/** android.scaler.availableStreamUseCases enumeration values
* @see ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES
*/
enum CameraMetadataEnumAndroidScalerAvailableStreamUseCases : uint32_t {
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT = 0x0,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW = 0x1,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE = 0x2,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD = 0x3,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL
= 0x4,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL = 0x5,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START = 0x10000,
};

View file

@ -44,6 +44,7 @@
#include <android/hardware/camera/device/3.7/ICameraDevice.h>
#include <android/hardware/camera/device/3.8/ICameraDevice.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
@ -135,6 +136,8 @@ using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
using ::android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
using ::android::hardware::camera::metadata::V3_8::
CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
using ::android::hardware::camera::metadata::V3_8::
CameraMetadataEnumAndroidScalerAvailableStreamUseCases;
using ::android::hardware::camera::provider::V2_4::ICameraProvider;
using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
@ -198,6 +201,15 @@ enum SystemCameraKind {
HIDDEN_SECURE_CAMERA
};
const static std::vector<int32_t> kMandatoryUseCases = {
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL
};
namespace {
// "device@<version>/legacy/<id>"
const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
@ -879,6 +891,7 @@ public:
void verifyCameraCharacteristics(Status status, const CameraMetadata& chars);
void verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata);
void verifyZoomCharacteristics(const camera_metadata_t* metadata);
void verifyStreamUseCaseCharacteristics(const camera_metadata_t* metadata);
void verifyRecommendedConfigs(const CameraMetadata& metadata);
void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion);
void verifyMonochromeCameraResult(
@ -6879,6 +6892,134 @@ TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) {
}
}
// Verify that valid stream use cases can be configured successfully, and invalid use cases
// fail stream configuration.
TEST_P(CameraHidlTest, configureStreamsUseCases) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
for (const auto& name : cameraDeviceNames) {
int deviceVersion = getCameraDeviceVersion(name, mProviderType);
if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_8) {
continue;
}
camera_metadata_t* staticMeta;
Return<void> ret;
sp<ICameraDeviceSession> session;
sp<device::V3_3::ICameraDeviceSession> session3_3;
sp<device::V3_4::ICameraDeviceSession> session3_4;
sp<device::V3_5::ICameraDeviceSession> session3_5;
sp<device::V3_6::ICameraDeviceSession> session3_6;
sp<device::V3_7::ICameraDeviceSession> session3_7;
sp<device::V3_8::ICameraDeviceSession> session3_8;
sp<device::V3_2::ICameraDevice> cameraDevice;
sp<device::V3_5::ICameraDevice> cameraDevice3_5;
sp<device::V3_7::ICameraDevice> cameraDevice3_7;
sp<device::V3_8::ICameraDevice> cameraDevice3_8;
openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
&cameraDevice /*out*/);
castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
&session3_6, &session3_7, &session3_8);
ASSERT_NE(nullptr, session3_8);
castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
&cameraDevice3_8);
ASSERT_NE(nullptr, cameraDevice3_8);
// Check if camera support depth only
if (isDepthOnly(staticMeta)) {
free_camera_metadata(staticMeta);
ret = session->close();
ASSERT_TRUE(ret.isOk());
continue;
}
std::vector<AvailableStream> outputPreviewStreams;
AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputPreviewStreams,
&previewThreshold));
ASSERT_NE(0u, outputPreviewStreams.size());
// Combine valid and invalid stream use cases
std::vector<int32_t> useCases(kMandatoryUseCases);
useCases.push_back(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL + 1);
std::vector<int32_t> supportedUseCases;
camera_metadata_ro_entry entry;
auto retcode = find_camera_metadata_ro_entry(staticMeta,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES, &entry);
if ((0 == retcode) && (entry.count > 0)) {
supportedUseCases.insert(supportedUseCases.end(), entry.data.i32,
entry.data.i32 + entry.count);
} else {
supportedUseCases.push_back(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
}
free_camera_metadata(staticMeta);
::android::hardware::hidl_vec<V3_8::Stream> streams3_8(1);
streams3_8[0].v3_7.groupId = -1;
streams3_8[0].v3_7.sensorPixelModesUsed = {
CameraMetadataEnumAndroidSensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
streams3_8[0].v3_7.v3_4.bufferSize = 0;
streams3_8[0].v3_7.v3_4.v3_2.id = 0;
streams3_8[0].v3_7.v3_4.v3_2.streamType = StreamType::OUTPUT;
streams3_8[0].v3_7.v3_4.v3_2.width = static_cast<uint32_t>(outputPreviewStreams[0].width);
streams3_8[0].v3_7.v3_4.v3_2.height = static_cast<uint32_t>(outputPreviewStreams[0].height);
streams3_8[0].v3_7.v3_4.v3_2.format =
static_cast<PixelFormat>(outputPreviewStreams[0].format);
streams3_8[0].v3_7.v3_4.v3_2.usage = GRALLOC1_CONSUMER_USAGE_CPU_READ;
streams3_8[0].v3_7.v3_4.v3_2.dataSpace = 0;
streams3_8[0].v3_7.v3_4.v3_2.rotation = StreamRotation::ROTATION_0;
streams3_8[0].dynamicRangeProfile =
static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
uint32_t streamConfigCounter = 0;
::android::hardware::camera::device::V3_8::StreamConfiguration config3_8;
RequestTemplate reqTemplate = RequestTemplate::STILL_CAPTURE;
ret = session3_8->constructDefaultRequestSettings(reqTemplate,
[&config3_8](auto status, const auto& req) {
ASSERT_EQ(Status::OK, status);
config3_8.sessionParams = req;
});
ASSERT_TRUE(ret.isOk());
for (int32_t useCase : useCases) {
bool useCaseSupported = std::find(supportedUseCases.begin(),
supportedUseCases.end(), useCase) != supportedUseCases.end();
streams3_8[0].useCase =
static_cast<CameraMetadataEnumAndroidScalerAvailableStreamUseCases>(useCase);
config3_8.streams = streams3_8;
config3_8.operationMode = StreamConfigurationMode::NORMAL_MODE;
config3_8.streamConfigCounter = streamConfigCounter;
config3_8.multiResolutionInputImage = false;
ret = cameraDevice3_8->isStreamCombinationSupported_3_8(
config3_8, [&useCaseSupported](Status s, bool combStatus) {
ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
if (Status::OK == s) {
ASSERT_EQ(combStatus, useCaseSupported);
}
});
ASSERT_TRUE(ret.isOk());
ret = session3_8->configureStreams_3_8(
config3_8,
[&](Status s, device::V3_6::HalStreamConfiguration halConfig) {
if (useCaseSupported) {
ASSERT_EQ(Status::OK, s);
ASSERT_EQ(1u, halConfig.streams.size());
} else {
ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
}
});
ASSERT_TRUE(ret.isOk());
}
ret = session3_8->close();
ASSERT_TRUE(ret.isOk());
}
}
// Retrieve all valid output stream resolutions from the camera
// static characteristics.
Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta,
@ -9042,6 +9183,7 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta
verifyExtendedSceneModeCharacteristics(metadata);
verifyZoomCharacteristics(metadata);
verifyStreamUseCaseCharacteristics(metadata);
}
void CameraHidlTest::verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata) {
@ -9272,6 +9414,46 @@ void CameraHidlTest::verifyZoomCharacteristics(const camera_metadata_t* metadata
}
}
void CameraHidlTest::verifyStreamUseCaseCharacteristics(const camera_metadata_t* metadata) {
camera_metadata_ro_entry entry;
// Check capabilities
int retcode = find_camera_metadata_ro_entry(metadata,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry);
bool hasStreamUseCaseCap = false;
if ((0 == retcode) && (entry.count > 0)) {
if (std::find(entry.data.u8, entry.data.u8 + entry.count,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE) !=
entry.data.u8 + entry.count) {
hasStreamUseCaseCap = true;
}
}
bool supportMandatoryUseCases = false;
retcode = find_camera_metadata_ro_entry(metadata,
ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES, &entry);
if ((0 == retcode) && (entry.count > 0)) {
supportMandatoryUseCases = true;
for (size_t i = 0; i < kMandatoryUseCases.size(); i++) {
if (std::find(entry.data.i32, entry.data.i32 + entry.count, kMandatoryUseCases[i])
== entry.data.i32 + entry.count) {
supportMandatoryUseCases = false;
break;
}
}
bool supportDefaultUseCase = false;
for (size_t i = 0; i < entry.count; i++) {
if (entry.data.i32[i] == ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
supportDefaultUseCase = true;
}
ASSERT_TRUE(entry.data.i32[i] <= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL ||
entry.data.i32[i] >= ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START);
}
ASSERT_TRUE(supportDefaultUseCase);
}
ASSERT_EQ(hasStreamUseCaseCap, supportMandatoryUseCases);
}
void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars,
int deviceVersion) {
const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();