1 /*
2 * Copyright (C) 2022 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 "hdi_codec.h"
17 #include <unordered_map>
18 #include <hdf_base.h>
19 #include "codec_callback_type_stub.h"
20 #include "media_log.h"
21 #include "media_errors.h"
22 #include "hdi_init.h"
23 #include "hdi_codec_util.h"
24 #include "securec.h"
25 #include "media_dfx.h"
26 #include "scope_guard.h"
27
28 using namespace std;
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "HdiCodec"};
31 static const std::unordered_map<OMX_EVENTTYPE, std::string> OMX_EVENT_TO_STRING = {
32 {OMX_EventCmdComplete, "OMX_EventCmdComplete"},
33 {OMX_EventError, "OMX_EventError"},
34 {OMX_EventMark, "OMX_EventMark"},
35 {OMX_EventPortSettingsChanged, "OMX_EventPortSettingsChanged"},
36 {OMX_EventBufferFlag, "OMX_EventBufferFlag"},
37 {OMX_EventResourcesAcquired, "OMX_EventResourcesAcquired"},
38 {OMX_EventComponentResumed, "OMX_EventComponentResumed"},
39 {OMX_EventPortFormatDetected, "OMX_EventPortFormatDetected"},
40 {OMX_EventDynamicResourcesAvailable, "OMX_EventDynamicResourcesAvailable"},
41 {OMX_EventVendorStartUnused, "OMX_EventVendorStartUnused"},
42 {OMX_EventMax, "OMX_EventMax"},
43 };
44 }
45 namespace OHOS {
46 namespace Media {
HdiCodec(const string & component)47 HdiCodec::HdiCodec(const string& component)
48 : componentName_(component), taskQue_("HDICallback")
49 {
50 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
51 }
52
~HdiCodec()53 HdiCodec::~HdiCodec()
54 {
55 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
56 DeinitInner();
57 }
58
InitVersion()59 void HdiCodec::InitVersion()
60 {
61 (void)memset_s(&verInfo_, sizeof(verInfo_), 0, sizeof(verInfo_));
62 int32_t ret = HDF_SUCCESS;
63 LISTENER(ret = handle_->GetComponentVersion(handle_, &verInfo_),
64 "HdiCodec::GetComponentVersion", PlayerXCollie::timerTimeout)
65 CHECK_AND_RETURN_LOG(ret == HDF_SUCCESS, "get version failed");
66 }
67
Init()68 int32_t HdiCodec::Init()
69 {
70 MEDIA_LOGD("Init");
71 (void)taskQue_.Start();
72 callback_ = CodecCallbackTypeStubGetInstance();
73 CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, GST_CODEC_ERROR, "GetCallBack failed");
74 callback_->EventHandler = &HdiCodec::Event;
75 callback_->EmptyBufferDone = &HdiCodec::EmptyBufferDone;
76 callback_->FillBufferDone = &HdiCodec::FillBufferDone;
77 appData_ = new AppData();
78 appData_->instance = weak_from_this();
79 int32_t ret;
80 {
81 MediaTrace trace("HdiCodec::Init");
82 std::weak_ptr<IGstCodec> codec = weak_from_this();
83 HdiInfo info = {componentName_, appData_, callback_, codec};
84 ret = HdiInit::GetInstance().GetHandle(&handle_, id_, info);
85 CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "GetHandle failed");
86 CHECK_AND_RETURN_RET_LOG(handle_ != nullptr, GST_CODEC_ERROR, "Handle is nullptr");
87 InitVersion();
88 InitParam(portParam_, verInfo_);
89 ret = HdiGetParameter(handle_, OMX_IndexParamVideoInit, portParam_);
90 }
91 CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "VideoInit failed");
92 inPortIndex_ = portParam_.nStartPortNumber;
93 outPortIndex_ = portParam_.nStartPortNumber + 1;
94 return GST_CODEC_OK;
95 }
96
DeinitInner()97 void HdiCodec::DeinitInner()
98 {
99 if (handle_) {
100 MEDIA_LOGI("FreeHandle");
101 MediaTrace trace("HdiCodec::Deinit");
102 (void)HdiInit::GetInstance().FreeHandle(handle_, id_);
103 }
104 CodecComponentTypeRelease(handle_);
105 handle_ = nullptr;
106 if (appData_) {
107 delete appData_;
108 appData_ = nullptr;
109 }
110 if (callback_) {
111 CodecCallbackTypeStubRelease(callback_);
112 callback_ = nullptr;
113 }
114 (void)taskQue_.Stop();
115 }
116
Deinit()117 void HdiCodec::Deinit()
118 {
119 MEDIA_LOGD("Deinit");
120 if (curState_ > OMX_StateLoaded) {
121 (void)WaitForState(OMX_StateLoaded);
122 }
123 DeinitInner();
124 }
125
OnCodecDied()126 void HdiCodec::OnCodecDied()
127 {
128 MEDIA_LOGE("OnCodecDied");
129 MediaTrace trace("HdiCodec::OnCodecDied");
130
131 {
132 unique_lock<mutex> lock(mutex_);
133 start_ = false;
134 isError_ = true;
135 cond_.notify_all();
136 }
137
138 {
139 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
140 if (inBufferMgr_) {
141 inBufferMgr_->BufferReleased();
142 }
143 if (outBufferMgr_) {
144 outBufferMgr_->BufferReleased();
145 }
146 }
147
148 {
149 std::unique_lock<std::shared_mutex> wLock(bufferMgrMutex_);
150 inBufferMgr_ = nullptr;
151 outBufferMgr_ = nullptr;
152 }
153 }
154
SetHdiInBufferMgr(shared_ptr<HdiBufferMgr> bufferMgr)155 void HdiCodec::SetHdiInBufferMgr(shared_ptr<HdiBufferMgr> bufferMgr)
156 {
157 std::unique_lock<std::shared_mutex> wLock(bufferMgrMutex_);
158 inBufferMgr_ = bufferMgr;
159 inBufferMgr_->Init(handle_, inPortIndex_, verInfo_);
160 }
161
SetHdiOutBufferMgr(shared_ptr<HdiBufferMgr> bufferMgr)162 void HdiCodec::SetHdiOutBufferMgr(shared_ptr<HdiBufferMgr> bufferMgr)
163 {
164 std::unique_lock<std::shared_mutex> wLock(bufferMgrMutex_);
165 outBufferMgr_ = bufferMgr;
166 outBufferMgr_->Init(handle_, outPortIndex_, verInfo_);
167 }
168
SetHdiParamsMgr(shared_ptr<HdiParamsMgr> paramsMgr)169 void HdiCodec::SetHdiParamsMgr(shared_ptr<HdiParamsMgr> paramsMgr)
170 {
171 paramsMgr_ = paramsMgr;
172 paramsMgr_->Init(handle_, portParam_, verInfo_);
173 }
174
SetParameter(GstCodecParamKey key,GstElement * element)175 int32_t HdiCodec::SetParameter(GstCodecParamKey key, GstElement *element)
176 {
177 CHECK_AND_RETURN_RET_LOG(paramsMgr_ != nullptr, GST_CODEC_ERROR, "paramsMgr_ is nullptr");
178 return paramsMgr_->SetParameter(key, element);
179 }
180
GetParameter(GstCodecParamKey key,GstElement * element)181 int32_t HdiCodec::GetParameter(GstCodecParamKey key, GstElement *element)
182 {
183 CHECK_AND_RETURN_RET_LOG(paramsMgr_ != nullptr, GST_CODEC_ERROR, "paramsMgr_ is nullptr");
184 return paramsMgr_->GetParameter(key, element);
185 }
186
Start()187 int32_t HdiCodec::Start()
188 {
189 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
190 MEDIA_LOGD("Start begin");
191 if (curState_ != OMX_StateExecuting) {
192 CHECK_AND_RETURN_RET_LOG(ChangeState(OMX_StateExecuting) == GST_CODEC_OK, GST_CODEC_ERROR, "Change failed");
193 CHECK_AND_RETURN_RET_LOG(WaitForState(OMX_StateExecuting) == GST_CODEC_OK, GST_CODEC_ERROR, "Wait failed");
194 }
195 {
196 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
197 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
198 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
199 MediaTrace trace("HdiCodec::Start");
200 inBufferMgr_->Start();
201 outBufferMgr_->Start();
202 }
203 unique_lock<mutex> lock(mutex_);
204 start_ = true;
205 MEDIA_LOGD("Start end");
206 return GST_CODEC_OK;
207 }
208
Stop()209 int32_t HdiCodec::Stop()
210 {
211 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_OK, "codec error");
212 {
213 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
214 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
215 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
216 MediaTrace trace("HdiCodec::Stop");
217 inBufferMgr_->Stop(false);
218 outBufferMgr_->Stop(false);
219 }
220 if (curState_ == OMX_StateExecuting) {
221 CHECK_AND_RETURN_RET_LOG(ChangeState(OMX_StateIdle) == GST_CODEC_OK, GST_CODEC_ERROR, "ChangeState failed");
222 CHECK_AND_RETURN_RET_LOG(WaitForState(OMX_StateIdle) == GST_CODEC_OK, GST_CODEC_ERROR, "Wait failed");
223 }
224 if (curState_ == OMX_StateIdle) {
225 CHECK_AND_RETURN_RET_LOG(ChangeState(OMX_StateLoaded) == GST_CODEC_OK, GST_CODEC_ERROR, "ChangeState failed");
226 }
227 unique_lock<mutex> lock(mutex_);
228 start_ = false;
229 return GST_CODEC_OK;
230 }
231
ChangeState(OMX_STATETYPE state)232 int32_t HdiCodec::ChangeState(OMX_STATETYPE state)
233 {
234 MEDIA_LOGD("Change state from %{public}u to %{public}u", targetState_, state);
235 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
236 if (targetState_ != state && curState_ != state) {
237 auto ret = HdiSendCommand(handle_, OMX_CommandStateSet, state, 0);
238 CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "HdiSendCommand failed");
239 targetState_ = state;
240 }
241 return GST_CODEC_OK;
242 }
243
UseInputBuffers(std::vector<GstBuffer * > buffers)244 int32_t HdiCodec::UseInputBuffers(std::vector<GstBuffer*> buffers)
245 {
246 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
247 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
248 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
249 MediaTrace trace("HdiCodec::UseInputBuffers");
250 return inBufferMgr_->UseBuffers(buffers);
251 }
252
PushInputBuffer(GstBuffer * buffer)253 int32_t HdiCodec::PushInputBuffer(GstBuffer *buffer)
254 {
255 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
256 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
257 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
258 return inBufferMgr_->PushBuffer(buffer);
259 }
260
Flush(GstCodecDirect direct)261 int32_t HdiCodec::Flush(GstCodecDirect direct)
262 {
263 MEDIA_LOGD("Flush start");
264 if (!start_) {
265 return GST_CODEC_OK;
266 }
267
268 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
269 CHECK_AND_RETURN_RET_LOG(handle_ != nullptr, GST_CODEC_ERROR, "Handle is nullptr");
270 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
271 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
272 int32_t ret = HDF_SUCCESS;
273 if (direct == GST_CODEC_ALL) {
274 inBufferMgr_->Flush(true);
275 outBufferMgr_->Flush(true);
276 ret = HdiSendCommand(handle_, OMX_CommandFlush, -1, 0);
277 }
278 CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "HdiSendCommand failed");
279 inBufferMgr_->WaitFlushed();
280 outBufferMgr_->WaitFlushed();
281 startFormatChange_.store(false);
282 MEDIA_LOGD("Flush end");
283 return GST_CODEC_OK;
284 }
285
ActiveBufferMgr(GstCodecDirect direct,bool active)286 int32_t HdiCodec::ActiveBufferMgr(GstCodecDirect direct, bool active)
287 {
288 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
289 CHECK_AND_RETURN_RET_LOG(handle_ != nullptr, GST_CODEC_ERROR, "Handle is nullptr");
290 int32_t ret = HDF_SUCCESS;
291 // do not deal with input
292 if (direct == GST_CODEC_OUTPUT) {
293 if (active) {
294 ret = HdiSendCommand(handle_, OMX_CommandPortEnable, outPortIndex_, 0);
295 unique_lock<mutex> lock(mutex_);
296 outState_ = ACTIVING;
297 } else {
298 MEDIA_LOGD("OMX_CommandPortDisable out %{public}u", outPortIndex_);
299 ret = HdiSendCommand(handle_, OMX_CommandPortDisable, outPortIndex_, 0);
300 unique_lock<mutex> lock(mutex_);
301 outState_ = DEACTIVING;
302 }
303 }
304 CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "port change fail");
305 return GST_CODEC_OK;
306 }
307
FreeInputBuffers()308 int32_t HdiCodec::FreeInputBuffers()
309 {
310 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
311 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_OK, "codec error");
312 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
313 CHECK_AND_RETURN_RET_LOG(inBufferMgr_->FreeBuffers() == GST_CODEC_OK, GST_CODEC_ERROR, "Freebuffer fail");
314 if (inState_ == DEACTIVING) {
315 WaitForEvent(OMX_CommandPortDisable);
316 }
317 return GST_CODEC_OK;
318 }
319
UseOutputBuffers(std::vector<GstBuffer * > buffers)320 int32_t HdiCodec::UseOutputBuffers(std::vector<GstBuffer*> buffers)
321 {
322 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
323 MEDIA_LOGD("UseOutputBuffers");
324 MediaTrace trace("HdiCodec::UseOutputBuffers");
325 if (curState_ < OMX_StateIdle) {
326 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
327 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
328 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
329 CHECK_AND_RETURN_RET_LOG(ChangeState(OMX_StateIdle) == GST_CODEC_OK,
330 GST_CODEC_ERROR, "ChangeState failed");
331 // m40 need input and output allocate or use common
332 CHECK_AND_RETURN_RET_LOG(inBufferMgr_->Preprocessing() == GST_CODEC_OK,
333 GST_CODEC_ERROR, "Allocatebuffer fail");
334 CHECK_AND_RETURN_RET_LOG(outBufferMgr_->UseBuffers(buffers) == GST_CODEC_OK,
335 GST_CODEC_ERROR, "UseBuffers fail");
336 CHECK_AND_RETURN_RET_LOG(WaitForState(OMX_StateIdle) == GST_CODEC_OK,
337 GST_CODEC_ERROR, "Wait failed");
338 } else if (outState_ == ACTIVING) {
339 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
340 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
341 CHECK_AND_RETURN_RET_LOG(outBufferMgr_->UseBuffers(buffers) == GST_CODEC_OK,
342 GST_CODEC_ERROR, "Usebuffer fail");
343 WaitForEvent(OMX_CommandPortEnable);
344 }
345 return GST_CODEC_OK;
346 }
347
PushOutputBuffer(GstBuffer * buffer)348 int32_t HdiCodec::PushOutputBuffer(GstBuffer *buffer)
349 {
350 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
351 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
352 return outBufferMgr_->PushBuffer(buffer);
353 }
354
PullOutputBuffer(GstBuffer ** buffer)355 int32_t HdiCodec::PullOutputBuffer(GstBuffer **buffer)
356 {
357 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_ERROR, "codec error");
358 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
359 int32_t ret = GST_CODEC_OK;
360 {
361 unique_lock<mutex> lock(mutex_);
362 if ((ret_ != GST_CODEC_OK && ret_ != GST_CODEC_FORMAT_CHANGE) ||
363 (ret_ == GST_CODEC_FORMAT_CHANGE && outBufferMgr_->GetWaitDisPlayBufNum() == 0)) {
364 MEDIA_LOGD("change ret from ret %{public}d to ret %{public}d", ret, ret_);
365 ret = ret_;
366 ret_ = GST_CODEC_OK;
367 return ret;
368 }
369 }
370 {
371 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
372 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
373 ret = outBufferMgr_->PullBuffer(buffer);
374 }
375 MEDIA_LOGD("ret %{public}d", ret);
376 {
377 unique_lock<mutex> lock(mutex_);
378 if ((ret_ != GST_CODEC_OK && ret_ != GST_CODEC_FORMAT_CHANGE) ||
379 (ret_ == GST_CODEC_FORMAT_CHANGE && outBufferMgr_->GetWaitDisPlayBufNum() == 0)) {
380 MEDIA_LOGD("change ret from ret %{public}d to ret %{public}d", ret, ret_);
381 ret = ret_;
382 ret_ = GST_CODEC_OK;
383 return ret;
384 }
385 }
386 return ret;
387 }
388
SetOutputPool(GstBufferPool * pool)389 void HdiCodec::SetOutputPool(GstBufferPool *pool)
390 {
391 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
392 CHECK_AND_RETURN_LOG(outBufferMgr_ != nullptr, "outBufferMgr_ is nullptr");
393 outBufferMgr_->SetOutputPool(pool);
394 }
395
FreeOutputBuffers()396 int32_t HdiCodec::FreeOutputBuffers()
397 {
398 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
399 CHECK_AND_RETURN_RET_LOG(!isError_, GST_CODEC_OK, "codec error");
400 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
401 MEDIA_LOGD("FreeOutputBuffers");
402 CHECK_AND_RETURN_RET_LOG(outBufferMgr_->FreeBuffers() == GST_CODEC_OK, GST_CODEC_ERROR, "Freebuffers fail");
403 if (outState_ == DEACTIVING) {
404 WaitForEvent(OMX_CommandPortDisable);
405 }
406 return GST_CODEC_OK;
407 }
408
Event(CodecCallbackType * self,OMX_EVENTTYPE event,EventInfo * info)409 int32_t HdiCodec::Event(CodecCallbackType *self, OMX_EVENTTYPE event, EventInfo *info)
410 {
411 MediaTrace trace("HdiCodec::Event");
412 (void)self;
413 CHECK_AND_RETURN_RET_LOG(info != nullptr, HDF_ERR_INVALID_PARAM, "appData is null");
414 if (OMX_EVENT_TO_STRING.find(event) != OMX_EVENT_TO_STRING.end()) {
415 MEDIA_LOGD("Event %{public}s %{public}d data1 %{public}d data2 %{public}d",
416 OMX_EVENT_TO_STRING.at(event).c_str(), event, info->data1, info->data2);
417 } else {
418 MEDIA_LOGW("Unknown event %{public}d data1 %{public}d data2 %{public}d",
419 event, info->data1, info->data2);
420 }
421 AppData *mAppData = reinterpret_cast<AppData *>(info->appData);
422 auto instance = mAppData->instance.lock();
423 CHECK_AND_RETURN_RET_LOG(instance != nullptr, HDF_ERR_INVALID_PARAM, "HdiCodec is null");
424 return instance->OnEvent(event, info);
425 }
426
OnEvent(OMX_EVENTTYPE event,EventInfo * info)427 int32_t HdiCodec::OnEvent(OMX_EVENTTYPE event, EventInfo *info)
428 {
429 auto task = std::make_shared<TaskHandler<void>>([this, event, info] {
430 switch (event) {
431 case OMX_EventCmdComplete:
432 return HandelEventCmdComplete(info->data1, info->data2);
433 case OMX_EventPortSettingsChanged:
434 return HandleEventPortSettingsChanged(info->data1, info->data2);
435 case OMX_EventBufferFlag:
436 return HandleEventBufferFlag(info->data1, info->data2);
437 case OMX_EventError:
438 return HandleEventError(info->data1);
439 default:
440 break;
441 }
442 });
443 (void)taskQue_.EnqueueTask(task);
444 (void)task->GetResult();
445 return HDF_SUCCESS;
446 }
447
WaitForState(OMX_STATETYPE state)448 int32_t HdiCodec::WaitForState(OMX_STATETYPE state)
449 {
450 WaitForEvent(OMX_CommandStateSet);
451 CHECK_AND_RETURN_RET_LOG(curState_ == state, GST_CODEC_ERROR, "Wait state failed");
452 return GST_CODEC_OK;
453 }
454
WaitForEvent(OMX_U32 cmd)455 void HdiCodec::WaitForEvent(OMX_U32 cmd)
456 {
457 unique_lock<mutex> lock(mutex_);
458 int32_t newCmd = static_cast<int32_t>(cmd);
459 MEDIA_LOGD("wait eventdone %{public}d lastcmd %{public}d cmd %{public}u", eventDone_, lastCmd_, cmd);
460 static constexpr int32_t timeout = 2;
461 cond_.wait_for(lock, std::chrono::seconds(timeout),
462 [this, &newCmd]() { return (eventDone_ && (lastCmd_ == newCmd || lastCmd_ == -1)) || isError_; });
463 eventDone_ = false;
464 }
465
HandelEventStateSet(OMX_U32 data)466 void HdiCodec::HandelEventStateSet(OMX_U32 data)
467 {
468 MEDIA_LOGD("change curState_ from %{public}u to %{public}u", curState_, data);
469 curState_ = static_cast<OMX_STATETYPE>(data);
470 eventDone_ = true;
471 }
472
HandelEventFlush(OMX_U32 data)473 void HdiCodec::HandelEventFlush(OMX_U32 data)
474 {
475 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
476 if (data == inPortIndex_) {
477 CHECK_AND_RETURN_LOG(inBufferMgr_ != nullptr, "inBufferMgr_ is nullptr");
478 inBufferMgr_->Flush(false);
479 } else {
480 CHECK_AND_RETURN_LOG(outBufferMgr_ != nullptr, "outBufferMgr_ is nullptr");
481 outBufferMgr_->Flush(false);
482 }
483 }
484
HandelEventPortDisable(OMX_U32 data)485 void HdiCodec::HandelEventPortDisable(OMX_U32 data)
486 {
487 if (data != inPortIndex_) {
488 outState_ = DEACTIVATED;
489 }
490 eventDone_ = true;
491 }
492
HandelEventPortEnable(OMX_U32 data)493 void HdiCodec::HandelEventPortEnable(OMX_U32 data)
494 {
495 if (data != inPortIndex_) {
496 outState_ = ACTIVATED;
497 }
498 eventDone_ = true;
499 }
500
HandelEventCmdComplete(OMX_U32 data1,OMX_U32 data2)501 void HdiCodec::HandelEventCmdComplete(OMX_U32 data1, OMX_U32 data2)
502 {
503 unique_lock<mutex> lock(mutex_);
504 lastCmd_ = (int32_t)data1;
505 switch (data1) {
506 case OMX_CommandStateSet:
507 HandelEventStateSet(data2);
508 break;
509 case OMX_CommandFlush:
510 HandelEventFlush(data2);
511 break;
512 case OMX_CommandPortDisable:
513 HandelEventPortDisable(data2);
514 break;
515 case OMX_CommandPortEnable:
516 HandelEventPortEnable(data2);
517 break;
518 default:
519 break;
520 }
521 cond_.notify_all();
522 }
523
HandleEventPortSettingsChanged(OMX_U32 data1,OMX_U32 data2)524 void HdiCodec::HandleEventPortSettingsChanged(OMX_U32 data1, OMX_U32 data2)
525 {
526 MEDIA_LOGD("handle change");
527 unique_lock<mutex> lock(mutex_);
528 if (data2 == OMX_IndexParamPortDefinition) {
529 MEDIA_LOGD("GST_CODEC_FORMAT_CHANGE");
530 ret_ = GST_CODEC_FORMAT_CHANGE;
531 startFormatChange_.store(true);
532 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
533 CHECK_AND_RETURN_LOG(data1 != inPortIndex_, "inPortIndex_ setting changed");
534 if (data1 != inPortIndex_) {
535 CHECK_AND_RETURN_LOG(outBufferMgr_ != nullptr, "outBufferMgr_ is nullptr");
536 outBufferMgr_->Stop(true);
537 }
538 }
539 MEDIA_LOGD("handle change end");
540 }
541
HandleEventBufferFlag(OMX_U32 data1,OMX_U32 data2)542 void HdiCodec::HandleEventBufferFlag(OMX_U32 data1, OMX_U32 data2)
543 {
544 unique_lock<mutex> lock(mutex_);
545 if (data1 == 1 && (data2 & OMX_BUFFERFLAG_EOS)) {
546 MEDIA_LOGD("it is eos, wait buffer eos");
547 }
548 }
549
HandleEventError(OMX_U32 data)550 void HdiCodec::HandleEventError(OMX_U32 data)
551 {
552 (void)data;
553 unique_lock<mutex> lock(mutex_);
554 ret_ = GST_CODEC_ERROR;
555 eventDone_ = true;
556 lastCmd_ = -1;
557 cond_.notify_all();
558 }
559
EmptyBufferDone(CodecCallbackType * self,int64_t appData,const OmxCodecBuffer * buffer)560 int32_t HdiCodec::EmptyBufferDone(CodecCallbackType *self, int64_t appData, const OmxCodecBuffer *buffer)
561 {
562 MediaTrace trace("HdiCodec::EmptyBufferDone");
563 MEDIA_LOGD("EmptyBufferDone");
564 (void)self;
565 AppData *mAppData = reinterpret_cast<AppData *>(appData);
566 CHECK_AND_RETURN_RET_LOG(mAppData != nullptr, HDF_ERR_INVALID_PARAM, "appData is null");
567 auto instance = mAppData->instance.lock();
568 CHECK_AND_RETURN_RET_LOG(instance != nullptr, HDF_ERR_INVALID_PARAM, "HdiCodec is null");
569 CHECK_AND_RETURN_RET_LOG(instance->OnEmptyBufferDone(buffer) == GST_CODEC_OK,
570 OMX_ErrorBadParameter, "empty buffer done failed");
571 return HDF_SUCCESS;
572 }
573
OnEmptyBufferDone(const OmxCodecBuffer * buffer)574 int32_t HdiCodec::OnEmptyBufferDone(const OmxCodecBuffer *buffer)
575 {
576 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
577 CHECK_AND_RETURN_RET_LOG(inBufferMgr_ != nullptr, GST_CODEC_ERROR, "inBufferMgr_ is nullptr");
578 auto task = std::make_shared<TaskHandler<int32_t>>([this, buffer] {
579 return inBufferMgr_->CodecBufferAvailable(buffer);
580 });
581 (void)taskQue_.EnqueueTask(task);
582 auto result = task->GetResult();
583 int32_t ret = GST_CODEC_OK;
584 if (result.HasResult()) {
585 ret = result.Value();
586 }
587 return ret;
588 }
589
FillBufferDone(CodecCallbackType * self,int64_t appData,const OmxCodecBuffer * buffer)590 int32_t HdiCodec::FillBufferDone(CodecCallbackType *self, int64_t appData, const OmxCodecBuffer *buffer)
591 {
592 MediaTrace trace("HdiCodec::FillBufferDone");
593 MEDIA_LOGD("FillBufferDone");
594 (void)self;
595 AppData *mAppData = reinterpret_cast<AppData *>(appData);
596 CHECK_AND_RETURN_RET_LOG(mAppData != nullptr, OMX_ErrorBadParameter, "appData is null");
597 auto instance = mAppData->instance.lock();
598 CHECK_AND_RETURN_RET_LOG(instance != nullptr, OMX_ErrorBadParameter, "HdiCodec is null");
599 if (instance->OnFillBufferDone(buffer) != GST_CODEC_OK) {
600 MEDIA_LOGE("fill buffer done failed");
601 return OMX_ErrorBadParameter;
602 }
603 return HDF_SUCCESS;
604 }
605
OnFillBufferDone(const OmxCodecBuffer * buffer)606 int32_t HdiCodec::OnFillBufferDone(const OmxCodecBuffer *buffer)
607 {
608 std::shared_lock<std::shared_mutex> rLock(bufferMgrMutex_);
609 CHECK_AND_RETURN_RET_LOG(outBufferMgr_ != nullptr, GST_CODEC_ERROR, "outBufferMgr_ is nullptr");
610 auto task = std::make_shared<TaskHandler<int32_t>>([this, buffer] {
611 return outBufferMgr_->CodecBufferAvailable(buffer);
612 });
613 (void)taskQue_.EnqueueTask(task);
614 auto result = task->GetResult();
615 int32_t ret = GST_CODEC_OK;
616 if (result.HasResult()) {
617 ret = result.Value();
618 }
619 return ret;
620 }
621
IsFormatChanged()622 bool HdiCodec::IsFormatChanged()
623 {
624 bool ret = startFormatChange_.load();
625 startFormatChange_.store(false);
626 return ret;
627 }
628 } // namespace Media
629 } // namespace OHOS
630