diff --git a/frameworks/js/camera_napi/src/input/camera_napi.cpp b/frameworks/js/camera_napi/src/input/camera_napi.cpp index 4780e2a83368f96b7098ceec333c00278229d2ed..37484c40b0067d06c056900130539ceac456c6af 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 57f11b0219c19f29bf4054627552e45503f8338e..ab0b98d3ff9d05cd57761c36a61664f593cb5ec0 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/output/photo_output.cpp b/frameworks/native/camera/base/src/output/photo_output.cpp index 6a6316342e459fe47cb711bbc4d722797ab8004a..2ba783494da502c981222fb12ab2fe861d6fadf2 100644 --- a/frameworks/native/camera/base/src/output/photo_output.cpp +++ b/frameworks/native/camera/base/src/output/photo_output.cpp @@ -38,6 +38,13 @@ using namespace std; namespace OHOS { namespace CameraStandard { constexpr uint32_t CAPTURE_TIMEOUT = 1; + +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} +}; + PhotoCaptureSetting::PhotoCaptureSetting() { int32_t items = 10; @@ -1494,5 +1501,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 c47a48875bdf32f0e524bb29abc4f1512e63e9f8..80a11374b72e5932927eb64ebd33398d677ab877 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 eaf4d5a612b41162ad9bdf30e4b93f1853f87548..dd7f97a9d1f27e86aa8da3cb66968b1e94a3a6d4 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 IsPhotoQualityPrioritizationSupported + * SubFunction: NA + * FunctionPoints: NA + * EnvConditions: NA + * CaseDescription: Test IsPhotoQualityPrioritizationSupported 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 9ea8a533322105c7a4a0a47bfce62ae5912fbd81..a997659bd00a5c4696efc6692f3eabc224842115 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,153 @@ 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); + + 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); + + 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); + int ret = phtOutput->SetPhotoQualityPrioritization(static_cast(1)); + + EXPECT_EQ(ret, 0); + EXPECT_EQ(session->CommitConfig(), 0); + EXPECT_EQ(session->Start(), 0); + + camera_metadata_item_t item; + int32_t res = OHOS::Camera::FindCameraMetadataItem(metadata->get(), + OHOS_CONTROL_PHOTO_QUALITY_PRIORITIZATION, &item); + 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 11a53a89dfe86586ed8187b82a6f277937792f7f..8ab1490e54f66617ab8e0c37e7c35e09ca255d31 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 0504a60e1a29b6dee03118a3e39e8637ded8e03d..5f7ce8f88e2abb64369caa675b732ef9245605e6 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 53f1adece0dd674e2b6f2cad7c52e28c9dd851b0..733e8f535c86fc4293524dde44fae5a2458d13af 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/output/photo_output.h b/interfaces/inner_api/native/camera/include/output/photo_output.h index a0a5896e0f971fb0817eaf44a1d87905f9b95bb0..da199aec272f6fa258116d7880dd77d829044037 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,10 @@ 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 + }; explicit PhotoOutput(); explicit PhotoOutput(sptr bufferProducer); explicit PhotoOutput(sptr bufferProducer, sptr photoSurface); @@ -515,6 +519,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. */ @@ -573,6 +580,8 @@ private: sptr svcThumbnailCallback_; std::shared_ptr defaultCaptureSetting_; sptr photoNativeConsumer_; + static const std::unordered_map + g_photoQualityPrioritizationMap_; void CameraServerDied(pid_t pid) override; bool mIsHasEnableOfflinePhoto_ = false; bool isHasSwitched_ = false; @@ -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 73b395727eb6491c7b9625b6b384abd96c2e9734..0ea1dca842f0aea5ceb42bb88c3f8c3f5005c8ba 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 2151606374838acf0640ec5186f2613b16dd4eb7..6f9615bdcf905f27c7592b4800e868b94320837a 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 fc94c20c22478a349ace9363e5deded08ee5e22f..e8065013a018433af5f798561f8692802660cee7 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 eec320de07f819fd9b637e7b32745f1b66e30588..81b93e775d3b86161fe2ae941b4ba1c6a197cbb7 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 4bf95962b3850c3ccd0d06bfa10a7ee741b3ac4a..37065678d5f9d91ab57cac6e483419872d4a2105 100644 --- a/interfaces/kits/native/include/camera/photo_output.h +++ b/interfaces/kits/native/include/camera/photo_output.h @@ -502,6 +502,36 @@ 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_OPERATION_NOT_ALLOWED} if operation not allowed. + * {@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 6b1276f97cf7f7234740775cf073b65bc257bbd8..44dba40fabd3b1d41178d4a6f56a678a652d52b0 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(); }