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 }