From bc2e360c741ec9be39868210b760151696985626 Mon Sep 17 00:00:00 2001 From: w30048789 Date: Thu, 11 Sep 2025 12:29:01 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=88=86=E5=B8=83=E5=BC=8F=E7=9B=B8?= =?UTF-8?q?=E6=9C=BA=E3=80=91=E5=88=86=E5=B8=83=E5=BC=8F=E7=9B=B8=E6=9C=BA?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=B3=BB=E7=BB=9F=E5=88=87=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: w30048789 --- .../dcamera_provider/dcamera_provider.h | 3 + .../dstream_operator/dstream_operator.h | 30 ++++++ .../hdi_service/include/utils/constants.h | 2 + .../src/dcamera_device/dcamera_device.cpp | 11 ++- .../src/dcamera_provider/dcamera_provider.cpp | 17 ++++ .../src/dstream_operator/dstream_operator.cpp | 92 ++++++++++++++++++- 6 files changed, 153 insertions(+), 2 deletions(-) diff --git a/distributed_camera/hdi_service/include/dcamera_provider/dcamera_provider.h b/distributed_camera/hdi_service/include/dcamera_provider/dcamera_provider.h index faf2f4a388..30a2f4218b 100644 --- a/distributed_camera/hdi_service/include/dcamera_provider/dcamera_provider.h +++ b/distributed_camera/hdi_service/include/dcamera_provider/dcamera_provider.h @@ -55,6 +55,8 @@ public: int32_t StartCapture(const DHBase &dhBase, const std::vector &captureInfos); int32_t StopCapture(const DHBase &dhBase, const std::vector &streamIds); int32_t UpdateSettings(const DHBase &dhBase, const std::vector &settings); + bool IsForceSwitch(); + int32_t SetForceSwitch(bool forceSwitch); private: bool IsDCameraSettingsInvalid(const DCameraSettings& result); @@ -77,6 +79,7 @@ private: }; static AutoRelease autoRelease_; static OHOS::sptr instance_; + bool isForceSwitch_ = false; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/distributed_camera/hdi_service/include/dstream_operator/dstream_operator.h b/distributed_camera/hdi_service/include/dstream_operator/dstream_operator.h index 5817cd12b4..6e319dd33a 100644 --- a/distributed_camera/hdi_service/include/dstream_operator/dstream_operator.h +++ b/distributed_camera/hdi_service/include/dstream_operator/dstream_operator.h @@ -43,6 +43,33 @@ using namespace OHOS::HDI::Camera::V1_0; using HDI::Camera::V1_1::OperationMode_V1_1; using HDI::Camera::V1_1::StreamInfo_V1_1; class DCameraProvider; +struct ResolutionCandidate { + int srcWidth; + int srcHeight; + int targetWidth; + int targetHeight; + double ratio; + double area; + double diffRatio; + bool isSameRatio; + bool isAboveTarget; + bool isBelowTarget; + bool isMixed; + + ResolutionCandidate(int srcWidth, int srcHeight, int targetWidth, int targetHeight) + : srcWidth(srcWidth), srcHeight(srcHeight), targetWidth(targetWidth), targetHeight(targetHeight) + { + area = static_cast(srcWidth * srcHeight); + ratio = srcHeight == 0 ? 0 : static_cast(srcWidth) / srcHeight; + double targetRatio = targetHeight == 0 ? 0 : static_cast(targetWidth) / targetHeight; + diffRatio = std::abs(ratio - targetRatio); + isSameRatio = std::abs(ratio - targetRatio) < 1e-6; + + isAboveTarget = (srcWidth >= targetWidth && srcHeight >= targetHeight); + isBelowTarget = (srcWidth <= targetWidth && srcHeight <= targetHeight); + isMixed = !(isAboveTarget || isBelowTarget); + } +}; class DStreamOperator : public HDI::Camera::V1_3::IStreamOperator { public: explicit DStreamOperator(std::shared_ptr &dMetadataProcessor); @@ -103,6 +130,9 @@ private: std::shared_ptr &captureInfo); void ChooseSuitableResolution(std::vector> &streamInfo, std::shared_ptr &captureInfo); + bool CompareCandidates(const ResolutionCandidate& src1, const ResolutionCandidate& src2); + void ResolutionAlignment(std::vector> &streamInfo, + std::shared_ptr &captureInfo); void ChooseSuitableDataSpace(std::vector> &streamInfo, std::shared_ptr &captureInfo); void ChooseSuitableEncodeType(std::vector> &streamInfo, diff --git a/distributed_camera/hdi_service/include/utils/constants.h b/distributed_camera/hdi_service/include/utils/constants.h index 71e3f35d79..478271e9e2 100644 --- a/distributed_camera/hdi_service/include/utils/constants.h +++ b/distributed_camera/hdi_service/include/utils/constants.h @@ -68,6 +68,7 @@ const std::string META_DATA_KEY = "MetaData"; const std::string CAMERA_SUPPORT_MODE = "Mode"; constexpr int32_t LOG_MAX_LEN = 4096; constexpr uint64_t SEC_TO_NSEC_TIMES = 1000000000; +const uint32_t OHOS_CONTROL_REQUEST_CAMERA_SWITCH = 268566549; typedef enum { OHOS_CAMERA_FORMAT_INVALID = 0, @@ -82,6 +83,7 @@ typedef enum { DCAMERA_OPERATION = 1, DCAMERA_SINK_STOP = 2, DCAMERE_GETFULLCAP = 3, + DCAMERE_FORCE_SWITCH = 4, } DCameraEventType; typedef enum { diff --git a/distributed_camera/hdi_service/src/dcamera_device/dcamera_device.cpp b/distributed_camera/hdi_service/src/dcamera_device/dcamera_device.cpp index 2c1fc880d7..bd28284125 100644 --- a/distributed_camera/hdi_service/src/dcamera_device/dcamera_device.cpp +++ b/distributed_camera/hdi_service/src/dcamera_device/dcamera_device.cpp @@ -235,7 +235,15 @@ int32_t DCameraDevice::UpdateSettings(const std::vector& settings) DHLOGE("Distributed camera provider instance is null."); return CamRetCode::DEVICE_ERROR; } - int32_t ret = provider->UpdateSettings(dhBase_, dcSettings); + camera_metadata_item_t forceSwitchItem; + int32_t ret = OHOS::Camera::FindCameraMetadataItem(updateSettings->get(), + OHOS_CONTROL_REQUEST_CAMERA_SWITCH, &forceSwitchItem); + if (ret == CAM_META_SUCCESS) { + bool isForceSwitch = (bool)forceSwitchItem.data.u8[0]; + DHLOGI("isForceSwitch: %{public}d", isForceSwitch); + provider->SetForceSwitch(isForceSwitch); + } + ret = provider->UpdateSettings(dhBase_, dcSettings); return MapToExternalRetCode(static_cast(ret)); } @@ -361,6 +369,7 @@ int32_t DCameraDevice::Close() dCameraStreamOperator_ = nullptr; } if (provider != nullptr) { + provider->SetForceSwitch(false); provider->CloseSession(dhBase_); } if (dMetadataProcessor_ != nullptr) { diff --git a/distributed_camera/hdi_service/src/dcamera_provider/dcamera_provider.cpp b/distributed_camera/hdi_service/src/dcamera_provider/dcamera_provider.cpp index 351ab48cef..9c2f2ccb0b 100644 --- a/distributed_camera/hdi_service/src/dcamera_provider/dcamera_provider.cpp +++ b/distributed_camera/hdi_service/src/dcamera_provider/dcamera_provider.cpp @@ -236,6 +236,12 @@ int32_t DCameraProvider::Notify(const DHBase& dhBase, const DCameraHDFEvent& eve DHLOGI("DCameraProvider::Notify for {devId: %{public}s, dhId: %{public}s}.", GetAnonyString(dhBase.deviceId_).c_str(), GetAnonyString(dhBase.dhId_).c_str()); + if (event.type_ == DCAMERE_FORCE_SWITCH) { + sptr callback = GetCallbackBydhBase(dhBase); + callback->NotifyEvent(dhBase, event); + return DCamRetCode::SUCCESS; + } + OHOS::sptr device = GetDCameraDevice(dhBase); if (device == nullptr) { DHLOGE("DCameraProvider::Notify failed, dcamera device not found."); @@ -412,6 +418,17 @@ int32_t DCameraProvider::UpdateSettings(const DHBase &dhBase, const std::vector< return callback->UpdateSettings(dhBase, settings); } +bool DCameraProvider::IsForceSwitch() +{ + return isForceSwitch_; +} + +int32_t DCameraProvider::SetForceSwitch(bool forceSwitch) +{ + isForceSwitch_ = forceSwitch; + return DCamRetCode::SUCCESS; +} + bool DCameraProvider::IsDCameraSettingsInvalid(const DCameraSettings& result) { return result.value_.empty() || result.value_.length() > SETTING_VALUE_MAX_LENGTH; diff --git a/distributed_camera/hdi_service/src/dstream_operator/dstream_operator.cpp b/distributed_camera/hdi_service/src/dstream_operator/dstream_operator.cpp index a7d826b7ed..5633d9dbfc 100644 --- a/distributed_camera/hdi_service/src/dstream_operator/dstream_operator.cpp +++ b/distributed_camera/hdi_service/src/dstream_operator/dstream_operator.cpp @@ -242,6 +242,13 @@ int32_t DStreamOperator::CommitStreams_V1_1(OperationMode_V1_1 mode, const std:: DHLOGE("DCameraProvider not init."); return CamRetCode::DEVICE_ERROR; } + bool isForceSwitch = dProvider->IsForceSwitch(); + DHLOGI("IsForceSwitch: %{public}d", isForceSwitch); + if (isForceSwitch) { + DCameraHDFEvent dCameraEvent; + dCameraEvent.type_ = DCameraEventType::DCAMERE_FORCE_SWITCH; + dProvider->Notify(dhBase_, dCameraEvent); + } ret = dProvider->ConfigureStreams(dhBase_, dCameraStreams); if (ret != DCamRetCode::SUCCESS) { DHLOGE("Commit distributed camera streams failed."); @@ -1126,13 +1133,96 @@ DCamRetCode DStreamOperator::GetInputCaptureInfo(const CaptureInfo& srcCaptureIn return DCamRetCode::SUCCESS; } +bool DStreamOperator::CompareCandidates(const ResolutionCandidate& src1, const ResolutionCandidate& src2) +{ + DHLOGI("Start CompareCandidates"); + if (src1.isSameRatio != src2.isSameRatio) { + DHLOGI("Priority for the same aspect ratio"); + return src1.isSameRatio; + } + if (src1.isSameRatio) { + if (src1.isAboveTarget && src2.isAboveTarget) { + DHLOGI("First Priority: Both width and height are >= target, with the smallest area."); + return src1.area < src2.area; + } + if (src1.isBelowTarget && src2.isBelowTarget) { + DHLOGI("Second priority: Both width and height are <= target, with the largest area."); + return src1.area > src2.area; + } + DHLOGI("Prioritize those with the same aspect ratio, and choose the larger one."); + return src1.isAboveTarget ? true : false; + } + if (src1.diffRatio != src2.diffRatio) { + DHLOGI("Aspect ratios vary; sorted by proximity to the target aspect ratio."); + return src1.diffRatio < src2.diffRatio; + } + if (src1.isAboveTarget && src2.isAboveTarget) { + DHLOGI("Third Priority: Aspect ratios differ but are both >= target, with the smallest area."); + return src1.area < src2.area; + } + if (src1.isBelowTarget && src2.isBelowTarget) { + DHLOGI("Priority Four: Aspect ratios differ but are all <= target, with the largest area."); + return src1.area > src2.area; + } + DHLOGI("Priority Five: Different aspect ratios, some larger and some smaller, based on the closest area."); + return std::abs(src1.area - src1.targetWidth * src1.targetHeight) < + std::abs(src2.area - src2.targetWidth * src2.targetHeight); +} + +void DStreamOperator::ResolutionAlignment(std::vector> &streamInfo, + std::shared_ptr &captureInfo) +{ + DHLOGI("Start ResolutionAlignment"); + if (captureInfo == nullptr) { + DHLOGE("DStreamOperator::ChooseSuitableResolution, captureInfo is null."); + return; + } + std::vector supportedResolutionList; + if ((streamInfo.at(0))->type_ == DCStreamType::CONTINUOUS_FRAME) { + supportedResolutionList = dcSupportedPreviewResolutionMap_[captureInfo->format_]; + } else { + supportedResolutionList = dcSupportedPhotoResolutionMap_[captureInfo->format_]; + } + + for (auto stream : streamInfo) { + captureInfo->streamIds_.push_back(stream->streamId_); + } + + std::lock_guard autoLock(streamAttrLock_); + std::vector candidates; + for (auto& profile : supportedResolutionList) { + candidates.emplace_back(profile.width_, profile.height_, streamInfo.at(0)->width_, streamInfo.at(0)->height_); + } + std::sort(candidates.begin(), candidates.end(), + [this](const ResolutionCandidate& src1, const ResolutionCandidate& src2) { + return this->CompareCandidates(src1, src2); + }); + if (candidates.size() > 0) { + DHLOGI("ResolutionAlignment resolusion change: %{public}d x %{public}d -> %{public}d x %{public}d", + captureInfo->width_, captureInfo->height_, candidates[0].srcWidth, candidates[0].srcHeight); + captureInfo->width_ = candidates[0].srcWidth; + captureInfo->height_ = candidates[0].srcHeight; + } +} + std::shared_ptr DStreamOperator::BuildSuitableCaptureInfo(const CaptureInfo& srcCaptureInfo, std::vector> &srcStreamInfo) { std::shared_ptr captureInfo = std::make_shared(); ChooseSuitableFormat(srcStreamInfo, captureInfo); - ChooseSuitableResolution(srcStreamInfo, captureInfo); + OHOS::sptr dProvider = DCameraProvider::GetInstance(); + if (dProvider == nullptr) { + DHLOGE("DCameraProvider not init."); + return captureInfo; + } + bool isForceSwitch = dProvider->IsForceSwitch(); + DHLOGI("BuildSuitableCaptureInfo ForceSwitch: %{public}d", isForceSwitch); + if (isForceSwitch) { + ResolutionAlignment(srcStreamInfo, captureInfo); + } else { + ChooseSuitableResolution(srcStreamInfo, captureInfo); + } ChooseSuitableDataSpace(srcStreamInfo, captureInfo); ChooseSuitableEncodeType(srcStreamInfo, captureInfo); -- Gitee