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 "hcodec.h"
17 #include <cassert>
18 #include <vector>
19 #include <algorithm>
20 #include <thread>
21 #include "syspara/parameters.h" // base/startup/init/interfaces/innerkits/include/
22 #include "qos.h"
23 #include "hdf_base.h"
24 #include "codec_omx_ext.h"
25 #include "hcodec_list.h"
26 #include "hencoder.h"
27 #include "hdecoder.h"
28 #include "hitrace_meter.h"
29 #include "hcodec_log.h"
30 #include "hcodec_dfx.h"
31 #include "hcodec_utils.h"
32 #include <sys/ioctl.h>
33 #include <linux/dma-buf.h>
34 #define DMA_BUF_SET_LEAK_TYPE _IOW(DMA_BUF_BASE, 5, const char *)
35
36 namespace OHOS::MediaAVCodec {
37 using namespace std;
38 using namespace CodecHDI;
39 using namespace Media;
40
SetCallerToBuffer(int fd,uint32_t w,uint32_t h)41 void HCodec::SetCallerToBuffer(int fd, uint32_t w, uint32_t h)
42 {
43 const char* type = isEncoder_ ? "hw-video-encoder" : "hw-video-decoder";
44 ioctl(fd, DMA_BUF_SET_LEAK_TYPE, type);
45
46 string bufName = to_string(w) + 'x' + to_string(h) + '-' + mime_ + '-' + to_string(componentId_);
47 ioctl(fd, DMA_BUF_SET_NAME_A, bufName.c_str());
48 }
49
Create(const std::string & name)50 std::shared_ptr<HCodec> HCodec::Create(const std::string &name)
51 {
52 vector<CodecCompCapability> capList = GetCapList();
53 shared_ptr<HCodec> codec;
54 for (const auto& cap : capList) {
55 if (cap.compName != name) {
56 continue;
57 }
58 optional<OMX_VIDEO_CODINGTYPE> type = TypeConverter::HdiRoleToOmxCodingType(cap.role);
59 if (!type) {
60 LOGE("unsupported role %d", cap.role);
61 return nullptr;
62 }
63 if (cap.type == VIDEO_DECODER) {
64 codec = make_shared<HDecoder>(cap, type.value());
65 } else if (cap.type == VIDEO_ENCODER) {
66 codec = make_shared<HEncoder>(cap, type.value());
67 }
68 break;
69 }
70 if (codec == nullptr) {
71 LOGE("cannot find %s", name.c_str());
72 return nullptr;
73 }
74 return codec;
75 }
76
Init(Media::Meta & callerInfo)77 int32_t HCodec::Init(Media::Meta &callerInfo)
78 {
79 if (callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PID, caller_.playerCaller.pid) &&
80 callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, caller_.playerCaller.processName)) {
81 caller_.calledByAvcodec = false;
82 caller_.app = caller_.playerCaller;
83 } else if (callerInfo.GetData(Tag::AV_CODEC_CALLER_PID, caller_.avcodecCaller.pid) &&
84 callerInfo.GetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, caller_.avcodecCaller.processName)) {
85 caller_.calledByAvcodec = true;
86 caller_.app = caller_.avcodecCaller;
87 }
88 callerInfo.GetData("av_codec_event_info_instance_id", instanceId_);
89 return DoSyncCall(MsgWhat::INIT, nullptr);
90 }
91
92 std::shared_mutex HCodec::g_mtx;
93 std::unordered_map<std::string, HCodec::Caller> HCodec::g_callers;
94
PrintCaller()95 void HCodec::PrintCaller()
96 {
97 if (caller_.calledByAvcodec) {
98 HLOGI("[pid %d][%s] -> avcodec", caller_.avcodecCaller.pid, caller_.avcodecCaller.processName.c_str());
99 } else {
100 HLOGI("[pid %d][%s] -> player -> avcodec", caller_.playerCaller.pid, caller_.playerCaller.processName.c_str());
101 }
102 std::unique_lock<std::shared_mutex> lk(g_mtx);
103 g_callers[compUniqueStr_] = caller_;
104 }
105
PrintAllCaller()106 void HCodec::PrintAllCaller()
107 {
108 std::shared_lock<std::shared_mutex> lk(g_mtx);
109 for (const auto& [inst, caller] : g_callers) {
110 if (caller.calledByAvcodec) {
111 LOGI("%s: [pid %d][%s] -> avcodec", inst.c_str(),
112 caller.avcodecCaller.pid, caller.avcodecCaller.processName.c_str());
113 } else {
114 LOGI("%s: [pid %d][%s] -> player -> avcodec", inst.c_str(),
115 caller.playerCaller.pid, caller.playerCaller.processName.c_str());
116 }
117 }
118 }
119
RemoveCaller()120 void HCodec::RemoveCaller()
121 {
122 std::unique_lock<std::shared_mutex> lk(g_mtx);
123 g_callers.erase(compUniqueStr_);
124 }
125
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)126 int32_t HCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
127 {
128 HLOGD(">>");
129 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
130 msg->SetValue("callback", callback);
131 };
132 return DoSyncCall(MsgWhat::SET_CALLBACK, proc);
133 }
134
Configure(const Format & format)135 int32_t HCodec::Configure(const Format &format)
136 {
137 SCOPED_TRACE();
138 HLOGI("%s", format.Stringify().c_str());
139 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
140 msg->SetValue("format", format);
141 };
142 return DoSyncCall(MsgWhat::CONFIGURE, proc);
143 }
144
SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)145 int32_t HCodec::SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)
146 {
147 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
148 msg->SetValue("buffer", buffer);
149 };
150 return DoSyncCall(MsgWhat::CONFIGURE_BUFFER, proc);
151 }
152
SetOutputSurface(sptr<Surface> surface)153 int32_t HCodec::SetOutputSurface(sptr<Surface> surface)
154 {
155 HLOGI(">>");
156 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
157 msg->SetValue("surface", surface);
158 };
159 return DoSyncCall(MsgWhat::SET_OUTPUT_SURFACE, proc);
160 }
161
Start()162 int32_t HCodec::Start()
163 {
164 SCOPED_TRACE();
165 FUNC_TRACKER();
166 return DoSyncCall(MsgWhat::START, nullptr,
167 (isSecure_ ? FIVE_SECONDS_IN_MS * 2 : FIVE_SECONDS_IN_MS)); // 2: Secure mode
168 }
169
Stop()170 int32_t HCodec::Stop()
171 {
172 SCOPED_TRACE();
173 FUNC_TRACKER();
174 return DoSyncCall(MsgWhat::STOP, nullptr);
175 }
176
Flush()177 int32_t HCodec::Flush()
178 {
179 SCOPED_TRACE();
180 FUNC_TRACKER();
181 return DoSyncCall(MsgWhat::FLUSH, nullptr);
182 }
183
Reset()184 int32_t HCodec::Reset()
185 {
186 SCOPED_TRACE();
187 FUNC_TRACKER();
188 int32_t ret = Release();
189 if (ret == AVCS_ERR_OK) {
190 ret = DoSyncCall(MsgWhat::INIT, nullptr);
191 }
192 return ret;
193 }
194
Release()195 int32_t HCodec::Release()
196 {
197 SCOPED_TRACE();
198 FUNC_TRACKER();
199 return DoSyncCall(MsgWhat::RELEASE, nullptr);
200 }
201
NotifyEos()202 int32_t HCodec::NotifyEos()
203 {
204 HLOGI(">>");
205 return DoSyncCall(MsgWhat::NOTIFY_EOS, nullptr);
206 }
207
SetParameter(const Format & format)208 int32_t HCodec::SetParameter(const Format &format)
209 {
210 HLOGI("%s", format.Stringify().c_str());
211 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
212 msg->SetValue("params", format);
213 };
214 return DoSyncCall(MsgWhat::SET_PARAMETERS, proc);
215 }
216
GetInputFormat(Format & format)217 int32_t HCodec::GetInputFormat(Format& format)
218 {
219 HLOGI(">>");
220 ParamSP reply;
221 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_INPUT_FORMAT, nullptr, reply);
222 if (ret != AVCS_ERR_OK) {
223 HLOGE("failed to get input format");
224 return ret;
225 }
226 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format),
227 AVCS_ERR_UNKNOWN, "input format not replied");
228 return AVCS_ERR_OK;
229 }
230
GetOutputFormat(Format & format)231 int32_t HCodec::GetOutputFormat(Format &format)
232 {
233 ParamSP reply;
234 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_OUTPUT_FORMAT, nullptr, reply);
235 if (ret != AVCS_ERR_OK) {
236 HLOGE("failed to get output format");
237 return ret;
238 }
239 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format),
240 AVCS_ERR_UNKNOWN, "output format not replied");
241 format.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, caps_.compName);
242 format.PutIntValue("IS_VENDOR", 1);
243 return AVCS_ERR_OK;
244 }
245
246 // LCOV_EXCL_START
GetChannelId(int32_t & channelId)247 int32_t HCodec::GetChannelId(int32_t &channelId)
248 {
249 GetChannelIdParam param {};
250 InitOMXParamExt(param);
251 if (!GetParameter(OMX_IndexParamChannelId, param)) {
252 HLOGI("LowPowerPlayer GetChannelId failed");
253 return AVCS_ERR_UNKNOWN;
254 }
255 HLOGI("LowPowerPlayer GetChannelId Success");
256 channelId = param.channelId;
257 return AVCS_ERR_OK;
258 }
259
SetLowPowerPlayerMode(bool isLpp)260 int32_t HCodec::SetLowPowerPlayerMode(bool isLpp)
261 {
262 bool originalIsLpp = isLpp_;
263 isLpp_ = isLpp;
264 GetLppModeParam param {};
265 InitOMXParamExt(param);
266 param.enable = isLpp;
267 if (!SetParameter(OMX_IndexParamLppMode, param)) {
268 HLOGE("set LowPowerPlayer Mode failed");
269 isLpp_ = originalIsLpp;
270 return AVCS_ERR_UNKNOWN;
271 }
272 return AVCS_ERR_OK;
273 }
274
GetHidumperInfo()275 std::string HCodec::GetHidumperInfo()
276 {
277 HLOGI(">>");
278 ParamSP reply;
279 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_HIDUMPER_INFO, nullptr, reply);
280 if (ret != AVCS_ERR_OK) {
281 HLOGW("failed to get hidumper info");
282 return "";
283 }
284 string info;
285 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("hidumper-info", info),
286 "", "hidumper info not replied");
287 return info;
288 }
289 // LCOV_EXCL_STOP
290
CreateInputSurface()291 sptr<Surface> HCodec::CreateInputSurface()
292 {
293 HLOGI(">>");
294 ParamSP reply;
295 int32_t ret = DoSyncCallAndGetReply(MsgWhat::CREATE_INPUT_SURFACE, nullptr, reply);
296 if (ret != AVCS_ERR_OK) {
297 HLOGE("failed to create input surface");
298 return nullptr;
299 }
300 sptr<Surface> inputSurface;
301 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("surface", inputSurface), nullptr, "input surface not replied");
302 return inputSurface;
303 }
304
SetInputSurface(sptr<Surface> surface)305 int32_t HCodec::SetInputSurface(sptr<Surface> surface)
306 {
307 HLOGI(">>");
308 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
309 msg->SetValue("surface", surface);
310 };
311 return DoSyncCall(MsgWhat::SET_INPUT_SURFACE, proc);
312 }
313
SignalRequestIDRFrame()314 int32_t HCodec::SignalRequestIDRFrame()
315 {
316 HLOGI(">>");
317 return DoSyncCall(MsgWhat::REQUEST_IDR_FRAME, nullptr);
318 }
319
QueueInputBuffer(uint32_t index)320 int32_t HCodec::QueueInputBuffer(uint32_t index)
321 {
322 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
323 msg->SetValue(BUFFER_ID, index);
324 };
325 return DoSyncCall(MsgWhat::QUEUE_INPUT_BUFFER, proc);
326 }
327
RenderOutputBuffer(uint32_t index)328 int32_t HCodec::RenderOutputBuffer(uint32_t index)
329 {
330 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
331 msg->SetValue(BUFFER_ID, index);
332 };
333 return DoSyncCall(MsgWhat::RENDER_OUTPUT_BUFFER, proc);
334 }
335
ReleaseOutputBuffer(uint32_t index)336 int32_t HCodec::ReleaseOutputBuffer(uint32_t index)
337 {
338 std::function<void(ParamSP)> proc = [&](ParamSP msg) {
339 msg->SetValue(BUFFER_ID, index);
340 };
341 return DoSyncCall(MsgWhat::RELEASE_OUTPUT_BUFFER, proc);
342 }
343 /**************************** public functions end ****************************/
344
345
HCodec(CodecCompCapability caps,OMX_VIDEO_CODINGTYPE codingType,bool isEncoder)346 HCodec::HCodec(CodecCompCapability caps, OMX_VIDEO_CODINGTYPE codingType, bool isEncoder)
347 : caps_(caps), codingType_(codingType), isEncoder_(isEncoder)
348 {
349 debugMode_ = HiLogIsLoggable(HCODEC_DOMAIN, HCODEC_TAG, LOG_DEBUG);
350 string dumpModeStr = OHOS::system::GetParameter("hcodec.dump", "0");
351 dumpMode_ = static_cast<DumpMode>(strtoul(dumpModeStr.c_str(), nullptr, 2)); // 2 is binary
352 disableDmaSwap_ = OHOS::system::GetBoolParameter("hcodec.dmaswap.disable", false);
353 pid_ = getpid();
354
355 switch (static_cast<int>(codingType_)) {
356 case OMX_VIDEO_CodingAVC:
357 mime_ = "avc";
358 break;
359 case CODEC_OMX_VIDEO_CodingHEVC:
360 mime_ = "hevc";
361 break;
362 case CODEC_OMX_VIDEO_CodingVVC:
363 mime_ = "vvc";
364 break;
365 default:
366 break;
367 };
368 isSecure_ = IsSecureMode(caps_.compName);
369
370 uninitializedState_ = make_shared<UninitializedState>(this);
371 initializedState_ = make_shared<InitializedState>(this);
372 startingState_ = make_shared<StartingState>(this);
373 runningState_ = make_shared<RunningState>(this);
374 outputPortChangedState_ = make_shared<OutputPortChangedState>(this);
375 stoppingState_ = make_shared<StoppingState>(this);
376 flushingState_ = make_shared<FlushingState>(this);
377 frozenState_ = make_shared<FrozenState>(this);
378 StateMachine::ChangeStateTo(uninitializedState_);
379 }
380
~HCodec()381 HCodec::~HCodec()
382 {
383 HLOGI(">>");
384 MsgHandleLoop::Stop();
385 ReleaseComponent();
386 }
387
EventHandler(CodecEventType event,const EventInfo & info)388 int32_t HCodec::HdiCallback::EventHandler(CodecEventType event, const EventInfo &info)
389 {
390 LOGD("event = %d, data1 = %u, data2 = %u", event, info.data1, info.data2);
391 ParamSP msg = make_shared<ParamBundle>();
392 msg->SetValue("event", event);
393 msg->SetValue("data1", info.data1);
394 msg->SetValue("data2", info.data2);
395 std::shared_ptr<MsgToken> codec = codec_.lock();
396 if (codec == nullptr) {
397 LOGI("HCodec is gone");
398 return HDF_SUCCESS;
399 }
400 codec->SendAsyncMsg(MsgWhat::CODEC_EVENT, msg);
401 return HDF_SUCCESS;
402 }
403
EmptyBufferDone(int64_t appData,const OmxCodecBuffer & buffer)404 int32_t HCodec::HdiCallback::EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer)
405 {
406 ParamSP msg = make_shared<ParamBundle>();
407 msg->SetValue(BUFFER_ID, buffer.bufferId);
408 std::shared_ptr<MsgToken> codec = codec_.lock();
409 if (codec == nullptr) {
410 LOGI("HCodec is gone");
411 return HDF_SUCCESS;
412 }
413 codec->SendAsyncMsg(MsgWhat::OMX_EMPTY_BUFFER_DONE, msg);
414 return HDF_SUCCESS;
415 }
416
FillBufferDone(int64_t appData,const OmxCodecBuffer & buffer)417 int32_t HCodec::HdiCallback::FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer)
418 {
419 ParamSP msg = make_shared<ParamBundle>();
420 msg->SetValue("omxBuffer", buffer);
421 std::shared_ptr<MsgToken> codec = codec_.lock();
422 if (codec == nullptr) {
423 LOGI("HCodec is gone");
424 return HDF_SUCCESS;
425 }
426 codec->SendAsyncMsg(MsgWhat::OMX_FILL_BUFFER_DONE, msg);
427 return HDF_SUCCESS;
428 }
429
SetFrameRateAdaptiveMode(const Format & format)430 int32_t HCodec::SetFrameRateAdaptiveMode(const Format &format)
431 {
432 if (!format.ContainKey(OHOS::Media::Tag::VIDEO_FRAME_RATE_ADAPTIVE_MODE)) {
433 return AVCS_ERR_UNKNOWN;
434 }
435
436 WorkingFrequencyParam param {};
437 InitOMXParamExt(param);
438 if (!GetParameter(OMX_IndexParamWorkingFrequency, param)) {
439 HLOGW("get working freq param failed");
440 return AVCS_ERR_UNKNOWN;
441 }
442 if (param.level == 0) {
443 return AVCS_ERR_UNKNOWN;
444 }
445 HLOGI("level cnt is %d, set level to %d", param.level, param.level - 1);
446 param.level = param.level - 1;
447
448 if (!SetParameter(OMX_IndexParamWorkingFrequency, param)) {
449 HLOGW("set working freq param failed");
450 return AVCS_ERR_UNKNOWN;
451 }
452 return AVCS_ERR_OK;
453 }
454
SetProcessName()455 int32_t HCodec::SetProcessName()
456 {
457 const std::string& processName = caller_.app.processName;
458 HLOGI("processName is %s", processName.c_str());
459
460 ProcessNameParam param {};
461 InitOMXParamExt(param);
462 if (strcpy_s(param.processName, sizeof(param.processName), processName.c_str()) != EOK) {
463 HLOGW("strcpy failed");
464 return AVCS_ERR_UNKNOWN;
465 }
466 if (!SetParameter(OMX_IndexParamProcessName, param)) {
467 HLOGW("set process name failed");
468 return AVCS_ERR_UNKNOWN;
469 }
470 return AVCS_ERR_OK;
471 }
472
SetLowLatency(const Format & format)473 int32_t HCodec::SetLowLatency(const Format &format)
474 {
475 int32_t enableLowLatency;
476 if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENABLE_LOW_LATENCY, enableLowLatency)) {
477 return AVCS_ERR_OK;
478 }
479 if (!HCodecList::FindFeature(caps_.port.video.features, VIDEO_FEATURE_LOW_LATENCY).support) {
480 HLOGW("platform not support LowLatency");
481 return AVCS_ERR_OK;
482 }
483
484 OMX_CONFIG_BOOLEANTYPE param {};
485 InitOMXParam(param);
486 param.bEnabled = enableLowLatency ? OMX_TRUE : OMX_FALSE;
487 if (!SetParameter(OMX_IndexParamLowLatency, param)) {
488 HLOGW("set low latency failed");
489 return AVCS_ERR_UNKNOWN;
490 }
491 HLOGI("set low latency %s", enableLowLatency ? "enable" : "disable");
492 return AVCS_ERR_OK;
493 }
494
GetPixelFmtFromUser(const Format & format)495 bool HCodec::GetPixelFmtFromUser(const Format &format)
496 {
497 optional<PixelFmt> fmt;
498 VideoPixelFormat innerFmt;
499 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, *(int *)&innerFmt) &&
500 innerFmt != VideoPixelFormat::SURFACE_FORMAT) {
501 fmt = TypeConverter::InnerFmtToFmt(innerFmt);
502 } else {
503 HLOGI("user don't set VideoPixelFormat, use default");
504 for (int32_t f : caps_.port.video.supportPixFmts) {
505 fmt = TypeConverter::GraphicFmtToFmt(static_cast<GraphicPixelFormat>(f));
506 if (fmt.has_value()) {
507 break;
508 }
509 }
510 }
511 if (!fmt) {
512 HLOGE("pixel format unspecified");
513 return false;
514 }
515 configuredFmt_ = fmt.value();
516 HLOGI("configured pixel format is %s", configuredFmt_.strFmt.c_str());
517 return true;
518 }
519
GetFrameRateFromUser(const Format & format)520 std::optional<double> HCodec::GetFrameRateFromUser(const Format &format)
521 {
522 double frameRateDouble;
523 if (format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateDouble) && frameRateDouble > 0) {
524 LOGD("user set frame rate %.2f", frameRateDouble);
525 return frameRateDouble;
526 }
527 int frameRateInt;
528 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateInt) && frameRateInt > 0) {
529 LOGD("user set frame rate %d", frameRateInt);
530 return static_cast<double>(frameRateInt);
531 }
532 return nullopt;
533 }
534
CheckBufPixFmt(const sptr<SurfaceBuffer> & buffer)535 bool HCodec::CheckBufPixFmt(const sptr<SurfaceBuffer>& buffer)
536 {
537 int32_t dispFmt = buffer->GetFormat();
538 const std::vector<int32_t>& supportFmts = caps_.port.video.supportPixFmts;
539 if (std::find(supportFmts.begin(), supportFmts.end(), dispFmt) == supportFmts.end()) {
540 LOGE("unsupported buffer pixel format %d", dispFmt);
541 callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR);
542 return false;
543 }
544 return true;
545 }
546
SetVideoPortInfo(OMX_DIRTYPE portIndex,const PortInfo & info)547 int32_t HCodec::SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info)
548 {
549 if (info.pixelFmt.has_value()) {
550 CodecVideoPortFormatParam param;
551 InitOMXParamExt(param);
552 param.portIndex = portIndex;
553 param.codecCompressFormat = info.codingType;
554 param.codecColorFormat = info.pixelFmt->graphicFmt;
555 param.framerate = info.frameRate * FRAME_RATE_COEFFICIENT;
556 if (!SetParameter(OMX_IndexCodecVideoPortFormat, param)) {
557 HLOGE("set port format failed");
558 return AVCS_ERR_UNKNOWN;
559 }
560 }
561 {
562 OMX_PARAM_PORTDEFINITIONTYPE def;
563 InitOMXParam(def);
564 def.nPortIndex = portIndex;
565 if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
566 HLOGE("get port definition failed");
567 return AVCS_ERR_UNKNOWN;
568 }
569 def.format.video.nFrameWidth = info.width;
570 def.format.video.nFrameHeight = info.height;
571 def.format.video.eCompressionFormat = info.codingType;
572 // we dont set eColorFormat here because it has been set by CodecVideoPortFormatParam
573 def.format.video.xFramerate = info.frameRate * FRAME_RATE_COEFFICIENT;
574 if (portIndex == OMX_DirInput && info.inputBufSize.has_value()) {
575 def.nBufferSize = info.inputBufSize.value();
576 }
577 if (!SetParameter(OMX_IndexParamPortDefinition, def)) {
578 HLOGE("set port definition failed");
579 return AVCS_ERR_UNKNOWN;
580 }
581 if (portIndex == OMX_DirOutput) {
582 if (outputFormat_ == nullptr) {
583 outputFormat_ = make_shared<Format>();
584 }
585 outputFormat_->PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, info.frameRate);
586 }
587 }
588
589 return (portIndex == OMX_DirInput) ? UpdateInPortFormat() : UpdateOutPortFormat();
590 }
591
PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE & def)592 void HCodec::PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def)
593 {
594 const OMX_VIDEO_PORTDEFINITIONTYPE& video = def.format.video;
595 HLOGI("%s: bufCntAct %u, bufCntMin %u bufSize %u, %u x %u @ %u(%.2f)",
596 (def.nPortIndex == OMX_DirInput) ? "INPUT" : "OUTPUT",
597 def.nBufferCountActual, def.nBufferCountMin, def.nBufferSize, video.nFrameWidth, video.nFrameHeight,
598 video.xFramerate, video.xFramerate / FRAME_RATE_COEFFICIENT);
599 }
600
GetPortDefinition(OMX_DIRTYPE portIndex,OMX_PARAM_PORTDEFINITIONTYPE & def)601 int32_t HCodec::GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def)
602 {
603 InitOMXParam(def);
604 def.nPortIndex = portIndex;
605 if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
606 HLOGE("get %s port definition failed", (portIndex == OMX_DirInput ? "input" : "output"));
607 return AVCS_ERR_INVALID_VAL;
608 }
609 if (def.nBufferSize == 0 || def.nBufferSize > MAX_HCODEC_BUFFER_SIZE) {
610 HLOGE("invalid nBufferSize %u", def.nBufferSize);
611 return AVCS_ERR_INVALID_VAL;
612 }
613 return AVCS_ERR_OK;
614 }
615
AllocateAvLinearBuffers(OMX_DIRTYPE portIndex)616 int32_t HCodec::AllocateAvLinearBuffers(OMX_DIRTYPE portIndex)
617 {
618 SCOPED_TRACE();
619 OMX_PARAM_PORTDEFINITIONTYPE def;
620 int32_t ret = GetPortDefinition(portIndex, def);
621 if (ret != AVCS_ERR_OK) {
622 return ret;
623 }
624
625 SupportBufferType type;
626 InitOMXParamExt(type);
627 type.portIndex = portIndex;
628 if (GetParameter(OMX_IndexParamSupportBufferType, type) && (type.bufferTypes & CODEC_BUFFER_TYPE_DMA_MEM_FD)) {
629 HLOGI("allocate hardware buffer");
630 return AllocateAvHardwareBuffers(portIndex, def);
631 } else {
632 HLOGI("allocate shared buffer");
633 return AllocateAvSharedBuffers(portIndex, def);
634 }
635 }
636
AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex,const OMX_PARAM_PORTDEFINITIONTYPE & def)637 int32_t HCodec::AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def)
638 {
639 SCOPED_TRACE();
640 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
641 pool.clear();
642 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) {
643 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
644 omxBuffer->size = sizeof(OmxCodecBuffer);
645 omxBuffer->version.version.majorVersion = 1;
646 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DMA_MEM_FD;
647 omxBuffer->fd = -1;
648 omxBuffer->allocLen = def.nBufferSize;
649 omxBuffer->fenceFd = -1;
650 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
651 int32_t ret = compNode_->AllocateBuffer(portIndex, *omxBuffer, *outBuffer);
652 if (ret != HDF_SUCCESS) {
653 HLOGE("Failed to AllocateBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output"));
654 return AVCS_ERR_INVALID_VAL;
655 }
656 MemoryFlag memFlag = MEMORY_READ_WRITE;
657 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateHardwareAllocator(
658 outBuffer->fd, static_cast<int32_t>(def.nBufferSize), memFlag, isSecure_);
659 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateHardwareAllocator failed");
660
661 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(
662 avAllocator, static_cast<int32_t>(def.nBufferSize));
663 if (avBuffer == nullptr || avBuffer->memory_ == nullptr ||
664 avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) {
665 HLOGE("CreateAVBuffer failed");
666 return AVCS_ERR_NO_MEMORY;
667 }
668 SetCallerToBuffer(outBuffer->fd, def.format.video.nFrameWidth, def.format.video.nFrameHeight);
669 BufferInfo bufInfo((portIndex == OMX_DirInput), BufferOwner::OWNED_BY_US, record_);
670 bufInfo.surfaceBuffer = nullptr;
671 bufInfo.avBuffer = avBuffer;
672 bufInfo.omxBuffer = outBuffer;
673 bufInfo.bufferId = outBuffer->bufferId;
674 bufInfo.CleanUpUnusedInfo();
675 pool.push_back(bufInfo);
676 }
677 return AVCS_ERR_OK;
678 }
679
680 // LCOV_EXCL_START
AllocateAvSharedBuffers(OMX_DIRTYPE portIndex,const OMX_PARAM_PORTDEFINITIONTYPE & def)681 int32_t HCodec::AllocateAvSharedBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def)
682 {
683 SCOPED_TRACE();
684 MemoryFlag memFlag = MEMORY_READ_WRITE;
685 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSharedAllocator(memFlag);
686 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSharedAllocator failed");
687
688 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
689 pool.clear();
690 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) {
691 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator,
692 static_cast<int32_t>(def.nBufferSize));
693 if (avBuffer == nullptr || avBuffer->memory_ == nullptr ||
694 avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) {
695 HLOGE("CreateAVBuffer failed");
696 return AVCS_ERR_NO_MEMORY;
697 }
698 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
699 omxBuffer->size = sizeof(OmxCodecBuffer);
700 omxBuffer->version.version.majorVersion = 1;
701 omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
702 omxBuffer->fd = avBuffer->memory_->GetFileDescriptor();
703 omxBuffer->allocLen = def.nBufferSize;
704 omxBuffer->fenceFd = -1;
705 omxBuffer->type = (portIndex == OMX_DirInput) ? READ_ONLY_TYPE : READ_WRITE_TYPE;
706 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
707 int32_t ret = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer);
708 if (ret != HDF_SUCCESS) {
709 HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output"));
710 return AVCS_ERR_INVALID_VAL;
711 }
712 BufferInfo bufInfo((portIndex == OMX_DirInput), BufferOwner::OWNED_BY_US, record_);
713 bufInfo.surfaceBuffer = nullptr;
714 bufInfo.avBuffer = avBuffer;
715 bufInfo.omxBuffer = outBuffer;
716 bufInfo.bufferId = outBuffer->bufferId;
717 pool.push_back(bufInfo);
718 }
719 return AVCS_ERR_OK;
720 }
721 // LCOV_EXCL_STOP
722
AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex)723 int32_t HCodec::AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex)
724 {
725 SCOPED_TRACE();
726 OMX_PARAM_PORTDEFINITIONTYPE def;
727 int32_t ret = GetPortDefinition(portIndex, def);
728 if (ret != AVCS_ERR_OK) {
729 return ret;
730 }
731 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSurfaceAllocator(requestCfg_);
732 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSurfaceAllocator failed");
733 bool needDealWithCache = (requestCfg_.usage & BUFFER_USAGE_MEM_MMZ_CACHE);
734
735 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
736 pool.clear();
737 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) {
738 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator,
739 static_cast<int32_t>(def.nBufferSize));
740 if (avBuffer == nullptr || avBuffer->memory_ == nullptr) {
741 HLOGE("CreateAVBuffer failed");
742 return AVCS_ERR_NO_MEMORY;
743 }
744 sptr<SurfaceBuffer> surfaceBuffer = avBuffer->memory_->GetSurfaceBuffer();
745 IF_TRUE_RETURN_VAL_WITH_MSG(surfaceBuffer == nullptr, AVCS_ERR_INVALID_VAL, "avbuffer has null surfacebuffer");
746 shared_ptr<OmxCodecBuffer> omxBuffer = isEncoder_ ?
747 DynamicSurfaceBufferToOmxBuffer() : SurfaceBufferToOmxBuffer(surfaceBuffer);
748 IF_TRUE_RETURN_VAL(omxBuffer == nullptr, AVCS_ERR_INVALID_VAL);
749 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
750 int32_t hdiRet = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer);
751 if (hdiRet != HDF_SUCCESS) {
752 HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output"));
753 return AVCS_ERR_INVALID_VAL;
754 }
755 SetCallerToBuffer(surfaceBuffer->GetFileDescriptor(),
756 static_cast<uint32_t>(surfaceBuffer->GetWidth()),
757 static_cast<uint32_t>(surfaceBuffer->GetHeight()));
758 BufferInfo bufInfo((portIndex == OMX_DirInput), BufferOwner::OWNED_BY_US, record_);
759 bufInfo.surfaceBuffer = surfaceBuffer;
760 bufInfo.avBuffer = avBuffer;
761 bufInfo.omxBuffer = outBuffer;
762 bufInfo.bufferId = outBuffer->bufferId;
763 bufInfo.needDealWithCache = needDealWithCache;
764 pool.push_back(bufInfo);
765 }
766
767 return AVCS_ERR_OK;
768 }
769
SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer> & surfaceBuffer)770 shared_ptr<OmxCodecBuffer> HCodec::SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer>& surfaceBuffer)
771 {
772 BufferHandle* bufferHandle = surfaceBuffer->GetBufferHandle();
773 IF_TRUE_RETURN_VAL_WITH_MSG(bufferHandle == nullptr, nullptr, "surfacebuffer has null bufferhandle");
774 auto omxBuffer = std::make_shared<OmxCodecBuffer>();
775 omxBuffer->size = sizeof(OmxCodecBuffer);
776 omxBuffer->version.version.majorVersion = 1;
777 omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE;
778 omxBuffer->bufferhandle = new NativeBuffer(bufferHandle);
779 omxBuffer->fd = -1;
780 omxBuffer->allocLen = surfaceBuffer->GetSize();
781 omxBuffer->fenceFd = -1;
782 return omxBuffer;
783 }
784
DynamicSurfaceBufferToOmxBuffer()785 shared_ptr<OmxCodecBuffer> HCodec::DynamicSurfaceBufferToOmxBuffer()
786 {
787 auto omxBuffer = make_shared<OmxCodecBuffer>();
788 omxBuffer->size = sizeof(OmxCodecBuffer);
789 omxBuffer->version.version.majorVersion = 1;
790 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
791 omxBuffer->fd = -1;
792 omxBuffer->allocLen = 0;
793 omxBuffer->fenceFd = -1;
794 return omxBuffer;
795 }
796
ToString(BufferOwner owner)797 const char* HCodec::ToString(BufferOwner owner)
798 {
799 switch (owner) {
800 case BufferOwner::OWNED_BY_US:
801 return "us";
802 case BufferOwner::OWNED_BY_USER:
803 return "user";
804 case BufferOwner::OWNED_BY_OMX:
805 return "omx";
806 case BufferOwner::OWNED_BY_SURFACE:
807 return "surface";
808 default:
809 return "";
810 }
811 }
812
CleanUpUnusedInfo()813 void HCodec::BufferInfo::CleanUpUnusedInfo()
814 {
815 if (omxBuffer == nullptr || omxBuffer->fd < 0) {
816 return;
817 }
818 if (omxBuffer->fd == 0) {
819 LOGW("fd of omxbuffer should never be 0");
820 }
821 close(omxBuffer->fd);
822 omxBuffer->fd = -1;
823 }
824
BeginCpuAccess()825 void HCodec::BufferInfo::BeginCpuAccess()
826 {
827 if (surfaceBuffer && needDealWithCache) {
828 GSError err = surfaceBuffer->InvalidateCache();
829 if (err != GSERROR_OK) {
830 LOGW("InvalidateCache failed, GSError=%d", err);
831 }
832 }
833 }
834
EndCpuAccess()835 void HCodec::BufferInfo::EndCpuAccess()
836 {
837 if (surfaceBuffer && needDealWithCache) {
838 GSError err = surfaceBuffer->Map();
839 if (err != GSERROR_OK) {
840 LOGW("Map failed, GSError=%d", err);
841 return;
842 }
843 err = surfaceBuffer->FlushCache();
844 if (err != GSERROR_OK) {
845 LOGW("FlushCache failed, GSError=%d", err);
846 }
847 }
848 }
849
FindBufferInfoByID(OMX_DIRTYPE portIndex,uint32_t bufferId)850 HCodec::BufferInfo* HCodec::FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId)
851 {
852 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
853 for (BufferInfo &info : pool) {
854 if (info.bufferId == bufferId) {
855 return &info;
856 }
857 }
858 HLOGE("unknown buffer id %u", bufferId);
859 return nullptr;
860 }
861
FindBufferIndexByID(OMX_DIRTYPE portIndex,uint32_t bufferId)862 optional<size_t> HCodec::FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId)
863 {
864 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
865 for (size_t i = 0; i < pool.size(); i++) {
866 if (pool[i].bufferId == bufferId) {
867 return i;
868 }
869 }
870 HLOGE("unknown buffer id %u", bufferId);
871 return nullopt;
872 }
873
UserFlagToOmxFlag(AVCodecBufferFlag userFlag)874 uint32_t HCodec::UserFlagToOmxFlag(AVCodecBufferFlag userFlag)
875 {
876 uint32_t flags = 0;
877 if (userFlag & AVCODEC_BUFFER_FLAG_EOS) {
878 flags |= OMX_BUFFERFLAG_EOS;
879 HLOGI("got input eos");
880 }
881 if (userFlag & AVCODEC_BUFFER_FLAG_SYNC_FRAME) {
882 flags |= OMX_BUFFERFLAG_SYNCFRAME;
883 }
884 if (userFlag & AVCODEC_BUFFER_FLAG_CODEC_DATA) {
885 flags |= OMX_BUFFERFLAG_CODECCONFIG;
886 }
887 if (isLpp_ && (userFlag & AVCODEC_BUFFER_FLAG_MUL_FRAME)) {
888 flags |= OMX_BUFFERFLAG_MULTI_FRAME;
889 }
890 return flags;
891 }
892
OmxFlagToUserFlag(uint32_t omxFlag)893 AVCodecBufferFlag HCodec::OmxFlagToUserFlag(uint32_t omxFlag)
894 {
895 uint32_t flags = 0;
896 if (omxFlag & OMX_BUFFERFLAG_EOS) {
897 flags |= AVCODEC_BUFFER_FLAG_EOS;
898 HLOGI("got output eos");
899 }
900 if (omxFlag & OMX_BUFFERFLAG_SYNCFRAME) {
901 flags |= AVCODEC_BUFFER_FLAG_SYNC_FRAME;
902 }
903 if (omxFlag & OMX_BUFFERFLAG_CODECCONFIG) {
904 flags |= AVCODEC_BUFFER_FLAG_CODEC_DATA;
905 }
906 return static_cast<AVCodecBufferFlag>(flags);
907 }
908
WaitFence(const sptr<SyncFence> & fence)909 bool HCodec::WaitFence(const sptr<SyncFence>& fence)
910 {
911 if (fence == nullptr || !fence->IsValid()) {
912 return true;
913 }
914 SCOPED_TRACE();
915 uint64_t& waitFenceCostUs = isEncoder_ ?
916 record_[OMX_DirInput].waitFenceCostUsInterval_ : record_[OMX_DirOutput].waitFenceCostUsInterval_;
917 auto before = chrono::steady_clock::now();
918 int waitRes = fence->Wait(WAIT_FENCE_MS);
919 if (waitRes == 0) {
920 uint64_t costUs = static_cast<uint64_t>(
921 chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - before).count());
922 waitFenceCostUs += costUs;
923 return true;
924 } else {
925 HLOGE("wait fence time out, cost more than %u ms", WAIT_FENCE_MS);
926 waitFenceCostUs += WAIT_FENCE_MS * TIME_RATIO_S_TO_MS;
927 return false;
928 }
929 }
930
NotifyUserToFillThisInBuffer(BufferInfo & info)931 void HCodec::NotifyUserToFillThisInBuffer(BufferInfo &info)
932 {
933 SCOPED_TRACE_FMT("id: %u", info.bufferId);
934 callback_->OnInputBufferAvailable(info.bufferId, info.avBuffer);
935 ChangeOwner(info, BufferOwner::OWNED_BY_USER);
936 }
937
OnQueueInputBuffer(const MsgInfo & msg,BufferOperationMode mode)938 void HCodec::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode)
939 {
940 uint32_t bufferId = 0;
941 (void)msg.param->GetValue(BUFFER_ID, bufferId);
942 SCOPED_TRACE_FMT("id: %u", bufferId);
943 BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId);
944 if (bufferInfo == nullptr) {
945 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
946 return;
947 }
948 if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) {
949 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner));
950 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
951 return;
952 }
953 bufferInfo->omxBuffer->filledLen = static_cast<uint32_t>
954 (bufferInfo->avBuffer->memory_->GetSize());
955 bufferInfo->omxBuffer->offset = static_cast<uint32_t>(bufferInfo->avBuffer->memory_->GetOffset());
956 bufferInfo->omxBuffer->pts = bufferInfo->avBuffer->pts_;
957 bufferInfo->omxBuffer->flag = UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_));
958 ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US);
959 ReplyErrorCode(msg.id, AVCS_ERR_OK);
960 int32_t ret = OnQueueInputBuffer(mode, bufferInfo);
961 if (ret != AVCS_ERR_OK) {
962 SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
963 }
964 }
965
OnQueueInputBuffer(BufferOperationMode mode,BufferInfo * info)966 int32_t HCodec::OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info)
967 {
968 switch (mode) {
969 case KEEP_BUFFER: {
970 return AVCS_ERR_OK;
971 }
972 case RESUBMIT_BUFFER: {
973 if (inputPortEos_) {
974 HLOGI("input already eos, keep this buffer");
975 return AVCS_ERR_OK;
976 }
977 bool eos = (info->omxBuffer->flag & OMX_BUFFERFLAG_EOS);
978 if (!eos && info->omxBuffer->filledLen == 0) {
979 HLOGI("this is not a eos buffer but not filled, ask user to re-fill it");
980 NotifyUserToFillThisInBuffer(*info);
981 return AVCS_ERR_OK;
982 }
983 if (eos) {
984 inputPortEos_ = true;
985 }
986 return InBufUsToOmx(*info);
987 }
988 default: {
989 HLOGE("SHOULD NEVER BE HERE");
990 return AVCS_ERR_UNKNOWN;
991 }
992 }
993 }
994
WrapSurfaceBufferToSlot(BufferInfo & info,const sptr<SurfaceBuffer> & surfaceBuffer,int64_t pts,uint32_t flag)995 void HCodec::WrapSurfaceBufferToSlot(BufferInfo &info,
996 const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts, uint32_t flag)
997 {
998 info.surfaceBuffer = surfaceBuffer;
999 info.omxBuffer->bufferhandle = new NativeBuffer(surfaceBuffer->GetBufferHandle());
1000 info.omxBuffer->filledLen = surfaceBuffer->GetSize();
1001 info.omxBuffer->fd = -1;
1002 info.omxBuffer->fenceFd = -1;
1003 info.omxBuffer->pts = pts;
1004 info.omxBuffer->flag = flag;
1005 }
1006
OnSignalEndOfInputStream(const MsgInfo & msg)1007 void HCodec::OnSignalEndOfInputStream(const MsgInfo &msg)
1008 {
1009 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT);
1010 }
1011
InBufUsToOmx(BufferInfo & info)1012 int32_t HCodec::InBufUsToOmx(BufferInfo& info)
1013 {
1014 SCOPED_TRACE_FMT("id: %u, pts: %" PRId64, info.bufferId, info.omxBuffer->pts);
1015 if (!gotFirstInput_) {
1016 HLOGI("got first input, pts = %" PRId64 ", len = %u, flags = 0x%x",
1017 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag);
1018 gotFirstInput_ = true;
1019 }
1020 #ifdef BUILD_ENG_VERSION
1021 info.Dump(compUniqueStr_, record_[OMX_DirInput].frameCntTotal_, dumpMode_, isEncoder_);
1022 #endif
1023 info.EndCpuAccess();
1024 int32_t ret = compNode_->EmptyThisBuffer(*(info.omxBuffer));
1025 if (ret != HDF_SUCCESS) {
1026 HLOGE("EmptyThisBuffer failed");
1027 return AVCS_ERR_UNKNOWN;
1028 }
1029 ChangeOwner(info, BufferOwner::OWNED_BY_OMX);
1030 return AVCS_ERR_OK;
1031 }
1032
NotifyOmxToFillThisOutBuffer(BufferInfo & info)1033 int32_t HCodec::NotifyOmxToFillThisOutBuffer(BufferInfo& info)
1034 {
1035 SCOPED_TRACE_FMT("id: %u", info.bufferId);
1036 info.omxBuffer->flag = 0;
1037 int32_t ret = compNode_->FillThisBuffer(*(info.omxBuffer));
1038 if (ret != HDF_SUCCESS) {
1039 HLOGE("outBufId = %u failed", info.bufferId);
1040 return AVCS_ERR_UNKNOWN;
1041 }
1042 ChangeOwner(info, BufferOwner::OWNED_BY_OMX);
1043 return AVCS_ERR_OK;
1044 }
1045
OnOMXFillBufferDone(const OmxCodecBuffer & omxBuffer,BufferOperationMode mode)1046 void HCodec::OnOMXFillBufferDone(const OmxCodecBuffer& omxBuffer, BufferOperationMode mode)
1047 {
1048 SCOPED_TRACE_FMT("id: %u", omxBuffer.bufferId);
1049 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, omxBuffer.bufferId);
1050 if (!idx.has_value()) {
1051 return;
1052 }
1053 BufferInfo& info = outputBufferPool_[idx.value()];
1054 if (info.owner != BufferOwner::OWNED_BY_OMX) {
1055 HLOGE("wrong ownership: buffer id=%d, owner=%s", info.bufferId, ToString(info.owner));
1056 return;
1057 }
1058 info.omxBuffer->offset = omxBuffer.offset;
1059 info.omxBuffer->filledLen = omxBuffer.filledLen;
1060 info.omxBuffer->pts = omxBuffer.pts;
1061 info.omxBuffer->flag = omxBuffer.flag;
1062 info.omxBuffer->alongParam = std::move(omxBuffer.alongParam);
1063 ChangeOwner(info, BufferOwner::OWNED_BY_US);
1064 OnOMXFillBufferDone(mode, info, idx.value());
1065 }
1066
OnOMXFillBufferDone(BufferOperationMode mode,BufferInfo & info,size_t bufferIdx)1067 void HCodec::OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx)
1068 {
1069 switch (mode) {
1070 case KEEP_BUFFER:
1071 return;
1072 case RESUBMIT_BUFFER: {
1073 if (outputPortEos_) {
1074 HLOGD("output eos, keep this buffer");
1075 return;
1076 }
1077 bool eos = (info.omxBuffer->flag & OMX_BUFFERFLAG_EOS);
1078 if (!eos && info.omxBuffer->filledLen == 0) {
1079 HLOGW("it's not a eos buffer but not filled, ask omx to re-fill it");
1080 NotifyOmxToFillThisOutBuffer(info);
1081 return;
1082 }
1083 #ifdef USE_VIDEO_PROCESSING_ENGINE
1084 if (!isEncoder_ && isVrrInitialized_) {
1085 (void)VrrPrediction(info);
1086 }
1087 #endif
1088 OutBufUsToUser(info);
1089 if (eos) {
1090 outputPortEos_ = true;
1091 }
1092 return;
1093 }
1094 case FREE_BUFFER:
1095 EraseBufferFromPool(OMX_DirOutput, bufferIdx);
1096 return;
1097 default:
1098 HLOGE("SHOULD NEVER BE HERE");
1099 return;
1100 }
1101 }
1102
OutBufUsToUser(BufferInfo & info)1103 void HCodec::OutBufUsToUser(BufferInfo &info)
1104 {
1105 SCOPED_TRACE_FMT("id: %u, pts: %" PRId64, info.bufferId, info.omxBuffer->pts);
1106 if (!gotFirstOutput_) {
1107 HLOGI("got first output, pts = %" PRId64 ", len = %u, flags = 0x%x",
1108 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag);
1109 gotFirstOutput_ = true;
1110 }
1111 #ifndef AV_CODEC_HCODEC_ENABLE_QOS_THE_WHOLE_TIME
1112 if (!isEncoder_ || codecRate_ < HIGH_FPS) {
1113 SetThreadInteractiveQos(false);
1114 }
1115 #endif
1116 info.BeginCpuAccess();
1117 #ifdef BUILD_ENG_VERSION
1118 info.Dump(compUniqueStr_, record_[OMX_DirOutput].frameCntTotal_, dumpMode_, isEncoder_);
1119 #endif
1120 shared_ptr<OmxCodecBuffer> omxBuffer = info.omxBuffer;
1121 info.avBuffer->pts_ = omxBuffer->pts;
1122 info.avBuffer->flag_ = OmxFlagToUserFlag(omxBuffer->flag);
1123 if (info.avBuffer->memory_) {
1124 info.avBuffer->memory_->SetSize(static_cast<int32_t>(omxBuffer->filledLen));
1125 info.avBuffer->memory_->SetOffset(static_cast<int32_t>(omxBuffer->offset));
1126 }
1127 BeforeCbOutToUser(info);
1128 callback_->OnOutputBufferAvailable(info.bufferId, info.avBuffer);
1129 ChangeOwner(info, BufferOwner::OWNED_BY_USER);
1130 }
1131
OnReleaseOutputBuffer(const MsgInfo & msg,BufferOperationMode mode)1132 void HCodec::OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode)
1133 {
1134 uint32_t bufferId = 0;
1135 (void)msg.param->GetValue(BUFFER_ID, bufferId);
1136 SCOPED_TRACE_FMT("id: %u", bufferId);
1137 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId);
1138 if (!idx.has_value()) {
1139 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1140 return;
1141 }
1142 BufferInfo& info = outputBufferPool_[idx.value()];
1143 if (info.owner != BufferOwner::OWNED_BY_USER) {
1144 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info.owner));
1145 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1146 return;
1147 }
1148 OnReleaseOutputBuffer(info);
1149 ChangeOwner(info, BufferOwner::OWNED_BY_US);
1150 ReplyErrorCode(msg.id, AVCS_ERR_OK);
1151 OnReleaseOutputBuffer(bufferId, mode);
1152 }
1153
OnReleaseOutputBuffer(uint32_t bufferId,BufferOperationMode mode)1154 void HCodec::OnReleaseOutputBuffer(uint32_t bufferId, BufferOperationMode mode)
1155 {
1156 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId);
1157 if (!idx.has_value()) {
1158 return;
1159 }
1160 BufferInfo& info = outputBufferPool_[idx.value()];
1161 switch (mode) {
1162 case KEEP_BUFFER: {
1163 return;
1164 }
1165 case RESUBMIT_BUFFER: {
1166 if (outputPortEos_) {
1167 HLOGD("output eos, keep this buffer");
1168 return;
1169 }
1170 int32_t ret = NotifyOmxToFillThisOutBuffer(info);
1171 if (ret != AVCS_ERR_OK) {
1172 SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
1173 }
1174 return;
1175 }
1176 case FREE_BUFFER: {
1177 EraseBufferFromPool(OMX_DirOutput, idx.value());
1178 return;
1179 }
1180 default: {
1181 HLOGE("SHOULD NEVER BE HERE");
1182 return;
1183 }
1184 }
1185 }
1186
OnRenderOutputBuffer(const MsgInfo & msg,BufferOperationMode mode)1187 void HCodec::OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode)
1188 {
1189 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT);
1190 }
1191
ReclaimBuffer(OMX_DIRTYPE portIndex,BufferOwner owner,bool erase)1192 void HCodec::ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase)
1193 {
1194 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
1195 for (size_t i = pool.size(); i > 0;) {
1196 i--;
1197 BufferInfo& info = pool[i];
1198 if (info.owner == owner) {
1199 ChangeOwner(info, BufferOwner::OWNED_BY_US);
1200 if (erase) {
1201 EraseBufferFromPool(portIndex, i);
1202 }
1203 }
1204 }
1205 }
1206
IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex)1207 bool HCodec::IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex)
1208 {
1209 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
1210 for (const BufferInfo& info : pool) {
1211 if (info.owner != BufferOwner::OWNED_BY_US &&
1212 info.owner != BufferOwner::OWNED_BY_SURFACE) {
1213 return false;
1214 }
1215 }
1216 return true;
1217 }
1218
IsAllBufferOwnedByUsOrSurface()1219 bool HCodec::IsAllBufferOwnedByUsOrSurface()
1220 {
1221 return IsAllBufferOwnedByUsOrSurface(OMX_DirInput) &&
1222 IsAllBufferOwnedByUsOrSurface(OMX_DirOutput);
1223 }
1224
ClearBufferPool(OMX_DIRTYPE portIndex)1225 void HCodec::ClearBufferPool(OMX_DIRTYPE portIndex)
1226 {
1227 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
1228 for (size_t i = pool.size(); i > 0;) {
1229 i--;
1230 EraseBufferFromPool(portIndex, i);
1231 }
1232 OnClearBufferPool(portIndex);
1233 }
1234
FreeOmxBuffer(OMX_DIRTYPE portIndex,const BufferInfo & info)1235 void HCodec::FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info)
1236 {
1237 if (compNode_ && info.omxBuffer) {
1238 int32_t omxRet = compNode_->FreeBuffer(portIndex, *(info.omxBuffer));
1239 if (omxRet != HDF_SUCCESS) {
1240 HLOGW("notify omx to free buffer failed");
1241 }
1242 }
1243 }
1244
EraseOutBuffersOwnedByUsOrSurface()1245 void HCodec::EraseOutBuffersOwnedByUsOrSurface()
1246 {
1247 // traverse index in reverse order because we need to erase index from vector
1248 for (size_t i = outputBufferPool_.size(); i > 0;) {
1249 i--;
1250 const BufferInfo& info = outputBufferPool_[i];
1251 if (info.owner == BufferOwner::OWNED_BY_US || info.owner == BufferOwner::OWNED_BY_SURFACE) {
1252 EraseBufferFromPool(OMX_DirOutput, i);
1253 }
1254 }
1255 }
1256
OnSetOutputSurface(const MsgInfo & msg,BufferOperationMode mode)1257 void HCodec::OnSetOutputSurface(const MsgInfo &msg, BufferOperationMode mode)
1258 {
1259 (void)msg;
1260 (void)mode;
1261 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT);
1262 }
1263
ForceShutdown(int32_t generation,bool isNeedNotifyCaller)1264 int32_t HCodec::ForceShutdown(int32_t generation, bool isNeedNotifyCaller)
1265 {
1266 if (generation != stateGeneration_) {
1267 HLOGE("ignoring stale force shutdown message: #%d (now #%d)",
1268 generation, stateGeneration_);
1269 return AVCS_ERR_OK;
1270 }
1271 HLOGI("force to shutdown");
1272 isShutDownFromRunning_ = true;
1273 notifyCallerAfterShutdownComplete_ = isNeedNotifyCaller;
1274 keepComponentAllocated_ = false;
1275 auto err = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
1276 if (err == HDF_SUCCESS) {
1277 ChangeStateTo(stoppingState_);
1278 }
1279 return AVCS_ERR_OK;
1280 }
1281
SignalError(AVCodecErrorType errorType,int32_t errorCode)1282 void HCodec::SignalError(AVCodecErrorType errorType, int32_t errorCode)
1283 {
1284 HLOGE("fatal error happened: errType=%d, errCode=%d", errorType, errorCode);
1285 hasFatalError_ = true;
1286 callback_->OnError(errorType, errorCode);
1287 }
1288
DoSyncCall(MsgWhat msgType,std::function<void (ParamSP)> oper,uint32_t waitMs)1289 int32_t HCodec::DoSyncCall(MsgWhat msgType, std::function<void(ParamSP)> oper, uint32_t waitMs)
1290 {
1291 ParamSP reply;
1292 return DoSyncCallAndGetReply(msgType, oper, reply, waitMs);
1293 }
1294
DoSyncCallAndGetReply(MsgWhat msgType,std::function<void (ParamSP)> oper,ParamSP & reply,uint32_t waitMs)1295 int32_t HCodec::DoSyncCallAndGetReply(MsgWhat msgType, std::function<void(ParamSP)> oper,
1296 ParamSP &reply, uint32_t waitMs)
1297 {
1298 ParamSP msg = make_shared<ParamBundle>();
1299 IF_TRUE_RETURN_VAL_WITH_MSG(msg == nullptr, AVCS_ERR_NO_MEMORY, "out of memory");
1300 if (oper) {
1301 oper(msg);
1302 }
1303 bool ret = MsgHandleLoop::SendSyncMsg(msgType, msg, reply, waitMs);
1304 if (!ret) {
1305 HLOGE("wait msg %d(%s) time out", msgType, ToString(msgType));
1306 return AVCS_ERR_UNKNOWN;
1307 }
1308 int32_t err;
1309 IF_TRUE_RETURN_VAL_WITH_MSG(reply == nullptr || !reply->GetValue("err", err),
1310 AVCS_ERR_UNKNOWN, "error code of msg %d not replied", msgType);
1311 return err;
1312 }
1313
DeferMessage(const MsgInfo & info)1314 void HCodec::DeferMessage(const MsgInfo &info)
1315 {
1316 deferredQueue_.push_back(info);
1317 }
1318
ProcessDeferredMessages()1319 void HCodec::ProcessDeferredMessages()
1320 {
1321 std::list<MsgInfo> queue = std::exchange(deferredQueue_, {});
1322 for (const MsgInfo &info : queue) {
1323 StateMachine::OnMsgReceived(info);
1324 }
1325 queue.clear();
1326 }
1327
ReplyToSyncMsgLater(const MsgInfo & msg)1328 void HCodec::ReplyToSyncMsgLater(const MsgInfo& msg)
1329 {
1330 syncMsgToReply_[msg.type].push(std::make_pair(msg.id, msg.param));
1331 }
1332
GetFirstSyncMsgToReply(MsgInfo & msg)1333 bool HCodec::GetFirstSyncMsgToReply(MsgInfo& msg)
1334 {
1335 auto iter = syncMsgToReply_.find(msg.type);
1336 if (iter == syncMsgToReply_.end()) {
1337 return false;
1338 }
1339 std::tie(msg.id, msg.param) = iter->second.front();
1340 iter->second.pop();
1341 return true;
1342 }
1343
ReplyErrorCode(MsgId id,int32_t err)1344 void HCodec::ReplyErrorCode(MsgId id, int32_t err)
1345 {
1346 if (id == ASYNC_MSG_ID) {
1347 return;
1348 }
1349 ParamSP reply = make_shared<ParamBundle>();
1350 reply->SetValue("err", err);
1351 PostReply(id, reply);
1352 }
1353
ChangeOmxToTargetState(CodecStateType & state,CodecStateType targetState)1354 void HCodec::ChangeOmxToTargetState(CodecStateType &state, CodecStateType targetState)
1355 {
1356 int32_t ret = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, targetState, {});
1357 if (ret != HDF_SUCCESS) {
1358 HLOGE("failed to change omx state, ret=%d", ret);
1359 return;
1360 }
1361 if (targetState == CODEC_STATE_LOADED) {
1362 for (const BufferInfo& info : inputBufferPool_) {
1363 FreeOmxBuffer(OMX_DirInput, info);
1364 }
1365 for (const BufferInfo& info : outputBufferPool_) {
1366 FreeOmxBuffer(OMX_DirOutput, info);
1367 }
1368 }
1369 int tryCnt = 0;
1370 do {
1371 if (tryCnt++ > 10) { // try up to 10 times
1372 HLOGE("failed to change to state(%d), abort", targetState);
1373 state = CODEC_STATE_INVALID;
1374 break;
1375 }
1376 this_thread::sleep_for(10ms); // wait 10ms
1377 ret = compNode_->GetState(state);
1378 if (ret != HDF_SUCCESS) {
1379 HLOGE("failed to get omx state, ret=%d", ret);
1380 }
1381 } while (ret == HDF_SUCCESS && state != targetState && state != CODEC_STATE_INVALID);
1382 }
1383
RollOmxBackToLoaded()1384 bool HCodec::RollOmxBackToLoaded()
1385 {
1386 CodecStateType state;
1387 int32_t ret = compNode_->GetState(state);
1388 if (ret != HDF_SUCCESS) {
1389 HLOGE("failed to get omx node status(ret=%d), can not perform state rollback", ret);
1390 return false;
1391 }
1392 HLOGI("current omx state (%d)", state);
1393 switch (state) {
1394 case CODEC_STATE_EXECUTING: {
1395 ChangeOmxToTargetState(state, CODEC_STATE_IDLE);
1396 [[fallthrough]];
1397 }
1398 case CODEC_STATE_IDLE: {
1399 ChangeOmxToTargetState(state, CODEC_STATE_LOADED);
1400 [[fallthrough]];
1401 }
1402 case CODEC_STATE_LOADED:
1403 case CODEC_STATE_INVALID: {
1404 return true;
1405 }
1406 default: {
1407 HLOGE("invalid omx state: %d", state);
1408 return false;
1409 }
1410 }
1411 }
1412
CleanUpOmxNode()1413 void HCodec::CleanUpOmxNode()
1414 {
1415 if (compNode_ == nullptr) {
1416 return;
1417 }
1418 RollOmxBackToLoaded();
1419 }
1420
OnAllocateComponent()1421 int32_t HCodec::OnAllocateComponent()
1422 {
1423 HitraceMeterFmtScoped trace(HITRACE_TAG_ZMEDIA, "hcodec %s %s", __func__, caps_.compName.c_str());
1424 compMgr_ = GetManager(false,
1425 HCodecList::FindFeature(caps_.port.video.features, VIDEO_FEATURE_PASS_THROUGH).support,
1426 isSecure_);
1427 if (compMgr_ == nullptr) {
1428 HLOGE("GetCodecComponentManager failed");
1429 return AVCS_ERR_UNKNOWN;
1430 }
1431 compCb_ = new HdiCallback(m_token);
1432 int32_t ret = compMgr_->CreateComponent(compNode_, componentId_, caps_.compName, 0, compCb_);
1433 if (ret != HDF_SUCCESS || compNode_ == nullptr) {
1434 compCb_ = nullptr;
1435 compMgr_ = nullptr;
1436 HLOGE("CreateComponent failed, ret=%d", ret);
1437 PrintAllCaller();
1438 return AVCS_ERR_UNKNOWN;
1439 }
1440 compUniqueStr_ = to_string(componentId_) + (isEncoder_ ? "_e" : "_d");
1441 record_[OMX_DirInput].ownerTraceTag_ = { "[" + compUniqueStr_ + "]in_us", "[" + compUniqueStr_ + "]in_user",
1442 "[" + compUniqueStr_ + "]in_omx", "[" + compUniqueStr_ + "]in_surface"};
1443 record_[OMX_DirOutput].ownerTraceTag_ = { "[" + compUniqueStr_ + "]out_us", "[" + compUniqueStr_ + "]out_user",
1444 "[" + compUniqueStr_ + "]out_omx", "[" + compUniqueStr_ + "]out_surface"};
1445 HLOGI("create omx node %s succ", caps_.compName.c_str());
1446 PrintCaller();
1447 return AVCS_ERR_OK;
1448 }
1449
ReleaseComponent()1450 void HCodec::ReleaseComponent()
1451 {
1452 CleanUpOmxNode();
1453 if (compMgr_ != nullptr) {
1454 RemoveCaller();
1455 compMgr_->DestroyComponent(componentId_);
1456 }
1457 compNode_ = nullptr;
1458 compCb_ = nullptr;
1459 compMgr_ = nullptr;
1460 componentId_ = 0;
1461 }
1462
ToString(MsgWhat what)1463 const char* HCodec::ToString(MsgWhat what)
1464 {
1465 static const map<MsgWhat, const char*> m = {
1466 { INIT, "INIT" }, { SET_CALLBACK, "SET_CALLBACK" }, { CONFIGURE, "CONFIGURE" },
1467 { CREATE_INPUT_SURFACE, "CREATE_INPUT_SURFACE" }, { SET_INPUT_SURFACE, "SET_INPUT_SURFACE" },
1468 { SET_OUTPUT_SURFACE, "SET_OUTPUT_SURFACE" }, { START, "START" },
1469 { GET_INPUT_FORMAT, "GET_INPUT_FORMAT" }, { GET_OUTPUT_FORMAT, "GET_OUTPUT_FORMAT" },
1470 { SET_PARAMETERS, "SET_PARAMETERS" }, { REQUEST_IDR_FRAME, "REQUEST_IDR_FRAME" },
1471 { FLUSH, "FLUSH" }, { QUEUE_INPUT_BUFFER, "QUEUE_INPUT_BUFFER" },
1472 { NOTIFY_EOS, "NOTIFY_EOS" }, { RELEASE_OUTPUT_BUFFER, "RELEASE_OUTPUT_BUFFER" },
1473 { RENDER_OUTPUT_BUFFER, "RENDER_OUTPUT_BUFFER" }, { STOP, "STOP" }, { RELEASE, "RELEASE" },
1474 { CODEC_EVENT, "CODEC_EVENT" }, { OMX_EMPTY_BUFFER_DONE, "OMX_EMPTY_BUFFER_DONE" },
1475 { OMX_FILL_BUFFER_DONE, "OMX_FILL_BUFFER_DONE" }, { GET_BUFFER_FROM_SURFACE, "GET_BUFFER_FROM_SURFACE" },
1476 { CHECK_IF_STUCK, "CHECK_IF_STUCK" }, { FORCE_SHUTDOWN, "FORCE_SHUTDOWN" },
1477 };
1478 auto it = m.find(what);
1479 if (it != m.end()) {
1480 return it->second;
1481 }
1482 return "UNKNOWN";
1483 }
1484 } // namespace OHOS::MediaAVCodec