• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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