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