diff --git a/common/include/constants/dcamera_ipc_interface_code.h b/common/include/constants/dcamera_ipc_interface_code.h index d18d37dd65753c89f53956fb151862b57f45c854..3be7438216829a5e6d6997e188cd0b8d90733a28 100644 --- a/common/include/constants/dcamera_ipc_interface_code.h +++ b/common/include/constants/dcamera_ipc_interface_code.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -27,6 +27,7 @@ enum class IDCameraSourceInterfaceCode : uint32_t { REGISTER_DISTRIBUTED_HARDWARE = 2, UNREGISTER_DISTRIBUTED_HARDWARE = 3, CAMERA_NOTIFY = 4, + UPDATE_WORKMODE = 5 }; /* SAID: 4804 */ diff --git a/interfaces/inner_kits/native_cpp/camera_source/include/dcamera_source_handler.h b/interfaces/inner_kits/native_cpp/camera_source/include/dcamera_source_handler.h index 99bd109da99a1c714a16ebcbc2c45ff8948788a0..5b3a31dcdde3d82b413aad955f8f646a58dea16d 100644 --- a/interfaces/inner_kits/native_cpp/camera_source/include/dcamera_source_handler.h +++ b/interfaces/inner_kits/native_cpp/camera_source/include/dcamera_source_handler.h @@ -47,6 +47,8 @@ public: int32_t LoadDistributedHDF(std::shared_ptr callback) override; int32_t UnLoadDistributedHDF() override; void SetSAState(); + int32_t UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) override; private: typedef enum { DCAMERA_SA_STATE_STOP = 0, diff --git a/interfaces/inner_kits/native_cpp/camera_source/include/distributed_camera_source_proxy.h b/interfaces/inner_kits/native_cpp/camera_source/include/distributed_camera_source_proxy.h index 356735e031cf24d333d00a76d4fa8814a010b97f..c29ec0c685a3fd7f66073c3ee17ce0a40473fbcc 100644 --- a/interfaces/inner_kits/native_cpp/camera_source/include/distributed_camera_source_proxy.h +++ b/interfaces/inner_kits/native_cpp/camera_source/include/distributed_camera_source_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -41,12 +41,15 @@ public: int32_t UnregisterDistributedHardware(const std::string& devId, const std::string& dhId, const std::string& reqId) override; int32_t DCameraNotify(const std::string& devId, const std::string& dhId, std::string& events) override; + int32_t UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) override; private: bool CheckRegParams(const std::string& devId, const std::string& dhId, const std::string& reqId, const EnableParam& param); bool CheckUnregParams(const std::string& devId, const std::string& dhId, const std::string& reqId); bool CheckNotifyParams(const std::string& devId, const std::string& dhId, std::string& events); + bool CheckUpdateParams(const std::string& devId, const std::string& dhId, const WorkModeParam& param); static inline BrokerDelegator delegator_; const size_t PARAM_MAX_SIZE = 50 * 1024 * 1024; diff --git a/interfaces/inner_kits/native_cpp/camera_source/include/idistributed_camera_source.h b/interfaces/inner_kits/native_cpp/camera_source/include/idistributed_camera_source.h index 8a36f3391255b8b9d1403170703440c840e141ee..45519394b555cb9990214dc3b68f064704e88ceb 100644 --- a/interfaces/inner_kits/native_cpp/camera_source/include/idistributed_camera_source.h +++ b/interfaces/inner_kits/native_cpp/camera_source/include/idistributed_camera_source.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -35,6 +35,8 @@ public: virtual int32_t UnregisterDistributedHardware(const std::string& devId, const std::string& dhId, const std::string& reqId) = 0; virtual int32_t DCameraNotify(const std::string& devId, const std::string& dhId, std::string& events) = 0; + virtual int32_t UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/interfaces/inner_kits/native_cpp/camera_source/src/dcamera_source_handler.cpp b/interfaces/inner_kits/native_cpp/camera_source/src/dcamera_source_handler.cpp index 732c58173e0d300fa12b88f60700b0e5b50c4081..6ec9ddff275ba394e51dab0417b55209dc214134 100644 --- a/interfaces/inner_kits/native_cpp/camera_source/src/dcamera_source_handler.cpp +++ b/interfaces/inner_kits/native_cpp/camera_source/src/dcamera_source_handler.cpp @@ -228,6 +228,20 @@ void DCameraSourceHandler::SetSAState() state_ = DCAMERA_SA_STATE_STOP; } +int32_t DCameraSourceHandler::UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) +{ + DHLOGI("update camera workmode, devId: %{public}s dhId: %{public}s", GetAnonyString(devId).c_str(), + GetAnonyString(dhId).c_str()); + sptr dCameraSourceSrv = DCameraSourceHandlerIpc::GetInstance().GetSourceLocalCamSrv(); + CHECK_AND_RETURN_RET_LOG(dCameraSourceSrv == nullptr, DCAMERA_BAD_VALUE, "get service failed"); + int32_t ret = dCameraSourceSrv->UpdateDistributedHardwareWorkMode(devId, dhId, param); + if (ret != DCAMERA_OK) { + DHLOGE("update camera workmode failed, ret:%{public}d", ret); + } + return ret; +} + IDistributedHardwareSource *GetSourceHardwareHandler() { DHLOGI("DCameraSourceHandler GetSourceHardwareHandler Start"); diff --git a/interfaces/inner_kits/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp b/interfaces/inner_kits/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp index b42201efb3790c84cfa2b6632eb3fd276889b946..2575b63531e0e015280c693dfaaabc8dc507e62c 100644 --- a/interfaces/inner_kits/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp +++ b/interfaces/inner_kits/native_cpp/camera_source/src/distributed_camera_source_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -226,5 +226,45 @@ bool DistributedCameraSourceProxy::CheckNotifyParams(const std::string& devId, c } return true; } + +int32_t DistributedCameraSourceProxy::UpdateDistributedHardwareWorkMode(const std::string& devId, + const std::string& dhId, const WorkModeParam& param) +{ + DHLOGI("devId: %{public}s dhId: %{public}s", GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str()); + if (!CheckUpdateParams(devId, dhId, param)) { + DHLOGE("workmode param is invalid"); + return DCAMERA_BAD_VALUE; + } + sptr remote = Remote(); + CHECK_AND_RETURN_RET_LOG(remote == nullptr, DCAMERA_BAD_VALUE, "remote service is null"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(DistributedCameraSourceProxy::GetDescriptor())) { + DHLOGE("write token failed"); + return DCAMERA_BAD_VALUE; + } + bool writeRet = !data.WriteString(devId) || !data.WriteString(dhId) || !data.WriteFileDescriptor(param.fd) || + !data.WriteInt32(param.sharedMemLen) || !data.WriteUint32(param.scene) || !data.WriteInt32(param.isAVsync); + CHECK_AND_RETURN_RET_LOG(writeRet, DCAMERA_BAD_VALUE, "write params failed"); + remote->SendRequest(static_cast(IDCameraSourceInterfaceCode::UPDATE_WORKMODE), + data, reply, option); + int32_t result = reply.ReadInt32(); + return result; +} + +bool DistributedCameraSourceProxy::CheckUpdateParams(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) +{ + if (devId.empty() || devId.size() > DID_MAX_SIZE || dhId.empty() || dhId.size() > DID_MAX_SIZE) { + DHLOGE("input params is invalid"); + return false; + } + if (param.fd < 0 || param.sharedMemLen < 0) { + DHLOGE("workmode param is invalid"); + return false; + } + return true; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/BUILD.gn b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/BUILD.gn index 15dff9b51c6e3d64aabf015d886bde626696b02c..a8fa0b4817025ac04251960982cad65ae65992c7 100644 --- a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/BUILD.gn +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/BUILD.gn @@ -46,5 +46,6 @@ group("fuzztest") { "sourceserviceregisterdistributedhardware_fuzzer:fuzztest", "sourceservicereleasesource_fuzzer:fuzztest", "sourceserviceunregisterdistributedhardware_fuzzer:fuzztest", + "sourceserviceupdateworkmode_fuzzer:fuzztest", ] } diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/BUILD.gn b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..efdcd4db3ba3ccfa7e05627528dc9c757415aa92 --- /dev/null +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/BUILD.gn @@ -0,0 +1,88 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import( + "//foundation/distributedhardware/distributed_camera/distributedcamera.gni") + +##############################fuzztest########################################## +ohos_fuzztest("SourceServiceUpdateWorkModeFuzzTest") { + module_out_path = "${fuzz_test_output_path}/sourceserviceupdateworkmode" + + fuzz_config_file = "${innerkits_path}/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer" + + include_dirs = + [ "${innerkits_path}/native_cpp/camera_source/include/callback" ] + + include_dirs += [ + "include", + "${common_path}/include/constants", + "${common_path}/include/utils", + "${innerkits_path}/native_cpp/camera_source/include", + "${innerkits_path}/native_cpp/camera_source/include/callback", + "${services_path}/cameraservice/base/include", + "${services_path}/cameraservice/sourceservice/include/distributedcamera", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr/dcameracontrol", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr/dcameradata", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr/dcamerahdf", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface", + "${services_path}/cameraservice/sourceservice/include/distributedcameramgr/dcamerastate", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-Dprivate=public", + "-Dprotected=public", + ] + + sources = [ "sourceserviceupdateworkmode_fuzzer.cpp" ] + + deps = [ + "${common_path}:distributed_camera_utils", + "${innerkits_path}/native_cpp/camera_source:distributed_camera_source_sdk", + "${services_path}/cameraservice/sourceservice:distributed_camera_source", + ] + + defines = [ + "HI_LOG_ENABLE", + "DH_LOG_TAG=\"SourceServiceUpdateWorkModeFuzzTest\"", + "LOG_DOMAIN=0xD004150", + ] + + external_deps = [ + "cJSON:cjson", + "c_utils:utils", + "distributed_hardware_fwk:distributed_av_receiver", + "distributed_hardware_fwk:distributedhardwareutils", + "distributed_hardware_fwk:libdhfwk_sdk", + "drivers_interface_distributed_camera:libdistributed_camera_provider_proxy_1.1", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [ ":SourceServiceUpdateWorkModeFuzzTest" ] +} +############################################################################### diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/corpus/init b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..65af8ee8d11bf23407ea34d4de49f7cbb6a2b791 --- /dev/null +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FUZZ \ No newline at end of file diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/project.xml b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..66e1dcac475475fb101b6f8670ec699e6e9696aa --- /dev/null +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.cpp b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e053a49e58e1527500ffff2bb376e25a032ac37 --- /dev/null +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sourceserviceupdateworkmode_fuzzer.h" +#include + +#include "dcamera_source_callback.h" +#include "distributed_camera_constants.h" +#include "distributed_camera_source_service.h" +#include "idistributed_hardware_source.h" + +namespace OHOS { +namespace DistributedHardware { +void SourceServiceUpdateWorkModeFuzzTest(const uint8_t* data, size_t size) +{ + if ((data == nullptr) || (size < sizeof(int32_t))) { + return; + } + + FuzzedDataProvider fdp(data, size); + int32_t tempLen = 32; + std::string devId(fdp.ConsumeRandomLengthString(tempLen)); + std::string dhId(fdp.ConsumeRandomLengthString(tempLen)); + WorkModeParam param(-1, 0, 0, 0); + param.fd = fdp.ConsumeIntegral(); + param.sharedMemLen = fdp.ConsumeIntegral(); + param.scene = fdp.ConsumeIntegral(); + param.isAVsync = fdp.ConsumeBool(); + + std::shared_ptr sourceService = + std::make_shared(DISTRIBUTED_HARDWARE_CAMERA_SOURCE_SA_ID, true); + sptr callback(new DCameraSourceCallback()); + + sourceService->UpdateDistributedHardwareWorkMode(devId, dhId, param); +} +} +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + OHOS::DistributedHardware::SourceServiceUpdateWorkModeFuzzTest(data, size); + return 0; +} + diff --git a/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.h b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..27c71640fd293a38bba3b348e9c7b900f19c6230 --- /dev/null +++ b/interfaces/inner_kits/native_cpp/test/sourcefuzztest/sourceserviceupdateworkmode_fuzzer/sourceserviceupdateworkmode_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SOURCESERVICEUPDATEWORKMODE_FUZZER_H +#define SOURCESERVICEUPDATEWORKMODE_FUZZER_H + +#define FUZZ_PROJECT_NAME "sourceserviceupdateworkmode_fuzzer" + +#endif \ No newline at end of file diff --git a/interfaces/inner_kits/native_cpp/test/unittest/common/camera_source/dcamera_source_handler_test.cpp b/interfaces/inner_kits/native_cpp/test/unittest/common/camera_source/dcamera_source_handler_test.cpp index d72a7d4bbf3986b5b25b33671e80d8a619ea6d7a..3712fe7b62dd1b0f909a7a461223b73109d55f23 100644 --- a/interfaces/inner_kits/native_cpp/test/unittest/common/camera_source/dcamera_source_handler_test.cpp +++ b/interfaces/inner_kits/native_cpp/test/unittest/common/camera_source/dcamera_source_handler_test.cpp @@ -187,5 +187,24 @@ HWTEST_F(DCameraSourceHandlerTest, dcamera_source_handler_test_006, TestSize.Lev int32_t ret = DCameraSourceHandler::GetInstance().InitSource(params); EXPECT_EQ(DCAMERA_OK, ret); } + +/** + * @tc.name: dcamera_source_handler_test_007 + * @tc.desc: Verify the UpdateDistributedHardwareWorkMode function. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraSourceHandlerTest, dcamera_source_handler_test_007, TestSize.Level0) +{ + std::string devId = TEST_DEVICE_ID; + std::string dhId = TEST_CAMERA_DH_ID_0; + WorkModeParam param(-1, 0, 0, false); + int32_t ret = DCameraSourceHandler::GetInstance().UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + param.fd = 12; + param.sharedMemLen = 120; + ret = DCameraSourceHandler::GetInstance().UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_NE(DCAMERA_OK, ret); +} } } \ No newline at end of file diff --git a/services/cameraservice/base/include/dcamera_frame_info.h b/services/cameraservice/base/include/dcamera_frame_info.h index 042435a462a1ce44016548b4b23886e6a4ac6244..7ec96675a4081b3385ea4ffdde0eaa2c1c3aed10 100644 --- a/services/cameraservice/base/include/dcamera_frame_info.h +++ b/services/cameraservice/base/include/dcamera_frame_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -38,6 +38,7 @@ struct DCameraFrameInfo { int32_t index = 0; int32_t offset = 0; int64_t pts = 0; + int64_t rawTime = 0; DCameraFrameProcessTimePoint timePonit {0}; }; } // namespace DistributedHardware diff --git a/services/cameraservice/base/include/dcamera_sink_frame_info.h b/services/cameraservice/base/include/dcamera_sink_frame_info.h index d5a8f6153403c929d109e4c00068ca21c37da02c..953a9a886a810081b0ba35e2e98661b4e1b1377b 100644 --- a/services/cameraservice/base/include/dcamera_sink_frame_info.h +++ b/services/cameraservice/base/include/dcamera_sink_frame_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -33,6 +33,7 @@ public: int64_t finishEncodeT_; int64_t sendT_; std::string ver_; + std::string rawTime_; public: const std::string FRAME_INFO_TYPE = "type"; @@ -43,6 +44,7 @@ public: const std::string FRAME_INFO_ENCODET = "encodeT"; const std::string FRAME_INFO_SENDT = "sendT"; const std::string FRAME_INFO_VERSION = "ver"; + const std::string RAW_TIME = "rawTime"; public: void Marshal(std::string& jsonStr); diff --git a/services/cameraservice/base/src/dcamera_sink_frame_info.cpp b/services/cameraservice/base/src/dcamera_sink_frame_info.cpp index 3290041698d292e25e7cf80093ecf9a8da7e5dec..693fb8edc7b5a5c0f2b81099c4e99d38872ebc61 100644 --- a/services/cameraservice/base/src/dcamera_sink_frame_info.cpp +++ b/services/cameraservice/base/src/dcamera_sink_frame_info.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -33,6 +33,7 @@ void DCameraSinkFrameInfo::Marshal(std::string& jsonStr) cJSON_AddNumberToObject(frameInfo, FRAME_INFO_FINISH_ENCODE.c_str(), finishEncodeT_); cJSON_AddNumberToObject(frameInfo, FRAME_INFO_SENDT.c_str(), sendT_); cJSON_AddStringToObject(frameInfo, FRAME_INFO_VERSION.c_str(), ver_.c_str()); + cJSON_AddStringToObject(frameInfo, RAW_TIME.c_str(), rawTime_.c_str()); char *data = cJSON_Print(frameInfo); if (data == nullptr) { @@ -47,51 +48,53 @@ void DCameraSinkFrameInfo::Marshal(std::string& jsonStr) int32_t DCameraSinkFrameInfo::Unmarshal(const std::string& jsonStr) { cJSON *rootValue = cJSON_Parse(jsonStr.c_str()); - if (rootValue == nullptr) { - return DCAMERA_BAD_VALUE; - } + CHECK_NULL_RETURN((rootValue == nullptr), DCAMERA_BAD_VALUE); + cJSON *type = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_TYPE.c_str()); - if (type == nullptr || !cJSON_IsNumber(type)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((type == nullptr || !cJSON_IsNumber(type)), + DCAMERA_BAD_VALUE, rootValue, "type parse fail."); type_ = static_cast(type->valueint); + cJSON *index = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_INDEX.c_str()); - if (index == nullptr || !cJSON_IsNumber(index)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((index == nullptr || !cJSON_IsNumber(index)), + DCAMERA_BAD_VALUE, rootValue, "index parse fail."); index_ = static_cast(index->valueint); + cJSON *pts = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_PTS.c_str()); - if (pts == nullptr || !cJSON_IsNumber(pts)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((pts == nullptr || !cJSON_IsNumber(pts)), + DCAMERA_BAD_VALUE, rootValue, "pts parse fail."); pts_ = static_cast(pts->valueint); + cJSON *startEncode = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_START_ENCODE.c_str()); - if (startEncode == nullptr || !cJSON_IsNumber(startEncode)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((startEncode == nullptr || !cJSON_IsNumber(startEncode)), + DCAMERA_BAD_VALUE, rootValue, "startEncode parse fail."); startEncodeT_ = static_cast(startEncode->valueint); + cJSON *finishEncode = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_FINISH_ENCODE.c_str()); - if (finishEncode == nullptr || !cJSON_IsNumber(finishEncode)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((finishEncode == nullptr || !cJSON_IsNumber(finishEncode)), + DCAMERA_BAD_VALUE, rootValue, "finishEncode parse fail."); finishEncodeT_ = static_cast(finishEncode->valueint); + cJSON *sendT = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_SENDT.c_str()); - if (sendT == nullptr || !cJSON_IsNumber(sendT)) { - cJSON_Delete(rootValue); - return DCAMERA_BAD_VALUE; - } + CHECK_AND_FREE_RETURN_RET_LOG((sendT == nullptr || !cJSON_IsNumber(sendT)), + DCAMERA_BAD_VALUE, rootValue, "sendT parse fail."); sendT_ = static_cast(sendT->valueint); + cJSON *ver = cJSON_GetObjectItemCaseSensitive(rootValue, FRAME_INFO_VERSION.c_str()); - if (ver == nullptr || !cJSON_IsString(ver)) { + CHECK_AND_FREE_RETURN_RET_LOG((ver == nullptr || !cJSON_IsString(ver)), + DCAMERA_BAD_VALUE, rootValue, "ver parse fail."); + ver_ = std::string(ver->valuestring); + + cJSON *rawTime = cJSON_GetObjectItemCaseSensitive(rootValue, RAW_TIME.c_str()); + if (rawTime == nullptr) { + rawTime_ = ""; + } else if (!cJSON_IsString(rawTime)) { + DHLOGE("rawTime parse fail."); cJSON_Delete(rootValue); return DCAMERA_BAD_VALUE; + } else { + rawTime_ = std::string(rawTime->valuestring); } - ver_ = std::string(ver->valuestring); cJSON_Delete(rootValue); return DCAMERA_OK; } diff --git a/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_service.h b/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_service.h index d84296737fe0355a33b5feae8909d5cc37a8d076..1714fcad6a72219d7afce09de4b0d75cc6cb50a3 100644 --- a/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_service.h +++ b/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_service.h @@ -57,6 +57,8 @@ public: static void CamDevErase(DCameraIndex& index); static uint32_t GetCamDevNum(); void StartHicollieThread(); + int32_t UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) override; protected: void OnStart() override; diff --git a/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_stub.h b/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_stub.h index 99df7ea9bed8f300c7b1a78ba9127c0bf9374caa..e9222217532fe44ba5d258792290d4ec92e05f6c 100644 --- a/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_stub.h +++ b/services/cameraservice/sourceservice/include/distributedcamera/distributed_camera_source_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -34,12 +34,14 @@ private: int32_t ReleaseSourceInner(MessageParcel &data, MessageParcel &reply); int32_t RegisterDistributedHardwareInner(MessageParcel &data, MessageParcel &reply); int32_t UnregisterDistributedHardwareInner(MessageParcel &data, MessageParcel &reply); + int32_t UpdateDCameraWorkModeInner(MessageParcel &data, MessageParcel &reply); int32_t DCameraNotifyInner(MessageParcel &data, MessageParcel &reply); bool CheckRegParams(const std::string& devId, const std::string& dhId, const std::string& reqId, const EnableParam& param); bool CheckUnregParams(const std::string& devId, const std::string& dhId, const std::string& reqId); bool CheckNotifyParams(const std::string& devId, const std::string& dhId, std::string& events); bool HasEnableDHPermission(); + bool CheckUpdateParams(const std::string& devId, const std::string& dhId, const WorkModeParam& param); using DCameraFunc = int32_t (DistributedCameraSourceStub::*)(MessageParcel &data, MessageParcel &reply); std::map memberFuncMap_; diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamera_source_dev.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamera_source_dev.h index 15484d2373f92a20e5ee450e819ecdd26d556b1f..4d6376681d2643b218c76873ceeb7f05c7c3e04e 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamera_source_dev.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamera_source_dev.h @@ -70,6 +70,7 @@ public: bool GetHicollieFlag(); int32_t GetFullCaps(); void SetTokenId(uint64_t token); + int32_t UpdateDCameraWorkMode(const WorkModeParam& param); class DCameraSourceDevEventHandler : public AppExecFwk::EventHandler { public: diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_data_process.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_data_process.h index c92b3c17315f5922901d760494c9019c16b6bc19..4c01fa4a4c046a3bbf976b1cea925d1dca1eb95b 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_data_process.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_data_process.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -40,6 +40,7 @@ public: int32_t StopCapture(std::vector& streamIds) override; int32_t GetProducerSize() override; void GetAllStreamIds(std::vector& streamIds) override; + int32_t UpdateProducerWorkMode(std::vector& streamIds, const WorkModeParam& param) override; private: void DestroyPipeline(); diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_input.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_input.h index 14e1473f6d3a7ba4b94d90e589b034cd044aad2c..21f28963c30cb326b19be4d129e616b174e36e49 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_input.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_source_input.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -43,6 +43,7 @@ public: int32_t Init() override; int32_t UnInit() override; int32_t UpdateSettings(std::vector>& settings) override; + int32_t UpdateWorkMode(const WorkModeParam& param) override; void OnSessionState(DCStreamType streamType, int32_t state); void OnSessionError(DCStreamType streamType, int32_t eventType, int32_t eventReason, std::string detail); diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process.h index 8be56c23c4ef74b7969087937ec0b83f8b40a144..8d90c301c261ddca194b1edd7254db215ed14ff8 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -45,6 +45,7 @@ public: void OnProcessedVideoBuffer(const std::shared_ptr& videoResult); void OnError(const DataProcessErrorType errorType); void DestroyPipeline(); + int32_t UpdateProducerWorkMode(std::vector& streamIds, const WorkModeParam& param); private: void FeedStreamToSnapShot(const std::shared_ptr& buffer); diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.h index 6a45d1d3356a96b4d03235fdbd589c8eee446962..415465a42b198212ca33336bf577c7de834f8c2e 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,11 +21,15 @@ #include #include #include +#include +#include +#include #include "data_buffer.h" #include "event_handler.h" #include "v1_1/id_camera_provider.h" #include "dcamera_feeding_smoother.h" +#include "idistributed_camera_source.h" namespace OHOS { namespace DistributedHardware { @@ -38,21 +42,46 @@ public: DCAMERA_PRODUCER_STATE_START = 1, } DCameraProducerState; + struct SyncSharedData { + volatile int lock; + uint64_t audio_current_pts; + uint64_t audio_update_clock; + float audio_speed; + uint64_t video_current_pts; + uint64_t video_update_clock; + float video_speed; + uint64_t sync_strategy; + bool reset; + }; + DCameraStreamDataProcessProducer(std::string devId, std::string dhId, int32_t streamId, DCStreamType streamType); ~DCameraStreamDataProcessProducer(); void Start(); void Stop(); void FeedStream(const std::shared_ptr& buffer); virtual void OnSmoothFinished(const std::shared_ptr& data) override; + void UpdateProducerWorkMode(const WorkModeParam& param); private: void StartEvent(); void LooperSnapShot(); int32_t FeedStreamToDriver(const DHBase& dhBase, const std::shared_ptr& buffer); int32_t CheckSharedMemory(const DCameraBuffer& sharedMemory, const std::shared_ptr& buffer); + void WritePtsAndAddBuffer(const std::shared_ptr& buffer); + void SyncVideoThread(); + bool WaitForVideoFrame(std::shared_ptr& buffer); + int32_t SyncVideoFrame(uint64_t videoPtsUs); + void UpdateVideoClock(uint64_t videoPtsUs); const uint32_t DCAMERA_PRODUCER_MAX_BUFFER_SIZE = 30; const uint32_t DCAMERA_PRODUCER_RETRY_SLEEP_MS = 500; + const uint32_t DCAMERA_MAX_SYNC_BUFFER_SIZE = 10; + const uint32_t DCAMERA_SYNC_WATERMARK = 1; + const uint32_t DCAMERA_SYNC_TIME_INTERVAL = 33; + const uint32_t DCAMERA_NS_TO_MS = 1000000; + const uint32_t DCAMERA_US_TO_MS = 1000; + const uint32_t DCAMERA_TIME_DIFF_MAX = 5; + const int32_t DCAMERA_TIME_DIFF_MIN = -80; private: std::string devId_; @@ -75,6 +104,17 @@ private: sptr camHdiProvider_; std::unique_ptr smoother_ = nullptr; std::shared_ptr smootherListener_ = nullptr; + + std::thread syncThread_; + std::atomic syncRunning_; + std::deque> syncBufferQueue_; + std::mutex syncBufferMutex_; + std::condition_variable syncBufferCond_; + std::atomic isFirstFrame_; + std::chrono::steady_clock::time_point startTime_; + WorkModeParam workModeParam_; // Audio-video synchronization fwk transfer structure + std::mutex workModeParamMtx_; + sptr syncMem_ = nullptr; // Shared memory }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_input.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_input.h index 8d4e80516c9c8357bc0cc59bc30e5aa19a84f867..7da59effe2378183913037b802c458c7f1581c80 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_input.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_input.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,6 +16,7 @@ #ifndef OHOS_ICAMERA_INPUT_H #define OHOS_ICAMERA_INPUT_H +#include "idistributed_camera_source.h" #include "v1_1/dcamera_types.h" namespace OHOS { @@ -36,6 +37,7 @@ public: virtual int32_t Init() = 0; virtual int32_t UnInit() = 0; virtual int32_t UpdateSettings(std::vector>& settings) = 0; + virtual int32_t UpdateWorkMode(const WorkModeParam& param) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_source_data_process.h b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_source_data_process.h index 84e5182eccee078af634533239c32727efa57b45..4415f7ca7601f3346128fd8e019483df5476c1f6 100644 --- a/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_source_data_process.h +++ b/services/cameraservice/sourceservice/include/distributedcameramgr/dcamerainterface/icamera_source_data_process.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,6 +18,7 @@ #include +#include "idistributed_camera_source.h" #include "data_buffer.h" #include "v1_1/dcamera_types.h" @@ -63,6 +64,7 @@ public: virtual int32_t StopCapture(std::vector& streamIds) = 0; virtual int32_t GetProducerSize() = 0; virtual void GetAllStreamIds(std::vector& streamIds) = 0; + virtual int32_t UpdateProducerWorkMode(std::vector& streamIds, const WorkModeParam& param) = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_service.cpp b/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_service.cpp index efeaa435a75eaad2e5f3abe83789d675c10a7e5a..86cbbeae3313729409c0832e011480f57c43f626 100644 --- a/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_service.cpp +++ b/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_service.cpp @@ -443,5 +443,20 @@ void DistributedCameraSourceService::StartHicollieThread() } // LCOV_EXCL_STOP } + +int32_t DistributedCameraSourceService::UpdateDistributedHardwareWorkMode(const std::string& devId, + const std::string& dhId, const WorkModeParam& param) +{ + DHLOGI("update camera workmode, networkId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(), + GetAnonyString(dhId).c_str()); + DCameraIndex camIndex(devId, dhId); + int32_t ret = DCAMERA_OK; + std::shared_ptr camDev = GetCamDevByIndex(camIndex); + + CHECK_AND_RETURN_RET_LOG(camDev == nullptr, DCAMERA_NOT_FOUND, "can not found device"); + ret = camDev->UpdateDCameraWorkMode(param); + DHLOGI("update camera workmode done,ret:%{public}d", ret); + return ret; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_stub.cpp b/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_stub.cpp index 16c23999a2890836d09c0ed282bf0c2a3606b208..71e939364660f186d08f39c7d4c440a02735f1f1 100644 --- a/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_stub.cpp +++ b/services/cameraservice/sourceservice/src/distributedcamera/distributed_camera_source_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -37,6 +37,8 @@ DistributedCameraSourceStub::DistributedCameraSourceStub() : IRemoteStub(true) &DistributedCameraSourceStub::UnregisterDistributedHardwareInner; memberFuncMap_[static_cast(IDCameraSourceInterfaceCode::CAMERA_NOTIFY)] = &DistributedCameraSourceStub::DCameraNotifyInner; + memberFuncMap_[static_cast(IDCameraSourceInterfaceCode::UPDATE_WORKMODE)] = + &DistributedCameraSourceStub::UpdateDCameraWorkModeInner; } DistributedCameraSourceStub::~DistributedCameraSourceStub() @@ -73,6 +75,8 @@ int32_t DistributedCameraSourceStub::OnRemoteRequest(uint32_t code, MessageParce return UnregisterDistributedHardwareInner(data, reply); case static_cast(IDCameraSourceInterfaceCode::CAMERA_NOTIFY): return DCameraNotifyInner(data, reply); + case static_cast(IDCameraSourceInterfaceCode::UPDATE_WORKMODE): + return UpdateDCameraWorkModeInner(data, reply); default: DHLOGE("Invalid OnRemoteRequest code=%{public}d", code); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -253,5 +257,44 @@ bool DistributedCameraSourceStub::CheckNotifyParams(const std::string& devId, co } return true; } + +int32_t DistributedCameraSourceStub::UpdateDCameraWorkModeInner(MessageParcel &data, MessageParcel &reply) +{ + DHLOGD("update dcamera workmode"); + int32_t ret = DCAMERA_OK; + do { + if (!HasEnableDHPermission()) { + DHLOGE("The caller has no ENABLE_DISTRIBUTED_HARDWARE permission."); + ret = DCAMERA_BAD_VALUE; + break; + } + std::string devId = data.ReadString(); + std::string dhId = data.ReadString(); + WorkModeParam params(-1, 0, 0, false); + params.fd = data.ReadFileDescriptor(); + params.sharedMemLen = data.ReadInt32(); + params.scene = data.ReadUint32(); + params.isAVsync = static_cast(data.ReadInt32()); + if (!CheckUpdateParams(devId, dhId, params)) { + DHLOGE("input param is invalid"); + ret = DCAMERA_BAD_VALUE; + break; + } + ret = UpdateDistributedHardwareWorkMode(devId, dhId, params); + DHLOGI("DistributedCameraSourceStub UpdateDistributedHardwareWorkMode %{public}d", ret); + } while (0); + reply.WriteInt32(ret); + return ret; +} + +bool DistributedCameraSourceStub::CheckUpdateParams(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) +{ + bool ret = devId.empty() || devId.size() > DID_MAX_SIZE || dhId.empty() || dhId.size() > DID_MAX_SIZE; + CHECK_AND_RETURN_RET_LOG(ret, false, "input params is invalid"); + ret = param.fd < 0 || param.sharedMemLen < 0; + CHECK_AND_RETURN_RET_LOG(ret, false, "workmode param is invalid"); + return true; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcameramgr/dcamera_source_dev.cpp b/services/cameraservice/sourceservice/src/distributedcameramgr/dcamera_source_dev.cpp index fe2dd9efbfdcb45e09db1f8656a372e777c3921f..b0fd4bc61aa5c4565995c16571f81d07e111c003 100644 --- a/services/cameraservice/sourceservice/src/distributedcameramgr/dcamera_source_dev.cpp +++ b/services/cameraservice/sourceservice/src/distributedcameramgr/dcamera_source_dev.cpp @@ -503,7 +503,6 @@ int32_t DCameraSourceDev::OpenCamera() } CHECK_AND_RETURN_RET_LOG(stateListener_ == nullptr, DCAMERA_BAD_VALUE, "stateListener_ is nullptr."); - stateListener_->OnHardwareStateChanged(devId_, dhId_, DcameraBusinessState::RUNNING); return DCAMERA_OK; } @@ -638,10 +637,9 @@ int32_t DCameraSourceDev::StartCapture(std::vectorencodeType_ = (*iter)->encodeType_; capture->streamType_ = (*iter)->type_; DHLOGI("StartCapture devId %{public}s dhId %{public}s settings size: %{public}zu w: %{public}d h: %{public}d " - "fmt: %{public}d isC: %{public}d enc: %{public}d streamT: %{public}d", - GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), (*iter)->captureSettings_.size(), - capture->width_, capture->height_, capture->format_, capture->isCapture_ ? 1 : 0, capture->encodeType_, - capture->streamType_); + "fmt: %{public}d isC: %{public}d enc: %{public}d streamT: %{public}d", GetAnonyString(devId_).c_str(), + GetAnonyString(dhId_).c_str(), (*iter)->captureSettings_.size(), capture->width_, capture->height_, + capture->format_, capture->isCapture_ ? 1 : 0, capture->encodeType_, capture->streamType_); for (auto settingIter = (*iter)->captureSettings_.begin(); settingIter != (*iter)->captureSettings_.end(); settingIter++) { std::shared_ptr setting = std::make_shared(); @@ -660,6 +658,7 @@ int32_t DCameraSourceDev::StartCapture(std::vectorOnHardwareStateChanged(devId_, dhId_, DcameraBusinessState::RUNNING); return ret; } @@ -885,5 +884,13 @@ void DCameraSourceDev::SetTokenId(uint64_t token) { tokenId_ = token; } + +int32_t DCameraSourceDev::UpdateDCameraWorkMode(const WorkModeParam& param) +{ + CHECK_AND_RETURN_RET_LOG(input_ == nullptr, DCAMERA_BAD_VALUE, "input_ is nullptr"); + int32_t ret = input_->UpdateWorkMode(param); + DHLOGI("update dcamera workmode by input_ done, ret %{public}d", ret); + return ret; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_data_process.cpp b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_data_process.cpp index c2b676bc3658c8144b81fcd1582f6bc3d8b93c9c..98522b5908a686f5c5b4b6bbcca3b02cb82a0971 100644 --- a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_data_process.cpp +++ b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_data_process.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -216,5 +216,20 @@ void DCameraSourceDataProcess::GetAllStreamIds(std::vector& streamIds) { streamIds.assign(streamIds_.begin(), streamIds_.end()); } + +int32_t DCameraSourceDataProcess::UpdateProducerWorkMode(std::vector& streamIds, const WorkModeParam& param) +{ + DHLOGI("DCameraSourceDataProcess UpdateProducerWorkMode devId %{public}s dhId %{public}s", + GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str()); + int32_t ret = DCAMERA_OK; + for (auto iter = streamProcess_.begin(); iter != streamProcess_.end(); iter++) { + int32_t currentRet = (*iter)->UpdateProducerWorkMode(streamIds, param); + if (currentRet != DCAMERA_OK) { + DHLOGE("DCameraSourceDataProcess UpdateProducerWorkMode failed, ret:%{public}d", currentRet); + ret = currentRet; + } + } + return ret; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_input.cpp b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_input.cpp index 294ab4d200daa297857ad383c6ca317780d6b1f1..36ac4a8c3f820801e994bab0a3777a50480549bc 100644 --- a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_input.cpp +++ b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_source_input.cpp @@ -506,5 +506,19 @@ int32_t DCameraSourceInput::EstablishSnapshotFrameSession(std::vector streamIds; + auto dataprocess = dataProcess_.find(CONTINUOUS_FRAME); + CHECK_AND_RETURN_RET_LOG(dataprocess == dataProcess_.end(), DCAMERA_BAD_OPERATE, "can not find continuous frame"); + CHECK_AND_RETURN_RET_LOG(dataprocess->second == nullptr, DCAMERA_BAD_OPERATE, "dataprocess->second is nullptr"); + dataprocess->second->GetAllStreamIds(streamIds); + int32_t ret = dataprocess->second->UpdateProducerWorkMode(streamIds, param); + DHLOGI("update continue stream workmode finished, ret:%{public}d", ret); + return ret; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process.cpp b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process.cpp index 361a08f3e65703e903166a84a4b54cec7f1e5ef2..f2fb6d5c4ae4017c1ce7c28cd083fed10439e30f 100644 --- a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process.cpp +++ b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -308,5 +308,23 @@ Videoformat DCameraStreamDataProcess::GetPipelineFormat(int32_t format) } return videoFormat; } + +int32_t DCameraStreamDataProcess::UpdateProducerWorkMode(std::vector& streamIds, const WorkModeParam& param) +{ + std::lock_guard autoLock(producerMutex_); + for (auto iter = streamIds.begin(); iter != streamIds.end(); iter++) { + uint32_t streamId = *iter; + auto producerIter = producers_.find(streamId); + if (producerIter != producers_.end()) { + DHLOGI("update producer workmode, streamId: %{public}" PRIu32, streamId); + if (producerIter->second == nullptr) { + DHLOGE("update producer workmode failed, streamId: %{public}" PRIu32, streamId); + return DCAMERA_BAD_OPERATE; + } + producerIter->second->UpdateProducerWorkMode(param); + } + } + return DCAMERA_OK; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.cpp b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.cpp index 97e78bcf3bb40d5c39702f66ec50d5de25307a1d..61ac4d5924fad4b8f6571aa35492fec4595cd353 100644 --- a/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.cpp +++ b/services/cameraservice/sourceservice/src/distributedcameramgr/dcameradata/dcamera_stream_data_process_producer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -33,13 +33,15 @@ namespace DistributedHardware { DCameraStreamDataProcessProducer::DCameraStreamDataProcessProducer(std::string devId, std::string dhId, int32_t streamId, DCStreamType streamType) : devId_(devId), dhId_(dhId), streamId_(streamId), streamType_(streamType), eventHandler_(nullptr), - camHdiProvider_(nullptr) + camHdiProvider_(nullptr), workModeParam_(-1, 0, 0, false) { DHLOGI("DCameraStreamDataProcessProducer Constructor devId %{public}s dhId %{public}s streamType: %{public}d " "streamId: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_); state_ = DCAMERA_PRODUCER_STATE_STOP; interval_ = DCAMERA_PRODUCER_ONE_MINUTE_MS / DCAMERA_PRODUCER_FPS_DEFAULT; photoCount_ = COUNT_INIT_NUM; + syncRunning_.store(false); + isFirstFrame_.store(true); } DCameraStreamDataProcessProducer::~DCameraStreamDataProcessProducer() @@ -71,6 +73,10 @@ void DCameraStreamDataProcessProducer::Start() smootherListener_ = std::make_shared(shared_from_this()); smoother_->RegisterListener(smootherListener_); smoother_->StartSmooth(); + + // Start the audio and video synchronization thread + syncRunning_.store(true); + syncThread_ = std::thread([this]() { this->SyncVideoThread(); }); } else { producerThread_ = std::thread([this]() { this->LooperSnapShot(); }); } @@ -96,6 +102,17 @@ void DCameraStreamDataProcessProducer::Stop() } eventThread_.join(); eventHandler_ = nullptr; + // Stop the audio and video synchronization thread + if (syncMem_ != nullptr) { + syncMem_->UnmapAshmem(); + syncMem_->CloseAshmem(); + syncMem_ = nullptr; + } + syncRunning_.store(false); + syncBufferCond_.notify_all(); + if (syncThread_.joinable()) { + syncThread_.join(); + } } else { producerCon_.notify_one(); producerThread_.join(); @@ -280,6 +297,16 @@ void DCameraStreamDataProcessProducer::OnSmoothFinished(const std::shared_ptrData(), buffer->Size()); } #endif + { + // Check if audio-video synchronization is enabled + std::lock_guard lock(workModeParamMtx_); + DHLOGD("OnSmoothFinished rawTime: %{public}" PRIu64 ", isAVsync: %{public}d", + buffer->frameInfo_.rawTime, workModeParam_.isAVsync); + if (workModeParam_.isAVsync) { + WritePtsAndAddBuffer(buffer); + return; + } + } auto feedFunc = [this, dhBase, buffer]() { FeedStreamToDriver(dhBase, buffer); }; @@ -287,5 +314,226 @@ void DCameraStreamDataProcessProducer::OnSmoothFinished(const std::shared_ptrPostTask(feedFunc); } } + +void DCameraStreamDataProcessProducer::WritePtsAndAddBuffer(const std::shared_ptr& buffer) +{ + bool ret = false; + if (syncMem_ == nullptr) { + syncMem_ = sptr(new (std::nothrow) Ashmem(workModeParam_.fd, workModeParam_.sharedMemLen)); + CHECK_AND_RETURN_LOG(syncMem_ == nullptr, "SyncVideoFrame: syncMem_ is nullptr"); + + ret = syncMem_->MapReadAndWriteAshmem(); + CHECK_AND_RETURN_LOG(!ret, "SyncVideoFrame: MapReadAndWriteAshmem failed"); + } else { + DHLOGI("SyncVideoFrame: syncMem_ is already init"); + } + auto syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + SyncSharedData *readSyncSharedData = reinterpret_cast(const_cast(syncData)); + CHECK_AND_RETURN_LOG(readSyncSharedData == nullptr, "read SyncData failed"); + // get voliate lock + while (!readSyncSharedData->lock) { + DHLOGI("readSyncSharedData->lock is false"); + syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + readSyncSharedData = reinterpret_cast(const_cast(syncData)); + } + DHLOGI("readSyncSharedData->lock is true"); + readSyncSharedData->lock = 0; + ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_LOG(!ret, "write sync data failed!"); + readSyncSharedData->video_current_pts = buffer->frameInfo_.rawTime; + readSyncSharedData->video_update_clock = GetNowTimeStampUs(); + readSyncSharedData->reset = false; + readSyncSharedData->lock = 1; + ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_LOG(!ret, "write sync data failed!"); + std::lock_guard lock(syncBufferMutex_); + if (syncBufferQueue_.size() >= DCAMERA_MAX_SYNC_BUFFER_SIZE) { + DHLOGI("Sync buffer full, drop oldest frame, streamId: %{public}d", streamId_); + syncBufferQueue_.pop_front(); + } + syncBufferQueue_.push_back(buffer); + syncBufferCond_.notify_one(); // Notify the synchronization thread to process + return; +} + +void DCameraStreamDataProcessProducer::SyncVideoThread() +{ + DHLOGI("SyncVideoThread started for streamId: %{public}d", streamId_); + const std::chrono::milliseconds FRAME_INTERVAL(DCAMERA_SYNC_TIME_INTERVAL); // 33ms per frame + std::chrono::steady_clock::time_point nextScheduleTime; + + while (syncRunning_.load()) { + std::shared_ptr buffer = nullptr; + + // Wait for video frames in the sync queue + bool shouldBreak = WaitForVideoFrame(buffer); + if (shouldBreak) { + break; + } + + if (buffer == nullptr) { + continue; + } + + // Record the start time when the first frame is sent + if (isFirstFrame_.load()) { + nextScheduleTime = std::chrono::steady_clock::now(); + isFirstFrame_.store(false); + DHLOGI("First frame timestamp recorded, streamId: %{public}d", streamId_); + } + + // Synchronization frame judgment + uint64_t videoPtsUs = buffer->frameInfo_.rawTime; + int32_t syncResult = SyncVideoFrame(videoPtsUs); + if (syncResult == 1) { + // Synchronization successful, sending video frame + DHLOGI("Video frame in sync range, sending..."); + DHBase dhBase; + dhBase.deviceId_ = devId_; + dhBase.dhId_ = dhId_; + + int32_t ret = FeedStreamToDriver(dhBase, buffer); + if (ret != DCAMERA_OK) { + DHLOGE("FeedStreamToDriver failed, ret: %{public}d, streamId: %{public}d", ret, streamId_); + } else { + // FeedStreamToDriver success video_update_clock + DHLOGI("FeedStreamToDriver success, streamId: %{public}d", streamId_); + UpdateVideoClock(videoPtsUs); + } + nextScheduleTime += FRAME_INTERVAL; // Perform timed scheduling after successful transmission + std::this_thread::sleep_until(nextScheduleTime); + } else if (syncResult == 0) { + DHLOGI("Video frame too early, rescheduling for next cycle..."); + { + std::lock_guard lock(syncBufferMutex_); + syncBufferQueue_.push_front(buffer); + } + + // Perform timed scheduling after successful transmission + nextScheduleTime += FRAME_INTERVAL; + std::this_thread::sleep_until(nextScheduleTime); + } else { + // Video frame is too late, discard directly and process next frame immediately + DHLOGI("Video frame too late, dropped..."); + continue; + } + } + + DHLOGI("SyncVideoThread exited for streamId: %{public}d", streamId_); +} + +bool DCameraStreamDataProcessProducer::WaitForVideoFrame(std::shared_ptr& buffer) +{ + std::unique_lock lock(syncBufferMutex_); + syncBufferCond_.wait(lock, [this] { + return !syncBufferQueue_.empty() || !syncRunning_.load(); + }); + + if (!syncRunning_.load()) { + return true; // exit + } + + if (!syncBufferQueue_.empty() && syncBufferQueue_.size() >= DCAMERA_SYNC_WATERMARK) { + buffer = syncBufferQueue_.front(); + syncBufferQueue_.pop_front(); + } + + return false; // don't exit +} + +int32_t DCameraStreamDataProcessProducer::SyncVideoFrame(uint64_t videoPtsUs) +{ + int64_t videoPts = videoPtsUs / DCAMERA_NS_TO_MS; // us -> ms + int64_t audioPts = 0; // get audio timestamp from shared memory + int64_t audioUpdatePts = 0; // audio update time + float audioSpeed = 1.0f; // audio playback speed factor + bool ret = false; + CHECK_AND_RETURN_RET_LOG(syncMem_ == nullptr, DCAMERA_BAD_VALUE, "SyncVideoFrame: syncMem_ is nullptr."); + auto syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + SyncSharedData *readSyncSharedData = reinterpret_cast(const_cast(syncData)); + CHECK_AND_RETURN_RET_LOG(readSyncSharedData == nullptr, DCAMERA_BAD_VALUE, "read SyncData failed"); + // get voliate lock + while (!readSyncSharedData->lock) { + DHLOGI("readSyncSharedData->lock is false"); + syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + readSyncSharedData = reinterpret_cast(const_cast(syncData)); + } + readSyncSharedData->lock = 0; + ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, DCAMERA_BAD_VALUE, "write sync data failed!"); + audioPts = readSyncSharedData->audio_current_pts / DCAMERA_US_TO_MS; // us -> ms + audioUpdatePts = readSyncSharedData->audio_update_clock / DCAMERA_US_TO_MS; // us -> ms + audioSpeed = readSyncSharedData->audio_speed; + readSyncSharedData->lock = 1; + ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, DCAMERA_BAD_VALUE, "write sync data failed!"); + + int64_t currentTime = static_cast(GetNowTimeStampMs()); + int64_t estimatedPts = static_cast(audioPts + (currentTime - audioUpdatePts) * audioSpeed); + + int64_t diff = static_cast(estimatedPts - videoPts); // calculate audio-video time difference + DHLOGD("SyncCheck: videoPts=%{public}" PRIu64 ", estimatedPts=%{public}" PRIu64 ", diff=%{public}" PRId64 "ms", + videoPts, estimatedPts, diff); + + if (diff > DCAMERA_TIME_DIFF_MAX) { + DHLOGI("SyncVideoFrame::Video is too late (diff=%{public}" PRId64 "ms), skip this frame.", diff); + // Drop if there is still data in the queue, play the last frame directly + return (syncBufferQueue_.size() > 0) ? -1 : 1; + } else if (diff < DCAMERA_TIME_DIFF_MIN) { + DHLOGI("SyncVideoFrame::Video is too early (diff=%{public}" PRId64 "ms), wait for next scheduling.", diff); + return 0; + } else { + DHLOGD("SyncVideoFrame::Video frame in sync range, will be sent. diff=%{public}" PRId64 "ms", diff); + return 1; + } +} + +void DCameraStreamDataProcessProducer::UpdateVideoClock(uint64_t videoPtsUs) +{ + { + std::lock_guard lock(workModeParamMtx_); + if (!workModeParam_.isAVsync) { + return; + } + } + + CHECK_AND_RETURN_LOG(syncMem_ == nullptr, "UpdateVideoClock: syncMem_ is nullptr."); + + auto syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + SyncSharedData *readSyncSharedData = reinterpret_cast(const_cast(syncData)); + CHECK_AND_RETURN_LOG(readSyncSharedData == nullptr, "read SyncData failed"); + while (!readSyncSharedData->lock) { + syncData = syncMem_->ReadFromAshmem(workModeParam_.sharedMemLen, 0); + readSyncSharedData = reinterpret_cast(const_cast(syncData)); + } + readSyncSharedData->lock = 0; + bool ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_LOG(!ret, "write sync data failed!"); + readSyncSharedData->video_current_pts = videoPtsUs; + readSyncSharedData->video_update_clock = GetNowTimeStampUs(); + readSyncSharedData->reset = false; + readSyncSharedData->lock = 1; + ret = syncMem_->WriteToAshmem(static_cast(readSyncSharedData), sizeof(SyncSharedData), 0); + CHECK_AND_RETURN_LOG(!ret, "write sync data failed!"); + DHLOGD("Video update clock updated to: %" PRIu64 " us", readSyncSharedData->video_update_clock); +} + +void DCameraStreamDataProcessProducer::UpdateProducerWorkMode(const WorkModeParam& param) +{ + DHLOGI("begin update producer workmode"); + if (!param.isAVsync) { + if (syncMem_ != nullptr) { + syncMem_->UnmapAshmem(); + syncMem_->CloseAshmem(); + syncMem_ = nullptr; + DHLOGI("syncMem_ release success."); + } + } + { + std::lock_guard lock(workModeParamMtx_); + workModeParam_ = param; + } + DHLOGI("update producer workmode success"); +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_service_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_service_test.cpp index 7caa25a36b5fcd1e82eca13c1e92cbc349ac6744..63a5ca89ab84c227073b48f38d451292f7805273 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_service_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_service_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -241,5 +241,21 @@ HWTEST_F(DistributedCameraSourceServiceTest, dcamera_source_service_test_009, Te EXPECT_EQ(DCAMERA_OK, ret); usleep(TEST_SOURCE_SERVICE); } + +/** + * @tc.name: dcamera_source_service_test_010 + * @tc.desc: Verify the UpdateDistributedHardwareWorkMode function. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DistributedCameraSourceServiceTest, dcamera_source_service_test_010, TestSize.Level1) +{ + DHLOGI("DistributedCameraSourceServiceTest::dcamera_source_service_test_010"); + EXPECT_EQ(false, testSrcService_ == nullptr); + + WorkModeParam param(12, 120, 0, false);; + int32_t ret = testSrcService_->UpdateDistributedHardwareWorkMode(TEST_DEVICE_ID, TEST_CAMERA_DH_ID_0, param); + EXPECT_EQ(DCAMERA_BAD_OPERATE, ret); +} } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_stub_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_stub_test.cpp index 5ad1c54db89da25dc0671506d8a8cdfdbc169e6a..26864f6d284b414befc7a7592c98fe4f2b455736 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_stub_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/distributed_camera_source_stub_test.cpp @@ -16,6 +16,7 @@ #include #include "accesstoken_kit.h" +#include "ashmem.h" #include "nativetoken_kit.h" #include "token_setproc.h" #include "softbus_common.h" @@ -270,5 +271,83 @@ HWTEST_F(DcameraSourceStubTest, dcamera_source_stub_test_008, TestSize.Level1) ret = sourceProxy.RegisterDistributedHardware(devId, dhId, reqId, param); EXPECT_EQ(DCAMERA_BAD_VALUE, ret); } + +/** + * @tc.name: dcamera_source_stub_test_009 + * @tc.desc: Verify the UpdateDistributedHardwareWorkMode function. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DcameraSourceStubTest, dcamera_source_stub_test_009, TestSize.Level1) +{ + DHLOGI("DcameraSourceStubTest::dcamera_source_stub_test_009"); + sptr sourceStubPtr(new MockDistributedCameraSourceStub()); + DistributedCameraSourceProxy sourceProxy(sourceStubPtr); + std::string devId = ""; + std::string dhId = "dhId000"; + WorkModeParam param(-1, 0, 0, false); + + int32_t ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + devId = "devId000"; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + dhId = ""; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + dhId = "dhId000"; + param.sharedMemLen = 120; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + param.fd = 12; + param.sharedMemLen = 0; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); +} + +/** + * @tc.name: dcamera_source_stub_test_010 + * @tc.desc: Verify the UpdateDistributedHardwareWorkMode function. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DcameraSourceStubTest, dcamera_source_stub_test_010, TestSize.Level1) +{ + DHLOGI("DcameraSourceStubTest::dcamera_source_stub_test_009"); + sptr sourceStubPtr(new MockDistributedCameraSourceStub()); + DistributedCameraSourceProxy sourceProxy(sourceStubPtr); + std::string devId = ""; + std::string dhId = "dhId000"; + WorkModeParam param(-1, 0, 0, false); + + int32_t ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + devId = "devId000"; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + dhId = ""; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + dhId = "dhId000"; + param.sharedMemLen = 120; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + + uint32_t memLen = sizeof(static_cast(120)); + std::string memName = "testMemory"; + auto syncSharedMem = OHOS::Ashmem::CreateAshmem(memName.c_str(), memLen); + param.fd = syncSharedMem->GetAshmemFd(); + param.sharedMemLen = 120; + ret = sourceProxy.UpdateDistributedHardwareWorkMode(devId, dhId, param); + EXPECT_EQ(DCAMERA_OK, ret); + syncSharedMem->CloseAshmem(); +} } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/mock_distributed_camera_source_stub.h b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/mock_distributed_camera_source_stub.h index 2809bc23a9efad0d641365e1edb9220e0a0acce2..d7a838f6489288dc3ddc9446b4afa74475a37f63 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/mock_distributed_camera_source_stub.h +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcamera/mock_distributed_camera_source_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -64,6 +64,15 @@ public: (void)events; return DCAMERA_OK; } + + int32_t UpdateDistributedHardwareWorkMode(const std::string& devId, const std::string& dhId, + const WorkModeParam& param) + { + (void)devId; + (void)dhId; + (void)param; + return DCAMERA_OK; + } }; diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_data_process_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_data_process_test.cpp index 541bd1c308c7c77b8944c1dec2ba72e63b0c965b..3522c072bc93214b44d14f14f076118a06d12989 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_data_process_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_data_process_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -214,5 +214,34 @@ HWTEST_F(DCameraSourceDataProcessTest, dcamera_source_data_process_test_006, Tes rc = testSrcDataProcess_->ReleaseStreams(g_streamIds); EXPECT_EQ(rc, DCAMERA_OK); } + +/** + * @tc.name: dcamera_source_data_process_test_007 + * @tc.desc: Verify UpdateProducerWorkMode. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraSourceDataProcessTest, dcamera_source_data_process_test_007, TestSize.Level1) +{ + EXPECT_EQ(false, testSrcDataProcess_ == nullptr); + + std::shared_ptr captureInfo = std::make_shared(); + captureInfo->streamIds_.push_back(1); + captureInfo->width_ = TEST_WIDTH; + captureInfo->height_ = TEST_HEIGTH; + captureInfo->stride_ = 1; + captureInfo->format_ = 1; + captureInfo->dataspace_ = 1; + captureInfo->encodeType_ = ENCODE_TYPE_H265; + captureInfo->type_ = CONTINUOUS_FRAME; + int32_t rc = testSrcDataProcess_->StartCapture(captureInfo); + EXPECT_EQ(rc, DCAMERA_OK); + + std::vector streamIds; + streamIds.push_back(1); + WorkModeParam param(12, 120, 0, false); + rc = testSrcDataProcess_->UpdateProducerWorkMode(streamIds, param); + EXPECT_EQ(rc, DCAMERA_OK); +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_dev_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_dev_test.cpp index bb2638b0031752085c7020cbb2eb617b16938ab0..757a9e656d7d78bc5a90c659039deb5368074406 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_dev_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_dev_test.cpp @@ -703,6 +703,23 @@ HWTEST_F(DCameraSourceDevTest, dcamera_source_dev_test_022, TestSize.Level1) EXPECT_EQ(DCAMERA_OK, ret); } +/** + * @tc.name: dcamera_source_dev_test_023 + * @tc.desc: Verify source dev UpdateDCameraWorkMode. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraSourceDevTest, dcamera_source_dev_test_023, TestSize.Level1) +{ + WorkModeParam param(12, 120, 0, false); + int32_t ret = camDev_->UpdateDCameraWorkMode(param); + EXPECT_EQ(DCAMERA_BAD_VALUE, ret); + camDev_->InitDCameraSourceDev(); + camDev_->input_->Init(); + ret = camDev_->UpdateDCameraWorkMode(param); + EXPECT_EQ(DCAMERA_OK, ret); +} + /** * @tc.name: SetHicollieFlag_001 * @tc.desc: Verify source dev SetHicollieFlag. diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_input_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_input_test.cpp index 5bc85ea0b7ccbf3b64b7504bb6a8caf1eab93426..598ed787406c15f99e92f5d5b93dcee635ace02e 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_input_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_source_input_test.cpp @@ -455,5 +455,30 @@ HWTEST_F(DCameraSourceInputTest, dcamera_source_input_test_014, TestSize.Level1) testInputListener->OnDataReceived(buffers); EXPECT_EQ(true, capacity == 0); } + +/** + * @tc.name: dcamera_source_input_test_015 + * @tc.desc: Verify source inptut UpdateWorkMode. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraSourceInputTest, dcamera_source_input_test_015, TestSize.Level1) +{ + EXPECT_EQ(false, testInput_ == nullptr); + + int32_t rc = testInput_->Init(); + EXPECT_EQ(rc, DCAMERA_OK); + + rc = testInput_->ConfigStreams(g_streamInfos); + EXPECT_EQ(rc, DCAMERA_OK); + + WorkModeParam param(12, 120, 0, false); + rc = testInput_->UpdateWorkMode(param); + EXPECT_EQ(rc, DCAMERA_OK); + + rc = testInput_->UnInit(); + EXPECT_EQ(rc, DCAMERA_OK); +} + } // namespace DistributedHardware } // namespace OHOS diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_producer_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_producer_test.cpp index bb6fe7c5719825740ad21d220ac3615232b5d98a..3dc9434560691810067d69c85b49a6133c672746 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_producer_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_producer_test.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #define private public #include "dcamera_stream_data_process_producer.h" #undef private @@ -24,6 +25,7 @@ #include "distributed_camera_constants.h" #include "distributed_camera_errno.h" #include "distributed_hardware_log.h" +#include "idistributed_camera_source.h" #include "v1_1/dcamera_types.h" using namespace testing::ext; @@ -36,6 +38,12 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + + std::shared_ptr producer_ = nullptr; + std::string devId_ = "test_devId"; + std::string dhId_ = "test_dhId"; + int32_t streamId_ = 1; + DCStreamType streamType_ = CONTINUOUS_FRAME; }; namespace { @@ -44,22 +52,32 @@ const std::string TEST_CAMERA_DH_ID_0 = "camera_0"; const uint8_t SLEEP_TIME = 1; const int32_t STREAM_ID_1 = 1; const int32_t STREAM_ID_2 = 2; -#define DCAMERA_PRODUCER_MAX_BUFFER_SIZE 2 } void DCameraStreamDataProcessProducerTest::SetUpTestCase(void) { + DHLOGI("DCameraStreamDataProcessProducerTest SetUpTestCase"); } void DCameraStreamDataProcessProducerTest::TearDownTestCase(void) { + DHLOGI("DCameraStreamDataProcessProducerTest TearDownTestCase"); } void DCameraStreamDataProcessProducerTest::SetUp(void) { + DHLOGI("DCameraStreamDataProcessProducerTest SetUp"); + producer_ = std::make_shared(devId_, dhId_, streamId_, streamType_); } void DCameraStreamDataProcessProducerTest::TearDown(void) { + DHLOGI("DCameraStreamDataProcessProducerTest TearDown"); + if (producer_ != nullptr) { + if (producer_->state_ == DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_START) { + producer_->Stop(); + } + producer_ = nullptr; + } } /** @@ -228,5 +246,520 @@ HWTEST_F(DCameraStreamDataProcessProducerTest, dcamera_stream_data_process_produ ret = streamProcess2->FeedStreamToDriver(dhBase, buffer); EXPECT_EQ(DCAMERA_BAD_VALUE, ret); } + +/** + * @tc.name: Start_001 + * @tc.desc: Verify DCameraStreamDataProcessProducer Start with CONTINUOUS_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, Start_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest Start_001"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->Start(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_START, producer_->state_); +} + +/** + * @tc.name: Start_002 + * @tc.desc: Test DCameraStreamDataProcessProducer Start with SNAPSHOT_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, Start_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest Start_002"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = SNAPSHOT_FRAME; + producer_->Start(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_START, producer_->state_); +} + +/** + * @tc.name: Stop_001 + * @tc.desc: Test DCameraStreamDataProcessProducer Stop when in start state with CONTINUOUS_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, Stop_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest Stop_001"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->Start(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_START, producer_->state_); + producer_->Stop(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_STOP, producer_->state_); +} + +/** + * @tc.name: Stop_002 + * @tc.desc: Test DCameraStreamDataProcessProducer Stop when in start state with SNAPSHOT_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, Stop_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest Stop_002"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = SNAPSHOT_FRAME; + producer_->Start(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_START, producer_->state_); + producer_->Stop(); + EXPECT_EQ(DCameraStreamDataProcessProducer::DCAMERA_PRODUCER_STATE_STOP, producer_->state_); +} + +/** + * @tc.name: FeedStream_001 + * @tc.desc: Test DCameraStreamDataProcessProducer FeedStream with CONTINUOUS_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, FeedStream_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest FeedStream_001"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->Start(); + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000; + producer_->FeedStream(buffer); + producer_->Stop(); + SUCCEED(); +} + +/** + * @tc.name: FeedStream_002 + * @tc.desc: Test DCameraStreamDataProcessProducer FeedStream with SNAPSHOT_FRAME stream type. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, FeedStream_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest FeedStream_002"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = SNAPSHOT_FRAME; + producer_->Start(); + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000; + producer_->FeedStream(buffer); + { + std::lock_guard lock(producer_->bufferMutex_); + EXPECT_FALSE(producer_->buffers_.empty()); + } + producer_->Stop(); +} + +/** + * @tc.name: FeedStream_003 + * @tc.desc: Test DCameraStreamDataProcessProducer FeedStream when buffer queue is full. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, FeedStream_003, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest FeedStream_003"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = SNAPSHOT_FRAME; + producer_->Start(); + + for (uint32_t i = 0; i <= producer_->DCAMERA_PRODUCER_MAX_BUFFER_SIZE; i++) { + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000 + i * 1000; // Incremental timestamps + producer_->FeedStream(buffer); + } + + { + std::lock_guard lock(producer_->bufferMutex_); + EXPECT_EQ(producer_->buffers_.size(), producer_->DCAMERA_PRODUCER_MAX_BUFFER_SIZE); + } + producer_->Stop(); +} + +/** + * @tc.name: OnSmoothFinished_001 + * @tc.desc: Test DCameraStreamDataProcessProducer OnSmoothFinished with AV sync disabled. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, OnSmoothFinished_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest OnSmoothFinished_001"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->DCameraStreamDataProcessProducer::workModeParam_.isAVsync = false; + producer_->Start(); + + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000; // 1s in us + auto feedableData = std::static_pointer_cast(buffer); + producer_->OnSmoothFinished(feedableData); + + producer_->Stop(); + SUCCEED(); +} + +/** + * @tc.name: OnSmoothFinished_002 + * @tc.desc: Test DCameraStreamDataProcessProducer OnSmoothFinished with AV sync enabled. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, OnSmoothFinished_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest OnSmoothFinished_002"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->DCameraStreamDataProcessProducer::workModeParam_.isAVsync = true; + producer_->Start(); + + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000; // 1s in us + auto feedableData = std::static_pointer_cast(buffer); + producer_->OnSmoothFinished(feedableData); + + { + std::lock_guard lock(producer_->syncBufferMutex_); + EXPECT_TRUE(producer_->syncBufferQueue_.empty()); + } + producer_->Stop(); +} + +/** + * @tc.name: OnSmoothFinished_003 + * @tc.desc: Test DCameraStreamDataProcessProducer OnSmoothFinished with full sync buffer queue. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, OnSmoothFinished_003, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest OnSmoothFinished_003"); + ASSERT_NE(producer_, nullptr); + producer_->streamType_ = CONTINUOUS_FRAME; + producer_->DCameraStreamDataProcessProducer::workModeParam_.isAVsync = true; + producer_->Start(); + + for (uint32_t i = 0; i <= producer_->DCAMERA_MAX_SYNC_BUFFER_SIZE; i++) { + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000 + i * 1000; // Incremental timestamps + auto feedableData = std::static_pointer_cast(buffer); + producer_->OnSmoothFinished(feedableData); + } + + { + std::lock_guard lock(producer_->syncBufferMutex_); + EXPECT_EQ(producer_->syncBufferQueue_.size(), 0); + } + producer_->Stop(); +} + +/** + * @tc.name: UpdateProducerWorkMode_001 + * @tc.desc: Test DCameraStreamDataProcessProducer UpdateProducerWorkMode. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateProducerWorkMode_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateProducerWorkMode_001"); + ASSERT_NE(producer_, nullptr); + WorkModeParam param(-1, 0, 0, 0); + param.fd = 10; + param.sharedMemLen = 1024; + param.isAVsync = true; + param.scene = 0; + + producer_->UpdateProducerWorkMode(param); + uint64_t videoPtsUs = 1000000; + int32_t result = producer_->SyncVideoFrame(videoPtsUs); + EXPECT_TRUE(result == DCAMERA_BAD_VALUE || result == -1 || result == 0 || result == 1); } + +/** + * @tc.name: SyncVideoFrame_001 + * @tc.desc: Test DCameraStreamDataProcessProducer SyncVideoFrame with null syncMem. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, SyncVideoFrame_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest SyncVideoFrame_001"); + ASSERT_NE(producer_, nullptr); + uint64_t videoPtsUs = 1000000; // 1s in us + int32_t result = producer_->SyncVideoFrame(videoPtsUs); + EXPECT_TRUE(result == DCAMERA_BAD_VALUE || result == -1 || result == 0 || result == 1); +} + +/** + * @tc.name: SyncVideoFrame_002 + * @tc.desc: Verify SyncVideoFrame function with different timestamp values. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, SyncVideoFrame_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest SyncVideoFrame_002"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.fd = 10; + param.sharedMemLen = 1024; + param.isAVsync = 1; + param.scene = 0; + producer_->UpdateProducerWorkMode(param); + + uint64_t videoPtsUs1 = 1000000; // 1 second + uint64_t videoPtsUs2 = 50000000; // 50 seconds + uint64_t videoPtsUs3 = 100000; // 0.1 seconds + + int32_t result1 = producer_->SyncVideoFrame(videoPtsUs1); + int32_t result2 = producer_->SyncVideoFrame(videoPtsUs2); + int32_t result3 = producer_->SyncVideoFrame(videoPtsUs3); + + EXPECT_TRUE(result1 == DCAMERA_BAD_VALUE || result1 == -1 || result1 == 0 || result1 == 1); + EXPECT_TRUE(result2 == DCAMERA_BAD_VALUE || result2 == -1 || result2 == 0 || result2 == 1); + EXPECT_TRUE(result3 == DCAMERA_BAD_VALUE || result3 == -1 || result3 == 0 || result3 == 1); +} + +/** + * @tc.name: SyncVideoFrame_003 + * @tc.desc: Verify SyncVideoFrame function when AV sync is disabled. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, SyncVideoFrame_003, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest SyncVideoFrame_003"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.fd = 10; + param.sharedMemLen = 1024; + param.isAVsync = 0; // AV sync disabled + param.scene = 0; + producer_->UpdateProducerWorkMode(param); + + uint64_t videoPtsUs = 1000000; + int32_t result = producer_->SyncVideoFrame(videoPtsUs); + + EXPECT_TRUE(result == DCAMERA_BAD_VALUE || result == -1 || result == 0 || result == 1); +} + +/** + * @tc.name: SyncVideoFrame_004 + * @tc.desc: Integration test for SyncVideoFrame through public interface. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, SyncVideoFrame_004, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest SyncVideoFrame_004"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.fd = 10; + param.sharedMemLen = 1024; + param.isAVsync = 1; + param.scene = 0; + producer_->UpdateProducerWorkMode(param); + + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1000000; // Set a specific timestamp + + producer_->Start(); + + producer_->FeedStream(buffer); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + // Stop the producer + producer_->Stop(); + SUCCEED(); +} + +/** + * @tc.name: UpdateVideoClock_001 + * @tc.desc: Verify UpdateVideoClock function when AV sync is disabled. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateVideoClock_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateVideoClock_001"); + ASSERT_NE(producer_, nullptr); + uint64_t videoPtsUs = 1000000; // 1s in us + WorkModeParam param(-1, 0, 0, 0); + param.isAVsync = 0; + producer_->DCameraStreamDataProcessProducer::workModeParam_ = param; + + producer_->UpdateVideoClock(videoPtsUs); + SUCCEED(); +} + +/** + * @tc.name: UpdateVideoClock_002 + * @tc.desc: Verify UpdateVideoClock function when syncMem is null. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateVideoClock_002, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateVideoClock_002"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.isAVsync = 1; + producer_->DCameraStreamDataProcessProducer::workModeParam_ = param; + producer_->syncMem_ = nullptr; + + uint64_t videoPtsUs = 1000000; + producer_->UpdateVideoClock(videoPtsUs); + + SUCCEED(); +} + +/** + * @tc.name: UpdateVideoClock_003 + * @tc.desc: Verify UpdateVideoClock function updates video clock correctly. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateVideoClock_003, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateVideoClock_003"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.isAVsync = 1; + param.fd = 10; + param.sharedMemLen = 1024; + producer_->DCameraStreamDataProcessProducer::workModeParam_ = param; + + producer_->syncMem_ = sptr(new (std::nothrow) Ashmem(param.fd, param.sharedMemLen)); + + uint64_t videoPtsUs = 2000000; + producer_->UpdateVideoClock(videoPtsUs); + + SUCCEED(); +} + +/** + * @tc.name: UpdateVideoClock_004 + * @tc.desc: Integration test for UpdateVideoClock through FeedStream. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateVideoClock_004, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateVideoClock_004"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.isAVsync = 1; + param.fd = 10; + param.sharedMemLen = 1024; + param.scene = 0; + producer_->UpdateProducerWorkMode(param); + + producer_->Start(); + + auto buffer = std::make_shared(100); + buffer->frameInfo_.rawTime = 1500000; // Set a specific timestamp + + producer_->FeedStream(buffer); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + producer_->Stop(); + SUCCEED(); +} + +/** + * @tc.name: UpdateVideoClock_005 + * @tc.desc: Verify UpdateVideoClock function handles different video timestamps. + * @tc.type: FUNC + * @tc.require: Issue Number + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, UpdateVideoClock_005, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest UpdateVideoClock_005"); + ASSERT_NE(producer_, nullptr); + + WorkModeParam param(-1, 0, 0, 0); + param.isAVsync = 1; + param.fd = 10; + param.sharedMemLen = 1024; + producer_->DCameraStreamDataProcessProducer::workModeParam_ = param; + + producer_->syncMem_ = sptr(new (std::nothrow) Ashmem(param.fd, param.sharedMemLen)); + std::vector timestamps = {0, 1000000, 50000000, 100000000}; + for (uint64_t timestamp : timestamps) { + producer_->UpdateVideoClock(timestamp); + } + + SUCCEED(); +} + +/** + * @tc.name: WaitForVideoFrame_001 + * @tc.desc: Test DCameraStreamDataProcessProducer WaitForVideoFrame with empty queue and stopped sync. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, WaitForVideoFrame_001, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessProducerTest WaitForVideoFrame_001"); + std::shared_ptr buffer = nullptr; + producer_->syncRunning_.store(false); + + bool shouldBreak = producer_->WaitForVideoFrame(buffer); + EXPECT_TRUE(shouldBreak); + EXPECT_EQ(buffer, nullptr); +} + +/** + * @tc.name: dcamera_stream_data_process_producer_test_006 + * @tc.desc: Test UpdateProducerWorkMode func. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, dcamera_stream_data_process_producer_test_006, TestSize.Level1) +{ + DHLOGI("dcamera_stream_data_process_producer_test_006"); + size_t capacity = 1; + std::shared_ptr buffer = std::make_shared(capacity); + std::shared_ptr producer = + std::make_shared(TEST_DEVICE_ID, TEST_CAMERA_DH_ID_0, STREAM_ID_1, + DCStreamType::SNAPSHOT_FRAME); + WorkModeParam param(12, 120, 0, true); + producer->UpdateProducerWorkMode(param); + EXPECT_EQ(true, producer->workModeParam_.isAVsync); +} + +/** + * @tc.name: dcamera_stream_data_process_producer_test_007 + * @tc.desc: Test UpdateProducerWorkMode func. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessProducerTest, dcamera_stream_data_process_producer_test_007, TestSize.Level1) +{ + DHLOGI("dcamera_stream_data_process_producer_test_007"); + size_t capacity = 1; + std::shared_ptr buffer = std::make_shared(capacity); + std::shared_ptr producer = + std::make_shared(TEST_DEVICE_ID, TEST_CAMERA_DH_ID_0, STREAM_ID_1, + DCStreamType::SNAPSHOT_FRAME); + WorkModeParam param(-1, 0, 0, false); + uint32_t memLen = sizeof(static_cast(120)); + std::string memName = "testMemory"; + auto syncSharedMem = OHOS::Ashmem::CreateAshmem(memName.c_str(), memLen); + param.fd = syncSharedMem->GetAshmemFd(); + param.sharedMemLen = 120; + producer->syncMem_ = syncSharedMem; + producer->UpdateProducerWorkMode(param); + EXPECT_EQ(false, producer->workModeParam_.isAVsync); } +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_test.cpp b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_test.cpp index d917b9b25cc78a04f923609cf64cf8fb981fd22a..2696e5f0e2e787f28a0efa08c6b896ae31313cef 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_test.cpp +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/dcamera_stream_data_process_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -271,5 +271,34 @@ HWTEST_F(DCameraStreamDataProcessTest, dcamera_stream_data_process_test_008, Tes ret = streamProcess1->GetPipelineFormat(format); EXPECT_EQ(Videoformat::NV21, ret); } + +/** + * @tc.name: dcamera_stream_data_process_test_002 + * @tc.desc: Verify StartCapture func. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(DCameraStreamDataProcessTest, dcamera_stream_data_process_test_009, TestSize.Level1) +{ + DHLOGI("DCameraStreamDataProcessTest::dcamera_stream_data_process_test_009"); + std::shared_ptr streamProcess = + std::make_shared(TEST_DEVICE_ID, TEST_CAMERA_DH_ID_0, DCStreamType::CONTINUOUS_FRAME); + std::shared_ptr srcConfig = + std::make_shared(TEST_WIDTH, TEST_HEIGTH, TEST_FORMAT, TEST_DATASPACE, + DCEncodeType::ENCODE_TYPE_H264, DCStreamType::SNAPSHOT_FRAME); + + std::set streamIds; + streamIds.insert(1); + WorkModeParam param(12, 120, 0, false); + std::vector streamId; + streamId.push_back(1); + int32_t ret = streamProcess->UpdateProducerWorkMode(streamId, param); + EXPECT_EQ(DCAMERA_OK, ret); + streamProcess->ConfigStreams(srcConfig, streamIds); + streamProcess->StartCapture(srcConfig, streamIds); + ret = streamProcess->UpdateProducerWorkMode(streamId, param); + EXPECT_EQ(DCAMERA_OK, ret); + streamProcess->StopCapture(streamIds); +} } } \ No newline at end of file diff --git a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/mock_dcamera_source_input.h b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/mock_dcamera_source_input.h index 9787f4a37aa63e80ff077ab17024b7bc97e9e39a..c4350ceb8091eaa590b05b4f7f3014a2694092b0 100644 --- a/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/mock_dcamera_source_input.h +++ b/services/cameraservice/sourceservice/test/unittest/common/distributedcameramgr/mock_dcamera_source_input.h @@ -73,6 +73,10 @@ public: { return DCAMERA_OK; } + int32_t UpdateWorkMode(const WorkModeParam& param) + { + return DCAMERA_OK; + } }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/channel/src/dcamera_softbus_adapter.cpp b/services/channel/src/dcamera_softbus_adapter.cpp index 0dbe8f5a013ea51374c8331099f51e3f3980f697..9dbc7c944f36bc819e22a40c4e04b991a2ba74ba 100644 --- a/services/channel/src/dcamera_softbus_adapter.cpp +++ b/services/channel/src/dcamera_softbus_adapter.cpp @@ -324,6 +324,7 @@ int32_t DCameraSoftbusAdapter::SendSofbusStream(int32_t socket, std::shared_ptr< sinkFrameInfo.startEncodeT_ = startEncodeT; sinkFrameInfo.finishEncodeT_ = finishEncodeT; sinkFrameInfo.sendT_ = GetNowTimeStampUs(); + sinkFrameInfo.rawTime_ = std::to_string(timeStamp); sinkFrameInfo.Marshal(jsonStr); StreamData ext = { const_cast(jsonStr.c_str()), jsonStr.length() }; StreamFrameInfo param = { 0 }; @@ -489,6 +490,7 @@ int32_t DCameraSoftbusAdapter::HandleSourceStreamExt(std::shared_ptr frameInfo.pts = sinkFrameInfo.pts_; frameInfo.index = sinkFrameInfo.index_; frameInfo.ver = sinkFrameInfo.ver_; + frameInfo.rawTime = sinkFrameInfo.rawTime_.empty() ? 0 : std::stoll(sinkFrameInfo.rawTime_); frameInfo.timePonit.startEncode = sinkFrameInfo.startEncodeT_; frameInfo.timePonit.finishEncode = sinkFrameInfo.finishEncodeT_; frameInfo.timePonit.send = sinkFrameInfo.sendT_; diff --git a/services/data_process/src/pipeline_node/multimedia_codec/encoder/encode_data_process.cpp b/services/data_process/src/pipeline_node/multimedia_codec/encoder/encode_data_process.cpp index d78ec93361a73d4677fec37059ecc17fd248836d..79a2ccce13582ddece5aa92dd076327cbbb87958 100644 --- a/services/data_process/src/pipeline_node/multimedia_codec/encoder/encode_data_process.cpp +++ b/services/data_process/src/pipeline_node/multimedia_codec/encoder/encode_data_process.cpp @@ -497,9 +497,9 @@ int32_t EncodeDataProcess::GetEncoderOutputBuffer(uint32_t index, MediaAVCodec:: CHECK_AND_RETURN_RET_LOG(err != EOK, DCAMERA_MEMORY_OPT_ERROR, "%{public}s", "memcpy_s buffer failed."); int64_t timeStamp = info.presentationTimeUs; struct timespec time = {0, 0}; - clock_gettime(CLOCK_MONOTONIC, &time); + clock_gettime(CLOCK_REALTIME, &time); int64_t timeNs = static_cast(time.tv_sec) * S2NS + static_cast(time.tv_nsec); - int64_t encodeT = (timeNs - timeStamp) / static_cast(US2NS); + int64_t encodeT = timeNs / static_cast(US2NS) - timeStamp; int64_t finishEncodeT = GetNowTimeStampUs(); int64_t startEncodeT = finishEncodeT - encodeT; bufferOutput->SetInt64(START_ENCODE_TIME_US, startEncodeT);