• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_utils.h"
17 
18 #include <sys/mman.h>
19 #include <securec.h>
20 #include <unistd.h>
21 #include "ashmem.h"
22 #include "nlohmann/json.hpp"
23 
24 #include "av_trans_constants.h"
25 #include "av_trans_errno.h"
26 #include "av_trans_log.h"
27 
28 namespace OHOS {
29 namespace DistributedHardware {
CreateAVTransSharedMemory(const std::string & name,size_t size)30 AVTransSharedMemory CreateAVTransSharedMemory(const std::string &name, size_t size)
31 {
32     int32_t fd = AshmemCreate(name.c_str(), size);
33     if (fd <= 0) {
34         AVTRANS_LOGE("create av trans shared memory failed, name=%s, fd=%" PRId32, name.c_str(), fd);
35         return AVTransSharedMemory{0, 0, name};
36     }
37 
38     unsigned int prot = PROT_READ | PROT_WRITE;
39     int result = AshmemSetProt(fd, static_cast<int>(prot));
40     if (result < 0) {
41         AVTRANS_LOGE("AshmemSetProt failed, name=%s, fd=%" PRId32, name.c_str(), fd);
42         (void)::close(fd);
43         return AVTransSharedMemory{0, 0, name};
44     }
45 
46     void *addr = ::mmap(nullptr, size, static_cast<int>(prot), MAP_SHARED, fd, 0);
47     if (addr == MAP_FAILED) {
48         AVTRANS_LOGE("shared memory mmap failed, name=%s, fd=%" PRId32, name.c_str(), fd);
49         (void)::close(fd);
50         return AVTransSharedMemory{0, 0, name};
51     }
52 
53     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
54     (void)memset_s(base, size, INVALID_VALUE_FALG, size);
55 
56     AVTRANS_LOGI("create av trans shared memory success, name=%s, size=%" PRId32 ", fd=%" PRId32,
57         name.c_str(), size, fd);
58     return AVTransSharedMemory{fd, size, name};
59 }
60 
CloseAVTransSharedMemory(const AVTransSharedMemory & memory)61 void CloseAVTransSharedMemory(const AVTransSharedMemory &memory) noexcept
62 {
63     AVTRANS_LOGI("close shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, memory.name.c_str(),
64         memory.size, memory.fd);
65     if (IsInValidSharedMemory(memory)) {
66         AVTRANS_LOGE("invalid input shared memory");
67         return;
68     }
69     if (memory.fd > 0) {
70         (void)::close(memory.fd);
71     }
72 }
73 
WriteClockUnitToMemory(const AVTransSharedMemory & memory,AVSyncClockUnit & clockUnit)74 int32_t WriteClockUnitToMemory(const AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit)
75 {
76     AVTRANS_LOGI("write clock unit to shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32,
77         memory.name.c_str(), memory.size, memory.fd);
78     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
79 
80     AVTRANS_LOGI("clock unit index=%" PRId32 ", frameNum=%" PRId32 ", pts=%lld", clockUnit.index,
81         clockUnit.frameNum, (long long)clockUnit.pts);
82     TRUE_RETURN_V_MSG_E(IsInValidClockUnit(clockUnit), ERR_DH_AVT_INVALID_PARAM, "invalid input clock unit");
83 
84     int size = AshmemGetSize(memory.fd);
85     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size);
86 
87     unsigned int prot = PROT_WRITE;
88     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
89     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
90 
91     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
92     if (addr == MAP_FAILED) {
93         free(addr);
94         addr = nullptr;
95         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
96         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
97     }
98 
99     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
100     size_t fOffset = (sizeof(uint32_t) + sizeof(int64_t)) * clockUnit.index;
101     size_t tOffset = fOffset + sizeof(uint32_t);
102     U64ToU8(base + tOffset, clockUnit.pts);
103     U32ToU8(base + fOffset, clockUnit.frameNum);
104 
105     clockUnit.index ++;
106     if (clockUnit.index == MAX_CLOCK_UNIT_COUNT) {
107         clockUnit.index = 0;
108     }
109 
110     AVTRANS_LOGI("write clock unit frameNum=%" PRId32 ", pts=%lld to shared memory success",
111         clockUnit.frameNum, (long long)(clockUnit.pts));
112     return DH_AVT_SUCCESS;
113 }
114 
ReadClockUnitFromMemory(const AVTransSharedMemory & memory,AVSyncClockUnit & clockUnit)115 int32_t ReadClockUnitFromMemory(const AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit)
116 {
117     AVTRANS_LOGI("read clock unit from shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32,
118         memory.name.c_str(), memory.size, memory.fd);
119     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
120 
121     AVTRANS_LOGI("clock unit index=%" PRId32 ", frameNum=%" PRId32, clockUnit.index, clockUnit.frameNum);
122     TRUE_RETURN_V_MSG_E((clockUnit.frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number");
123 
124     int size = AshmemGetSize(memory.fd);
125     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size);
126 
127     unsigned int prot = PROT_WRITE;
128     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
129     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
130 
131     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
132     if (addr == MAP_FAILED) {
133         free(addr);
134         addr = nullptr;
135         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
136         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
137     }
138 
139     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
140     uint32_t firstUnit = U8ToU32(base);
141     TRUE_RETURN_V_MSG_E(firstUnit == 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, clock is null.");
142 
143     uint32_t index = 0;
144     int64_t latestPts = 0;
145     size_t unitSize = sizeof(uint32_t) + sizeof(int64_t);
146     while (index < MAX_CLOCK_UNIT_COUNT) {
147         uint32_t frameNum = U8ToU32(base + (index * unitSize));
148         int64_t pts = static_cast<int64_t>(U8ToU64(base + (index * unitSize) + sizeof(uint32_t)));
149         if (pts > latestPts) {
150             latestPts = pts;
151             clockUnit.pts = pts;
152             clockUnit.frameNum = frameNum;
153         }
154         index++;
155     }
156     AVTRANS_LOGI("read clock unit from shared memory success, frameNum=%" PRId32 ", pts=%lld",
157         clockUnit.frameNum, (long long)clockUnit.pts);
158     return DH_AVT_SUCCESS;
159 }
160 
WriteFrameInfoToMemory(const AVTransSharedMemory & memory,uint32_t frameNum,int64_t timestamp)161 int32_t WriteFrameInfoToMemory(const AVTransSharedMemory &memory, uint32_t frameNum, int64_t timestamp)
162 {
163     AVTRANS_LOGI("write frame info to shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32,
164         memory.name.c_str(), memory.size, memory.fd);
165     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
166 
167     TRUE_RETURN_V_MSG_E((frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number");
168 
169     int size = AshmemGetSize(memory.fd);
170     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size);
171 
172     unsigned int prot = PROT_WRITE;
173     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
174     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
175 
176     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
177     if (addr == MAP_FAILED) {
178         free(addr);
179         addr = nullptr;
180         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
181         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
182     }
183 
184     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
185     U32ToU8(base, frameNum);
186     U64ToU8(base + sizeof(uint32_t), timestamp);
187 
188     AVTRANS_LOGI("write frameNum=%" PRId32 ", timestamp=%lld to shared memory success", frameNum, (long long)timestamp);
189     return DH_AVT_SUCCESS;
190 }
191 
ReadFrameInfoFromMemory(const AVTransSharedMemory & memory,uint32_t & frameNum,int64_t & timestamp)192 int32_t ReadFrameInfoFromMemory(const AVTransSharedMemory &memory, uint32_t &frameNum, int64_t &timestamp)
193 {
194     AVTRANS_LOGI("read frame info from shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32,
195         memory.name.c_str(), memory.size, memory.fd);
196     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
197 
198     int size = AshmemGetSize(memory.fd);
199     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size);
200 
201     unsigned int prot = PROT_WRITE;
202     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
203     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
204 
205     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
206     if (addr == MAP_FAILED) {
207         free(addr);
208         addr = nullptr;
209         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
210         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
211     }
212 
213     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
214     frameNum = U8ToU32(base);
215     timestamp = static_cast<int64_t>(U8ToU64(base + sizeof(uint32_t)));
216     TRUE_RETURN_V_MSG_E(frameNum <= 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, frameNum is null.");
217 
218     AVTRANS_LOGI("read frameNum=%" PRId32 ", timestamp=%lld from shared memory success.", frameNum,
219         (long long)timestamp);
220     return DH_AVT_SUCCESS;
221 }
222 
ResetSharedMemory(const AVTransSharedMemory & memory)223 int32_t ResetSharedMemory(const AVTransSharedMemory &memory)
224 {
225     AVTRANS_LOGI("reset shared memory, name=%s, size=%" PRId32 ", fd=%" PRId32, memory.name.c_str(),
226         memory.size, memory.fd);
227     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
228 
229     int size = AshmemGetSize(memory.fd);
230     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %" PRId32, size);
231 
232     unsigned int prot = PROT_WRITE;
233     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
234     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
235 
236     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
237     if (addr == MAP_FAILED) {
238         free(addr);
239         addr = nullptr;
240         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
241         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
242     }
243     (void)memset_s(reinterpret_cast<uint8_t*>(addr), size, INVALID_VALUE_FALG, size);
244 
245     AVTRANS_LOGI("reset shared memory success.");
246     return DH_AVT_SUCCESS;
247 }
248 
IsInValidSharedMemory(const AVTransSharedMemory & memory)249 bool IsInValidSharedMemory(const AVTransSharedMemory &memory)
250 {
251     return (memory.fd <= 0) || (memory.size <= 0) || memory.name.empty();
252 }
253 
IsInValidClockUnit(const AVSyncClockUnit & clockUnit)254 bool IsInValidClockUnit(const AVSyncClockUnit &clockUnit)
255 {
256     return (clockUnit.index < 0) || (clockUnit.index >= MAX_CLOCK_UNIT_COUNT) || (clockUnit.frameNum <= 0)
257         || (clockUnit.pts <= 0);
258 }
259 
MarshalSharedMemory(const AVTransSharedMemory & memory)260 std::string MarshalSharedMemory(const AVTransSharedMemory &memory)
261 {
262     nlohmann::json memoryJson;
263 
264     memoryJson[KEY_SHARED_MEM_FD] = memory.fd;
265     memoryJson[KEY_SHARED_MEM_SIZE] = memory.size;
266     memoryJson[KEY_SHARED_MEM_NAME] = memory.name;
267 
268     return memoryJson.dump();
269 }
270 
UnmarshalSharedMemory(const std::string & jsonStr)271 AVTransSharedMemory UnmarshalSharedMemory(const std::string &jsonStr)
272 {
273     nlohmann::json paramJson = nlohmann::json::parse(jsonStr, nullptr, false);
274     if (paramJson.is_discarded()) {
275         return AVTransSharedMemory{0, 0, ""};
276     }
277 
278     if (!paramJson.contains(KEY_SHARED_MEM_FD) || !paramJson.contains(KEY_SHARED_MEM_SIZE) ||
279         !paramJson.contains(KEY_SHARED_MEM_NAME)) {
280         return AVTransSharedMemory{0, 0, ""};
281     }
282 
283     if (!paramJson[KEY_SHARED_MEM_FD].is_number_integer() || !paramJson[KEY_SHARED_MEM_SIZE].is_number_integer() ||
284         !paramJson[KEY_SHARED_MEM_NAME].is_string()) {
285         return AVTransSharedMemory{0, 0, ""};
286     }
287 
288     int32_t fd = paramJson[KEY_SHARED_MEM_FD].get<int32_t>();
289     int32_t size = paramJson[KEY_SHARED_MEM_SIZE].get<int32_t>();
290     std::string name = paramJson[KEY_SHARED_MEM_NAME].get<std::string>();
291 
292     return AVTransSharedMemory{ fd, size, name };
293 }
294 
U32ToU8(uint8_t * ptr,uint32_t value)295 void U32ToU8(uint8_t *ptr, uint32_t value)
296 {
297     ptr[0] = (uint8_t)((value) & 0xff);
298     ptr[1] = (uint8_t)((value >> 8) & 0xff);
299     ptr[2] = (uint8_t)((value >> 16) & 0xff);
300     ptr[3] = (uint8_t)((value >> 24) & 0xff);
301 }
302 
U64ToU8(uint8_t * ptr,uint64_t value)303 void U64ToU8(uint8_t *ptr, uint64_t value)
304 {
305     ptr[0] = (uint8_t)((value) & 0xff);
306     ptr[1] = (uint8_t)((value >> 8) & 0xff);
307     ptr[2] = (uint8_t)((value >> 16) & 0xff);
308     ptr[3] = (uint8_t)((value >> 24) & 0xff);
309     ptr[4] = (uint8_t)((value >> 32) & 0xff);
310     ptr[5] = (uint8_t)((value >> 40) & 0xff);
311     ptr[6] = (uint8_t)((value >> 48) & 0xff);
312     ptr[7] = (uint8_t)((value >> 56) & 0xff);
313 }
314 
U8ToU32(const uint8_t * ptr)315 uint32_t U8ToU32(const uint8_t *ptr)
316 {
317     return (((uint32_t)(ptr[0] & 0xff)) |
318             ((uint32_t)(ptr[1] & 0xff) << 8) |
319             ((uint32_t)(ptr[2] & 0xff) << 16) |
320             ((uint32_t)(ptr[3] & 0xff) << 24));
321 }
322 
U8ToU64(const uint8_t * ptr)323 uint64_t U8ToU64(const uint8_t *ptr)
324 {
325     return (((uint64_t)(ptr[0] & 0xff)) |
326             ((uint64_t)(ptr[1] & 0xff) << 8) |
327             ((uint64_t)(ptr[2] & 0xff) << 16) |
328             ((uint64_t)(ptr[3] & 0xff) << 24) |
329             ((uint64_t)(ptr[4] & 0xff) << 32) |
330             ((uint64_t)(ptr[5] & 0xff) << 40) |
331             ((uint64_t)(ptr[6] & 0xff) << 48) |
332             ((uint64_t)(ptr[7] & 0xff) << 56));
333 }
334 } // namespace DistributedHardware
335 } // namespace OHOS