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 "hencoder.h"
17da853ecaSopenharmony_ci#include <map>
18da853ecaSopenharmony_ci#include <utility>
19da853ecaSopenharmony_ci#include "utils/hdf_base.h"
20da853ecaSopenharmony_ci#include "OMX_VideoExt.h"
21da853ecaSopenharmony_ci#include "media_description.h"  // foundation/multimedia/av_codec/interfaces/inner_api/native/
22da853ecaSopenharmony_ci#include "type_converter.h"
23da853ecaSopenharmony_ci#include "hcodec_log.h"
24da853ecaSopenharmony_ci#include "hcodec_dfx.h"
25da853ecaSopenharmony_ci#include "v3_0/codec_ext_types.h"
26da853ecaSopenharmony_ci
27da853ecaSopenharmony_cinamespace OHOS::MediaAVCodec {
28da853ecaSopenharmony_ciusing namespace std;
29da853ecaSopenharmony_ci
30da853ecaSopenharmony_ciHEncoder::~HEncoder()
31da853ecaSopenharmony_ci{
32da853ecaSopenharmony_ci    MsgHandleLoop::Stop();
33da853ecaSopenharmony_ci}
34da853ecaSopenharmony_ci
35da853ecaSopenharmony_ciint32_t HEncoder::OnConfigure(const Format &format)
36da853ecaSopenharmony_ci{
37da853ecaSopenharmony_ci    configFormat_ = make_shared<Format>(format);
38da853ecaSopenharmony_ci    int32_t ret = ConfigureBufferType();
39da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
40da853ecaSopenharmony_ci        return ret;
41da853ecaSopenharmony_ci    }
42da853ecaSopenharmony_ci
43da853ecaSopenharmony_ci    optional<double> frameRate = GetFrameRateFromUser(format);
44da853ecaSopenharmony_ci    ret = SetupPort(format, frameRate);
45da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
46da853ecaSopenharmony_ci        return ret;
47da853ecaSopenharmony_ci    }
48da853ecaSopenharmony_ci    ConfigureProtocol(format, frameRate);
49da853ecaSopenharmony_ci
50da853ecaSopenharmony_ci    ret = ConfigureOutputBitrate(format);
51da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
52da853ecaSopenharmony_ci        HLOGW("ConfigureOutputBitrate failed");
53da853ecaSopenharmony_ci    }
54da853ecaSopenharmony_ci    ret = SetColorAspects(format);
55da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
56da853ecaSopenharmony_ci        HLOGW("set color aspect failed");
57da853ecaSopenharmony_ci    }
58da853ecaSopenharmony_ci    (void)SetProcessName();
59da853ecaSopenharmony_ci    (void)SetFrameRateAdaptiveMode(format);
60da853ecaSopenharmony_ci    CheckIfEnableCb(format);
61da853ecaSopenharmony_ci    ret = SetTemperalLayer(format);
62da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
63da853ecaSopenharmony_ci        return ret;
64da853ecaSopenharmony_ci    }
65da853ecaSopenharmony_ci    ret = SetLTRParam(format);
66da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
67da853ecaSopenharmony_ci        return ret;
68da853ecaSopenharmony_ci    }
69da853ecaSopenharmony_ci    ret = SetQpRange(format, false);
70da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
71da853ecaSopenharmony_ci        return ret;
72da853ecaSopenharmony_ci    }
73da853ecaSopenharmony_ci    ret = SetLowLatency(format);
74da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
75da853ecaSopenharmony_ci        return ret;
76da853ecaSopenharmony_ci    }
77da853ecaSopenharmony_ci    ret = SetRepeat(format);
78da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
79da853ecaSopenharmony_ci        return ret;
80da853ecaSopenharmony_ci    }
81da853ecaSopenharmony_ci    (void)EnableEncoderParamsFeedback(format);
82da853ecaSopenharmony_ci    return AVCS_ERR_OK;
83da853ecaSopenharmony_ci}
84da853ecaSopenharmony_ci
85da853ecaSopenharmony_ciint32_t HEncoder::ConfigureBufferType()
86da853ecaSopenharmony_ci{
87da853ecaSopenharmony_ci    UseBufferType useBufferTypes;
88da853ecaSopenharmony_ci    InitOMXParamExt(useBufferTypes);
89da853ecaSopenharmony_ci    useBufferTypes.portIndex = OMX_DirInput;
90da853ecaSopenharmony_ci    useBufferTypes.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
91da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamUseBufferType, useBufferTypes)) {
92da853ecaSopenharmony_ci        HLOGE("component don't support CODEC_BUFFER_TYPE_DYNAMIC_HANDLE");
93da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
94da853ecaSopenharmony_ci    }
95da853ecaSopenharmony_ci    return AVCS_ERR_OK;
96da853ecaSopenharmony_ci}
97da853ecaSopenharmony_ci
98da853ecaSopenharmony_civoid HEncoder::CheckIfEnableCb(const Format &format)
99da853ecaSopenharmony_ci{
100da853ecaSopenharmony_ci    int32_t enableCb = 0;
101da853ecaSopenharmony_ci    if (format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, enableCb)) {
102da853ecaSopenharmony_ci        HLOGI("enable surface mode callback flag %d", enableCb);
103da853ecaSopenharmony_ci        enableSurfaceModeInputCb_ = static_cast<bool>(enableCb);
104da853ecaSopenharmony_ci    }
105da853ecaSopenharmony_ci}
106da853ecaSopenharmony_ci
107da853ecaSopenharmony_ciint32_t HEncoder::SetRepeat(const Format &format)
108da853ecaSopenharmony_ci{
109da853ecaSopenharmony_ci    int repeatMs = 0;
110da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, repeatMs)) {
111da853ecaSopenharmony_ci        return AVCS_ERR_OK;
112da853ecaSopenharmony_ci    }
113da853ecaSopenharmony_ci    if (repeatMs <= 0) {
114da853ecaSopenharmony_ci        HLOGW("invalid repeatMs %d", repeatMs);
115da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
116da853ecaSopenharmony_ci    }
117da853ecaSopenharmony_ci    repeatUs_ = static_cast<uint64_t>(repeatMs * TIME_RATIO_S_TO_MS);
118da853ecaSopenharmony_ci
119da853ecaSopenharmony_ci    int repeatMaxCnt = 0;
120da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, repeatMaxCnt)) {
121da853ecaSopenharmony_ci        return AVCS_ERR_OK;
122da853ecaSopenharmony_ci    }
123da853ecaSopenharmony_ci    if (repeatMaxCnt == 0) {
124da853ecaSopenharmony_ci        HLOGW("invalid repeatMaxCnt %d", repeatMaxCnt);
125da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
126da853ecaSopenharmony_ci    }
127da853ecaSopenharmony_ci    repeatMaxCnt_ = repeatMaxCnt;
128da853ecaSopenharmony_ci    return AVCS_ERR_OK;
129da853ecaSopenharmony_ci}
130da853ecaSopenharmony_ci
131da853ecaSopenharmony_ciint32_t HEncoder::SetLTRParam(const Format &format)
132da853ecaSopenharmony_ci{
133da853ecaSopenharmony_ci    int32_t ltrFrameNum = -1;
134da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameNum)) {
135da853ecaSopenharmony_ci        return AVCS_ERR_OK;
136da853ecaSopenharmony_ci    }
137da853ecaSopenharmony_ci    if (!caps_.port.video.isSupportLTR) {
138da853ecaSopenharmony_ci        HLOGW("platform not support LTR");
139da853ecaSopenharmony_ci        return AVCS_ERR_OK;
140da853ecaSopenharmony_ci    }
141da853ecaSopenharmony_ci    if (ltrFrameNum <= 0 || ltrFrameNum > caps_.port.video.maxLTRFrameNum) {
142da853ecaSopenharmony_ci        HLOGE("invalid ltrFrameNum %d", ltrFrameNum);
143da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
144da853ecaSopenharmony_ci    }
145da853ecaSopenharmony_ci    if (enableTSVC_) {
146da853ecaSopenharmony_ci        HLOGW("user has enabled temporal scale, can not set LTR param");
147da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
148da853ecaSopenharmony_ci    }
149da853ecaSopenharmony_ci    CodecLTRParam info;
150da853ecaSopenharmony_ci    InitOMXParamExt(info);
151da853ecaSopenharmony_ci    info.ltrFrameListLen = static_cast<uint32_t>(ltrFrameNum);
152da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamLTR, info)) {
153da853ecaSopenharmony_ci        HLOGE("configure LTR failed");
154da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
155da853ecaSopenharmony_ci    }
156da853ecaSopenharmony_ci    enableLTR_ = true;
157da853ecaSopenharmony_ci    return AVCS_ERR_OK;
158da853ecaSopenharmony_ci}
159da853ecaSopenharmony_ci
160da853ecaSopenharmony_ciint32_t HEncoder::EnableEncoderParamsFeedback(const Format &format)
161da853ecaSopenharmony_ci{
162da853ecaSopenharmony_ci    int32_t enableParamsFeedback {};
163da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_PARAMS_FEEDBACK, enableParamsFeedback)) {
164da853ecaSopenharmony_ci        return AVCS_ERR_OK;
165da853ecaSopenharmony_ci    }
166da853ecaSopenharmony_ci    OMX_CONFIG_BOOLEANTYPE param {};
167da853ecaSopenharmony_ci    InitOMXParam(param);
168da853ecaSopenharmony_ci    param.bEnabled = enableParamsFeedback ? OMX_TRUE : OMX_FALSE;
169da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamEncParamsFeedback, param)) {
170da853ecaSopenharmony_ci        HLOGE("configure encoder params feedback[%d] failed", enableParamsFeedback);
171da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
172da853ecaSopenharmony_ci    }
173da853ecaSopenharmony_ci    HLOGI("configure encoder params feedback[%d] success", enableParamsFeedback);
174da853ecaSopenharmony_ci    return AVCS_ERR_OK;
175da853ecaSopenharmony_ci}
176da853ecaSopenharmony_ci
177da853ecaSopenharmony_ciint32_t HEncoder::SetQpRange(const Format &format, bool isCfg)
178da853ecaSopenharmony_ci{
179da853ecaSopenharmony_ci    int32_t minQp;
180da853ecaSopenharmony_ci    int32_t maxQp;
181da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) ||
182da853ecaSopenharmony_ci        !format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) {
183da853ecaSopenharmony_ci        return AVCS_ERR_OK;
184da853ecaSopenharmony_ci    }
185da853ecaSopenharmony_ci
186da853ecaSopenharmony_ci    CodecQPRangeParam QPRangeParam;
187da853ecaSopenharmony_ci    InitOMXParamExt(QPRangeParam);
188da853ecaSopenharmony_ci    QPRangeParam.minQp = static_cast<uint32_t>(minQp);
189da853ecaSopenharmony_ci    QPRangeParam.maxQp = static_cast<uint32_t>(maxQp);
190da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamQPRange, QPRangeParam, isCfg)) {
191da853ecaSopenharmony_ci        HLOGE("set qp range (%d~%d) failed", minQp, maxQp);
192da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
193da853ecaSopenharmony_ci    }
194da853ecaSopenharmony_ci    HLOGI("set qp range (%d~%d) succ", minQp, maxQp);
195da853ecaSopenharmony_ci    return AVCS_ERR_OK;
196da853ecaSopenharmony_ci}
197da853ecaSopenharmony_ci
198da853ecaSopenharmony_ciint32_t HEncoder::SetTemperalLayer(const Format &format)
199da853ecaSopenharmony_ci{
200da853ecaSopenharmony_ci    int32_t enableTemporalScale = 0;
201da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enableTemporalScale) ||
202da853ecaSopenharmony_ci        (enableTemporalScale == 0)) {
203da853ecaSopenharmony_ci        return AVCS_ERR_OK;
204da853ecaSopenharmony_ci    }
205da853ecaSopenharmony_ci    if (!caps_.port.video.isSupportTSVC) {
206da853ecaSopenharmony_ci        HLOGW("platform not support temporal scale");
207da853ecaSopenharmony_ci        return AVCS_ERR_OK;
208da853ecaSopenharmony_ci    }
209da853ecaSopenharmony_ci    Media::Plugins::TemporalGopReferenceMode GopReferenceMode{};
210da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
211da853ecaSopenharmony_ci        *reinterpret_cast<int *>(&GopReferenceMode)) ||
212da853ecaSopenharmony_ci        static_cast<int32_t>(GopReferenceMode) != 2) { // 2: gop mode
213da853ecaSopenharmony_ci        HLOGE("user enable temporal scalability but not set invalid temporal gop mode");
214da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
215da853ecaSopenharmony_ci    }
216da853ecaSopenharmony_ci    int32_t temporalGopSize = 0;
217da853ecaSopenharmony_ci    if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize)) {
218da853ecaSopenharmony_ci        HLOGE("user enable temporal scalability but not set invalid temporal gop size");
219da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
220da853ecaSopenharmony_ci    }
221da853ecaSopenharmony_ci
222da853ecaSopenharmony_ci    CodecTemperalLayerParam temperalLayerParam;
223da853ecaSopenharmony_ci    InitOMXParamExt(temperalLayerParam);
224da853ecaSopenharmony_ci    switch (temporalGopSize) {
225da853ecaSopenharmony_ci        case 2: // 2: picture size of the temporal group
226da853ecaSopenharmony_ci            temperalLayerParam.layerCnt = 2; // 2: layer of the temporal group
227da853ecaSopenharmony_ci            break;
228da853ecaSopenharmony_ci        case 4: // 4: picture size of the temporal group
229da853ecaSopenharmony_ci            temperalLayerParam.layerCnt = 3; // 3: layer of the temporal group
230da853ecaSopenharmony_ci            break;
231da853ecaSopenharmony_ci        default:
232da853ecaSopenharmony_ci            HLOGE("user set invalid temporal gop size %d", temporalGopSize);
233da853ecaSopenharmony_ci            return AVCS_ERR_INVALID_VAL;
234da853ecaSopenharmony_ci    }
235da853ecaSopenharmony_ci
236da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamTemperalLayer, temperalLayerParam)) {
237da853ecaSopenharmony_ci        HLOGE("set temporal layer param failed");
238da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
239da853ecaSopenharmony_ci    }
240da853ecaSopenharmony_ci    HLOGI("set temporal layer param %d succ", temperalLayerParam.layerCnt);
241da853ecaSopenharmony_ci    enableTSVC_ = true;
242da853ecaSopenharmony_ci    return AVCS_ERR_OK;
243da853ecaSopenharmony_ci}
244da853ecaSopenharmony_ci
245da853ecaSopenharmony_ciint32_t HEncoder::OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer)
246da853ecaSopenharmony_ci{
247da853ecaSopenharmony_ci    if (!caps_.port.video.isSupportWaterMark) {
248da853ecaSopenharmony_ci        HLOGE("this device dont support water mark");
249da853ecaSopenharmony_ci        return AVCS_ERR_UNSUPPORT;
250da853ecaSopenharmony_ci    }
251da853ecaSopenharmony_ci    if (buffer == nullptr || buffer->memory_ == nullptr || buffer->meta_ == nullptr) {
252da853ecaSopenharmony_ci        HLOGE("invalid buffer");
253da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
254da853ecaSopenharmony_ci    }
255da853ecaSopenharmony_ci    sptr<SurfaceBuffer> waterMarkBuffer = buffer->memory_->GetSurfaceBuffer();
256da853ecaSopenharmony_ci    if (waterMarkBuffer == nullptr) {
257da853ecaSopenharmony_ci        HLOGE("null surfacebuffer");
258da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
259da853ecaSopenharmony_ci    }
260da853ecaSopenharmony_ci    if (waterMarkBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_8888) {
261da853ecaSopenharmony_ci        HLOGE("pixel fmt should be RGBA8888");
262da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
263da853ecaSopenharmony_ci    }
264da853ecaSopenharmony_ci    bool enableWaterMark = false;
265da853ecaSopenharmony_ci    int32_t x = 0;
266da853ecaSopenharmony_ci    int32_t y = 0;
267da853ecaSopenharmony_ci    int32_t w = 0;
268da853ecaSopenharmony_ci    int32_t h = 0;
269da853ecaSopenharmony_ci    if (!buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_WATERMARK, enableWaterMark) ||
270da853ecaSopenharmony_ci        !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_X, x) ||
271da853ecaSopenharmony_ci        !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_Y, y) ||
272da853ecaSopenharmony_ci        !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_W, w) ||
273da853ecaSopenharmony_ci        !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_H, h)) {
274da853ecaSopenharmony_ci        HLOGE("invalid value");
275da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
276da853ecaSopenharmony_ci    }
277da853ecaSopenharmony_ci    if (x < 0 || y < 0 || w <= 0 || h <= 0) {
278da853ecaSopenharmony_ci        HLOGE("invalid coordinate, x %d, y %d, w %d, h %d", x, y, w, h);
279da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
280da853ecaSopenharmony_ci    }
281da853ecaSopenharmony_ci    CodecHDI::CodecParamOverlay param {
282da853ecaSopenharmony_ci        .size = sizeof(param), .enable = enableWaterMark, .dstX = static_cast<uint32_t>(x),
283da853ecaSopenharmony_ci        .dstY = static_cast<uint32_t>(y), .dstW = static_cast<uint32_t>(w), .dstH = static_cast<uint32_t>(h),
284da853ecaSopenharmony_ci    };
285da853ecaSopenharmony_ci    int8_t* p = reinterpret_cast<int8_t*>(&param);
286da853ecaSopenharmony_ci    std::vector<int8_t> inVec(p, p + sizeof(param));
287da853ecaSopenharmony_ci    CodecHDI::OmxCodecBuffer omxbuffer {};
288da853ecaSopenharmony_ci    omxbuffer.bufferhandle = new HDI::Base::NativeBuffer(waterMarkBuffer->GetBufferHandle());
289da853ecaSopenharmony_ci    int32_t ret = compNode_->SetParameterWithBuffer(CodecHDI::Codec_IndexParamOverlayBuffer, inVec, omxbuffer);
290da853ecaSopenharmony_ci    if (ret != HDF_SUCCESS) {
291da853ecaSopenharmony_ci        HLOGE("SetParameterWithBuffer failed");
292da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
293da853ecaSopenharmony_ci    }
294da853ecaSopenharmony_ci    HLOGI("SetParameterWithBuffer succ");
295da853ecaSopenharmony_ci    return AVCS_ERR_OK;
296da853ecaSopenharmony_ci}
297da853ecaSopenharmony_ci
298da853ecaSopenharmony_ciint32_t HEncoder::SetColorAspects(const Format &format)
299da853ecaSopenharmony_ci{
300da853ecaSopenharmony_ci    int range = 0;
301da853ecaSopenharmony_ci    int primary = static_cast<int>(COLOR_PRIMARY_UNSPECIFIED);
302da853ecaSopenharmony_ci    int transfer = static_cast<int>(TRANSFER_CHARACTERISTIC_UNSPECIFIED);
303da853ecaSopenharmony_ci    int matrix = static_cast<int>(MATRIX_COEFFICIENT_UNSPECIFIED);
304da853ecaSopenharmony_ci
305da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, range)) {
306da853ecaSopenharmony_ci        HLOGI("user set range flag %d", range);
307da853ecaSopenharmony_ci    }
308da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, primary)) {
309da853ecaSopenharmony_ci        HLOGI("user set primary %d", primary);
310da853ecaSopenharmony_ci    }
311da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, transfer)) {
312da853ecaSopenharmony_ci        HLOGI("user set transfer %d", transfer);
313da853ecaSopenharmony_ci    }
314da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, matrix)) {
315da853ecaSopenharmony_ci        HLOGI("user set matrix %d", matrix);
316da853ecaSopenharmony_ci    }
317da853ecaSopenharmony_ci    if (primary < 0 || primary > UINT8_MAX ||
318da853ecaSopenharmony_ci        transfer < 0 || transfer > UINT8_MAX ||
319da853ecaSopenharmony_ci        matrix < 0 || matrix > UINT8_MAX) {
320da853ecaSopenharmony_ci        HLOGW("invalid color");
321da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
322da853ecaSopenharmony_ci    }
323da853ecaSopenharmony_ci
324da853ecaSopenharmony_ci    CodecVideoColorspace param;
325da853ecaSopenharmony_ci    InitOMXParamExt(param);
326da853ecaSopenharmony_ci    param.portIndex = OMX_DirInput;
327da853ecaSopenharmony_ci    param.aspects.range = static_cast<bool>(range);
328da853ecaSopenharmony_ci    param.aspects.primaries = static_cast<uint8_t>(primary);
329da853ecaSopenharmony_ci    param.aspects.transfer = static_cast<uint8_t>(transfer);
330da853ecaSopenharmony_ci    param.aspects.matrixCoeffs = static_cast<uint8_t>(matrix);
331da853ecaSopenharmony_ci
332da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexColorAspects, param, true)) {
333da853ecaSopenharmony_ci        HLOGE("failed to set CodecVideoColorSpace");
334da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
335da853ecaSopenharmony_ci    }
336da853ecaSopenharmony_ci    HLOGI("set color aspects (isFullRange %d, primary %u, transfer %u, matrix %u) succ",
337da853ecaSopenharmony_ci          param.aspects.range, param.aspects.primaries,
338da853ecaSopenharmony_ci          param.aspects.transfer, param.aspects.matrixCoeffs);
339da853ecaSopenharmony_ci    return AVCS_ERR_OK;
340da853ecaSopenharmony_ci}
341da853ecaSopenharmony_ci
342da853ecaSopenharmony_civoid HEncoder::CalcInputBufSize(PortInfo &info, VideoPixelFormat pixelFmt)
343da853ecaSopenharmony_ci{
344da853ecaSopenharmony_ci    uint32_t inSize = AlignTo(info.width, 128u) * AlignTo(info.height, 128u); // 128: block size
345da853ecaSopenharmony_ci    if (pixelFmt == VideoPixelFormat::RGBA) {
346da853ecaSopenharmony_ci        inSize = inSize * 4; // 4 byte per pixel
347da853ecaSopenharmony_ci    } else {
348da853ecaSopenharmony_ci        inSize = inSize * 3 / 2; // 3: nom, 2: denom
349da853ecaSopenharmony_ci    }
350da853ecaSopenharmony_ci    info.inputBufSize = inSize;
351da853ecaSopenharmony_ci}
352da853ecaSopenharmony_ci
353da853ecaSopenharmony_ciint32_t HEncoder::SetupPort(const Format &format, std::optional<double> frameRate)
354da853ecaSopenharmony_ci{
355da853ecaSopenharmony_ci    constexpr int32_t MAX_ENCODE_WIDTH = 10000;
356da853ecaSopenharmony_ci    constexpr int32_t MAX_ENCODE_HEIGHT = 10000;
357da853ecaSopenharmony_ci    int32_t width;
358da853ecaSopenharmony_ci    if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0 || width > MAX_ENCODE_WIDTH) {
359da853ecaSopenharmony_ci        HLOGE("format should contain width");
360da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
361da853ecaSopenharmony_ci    }
362da853ecaSopenharmony_ci    int32_t height;
363da853ecaSopenharmony_ci    if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0 || height > MAX_ENCODE_HEIGHT) {
364da853ecaSopenharmony_ci        HLOGE("format should contain height");
365da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
366da853ecaSopenharmony_ci    }
367da853ecaSopenharmony_ci    width_ = static_cast<uint32_t>(width);
368da853ecaSopenharmony_ci    height_ = static_cast<uint32_t>(height);
369da853ecaSopenharmony_ci    HLOGI("user set width %d, height %d", width, height);
370da853ecaSopenharmony_ci    if (!GetPixelFmtFromUser(format)) {
371da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
372da853ecaSopenharmony_ci    }
373da853ecaSopenharmony_ci
374da853ecaSopenharmony_ci    if (!frameRate.has_value()) {
375da853ecaSopenharmony_ci        HLOGI("user don't set valid frame rate, use default 60.0");
376da853ecaSopenharmony_ci        frameRate = 60.0; // default frame rate 60.0
377da853ecaSopenharmony_ci    }
378da853ecaSopenharmony_ci
379da853ecaSopenharmony_ci    PortInfo inputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
380da853ecaSopenharmony_ci                              OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()};
381da853ecaSopenharmony_ci    CalcInputBufSize(inputPortInfo, configuredFmt_.innerFmt);
382da853ecaSopenharmony_ci    int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo);
383da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
384da853ecaSopenharmony_ci        return ret;
385da853ecaSopenharmony_ci    }
386da853ecaSopenharmony_ci
387da853ecaSopenharmony_ci    PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
388da853ecaSopenharmony_ci                               codingType_, std::nullopt, frameRate.value()};
389da853ecaSopenharmony_ci    ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo);
390da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
391da853ecaSopenharmony_ci        return ret;
392da853ecaSopenharmony_ci    }
393da853ecaSopenharmony_ci    return AVCS_ERR_OK;
394da853ecaSopenharmony_ci}
395da853ecaSopenharmony_ci
396da853ecaSopenharmony_ciint32_t HEncoder::UpdateInPortFormat()
397da853ecaSopenharmony_ci{
398da853ecaSopenharmony_ci    OMX_PARAM_PORTDEFINITIONTYPE def;
399da853ecaSopenharmony_ci    InitOMXParam(def);
400da853ecaSopenharmony_ci    def.nPortIndex = OMX_DirInput;
401da853ecaSopenharmony_ci    if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
402da853ecaSopenharmony_ci        HLOGE("get input port definition failed");
403da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
404da853ecaSopenharmony_ci    }
405da853ecaSopenharmony_ci    PrintPortDefinition(def);
406da853ecaSopenharmony_ci    uint32_t w = def.format.video.nFrameWidth;
407da853ecaSopenharmony_ci    uint32_t h = def.format.video.nFrameHeight;
408da853ecaSopenharmony_ci    inBufferCnt_ = def.nBufferCountActual;
409da853ecaSopenharmony_ci
410da853ecaSopenharmony_ci    // save into member variable
411da853ecaSopenharmony_ci    requestCfg_.timeout = 0;
412da853ecaSopenharmony_ci    requestCfg_.width = static_cast<int32_t>(w);
413da853ecaSopenharmony_ci    requestCfg_.height = static_cast<int32_t>(h);
414da853ecaSopenharmony_ci    requestCfg_.strideAlignment = STRIDE_ALIGNMENT;
415da853ecaSopenharmony_ci    requestCfg_.format = configuredFmt_.graphicFmt;
416da853ecaSopenharmony_ci    requestCfg_.usage = BUFFER_MODE_REQUEST_USAGE;
417da853ecaSopenharmony_ci
418da853ecaSopenharmony_ci    if (inputFormat_ == nullptr) {
419da853ecaSopenharmony_ci        inputFormat_ = make_shared<Format>();
420da853ecaSopenharmony_ci    }
421da853ecaSopenharmony_ci    inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w);
422da853ecaSopenharmony_ci    inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h);
423da853ecaSopenharmony_ci    inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT,
424da853ecaSopenharmony_ci        static_cast<int32_t>(configuredFmt_.innerFmt));
425da853ecaSopenharmony_ci    return AVCS_ERR_OK;
426da853ecaSopenharmony_ci}
427da853ecaSopenharmony_ci
428da853ecaSopenharmony_ciint32_t HEncoder::UpdateOutPortFormat()
429da853ecaSopenharmony_ci{
430da853ecaSopenharmony_ci    OMX_PARAM_PORTDEFINITIONTYPE def;
431da853ecaSopenharmony_ci    InitOMXParam(def);
432da853ecaSopenharmony_ci    def.nPortIndex = OMX_DirOutput;
433da853ecaSopenharmony_ci    if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
434da853ecaSopenharmony_ci        HLOGE("get output port definition failed");
435da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
436da853ecaSopenharmony_ci    }
437da853ecaSopenharmony_ci    PrintPortDefinition(def);
438da853ecaSopenharmony_ci    if (outputFormat_ == nullptr) {
439da853ecaSopenharmony_ci        outputFormat_ = make_shared<Format>();
440da853ecaSopenharmony_ci    }
441da853ecaSopenharmony_ci    outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth);
442da853ecaSopenharmony_ci    outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight);
443da853ecaSopenharmony_ci    return AVCS_ERR_OK;
444da853ecaSopenharmony_ci}
445da853ecaSopenharmony_ci
446da853ecaSopenharmony_cistatic uint32_t SetPFramesSpacing(int32_t iFramesIntervalInMs, double frameRate, uint32_t bFramesSpacing = 0)
447da853ecaSopenharmony_ci{
448da853ecaSopenharmony_ci    if (iFramesIntervalInMs < 0) { // IPPPP...
449da853ecaSopenharmony_ci        return UINT32_MAX - 1;
450da853ecaSopenharmony_ci    }
451da853ecaSopenharmony_ci    if (iFramesIntervalInMs == 0) { // IIIII...
452da853ecaSopenharmony_ci        return 0;
453da853ecaSopenharmony_ci    }
454da853ecaSopenharmony_ci    uint32_t iFramesInterval = iFramesIntervalInMs * frameRate / TIME_RATIO_S_TO_MS;
455da853ecaSopenharmony_ci    uint32_t pFramesSpacing = iFramesInterval / (bFramesSpacing + 1);
456da853ecaSopenharmony_ci    return pFramesSpacing > 0 ? pFramesSpacing - 1 : 0;
457da853ecaSopenharmony_ci}
458da853ecaSopenharmony_ci
459da853ecaSopenharmony_cistd::optional<uint32_t> HEncoder::GetBitRateFromUser(const Format &format)
460da853ecaSopenharmony_ci{
461da853ecaSopenharmony_ci    int64_t bitRateLong;
462da853ecaSopenharmony_ci    if (format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateLong) && bitRateLong > 0 &&
463da853ecaSopenharmony_ci        bitRateLong <= UINT32_MAX) {
464da853ecaSopenharmony_ci        LOGI("user set bit rate %" PRId64 "", bitRateLong);
465da853ecaSopenharmony_ci        return static_cast<uint32_t>(bitRateLong);
466da853ecaSopenharmony_ci    }
467da853ecaSopenharmony_ci    int32_t bitRateInt;
468da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateInt) && bitRateInt > 0) {
469da853ecaSopenharmony_ci        LOGI("user set bit rate %d", bitRateInt);
470da853ecaSopenharmony_ci        return static_cast<uint32_t>(bitRateInt);
471da853ecaSopenharmony_ci    }
472da853ecaSopenharmony_ci    return nullopt;
473da853ecaSopenharmony_ci}
474da853ecaSopenharmony_ci
475da853ecaSopenharmony_cistd::optional<VideoEncodeBitrateMode> HEncoder::GetBitRateModeFromUser(const Format &format)
476da853ecaSopenharmony_ci{
477da853ecaSopenharmony_ci    VideoEncodeBitrateMode mode;
478da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, *reinterpret_cast<int *>(&mode))) {
479da853ecaSopenharmony_ci        return mode;
480da853ecaSopenharmony_ci    }
481da853ecaSopenharmony_ci    return nullopt;
482da853ecaSopenharmony_ci}
483da853ecaSopenharmony_ci
484da853ecaSopenharmony_ciint32_t HEncoder::SetConstantQualityMode(int32_t quality)
485da853ecaSopenharmony_ci{
486da853ecaSopenharmony_ci    ControlRateConstantQuality bitrateType;
487da853ecaSopenharmony_ci    InitOMXParamExt(bitrateType);
488da853ecaSopenharmony_ci    bitrateType.portIndex = OMX_DirOutput;
489da853ecaSopenharmony_ci    bitrateType.qualityValue = static_cast<uint32_t>(quality);
490da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamControlRateConstantQuality, bitrateType)) {
491da853ecaSopenharmony_ci        HLOGE("failed to set OMX_IndexParamControlRateConstantQuality");
492da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
493da853ecaSopenharmony_ci    }
494da853ecaSopenharmony_ci    HLOGI("set CQ mode and target quality %u succ", bitrateType.qualityValue);
495da853ecaSopenharmony_ci    outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, CQ);
496da853ecaSopenharmony_ci    outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
497da853ecaSopenharmony_ci    return AVCS_ERR_OK;
498da853ecaSopenharmony_ci}
499da853ecaSopenharmony_ci
500da853ecaSopenharmony_ciint32_t HEncoder::ConfigureOutputBitrate(const Format &format)
501da853ecaSopenharmony_ci{
502da853ecaSopenharmony_ci    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
503da853ecaSopenharmony_ci    InitOMXParam(bitrateType);
504da853ecaSopenharmony_ci    bitrateType.nPortIndex = OMX_DirOutput;
505da853ecaSopenharmony_ci    if (!GetParameter(OMX_IndexParamVideoBitrate, bitrateType)) {
506da853ecaSopenharmony_ci        HLOGE("get OMX_IndexParamVideoBitrate failed");
507da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
508da853ecaSopenharmony_ci    }
509da853ecaSopenharmony_ci    optional<VideoEncodeBitrateMode> bitRateMode = GetBitRateModeFromUser(format);
510da853ecaSopenharmony_ci    int32_t quality;
511da853ecaSopenharmony_ci    if (bitRateMode.has_value() && bitRateMode.value() == CQ &&
512da853ecaSopenharmony_ci        format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality) && quality >= 0) {
513da853ecaSopenharmony_ci        return SetConstantQualityMode(quality);
514da853ecaSopenharmony_ci    }
515da853ecaSopenharmony_ci    optional<uint32_t> bitRate = GetBitRateFromUser(format);
516da853ecaSopenharmony_ci    if (bitRate.has_value()) {
517da853ecaSopenharmony_ci        bitrateType.nTargetBitrate = bitRate.value();
518da853ecaSopenharmony_ci    }
519da853ecaSopenharmony_ci    if (bitRateMode.has_value()) {
520da853ecaSopenharmony_ci        auto omxBitrateMode = TypeConverter::InnerModeToOmxBitrateMode(bitRateMode.value());
521da853ecaSopenharmony_ci        if (omxBitrateMode.has_value()) {
522da853ecaSopenharmony_ci            bitrateType.eControlRate = omxBitrateMode.value();
523da853ecaSopenharmony_ci        }
524da853ecaSopenharmony_ci    }
525da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamVideoBitrate, bitrateType)) {
526da853ecaSopenharmony_ci        HLOGE("failed to set OMX_IndexParamVideoBitrate");
527da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
528da853ecaSopenharmony_ci    }
529da853ecaSopenharmony_ci    outputFormat_->PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE,
530da853ecaSopenharmony_ci        static_cast<int64_t>(bitrateType.nTargetBitrate));
531da853ecaSopenharmony_ci    auto innerMode = TypeConverter::OmxBitrateModeToInnerMode(bitrateType.eControlRate);
532da853ecaSopenharmony_ci    if (innerMode.has_value()) {
533da853ecaSopenharmony_ci        outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE,
534da853ecaSopenharmony_ci            static_cast<int32_t>(innerMode.value()));
535da853ecaSopenharmony_ci        HLOGI("set %d mode and target bitrate %u bps succ", bitRateMode.value(), bitrateType.nTargetBitrate);
536da853ecaSopenharmony_ci    } else {
537da853ecaSopenharmony_ci        HLOGI("set default bitratemode and target bitrate %u bps succ", bitrateType.nTargetBitrate);
538da853ecaSopenharmony_ci    }
539da853ecaSopenharmony_ci    return AVCS_ERR_OK;
540da853ecaSopenharmony_ci}
541da853ecaSopenharmony_ci
542da853ecaSopenharmony_civoid HEncoder::ConfigureProtocol(const Format &format, std::optional<double> frameRate)
543da853ecaSopenharmony_ci{
544da853ecaSopenharmony_ci    int32_t ret = AVCS_ERR_OK;
545da853ecaSopenharmony_ci    switch (static_cast<int>(codingType_)) {
546da853ecaSopenharmony_ci        case OMX_VIDEO_CodingAVC:
547da853ecaSopenharmony_ci            ret = SetupAVCEncoderParameters(format, frameRate);
548da853ecaSopenharmony_ci            break;
549da853ecaSopenharmony_ci        case CODEC_OMX_VIDEO_CodingHEVC:
550da853ecaSopenharmony_ci            ret = SetupHEVCEncoderParameters(format, frameRate);
551da853ecaSopenharmony_ci            break;
552da853ecaSopenharmony_ci        default:
553da853ecaSopenharmony_ci            break;
554da853ecaSopenharmony_ci    }
555da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
556da853ecaSopenharmony_ci        HLOGW("set protocol param failed");
557da853ecaSopenharmony_ci    }
558da853ecaSopenharmony_ci}
559da853ecaSopenharmony_ci
560da853ecaSopenharmony_ciint32_t HEncoder::SetupAVCEncoderParameters(const Format &format, std::optional<double> frameRate)
561da853ecaSopenharmony_ci{
562da853ecaSopenharmony_ci    OMX_VIDEO_PARAM_AVCTYPE avcType;
563da853ecaSopenharmony_ci    InitOMXParam(avcType);
564da853ecaSopenharmony_ci    avcType.nPortIndex = OMX_DirOutput;
565da853ecaSopenharmony_ci    if (!GetParameter(OMX_IndexParamVideoAvc, avcType)) {
566da853ecaSopenharmony_ci        HLOGE("get OMX_IndexParamVideoAvc parameter fail");
567da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
568da853ecaSopenharmony_ci    }
569da853ecaSopenharmony_ci    avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
570da853ecaSopenharmony_ci    avcType.nBFrames = 0;
571da853ecaSopenharmony_ci
572da853ecaSopenharmony_ci    AVCProfile profile;
573da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) {
574da853ecaSopenharmony_ci        optional<OMX_VIDEO_AVCPROFILETYPE> omxAvcProfile = TypeConverter::InnerAvcProfileToOmxProfile(profile);
575da853ecaSopenharmony_ci        if (omxAvcProfile.has_value()) {
576da853ecaSopenharmony_ci            avcType.eProfile = omxAvcProfile.value();
577da853ecaSopenharmony_ci        }
578da853ecaSopenharmony_ci    }
579da853ecaSopenharmony_ci    int32_t iFrameInterval;
580da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) {
581da853ecaSopenharmony_ci        SetAvcFields(avcType, iFrameInterval, frameRate.value());
582da853ecaSopenharmony_ci    }
583da853ecaSopenharmony_ci
584da853ecaSopenharmony_ci    if (avcType.nBFrames != 0) {
585da853ecaSopenharmony_ci        avcType.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
586da853ecaSopenharmony_ci    }
587da853ecaSopenharmony_ci    avcType.bEnableUEP = OMX_FALSE;
588da853ecaSopenharmony_ci    avcType.bEnableFMO = OMX_FALSE;
589da853ecaSopenharmony_ci    avcType.bEnableASO = OMX_FALSE;
590da853ecaSopenharmony_ci    avcType.bEnableRS = OMX_FALSE;
591da853ecaSopenharmony_ci    avcType.bFrameMBsOnly = OMX_TRUE;
592da853ecaSopenharmony_ci    avcType.bMBAFF = OMX_FALSE;
593da853ecaSopenharmony_ci    avcType.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
594da853ecaSopenharmony_ci
595da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamVideoAvc, avcType)) {
596da853ecaSopenharmony_ci        HLOGE("failed to set OMX_IndexParamVideoAvc");
597da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
598da853ecaSopenharmony_ci    }
599da853ecaSopenharmony_ci    return AVCS_ERR_OK;
600da853ecaSopenharmony_ci}
601da853ecaSopenharmony_ci
602da853ecaSopenharmony_civoid HEncoder::SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE &avcType, int32_t iFrameInterval, double frameRate)
603da853ecaSopenharmony_ci{
604da853ecaSopenharmony_ci    HLOGI("iFrameInterval:%d, frameRate:%.2f, eProfile:0x%x, eLevel:0x%x",
605da853ecaSopenharmony_ci          iFrameInterval, frameRate, avcType.eProfile, avcType.eLevel);
606da853ecaSopenharmony_ci
607da853ecaSopenharmony_ci    if (avcType.eProfile == OMX_VIDEO_AVCProfileBaseline) {
608da853ecaSopenharmony_ci        avcType.nSliceHeaderSpacing = 0;
609da853ecaSopenharmony_ci        avcType.bUseHadamard = OMX_TRUE;
610da853ecaSopenharmony_ci        avcType.nRefFrames = 1;
611da853ecaSopenharmony_ci        avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
612da853ecaSopenharmony_ci        if (avcType.nPFrames == 0) {
613da853ecaSopenharmony_ci            avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
614da853ecaSopenharmony_ci        }
615da853ecaSopenharmony_ci        avcType.nRefIdx10ActiveMinus1 = 0;
616da853ecaSopenharmony_ci        avcType.nRefIdx11ActiveMinus1 = 0;
617da853ecaSopenharmony_ci        avcType.bEntropyCodingCABAC = OMX_FALSE;
618da853ecaSopenharmony_ci        avcType.bWeightedPPrediction = OMX_FALSE;
619da853ecaSopenharmony_ci        avcType.bconstIpred = OMX_FALSE;
620da853ecaSopenharmony_ci        avcType.bDirect8x8Inference = OMX_FALSE;
621da853ecaSopenharmony_ci        avcType.bDirectSpatialTemporal = OMX_FALSE;
622da853ecaSopenharmony_ci        avcType.nCabacInitIdc = 0;
623da853ecaSopenharmony_ci    } else if (avcType.eProfile == OMX_VIDEO_AVCProfileMain || avcType.eProfile == OMX_VIDEO_AVCProfileHigh) {
624da853ecaSopenharmony_ci        avcType.nSliceHeaderSpacing = 0;
625da853ecaSopenharmony_ci        avcType.bUseHadamard = OMX_TRUE;
626da853ecaSopenharmony_ci        avcType.nRefFrames = avcType.nBFrames == 0 ? 1 : 2; // 2 is number of reference frames
627da853ecaSopenharmony_ci        avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
628da853ecaSopenharmony_ci        avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
629da853ecaSopenharmony_ci        avcType.nRefIdx10ActiveMinus1 = 0;
630da853ecaSopenharmony_ci        avcType.nRefIdx11ActiveMinus1 = 0;
631da853ecaSopenharmony_ci        avcType.bEntropyCodingCABAC = OMX_TRUE;
632da853ecaSopenharmony_ci        avcType.bWeightedPPrediction = OMX_TRUE;
633da853ecaSopenharmony_ci        avcType.bconstIpred = OMX_TRUE;
634da853ecaSopenharmony_ci        avcType.bDirect8x8Inference = OMX_TRUE;
635da853ecaSopenharmony_ci        avcType.bDirectSpatialTemporal = OMX_TRUE;
636da853ecaSopenharmony_ci        avcType.nCabacInitIdc = 1;
637da853ecaSopenharmony_ci    }
638da853ecaSopenharmony_ci}
639da853ecaSopenharmony_ci
640da853ecaSopenharmony_ciint32_t HEncoder::SetupHEVCEncoderParameters(const Format &format, std::optional<double> frameRate)
641da853ecaSopenharmony_ci{
642da853ecaSopenharmony_ci    CodecVideoParamHevc hevcType;
643da853ecaSopenharmony_ci    InitOMXParamExt(hevcType);
644da853ecaSopenharmony_ci    hevcType.portIndex = OMX_DirOutput;
645da853ecaSopenharmony_ci    if (!GetParameter(OMX_IndexParamVideoHevc, hevcType)) {
646da853ecaSopenharmony_ci        HLOGE("get OMX_IndexParamVideoHevc parameter fail");
647da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
648da853ecaSopenharmony_ci    }
649da853ecaSopenharmony_ci
650da853ecaSopenharmony_ci    HEVCProfile profile;
651da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) {
652da853ecaSopenharmony_ci        optional<CodecHevcProfile> omxHevcProfile = TypeConverter::InnerHevcProfileToOmxProfile(profile);
653da853ecaSopenharmony_ci        if (omxHevcProfile.has_value()) {
654da853ecaSopenharmony_ci            hevcType.profile = omxHevcProfile.value();
655da853ecaSopenharmony_ci            HLOGI("HEVCProfile %d, CodecHevcProfile 0x%x", profile, hevcType.profile);
656da853ecaSopenharmony_ci        }
657da853ecaSopenharmony_ci    }
658da853ecaSopenharmony_ci
659da853ecaSopenharmony_ci    int32_t iFrameInterval;
660da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) {
661da853ecaSopenharmony_ci        if (iFrameInterval < 0) { // IPPPP...
662da853ecaSopenharmony_ci            hevcType.keyFrameInterval = UINT32_MAX - 1;
663da853ecaSopenharmony_ci        } else if (iFrameInterval == 0) { // all intra
664da853ecaSopenharmony_ci            hevcType.keyFrameInterval = 1;
665da853ecaSopenharmony_ci        } else {
666da853ecaSopenharmony_ci            hevcType.keyFrameInterval = iFrameInterval * frameRate.value() / TIME_RATIO_S_TO_MS;
667da853ecaSopenharmony_ci        }
668da853ecaSopenharmony_ci        HLOGI("frameRate %.2f, iFrameInterval %d, keyFrameInterval %u", frameRate.value(),
669da853ecaSopenharmony_ci              iFrameInterval, hevcType.keyFrameInterval);
670da853ecaSopenharmony_ci    }
671da853ecaSopenharmony_ci
672da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexParamVideoHevc, hevcType)) {
673da853ecaSopenharmony_ci        HLOGE("failed to set OMX_IndexParamVideoHevc");
674da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
675da853ecaSopenharmony_ci    }
676da853ecaSopenharmony_ci    return AVCS_ERR_OK;
677da853ecaSopenharmony_ci}
678da853ecaSopenharmony_ci
679da853ecaSopenharmony_ciint32_t HEncoder::RequestIDRFrame()
680da853ecaSopenharmony_ci{
681da853ecaSopenharmony_ci    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
682da853ecaSopenharmony_ci    InitOMXParam(params);
683da853ecaSopenharmony_ci    params.nPortIndex = OMX_DirOutput;
684da853ecaSopenharmony_ci    params.IntraRefreshVOP = OMX_TRUE;
685da853ecaSopenharmony_ci    if (!SetParameter(OMX_IndexConfigVideoIntraVOPRefresh, params, true)) {
686da853ecaSopenharmony_ci        HLOGE("failed to request IDR frame");
687da853ecaSopenharmony_ci        return AVCS_ERR_UNKNOWN;
688da853ecaSopenharmony_ci    }
689da853ecaSopenharmony_ci    HLOGI("Set IDR Frame success");
690da853ecaSopenharmony_ci    return AVCS_ERR_OK;
691da853ecaSopenharmony_ci}
692da853ecaSopenharmony_ci
693da853ecaSopenharmony_ciint32_t HEncoder::OnSetParameters(const Format &format)
694da853ecaSopenharmony_ci{
695da853ecaSopenharmony_ci    optional<uint32_t> bitRate = GetBitRateFromUser(format);
696da853ecaSopenharmony_ci    if (bitRate.has_value()) {
697da853ecaSopenharmony_ci        OMX_VIDEO_CONFIG_BITRATETYPE bitrateCfgType;
698da853ecaSopenharmony_ci        InitOMXParam(bitrateCfgType);
699da853ecaSopenharmony_ci        bitrateCfgType.nPortIndex = OMX_DirOutput;
700da853ecaSopenharmony_ci        bitrateCfgType.nEncodeBitrate = bitRate.value();
701da853ecaSopenharmony_ci        if (!SetParameter(OMX_IndexConfigVideoBitrate, bitrateCfgType, true)) {
702da853ecaSopenharmony_ci            HLOGW("failed to config OMX_IndexConfigVideoBitrate");
703da853ecaSopenharmony_ci        }
704da853ecaSopenharmony_ci    }
705da853ecaSopenharmony_ci
706da853ecaSopenharmony_ci    optional<double> frameRate = GetFrameRateFromUser(format);
707da853ecaSopenharmony_ci    if (frameRate.has_value()) {
708da853ecaSopenharmony_ci        OMX_CONFIG_FRAMERATETYPE framerateCfgType;
709da853ecaSopenharmony_ci        InitOMXParam(framerateCfgType);
710da853ecaSopenharmony_ci        framerateCfgType.nPortIndex = OMX_DirInput;
711da853ecaSopenharmony_ci        framerateCfgType.xEncodeFramerate = frameRate.value() * FRAME_RATE_COEFFICIENT;
712da853ecaSopenharmony_ci        if (!SetParameter(OMX_IndexConfigVideoFramerate, framerateCfgType, true)) {
713da853ecaSopenharmony_ci            HLOGW("failed to config OMX_IndexConfigVideoFramerate");
714da853ecaSopenharmony_ci        }
715da853ecaSopenharmony_ci    }
716da853ecaSopenharmony_ci
717da853ecaSopenharmony_ci    int32_t requestIdr;
718da853ecaSopenharmony_ci    if (format.GetIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, requestIdr) && requestIdr != 0) {
719da853ecaSopenharmony_ci        int32_t ret = RequestIDRFrame();
720da853ecaSopenharmony_ci        if (ret != AVCS_ERR_OK) {
721da853ecaSopenharmony_ci            return ret;
722da853ecaSopenharmony_ci        }
723da853ecaSopenharmony_ci    }
724da853ecaSopenharmony_ci
725da853ecaSopenharmony_ci    int32_t ret = SetQpRange(format, true);
726da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
727da853ecaSopenharmony_ci        return ret;
728da853ecaSopenharmony_ci    }
729da853ecaSopenharmony_ci    return AVCS_ERR_OK;
730da853ecaSopenharmony_ci}
731da853ecaSopenharmony_ci
732da853ecaSopenharmony_ciint32_t HEncoder::SubmitOutputBuffersToOmxNode()
733da853ecaSopenharmony_ci{
734da853ecaSopenharmony_ci    for (BufferInfo &info : outputBufferPool_) {
735da853ecaSopenharmony_ci        if (info.owner == BufferOwner::OWNED_BY_US) {
736da853ecaSopenharmony_ci            int32_t ret = NotifyOmxToFillThisOutBuffer(info);
737da853ecaSopenharmony_ci            if (ret != AVCS_ERR_OK) {
738da853ecaSopenharmony_ci                return ret;
739da853ecaSopenharmony_ci            }
740da853ecaSopenharmony_ci        } else {
741da853ecaSopenharmony_ci            HLOGE("buffer should be owned by us");
742da853ecaSopenharmony_ci            return AVCS_ERR_UNKNOWN;
743da853ecaSopenharmony_ci        }
744da853ecaSopenharmony_ci    }
745da853ecaSopenharmony_ci    return AVCS_ERR_OK;
746da853ecaSopenharmony_ci}
747da853ecaSopenharmony_ci
748da853ecaSopenharmony_cibool HEncoder::ReadyToStart()
749da853ecaSopenharmony_ci{
750da853ecaSopenharmony_ci    if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) {
751da853ecaSopenharmony_ci        return false;
752da853ecaSopenharmony_ci    }
753da853ecaSopenharmony_ci    if (inputSurface_) {
754da853ecaSopenharmony_ci        HLOGI("surface mode, surface id = %" PRIu64, inputSurface_->GetUniqueId());
755da853ecaSopenharmony_ci    } else {
756da853ecaSopenharmony_ci        HLOGI("buffer mode");
757da853ecaSopenharmony_ci    }
758da853ecaSopenharmony_ci    return true;
759da853ecaSopenharmony_ci}
760da853ecaSopenharmony_ci
761da853ecaSopenharmony_ciint32_t HEncoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex)
762da853ecaSopenharmony_ci{
763da853ecaSopenharmony_ci    if (portIndex == OMX_DirOutput) {
764da853ecaSopenharmony_ci        return AllocateAvLinearBuffers(portIndex);
765da853ecaSopenharmony_ci    }
766da853ecaSopenharmony_ci    if (inputSurface_) {
767da853ecaSopenharmony_ci        return AllocInBufsForDynamicSurfaceBuf();
768da853ecaSopenharmony_ci    } else {
769da853ecaSopenharmony_ci        int32_t ret = AllocateAvSurfaceBuffers(portIndex);
770da853ecaSopenharmony_ci        if (ret == AVCS_ERR_OK) {
771da853ecaSopenharmony_ci            UpdateFormatFromSurfaceBuffer();
772da853ecaSopenharmony_ci        }
773da853ecaSopenharmony_ci        return ret;
774da853ecaSopenharmony_ci    }
775da853ecaSopenharmony_ci}
776da853ecaSopenharmony_ci
777da853ecaSopenharmony_civoid HEncoder::UpdateFormatFromSurfaceBuffer()
778da853ecaSopenharmony_ci{
779da853ecaSopenharmony_ci    if (inputBufferPool_.empty()) {
780da853ecaSopenharmony_ci        return;
781da853ecaSopenharmony_ci    }
782da853ecaSopenharmony_ci    sptr<SurfaceBuffer> surfaceBuffer = inputBufferPool_.front().surfaceBuffer;
783da853ecaSopenharmony_ci    if (surfaceBuffer == nullptr) {
784da853ecaSopenharmony_ci        return;
785da853ecaSopenharmony_ci    }
786da853ecaSopenharmony_ci    int32_t stride = surfaceBuffer->GetStride();
787da853ecaSopenharmony_ci    HLOGI("input stride = %d", stride);
788da853ecaSopenharmony_ci    inputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, stride);
789da853ecaSopenharmony_ci}
790da853ecaSopenharmony_ci
791da853ecaSopenharmony_civoid HEncoder::ClearDirtyList()
792da853ecaSopenharmony_ci{
793da853ecaSopenharmony_ci    sptr<SurfaceBuffer> buffer;
794da853ecaSopenharmony_ci    sptr<SyncFence> fence;
795da853ecaSopenharmony_ci    int64_t pts = -1;
796da853ecaSopenharmony_ci    OHOS::Rect damage;
797da853ecaSopenharmony_ci    while (true) {
798da853ecaSopenharmony_ci        GSError ret = inputSurface_->AcquireBuffer(buffer, fence, pts, damage);
799da853ecaSopenharmony_ci        if (ret != GSERROR_OK || buffer == nullptr) {
800da853ecaSopenharmony_ci            return;
801da853ecaSopenharmony_ci        }
802da853ecaSopenharmony_ci        HLOGI("return stale buffer to surface, seq = %u, pts = %" PRId64 "", buffer->GetSeqNum(), pts);
803da853ecaSopenharmony_ci        inputSurface_->ReleaseBuffer(buffer, -1);
804da853ecaSopenharmony_ci    }
805da853ecaSopenharmony_ci}
806da853ecaSopenharmony_ci
807da853ecaSopenharmony_ciint32_t HEncoder::SubmitAllBuffersOwnedByUs()
808da853ecaSopenharmony_ci{
809da853ecaSopenharmony_ci    HLOGI(">>");
810da853ecaSopenharmony_ci    if (isBufferCirculating_) {
811da853ecaSopenharmony_ci        HLOGI("buffer is already circulating, no need to do again");
812da853ecaSopenharmony_ci        return AVCS_ERR_OK;
813da853ecaSopenharmony_ci    }
814da853ecaSopenharmony_ci    int32_t ret = SubmitOutputBuffersToOmxNode();
815da853ecaSopenharmony_ci    if (ret != AVCS_ERR_OK) {
816da853ecaSopenharmony_ci        return ret;
817da853ecaSopenharmony_ci    }
818da853ecaSopenharmony_ci    if (inputSurface_) {
819da853ecaSopenharmony_ci        ClearDirtyList();
820da853ecaSopenharmony_ci        sptr<IBufferConsumerListener> listener = new EncoderBuffersConsumerListener(this);
821da853ecaSopenharmony_ci        inputSurface_->RegisterConsumerListener(listener);
822da853ecaSopenharmony_ci        SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
823da853ecaSopenharmony_ci    } else {
824da853ecaSopenharmony_ci        for (BufferInfo &info : inputBufferPool_) {
825da853ecaSopenharmony_ci            if (info.owner == BufferOwner::OWNED_BY_US) {
826da853ecaSopenharmony_ci                NotifyUserToFillThisInBuffer(info);
827da853ecaSopenharmony_ci            }
828da853ecaSopenharmony_ci        }
829da853ecaSopenharmony_ci    }
830da853ecaSopenharmony_ci
831da853ecaSopenharmony_ci    isBufferCirculating_ = true;
832da853ecaSopenharmony_ci    return AVCS_ERR_OK;
833da853ecaSopenharmony_ci}
834da853ecaSopenharmony_ci
835da853ecaSopenharmony_cisptr<Surface> HEncoder::OnCreateInputSurface()
836da853ecaSopenharmony_ci{
837da853ecaSopenharmony_ci    if (inputSurface_) {
838da853ecaSopenharmony_ci        HLOGE("inputSurface_ already exists");
839da853ecaSopenharmony_ci        return nullptr;
840da853ecaSopenharmony_ci    }
841da853ecaSopenharmony_ci
842da853ecaSopenharmony_ci    sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("HEncoderSurface");
843da853ecaSopenharmony_ci    if (consumerSurface == nullptr) {
844da853ecaSopenharmony_ci        HLOGE("Create the surface consummer fail");
845da853ecaSopenharmony_ci        return nullptr;
846da853ecaSopenharmony_ci    }
847da853ecaSopenharmony_ci    GSError err = consumerSurface->SetDefaultUsage(SURFACE_MODE_CONSUMER_USAGE);
848da853ecaSopenharmony_ci    if (err == GSERROR_OK) {
849da853ecaSopenharmony_ci        HLOGI("set consumer usage 0x%x succ", SURFACE_MODE_CONSUMER_USAGE);
850da853ecaSopenharmony_ci    } else {
851da853ecaSopenharmony_ci        HLOGW("set consumer usage 0x%x failed", SURFACE_MODE_CONSUMER_USAGE);
852da853ecaSopenharmony_ci    }
853da853ecaSopenharmony_ci
854da853ecaSopenharmony_ci    sptr<IBufferProducer> producer = consumerSurface->GetProducer();
855da853ecaSopenharmony_ci    if (producer == nullptr) {
856da853ecaSopenharmony_ci        HLOGE("Get the surface producer fail");
857da853ecaSopenharmony_ci        return nullptr;
858da853ecaSopenharmony_ci    }
859da853ecaSopenharmony_ci
860da853ecaSopenharmony_ci    sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
861da853ecaSopenharmony_ci    if (producerSurface == nullptr) {
862da853ecaSopenharmony_ci        HLOGE("CreateSurfaceAsProducer fail");
863da853ecaSopenharmony_ci        return nullptr;
864da853ecaSopenharmony_ci    }
865da853ecaSopenharmony_ci
866da853ecaSopenharmony_ci    inputSurface_ = consumerSurface;
867da853ecaSopenharmony_ci    if (inBufferCnt_ > inputSurface_->GetQueueSize()) {
868da853ecaSopenharmony_ci        inputSurface_->SetQueueSize(inBufferCnt_);
869da853ecaSopenharmony_ci    }
870da853ecaSopenharmony_ci    HLOGI("succ, surface id = %" PRIu64 ", queue size %u",
871da853ecaSopenharmony_ci          inputSurface_->GetUniqueId(), inputSurface_->GetQueueSize());
872da853ecaSopenharmony_ci    return producerSurface;
873da853ecaSopenharmony_ci}
874da853ecaSopenharmony_ci
875da853ecaSopenharmony_ciint32_t HEncoder::OnSetInputSurface(sptr<Surface> &inputSurface)
876da853ecaSopenharmony_ci{
877da853ecaSopenharmony_ci    if (inputSurface_) {
878da853ecaSopenharmony_ci        HLOGW("inputSurface_ already exists");
879da853ecaSopenharmony_ci    }
880da853ecaSopenharmony_ci
881da853ecaSopenharmony_ci    if (inputSurface == nullptr) {
882da853ecaSopenharmony_ci        HLOGE("surface is null");
883da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
884da853ecaSopenharmony_ci    }
885da853ecaSopenharmony_ci    if (!inputSurface->IsConsumer()) {
886da853ecaSopenharmony_ci        HLOGE("expect consumer surface");
887da853ecaSopenharmony_ci        return AVCS_ERR_INVALID_VAL;
888da853ecaSopenharmony_ci    }
889da853ecaSopenharmony_ci
890da853ecaSopenharmony_ci    inputSurface_ = inputSurface;
891da853ecaSopenharmony_ci    if (inBufferCnt_ > inputSurface_->GetQueueSize()) {
892da853ecaSopenharmony_ci        inputSurface_->SetQueueSize(inBufferCnt_);
893da853ecaSopenharmony_ci    }
894da853ecaSopenharmony_ci    HLOGI("succ");
895da853ecaSopenharmony_ci    return AVCS_ERR_OK;
896da853ecaSopenharmony_ci}
897da853ecaSopenharmony_ci
898da853ecaSopenharmony_civoid HEncoder::WrapPerFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
899da853ecaSopenharmony_ci                                              const shared_ptr<Media::Meta> &meta)
900da853ecaSopenharmony_ci{
901da853ecaSopenharmony_ci    omxBuffer->alongParam.clear();
902da853ecaSopenharmony_ci    WrapLTRParamIntoOmxBuffer(omxBuffer, meta);
903da853ecaSopenharmony_ci    WrapRequestIFrameParamIntoOmxBuffer(omxBuffer, meta);
904da853ecaSopenharmony_ci    WrapQPRangeParamIntoOmxBuffer(omxBuffer, meta);
905da853ecaSopenharmony_ci    WrapStartQPIntoOmxBuffer(omxBuffer, meta);
906da853ecaSopenharmony_ci    WrapIsSkipFrameIntoOmxBuffer(omxBuffer, meta);
907da853ecaSopenharmony_ci    meta->Clear();
908da853ecaSopenharmony_ci}
909da853ecaSopenharmony_ci
910da853ecaSopenharmony_civoid HEncoder::WrapLTRParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
911da853ecaSopenharmony_ci                                         const shared_ptr<Media::Meta> &meta)
912da853ecaSopenharmony_ci{
913da853ecaSopenharmony_ci    if (!enableLTR_) {
914da853ecaSopenharmony_ci        return;
915da853ecaSopenharmony_ci    }
916da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, OMX_IndexParamLTR);
917da853ecaSopenharmony_ci    CodecLTRPerFrameParam param;
918da853ecaSopenharmony_ci    bool markLTR = false;
919da853ecaSopenharmony_ci    meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_MARK_LTR, markLTR);
920da853ecaSopenharmony_ci    param.markAsLTR = markLTR;
921da853ecaSopenharmony_ci    int32_t useLtrPoc = 0;
922da853ecaSopenharmony_ci    param.useLTR = meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrPoc);
923da853ecaSopenharmony_ci    param.useLTRPoc = static_cast<uint32_t>(useLtrPoc);
924da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, param);
925da853ecaSopenharmony_ci}
926da853ecaSopenharmony_ci
927da853ecaSopenharmony_civoid HEncoder::WrapRequestIFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
928da853ecaSopenharmony_ci                                                   const shared_ptr<Media::Meta> &meta)
929da853ecaSopenharmony_ci{
930da853ecaSopenharmony_ci    bool requestIFrame = false;
931da853ecaSopenharmony_ci    meta->GetData(OHOS::Media::Tag::VIDEO_REQUEST_I_FRAME, requestIFrame);
932da853ecaSopenharmony_ci    if (!requestIFrame) {
933da853ecaSopenharmony_ci        return;
934da853ecaSopenharmony_ci    }
935da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, OMX_IndexConfigVideoIntraVOPRefresh);
936da853ecaSopenharmony_ci    OMX_CONFIG_INTRAREFRESHVOPTYPE params;
937da853ecaSopenharmony_ci    InitOMXParam(params);
938da853ecaSopenharmony_ci    params.nPortIndex = OMX_DirOutput;
939da853ecaSopenharmony_ci    params.IntraRefreshVOP = OMX_TRUE;
940da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, params);
941da853ecaSopenharmony_ci    HLOGI("pts=%" PRId64 ", requestIFrame", omxBuffer->pts);
942da853ecaSopenharmony_ci}
943da853ecaSopenharmony_ci
944da853ecaSopenharmony_civoid HEncoder::WrapQPRangeParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
945da853ecaSopenharmony_ci                                             const shared_ptr<Media::Meta> &meta)
946da853ecaSopenharmony_ci{
947da853ecaSopenharmony_ci    int32_t minQp;
948da853ecaSopenharmony_ci    int32_t maxQp;
949da853ecaSopenharmony_ci    if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) ||
950da853ecaSopenharmony_ci        !meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) {
951da853ecaSopenharmony_ci        return;
952da853ecaSopenharmony_ci    }
953da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPRange);
954da853ecaSopenharmony_ci    CodecQPRangeParam param;
955da853ecaSopenharmony_ci    InitOMXParamExt(param);
956da853ecaSopenharmony_ci    param.minQp = static_cast<uint32_t>(minQp);
957da853ecaSopenharmony_ci    param.maxQp = static_cast<uint32_t>(maxQp);
958da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, param);
959da853ecaSopenharmony_ci    HLOGI("pts=%" PRId64 ", qp=(%d~%d)", omxBuffer->pts, minQp, maxQp);
960da853ecaSopenharmony_ci}
961da853ecaSopenharmony_ci
962da853ecaSopenharmony_civoid HEncoder::WrapStartQPIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
963da853ecaSopenharmony_ci                                        const shared_ptr<Media::Meta> &meta)
964da853ecaSopenharmony_ci{
965da853ecaSopenharmony_ci    int32_t startQp {};
966da853ecaSopenharmony_ci    if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_START, startQp)) {
967da853ecaSopenharmony_ci        return;
968da853ecaSopenharmony_ci    }
969da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPStsart);
970da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, startQp);
971da853ecaSopenharmony_ci}
972da853ecaSopenharmony_ci
973da853ecaSopenharmony_civoid HEncoder::WrapIsSkipFrameIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
974da853ecaSopenharmony_ci                                            const shared_ptr<Media::Meta> &meta)
975da853ecaSopenharmony_ci{
976da853ecaSopenharmony_ci    bool isSkip {};
977da853ecaSopenharmony_ci    if (!meta->GetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_SKIP, isSkip)) {
978da853ecaSopenharmony_ci        return;
979da853ecaSopenharmony_ci    }
980da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, OMX_IndexParamSkipFrame);
981da853ecaSopenharmony_ci    AppendToVector(omxBuffer->alongParam, isSkip);
982da853ecaSopenharmony_ci}
983da853ecaSopenharmony_ci
984da853ecaSopenharmony_civoid HEncoder::DealWithResolutionChange(uint32_t newWidth, uint32_t newHeight)
985da853ecaSopenharmony_ci{
986da853ecaSopenharmony_ci    if (width_ != newWidth || height_ != newHeight) {
987da853ecaSopenharmony_ci        HLOGI("resolution changed, %ux%u -> %ux%u", width_, height_, newWidth, newHeight);
988da853ecaSopenharmony_ci        width_ = newWidth;
989da853ecaSopenharmony_ci        height_ = newHeight;
990da853ecaSopenharmony_ci        outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
991da853ecaSopenharmony_ci        outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
992da853ecaSopenharmony_ci        outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
993da853ecaSopenharmony_ci        outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
994da853ecaSopenharmony_ci        HLOGI("output format changed: %s", outputFormat_->Stringify().c_str());
995da853ecaSopenharmony_ci        callback_->OnOutputFormatChanged(*(outputFormat_.get()));
996da853ecaSopenharmony_ci    }
997da853ecaSopenharmony_ci}
998da853ecaSopenharmony_ci
999da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameParamFromOmxBuffer(
1000da853ecaSopenharmony_ci    const shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, shared_ptr<Media::Meta> &meta)
1001da853ecaSopenharmony_ci{
1002da853ecaSopenharmony_ci    meta->Clear();
1003da853ecaSopenharmony_ci    BinaryReader reader(static_cast<uint8_t*>(omxBuffer->alongParam.data()), omxBuffer->alongParam.size());
1004da853ecaSopenharmony_ci    int* index = nullptr;
1005da853ecaSopenharmony_ci    while ((index = reader.Read<int>()) != nullptr) {
1006da853ecaSopenharmony_ci        switch (*index) {
1007da853ecaSopenharmony_ci            case OMX_IndexConfigCommonOutputSize: {
1008da853ecaSopenharmony_ci                auto *param = reader.Read<OMX_FRAMESIZETYPE>();
1009da853ecaSopenharmony_ci                IF_TRUE_RETURN_VOID(param == nullptr);
1010da853ecaSopenharmony_ci                DealWithResolutionChange(param->nWidth, param->nHeight);
1011da853ecaSopenharmony_ci                break;
1012da853ecaSopenharmony_ci            }
1013da853ecaSopenharmony_ci            case OMX_IndexParamEncOutQp:
1014da853ecaSopenharmony_ci                ExtractPerFrameAveQpParam(reader, meta);
1015da853ecaSopenharmony_ci                break;
1016da853ecaSopenharmony_ci            case OMX_IndexParamEncOutMse:
1017da853ecaSopenharmony_ci                ExtractPerFrameMSEParam(reader, meta);
1018da853ecaSopenharmony_ci                break;
1019da853ecaSopenharmony_ci            case OMX_IndexParamEncOutLTR:
1020da853ecaSopenharmony_ci                ExtractPerFrameLTRParam(reader, meta);
1021da853ecaSopenharmony_ci                break;
1022da853ecaSopenharmony_ci            case OMX_IndexParamEncOutFrameLayer:
1023da853ecaSopenharmony_ci                ExtractPerFrameLayerParam(reader, meta);
1024da853ecaSopenharmony_ci                break;
1025da853ecaSopenharmony_ci            case OMX_IndexParamEncOutRealBitrate:
1026da853ecaSopenharmony_ci                ExtractPerFrameRealBitrateParam(reader, meta);
1027da853ecaSopenharmony_ci                break;
1028da853ecaSopenharmony_ci            case OMX_IndexParamEncOutFrameQp:
1029da853ecaSopenharmony_ci                ExtractPerFrameFrameQpParam(reader, meta);
1030da853ecaSopenharmony_ci                break;
1031da853ecaSopenharmony_ci            case OMX_IndexParamEncOutMad:
1032da853ecaSopenharmony_ci                ExtractPerFrameMadParam(reader, meta);
1033da853ecaSopenharmony_ci                break;
1034da853ecaSopenharmony_ci            case OMX_IndexParamEncOutIRatio:
1035da853ecaSopenharmony_ci                ExtractPerFrameIRitioParam(reader, meta);
1036da853ecaSopenharmony_ci                break;
1037da853ecaSopenharmony_ci            default:
1038da853ecaSopenharmony_ci                break;
1039da853ecaSopenharmony_ci        }
1040da853ecaSopenharmony_ci    }
1041da853ecaSopenharmony_ci    omxBuffer->alongParam.clear();
1042da853ecaSopenharmony_ci    if (debugMode_) {
1043da853ecaSopenharmony_ci        auto metaStr = StringifyMeta(meta);
1044da853ecaSopenharmony_ci        HLOGI("%s", metaStr.c_str());
1045da853ecaSopenharmony_ci    }
1046da853ecaSopenharmony_ci}
1047da853ecaSopenharmony_ci
1048da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameLTRParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta)
1049da853ecaSopenharmony_ci{
1050da853ecaSopenharmony_ci    auto *ltrParam = reader.Read<CodecEncOutLTRParam>();
1051da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(ltrParam == nullptr);
1052da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_LTR, ltrParam->isLTR);
1053da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_POC, static_cast<int32_t>(ltrParam->poc));
1054da853ecaSopenharmony_ci}
1055da853ecaSopenharmony_ci
1056da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameMadParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta)
1057da853ecaSopenharmony_ci{
1058da853ecaSopenharmony_ci    auto *madParam = reader.Read<CodecEncOutMadParam>();
1059da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(madParam == nullptr);
1060da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADI, madParam->frameMadi);
1061da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADP, madParam->frameMadp);
1062da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_SUM_MADI, madParam->sumMadi);
1063da853ecaSopenharmony_ci}
1064da853ecaSopenharmony_ci
1065da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameRealBitrateParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1066da853ecaSopenharmony_ci{
1067da853ecaSopenharmony_ci    auto *realBitrate = reader.Read<OMX_S32>();
1068da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(realBitrate == nullptr);
1069da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_REAL_BITRATE, *realBitrate);
1070da853ecaSopenharmony_ci}
1071da853ecaSopenharmony_ci
1072da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameFrameQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1073da853ecaSopenharmony_ci{
1074da853ecaSopenharmony_ci    auto *frameQp = reader.Read<OMX_S32>();
1075da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(frameQp == nullptr);
1076da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_QP, *frameQp);
1077da853ecaSopenharmony_ci}
1078da853ecaSopenharmony_ci
1079da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameIRitioParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1080da853ecaSopenharmony_ci{
1081da853ecaSopenharmony_ci    auto *iRatio = reader.Read<OMX_S32>();
1082da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(iRatio == nullptr);
1083da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_I_RATIO, *iRatio);
1084da853ecaSopenharmony_ci}
1085da853ecaSopenharmony_ci
1086da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameAveQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1087da853ecaSopenharmony_ci{
1088da853ecaSopenharmony_ci    auto *averageQp = reader.Read<OMX_S32>();
1089da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(averageQp == nullptr);
1090da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_AVERAGE, *averageQp);
1091da853ecaSopenharmony_ci}
1092da853ecaSopenharmony_ci
1093da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameMSEParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1094da853ecaSopenharmony_ci{
1095da853ecaSopenharmony_ci    auto *averageMseLcu = reader.Read<double>();
1096da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(averageMseLcu == nullptr);
1097da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_MSE, *averageMseLcu);
1098da853ecaSopenharmony_ci}
1099da853ecaSopenharmony_ci
1100da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameLayerParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1101da853ecaSopenharmony_ci{
1102da853ecaSopenharmony_ci    auto *frameLayer = reader.Read<OMX_S32>();
1103da853ecaSopenharmony_ci    IF_TRUE_RETURN_VOID(frameLayer == nullptr);
1104da853ecaSopenharmony_ci    meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_TEMPORAL_ID, *frameLayer);
1105da853ecaSopenharmony_ci}
1106da853ecaSopenharmony_ci
1107da853ecaSopenharmony_ciint32_t HEncoder::AllocInBufsForDynamicSurfaceBuf()
1108da853ecaSopenharmony_ci{
1109da853ecaSopenharmony_ci    inputBufferPool_.clear();
1110da853ecaSopenharmony_ci    for (uint32_t i = 0; i < inBufferCnt_; ++i) {
1111da853ecaSopenharmony_ci        shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer = DynamicSurfaceBufferToOmxBuffer();
1112da853ecaSopenharmony_ci        shared_ptr<CodecHDI::OmxCodecBuffer> outBuffer = make_shared<CodecHDI::OmxCodecBuffer>();
1113da853ecaSopenharmony_ci        int32_t ret = compNode_->UseBuffer(OMX_DirInput, *omxBuffer, *outBuffer);
1114da853ecaSopenharmony_ci        if (ret != HDF_SUCCESS) {
1115da853ecaSopenharmony_ci            HLOGE("Failed to UseBuffer on input port");
1116da853ecaSopenharmony_ci            return AVCS_ERR_UNKNOWN;
1117da853ecaSopenharmony_ci        }
1118da853ecaSopenharmony_ci        BufferInfo info {};
1119da853ecaSopenharmony_ci        info.isInput = true;
1120da853ecaSopenharmony_ci        info.owner = BufferOwner::OWNED_BY_SURFACE;
1121da853ecaSopenharmony_ci        info.surfaceBuffer = nullptr;
1122da853ecaSopenharmony_ci        info.avBuffer = AVBuffer::CreateAVBuffer();
1123da853ecaSopenharmony_ci        info.omxBuffer = outBuffer;
1124da853ecaSopenharmony_ci        info.bufferId = outBuffer->bufferId;
1125da853ecaSopenharmony_ci        inputBufferPool_.push_back(info);
1126da853ecaSopenharmony_ci    }
1127da853ecaSopenharmony_ci
1128da853ecaSopenharmony_ci    return AVCS_ERR_OK;
1129da853ecaSopenharmony_ci}
1130da853ecaSopenharmony_ci
1131da853ecaSopenharmony_civoid HEncoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i)
1132da853ecaSopenharmony_ci{
1133da853ecaSopenharmony_ci    vector<BufferInfo> &pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
1134da853ecaSopenharmony_ci    if (i >= pool.size()) {
1135da853ecaSopenharmony_ci        return;
1136da853ecaSopenharmony_ci    }
1137da853ecaSopenharmony_ci    const BufferInfo &info = pool[i];
1138da853ecaSopenharmony_ci    FreeOmxBuffer(portIndex, info);
1139da853ecaSopenharmony_ci    ReduceOwner((portIndex == OMX_DirInput), info.owner);
1140da853ecaSopenharmony_ci    pool.erase(pool.begin() + i);
1141da853ecaSopenharmony_ci}
1142da853ecaSopenharmony_ci
1143da853ecaSopenharmony_civoid HEncoder::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode)
1144da853ecaSopenharmony_ci{
1145da853ecaSopenharmony_ci    if (inputSurface_ && !enableSurfaceModeInputCb_) {
1146da853ecaSopenharmony_ci        HLOGE("cannot queue input on surface mode");
1147da853ecaSopenharmony_ci        ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
1148da853ecaSopenharmony_ci        return;
1149da853ecaSopenharmony_ci    }
1150da853ecaSopenharmony_ci    // buffer mode or surface callback mode
1151da853ecaSopenharmony_ci    uint32_t bufferId = 0;
1152da853ecaSopenharmony_ci    (void)msg.param->GetValue(BUFFER_ID, bufferId);
1153da853ecaSopenharmony_ci    SCOPED_TRACE_WITH_ID(bufferId);
1154da853ecaSopenharmony_ci    BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId);
1155da853ecaSopenharmony_ci    if (bufferInfo == nullptr) {
1156da853ecaSopenharmony_ci        ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1157da853ecaSopenharmony_ci        return;
1158da853ecaSopenharmony_ci    }
1159da853ecaSopenharmony_ci    if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) {
1160da853ecaSopenharmony_ci        HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner));
1161da853ecaSopenharmony_ci        ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1162da853ecaSopenharmony_ci        return;
1163da853ecaSopenharmony_ci    }
1164da853ecaSopenharmony_ci
1165da853ecaSopenharmony_ci    bool discard = false;
1166da853ecaSopenharmony_ci    if (inputSurface_ && bufferInfo->avBuffer->meta_->GetData(
1167da853ecaSopenharmony_ci        OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_DISCARD, discard) && discard) {
1168da853ecaSopenharmony_ci        HLOGI("inBufId = %u, discard by user, pts = %" PRId64, bufferId, bufferInfo->avBuffer->pts_);
1169da853ecaSopenharmony_ci        bufferInfo->avBuffer->meta_->Clear();
1170da853ecaSopenharmony_ci        ResetSlot(*bufferInfo);
1171da853ecaSopenharmony_ci        ReplyErrorCode(msg.id, AVCS_ERR_OK);
1172da853ecaSopenharmony_ci        return;
1173da853ecaSopenharmony_ci    }
1174da853ecaSopenharmony_ci    ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US);
1175da853ecaSopenharmony_ci    WrapSurfaceBufferToSlot(*bufferInfo, bufferInfo->surfaceBuffer, bufferInfo->avBuffer->pts_,
1176da853ecaSopenharmony_ci        UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_)));
1177da853ecaSopenharmony_ci    WrapPerFrameParamIntoOmxBuffer(bufferInfo->omxBuffer, bufferInfo->avBuffer->meta_);
1178da853ecaSopenharmony_ci    ReplyErrorCode(msg.id, AVCS_ERR_OK);
1179da853ecaSopenharmony_ci    int32_t err = HCodec::OnQueueInputBuffer(mode, bufferInfo);
1180da853ecaSopenharmony_ci    if (err != AVCS_ERR_OK) {
1181da853ecaSopenharmony_ci        ResetSlot(*bufferInfo);
1182da853ecaSopenharmony_ci        callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR);
1183da853ecaSopenharmony_ci    }
1184da853ecaSopenharmony_ci}
1185da853ecaSopenharmony_ci
1186da853ecaSopenharmony_civoid HEncoder::OnGetBufferFromSurface(const ParamSP& param)
1187da853ecaSopenharmony_ci{
1188da853ecaSopenharmony_ci    if (GetOneBufferFromSurface()) {
1189da853ecaSopenharmony_ci        TraverseAvaliableBuffers();
1190da853ecaSopenharmony_ci    }
1191da853ecaSopenharmony_ci}
1192da853ecaSopenharmony_ci
1193da853ecaSopenharmony_cibool HEncoder::GetOneBufferFromSurface()
1194da853ecaSopenharmony_ci{
1195da853ecaSopenharmony_ci    SCOPED_TRACE();
1196da853ecaSopenharmony_ci    InSurfaceBufferEntry entry{};
1197da853ecaSopenharmony_ci    entry.item = make_shared<BufferItem>();
1198da853ecaSopenharmony_ci    GSError ret = inputSurface_->AcquireBuffer(
1199da853ecaSopenharmony_ci        entry.item->buffer, entry.item->fence, entry.pts, entry.item->damage);
1200da853ecaSopenharmony_ci    if (ret != GSERROR_OK || entry.item->buffer == nullptr) {
1201da853ecaSopenharmony_ci        return false;
1202da853ecaSopenharmony_ci    }
1203da853ecaSopenharmony_ci    if (!CheckBufPixFmt(entry.item->buffer)) {
1204da853ecaSopenharmony_ci        return false;
1205da853ecaSopenharmony_ci    }
1206da853ecaSopenharmony_ci    entry.item->generation = ++currGeneration_;
1207da853ecaSopenharmony_ci    entry.item->surface = inputSurface_;
1208da853ecaSopenharmony_ci    avaliableBuffers_.push_back(entry);
1209da853ecaSopenharmony_ci    newestBuffer_ = entry;
1210da853ecaSopenharmony_ci    HLOGD("generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", now list size = %zu",
1211da853ecaSopenharmony_ci          entry.item->generation, entry.item->buffer->GetSeqNum(), entry.pts, avaliableBuffers_.size());
1212da853ecaSopenharmony_ci    if (repeatUs_ != 0) {
1213da853ecaSopenharmony_ci        SendRepeatMsg(entry.item->generation);
1214da853ecaSopenharmony_ci    }
1215da853ecaSopenharmony_ci    return true;
1216da853ecaSopenharmony_ci}
1217da853ecaSopenharmony_ci
1218da853ecaSopenharmony_civoid HEncoder::SendRepeatMsg(uint64_t generation)
1219da853ecaSopenharmony_ci{
1220da853ecaSopenharmony_ci    ParamSP param = make_shared<ParamBundle>();
1221da853ecaSopenharmony_ci    param->SetValue("generation", generation);
1222da853ecaSopenharmony_ci    SendAsyncMsg(MsgWhat::CHECK_IF_REPEAT, param, repeatUs_);
1223da853ecaSopenharmony_ci}
1224da853ecaSopenharmony_ci
1225da853ecaSopenharmony_civoid HEncoder::RepeatIfNecessary(const ParamSP& param)
1226da853ecaSopenharmony_ci{
1227da853ecaSopenharmony_ci    uint64_t generation = 0;
1228da853ecaSopenharmony_ci    param->GetValue("generation", generation);
1229da853ecaSopenharmony_ci    if (inputPortEos_ || (repeatUs_ == 0) || newestBuffer_.item == nullptr ||
1230da853ecaSopenharmony_ci        newestBuffer_.item->generation != generation) {
1231da853ecaSopenharmony_ci        return;
1232da853ecaSopenharmony_ci    }
1233da853ecaSopenharmony_ci    if (repeatMaxCnt_ > 0 && newestBuffer_.repeatTimes >= repeatMaxCnt_) {
1234da853ecaSopenharmony_ci        HLOGD("stop repeat generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", which has been repeated %d times",
1235da853ecaSopenharmony_ci              generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newestBuffer_.repeatTimes);
1236da853ecaSopenharmony_ci        return;
1237da853ecaSopenharmony_ci    }
1238da853ecaSopenharmony_ci    if (avaliableBuffers_.size() >= MAX_LIST_SIZE) {
1239da853ecaSopenharmony_ci        HLOGW("stop repeat, list size to big: %zu", avaliableBuffers_.size());
1240da853ecaSopenharmony_ci        return;
1241da853ecaSopenharmony_ci    }
1242da853ecaSopenharmony_ci    int64_t newPts = newestBuffer_.pts + static_cast<int64_t>(repeatUs_);
1243da853ecaSopenharmony_ci    HLOGD("generation = %" PRIu64 ", seq = %u, pts %" PRId64 " -> %" PRId64,
1244da853ecaSopenharmony_ci          generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newPts);
1245da853ecaSopenharmony_ci    newestBuffer_.pts = newPts;
1246da853ecaSopenharmony_ci    newestBuffer_.repeatTimes++;
1247da853ecaSopenharmony_ci    avaliableBuffers_.push_back(newestBuffer_);
1248da853ecaSopenharmony_ci    SendRepeatMsg(generation);
1249da853ecaSopenharmony_ci    TraverseAvaliableBuffers();
1250da853ecaSopenharmony_ci}
1251da853ecaSopenharmony_ci
1252da853ecaSopenharmony_civoid HEncoder::TraverseAvaliableBuffers()
1253da853ecaSopenharmony_ci{
1254da853ecaSopenharmony_ci    while (!avaliableBuffers_.empty()) {
1255da853ecaSopenharmony_ci        auto it = find_if(inputBufferPool_.begin(), inputBufferPool_.end(),
1256da853ecaSopenharmony_ci                          [](const BufferInfo &info) { return info.owner == BufferOwner::OWNED_BY_SURFACE; });
1257da853ecaSopenharmony_ci        if (it == inputBufferPool_.end()) {
1258da853ecaSopenharmony_ci            HLOGD("buffer cnt = %zu, but no avaliable slot", avaliableBuffers_.size());
1259da853ecaSopenharmony_ci            return;
1260da853ecaSopenharmony_ci        }
1261da853ecaSopenharmony_ci        InSurfaceBufferEntry entry = avaliableBuffers_.front();
1262da853ecaSopenharmony_ci        avaliableBuffers_.pop_front();
1263da853ecaSopenharmony_ci        SubmitOneBuffer(entry, *it);
1264da853ecaSopenharmony_ci    }
1265da853ecaSopenharmony_ci}
1266da853ecaSopenharmony_ci
1267da853ecaSopenharmony_civoid HEncoder::TraverseAvaliableSlots()
1268da853ecaSopenharmony_ci{
1269da853ecaSopenharmony_ci    for (BufferInfo& info : inputBufferPool_) {
1270da853ecaSopenharmony_ci        if (info.owner != BufferOwner::OWNED_BY_SURFACE) {
1271da853ecaSopenharmony_ci            continue;
1272da853ecaSopenharmony_ci        }
1273da853ecaSopenharmony_ci        if (avaliableBuffers_.empty() && !GetOneBufferFromSurface()) {
1274da853ecaSopenharmony_ci            HLOGD("slot %u is avaliable, but no buffer", info.bufferId);
1275da853ecaSopenharmony_ci            return;
1276da853ecaSopenharmony_ci        }
1277da853ecaSopenharmony_ci        InSurfaceBufferEntry entry = avaliableBuffers_.front();
1278da853ecaSopenharmony_ci        avaliableBuffers_.pop_front();
1279da853ecaSopenharmony_ci        SubmitOneBuffer(entry, info);
1280da853ecaSopenharmony_ci    }
1281da853ecaSopenharmony_ci}
1282da853ecaSopenharmony_ci
1283da853ecaSopenharmony_civoid HEncoder::SubmitOneBuffer(InSurfaceBufferEntry& entry, BufferInfo &info)
1284da853ecaSopenharmony_ci{
1285da853ecaSopenharmony_ci    if (entry.item == nullptr) {
1286da853ecaSopenharmony_ci        ChangeOwner(info, BufferOwner::OWNED_BY_US);
1287da853ecaSopenharmony_ci        HLOGI("got input eos");
1288da853ecaSopenharmony_ci        inputPortEos_ = true;
1289da853ecaSopenharmony_ci        info.omxBuffer->flag = OMX_BUFFERFLAG_EOS;
1290da853ecaSopenharmony_ci        info.omxBuffer->bufferhandle = nullptr;
1291da853ecaSopenharmony_ci        info.omxBuffer->filledLen = 0;
1292da853ecaSopenharmony_ci        info.surfaceBuffer = nullptr;
1293da853ecaSopenharmony_ci        NotifyOmxToEmptyThisInBuffer(info);
1294da853ecaSopenharmony_ci        return;
1295da853ecaSopenharmony_ci    }
1296da853ecaSopenharmony_ci    if (!WaitFence(entry.item->fence)) {
1297da853ecaSopenharmony_ci        return;
1298da853ecaSopenharmony_ci    }
1299da853ecaSopenharmony_ci    ChangeOwner(info, BufferOwner::OWNED_BY_US);
1300da853ecaSopenharmony_ci    WrapSurfaceBufferToSlot(info, entry.item->buffer, entry.pts, 0);
1301da853ecaSopenharmony_ci    encodingBuffers_[info.bufferId] = entry;
1302da853ecaSopenharmony_ci    if (enableSurfaceModeInputCb_) {
1303da853ecaSopenharmony_ci        info.avBuffer->pts_ = entry.pts;
1304da853ecaSopenharmony_ci        NotifyUserToFillThisInBuffer(info);
1305da853ecaSopenharmony_ci    } else {
1306da853ecaSopenharmony_ci        int32_t err = NotifyOmxToEmptyThisInBuffer(info);
1307da853ecaSopenharmony_ci        if (err != AVCS_ERR_OK) {
1308da853ecaSopenharmony_ci            ResetSlot(info);
1309da853ecaSopenharmony_ci            callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR);
1310da853ecaSopenharmony_ci        }
1311da853ecaSopenharmony_ci    }
1312da853ecaSopenharmony_ci}
1313da853ecaSopenharmony_ci
1314da853ecaSopenharmony_civoid HEncoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode)
1315da853ecaSopenharmony_ci{
1316da853ecaSopenharmony_ci    SCOPED_TRACE_WITH_ID(bufferId);
1317da853ecaSopenharmony_ci    BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId);
1318da853ecaSopenharmony_ci    if (info == nullptr) {
1319da853ecaSopenharmony_ci        HLOGE("unknown buffer id %u", bufferId);
1320da853ecaSopenharmony_ci        return;
1321da853ecaSopenharmony_ci    }
1322da853ecaSopenharmony_ci    if (info->owner != BufferOwner::OWNED_BY_OMX) {
1323da853ecaSopenharmony_ci        HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info->owner));
1324da853ecaSopenharmony_ci        return;
1325da853ecaSopenharmony_ci    }
1326da853ecaSopenharmony_ci    if (inputSurface_) {
1327da853ecaSopenharmony_ci        ResetSlot(*info);
1328da853ecaSopenharmony_ci        if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
1329da853ecaSopenharmony_ci            TraverseAvaliableSlots();
1330da853ecaSopenharmony_ci        }
1331da853ecaSopenharmony_ci    } else {
1332da853ecaSopenharmony_ci        ChangeOwner(*info, BufferOwner::OWNED_BY_US);
1333da853ecaSopenharmony_ci        if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
1334da853ecaSopenharmony_ci            NotifyUserToFillThisInBuffer(*info);
1335da853ecaSopenharmony_ci        }
1336da853ecaSopenharmony_ci    }
1337da853ecaSopenharmony_ci}
1338da853ecaSopenharmony_ci
1339da853ecaSopenharmony_civoid HEncoder::ResetSlot(BufferInfo& info)
1340da853ecaSopenharmony_ci{
1341da853ecaSopenharmony_ci    ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE);
1342da853ecaSopenharmony_ci    encodingBuffers_.erase(info.bufferId);
1343da853ecaSopenharmony_ci    info.surfaceBuffer = nullptr;
1344da853ecaSopenharmony_ci}
1345da853ecaSopenharmony_ci
1346da853ecaSopenharmony_civoid HEncoder::EncoderBuffersConsumerListener::OnBufferAvailable()
1347da853ecaSopenharmony_ci{
1348da853ecaSopenharmony_ci    codec_->SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
1349da853ecaSopenharmony_ci}
1350da853ecaSopenharmony_ci
1351da853ecaSopenharmony_civoid HEncoder::OnSignalEndOfInputStream(const MsgInfo &msg)
1352da853ecaSopenharmony_ci{
1353da853ecaSopenharmony_ci    if (inputSurface_ == nullptr) {
1354da853ecaSopenharmony_ci        HLOGE("can only be called in surface mode");
1355da853ecaSopenharmony_ci        ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
1356da853ecaSopenharmony_ci        return;
1357da853ecaSopenharmony_ci    }
1358da853ecaSopenharmony_ci    ReplyErrorCode(msg.id, AVCS_ERR_OK);
1359da853ecaSopenharmony_ci    avaliableBuffers_.push_back(InSurfaceBufferEntry {});
1360da853ecaSopenharmony_ci    TraverseAvaliableBuffers();
1361da853ecaSopenharmony_ci}
1362da853ecaSopenharmony_ci
1363da853ecaSopenharmony_civoid HEncoder::OnEnterUninitializedState()
1364da853ecaSopenharmony_ci{
1365da853ecaSopenharmony_ci    if (inputSurface_) {
1366da853ecaSopenharmony_ci        inputSurface_->UnregisterConsumerListener();
1367da853ecaSopenharmony_ci    }
1368da853ecaSopenharmony_ci    avaliableBuffers_.clear();
1369da853ecaSopenharmony_ci    newestBuffer_.item.reset();
1370da853ecaSopenharmony_ci    encodingBuffers_.clear();
1371da853ecaSopenharmony_ci}
1372da853ecaSopenharmony_ci
1373da853ecaSopenharmony_ciHEncoder::BufferItem::~BufferItem()
1374da853ecaSopenharmony_ci{
1375da853ecaSopenharmony_ci    if (surface && buffer) {
1376da853ecaSopenharmony_ci        LOGD("release seq = %u", buffer->GetSeqNum());
1377da853ecaSopenharmony_ci        surface->ReleaseBuffer(buffer, -1);
1378da853ecaSopenharmony_ci    }
1379da853ecaSopenharmony_ci}
1380da853ecaSopenharmony_ci
1381da853ecaSopenharmony_ci} // namespace OHOS::MediaAVCodec
1382