1 /*
2  * Copyright (C) 2021 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 "avmetadatahelper_server.h"
17 #include "media_log.h"
18 #include "media_errors.h"
19 #include "engine_factory_repo.h"
20 #include "uri_helper.h"
21 #include "media_dfx.h"
22 #include "ipc_skeleton.h"
23 
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadataHelperServer"};
26 }
27 
28 namespace OHOS {
29 namespace Media {
30 static const std::unordered_map<int32_t, std::string> STATUS_TO_STATUS_DESCRIPTION_TABLE = {
31     {HELPER_STATE_ERROR, "HELPER_STATE_ERROR"},
32     {HELPER_IDLE, "HELPER_IDLE"},
33     {HELPER_PREPARED, "HELPER_PREPARED"},
34     {HELPER_CALL_DONE, "HELPER_CALL_DONE"},
35     {HELPER_RELEASED, "HELPER_RELEASED"},
36 };
37 
Create()38 std::shared_ptr<IAVMetadataHelperService> AVMetadataHelperServer::Create()
39 {
40     std::shared_ptr<AVMetadataHelperServer> server = std::make_shared<AVMetadataHelperServer>();
41     CHECK_AND_RETURN_RET_LOG(server != nullptr, nullptr, "Failed to new AVMetadataHelperServer");
42     return server;
43 }
44 
AVMetadataHelperServer()45 AVMetadataHelperServer::AVMetadataHelperServer()
46     : taskQue_("AVMetadata")
47 {
48     appUid_ = IPCSkeleton::GetCallingUid();
49     (void)taskQue_.Start();
50     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
51 }
52 
~AVMetadataHelperServer()53 AVMetadataHelperServer::~AVMetadataHelperServer()
54 {
55     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
56     std::lock_guard<std::mutex> lock(mutex_);
57     auto task = std::make_shared<TaskHandler<void>>([&, this] {
58         avMetadataHelperEngine_ = nullptr;
59     });
60     (void)taskQue_.EnqueueTask(task, true);
61     (void)task->GetResult();
62     uriHelper_ = nullptr;
63     taskQue_.Stop();
64 }
65 
SetSource(const std::string &uri, int32_t usage)66 int32_t AVMetadataHelperServer::SetSource(const std::string &uri, int32_t usage)
67 {
68     std::lock_guard<std::mutex> lock(mutex_);
69     MediaTrace trace("AVMetadataHelperServer::SetSource_uri");
70     MEDIA_LOGD("Current uri is : %{private}s %{public}u", uri.c_str(), usage);
71     CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty");
72 
73     uriHelper_ = std::make_unique<UriHelper>(uri);
74     CHECK_AND_RETURN_RET_LOG(!uriHelper_->FormattedUri().empty(),
75                              MSERR_INVALID_VAL,
76                              "Failed to construct formatted uri");
77     if (!uriHelper_->AccessCheck(UriHelper::URI_READ)) {
78         MEDIA_LOGE("Failed to read the file");
79         return MSERR_INVALID_VAL;
80     }
81     auto res = InitEngine(uriHelper_->FormattedUri());
82     CHECK_AND_RETURN_RET(res == MSERR_OK, res);
83     auto task = std::make_shared<TaskHandler<int32_t>>([&, this, usage] {
84         CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
85             (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine.");
86         int32_t ret = avMetadataHelperEngine_->SetSource(uriHelper_->FormattedUri(), usage);
87         currState_ = ret == MSERR_OK ? HELPER_PREPARED : HELPER_STATE_ERROR;
88         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "0x%{public}06" PRIXPTR " SetSource failed", FAKE_POINTER(this));
89         return ret;
90     });
91     return taskQue_.EnqueueTask(task);
92 }
93 
SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)94 int32_t AVMetadataHelperServer::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
95 {
96     std::lock_guard<std::mutex> lock(mutex_);
97     MediaTrace trace("AVMetadataHelperServer::SetSource_fd");
98     MEDIA_LOGD("Current is fd source, offset: %{public}" PRIi64 ", size: %{public}" PRIi64 " usage: %{public}u",
99                offset, size, usage);
100     uriHelper_ = std::make_unique<UriHelper>(fd, offset, size);
101     CHECK_AND_RETURN_RET_LOG(!uriHelper_->FormattedUri().empty(),
102         MSERR_INVALID_VAL, "Failed to construct formatted uri");
103     CHECK_AND_RETURN_RET_LOG(uriHelper_->AccessCheck(UriHelper::URI_READ), MSERR_INVALID_VAL, "Failed to read the fd");
104     auto res = InitEngine(uriHelper_->FormattedUri());
105     CHECK_AND_RETURN_RET(res == MSERR_OK, res);
106     auto task = std::make_shared<TaskHandler<int32_t>>([&, this, usage] {
107         CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
108             (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
109 
110         int32_t ret = avMetadataHelperEngine_->SetSource(uriHelper_->FormattedUri(), usage);
111         currState_ = ret == MSERR_OK ? HELPER_PREPARED : HELPER_STATE_ERROR;
112         CHECK_AND_RETURN_RET_LOG(
113             ret == MSERR_OK, ret, "0x%{public}06" PRIXPTR " SetSource failed!", FAKE_POINTER(this));
114         return ret;
115     });
116     return taskQue_.EnqueueTask(task);
117 }
118 
SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)119 int32_t AVMetadataHelperServer::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
120 {
121     std::lock_guard<std::mutex> lock(mutex_);
122     MediaTrace trace("AVMetadataHelperServer::SetSource dataSrc");
123     MEDIA_LOGD("AVMetadataHelperServer SetSource");
124     CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "data source is nullptr");
125     dataSrc_ = dataSrc;
126     auto res = InitEngine("media data source");
127     CHECK_AND_RETURN_RET(res == MSERR_OK, res);
128     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
129         CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
130             (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
131         int32_t ret = avMetadataHelperEngine_->SetSource(dataSrc_);
132         currState_ = ret == MSERR_OK ? HELPER_PREPARED : HELPER_STATE_ERROR;
133         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetSource failed!");
134 
135         int64_t size = 0;
136         (void)dataSrc_->GetSize(size);
137         if (size == -1) {
138             config_.looping = false;
139             isLiveStream_ = true;
140         }
141         return ret;
142     });
143     return taskQue_.EnqueueTask(task);
144 }
145 
InitEngine(const std::string &uri)146 int32_t AVMetadataHelperServer::InitEngine(const std::string &uri)
147 {
148     auto engineFactory = EngineFactoryRepo::Instance().GetEngineFactory(
149         IEngineFactory::Scene::SCENE_AVMETADATA, appUid_, uri);
150     CHECK_AND_RETURN_RET_LOG(engineFactory != nullptr,
151         (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED,  "Failed to get engine factory");
152     avMetadataHelperEngine_ = engineFactory->CreateAVMetadataHelperEngine();
153     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
154         (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
155     return MSERR_OK;
156 }
157 
ResolveMetadata(int32_t key)158 std::string AVMetadataHelperServer::ResolveMetadata(int32_t key)
159 {
160     std::lock_guard<std::mutex> lock(mutex_);
161     MediaTrace trace("AVMetadataHelperServer::ResolveMetadata_key");
162     MEDIA_LOGD("Key is %{public}d", key);
163     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, "", "avMetadataHelperEngine_ is nullptr");
164     auto task = std::make_shared<TaskHandler<std::string>>([&, this] {
165         std::string err = "";
166         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
167         return avMetadataHelperEngine_->ResolveMetadata(key);
168     });
169     int32_t ret = taskQue_.EnqueueTask(task);
170     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, "", "EnqueueTask failed");
171 
172     auto result = task->GetResult();
173     ChangeState(HelperStates::HELPER_CALL_DONE);
174     return result.Value();
175 }
176 
ResolveMetadata()177 std::unordered_map<int32_t, std::string> AVMetadataHelperServer::ResolveMetadata()
178 {
179     std::lock_guard<std::mutex> lock(mutex_);
180     MediaTrace trace("AVMetadataHelperServer::ResolveMetadata");
181     {
182         std::unordered_map<int32_t, std::string> map;
183         CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, map, "avMetadataHelperEngine_ is nullptr");
184     }
185     auto task = std::make_shared<TaskHandler<std::unordered_map<int32_t, std::string>>>([&, this] {
186         std::unordered_map<int32_t, std::string> err;
187         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
188         return avMetadataHelperEngine_->ResolveMetadata();
189     });
190     int32_t ret = taskQue_.EnqueueTask(task);
191     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, {}, "EnqueueTask failed");
192 
193     auto result = task->GetResult();
194     ChangeState(HelperStates::HELPER_CALL_DONE);
195     return result.Value();
196 }
197 
GetAVMetadata()198 std::shared_ptr<Meta> AVMetadataHelperServer::GetAVMetadata()
199 {
200     std::lock_guard<std::mutex> lock(mutex_);
201     MediaTrace trace("AVMetadataHelperServer::ResolveMetadata");
202     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, {}, "avMetadataHelperEngine_ is nullptr");
203     auto task = std::make_shared<TaskHandler<std::shared_ptr<Meta>>>([&, this] {
204         std::shared_ptr<Meta> err = nullptr;
205         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
206         return avMetadataHelperEngine_->GetAVMetadata();
207     });
208     int32_t ret = taskQue_.EnqueueTask(task);
209     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, {}, "EnqueueTask failed");
210 
211     auto result = task->GetResult();
212     ChangeState(HelperStates::HELPER_CALL_DONE);
213     return result.Value();
214 }
215 
FetchArtPicture()216 std::shared_ptr<AVSharedMemory> AVMetadataHelperServer::FetchArtPicture()
217 {
218     std::lock_guard<std::mutex> lock(mutex_);
219     MediaTrace trace("AVMetadataHelperServer::FetchArtPicture");
220     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, {}, "avMetadataHelperEngine_ is nullptr");
221     auto task = std::make_shared<TaskHandler<std::shared_ptr<AVSharedMemory>>>([&, this] {
222         std::shared_ptr<AVSharedMemory> err = nullptr;
223         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
224         return avMetadataHelperEngine_->FetchArtPicture();
225     });
226     int32_t ret = taskQue_.EnqueueTask(task);
227     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
228 
229     auto result = task->GetResult();
230     if (result.Value() == nullptr) {
231         MEDIA_LOGE("FetchArtPicture result is nullptr.");
232         NotifyErrorCallback(HelperErrorType::INVALID_RESULT, "FetchArtPicture result is nullptr.");
233         return nullptr;
234     }
235     ChangeState(HelperStates::HELPER_CALL_DONE);
236     return result.Value();
237 }
238 
FetchFrameAtTime(int64_t timeUs, int32_t option, const OutputConfiguration &param)239 std::shared_ptr<AVSharedMemory> AVMetadataHelperServer::FetchFrameAtTime(int64_t timeUs, int32_t option,
240     const OutputConfiguration &param)
241 {
242     std::lock_guard<std::mutex> lock(mutex_);
243     MediaTrace trace("AVMetadataHelperServer::FetchFrameAtTime");
244     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, nullptr, "avMetadataHelperEngine_ is nullptr");
245     auto task = std::make_shared<TaskHandler<std::shared_ptr<AVSharedMemory>>>([&, this] {
246         std::shared_ptr<AVSharedMemory> err = nullptr;
247         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
248         return avMetadataHelperEngine_->FetchFrameAtTime(timeUs, option, param);
249     });
250     int32_t ret = taskQue_.EnqueueTask(task);
251     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
252 
253     auto result = task->GetResult();
254     ChangeState(HelperStates::HELPER_CALL_DONE);
255     return result.Value();
256 }
257 
FetchFrameYuv(int64_t timeUs, int32_t option, const OutputConfiguration &param)258 std::shared_ptr<AVBuffer> AVMetadataHelperServer::FetchFrameYuv(int64_t timeUs, int32_t option,
259     const OutputConfiguration &param)
260 {
261     MediaTrace trace("AVMetadataHelperServer::FetchFrameAtTime");
262     std::lock_guard<std::mutex> lock(mutex_);
263     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, nullptr, "avMetadataHelperEngine_ is nullptr");
264     auto task = std::make_shared<TaskHandler<std::shared_ptr<AVBuffer>>>([&, this] {
265         return avMetadataHelperEngine_->FetchFrameYuv(timeUs, option, param);
266     });
267     int32_t ret = taskQue_.EnqueueTask(task);
268     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
269     auto result = task->GetResult();
270     return result.Value();
271 }
272 
Release()273 void AVMetadataHelperServer::Release()
274 {
275     MediaTrace trace("AVMetadataHelperServer::Release");
276     CHECK_AND_RETURN_LOG(avMetadataHelperEngine_ != nullptr, "avMetadataHelperEngine_ is nullptr");
277     avMetadataHelperEngine_->SetInterruptState(true);
278     auto task = std::make_shared<TaskHandler<void>>([&, this] {
279         avMetadataHelperEngine_ = nullptr;
280     });
281     (void)taskQue_.EnqueueTask(task, true);
282     (void)task->GetResult();
283     uriHelper_ = nullptr;
284     ChangeState(HelperStates::HELPER_RELEASED);
285     {
286         std::lock_guard<std::mutex> lockCb(mutexCb_);
287         helperCb_ = nullptr;
288     }
289 }
290 
SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)291 int32_t AVMetadataHelperServer::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
292 {
293     std::lock_guard<std::mutex> lock(mutex_);
294     CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
295 
296     if (currState_ != HELPER_IDLE) {
297         MEDIA_LOGE("Can not SetHelperCallback, currentState is %{public}s",
298             GetStatusDescription(currState_).c_str());
299         return MSERR_INVALID_OPERATION;
300     }
301 
302     {
303         std::lock_guard<std::mutex> lockCb(mutexCb_);
304         helperCb_ = callback;
305     }
306     return MSERR_OK;
307 }
308 
GetTimeByFrameIndex(uint32_t index, uint64_t &time)309 int32_t AVMetadataHelperServer::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
310 {
311     MediaTrace trace("AVMetadataHelperServer::GetTimeByFrameIndex");
312     std::lock_guard<std::mutex> lock(mutex_);
313     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, MSERR_NO_MEMORY, "avMetadataHelperEngine_ is nullptr");
314     auto task = std::make_shared<TaskHandler<int32_t>>([&, this, &timeUs = time] {
315         int32_t err = static_cast<int32_t>(MSERR_INVALID_STATE);
316         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
317         return avMetadataHelperEngine_->GetTimeByFrameIndex(index, timeUs);
318     });
319     int32_t ret = taskQue_.EnqueueTask(task);
320     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_NO_MEMORY, "EnqueueTask failed");
321     auto result = task->GetResult();
322     return result.Value();
323 }
324 
GetFrameIndexByTime(uint64_t time, uint32_t &index)325 int32_t AVMetadataHelperServer::GetFrameIndexByTime(uint64_t time, uint32_t &index)
326 {
327     MediaTrace trace("AVMetadataHelperServer::GetFrameIndexByTime");
328     std::lock_guard<std::mutex> lock(mutex_);
329     CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, MSERR_NO_MEMORY, "avMetadataHelperEngine_ is nullptr");
330     auto task = std::make_shared<TaskHandler<int32_t>>([&, this, &index = index] {
331         int32_t err = static_cast<int32_t>(MSERR_INVALID_STATE);
332         CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
333         return avMetadataHelperEngine_->GetFrameIndexByTime(time, index);
334     });
335     int32_t ret = taskQue_.EnqueueTask(task);
336     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
337     auto result = task->GetResult();
338     return result.Value();
339 }
340 
ChangeState(const HelperStates state)341 void AVMetadataHelperServer::ChangeState(const HelperStates state)
342 {
343     switch (state) {
344         case HELPER_PREPARED:
345             if (currState_ == HELPER_IDLE) {
346                 currState_ = HELPER_PREPARED;
347                 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
348             } else {
349                 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
350             }
351             break;
352         case HELPER_CALL_DONE:
353             if (currState_ == HELPER_CALL_DONE || currState_ == HELPER_PREPARED) {
354                 currState_ = HELPER_CALL_DONE;
355                 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
356             } else {
357                 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
358             }
359             break;
360         case HELPER_RELEASED:
361             if (currState_ == HELPER_IDLE || currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE) {
362                 currState_ = HELPER_RELEASED;
363                 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
364             } else {
365                 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
366             }
367             break;
368         case HELPER_STATE_ERROR:
369             currState_ = HELPER_STATE_ERROR;
370             NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
371             break;
372         default:
373             MEDIA_LOGI("Changed state is invalid.");
374             break;
375     }
376 }
377 
NotifyErrorCallback(int32_t code, const std::string msg)378 void AVMetadataHelperServer::NotifyErrorCallback(int32_t code, const std::string msg)
379 {
380     std::lock_guard<std::mutex> lockCb(mutexCb_);
381     MEDIA_LOGD("NotifyErrorCallback error code: %{public}d", code);
382     if (helperCb_ != nullptr) {
383         helperCb_->OnError(code, msg);
384     }
385 }
386 
NotifyInfoCallback(HelperOnInfoType type, int32_t extra)387 void AVMetadataHelperServer::NotifyInfoCallback(HelperOnInfoType type, int32_t extra)
388 {
389     std::lock_guard<std::mutex> lockCb(mutexCb_);
390     MEDIA_LOGD("NotifyInfoCallback, extra: %{public}d", extra);
391     if (helperCb_ != nullptr) {
392         helperCb_->OnInfo(type, extra);
393     }
394 }
395 
GetStatusDescription(int32_t status)396 const std::string &AVMetadataHelperServer::GetStatusDescription(int32_t status)
397 {
398     static const std::string ILLEGAL_STATE = "PLAYER_STATUS_ILLEGAL";
399     if (status < HELPER_STATE_ERROR || status > HELPER_RELEASED) {
400         return ILLEGAL_STATE;
401     }
402 
403     return STATUS_TO_STATUS_DESCRIPTION_TABLE.find(status)->second;
404 }
405 
SetIsNapiInstance(bool isNapiInstance)406 void AVMetadataHelperServer::SetIsNapiInstance(bool isNapiInstance)
407 {
408     isNapiInstance_ = isNapiInstance;
409 }
410 
411 } // namespace Media
412 } // namespace OHOS
413