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,
103 "Failed to construct formatted uri");
104 CHECK_AND_RETURN_RET_LOG(uriHelper_->AccessCheck(UriHelper::URI_READ), MSERR_INVALID_VAL, "Failed to read the fd");
105 auto res = InitEngine(uriHelper_->FormattedUri());
106 CHECK_AND_RETURN_RET(res == MSERR_OK, res);
107 auto task = std::make_shared<TaskHandler<int32_t>>([&, this, usage] {
108 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
109 (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
110
111 int32_t ret = avMetadataHelperEngine_->SetSource(uriHelper_->FormattedUri(), usage);
112 currState_ = ret == MSERR_OK ? HELPER_PREPARED : HELPER_STATE_ERROR;
113 CHECK_AND_RETURN_RET_LOG(
114 ret == MSERR_OK, ret, "0x%{public}06" PRIXPTR " SetSource failed!", FAKE_POINTER(this));
115 return ret;
116 });
117 return taskQue_.EnqueueTask(task);
118 }
119
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)120 int32_t AVMetadataHelperServer::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
121 {
122 std::lock_guard<std::mutex> lock(mutex_);
123 MediaTrace trace("AVMetadataHelperServer::SetSource dataSrc");
124 MEDIA_LOGD("AVMetadataHelperServer SetSource");
125 CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "data source is nullptr");
126 dataSrc_ = dataSrc;
127 auto res = InitEngine("media data source");
128 CHECK_AND_RETURN_RET(res == MSERR_OK, res);
129 auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
130 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
131 (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
132 int32_t ret = avMetadataHelperEngine_->SetSource(dataSrc_);
133 currState_ = ret == MSERR_OK ? HELPER_PREPARED : HELPER_STATE_ERROR;
134 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetSource failed!");
135
136 int64_t size = 0;
137 (void)dataSrc_->GetSize(size);
138 if (size == -1) {
139 config_.looping = false;
140 isLiveStream_ = true;
141 }
142 return ret;
143 });
144 return taskQue_.EnqueueTask(task);
145 }
146
InitEngine(const std::string & uri)147 int32_t AVMetadataHelperServer::InitEngine(const std::string &uri)
148 {
149 auto engineFactory = EngineFactoryRepo::Instance().GetEngineFactory(
150 IEngineFactory::Scene::SCENE_AVMETADATA, appUid_, uri);
151 CHECK_AND_RETURN_RET_LOG(engineFactory != nullptr,
152 (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to get engine factory");
153 avMetadataHelperEngine_ = engineFactory->CreateAVMetadataHelperEngine();
154 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr,
155 (int32_t)MSERR_CREATE_AVMETADATAHELPER_ENGINE_FAILED, "Failed to create avmetadatahelper engine");
156 return MSERR_OK;
157 }
158
ResolveMetadata(int32_t key)159 std::string AVMetadataHelperServer::ResolveMetadata(int32_t key)
160 {
161 std::lock_guard<std::mutex> lock(mutex_);
162 MediaTrace trace("AVMetadataHelperServer::ResolveMetadata_key");
163 MEDIA_LOGD("Key is %{public}d", key);
164 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, "", "avMetadataHelperEngine_ is nullptr");
165 auto task = std::make_shared<TaskHandler<std::string>>([&, this] {
166 std::string err = "";
167 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
168 return avMetadataHelperEngine_->ResolveMetadata(key);
169 });
170 int32_t ret = taskQue_.EnqueueTask(task);
171 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, "", "EnqueueTask failed");
172
173 auto result = task->GetResult();
174 ChangeState(HelperStates::HELPER_CALL_DONE);
175 return result.Value();
176 }
177
ResolveMetadata()178 std::unordered_map<int32_t, std::string> AVMetadataHelperServer::ResolveMetadata()
179 {
180 std::lock_guard<std::mutex> lock(mutex_);
181 MediaTrace trace("AVMetadataHelperServer::ResolveMetadata");
182 {
183 std::unordered_map<int32_t, std::string> map;
184 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, map, "avMetadataHelperEngine_ is nullptr");
185 }
186 auto task = std::make_shared<TaskHandler<std::unordered_map<int32_t, std::string>>>([&, this] {
187 std::unordered_map<int32_t, std::string> err;
188 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
189 return avMetadataHelperEngine_->ResolveMetadata();
190 });
191 int32_t ret = taskQue_.EnqueueTask(task);
192 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, {}, "EnqueueTask failed");
193
194 auto result = task->GetResult();
195 ChangeState(HelperStates::HELPER_CALL_DONE);
196 return result.Value();
197 }
198
GetAVMetadata()199 std::shared_ptr<Meta> AVMetadataHelperServer::GetAVMetadata()
200 {
201 std::lock_guard<std::mutex> lock(mutex_);
202 MediaTrace trace("AVMetadataHelperServer::ResolveMetadata");
203 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, {}, "avMetadataHelperEngine_ is nullptr");
204 auto task = std::make_shared<TaskHandler<std::shared_ptr<Meta>>>([&, this] {
205 std::shared_ptr<Meta> err = nullptr;
206 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
207 return avMetadataHelperEngine_->GetAVMetadata();
208 });
209 int32_t ret = taskQue_.EnqueueTask(task);
210 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, {}, "EnqueueTask failed");
211
212 auto result = task->GetResult();
213 ChangeState(HelperStates::HELPER_CALL_DONE);
214 return result.Value();
215 }
216
FetchArtPicture()217 std::shared_ptr<AVSharedMemory> AVMetadataHelperServer::FetchArtPicture()
218 {
219 std::lock_guard<std::mutex> lock(mutex_);
220 MediaTrace trace("AVMetadataHelperServer::FetchArtPicture");
221 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, {}, "avMetadataHelperEngine_ is nullptr");
222 auto task = std::make_shared<TaskHandler<std::shared_ptr<AVSharedMemory>>>([&, this] {
223 std::shared_ptr<AVSharedMemory> err = nullptr;
224 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
225 return avMetadataHelperEngine_->FetchArtPicture();
226 });
227 int32_t ret = taskQue_.EnqueueTask(task);
228 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
229
230 auto result = task->GetResult();
231 if (result.Value() == nullptr) {
232 MEDIA_LOGE("FetchArtPicture result is nullptr.");
233 NotifyErrorCallback(HelperErrorType::INVALID_RESULT, "FetchArtPicture result is nullptr.");
234 return nullptr;
235 }
236 ChangeState(HelperStates::HELPER_CALL_DONE);
237 return result.Value();
238 }
239
FetchFrameAtTime(int64_t timeUs,int32_t option,const OutputConfiguration & param)240 std::shared_ptr<AVSharedMemory> AVMetadataHelperServer::FetchFrameAtTime(int64_t timeUs, int32_t option,
241 const OutputConfiguration ¶m)
242 {
243 std::lock_guard<std::mutex> lock(mutex_);
244 MediaTrace trace("AVMetadataHelperServer::FetchFrameAtTime");
245 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, nullptr, "avMetadataHelperEngine_ is nullptr");
246 auto task = std::make_shared<TaskHandler<std::shared_ptr<AVSharedMemory>>>([&, this] {
247 std::shared_ptr<AVSharedMemory> err = nullptr;
248 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
249 return avMetadataHelperEngine_->FetchFrameAtTime(timeUs, option, param);
250 });
251 int32_t ret = taskQue_.EnqueueTask(task);
252 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
253
254 auto result = task->GetResult();
255 ChangeState(HelperStates::HELPER_CALL_DONE);
256 return result.Value();
257 }
258
FetchFrameYuv(int64_t timeUs,int32_t option,const OutputConfiguration & param)259 std::shared_ptr<AVBuffer> AVMetadataHelperServer::FetchFrameYuv(int64_t timeUs, int32_t option,
260 const OutputConfiguration ¶m)
261 {
262 MediaTrace trace("AVMetadataHelperServer::FetchFrameAtTime");
263 std::lock_guard<std::mutex> lock(mutex_);
264 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, nullptr, "avMetadataHelperEngine_ is nullptr");
265 auto task = std::make_shared<TaskHandler<std::shared_ptr<AVBuffer>>>([&, this] {
266 return avMetadataHelperEngine_->FetchFrameYuv(timeUs, option, param);
267 });
268 int32_t ret = taskQue_.EnqueueTask(task);
269 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "EnqueueTask failed");
270 auto result = task->GetResult();
271 return result.Value();
272 }
273
Release()274 void AVMetadataHelperServer::Release()
275 {
276 MediaTrace trace("AVMetadataHelperServer::Release");
277 {
278 auto avMetadataHelperEngine = avMetadataHelperEngine_;
279 CHECK_AND_RETURN_LOG(avMetadataHelperEngine != nullptr, "avMetadataHelperEngine_ is nullptr");
280 avMetadataHelperEngine->SetInterruptState(true);
281 }
282
283 auto task = std::make_shared<TaskHandler<void>>([&, this] {
284 avMetadataHelperEngine_ = nullptr;
285 uriHelper_ = nullptr;
286 ChangeState(HelperStates::HELPER_RELEASED);
287 {
288 std::lock_guard<std::mutex> lockCb(mutexCb_);
289 helperCb_ = nullptr;
290 }
291 });
292 (void)taskQue_.EnqueueTask(task, true);
293 (void)task->GetResult();
294 }
295
SetHelperCallback(const std::shared_ptr<HelperCallback> & callback)296 int32_t AVMetadataHelperServer::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
297 {
298 std::lock_guard<std::mutex> lock(mutex_);
299 CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
300
301 if (currState_ != HELPER_IDLE) {
302 MEDIA_LOGE("Can not SetHelperCallback, currentState is %{public}s",
303 GetStatusDescription(currState_).c_str());
304 return MSERR_INVALID_OPERATION;
305 }
306
307 {
308 std::lock_guard<std::mutex> lockCb(mutexCb_);
309 helperCb_ = callback;
310 }
311 return MSERR_OK;
312 }
313
GetTimeByFrameIndex(uint32_t index,uint64_t & time)314 int32_t AVMetadataHelperServer::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
315 {
316 MediaTrace trace("AVMetadataHelperServer::GetTimeByFrameIndex");
317 std::lock_guard<std::mutex> lock(mutex_);
318 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, MSERR_NO_MEMORY, "avMetadataHelperEngine_ is nullptr");
319 auto task = std::make_shared<TaskHandler<int32_t>>([&, this, &timeUs = time] {
320 int32_t err = static_cast<int32_t>(MSERR_INVALID_STATE);
321 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
322 return avMetadataHelperEngine_->GetTimeByFrameIndex(index, timeUs);
323 });
324 int32_t ret = taskQue_.EnqueueTask(task);
325 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_NO_MEMORY, "EnqueueTask failed");
326 auto result = task->GetResult();
327 return result.Value();
328 }
329
GetFrameIndexByTime(uint64_t time,uint32_t & index)330 int32_t AVMetadataHelperServer::GetFrameIndexByTime(uint64_t time, uint32_t &index)
331 {
332 MediaTrace trace("AVMetadataHelperServer::GetFrameIndexByTime");
333 std::lock_guard<std::mutex> lock(mutex_);
334 CHECK_AND_RETURN_RET_LOG(avMetadataHelperEngine_ != nullptr, MSERR_NO_MEMORY, "avMetadataHelperEngine_ is nullptr");
335 auto task = std::make_shared<TaskHandler<int32_t>>([&, this, &index = index] {
336 int32_t err = static_cast<int32_t>(MSERR_INVALID_STATE);
337 CHECK_AND_RETURN_RET(currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE, err);
338 return avMetadataHelperEngine_->GetFrameIndexByTime(time, index);
339 });
340 int32_t ret = taskQue_.EnqueueTask(task);
341 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
342 auto result = task->GetResult();
343 return result.Value();
344 }
345
ChangeState(const HelperStates state)346 void AVMetadataHelperServer::ChangeState(const HelperStates state)
347 {
348 switch (state) {
349 case HELPER_PREPARED:
350 if (currState_ == HELPER_IDLE) {
351 currState_ = HELPER_PREPARED;
352 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
353 } else {
354 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
355 }
356 break;
357 case HELPER_CALL_DONE:
358 if (currState_ == HELPER_CALL_DONE || currState_ == HELPER_PREPARED) {
359 currState_ = HELPER_CALL_DONE;
360 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
361 } else {
362 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
363 }
364 break;
365 case HELPER_RELEASED:
366 if (currState_ == HELPER_IDLE || currState_ == HELPER_PREPARED || currState_ == HELPER_CALL_DONE) {
367 currState_ = HELPER_RELEASED;
368 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
369 } else {
370 NotifyErrorCallback(HelperErrorType::INVALID_OPERATION, "State error, current Operation is invalid.");
371 }
372 break;
373 case HELPER_STATE_ERROR:
374 currState_ = HELPER_STATE_ERROR;
375 NotifyInfoCallback(HELPER_INFO_TYPE_STATE_CHANGE, currState_);
376 break;
377 default:
378 MEDIA_LOGI("Changed state is invalid.");
379 break;
380 }
381 }
382
NotifyErrorCallback(int32_t code,const std::string msg)383 void AVMetadataHelperServer::NotifyErrorCallback(int32_t code, const std::string msg)
384 {
385 std::lock_guard<std::mutex> lockCb(mutexCb_);
386 MEDIA_LOGD("NotifyErrorCallback error code: %{public}d", code);
387 if (helperCb_ != nullptr) {
388 helperCb_->OnError(code, msg);
389 }
390 }
391
NotifyInfoCallback(HelperOnInfoType type,int32_t extra)392 void AVMetadataHelperServer::NotifyInfoCallback(HelperOnInfoType type, int32_t extra)
393 {
394 std::lock_guard<std::mutex> lockCb(mutexCb_);
395 MEDIA_LOGD("NotifyInfoCallback, extra: %{public}d", extra);
396 if (helperCb_ != nullptr) {
397 helperCb_->OnInfo(type, extra);
398 }
399 }
400
GetStatusDescription(int32_t status)401 const std::string &AVMetadataHelperServer::GetStatusDescription(int32_t status)
402 {
403 static const std::string ILLEGAL_STATE = "PLAYER_STATUS_ILLEGAL";
404 if (status < HELPER_STATE_ERROR || status > HELPER_RELEASED) {
405 return ILLEGAL_STATE;
406 }
407
408 return STATUS_TO_STATUS_DESCRIPTION_TABLE.find(status)->second;
409 }
410 } // namespace Media
411 } // namespace OHOS
412