From 8935df624ed97fbb427d5fb779f0587e8669f507 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Mon, 1 Sep 2025 11:04:02 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=B8=E6=9C=BA=E6=A1=86=E6=9E=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=94=AF=E6=8C=81=E9=AB=98=E6=80=A7=E8=83=BD=E6=8B=8D?= =?UTF-8?q?=E7=85=A7=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhanglei --- .../js/camera_napi/src/input/camera_napi.cpp | 2 + .../src/output/photo_output_napi.cpp | 54 ++++++- .../base/src/ability/camera_ability_const.cpp | 1 + .../camera/base/src/output/photo_output.cpp | 105 ++++++++++++ .../base/src/session/capture_session.cpp | 10 ++ .../src/camera_photo_output_unittest.cpp | 76 +++++++++ .../output/src/photo_output_unittest.cpp | 150 ++++++++++++++++++ .../native/ndk/impl/photo_output_impl.cpp | 26 ++- .../native/ndk/impl/photo_output_impl.h | 4 + frameworks/native/ndk/photo_output.cpp | 19 +++ .../include/ability/camera_ability_const.h | 1 + .../camera/include/output/photo_output.h | 12 ++ .../camera/include/session/capture_session.h | 1 + .../camera_napi/include/input/camera_napi.h | 5 + .../include/output/photo_output_napi.h | 2 + .../kits/native/include/camera/camera.h | 17 ++ .../kits/native/include/camera/photo_output.h | 29 ++++ .../photo_output_fuzzer.cpp | 5 + 18 files changed, 514 insertions(+), 5 deletions(-) diff --git a/frameworks/js/camera_napi/src/input/camera_napi.cpp b/frameworks/js/camera_napi/src/input/camera_napi.cpp index 4780e2a83..37484c40b 100644 --- a/frameworks/js/camera_napi/src/input/camera_napi.cpp +++ b/frameworks/js/camera_napi/src/input/camera_napi.cpp @@ -192,6 +192,8 @@ napi_value CameraNapi::Init(napi_env env, napi_value exports) CreateObjectWithMap(env, "LightStatus", mapLightStatus, g_ignoreRef_)), DECLARE_NAPI_PROPERTY("WhiteBalanceMode", CreateObjectWithMap(env, "WhiteBalanceMode", mapWhiteBalanceMode, g_ignoreRef_)), + DECLARE_NAPI_PROPERTY("PhotoQualityPrioritization", + CreateObjectWithMap(env, "PhotoQualityPrioritization", mapPhotoQualityPrioritization, g_ignoreRef_)), }; status = napi_define_class(env, CAMERA_LIB_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, CameraNapiConstructor, diff --git a/frameworks/js/camera_napi/src/output/photo_output_napi.cpp b/frameworks/js/camera_napi/src/output/photo_output_napi.cpp index 57f11b021..ab0b98d3f 100644 --- a/frameworks/js/camera_napi/src/output/photo_output_napi.cpp +++ b/frameworks/js/camera_napi/src/output/photo_output_napi.cpp @@ -63,7 +63,7 @@ void AsyncCompleteCallback(napi_env env, napi_status status, void* data) photoOutputAsyncContext->funcName.c_str(), photoOutputAsyncContext->status); std::unique_ptr jsContext = std::make_unique(); jsContext->status = photoOutputAsyncContext->status; - + if (!photoOutputAsyncContext->status) { CameraNapiUtils::CreateNapiErrorObject(env, photoOutputAsyncContext->errorCode, photoOutputAsyncContext->errorMsg.c_str(), jsContext); @@ -689,7 +689,9 @@ napi_value PhotoOutputNapi::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("isAutoAigcPhotoSupported", IsAutoAigcPhotoSupported), DECLARE_NAPI_FUNCTION("enableAutoAigcPhoto", EnableAutoAigcPhoto), DECLARE_NAPI_FUNCTION("isOfflineSupported", IsOfflineSupported), - DECLARE_NAPI_FUNCTION("enableOffline", EnableOfflinePhoto) + DECLARE_NAPI_FUNCTION("enableOffline", EnableOfflinePhoto), + DECLARE_NAPI_FUNCTION("isPhotoQualityPrioritizationSupported", IsPhotoQualityPrioritizationSupported), + DECLARE_NAPI_FUNCTION("setPhotoQualityPrioritization", SetPhotoQualityPrioritization) }; status = napi_define_class(env, CAMERA_PHOTO_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, PhotoOutputNapiConstructor, @@ -806,7 +808,7 @@ napi_value PhotoOutputNapi::CreatePhotoOutput(napi_env env, Profile& profile, st MEDIA_ERR_LOG("CreatePhotoOutput call Failed!"); return result; } - + napi_value PhotoOutputNapi::CreatePhotoOutput(napi_env env, std::string surfaceId) { MEDIA_INFO_LOG("CreatePhotoOutput with only surfaceId is called"); @@ -1999,5 +2001,51 @@ napi_value PhotoOutputNapi::EnableOfflinePhoto(napi_env env, napi_callback_info } return result; } + +napi_value PhotoOutputNapi::IsPhotoQualityPrioritizationSupported(napi_env env, napi_callback_info info) +{ + MEDIA_INFO_LOG("PhotoOutputNapi::IsPhotoQualityPrioritizationSupported is called"); + PhotoOutputNapi* photoOutputNapi = nullptr; + int32_t quality = 0; + auto result = CameraNapiUtils::GetUndefinedValue(env); + CameraNapiParamParser jsParamParser(env, info, photoOutputNapi, quality); + if (!jsParamParser.AssertStatus(PARAMETER_ERROR, "parameter occur error")) { + MEDIA_ERR_LOG("PhotoOutputNapi::IsPhotoQualityPrioritizationSupported parse parameter occur error"); + return result; + } + if (photoOutputNapi != nullptr && photoOutputNapi->photoOutput_ != nullptr) { + bool isSupported = false; + int32_t ret = photoOutputNapi->photoOutput_->IsPhotoQualityPrioritizationSupported( + static_cast(quality), isSupported); + CHECK_RETURN_RET(!CameraNapiUtils::CheckError(env, ret), result); + napi_get_boolean(env, isSupported, &result); + } else { + MEDIA_ERR_LOG("PhotoOutputNapi::IsPhotoQualityPrioritizationSupported get native object fail"); + CameraNapiUtils::ThrowError(env, PARAMETER_ERROR, "get native object fail"); + } + return result; +} + +napi_value PhotoOutputNapi::SetPhotoQualityPrioritization(napi_env env, napi_callback_info info) +{ + MEDIA_INFO_LOG("PhotoOutputNapi::SetPhotoQualityPrioritization is called"); + PhotoOutputNapi* photoOutputNapi = nullptr; + int32_t quality = 0; + auto result = CameraNapiUtils::GetUndefinedValue(env); + CameraNapiParamParser jsParamParser(env, info, photoOutputNapi, quality); + if (!jsParamParser.AssertStatus(PARAMETER_ERROR, "parameter occur error")) { + MEDIA_ERR_LOG("PhotoOutputNapi::SetPhotoQualityPrioritization parse parameter occur error"); + return result; + } + if (photoOutputNapi != nullptr && photoOutputNapi->photoOutput_ != nullptr) { + int32_t ret = photoOutputNapi->photoOutput_->SetPhotoQualityPrioritization( + static_cast(quality)); + CHECK_RETURN_RET(!CameraNapiUtils::CheckError(env, ret), result); + } else { + MEDIA_ERR_LOG("PhotoOutputNapi::SetPhotoQualityPrioritization get native object fail"); + CameraNapiUtils::ThrowError(env, PARAMETER_ERROR, "get native object fail"); + } + return result; +} } // namespace CameraStandard } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/camera/base/src/ability/camera_ability_const.cpp b/frameworks/native/camera/base/src/ability/camera_ability_const.cpp index 7bebe1c6d..275756acb 100644 --- a/frameworks/native/camera/base/src/ability/camera_ability_const.cpp +++ b/frameworks/native/camera/base/src/ability/camera_ability_const.cpp @@ -267,5 +267,6 @@ const std::unordered_map {ColorReservationType::COLOR_RESERVATION_TYPE_NONE, OHOS_CAMERA_COLOR_RESERVATION_NONE}, {ColorReservationType::COLOR_RESERVATION_TYPE_PORTRAIT, OHOS_CAMERA_COLOR_RESERVATION_PORTRAIT} }; + } // namespace CameraStandard } // namespace OHOS diff --git a/frameworks/native/camera/base/src/output/photo_output.cpp b/frameworks/native/camera/base/src/output/photo_output.cpp index 6a6316342..b8bf6619e 100644 --- a/frameworks/native/camera/base/src/output/photo_output.cpp +++ b/frameworks/native/camera/base/src/output/photo_output.cpp @@ -361,6 +361,12 @@ PhotoOutput::~PhotoOutput() // LCOV_EXCL_STOP } +const std::unordered_map PhotoOutput::g_photoQualityPrioritizationMap_ = { + {PhotoOutput::PhotoQualityPrioritization::HIGH_QUALITY, OHOS_CAMERA_PHOTO_QUALITY_PRIORITIZATION_HIGH_QUALITY}, + {PhotoOutput::PhotoQualityPrioritization::SPEED, OHOS_CAMERA_PHOTO_QUALITY_PRIORITIZATION_SPEED} +}; + void PhotoOutput::SetNativeSurface(bool isNativeSurface) { MEDIA_INFO_LOG("Enter Into SetNativeSurface %{public}d", isNativeSurface); @@ -1494,5 +1500,104 @@ void PhotoOutput::CreateMediaLibrary(sptr photoProxy, std::str } MEDIA_INFO_LOG("PhotoOutput::CreateMediaLibrary X"); } + +bool PhotoOutput::ParseQualityPrioritization(int32_t modeName, common_metadata_header_t* metadataHeader, + camera_photo_quality_prioritization_t type) +{ + CHECK_RETURN_RET_ELOG(metadataHeader == nullptr, false, + "PhotoOutput ParseQualityPrioritization error!, metadataHeader is nullptr"); + camera_metadata_item_t item; + int result = Camera::FindCameraMetadataItem(metadataHeader, OHOS_ABILITY_PHOTO_QUALITY_PRIORITIZATION, &item); + CHECK_RETURN_RET_ELOG(result != CAM_META_SUCCESS || item.count <= 0, false, + "PhotoOutput ParseQualityPrioritization error!, FindCameraMetadataItem error"); + int32_t* originInfo = item.data.i32; + uint32_t count = item.count; + CHECK_RETURN_RET_ELOG(count == 0 || originInfo == nullptr, false, + "PhotoOutput ParseQualityPrioritization error!, count is less than 2"); + uint32_t i = 0; + uint32_t j = i + STEP_ONE; + bool ret = false; + while (j < count) { + if (originInfo[j] != MODE_END) { + j = j + STEP_TWO; + continue; + } + if (originInfo[j - 1] == TAG_END) { + if (originInfo[i] == modeName) { + ret = IsQualityPrioritizationTypeSupported(originInfo, i + 1, j - 1, static_cast(type)); + break; + } else { + i = j + STEP_ONE; + j = i + STEP_ONE; + } + } else { + j++; + } + } + return ret; +} + +bool PhotoOutput::IsQualityPrioritizationTypeSupported(int32_t* originInfo, uint32_t start, uint32_t end, int32_t type) +{ + CHECK_RETURN_RET_ELOG(originInfo == nullptr, false, + "PhotoOutput IsQualityPrioritizationTypeSupported error!, originInfo is nullptr"); + CHECK_RETURN_RET_ELOG(start >= end, false, + "PhotoOutput IsQualityPrioritizationTypeSupported error!, start is greater than end"); + for (uint32_t i = start; i < end; i++) { + if (originInfo[i] == type) { + return true; + } + } + return false; +} + +int32_t PhotoOutput::IsPhotoQualityPrioritizationSupported(PhotoQualityPrioritization quality, bool &isSupported) +{ + MEDIA_INFO_LOG("PhotoOutput::IsPhotoQualityPrioritizationSupported E"); + auto itr = g_photoQualityPrioritizationMap_.find(quality); + CHECK_RETURN_RET_ELOG(itr == g_photoQualityPrioritizationMap_.end(), + PARAMETER_ERROR, "PhotoOutput IsPhotoQualityPrioritizationSupported error!, unknown quality type"); + auto session = GetSession(); + CHECK_RETURN_RET_ELOG(session == nullptr, SERVICE_FATL_ERROR, + "PhotoOutput IsPhotoQualityPrioritizationSupported error!, session is nullptr"); + auto inputDevice = session->GetInputDevice(); + CHECK_RETURN_RET_ELOG(inputDevice == nullptr, SERVICE_FATL_ERROR, + "PhotoOutput IsPhotoQualityPrioritizationSupported error!, inputDevice is nullptr"); + sptr cameraObj = inputDevice->GetCameraDeviceInfo(); + CHECK_RETURN_RET_ELOG(cameraObj == nullptr, SERVICE_FATL_ERROR, + "PhotoOutput IsPhotoQualityPrioritizationSupported error!, cameraObj is nullptr"); + std::shared_ptr metadata = cameraObj->GetCachedMetadata(); + CHECK_RETURN_RET_ELOG(metadata == nullptr, SERVICE_FATL_ERROR, + "PhotoOutput IsPhotoQualityPrioritizationSupported error!, metadata is nullptr"); + camera_photo_quality_prioritization_t qualityPrioritization = itr->second; + int32_t sessionMode = session->GetMode(); + isSupported = ParseQualityPrioritization(sessionMode, metadata->get(), qualityPrioritization); + return CameraErrorCode::SUCCESS; +} + +int32_t PhotoOutput::SetPhotoQualityPrioritization(PhotoQualityPrioritization quality) +{ + MEDIA_INFO_LOG("PhotoOutput::SetPhotoQualityPrioritization E"); + bool isSupported = false; + int32_t ret = IsPhotoQualityPrioritizationSupported(quality, isSupported); + CHECK_RETURN_RET_ELOG(ret != CameraErrorCode::SUCCESS, ret, + "PhotoOutput SetPhotoQualityPrioritization error!, IsPhotoQualityPrioritizationSupported failed"); + CHECK_RETURN_RET_ELOG(!isSupported, OPERATION_NOT_ALLOWED, + "PhotoOutput SetPhotoQualityPrioritization error!, ParseQualityPrioritization failed"); + auto session = GetSession(); + CHECK_RETURN_RET_ELOG(session == nullptr, SERVICE_FATL_ERROR, + "PhotoOutput SetPhotoQualityPrioritization error!, session is nullptr"); + auto itr = g_photoQualityPrioritizationMap_.find(quality); + CHECK_RETURN_RET_ELOG(itr == g_photoQualityPrioritizationMap_.end(), SERVICE_FATL_ERROR, + "PhotoOutput SetPhotoQualityPrioritization error!, unknown quality type"); + camera_photo_quality_prioritization_t qualityPrioritization = itr->second; + session->LockForControl(); + session->SetPhotoQualityPrioritization(qualityPrioritization); + ret = session->UnlockForControl(); + CHECK_PRINT_ELOG(ret != CameraErrorCode::SUCCESS, + "CaptureSession::SetPhotoQualityPrioritization Failed to UnlockForControl"); + MEDIA_DEBUG_LOG("CaptureSession::SetPhotoQualityPrioritization succeeded"); + return ret; +} } // namespace CameraStandard } // namespace OHOS diff --git a/frameworks/native/camera/base/src/session/capture_session.cpp b/frameworks/native/camera/base/src/session/capture_session.cpp index c47a48875..80a11374b 100644 --- a/frameworks/native/camera/base/src/session/capture_session.cpp +++ b/frameworks/native/camera/base/src/session/capture_session.cpp @@ -5263,5 +5263,15 @@ void CaptureSession::SetMacroStatusCallback(std::shared_ptr return; } +void CaptureSession::SetPhotoQualityPrioritization(camera_photo_quality_prioritization_t quality) +{ + MEDIA_INFO_LOG("CaptureSession::SetPhotoQualityPrioritization quality:%{public}d", quality); + CHECK_RETURN_ELOG(changedMetadata_ == nullptr, + "CaptureSession::SetPhotoQualityPrioritization changedMetadata_ is NULL"); + bool status = AddOrUpdateMetadata(changedMetadata_, OHOS_CONTROL_PHOTO_QUALITY_PRIORITIZATION, &quality, 1); + CHECK_PRINT_ELOG(!status, "CaptureSession::SetPhotoQualityPrioritization Failed to AddOrUpdateMetadata!"); + return; +} + } // namespace CameraStandard } // namespace OHOS diff --git a/frameworks/native/camera/test/unittest/camera_ndk_unittest/camera_ndk_output_test/src/camera_photo_output_unittest.cpp b/frameworks/native/camera/test/unittest/camera_ndk_unittest/camera_ndk_output_test/src/camera_photo_output_unittest.cpp index eaf4d5a61..67d1653df 100644 --- a/frameworks/native/camera/test/unittest/camera_ndk_unittest/camera_ndk_output_test/src/camera_photo_output_unittest.cpp +++ b/frameworks/native/camera/test/unittest/camera_ndk_unittest/camera_ndk_output_test/src/camera_photo_output_unittest.cpp @@ -1659,5 +1659,81 @@ HWTEST_F(CameraPhotoOutputUnitTest, camera_photo_output_unittest_041, TestSize.L ReleaseImageReceiver(); } +/* + * Feature: Framework + * Function: Test SetPhotoQualityPrioritization + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test SetPhotoQualityPrioritization with abnormal branch + */ +HWTEST_F(CameraPhotoOutputUnitTest, camera_photo_output_unittest_042, TestSize.Level0) +{ + Camera_PhotoQualityPrioritization qualityPrioritization = CAMERA_PHOTO_QUALITY_PRIORITIZATION_SPEED; + Camera_CaptureSession* captureSession = nullptr; + Camera_ErrorCode ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession); + EXPECT_EQ(ret, CAMERA_OK); + ASSERT_NE(captureSession, nullptr); + ret = OH_CaptureSession_SetSessionMode(captureSession, NORMAL_PHOTO); + EXPECT_EQ(ret, CAMERA_OK); + ret = OH_CaptureSession_BeginConfig(captureSession); + EXPECT_EQ(ret, CAMERA_OK); + Camera_Input *cameraInput = nullptr; + ret = OH_CameraManager_CreateCameraInput(cameraManager, cameraDevice, &cameraInput); + EXPECT_EQ(ret, CAMERA_OK); + ASSERT_NE(cameraInput, nullptr); + EXPECT_EQ(OH_CameraInput_Open(cameraInput), CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_AddInput(captureSession, cameraInput), CAMERA_OK); + Camera_PhotoOutput *photoOutput = CreatePhotoOutput(); + ASSERT_NE(photoOutput, nullptr); + ret = OH_CaptureSession_AddPhotoOutput(captureSession, photoOutput); + EXPECT_EQ(ret, CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_CommitConfig(captureSession), CAMERA_OK); + photoOutput = nullptr; + ret = OH_PhotoOutput_SetPhotoQualityPrioritization(photoOutput, qualityPrioritization); + EXPECT_EQ(ret, CAMERA_INVALID_ARGUMENT); + EXPECT_EQ(OH_CameraInput_Release(cameraInput), CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_Release(captureSession), CAMERA_OK); + ReleaseImageReceiver(); +} + +/* + * Feature: Framework + * Function: Test SetPhotoQualityPrioritization + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test SetPhotoQualityPrioritization with abnormal branch + */ +HWTEST_F(CameraPhotoOutputUnitTest, camera_photo_output_unittest_043, TestSize.Level0) +{ + bool isSupported = false; + Camera_PhotoQualityPrioritization qualityPrioritization = CAMERA_PHOTO_QUALITY_PRIORITIZATION_SPEED; + Camera_CaptureSession* captureSession = nullptr; + Camera_ErrorCode ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession); + EXPECT_EQ(ret, CAMERA_OK); + ASSERT_NE(captureSession, nullptr); + ret = OH_CaptureSession_SetSessionMode(captureSession, NORMAL_PHOTO); + EXPECT_EQ(ret, CAMERA_OK); + ret = OH_CaptureSession_BeginConfig(captureSession); + EXPECT_EQ(ret, CAMERA_OK); + Camera_Input *cameraInput = nullptr; + ret = OH_CameraManager_CreateCameraInput(cameraManager, cameraDevice, &cameraInput); + EXPECT_EQ(ret, CAMERA_OK); + ASSERT_NE(cameraInput, nullptr); + EXPECT_EQ(OH_CameraInput_Open(cameraInput), CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_AddInput(captureSession, cameraInput), CAMERA_OK); + Camera_PhotoOutput *photoOutput = CreatePhotoOutput(); + ASSERT_NE(photoOutput, nullptr); + ret = OH_CaptureSession_AddPhotoOutput(captureSession, photoOutput); + EXPECT_EQ(ret, CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_CommitConfig(captureSession), CAMERA_OK); + photoOutput = nullptr; + ret = OH_PhotoOutput_IsPhotoQualityPrioritizationSupported(photoOutput, qualityPrioritization, &isSupported); + EXPECT_EQ(ret, CAMERA_INVALID_ARGUMENT); + EXPECT_EQ(OH_CameraInput_Release(cameraInput), CAMERA_OK); + EXPECT_EQ(OH_CaptureSession_Release(captureSession), CAMERA_OK); + ReleaseImageReceiver(); +} } // CameraStandard } // OHOS \ No newline at end of file diff --git a/frameworks/native/camera/test/unittest/framework_native/output/src/photo_output_unittest.cpp b/frameworks/native/camera/test/unittest/framework_native/output/src/photo_output_unittest.cpp index 9ea8a5333..378000b4f 100644 --- a/frameworks/native/camera/test/unittest/framework_native/output/src/photo_output_unittest.cpp +++ b/frameworks/native/camera/test/unittest/framework_native/output/src/photo_output_unittest.cpp @@ -1955,5 +1955,155 @@ HWTEST_F(CameraPhotoOutputUnit, photo_output_unittest_030, TestSize.Level0) phtOutput->ReportCaptureEnhanceEnabled(str, true, 0); EXPECT_NE(photoOutput, nullptr); } + + +/* + * Feature: Framework + * Function: Test photooutput with IsPhotoQualityPrioritizationSupported + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test photooutput with IsPhotoQualityPrioritizationSupported + */ +HWTEST_F(CameraPhotoOutputUnit, IsPhotoQualityPrioritizationSupported_001, TestSize.Level0) +{ + MEDIA_INFO_LOG("IsPhotoQualityPrioritizationSupported_001: ENTER"); + std::vector> cameras = cameraManager_->GetCameraDeviceListFromServer(); + ASSERT_FALSE(cameras.empty()); + sptr input = cameraManager_->CreateCameraInput(cameras[0]); + ASSERT_NE(input, nullptr); + sptr camInput = (sptr &)input; + camInput->GetCameraDevice()->Open(); + sptr photoOutput = CreatePhotoOutput(); + ASSERT_NE(photoOutput, nullptr); + sptr phtOutput = (sptr&)photoOutput; + + sptr session = cameraManager_->CreateCaptureSession(); + ASSERT_NE(session, nullptr); + EXPECT_EQ(session->BeginConfig(), 0); + EXPECT_EQ(session->AddInput(input), 0); + EXPECT_EQ(session->AddOutput(photoOutput), 0); + std::shared_ptr metadata = + session->GetInputDevice()->GetCameraDeviceInfo()->GetCachedMetadata(); + ASSERT_NE(metadata, nullptr); + int32_t quality[15] = {0, 0, 1, -1, -1, 1, 0, 1, -1, -1, 2, 0, 1, -1, -1}; + bool status = AddOrUpdateMetadata(metadata, OHOS_ABILITY_PHOTO_QUALITY_PRIORITIZATION, &quality, + sizeof(quality) / sizeof(quality[0])); + ASSERT_TRUE(status); + bool isSupported = false; + int32_t ret = phtOutput->IsPhotoQualityPrioritizationSupported( + static_cast(1), isSupported); + EXPECT_EQ(ret, 0); + + camera_metadata_item_t item; + OHOS::Camera::FindCameraMetadataItem(metadata->get(), OHOS_ABILITY_PHOTO_QUALITY_PRIORITIZATION, &item); + for (int i = 0; i < static_cast(item.count); i++) { + cout << "item.data[" << i << "] = " << static_cast(item.data.i32[i]) << endl; + } + EXPECT_EQ(session->CommitConfig(), 0); + EXPECT_EQ(session->Start(), 0); + + input->Close(); + session->Stop(); + session->Release(); + input->Release(); + MEDIA_INFO_LOG("IsPhotoQualityPrioritizationSupported_001: END"); +} + +/* + * Feature: Framework + * Function: Test photooutput with IsPhotoQualityPrioritizationSupported + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test photooutput with IsPhotoQualityPrioritizationSupported + */ +HWTEST_F(CameraPhotoOutputUnit, IsPhotoQualityPrioritizationSupported_002, TestSize.Level0) +{ + MEDIA_INFO_LOG("IsPhotoQualityPrioritizationSupported_002: ENTER"); + std::vector> cameras = cameraManager_->GetCameraDeviceListFromServer(); + ASSERT_FALSE(cameras.empty()); + sptr input = cameraManager_->CreateCameraInput(cameras[0]); + ASSERT_NE(input, nullptr); + sptr camInput = (sptr &)input; + camInput->GetCameraDevice()->Open(); + sptr photoOutput = CreatePhotoOutput(); + ASSERT_NE(photoOutput, nullptr); + sptr phtOutput = (sptr&)photoOutput; + + sptr session = cameraManager_->CreateCaptureSession(); + ASSERT_NE(session, nullptr); + EXPECT_EQ(session->BeginConfig(), 0); + EXPECT_EQ(session->AddInput(input), 0); + EXPECT_EQ(session->AddOutput(photoOutput), 0); + std::shared_ptr metadata = + session->GetInputDevice()->GetCameraDeviceInfo()->GetCachedMetadata(); + ASSERT_NE(metadata, nullptr); + int32_t quality[9] = {0, 0, 1, -1, -1, 1, 0, -1, -1}; + bool status = AddOrUpdateMetadata(metadata, OHOS_ABILITY_PHOTO_QUALITY_PRIORITIZATION, &quality, + sizeof(quality) / sizeof(quality[0])); + ASSERT_TRUE(status); + bool isSupported = false; + int32_t ret = phtOutput->IsPhotoQualityPrioritizationSupported( + static_cast(1), isSupported); + EXPECT_EQ(ret, 0); + EXPECT_EQ(session->CommitConfig(), 0); + EXPECT_EQ(session->Start(), 0); + + input->Close(); + session->Stop(); + session->Release(); + input->Release(); + MEDIA_INFO_LOG("IsPhotoQualityPrioritizationSupported_002: END"); +} + +/* + * Feature: Framework + * Function: Test photooutput with SetPhotoQualityPrioritization + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test photooutput with SetPhotoQualityPrioritization + */ +HWTEST_F(CameraPhotoOutputUnit, SetPhotoQualityPrioritization_001, TestSize.Level0) +{ + MEDIA_INFO_LOG("SetPhotoQualityPrioritization_001: ENTER"); + std::vector> cameras = cameraManager_->GetCameraDeviceListFromServer(); + ASSERT_FALSE(cameras.empty()); + sptr input = cameraManager_->CreateCameraInput(cameras[0]); + ASSERT_NE(input, nullptr); + sptr camInput = (sptr &)input; + camInput->GetCameraDevice()->Open(); + sptr photoOutput = CreatePhotoOutput(); + ASSERT_NE(photoOutput, nullptr); + sptr phtOutput = (sptr&)photoOutput; + + sptr session = cameraManager_->CreateCaptureSession(); + ASSERT_NE(session, nullptr); + EXPECT_EQ(session->BeginConfig(), 0); + EXPECT_EQ(session->AddInput(input), 0); + EXPECT_EQ(session->AddOutput(photoOutput), 0); + int ret = phtOutput->SetPhotoQualityPrioritization(static_cast(1)); + EXPECT_EQ(ret, 0); + EXPECT_EQ(session->CommitConfig(), 0); + EXPECT_EQ(session->Start(), 0); + + std::shared_ptr metadata = + session->GetInputDevice()->GetCameraDeviceInfo()->GetCachedMetadata(); + ASSERT_NE(metadata, nullptr); + + camera_metadata_item_t item; + MEDIA_INFO_LOG("SetPhotoQualityPrioritization_001: END 11111"); + int32_t res = OHOS::Camera::FindCameraMetadataItem(metadata->get(), + OHOS_CONTROL_PHOTO_QUALITY_PRIORITIZATION, &item); + MEDIA_INFO_LOG("SetPhotoQualityPrioritization_001: END 22222"); + EXPECT_EQ(res, CAM_META_SUCCESS); + + input->Close(); + session->Stop(); + session->Release(); + input->Release(); + MEDIA_INFO_LOG("SetPhotoQualityPrioritization_001: END"); +} } } diff --git a/frameworks/native/ndk/impl/photo_output_impl.cpp b/frameworks/native/ndk/impl/photo_output_impl.cpp index 11a53a89d..8ab1490e5 100644 --- a/frameworks/native/ndk/impl/photo_output_impl.cpp +++ b/frameworks/native/ndk/impl/photo_output_impl.cpp @@ -290,7 +290,7 @@ Camera_ErrorCode Camera_PhotoOutput::EnableMirror(bool enableMirror) { int32_t ret = innerPhotoOutput_->EnableMirror(enableMirror); isMirrorEnable_ = (ret == napi_ok) ? enableMirror : isMirrorEnable_; - + return FrameworkToNdkCameraError(ret); } @@ -367,4 +367,26 @@ Camera_ErrorCode Camera_PhotoOutput::GetPhotoRotation(int32_t imageRotation, Cam "Camera_PhotoOutput::GetPhotoRotation failed to get photo profile! ret: %{public}d", cameraOutputRotation); *cameraImageRotation = static_cast(cameraOutputRotation); return CAMERA_OK; -} \ No newline at end of file +} + +Camera_ErrorCode Camera_PhotoOutput::IsPhotoQualityPrioritizationSupported( + Camera_PhotoQualityPrioritization qualityPrioritization, bool* isSupported) +{ + CHECK_RETURN_RET_ELOG(isSupported == nullptr, CAMERA_SERVICE_FATAL_ERROR, + "Camera_PhotoOutput::IsPhotoQualityPrioritizationSupported failed, isSupported is null"); + CHECK_RETURN_RET_ELOG(innerPhotoOutput_ == nullptr, CAMERA_SERVICE_FATAL_ERROR, + "Camera_PhotoOutput::IsPhotoQualityPrioritizationSupported failed, innerPhotoOutput_ is null"); + int32_t ret = innerPhotoOutput_->IsPhotoQualityPrioritizationSupported( + static_cast(qualityPrioritization), *isSupported); + return FrameworkToNdkCameraError(ret); +} + +Camera_ErrorCode Camera_PhotoOutput::SetPhotoQualityPrioritization( + Camera_PhotoQualityPrioritization qualityPrioritization) +{ + CHECK_RETURN_RET_ELOG(innerPhotoOutput_ == nullptr, CAMERA_SERVICE_FATAL_ERROR, + "Camera_PhotoOutput::SetPhotoQualityPrioritization failed, innerPhotoOutput_ is null"); + int32_t ret = innerPhotoOutput_->SetPhotoQualityPrioritization( + static_cast(qualityPrioritization)); + return FrameworkToNdkCameraError(ret); +} diff --git a/frameworks/native/ndk/impl/photo_output_impl.h b/frameworks/native/ndk/impl/photo_output_impl.h index 0504a60e1..5f7ce8f88 100644 --- a/frameworks/native/ndk/impl/photo_output_impl.h +++ b/frameworks/native/ndk/impl/photo_output_impl.h @@ -329,6 +329,10 @@ public: Camera_ErrorCode GetPhotoRotation(int32_t imageRotation, Camera_ImageRotation* cameraImageRotation); + Camera_ErrorCode IsPhotoQualityPrioritizationSupported( + Camera_PhotoQualityPrioritization qualityPrioritization, bool* isSupported); + Camera_ErrorCode SetPhotoQualityPrioritization( + Camera_PhotoQualityPrioritization qualityPrioritization); private: OHOS::sptr innerPhotoOutput_ = nullptr; diff --git a/frameworks/native/ndk/photo_output.cpp b/frameworks/native/ndk/photo_output.cpp index 53f1adece..733e8f535 100644 --- a/frameworks/native/ndk/photo_output.cpp +++ b/frameworks/native/ndk/photo_output.cpp @@ -405,6 +405,25 @@ Camera_ErrorCode OH_PhotoOutput_GetPhotoRotation(Camera_PhotoOutput* photoOutput "Invalid argument, cameraImageRotation is null!"); return photoOutput->GetPhotoRotation(deviceDegree, imageRotation); } + +Camera_ErrorCode OH_PhotoOutput_IsPhotoQualityPrioritizationSupported( + Camera_PhotoOutput* photoOutput, Camera_PhotoQualityPrioritization qualityPrioritization, bool* isSupported) +{ + CHECK_RETURN_RET_ELOG(photoOutput == nullptr, CAMERA_INVALID_ARGUMENT, + "Invalid argument, photoOutput is null!"); + CHECK_RETURN_RET_ELOG(isSupported == nullptr, CAMERA_INVALID_ARGUMENT, + "Invalid argument, isSupported is null!"); + return photoOutput->IsPhotoQualityPrioritizationSupported(qualityPrioritization, isSupported); +} + +Camera_ErrorCode OH_PhotoOutput_SetPhotoQualityPrioritization( + Camera_PhotoOutput* photoOutput, Camera_PhotoQualityPrioritization qualityPrioritization) +{ + CHECK_RETURN_RET_ELOG(photoOutput == nullptr, CAMERA_INVALID_ARGUMENT, + "Invalid argument, photoOutput is null!"); + return photoOutput->SetPhotoQualityPrioritization(qualityPrioritization); +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/interfaces/inner_api/native/camera/include/ability/camera_ability_const.h b/interfaces/inner_api/native/camera/include/ability/camera_ability_const.h index c147b9617..ca194375a 100644 --- a/interfaces/inner_api/native/camera/include/ability/camera_ability_const.h +++ b/interfaces/inner_api/native/camera/include/ability/camera_ability_const.h @@ -160,6 +160,7 @@ enum CameraStatus { CAMERA_SERVER_UNAVAILABLE }; + extern const std::unordered_map g_metaFlashModeMap_; extern const std::unordered_map g_metaExposureModeMap_; extern const std::unordered_map g_metaFocusModeMap_; diff --git a/interfaces/inner_api/native/camera/include/output/photo_output.h b/interfaces/inner_api/native/camera/include/output/photo_output.h index a0a5896e0..d153913a6 100644 --- a/interfaces/inner_api/native/camera/include/output/photo_output.h +++ b/interfaces/inner_api/native/camera/include/output/photo_output.h @@ -279,6 +279,12 @@ constexpr int32_t ROTATION_45_DEGREES = 45; constexpr int32_t ROTATION_90_DEGREES = 90; class PhotoOutput : public CaptureOutput { public: + enum PhotoQualityPrioritization { + HIGH_QUALITY = 0, + SPEED = 1 + }; + static const std::unordered_map + g_photoQualityPrioritizationMap_; explicit PhotoOutput(); explicit PhotoOutput(sptr bufferProducer); explicit PhotoOutput(sptr bufferProducer, sptr photoSurface); @@ -515,6 +521,9 @@ public: void CreateMediaLibrary(std::shared_ptr picture, sptr photoProxy, std::string &uri, int32_t &cameraShotType, std::string &burstKey, int64_t timestamp); + int32_t IsPhotoQualityPrioritizationSupported(PhotoQualityPrioritization quality, bool &isSupported); + + int32_t SetPhotoQualityPrioritization(PhotoQualityPrioritization quality); /** * @brief Get photo buffer. */ @@ -583,6 +592,9 @@ private: void SetPhotoNativeConsumer(); void SetPhotoAvailableInSvc(); void SetPhotoAssetAvailableInSvc(); + bool ParseQualityPrioritization(int32_t modeName, common_metadata_header_t* metadata, + camera_photo_quality_prioritization_t type); + bool IsQualityPrioritizationTypeSupported(int32_t* originInfo, uint32_t start, uint32_t end, int32_t type); }; class HStreamCaptureCallbackImpl : public StreamCaptureCallbackStub { diff --git a/interfaces/inner_api/native/camera/include/session/capture_session.h b/interfaces/inner_api/native/camera/include/session/capture_session.h index 73b395727..0ea1dca84 100644 --- a/interfaces/inner_api/native/camera/include/session/capture_session.h +++ b/interfaces/inner_api/native/camera/include/session/capture_session.h @@ -1750,6 +1750,7 @@ public: * @param The MacroStatusCallback pointer. */ void SetMacroStatusCallback(std::shared_ptr callback); + void SetPhotoQualityPrioritization(camera_photo_quality_prioritization_t quality); protected: static const std::unordered_map metaWhiteBalanceModeMap_; diff --git a/interfaces/kits/js/camera_napi/include/input/camera_napi.h b/interfaces/kits/js/camera_napi/include/input/camera_napi.h index 215160637..6f9615bdc 100644 --- a/interfaces/kits/js/camera_napi/include/input/camera_napi.h +++ b/interfaces/kits/js/camera_napi/include/input/camera_napi.h @@ -483,6 +483,11 @@ static const std::unordered_map mapWhiteBalanceMode = { {"LOCKED", 6}, }; +static const std::unordered_map mapPhotoQualityPrioritization = { + {"HIGH_QUALITY", 0}, + {"SPEED", 1}, +}; + enum CreateAsyncCallbackModes { CREATE_CAMERA_MANAGER_ASYNC_CALLBACK = 10, }; diff --git a/interfaces/kits/js/camera_napi/include/output/photo_output_napi.h b/interfaces/kits/js/camera_napi/include/output/photo_output_napi.h index fc94c20c2..e8065013a 100644 --- a/interfaces/kits/js/camera_napi/include/output/photo_output_napi.h +++ b/interfaces/kits/js/camera_napi/include/output/photo_output_napi.h @@ -218,6 +218,8 @@ public: static napi_value EnableAutoAigcPhoto(napi_env env, napi_callback_info info); static napi_value IsOfflineSupported(napi_env env, napi_callback_info info); static napi_value EnableOfflinePhoto(napi_env env, napi_callback_info info); + static napi_value IsPhotoQualityPrioritizationSupported(napi_env env, napi_callback_info info); + static napi_value SetPhotoQualityPrioritization(napi_env env, napi_callback_info info); PhotoOutputNapi(); ~PhotoOutputNapi() override; diff --git a/interfaces/kits/native/include/camera/camera.h b/interfaces/kits/native/include/camera/camera.h index eec320de0..81b93e775 100644 --- a/interfaces/kits/native/include/camera/camera.h +++ b/interfaces/kits/native/include/camera/camera.h @@ -1233,6 +1233,23 @@ typedef enum Camera_WhiteBalanceMode { CAMERA_WHITE_BALANCE_MODE_LOCKED = 6 } Camera_WhiteBalanceMode; +/** + * @brief Enum for photo quality prioritization. + * + * @since 21 + * @version 1.0 + */ +typedef enum Camera_PhotoQualityPrioritization { + /** + * High quality photos are the top preference, even at the expense of shot-to-shot time. + */ + CAMERA_PHOTO_QUALITY_PRIORITIZATION_HIGH_QUALITY = 0, + + /** + * Prefering speed over quality, even at the expense of quality. + */ + CAMERA_PHOTO_QUALITY_PRIORITIZATION_SPEED = 1, +} Camera_PhotoQualityPrioritization; #ifdef __cplusplus } #endif diff --git a/interfaces/kits/native/include/camera/photo_output.h b/interfaces/kits/native/include/camera/photo_output.h index 4bf95962b..d382afb3e 100644 --- a/interfaces/kits/native/include/camera/photo_output.h +++ b/interfaces/kits/native/include/camera/photo_output.h @@ -502,6 +502,35 @@ Camera_ErrorCode OH_PhotoOutput_EnableMovingPhoto(Camera_PhotoOutput* photoOutpu Camera_ErrorCode OH_PhotoOutput_GetPhotoRotation(Camera_PhotoOutput* photoOutput, int deviceDegree, Camera_ImageRotation* imageRotation); +/** + * @brief Check whether to support photo quality prioritization. + * + * @param photoOutput the {@link Camera_PhotoOutput} instance which used to check whether photo quality prioritization + * supported. + * @param qualityPrioritization the {@link Camera_PhotoQualityPrioritization} instance indicating quality preference. + * @param isSupported the result of whether quality prioritization is supported. + * @return {@link #CAMERA_OK} if the method call succeeds. + * {@link #CAMERA_INVALID_ARGUMENT} if parameter missing or parameter type incorrect. + * @since 21 + */ + +Camera_ErrorCode OH_PhotoOutput_IsPhotoQualityPrioritizationSupported(Camera_PhotoOutput* photoOutput, + Camera_PhotoQualityPrioritization qualityPrioritization, bool* isSupported); + +/** + * @brief Set photo quality prioritization. + * + * @param photoOutput the {@link Camera_PhotoOutput} instance which used to configure photo quality prioritization. + * @param qualityPrioritization the {@link Camera_PhotoQualityPrioritization} instance indicating the choice of quality + * or speed. + * @return {@link #CAMERA_OK} if the method call succeeds. + * {@link #CAMERA_INVALID_ARGUMENT} if parameter missing or parameter type incorrect. + * {@link #CAMERA_SERVICE_FATAL_ERROR} if camera service fatal error. + * @since 21 + */ +Camera_ErrorCode OH_PhotoOutput_SetPhotoQualityPrioritization(Camera_PhotoOutput* photoOutput, + Camera_PhotoQualityPrioritization qualityPrioritization); + #ifdef __cplusplus } #endif diff --git a/test/fuzztest/photooutput_fuzzer/photo_output_fuzzer.cpp b/test/fuzztest/photooutput_fuzzer/photo_output_fuzzer.cpp index 6b1276f97..44dba40fa 100644 --- a/test/fuzztest/photooutput_fuzzer/photo_output_fuzzer.cpp +++ b/test/fuzztest/photooutput_fuzzer/photo_output_fuzzer.cpp @@ -108,6 +108,11 @@ void TestOutput1(sptr output, uint8_t *rawData, size_t size) output->IsAutoAigcPhotoSupported(isAutoAigcPhotoSupported); data.RewindRead(0); output->EnableAutoHighQualityPhoto(data.ReadBool()); + PhotoOutput::PhotoQualityPrioritization quality = + static_cast(data.ReadInt32() % 1); + bool isSupported = false; + output->IsPhotoQualityPrioritizationSupported(quality, isSupported); + output->SetPhotoQualityPrioritization(quality); output->Release(); } -- Gitee