1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "av_sync_manager.h"
17
18 #include <set>
19 #include "nlohmann/json.hpp"
20
21 #include "av_trans_control_center.h"
22 #include "av_trans_log.h"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 #undef DH_LOG_TAG
27 #define DH_LOG_TAG "AVSyncManager"
28
AVSyncManager()29 AVSyncManager::AVSyncManager()
30 {
31 AVTRANS_LOGI("AVSyncManager ctor.");
32 sourceMemory_ = { 0, 0, "" };
33 sinkMemory_ = { 0, 0, "" };
34 }
35
~AVSyncManager()36 AVSyncManager::~AVSyncManager()
37 {
38 AVTRANS_LOGI("AVSyncManager dctor.");
39 streamInfoList_.clear();
40 CloseAVTransSharedMemory(sourceMemory_);
41 CloseAVTransSharedMemory(sinkMemory_);
42 }
43
AddStreamInfo(const AVStreamInfo & stream)44 void AVSyncManager::AddStreamInfo(const AVStreamInfo &stream)
45 {
46 AVTRANS_LOGI("add new stream info: sceneType=%s, peerDevId=%s", stream.sceneType.c_str(),
47 GetAnonyString(stream.peerDevId).c_str());
48 {
49 std::lock_guard<std::mutex> lock(listMutex_);
50 streamInfoList_.push_back(stream);
51
52 if (streamInfoList_.size() < AV_SYNC_STREAM_COUNT) {
53 AVTRANS_LOGI("No need enable sender av sync, stream info list size=%zu", streamInfoList_.size());
54 return;
55 }
56 }
57 EnableSenderAVSync();
58 }
59
RemoveStreamInfo(const AVStreamInfo & stream)60 void AVSyncManager::RemoveStreamInfo(const AVStreamInfo &stream)
61 {
62 AVTRANS_LOGI("remove stream info: sceneType=%s, peerDevId=%s", stream.sceneType.c_str(),
63 GetAnonyString(stream.peerDevId).c_str());
64 {
65 std::lock_guard<std::mutex> lock(listMutex_);
66 for (auto iter = streamInfoList_.begin(); iter != streamInfoList_.end();) {
67 if (((*iter).sceneType == stream.sceneType) && ((*iter).peerDevId == stream.peerDevId)) {
68 iter = streamInfoList_.erase(iter);
69 } else {
70 iter++;
71 }
72 }
73 }
74 DisableSenderAVSync();
75 }
76
EnableSenderAVSync()77 void AVSyncManager::EnableSenderAVSync()
78 {
79 std::string syncGroupInfo;
80 if (!MergeGroupInfo(syncGroupInfo)) {
81 AVTRANS_LOGI("No need start av sync.");
82 return;
83 }
84 AVTRANS_LOGI("merged av sync group info=%s", GetAnonyString(syncGroupInfo).c_str());
85 {
86 std::lock_guard<std::mutex> lock(listMutex_);
87 for (const auto &item : streamInfoList_) {
88 auto avMessage = std::make_shared<AVTransMessage>((uint32_t)AVTransTag::START_AV_SYNC,
89 syncGroupInfo, item.peerDevId);
90 AVTransControlCenter::GetInstance().SendMessage(avMessage);
91 }
92 }
93
94 sourceMemory_ = CreateAVTransSharedMemory("sourceSharedMemory", sizeof(uint32_t) + sizeof(int64_t));
95 AVTransControlCenter::GetInstance().SetParam2Engines(sourceMemory_);
96 }
97
DisableSenderAVSync()98 void AVSyncManager::DisableSenderAVSync()
99 {
100 {
101 std::lock_guard<std::mutex> lock(listMutex_);
102 if (streamInfoList_.size() >= AV_SYNC_STREAM_COUNT) {
103 AVTRANS_LOGI("Cannot disable sender av sync, stream info list size=%zu", streamInfoList_.size());
104 return;
105 }
106 for (const auto &item : streamInfoList_) {
107 auto avMessage = std::make_shared<AVTransMessage>((uint32_t)AVTransTag::STOP_AV_SYNC, "", item.peerDevId);
108 AVTransControlCenter::GetInstance().SendMessage(avMessage);
109 }
110 }
111 CloseAVTransSharedMemory(sourceMemory_);
112 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransSharedMemory{0, 0, "sourceSharedMemory"});
113 }
114
HandleAvSyncMessage(const std::shared_ptr<AVTransMessage> & message)115 void AVSyncManager::HandleAvSyncMessage(const std::shared_ptr<AVTransMessage> &message)
116 {
117 if (message->type_ == (uint32_t)AVTransTag::START_AV_SYNC) {
118 EnableReceiverAVSync(message->content_);
119 } else if (message->type_ == (uint32_t)AVTransTag::STOP_AV_SYNC) {
120 DisableReceiverAVSync(message->content_);
121 }
122 }
123
EnableReceiverAVSync(const std::string & groupInfo)124 void AVSyncManager::EnableReceiverAVSync(const std::string &groupInfo)
125 {
126 size_t size = (sizeof(uint32_t) + sizeof(int64_t)) * MAX_CLOCK_UNIT_COUNT;
127 sinkMemory_ = CreateAVTransSharedMemory("sinkSharedMemory", size);
128
129 AVTransControlCenter::GetInstance().SetParam2Engines(sinkMemory_);
130 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransTag::START_AV_SYNC, groupInfo);
131 }
132
DisableReceiverAVSync(const std::string & groupInfo)133 void AVSyncManager::DisableReceiverAVSync(const std::string &groupInfo)
134 {
135 (void)groupInfo;
136 CloseAVTransSharedMemory(sinkMemory_);
137 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransTag::STOP_AV_SYNC, "");
138 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransSharedMemory{0, 0, "sinkSharedMemory"});
139 }
140
MergeGroupInfo(std::string & syncGroupInfo)141 bool AVSyncManager::MergeGroupInfo(std::string &syncGroupInfo)
142 {
143 std::set<std::string> sceneTypeSet;
144 {
145 std::lock_guard<std::mutex> lock(listMutex_);
146 for (const auto &item : streamInfoList_) {
147 sceneTypeSet.insert(item.sceneType);
148 }
149 }
150 if (sceneTypeSet.size() < AV_SYNC_STREAM_COUNT) {
151 AVTRANS_LOGI("Can not merge av sync group info, because scene type count less than threshold.");
152 return false;
153 }
154
155 if ((sceneTypeSet.find(SCENE_TYPE_D_MIC) != sceneTypeSet.end()) &&
156 (sceneTypeSet.find(SCENE_TYPE_D_SPEAKER) != sceneTypeSet.end())) {
157 AVTRANS_LOGI("Can not merge av sync group info, because scene type are conflicting.");
158 return false;
159 }
160
161 bool source2Sink = (sceneTypeSet.find(SCENE_TYPE_D_SCREEN) != sceneTypeSet.end()) &&
162 (sceneTypeSet.find(SCENE_TYPE_D_SPEAKER) != sceneTypeSet.end());
163 bool sink2Source = (sceneTypeSet.find(SCENE_TYPE_D_CAMERA_STR) != sceneTypeSet.end()) &&
164 (sceneTypeSet.find(SCENE_TYPE_D_MIC) != sceneTypeSet.end());
165 if (!source2Sink && !sink2Source) {
166 AVTRANS_LOGI("Can not merge av sync group info, because scene type do not meet conditions.");
167 return false;
168 }
169
170 std::set<std::string> groupInfoSet;
171 for (const auto &item : streamInfoList_) {
172 if ((item.sceneType == SCENE_TYPE_D_MIC) || (item.sceneType == SCENE_TYPE_D_SPEAKER)) {
173 nlohmann::json masterStr;
174 masterStr[KEY_SCENE_TYPE] = item.sceneType;
175 masterStr[KEY_PEER_DEV_ID] = item.peerDevId;
176 masterStr[KEY_START_FRAME_NUM] = 0;
177 masterStr[KEY_AV_SYNC_FLAG] = AvSyncFlag::MASTER;
178 groupInfoSet.insert(masterStr.dump());
179 } else if ((item.sceneType == SCENE_TYPE_D_SCREEN) || (item.sceneType == SCENE_TYPE_D_CAMERA_STR)) {
180 nlohmann::json slaveStr;
181 slaveStr[KEY_SCENE_TYPE] = item.sceneType;
182 slaveStr[KEY_PEER_DEV_ID] = item.peerDevId;
183 slaveStr[KEY_START_FRAME_NUM] = 0;
184 slaveStr[KEY_AV_SYNC_FLAG] = AvSyncFlag::SLAVE;
185 groupInfoSet.insert(slaveStr.dump());
186 } else {
187 continue;
188 }
189 }
190
191 nlohmann::json jsonStr = {
192 { KEY_MY_DEV_ID, "" },
193 { KEY_GROUP_INFO_ARRAY, groupInfoSet },
194 };
195 syncGroupInfo = jsonStr.dump();
196 return true;
197 }
198 }
199 }