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_trans_utils.h"
17 
18 #include <cstddef>
19 #include <securec.h>
20 
21 #include "av_trans_constants.h"
22 #include "av_trans_log.h"
23 #include "av_trans_meta.h"
24 
25 #include "plugin/common/share_allocator.h"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
29 using HiSBufferMeta = OHOS::Media::Plugin::BufferMeta;
30 using TransBufferMeta = OHOS::DistributedHardware::BufferMeta;
31 
32 const std::string KEY_OWNER_NAME = "ownerName";
33 const std::string KEY_PEER_DEVID = "peerDevId";
34 
TransName2PkgName(const std::string & ownerName)35 std::string TransName2PkgName(const std::string &ownerName)
36 {
37     const static std::pair<std::string, std::string> mapArray[] = {
38         {OWNER_NAME_D_MIC, PKG_NAME_D_AUDIO},
39         {OWNER_NAME_D_VIRMODEM_MIC, PKG_NAME_D_CALL},
40         {OWNER_NAME_D_CAMERA, PKG_NAME_D_CAMERA},
41         {OWNER_NAME_D_SCREEN, PKG_NAME_D_SCREEN},
42         {OWNER_NAME_D_SPEAKER, PKG_NAME_D_AUDIO},
43         {OWNER_NAME_D_VIRMODEM_SPEAKER, PKG_NAME_D_CALL},
44     };
45     for (const auto& item : mapArray) {
46         if (item.first == ownerName) {
47             return item.second;
48         }
49     }
50     return EMPTY_STRING;
51 }
52 
TransName2MediaType(const std::string & ownerName)53 OHOS::Media::Plugin::MediaType TransName2MediaType(const std::string &ownerName)
54 {
55     const static std::pair<std::string, OHOS::Media::Plugin::MediaType> mapArray[] = {
56         {OWNER_NAME_D_MIC, OHOS::Media::Plugin::MediaType::AUDIO},
57         {OWNER_NAME_D_VIRMODEM_MIC, OHOS::Media::Plugin::MediaType::AUDIO},
58         {OWNER_NAME_D_CAMERA, OHOS::Media::Plugin::MediaType::VIDEO},
59         {OWNER_NAME_D_SCREEN, OHOS::Media::Plugin::MediaType::VIDEO},
60         {OWNER_NAME_D_SPEAKER, OHOS::Media::Plugin::MediaType::AUDIO},
61         {OWNER_NAME_D_VIRMODEM_SPEAKER, OHOS::Media::Plugin::MediaType::AUDIO},
62     };
63     for (const auto& item : mapArray) {
64         if (item.first == ownerName) {
65             return item.second;
66         }
67     }
68     return OHOS::Media::Plugin::MediaType::UNKNOWN;
69 }
70 
BuildChannelDescription(const std::string & ownerName,const std::string & peerDevId)71 std::string BuildChannelDescription(const std::string &ownerName, const std::string &peerDevId)
72 {
73     cJSON *descJson = cJSON_CreateObject();
74     if (descJson == nullptr) {
75         return "";
76     }
77     cJSON_AddStringToObject(descJson, KEY_OWNER_NAME.c_str(), ownerName.c_str());
78     cJSON_AddStringToObject(descJson, KEY_PEER_DEVID.c_str(), peerDevId.c_str());
79     char *data = cJSON_PrintUnformatted(descJson);
80     if (data == nullptr) {
81         cJSON_Delete(descJson);
82         return "";
83     }
84     std::string jsonstr(data);
85     cJSON_Delete(descJson);
86     cJSON_free(data);
87     return jsonstr;
88 }
89 
ParseChannelDescription(const std::string & descJsonStr,std::string & ownerName,std::string & peerDevId)90 void ParseChannelDescription(const std::string &descJsonStr, std::string &ownerName, std::string &peerDevId)
91 {
92     cJSON *descJson = cJSON_Parse(descJsonStr.c_str());
93     if (descJson == nullptr) {
94         return ;
95     }
96     cJSON *nameObj = cJSON_GetObjectItemCaseSensitive(descJson, KEY_OWNER_NAME.c_str());
97     if (nameObj == nullptr || !IsString(descJson, KEY_OWNER_NAME)) {
98         cJSON_Delete(descJson);
99         return ;
100     }
101     cJSON *devObj = cJSON_GetObjectItemCaseSensitive(descJson, KEY_PEER_DEVID.c_str());
102     if (devObj == nullptr || !IsString(descJson, KEY_PEER_DEVID)) {
103         cJSON_Delete(descJson);
104         return ;
105     }
106     ownerName = nameObj->valuestring;
107     peerDevId = devObj->valuestring;
108     cJSON_Delete(descJson);
109 }
110 
TransBuffer2HiSBuffer(const std::shared_ptr<AVTransBuffer> & transBuffer)111 std::shared_ptr<AVBuffer> TransBuffer2HiSBuffer(const std::shared_ptr<AVTransBuffer>& transBuffer)
112 {
113     if ((transBuffer == nullptr) || transBuffer->IsEmpty()) {
114         return nullptr;
115     }
116 
117     auto data = transBuffer->GetBufferData();
118     if (data == nullptr) {
119         return nullptr;
120     }
121 
122     auto hisBuffer = std::make_shared<AVBuffer>();
123     hisBuffer->WrapMemory(data->GetAddress(), data->GetCapacity(), data->GetSize());
124 
125     Convert2HiSBufferMeta(transBuffer, hisBuffer);
126     return hisBuffer;
127 }
128 
HiSBuffer2TransBuffer(const std::shared_ptr<AVBuffer> & hisBuffer)129 std::shared_ptr<AVTransBuffer> HiSBuffer2TransBuffer(const std::shared_ptr<AVBuffer>& hisBuffer)
130 {
131     if ((hisBuffer == nullptr) || hisBuffer->IsEmpty()) {
132         return nullptr;
133     }
134 
135     auto memory = hisBuffer->GetMemory();
136     if (memory == nullptr) {
137         return nullptr;
138     }
139 
140     auto transBuffer = std::make_shared<AVTransBuffer>();
141     transBuffer->WrapBufferData(memory->GetReadOnlyData(), memory->GetCapacity(), memory->GetSize());
142 
143     Convert2TransBufferMeta(hisBuffer, transBuffer);
144     return transBuffer;
145 }
146 
Convert2HiSBufferMeta(std::shared_ptr<AVTransBuffer> transBuffer,std::shared_ptr<AVBuffer> hisBuffer)147 void Convert2HiSBufferMeta(std::shared_ptr<AVTransBuffer> transBuffer, std::shared_ptr<AVBuffer> hisBuffer)
148 {
149     std::shared_ptr<TransBufferMeta> transMeta = transBuffer->GetBufferMeta();
150     if ((transMeta->GetMetaType() == MetaType::AUDIO)) {
151         auto hisAMeta = std::make_shared<AVTransAudioBufferMeta>();
152 
153         std::string value;
154         transMeta->GetMetaItem(AVTransTag::BUFFER_DATA_TYPE, value);
155         uint32_t dataType = static_cast<uint32_t>(std::atoi(value.c_str()));
156         hisAMeta->dataType_ = (BufferDataType)dataType;
157 
158         transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, value);
159         uint32_t format = static_cast<uint32_t>(std::atoi(value.c_str()));
160         hisAMeta->format_ = (AudioSampleFormat)format;
161 
162         transMeta->GetMetaItem(AVTransTag::AUDIO_SAMPLE_RATE, value);
163         hisAMeta->sampleRate_ = static_cast<uint32_t>(std::atoi(value.c_str()));
164 
165         hisBuffer->UpdateBufferMeta(*hisAMeta);
166     } else {
167         auto hisVMeta = std::make_shared<AVTransVideoBufferMeta>();
168 
169         std::string value;
170         transMeta->GetMetaItem(AVTransTag::BUFFER_DATA_TYPE, value);
171         uint32_t dataType = static_cast<uint32_t>(std::atoi(value.c_str()));
172         hisVMeta->dataType_ = (BufferDataType)dataType;
173 
174         transMeta->GetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, value);
175         uint32_t format = static_cast<uint32_t>(std::atoi(value.c_str()));
176         hisVMeta->format_ = (VideoPixelFormat)format;
177 
178         transMeta->GetMetaItem(AVTransTag::VIDEO_WIDTH, value);
179         hisVMeta->width_ = static_cast<uint32_t>(std::atoi(value.c_str()));
180 
181         transMeta->GetMetaItem(AVTransTag::VIDEO_HEIGHT, value);
182         hisVMeta->height_ = static_cast<uint32_t>(std::atoi(value.c_str()));
183 
184         TRUE_LOG_MSG(!transMeta->GetMetaItem(AVTransTag::PRE_TIMESTAMP, value), "get PRE_TIMESTAMP meta failed");
185         hisVMeta->pts_ = std::stoll(value.c_str());
186 
187         hisBuffer->pts = std::stoll(value.c_str());
188         hisBuffer->UpdateBufferMeta(*hisVMeta);
189     }
190 }
191 
Convert2TransBufferMeta(std::shared_ptr<AVBuffer> hisBuffer,std::shared_ptr<AVTransBuffer> transBuffer)192 void Convert2TransBufferMeta(std::shared_ptr<AVBuffer> hisBuffer, std::shared_ptr<AVTransBuffer> transBuffer)
193 {
194     std::shared_ptr<HiSBufferMeta> hisMeta = hisBuffer->GetBufferMeta();
195     if ((hisMeta->GetType() == BufferMetaType::AUDIO)) {
196         std::shared_ptr<AVTransAudioBufferMeta> hisAMeta = ReinterpretCastPointer<AVTransAudioBufferMeta>(hisMeta);
197         TRUE_RETURN(hisAMeta == nullptr, "hisAMeta is null");
198 
199         auto transAMeta = std::make_shared<TransBufferMeta>(MetaType::AUDIO);
200         transAMeta->SetMetaItem(AVTransTag::BUFFER_DATA_TYPE, std::to_string((uint32_t)(hisAMeta->dataType_)));
201         transAMeta->SetMetaItem(AVTransTag::AUDIO_SAMPLE_FORMAT, std::to_string((uint32_t)(hisAMeta->format_)));
202         transAMeta->SetMetaItem(AVTransTag::AUDIO_SAMPLE_RATE, std::to_string(hisAMeta->sampleRate_));
203 
204         transBuffer->UpdateBufferMeta(transAMeta);
205     } else {
206         std::shared_ptr<AVTransVideoBufferMeta> hisVMeta = ReinterpretCastPointer<AVTransVideoBufferMeta>(hisMeta);
207         TRUE_RETURN(hisVMeta == nullptr, "hisAMeta is null");
208 
209         auto transVMeta = std::make_shared<TransBufferMeta>(MetaType::VIDEO);
210         transVMeta->SetMetaItem(AVTransTag::BUFFER_DATA_TYPE, std::to_string((uint32_t)(hisVMeta->dataType_)));
211         transVMeta->SetMetaItem(AVTransTag::VIDEO_PIXEL_FORMAT, std::to_string((uint32_t)(hisVMeta->format_)));
212         transVMeta->SetMetaItem(AVTransTag::VIDEO_WIDTH, std::to_string(hisVMeta->width_));
213         transVMeta->SetMetaItem(AVTransTag::VIDEO_HEIGHT, std::to_string(hisVMeta->height_));
214         transVMeta->SetMetaItem(AVTransTag::PRE_TIMESTAMP, std::to_string(hisVMeta->pts_));
215 
216         transBuffer->UpdateBufferMeta(transVMeta);
217     }
218 }
219 
CastEventType(Plugin::PluginEventType type,bool isAbnormal)220 EventType CastEventType(Plugin::PluginEventType type, bool isAbnormal)
221 {
222     switch (type) {
223         case Plugin::PluginEventType::EVENT_CHANNEL_OPENED:
224             return EventType::EVENT_START_SUCCESS;
225         case Plugin::PluginEventType::EVENT_CHANNEL_OPEN_FAIL:
226             return EventType::EVENT_START_FAIL;
227         case Plugin::PluginEventType::EVENT_CHANNEL_CLOSED:
228             return isAbnormal ? EventType::EVENT_ENGINE_ERROR : EventType::EVENT_STOP_SUCCESS;
229         default:
230             AVTRANS_LOGE("unsupport plugin event type.");
231     }
232     return EventType::EVENT_ENGINE_ERROR;
233 }
234 
DumpBufferToFile(const std::string fileName,uint8_t * buffer,int32_t bufSize)235 void DumpBufferToFile(const std::string fileName, uint8_t *buffer, int32_t bufSize)
236 {
237     if (fileName.empty()) {
238         AVTRANS_LOGE("input fileName is empty.");
239         return;
240     }
241     char path[PATH_MAX + 1] = {0x00};
242     if (fileName.length() > PATH_MAX || realpath(fileName.c_str(), path) == nullptr) {
243         return;
244     }
245     std::ofstream ofs(path, std::ios::binary | std::ios::out | std::ios::app);
246     if (!ofs.is_open()) {
247         AVTRANS_LOGE("open file failed.");
248         return;
249     }
250     ofs.write((const char*)(buffer), bufSize);
251     ofs.close();
252 }
253 
IsUInt32(const cJSON * jsonObj,const std::string & key)254 bool IsUInt32(const cJSON *jsonObj, const std::string &key)
255 {
256     cJSON *keyObj = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
257     return (keyObj != nullptr) && cJSON_IsNumber(keyObj) &&
258         static_cast<uint32_t>(keyObj->valueint) <= UINT32_MAX;
259 }
260 
IsInt64(const cJSON * jsonObj,const std::string & key)261 bool IsInt64(const cJSON *jsonObj, const std::string &key)
262 {
263     cJSON *keyObj = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
264     return (keyObj != nullptr) && cJSON_IsNumber(keyObj) &&
265         static_cast<int64_t>(keyObj->valueint) <= INT64_MAX &&
266         static_cast<int64_t>(keyObj->valueint) >= INT64_MIN;
267 }
268 
IsString(const cJSON * jsonObj,const std::string & key)269 bool IsString(const cJSON *jsonObj, const std::string &key)
270 {
271     cJSON *keyObj = cJSON_GetObjectItemCaseSensitive(jsonObj, key.c_str());
272     return (keyObj != nullptr) && cJSON_IsString(keyObj) &&
273         strlen(cJSON_GetStringValue(keyObj)) <= MAX_MESSAGES_LEN;
274 }
275 
GetCurrentTime()276 int64_t GetCurrentTime()
277 {
278     struct timespec time = { 0, 0 };
279     clock_gettime(CLOCK_MONOTONIC, &time);
280     return time.tv_sec * NS_ONE_S + time.tv_nsec;
281 }
282 
GenerateAdtsHeader(unsigned char * adtsHeader,uint32_t packetLen,uint32_t profile,uint32_t sampleRate,uint32_t channels)283 void GenerateAdtsHeader(unsigned char* adtsHeader, uint32_t packetLen, uint32_t profile, uint32_t sampleRate,
284     uint32_t channels)
285 {
286     static std::map<int, uint32_t> mapSampleRateToFreIndex {
287         {96000, 0},
288         {88200, 1},
289         {64000, 2},
290         {48000, 3},
291         {44100, 4},
292         {32000, 5},
293         {24000, 6},
294         {16000, 8},
295         {12000, 9},
296         {11025, 10},
297         {8000, 11},
298         {7350, 12},
299     };
300     // profile only support AAC LC: 1
301     uint32_t freqIdx = mapSampleRateToFreIndex[sampleRate]; // 48KHz : 3
302     int8_t arrZero = 0;
303     int8_t arrOne = 1;
304     int8_t arrTwo = 2;
305     int8_t arrThree = 3;
306     int8_t arrFour = 4;
307     int8_t arrFive = 5;
308     int8_t arrSix = 6;
309     uint8_t calSix = 6;
310     uint8_t calThree = 3;
311     uint8_t calSeven = 7;
312     uint8_t calFive = 5;
313     uint8_t calEleven = 11;
314     uint8_t calTwo = 2;
315     adtsHeader[arrZero] = (unsigned char) 0xFF;
316     adtsHeader[arrOne] = (unsigned char) 0xF9;
317     if (profile < 1) {
318         return;
319     }
320     adtsHeader[arrTwo] = (unsigned char) (((profile - 1) << calSix) + (freqIdx << calTwo) + (channels >> calTwo));
321     adtsHeader[arrThree] = (unsigned char) (((channels & calThree) << calSix) + (packetLen >> calEleven));
322     adtsHeader[arrFour] = (unsigned char) ((packetLen & 0x7FF) >> calThree);
323     adtsHeader[arrFive] = (unsigned char) (((packetLen & calSeven) << calFive) + 0x1F);
324     adtsHeader[arrSix] = (unsigned char) 0xFC;
325 }
326 } // namespace DistributedHardware
327 } // namespace OHOS