• 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 "cJSON.h"
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=%{public}s, fd=%{public}" 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=%{public}s, fd=%{public}" 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=%{public}s, fd=%{public}" 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     if (memset_s(base, size, INVALID_VALUE_FALG, size) != EOK) {
55         AVTRANS_LOGE("memset_s failed.");
56         (void)::close(fd);
57         return AVTransSharedMemory{0, 0, name};
58     }
59     uint64_t tmpsize = static_cast<uint64_t>(size);
60     AVTRANS_LOGI("create av trans shared memory success, name=%{public}s, size=%{public}" PRIu64 ", fd=%{public}"
61         PRId32, name.c_str(), tmpsize, fd);
62     return AVTransSharedMemory{fd, size, name};
63 }
64 
CloseAVTransSharedMemory(const AVTransSharedMemory & memory)65 void CloseAVTransSharedMemory(const AVTransSharedMemory &memory) noexcept
66 {
67     AVTRANS_LOGI("close shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
68         memory.name.c_str(), memory.size, memory.fd);
69     if (IsInValidSharedMemory(memory)) {
70         AVTRANS_LOGE("invalid input shared memory");
71         return;
72     }
73     if (memory.fd > 0) {
74         (void)::close(memory.fd);
75     }
76 }
77 
WriteClockUnitToMemory(const AVTransSharedMemory & memory,AVSyncClockUnit & clockUnit)78 int32_t WriteClockUnitToMemory(const AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit)
79 {
80     AVTRANS_LOGI("write clock unit to shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
81         memory.name.c_str(), memory.size, memory.fd);
82     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
83 
84     int mSize = 12;
85     TRUE_RETURN_V_MSG_E(memory.size < mSize, ERR_DH_AVT_INVALID_PARAM,
86         "Memory.size is too small, future access may exceed the limit");
87     AVTRANS_LOGI("clock unit index=%{public}" PRId32 ", frameNum=%{public}" PRId32 ", pts=%{public}lld",
88         clockUnit.index, clockUnit.frameNum, (long long)clockUnit.pts);
89     TRUE_RETURN_V_MSG_E(IsInValidClockUnit(clockUnit), ERR_DH_AVT_INVALID_PARAM, "invalid input clock unit");
90 
91     int size = AshmemGetSize(memory.fd);
92     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %{public}" PRId32,
93         size);
94 
95     unsigned int prot = PROT_WRITE;
96     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
97     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
98 
99     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
100     if (addr == MAP_FAILED) {
101         addr = nullptr;
102         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
103         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
104     }
105 
106     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
107     size_t fOffset = (sizeof(uint32_t) + sizeof(int64_t)) * clockUnit.index;
108     size_t tOffset = fOffset + sizeof(uint32_t);
109     U64ToU8(base + tOffset, clockUnit.pts);
110     U32ToU8(base + fOffset, clockUnit.frameNum);
111 
112     clockUnit.index ++;
113     if (clockUnit.index == MAX_CLOCK_UNIT_COUNT) {
114         clockUnit.index = 0;
115     }
116     AVTRANS_LOGI("write clock unit frameNum=%{public}" PRId32 ", pts=%{public}lld to shared memory success",
117         clockUnit.frameNum, (long long)(clockUnit.pts));
118     return DH_AVT_SUCCESS;
119 }
120 
ReadClockUnitFromMemory(const AVTransSharedMemory & memory,AVSyncClockUnit & clockUnit)121 int32_t ReadClockUnitFromMemory(const AVTransSharedMemory &memory, AVSyncClockUnit &clockUnit)
122 {
123     AVTRANS_LOGI("read clock unit from shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
124         memory.name.c_str(), memory.size, memory.fd);
125     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
126 
127     int mSize = 12;
128     TRUE_RETURN_V_MSG_E(memory.size < mSize, ERR_DH_AVT_INVALID_PARAM,
129         "Memory.size is too small, future access may exceed the limit");
130     AVTRANS_LOGI("clock unit index=%{public}" PRId32 ", frameNum=%{public}" PRId32,
131         clockUnit.index, clockUnit.frameNum);
132     TRUE_RETURN_V_MSG_E((clockUnit.frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number");
133 
134     int size = AshmemGetSize(memory.fd);
135     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %{public}" PRId32,
136         size);
137 
138     unsigned int prot = PROT_WRITE;
139     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
140     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
141 
142     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
143     if (addr == MAP_FAILED) {
144         addr = nullptr;
145         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
146         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
147     }
148 
149     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
150     uint32_t firstUnit = U8ToU32(base);
151     TRUE_RETURN_V_MSG_E(firstUnit == 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, clock is null.");
152 
153     uint32_t index = 0;
154     int64_t latestPts = 0;
155     size_t unitSize = sizeof(uint32_t) + sizeof(int64_t);
156     while (index < MAX_CLOCK_UNIT_COUNT) {
157         uint32_t frameNum = U8ToU32(base + (index * unitSize));
158         int64_t pts = static_cast<int64_t>(U8ToU64(base + (index * unitSize) + sizeof(uint32_t)));
159         if (pts > latestPts) {
160             latestPts = pts;
161             clockUnit.pts = pts;
162             clockUnit.frameNum = frameNum;
163         }
164         index++;
165     }
166     AVTRANS_LOGI("read clock unit from shared memory success, frameNum=%{public}" PRId32 ", pts=%{public}lld",
167         clockUnit.frameNum, (long long)clockUnit.pts);
168     return DH_AVT_SUCCESS;
169 }
170 
WriteFrameInfoToMemory(const AVTransSharedMemory & memory,uint32_t frameNum,int64_t timestamp)171 int32_t WriteFrameInfoToMemory(const AVTransSharedMemory &memory, uint32_t frameNum, int64_t timestamp)
172 {
173     AVTRANS_LOGI("write frame info to shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
174         memory.name.c_str(), memory.size, memory.fd);
175     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
176 
177     int mSize = 12;
178     TRUE_RETURN_V_MSG_E(memory.size < mSize, ERR_DH_AVT_INVALID_PARAM,
179         "Memory.size is too small, future access may exceed the limit");
180     TRUE_RETURN_V_MSG_E((frameNum <= 0), ERR_DH_AVT_INVALID_PARAM, "invalid input frame number");
181 
182     int size = AshmemGetSize(memory.fd);
183     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %{public}" PRId32,
184         size);
185 
186     unsigned int prot = PROT_WRITE;
187     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
188     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
189 
190     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
191     if (addr == MAP_FAILED) {
192         addr = nullptr;
193         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
194         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
195     }
196 
197     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
198     U32ToU8(base, frameNum);
199     U64ToU8(base + sizeof(uint32_t), timestamp);
200 
201     AVTRANS_LOGI("write frameNum=%{public}" PRId32 ", timestamp=%{public}lld to shared memory success",
202         frameNum, (long long)timestamp);
203     return DH_AVT_SUCCESS;
204 }
205 
ReadFrameInfoFromMemory(const AVTransSharedMemory & memory,uint32_t & frameNum,int64_t & timestamp)206 int32_t ReadFrameInfoFromMemory(const AVTransSharedMemory &memory, uint32_t &frameNum, int64_t &timestamp)
207 {
208     AVTRANS_LOGI("read frame info from shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
209         memory.name.c_str(), memory.size, memory.fd);
210     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
211     int mSize = 12;
212     TRUE_RETURN_V_MSG_E(memory.size < mSize, ERR_DH_AVT_INVALID_PARAM,
213         "Memory.size is too small, future access may exceed the limit");
214 
215     int size = AshmemGetSize(memory.fd);
216     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %{public}" PRId32,
217         size);
218 
219     unsigned int prot = PROT_WRITE;
220     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
221     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
222 
223     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
224     if (addr == MAP_FAILED) {
225         addr = nullptr;
226         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
227         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
228     }
229 
230     uint8_t *base = reinterpret_cast<uint8_t*>(addr);
231     frameNum = U8ToU32(base);
232     timestamp = static_cast<int64_t>(U8ToU64(base + sizeof(uint32_t)));
233     TRUE_RETURN_V_MSG_E(frameNum <= 0, ERR_DH_AVT_MASTER_NOT_READY, "master queue not ready, frameNum is null.");
234 
235     AVTRANS_LOGI("read frameNum=%{public}" PRId32 ", timestamp=%{public}lld from shared memory success.", frameNum,
236         (long long)timestamp);
237     return DH_AVT_SUCCESS;
238 }
239 
ResetSharedMemory(const AVTransSharedMemory & memory)240 int32_t ResetSharedMemory(const AVTransSharedMemory &memory)
241 {
242     AVTRANS_LOGI("reset shared memory, name=%{public}s, size=%{public}" PRId32 ", fd=%{public}" PRId32,
243         memory.name.c_str(), memory.size, memory.fd);
244     TRUE_RETURN_V_MSG_E(IsInValidSharedMemory(memory), ERR_DH_AVT_INVALID_PARAM, "invalid input shared memory");
245 
246     int size = AshmemGetSize(memory.fd);
247     TRUE_RETURN_V_MSG_E(size != memory.size, ERR_DH_AVT_SHARED_MEMORY_FAILED, "invalid memory size = %{public}" PRId32,
248         size);
249 
250     unsigned int prot = PROT_WRITE;
251     int result = AshmemSetProt(memory.fd, static_cast<int>(prot));
252     TRUE_RETURN_V_MSG_E(result < 0, ERR_DH_AVT_SHARED_MEMORY_FAILED, "AshmemSetProt failed");
253 
254     void *addr = ::mmap(nullptr, static_cast<size_t>(memory.size), static_cast<int>(prot), MAP_SHARED, memory.fd, 0);
255     if (addr == MAP_FAILED) {
256         addr = nullptr;
257         AVTRANS_LOGE("shared memory mmap failed, mmap address is invalid.");
258         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
259     }
260     if (memset_s(reinterpret_cast<uint8_t*>(addr), size, INVALID_VALUE_FALG, size) != EOK) {
261         AVTRANS_LOGE("memset_s failed.");
262         return ERR_DH_AVT_SHARED_MEMORY_FAILED;
263     }
264     AVTRANS_LOGI("reset shared memory success.");
265     return DH_AVT_SUCCESS;
266 }
267 
IsInValidSharedMemory(const AVTransSharedMemory & memory)268 bool IsInValidSharedMemory(const AVTransSharedMemory &memory)
269 {
270     return (memory.fd <= 0) || (memory.size <= 0) || memory.name.empty();
271 }
272 
IsInValidClockUnit(const AVSyncClockUnit & clockUnit)273 bool IsInValidClockUnit(const AVSyncClockUnit &clockUnit)
274 {
275     return (clockUnit.index < 0) || (clockUnit.index >= MAX_CLOCK_UNIT_COUNT) || (clockUnit.frameNum <= 0)
276         || (clockUnit.pts <= 0);
277 }
278 
MarshalSharedMemory(const AVTransSharedMemory & memory)279 std::string MarshalSharedMemory(const AVTransSharedMemory &memory)
280 {
281     cJSON *memoryJson = cJSON_CreateObject();
282     if (memoryJson == nullptr) {
283         return "";
284     }
285     cJSON_AddNumberToObject(memoryJson, KEY_SHARED_MEM_FD.c_str(), memory.fd);
286     cJSON_AddNumberToObject(memoryJson, KEY_SHARED_MEM_SIZE.c_str(), memory.size);
287     cJSON_AddStringToObject(memoryJson, KEY_SHARED_MEM_NAME.c_str(), memory.name.c_str());
288 
289     char *data = cJSON_PrintUnformatted(memoryJson);
290     if (data == nullptr) {
291         cJSON_Delete(memoryJson);
292         return "";
293     }
294     std::string jsonstr(data);
295     cJSON_free(data);
296     cJSON_Delete(memoryJson);
297     return jsonstr;
298 }
299 
UnmarshalSharedMemory(const std::string & jsonStr)300 AVTransSharedMemory UnmarshalSharedMemory(const std::string &jsonStr)
301 {
302     cJSON *paramJson = cJSON_Parse(jsonStr.c_str());
303     if (paramJson == nullptr) {
304         return AVTransSharedMemory{0, 0, ""};
305     }
306     cJSON *fdObj = cJSON_GetObjectItemCaseSensitive(paramJson, KEY_SHARED_MEM_FD.c_str());
307     if (fdObj == nullptr || !cJSON_IsNumber(fdObj)) {
308         cJSON_Delete(paramJson);
309         return AVTransSharedMemory{0, 0, ""};
310     }
311     int32_t fd = fdObj->valueint;
312     cJSON *sizeObj = cJSON_GetObjectItemCaseSensitive(paramJson, KEY_SHARED_MEM_SIZE.c_str());
313     if (sizeObj == nullptr || !cJSON_IsNumber(sizeObj)) {
314         cJSON_Delete(paramJson);
315         return AVTransSharedMemory{0, 0, ""};
316     }
317     int32_t size = sizeObj->valueint;
318     cJSON *nameObj = cJSON_GetObjectItemCaseSensitive(paramJson, KEY_SHARED_MEM_NAME.c_str());
319     if (nameObj == nullptr || !cJSON_IsString(nameObj)) {
320         cJSON_Delete(paramJson);
321         return AVTransSharedMemory{0, 0, ""};
322     }
323     std::string name = nameObj->valuestring;
324     cJSON_Delete(paramJson);
325     return AVTransSharedMemory{ fd, size, name };
326 }
327 
U32ToU8(uint8_t * ptr,uint32_t value)328 void U32ToU8(uint8_t *ptr, uint32_t value)
329 {
330     if (ptr == nullptr) {
331         return;
332     }
333     int8_t arrZero = 0;
334     int8_t arrOne = 1;
335     int8_t arrTwo = 2;
336     int8_t arrThree = 3;
337     uint8_t cal = 8;
338     uint8_t calTwo = 16;
339     uint8_t calThree = 24;
340     ptr[arrZero] = (uint8_t)((value) & 0xff);
341     ptr[arrOne] = (uint8_t)((value >> cal) & 0xff);
342     ptr[arrTwo] = (uint8_t)((value >> calTwo) & 0xff);
343     ptr[arrThree] = (uint8_t)((value >> calThree) & 0xff);
344 }
345 
U64ToU8(uint8_t * ptr,uint64_t value)346 void U64ToU8(uint8_t *ptr, uint64_t value)
347 {
348     if (ptr == nullptr) {
349         return;
350     }
351     int8_t arrZero = 0;
352     int8_t arrOne = 1;
353     int8_t arrTwo = 2;
354     int8_t arrThree = 3;
355     int8_t arrFour = 4;
356     int8_t arrFive = 5;
357     int8_t arrSix = 6;
358     int8_t arrSeven = 7;
359     uint8_t calOne = 8;
360     uint8_t calTwo = 16;
361     uint8_t calThree = 24;
362     uint8_t calFour = 32;
363     uint8_t calFive = 40;
364     uint8_t calSix = 48;
365     uint8_t calSeven = 56;
366     ptr[arrZero] = (uint8_t)((value) & 0xff);
367     ptr[arrOne] = (uint8_t)((value >> calOne) & 0xff);
368     ptr[arrTwo] = (uint8_t)((value >> calTwo) & 0xff);
369     ptr[arrThree] = (uint8_t)((value >> calThree) & 0xff);
370     ptr[arrFour] = (uint8_t)((value >> calFour) & 0xff);
371     ptr[arrFive] = (uint8_t)((value >> calFive) & 0xff);
372     ptr[arrSix] = (uint8_t)((value >> calSix) & 0xff);
373     ptr[arrSeven] = (uint8_t)((value >> calSeven) & 0xff);
374 }
375 
U8ToU32(const uint8_t * ptr)376 uint32_t U8ToU32(const uint8_t *ptr)
377 {
378     if (ptr == nullptr) {
379         return -1;
380     }
381     int8_t arrZero = 0;
382     int8_t arrOne = 1;
383     int8_t arrTwo = 2;
384     int8_t arrThree = 3;
385     uint8_t calOne = 8;
386     uint8_t calTwo = 16;
387     uint8_t calThree = 24;
388     return (((uint32_t)(ptr[arrZero] & 0xff)) |
389             ((uint32_t)(ptr[arrOne] & 0xff) << calOne) |
390             ((uint32_t)(ptr[arrTwo] & 0xff) << calTwo) |
391             ((uint32_t)(ptr[arrThree] & 0xff) << calThree));
392 }
393 
U8ToU64(const uint8_t * ptr)394 uint64_t U8ToU64(const uint8_t *ptr)
395 {
396     if (ptr == nullptr) {
397         return -1;
398     }
399     int8_t arrZero = 0;
400     int8_t arrOne = 1;
401     int8_t arrTwo = 2;
402     int8_t arrThree = 3;
403     int8_t arrFour = 4;
404     int8_t arrFive = 5;
405     int8_t arrSix = 6;
406     int8_t arrSeven = 7;
407     uint8_t calOne = 8;
408     uint8_t calTwo = 16;
409     uint8_t calThree = 24;
410     uint8_t calFour = 32;
411     uint8_t calFive = 40;
412     uint8_t calSix = 48;
413     uint8_t calSeven = 56;
414     return (((uint64_t)(ptr[arrZero] & 0xff)) |
415             ((uint64_t)(ptr[arrOne] & 0xff) << calOne) |
416             ((uint64_t)(ptr[arrTwo] & 0xff) << calTwo) |
417             ((uint64_t)(ptr[arrThree] & 0xff) << calThree) |
418             ((uint64_t)(ptr[arrFour] & 0xff) << calFour) |
419             ((uint64_t)(ptr[arrFive] & 0xff) << calFive) |
420             ((uint64_t)(ptr[arrSix] & 0xff) << calSix) |
421             ((uint64_t)(ptr[arrSeven] & 0xff) << calSeven));
422 }
423 } // namespace DistributedHardware
424 } // namespace OHOS