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