1 /*
2 * Copyright (c) 2023-2024 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 "cJSON.h"
19
20 #include "av_trans_control_center.h"
21 #include "av_trans_log.h"
22
23 namespace OHOS {
24 namespace DistributedHardware {
25 #undef DH_LOG_TAG
26 #define DH_LOG_TAG "AVSyncManager"
27
AVSyncManager()28 AVSyncManager::AVSyncManager()
29 {
30 AVTRANS_LOGI("AVSyncManager ctor.");
31 sourceMemory_ = { 0, 0, "" };
32 sinkMemory_ = { 0, 0, "" };
33 }
34
~AVSyncManager()35 AVSyncManager::~AVSyncManager()
36 {
37 AVTRANS_LOGI("AVSyncManager dctor.");
38 streamInfoList_.clear();
39 CloseAVTransSharedMemory(sourceMemory_);
40 CloseAVTransSharedMemory(sinkMemory_);
41 }
42
AddStreamInfo(const AVStreamInfo & stream)43 void AVSyncManager::AddStreamInfo(const AVStreamInfo &stream)
44 {
45 AVTRANS_LOGI("add new stream info: sceneType=%{public}s, peerDevId=%{public}s", stream.sceneType.c_str(),
46 GetAnonyString(stream.peerDevId).c_str());
47 {
48 std::lock_guard<std::mutex> lock(listMutex_);
49 streamInfoList_.push_back(stream);
50
51 if (streamInfoList_.size() < AV_SYNC_STREAM_COUNT) {
52 AVTRANS_LOGI("No need enable sender av sync, stream info list size=%{public}zu", streamInfoList_.size());
53 return;
54 }
55 }
56 EnableSenderAVSync();
57 }
58
RemoveStreamInfo(const AVStreamInfo & stream)59 void AVSyncManager::RemoveStreamInfo(const AVStreamInfo &stream)
60 {
61 AVTRANS_LOGI("remove stream info: sceneType=%{public}s, peerDevId=%{public}s", stream.sceneType.c_str(),
62 GetAnonyString(stream.peerDevId).c_str());
63 {
64 std::lock_guard<std::mutex> lock(listMutex_);
65 for (auto iter = streamInfoList_.begin(); iter != streamInfoList_.end();) {
66 if (((*iter).sceneType == stream.sceneType) && ((*iter).peerDevId == stream.peerDevId)) {
67 iter = streamInfoList_.erase(iter);
68 } else {
69 iter++;
70 }
71 }
72 }
73 DisableSenderAVSync();
74 }
75
EnableSenderAVSync()76 void AVSyncManager::EnableSenderAVSync()
77 {
78 std::string syncGroupInfo;
79 if (!MergeGroupInfo(syncGroupInfo)) {
80 AVTRANS_LOGI("No need start av sync.");
81 return;
82 }
83 AVTRANS_LOGI("merged av sync group info=%{public}s", GetAnonyString(syncGroupInfo).c_str());
84 {
85 std::lock_guard<std::mutex> lock(listMutex_);
86 for (const auto &item : streamInfoList_) {
87 auto avMessage = std::make_shared<AVTransMessage>((uint32_t)AVTransTag::START_AV_SYNC,
88 syncGroupInfo, item.peerDevId);
89 AVTransControlCenter::GetInstance().SendMessage(avMessage);
90 }
91 }
92
93 sourceMemory_ = CreateAVTransSharedMemory("sourceSharedMemory", sizeof(uint32_t) + sizeof(int64_t));
94 AVTransControlCenter::GetInstance().SetParam2Engines(sourceMemory_);
95 }
96
DisableSenderAVSync()97 void AVSyncManager::DisableSenderAVSync()
98 {
99 {
100 std::lock_guard<std::mutex> lock(listMutex_);
101 if (streamInfoList_.size() >= AV_SYNC_STREAM_COUNT) {
102 AVTRANS_LOGI("Cannot disable sender av sync, stream info list size=%{public}zu", streamInfoList_.size());
103 return;
104 }
105 for (const auto &item : streamInfoList_) {
106 auto avMessage = std::make_shared<AVTransMessage>((uint32_t)AVTransTag::STOP_AV_SYNC, "", item.peerDevId);
107 AVTransControlCenter::GetInstance().SendMessage(avMessage);
108 }
109 }
110 CloseAVTransSharedMemory(sourceMemory_);
111 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransSharedMemory{0, 0, "sourceSharedMemory"});
112 }
113
HandleAvSyncMessage(const std::shared_ptr<AVTransMessage> & message)114 void AVSyncManager::HandleAvSyncMessage(const std::shared_ptr<AVTransMessage> &message)
115 {
116 if (message == nullptr) {
117 AVTRANS_LOGI("message is nullptr.");
118 return;
119 }
120 if (message->type_ == (uint32_t)AVTransTag::START_AV_SYNC) {
121 EnableReceiverAVSync(message->content_);
122 } else if (message->type_ == (uint32_t)AVTransTag::STOP_AV_SYNC) {
123 DisableReceiverAVSync(message->content_);
124 }
125 }
126
EnableReceiverAVSync(const std::string & groupInfo)127 void AVSyncManager::EnableReceiverAVSync(const std::string &groupInfo)
128 {
129 size_t size = (sizeof(uint32_t) + sizeof(int64_t)) * MAX_CLOCK_UNIT_COUNT;
130 sinkMemory_ = CreateAVTransSharedMemory("sinkSharedMemory", size);
131
132 AVTransControlCenter::GetInstance().SetParam2Engines(sinkMemory_);
133 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransTag::START_AV_SYNC, groupInfo);
134 }
135
DisableReceiverAVSync(const std::string & groupInfo)136 void AVSyncManager::DisableReceiverAVSync(const std::string &groupInfo)
137 {
138 (void)groupInfo;
139 CloseAVTransSharedMemory(sinkMemory_);
140 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransTag::STOP_AV_SYNC, "");
141 AVTransControlCenter::GetInstance().SetParam2Engines(AVTransSharedMemory{0, 0, "sinkSharedMemory"});
142 }
143
MergeGroupInfo(std::string & syncGroupInfo)144 bool AVSyncManager::MergeGroupInfo(std::string &syncGroupInfo)
145 {
146 std::set<std::string> sceneTypeSet;
147 {
148 std::lock_guard<std::mutex> lock(listMutex_);
149 for (const auto &item : streamInfoList_) {
150 sceneTypeSet.insert(item.sceneType);
151 }
152 }
153 if (sceneTypeSet.size() < AV_SYNC_STREAM_COUNT) {
154 AVTRANS_LOGI("Can not merge av sync group info, because scene type count less than threshold.");
155 return false;
156 }
157
158 if ((sceneTypeSet.find(SCENE_TYPE_D_MIC) != sceneTypeSet.end()) &&
159 (sceneTypeSet.find(SCENE_TYPE_D_SPEAKER) != sceneTypeSet.end())) {
160 AVTRANS_LOGI("Can not merge av sync group info, because scene type are conflicting.");
161 return false;
162 }
163
164 bool source2Sink = (sceneTypeSet.find(SCENE_TYPE_D_SCREEN) != sceneTypeSet.end()) &&
165 (sceneTypeSet.find(SCENE_TYPE_D_SPEAKER) != sceneTypeSet.end());
166 bool sink2Source = (sceneTypeSet.find(SCENE_TYPE_D_CAMERA_STR) != sceneTypeSet.end()) &&
167 (sceneTypeSet.find(SCENE_TYPE_D_MIC) != sceneTypeSet.end());
168 if (!source2Sink && !sink2Source) {
169 AVTRANS_LOGI("Can not merge av sync group info, because scene type do not meet conditions.");
170 return false;
171 }
172
173 std::set<std::string> groupInfoSet;
174 if (!MergeGroupInfoInner(groupInfoSet)) {
175 return false;
176 }
177 std::string info = GetsyncGroupInfo(groupInfoSet);
178 if (info == "") {
179 return false;
180 }
181 syncGroupInfo = info;
182 return true;
183 }
184
MergeGroupInfoInner(std::set<std::string> & groupInfoSet)185 bool AVSyncManager::MergeGroupInfoInner(std::set<std::string> &groupInfoSet)
186 {
187 for (const auto &item : streamInfoList_) {
188 if ((item.sceneType == SCENE_TYPE_D_MIC) || (item.sceneType == SCENE_TYPE_D_SPEAKER)) {
189 cJSON *masterStr = cJSON_CreateObject();
190 if (masterStr == nullptr) {
191 return false;
192 }
193 cJSON_AddStringToObject(masterStr, KEY_SCENE_TYPE.c_str(), item.sceneType.c_str());
194 cJSON_AddStringToObject(masterStr, KEY_PEER_DEV_ID.c_str(), item.peerDevId.c_str());
195 cJSON_AddNumberToObject(masterStr, KEY_START_FRAME_NUM.c_str(), 0);
196 cJSON_AddNumberToObject(masterStr, KEY_AV_SYNC_FLAG.c_str(), static_cast<uint32_t>(AvSyncFlag::MASTER));
197 char *jsonstr = cJSON_PrintUnformatted(masterStr);
198 if (jsonstr == nullptr) {
199 cJSON_Delete(masterStr);
200 return false;
201 }
202 groupInfoSet.insert(std::string(jsonstr));
203 cJSON_Delete(masterStr);
204 cJSON_free(jsonstr);
205 } else if ((item.sceneType == SCENE_TYPE_D_SCREEN) || (item.sceneType == SCENE_TYPE_D_CAMERA_STR)) {
206 cJSON *slaveStr = cJSON_CreateObject();
207 if (slaveStr == nullptr) {
208 return false;
209 }
210 cJSON_AddStringToObject(slaveStr, KEY_SCENE_TYPE.c_str(), item.sceneType.c_str());
211 cJSON_AddStringToObject(slaveStr, KEY_PEER_DEV_ID.c_str(), item.peerDevId.c_str());
212 cJSON_AddNumberToObject(slaveStr, KEY_START_FRAME_NUM.c_str(), 0);
213 cJSON_AddNumberToObject(slaveStr, KEY_AV_SYNC_FLAG.c_str(), static_cast<uint32_t>(AvSyncFlag::SLAVE));
214 char *jsonstr = cJSON_PrintUnformatted(slaveStr);
215 if (jsonstr == nullptr) {
216 cJSON_Delete(slaveStr);
217 return false;
218 }
219 groupInfoSet.insert(std::string(jsonstr));
220 cJSON_Delete(slaveStr);
221 cJSON_free(jsonstr);
222 } else {
223 continue;
224 }
225 }
226 return true;
227 }
228
GetsyncGroupInfo(std::set<std::string> & groupInfoSet)229 std::string AVSyncManager::GetsyncGroupInfo(std::set<std::string> &groupInfoSet)
230 {
231 cJSON *jsonStr = cJSON_CreateObject();
232 if (jsonStr == nullptr) {
233 return "";
234 }
235 cJSON_AddStringToObject(jsonStr, KEY_MY_DEV_ID.c_str(), "");
236 cJSON *array = cJSON_CreateArray();
237 if (array == nullptr) {
238 cJSON_Delete(jsonStr);
239 return "";
240 }
241 for (auto &info : groupInfoSet) {
242 cJSON_AddItemToArray(array, cJSON_CreateString(info.c_str()));
243 }
244 cJSON_AddItemToObject(jsonStr, KEY_GROUP_INFO_ARRAY.c_str(), array);
245 char *data = cJSON_PrintUnformatted(jsonStr);
246 if (data == nullptr) {
247 cJSON_Delete(jsonStr);
248 return "";
249 }
250 std::string info = std::string(data);
251 cJSON_free(data);
252 cJSON_Delete(jsonStr);
253 return info;
254 }
255 }
256 }