• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hencoder.h"
17 #include <map>
18 #include <utility>
19 #include "hdf_base.h"
20 #include "OMX_VideoExt.h"
21 #include "media_description.h"  // foundation/multimedia/av_codec/interfaces/inner_api/native/
22 #include "type_converter.h"
23 #include "hcodec_log.h"
24 #include "hcodec_dfx.h"
25 #include "hcodec_list.h"
26 #include "v4_0/codec_ext_types.h"
27 #include <algorithm>
28 #include <regex>
29 
30 namespace OHOS::MediaAVCodec {
31 using namespace std;
32 
~HEncoder()33 HEncoder::~HEncoder()
34 {
35     MsgHandleLoop::Stop();
36 }
37 
OnConfigure(const Format & format)38 int32_t HEncoder::OnConfigure(const Format &format)
39 {
40     configFormat_ = make_shared<Format>(format);
41     int32_t ret = ConfigureBufferType();
42     if (ret != AVCS_ERR_OK) {
43         return ret;
44     }
45 
46     EnableVariableFrameRate(format);
47     optional<double> frameRate = GetFrameRateFromUser(format);
48     defaultFrameRate_ = frameRate;
49     ret = ConfigBEncodeMode(format);
50     if (ret != AVCS_ERR_OK) {
51         return ret;
52     }
53     ret = SetupPort(format, frameRate);
54     if (ret != AVCS_ERR_OK) {
55         return ret;
56     }
57     ConfigureProtocol(format, frameRate);
58 
59     (void)ConfigureOutputBitrate(format);
60     (void)SetColorAspects(format);
61     (void)SetProcessName();
62     (void)SetFrameRateAdaptiveMode(format);
63     CheckIfEnableCb(format);
64     ret = SetTemperalLayer(format);
65     if (ret != AVCS_ERR_OK) {
66         return ret;
67     }
68     ret = SetLTRParam(format);
69     if (ret != AVCS_ERR_OK) {
70         return ret;
71     }
72     ret = SetQpRange(format, false);
73     if (ret != AVCS_ERR_OK) {
74         return ret;
75     }
76     ret = SetLowLatency(format);
77     if (ret != AVCS_ERR_OK) {
78         return ret;
79     }
80     ret = SetRepeat(format);
81     if (ret != AVCS_ERR_OK) {
82         return ret;
83     }
84     ret = EnableFrameQPMap(format);
85     if (ret != AVCS_ERR_OK) {
86         return ret;
87     }
88     (void)EnableEncoderParamsFeedback(format);
89     return AVCS_ERR_OK;
90 }
91 
EnableVariableFrameRate(const Format & format)92 void HEncoder::EnableVariableFrameRate(const Format &format)
93 {
94     int32_t enableVariableFrameRate = 0;
95     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_PTS_BASED_RATECONTROL, enableVariableFrameRate)) {
96         HLOGE("fail to get video_encoder_enable_pts_based_ratecontrol");
97         return;
98     }
99     HLOGI("video_encoder_enable_pts_based_ratecontrol flag is %d", enableVariableFrameRate);
100     if (enableVariableFrameRate) {
101         enableVariableFrameRate_ = true;
102     }
103     return;
104 }
105 
ConfigureBufferType()106 int32_t HEncoder::ConfigureBufferType()
107 {
108     UseBufferType useBufferTypes;
109     InitOMXParamExt(useBufferTypes);
110     useBufferTypes.portIndex = OMX_DirInput;
111     useBufferTypes.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
112     if (!SetParameter(OMX_IndexParamUseBufferType, useBufferTypes)) {
113         HLOGE("component don't support CODEC_BUFFER_TYPE_DYNAMIC_HANDLE");
114         return AVCS_ERR_INVALID_VAL;
115     }
116     return AVCS_ERR_OK;
117 }
118 
CheckIfEnableCb(const Format & format)119 void HEncoder::CheckIfEnableCb(const Format &format)
120 {
121     int32_t enableCb = 0;
122     if (format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, enableCb)) {
123         HLOGI("enable surface mode callback flag %d", enableCb);
124         enableSurfaceModeInputCb_ = static_cast<bool>(enableCb);
125     }
126 }
127 
SetRepeat(const Format & format)128 int32_t HEncoder::SetRepeat(const Format &format)
129 {
130     int repeatMs = 0;
131     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, repeatMs)) {
132         return AVCS_ERR_OK;
133     }
134     if (repeatMs <= 0) {
135         HLOGW("invalid repeatMs %d", repeatMs);
136         return AVCS_ERR_INVALID_VAL;
137     }
138     repeatUs_ = static_cast<uint64_t>(repeatMs * TIME_RATIO_S_TO_MS);
139 
140     int repeatMaxCnt = 0;
141     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, repeatMaxCnt)) {
142         return AVCS_ERR_OK;
143     }
144     if (repeatMaxCnt == 0) {
145         HLOGW("invalid repeatMaxCnt %d", repeatMaxCnt);
146         return AVCS_ERR_INVALID_VAL;
147     }
148     repeatMaxCnt_ = repeatMaxCnt;
149     return AVCS_ERR_OK;
150 }
151 
SetLTRParam(const Format & format)152 int32_t HEncoder::SetLTRParam(const Format &format)
153 {
154     int32_t ltrFrameNum = -1;
155     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameNum)) {
156         return AVCS_ERR_OK;
157     }
158     CodecHDI::VideoFeature ltrFeature =
159         HCodecList::FindFeature(caps_.port.video.features, CodecHDI::VIDEO_FEATURE_LTR);
160     if (!ltrFeature.support || ltrFeature.extendInfo.empty()) {
161         HLOGW("platform not support LTR");
162         return AVCS_ERR_OK;
163     }
164     int32_t maxLtrNum = ltrFeature.extendInfo[0];
165     if (ltrFrameNum <= 0 || ltrFrameNum > maxLtrNum) {
166         HLOGE("invalid ltrFrameNum %d", ltrFrameNum);
167         return AVCS_ERR_INVALID_VAL;
168     }
169     if (enableTSVC_) {
170         HLOGW("user has enabled temporal scale, can not set LTR param");
171         return AVCS_ERR_INVALID_VAL;
172     }
173     CodecLTRParam info;
174     InitOMXParamExt(info);
175     info.ltrFrameListLen = static_cast<uint32_t>(ltrFrameNum);
176     if (!SetParameter(OMX_IndexParamLTR, info)) {
177         HLOGE("configure LTR failed");
178         return AVCS_ERR_INVALID_VAL;
179     }
180     enableLTR_ = true;
181     return AVCS_ERR_OK;
182 }
183 
EnableEncoderParamsFeedback(const Format & format)184 int32_t HEncoder::EnableEncoderParamsFeedback(const Format &format)
185 {
186     int32_t enableParamsFeedback {};
187     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_PARAMS_FEEDBACK, enableParamsFeedback)) {
188         return AVCS_ERR_OK;
189     }
190     OMX_CONFIG_BOOLEANTYPE param {};
191     InitOMXParam(param);
192     param.bEnabled = enableParamsFeedback ? OMX_TRUE : OMX_FALSE;
193     if (!SetParameter(OMX_IndexParamEncParamsFeedback, param)) {
194         HLOGE("configure encoder params feedback[%d] failed", enableParamsFeedback);
195         return AVCS_ERR_INVALID_VAL;
196     }
197     HLOGI("configure encoder params feedback[%d] success", enableParamsFeedback);
198     return AVCS_ERR_OK;
199 }
200 
201 // LCOV_EXCL_START
EnableFrameQPMap(const Format & format)202 int32_t HEncoder::EnableFrameQPMap(const Format &format)
203 {
204     int32_t enableQPMap = false;
205     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_QP_MAP, enableQPMap)) {
206         return AVCS_ERR_OK;
207     }
208     CodecHDI::VideoFeature feature =
209         HCodecList::FindFeature(caps_.port.video.features, CodecHDI::VIDEO_FEATURE_QP_MAP);
210     if (!feature.support) {
211         HLOGE("this device dont support qp map");
212         return AVCS_ERR_UNSUPPORT;
213     }
214     OMX_CONFIG_BOOLEANTYPE param {};
215     InitOMXParam(param);
216     param.bEnabled = enableQPMap ? OMX_TRUE : OMX_FALSE;
217     if (!SetParameter(OMX_IndexParamEnableQPMap, param)) {
218         HLOGE("enable encoder frame qp map[%d] failed", enableQPMap);
219         return AVCS_ERR_INVALID_VAL;
220     }
221     HLOGI("enable encoder frame qp map[%d] success", enableQPMap);
222     enableQPMap_ = true;
223     return AVCS_ERR_OK;
224 }
225 
ConfigBEncodeMode(const Format & format)226 int32_t HEncoder::ConfigBEncodeMode(const Format &format)
227 {
228     Media::Plugins::VideoEncodeBFrameGopMode gopMode;
229     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODE_B_FRAME_GOP_MODE, *reinterpret_cast<int *>(&gopMode))) {
230         return AVCS_ERR_OK;
231     }
232 
233     CodecHDI::VideoFeature feature =
234         HCodecList::FindFeature(caps_.port.video.features, CodecHDI::VIDEO_FEATURE_ENCODE_B_FRAME);
235     if (!feature.support || feature.extendInfo.empty() || feature.extendInfo[0] <= 0) {
236         HLOGE("this device or protocol not support b frame");
237         return AVCS_ERR_UNSUPPORT;
238     }
239 
240     CodecEncGopMode param {};
241     InitOMXParamExt(param);
242     if (gopMode == Media::Plugins::VIDEO_ENCODE_GOP_ADAPTIVE_B_MODE) {
243         HLOGI("encoder use adaptive-b");
244         param.gopMode = OMX_ENCODE_GOP_ADAPTIVE_B_MODE;
245     } else if (gopMode == Media::Plugins::VIDEO_ENCODE_GOP_H3B_MODE) {
246         HLOGI("encoder use h3b");
247         param.gopMode = OMX_ENCODE_GOP_H3B_MODE;
248     } else {
249         HLOGE("invalid gop mode");
250         return AVCS_ERR_UNSUPPORT;
251     }
252 
253     if (!SetParameter(OMX_IndexParamEncBFrameMode, param)) {
254         HLOGE("config b gop mode [%d] failed", gopMode);
255         return AVCS_ERR_INVALID_VAL;
256     }
257     return AVCS_ERR_OK;
258 }
259 // LCOV_EXCL_STOP
260 
SetQpRange(const Format & format,bool isCfg)261 int32_t HEncoder::SetQpRange(const Format &format, bool isCfg)
262 {
263     int32_t minQp;
264     int32_t maxQp;
265     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) ||
266         !format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) {
267         return AVCS_ERR_OK;
268     }
269 
270     CodecQPRangeParam QPRangeParam;
271     InitOMXParamExt(QPRangeParam);
272     QPRangeParam.minQp = static_cast<uint32_t>(minQp);
273     QPRangeParam.maxQp = static_cast<uint32_t>(maxQp);
274     if (!SetParameter(OMX_IndexParamQPRange, QPRangeParam, isCfg)) {
275         HLOGE("set qp range (%d~%d) failed", minQp, maxQp);
276         return AVCS_ERR_UNKNOWN;
277     }
278     HLOGI("set qp range (%d~%d) succ", minQp, maxQp);
279     return AVCS_ERR_OK;
280 }
281 
SetTemperalLayer(const Format & format)282 int32_t HEncoder::SetTemperalLayer(const Format &format)
283 {
284     int32_t enableTemporalScale = 0;
285     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enableTemporalScale) ||
286         (enableTemporalScale == 0)) {
287         return AVCS_ERR_OK;
288     }
289     if (!HCodecList::FindFeature(caps_.port.video.features, CodecHDI::VIDEO_FEATURE_TSVC).support) {
290         HLOGW("platform not support temporal scale");
291         return AVCS_ERR_OK;
292     }
293     Media::Plugins::TemporalGopReferenceMode GopReferenceMode{};
294     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
295         *reinterpret_cast<int *>(&GopReferenceMode)) ||
296         static_cast<int32_t>(GopReferenceMode) != 2) { // 2: gop mode
297         HLOGE("user enable temporal scalability but not set invalid temporal gop mode");
298         return AVCS_ERR_INVALID_VAL;
299     }
300     int32_t temporalGopSize = 0;
301     if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize)) {
302         HLOGE("user enable temporal scalability but not set invalid temporal gop size");
303         return AVCS_ERR_INVALID_VAL;
304     }
305 
306     CodecTemperalLayerParam temperalLayerParam;
307     InitOMXParamExt(temperalLayerParam);
308     switch (temporalGopSize) {
309         case 2: // 2: picture size of the temporal group
310             temperalLayerParam.layerCnt = 2; // 2: layer of the temporal group
311             break;
312         case 4: // 4: picture size of the temporal group
313             temperalLayerParam.layerCnt = 3; // 3: layer of the temporal group
314             break;
315         default:
316             HLOGE("user set invalid temporal gop size %d", temporalGopSize);
317             return AVCS_ERR_INVALID_VAL;
318     }
319 
320     if (!SetParameter(OMX_IndexParamTemperalLayer, temperalLayerParam)) {
321         HLOGE("set temporal layer param failed");
322         return AVCS_ERR_UNKNOWN;
323     }
324     HLOGI("set temporal layer param %d succ", temperalLayerParam.layerCnt);
325     enableTSVC_ = true;
326     return AVCS_ERR_OK;
327 }
328 
GetWaterMarkInfo(std::shared_ptr<AVBuffer> buffer,WaterMarkInfo & info)329 int32_t HEncoder::GetWaterMarkInfo(std::shared_ptr<AVBuffer> buffer, WaterMarkInfo &info)
330 {
331     if (!buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_WATERMARK, info.enableWaterMark) ||
332         !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_X, info.x) ||
333         !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_Y, info.y) ||
334         !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_W, info.w) ||
335         !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_H, info.h)) {
336         LOGE("invalid value");
337         return AVCS_ERR_INVALID_VAL;
338     }
339     if (info.x < 0 || info.y < 0 || info.w <= 0 || info.h <= 0) {
340         LOGE("invalid coordinate, x %d, y %d, w %d, h %d", info.x, info.y, info.w, info.h);
341         return AVCS_ERR_INVALID_VAL;
342     }
343     return AVCS_ERR_OK;
344 }
345 
OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer)346 int32_t HEncoder::OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer)
347 {
348     if (!HCodecList::FindFeature(caps_.port.video.features, CodecHDI::VIDEO_FEATURE_WATERMARK).support) {
349         HLOGE("this device dont support water mark");
350         return AVCS_ERR_UNSUPPORT;
351     }
352     if (buffer == nullptr || buffer->memory_ == nullptr || buffer->meta_ == nullptr) {
353         HLOGE("invalid buffer");
354         return AVCS_ERR_INVALID_VAL;
355     }
356     sptr<SurfaceBuffer> waterMarkBuffer = buffer->memory_->GetSurfaceBuffer();
357     if (waterMarkBuffer == nullptr) {
358         HLOGE("null surfacebuffer");
359         return AVCS_ERR_INVALID_VAL;
360     }
361     if (waterMarkBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_8888) {
362         HLOGE("pixel fmt should be RGBA8888");
363         return AVCS_ERR_INVALID_VAL;
364     }
365     WaterMarkInfo info;
366     int32_t ret = GetWaterMarkInfo(buffer, info);
367     if (ret != AVCS_ERR_OK) {
368         return ret;
369     }
370     CodecHDI::CodecParamOverlay param {
371         .size = sizeof(param), .enable = info.enableWaterMark,
372         .dstX = static_cast<uint32_t>(info.x), .dstY = static_cast<uint32_t>(info.y),
373         .dstW = static_cast<uint32_t>(info.w), .dstH = static_cast<uint32_t>(info.h),
374     };
375     int8_t* p = reinterpret_cast<int8_t*>(&param);
376     std::vector<int8_t> inVec(p, p + sizeof(param));
377     CodecHDI::OmxCodecBuffer omxbuffer {};
378     omxbuffer.bufferhandle = new HDI::Base::NativeBuffer(waterMarkBuffer->GetBufferHandle());
379     ret = compNode_->SetParameterWithBuffer(CodecHDI::Codec_IndexParamOverlayBuffer, inVec, omxbuffer);
380     if (ret != HDF_SUCCESS) {
381         HLOGE("SetParameterWithBuffer failed");
382         return AVCS_ERR_INVALID_VAL;
383     }
384     HLOGI("SetParameterWithBuffer succ");
385     return AVCS_ERR_OK;
386 }
387 
SetColorAspects(const Format & format)388 int32_t HEncoder::SetColorAspects(const Format &format)
389 {
390     int range = 0;
391     int primary = static_cast<int>(COLOR_PRIMARY_UNSPECIFIED);
392     int transfer = static_cast<int>(TRANSFER_CHARACTERISTIC_UNSPECIFIED);
393     int matrix = static_cast<int>(MATRIX_COEFFICIENT_UNSPECIFIED);
394 
395     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, range)) {
396         HLOGI("user set range flag %d", range);
397     }
398     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, primary)) {
399         HLOGI("user set primary %d", primary);
400     }
401     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, transfer)) {
402         HLOGI("user set transfer %d", transfer);
403     }
404     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, matrix)) {
405         HLOGI("user set matrix %d", matrix);
406     }
407     if (primary < 0 || primary > UINT8_MAX ||
408         transfer < 0 || transfer > UINT8_MAX ||
409         matrix < 0 || matrix > UINT8_MAX) {
410         HLOGW("invalid color");
411         return AVCS_ERR_INVALID_VAL;
412     }
413 
414     CodecVideoColorspace param;
415     InitOMXParamExt(param);
416     param.portIndex = OMX_DirInput;
417     param.aspects.range = static_cast<bool>(range);
418     param.aspects.primaries = static_cast<uint8_t>(primary);
419     param.aspects.transfer = static_cast<uint8_t>(transfer);
420     param.aspects.matrixCoeffs = static_cast<uint8_t>(matrix);
421 
422     if (!SetParameter(OMX_IndexColorAspects, param, true)) {
423         HLOGE("failed to set CodecVideoColorSpace");
424         return AVCS_ERR_UNKNOWN;
425     }
426     HLOGI("set color aspects (isFullRange %d, primary %u, transfer %u, matrix %u) succ",
427           param.aspects.range, param.aspects.primaries,
428           param.aspects.transfer, param.aspects.matrixCoeffs);
429     return AVCS_ERR_OK;
430 }
431 
CalcInputBufSize(PortInfo & info,VideoPixelFormat pixelFmt)432 void HEncoder::CalcInputBufSize(PortInfo &info, VideoPixelFormat pixelFmt)
433 {
434     uint32_t inSize = AlignTo(info.width, 128u) * AlignTo(info.height, 128u); // 128: block size
435     if (pixelFmt == VideoPixelFormat::RGBA) {
436         inSize = inSize * 4; // 4 byte per pixel
437     } else {
438         inSize = inSize * 3 / 2; // 3: nom, 2: denom
439     }
440     info.inputBufSize = inSize;
441 }
442 
SetupPort(const Format & format,std::optional<double> & frameRate)443 int32_t HEncoder::SetupPort(const Format &format, std::optional<double> &frameRate)
444 {
445     constexpr int32_t MAX_ENCODE_WIDTH = 10000;
446     constexpr int32_t MAX_ENCODE_HEIGHT = 10000;
447     int32_t width;
448     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0 || width > MAX_ENCODE_WIDTH) {
449         HLOGE("format should contain width");
450         return AVCS_ERR_INVALID_VAL;
451     }
452     int32_t height;
453     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0 || height > MAX_ENCODE_HEIGHT) {
454         HLOGE("format should contain height");
455         return AVCS_ERR_INVALID_VAL;
456     }
457     width_ = static_cast<uint32_t>(width);
458     height_ = static_cast<uint32_t>(height);
459     HLOGI("user set width %d, height %d", width, height);
460     if (!GetPixelFmtFromUser(format)) {
461         return AVCS_ERR_INVALID_VAL;
462     }
463 
464     if (!frameRate.has_value()) {
465         HLOGI("user don't set valid frame rate, use default 60.0");
466         frameRate = 60.0; // default frame rate 60.0
467     }
468 
469     codecRate_ = frameRate.value();
470     PortInfo inputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
471                               OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()};
472     CalcInputBufSize(inputPortInfo, configuredFmt_.innerFmt);
473     int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo);
474     if (ret != AVCS_ERR_OK) {
475         return ret;
476     }
477 
478     PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
479                                codingType_, std::nullopt, frameRate.value()};
480     ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo);
481     if (ret != AVCS_ERR_OK) {
482         return ret;
483     }
484     return AVCS_ERR_OK;
485 }
486 
UpdateInPortFormat()487 int32_t HEncoder::UpdateInPortFormat()
488 {
489     OMX_PARAM_PORTDEFINITIONTYPE def;
490     InitOMXParam(def);
491     def.nPortIndex = OMX_DirInput;
492     if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
493         HLOGE("get input port definition failed");
494         return AVCS_ERR_UNKNOWN;
495     }
496     PrintPortDefinition(def);
497     uint32_t w = def.format.video.nFrameWidth;
498     uint32_t h = def.format.video.nFrameHeight;
499     inBufferCnt_ = def.nBufferCountActual;
500 
501     // save into member variable
502     requestCfg_.timeout = 0;
503     requestCfg_.width = static_cast<int32_t>(w);
504     requestCfg_.height = static_cast<int32_t>(h);
505     requestCfg_.strideAlignment = STRIDE_ALIGNMENT;
506     requestCfg_.format = configuredFmt_.graphicFmt;
507     requestCfg_.usage = BUFFER_MODE_REQUEST_USAGE;
508 
509     if (inputFormat_ == nullptr) {
510         inputFormat_ = make_shared<Format>();
511     }
512     inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w);
513     inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h);
514     inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT,
515         static_cast<int32_t>(configuredFmt_.innerFmt));
516     inputFormat_->PutIntValue("IS_VENDOR", 1);
517     return AVCS_ERR_OK;
518 }
519 
UpdateOutPortFormat()520 int32_t HEncoder::UpdateOutPortFormat()
521 {
522     OMX_PARAM_PORTDEFINITIONTYPE def;
523     InitOMXParam(def);
524     def.nPortIndex = OMX_DirOutput;
525     if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
526         HLOGE("get output port definition failed");
527         return AVCS_ERR_UNKNOWN;
528     }
529     PrintPortDefinition(def);
530     if (outputFormat_ == nullptr) {
531         outputFormat_ = make_shared<Format>();
532     }
533     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth);
534     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight);
535     outputFormat_->PutIntValue("IS_VENDOR", 1);
536     return AVCS_ERR_OK;
537 }
538 
SetPFramesSpacing(int32_t iFramesIntervalInMs,double frameRate,uint32_t bFramesSpacing=0)539 static uint32_t SetPFramesSpacing(int32_t iFramesIntervalInMs, double frameRate, uint32_t bFramesSpacing = 0)
540 {
541     if (iFramesIntervalInMs < 0) { // IPPPP...
542         return UINT32_MAX - 1;
543     }
544     if (iFramesIntervalInMs == 0) { // IIIII...
545         return 0;
546     }
547     uint32_t iFramesInterval = iFramesIntervalInMs * frameRate / TIME_RATIO_S_TO_MS;
548     uint32_t pFramesSpacing = iFramesInterval / (bFramesSpacing + 1);
549     return pFramesSpacing > 0 ? pFramesSpacing - 1 : 0;
550 }
551 
GetBitRateFromUser(const Format & format)552 std::optional<uint32_t> HEncoder::GetBitRateFromUser(const Format &format)
553 {
554     int64_t bitRateLong;
555     if (format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateLong) && bitRateLong > 0 &&
556         bitRateLong <= UINT32_MAX) {
557         LOGI("user set bit rate %" PRId64 "", bitRateLong);
558         return static_cast<uint32_t>(bitRateLong);
559     }
560     int32_t bitRateInt;
561     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateInt) && bitRateInt > 0) {
562         LOGI("user set bit rate %d", bitRateInt);
563         return static_cast<uint32_t>(bitRateInt);
564     }
565     return nullopt;
566 }
567 
GetSQRFactorFromUser(const Format & format)568 std::optional<uint32_t> HEncoder::GetSQRFactorFromUser(const Format &format)
569 {
570     int32_t sqrFactor;
571     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, sqrFactor) && sqrFactor >= 0) {
572         LOGI("user set SQR factor is  %d", sqrFactor);
573         return static_cast<uint32_t>(sqrFactor);
574     }
575     return nullopt;
576 }
577 
GetSQRMaxBitrateFromUser(const Format & format)578 std::optional<uint32_t> HEncoder::GetSQRMaxBitrateFromUser(const Format &format)
579 {
580     int64_t maxBitRateLong;
581     if (format.GetLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, maxBitRateLong) &&
582         maxBitRateLong > 0 && maxBitRateLong <= UINT32_MAX) {
583         LOGI("user set max bit rate %" PRId64 "", maxBitRateLong);
584         return static_cast<uint32_t>(maxBitRateLong);
585     }
586     int32_t maxBitRateInt;
587     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE, maxBitRateInt) && maxBitRateInt > 0) {
588         LOGI("user set max bit rate %d", maxBitRateInt);
589         return static_cast<uint32_t>(maxBitRateInt);
590     }
591     return nullopt;
592 }
593 
GetCRFtagetQpFromUser(const Format & format)594 std::optional<uint32_t> HEncoder::GetCRFtagetQpFromUser(const Format &format)
595 {
596     int32_t targetQp;
597     if (format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TARGET_QP, targetQp) && targetQp > 0) {
598         LOGI("user set CRF target_qp %d", targetQp);
599         return static_cast<uint32_t>(targetQp);
600     }
601     return nullopt;
602 }
603 
GetOperatingRateFromUser(const Format & format)604 std::optional<double> HEncoder::GetOperatingRateFromUser(const Format &format)
605 {
606     double operatingRate = 0.0;
607     if (format.GetDoubleValue(OHOS::Media::Tag::VIDEO_ENCODER_OPERATING_RATE, operatingRate) && operatingRate > 0.0) {
608         return operatingRate;
609     }
610     return nullopt;
611 }
612 
GetBitRateModeFromUser(const Format & format)613 std::optional<VideoEncodeBitrateMode> HEncoder::GetBitRateModeFromUser(const Format &format)
614 {
615     VideoEncodeBitrateMode mode;
616     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, *reinterpret_cast<int *>(&mode))) {
617         return mode;
618     }
619     return nullopt;
620 }
621 
622 // LCOV_EXCL_START
SetCRFMode(int32_t targetQp)623 int32_t HEncoder::SetCRFMode(int32_t targetQp)
624 {
625     ControlQualityTargetQp bitrateType;
626     InitOMXParamExt(bitrateType);
627     bitrateType.portIndex = OMX_DirOutput;
628     bitrateType.targetQp = static_cast<uint32_t>(targetQp);
629     if (!SetParameter(OMX_IndexParamControlRateCRF, bitrateType)) {
630         HLOGE("failed to set OMX_IndexParamControlRateCRF");
631         return AVCS_ERR_UNKNOWN;
632     }
633     HLOGI("set CRF mode and target quality %u succ", bitrateType.targetQp);
634     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, CRF);
635     outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TARGET_QP, targetQp);
636     return AVCS_ERR_OK;
637 }
638 // LCOV_EXCL_STOP
639 
SetConstantQualityMode(int32_t quality)640 int32_t HEncoder::SetConstantQualityMode(int32_t quality)
641 {
642     ControlRateConstantQuality bitrateType;
643     InitOMXParamExt(bitrateType);
644     bitrateType.portIndex = OMX_DirOutput;
645     bitrateType.qualityValue = static_cast<uint32_t>(quality);
646     if (!SetParameter(OMX_IndexParamControlRateConstantQuality, bitrateType)) {
647         HLOGE("failed to set OMX_IndexParamControlRateConstantQuality");
648         return AVCS_ERR_UNKNOWN;
649     }
650     HLOGI("set CQ mode and target quality %u succ", bitrateType.qualityValue);
651     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, CQ);
652     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality);
653     return AVCS_ERR_OK;
654 }
655 
SetSQRMode(const Format & format)656 int32_t HEncoder::SetSQRMode(const Format &format)
657 {
658     StableControlRate bitrateType;
659     InitOMXParamExt(bitrateType);
660     bitrateType.portIndex = OMX_DirOutput;
661     if (!GetParameter(OMX_IndexParamControlRateSQR, bitrateType)) {
662         HLOGE("get OMX_IndexParamControlRateSQR failed");
663         return AVCS_ERR_UNKNOWN;
664     }
665     optional<uint32_t> sqrFactor = GetSQRFactorFromUser(format);
666     optional<uint32_t> maxBitrate = GetSQRMaxBitrateFromUser(format);
667     optional<uint32_t> bitRate = GetBitRateFromUser(format);
668     if (sqrFactor.has_value()) {
669         bitrateType.sqrFactor = sqrFactor.value();
670         LOGI("set sqr factor %u", bitrateType.sqrFactor);
671     }
672     if (maxBitrate.has_value()) {
673         bitrateType.sMaxBitrate = maxBitrate.value();
674         LOGI("set max bit rate %u bps", bitrateType.sMaxBitrate);
675     }
676     if (bitRate.has_value() && !maxBitrate.has_value()) {
677         bitrateType.sTargetBitrate = bitRate.value();
678         bitrateType.bitrateEnabled = true;
679         LOGI("set target bitrate %u bps", bitrateType.sTargetBitrate);
680     }
681     if (!SetParameter(OMX_IndexParamControlRateSQR, bitrateType)) {
682         HLOGE("failed to set OMX_IndexParamControlRateSQR");
683         return AVCS_ERR_UNKNOWN;
684     }
685     HLOGI("set SQR mode succ");
686     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, SQR);
687     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_SQR_FACTOR, bitrateType.sqrFactor);
688     if (bitrateType.bitrateEnabled) {
689         outputFormat_->PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE,
690             static_cast<int64_t>(bitrateType.sTargetBitrate));
691     } else {
692         outputFormat_->PutLongValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODER_MAX_BITRATE,
693             static_cast<int64_t>(bitrateType.sMaxBitrate));
694     }
695     return AVCS_ERR_OK;
696 }
697 
ConfigureOutputBitrate(const Format & format)698 int32_t HEncoder::ConfigureOutputBitrate(const Format &format)
699 {
700     OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
701     InitOMXParam(bitrateType);
702     bitrateType.nPortIndex = OMX_DirOutput;
703     if (!GetParameter(OMX_IndexParamVideoBitrate, bitrateType)) {
704         HLOGE("get OMX_IndexParamVideoBitrate failed");
705         return AVCS_ERR_UNKNOWN;
706     }
707     optional<VideoEncodeBitrateMode> bitRateMode = GetBitRateModeFromUser(format);
708     if (bitRateMode.has_value()) {
709         int32_t metaValue;
710         if (bitRateMode.value() == CRF &&
711             format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TARGET_QP, metaValue) && metaValue >= 0) {
712             return SetCRFMode(metaValue);
713         }
714         if (format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, metaValue)) {
715             if (bitRateMode.value() == CQ && metaValue >= 0) {
716                 return SetConstantQualityMode(metaValue);
717             }
718         } else {
719             if (bitRateMode.value() == SQR) {
720                 return SetSQRMode(format);
721             }
722         }
723         if (bitRateMode.value() != SQR && bitRateMode.value() != CQ) {
724             auto omxBitrateMode = TypeConverter::InnerModeToOmxBitrateMode(bitRateMode.value());
725             if (omxBitrateMode.has_value()) {
726                 bitrateType.eControlRate = omxBitrateMode.value();
727             }
728         }
729     }
730     optional<uint32_t> bitRate = GetBitRateFromUser(format);
731     if (bitRate.has_value()) {
732         bitrateType.nTargetBitrate = bitRate.value();
733     }
734     if (!SetParameter(OMX_IndexParamVideoBitrate, bitrateType)) {
735         HLOGE("failed to set OMX_IndexParamVideoBitrate");
736         return AVCS_ERR_UNKNOWN;
737     }
738     outputFormat_->PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE,
739         static_cast<int64_t>(bitrateType.nTargetBitrate));
740     auto innerMode = TypeConverter::OmxBitrateModeToInnerMode(bitrateType.eControlRate);
741     if (innerMode.has_value()) {
742         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE,
743             static_cast<int32_t>(innerMode.value()));
744         HLOGI("set %d mode and target bitrate %u bps succ", innerMode.value(), bitrateType.nTargetBitrate);
745     } else {
746         HLOGI("set default bitratemode and target bitrate %u bps succ", bitrateType.nTargetBitrate);
747     }
748     return AVCS_ERR_OK;
749 }
750 
ConfigureProtocol(const Format & format,std::optional<double> frameRate)751 void HEncoder::ConfigureProtocol(const Format &format, std::optional<double> frameRate)
752 {
753     int32_t ret = AVCS_ERR_OK;
754     switch (static_cast<int>(codingType_)) {
755         case OMX_VIDEO_CodingAVC:
756             ret = SetupAVCEncoderParameters(format, frameRate);
757             break;
758         case CODEC_OMX_VIDEO_CodingHEVC:
759             ret = SetupHEVCEncoderParameters(format, frameRate);
760             break;
761         default:
762             break;
763     }
764     if (ret != AVCS_ERR_OK) {
765         HLOGW("set protocol param failed");
766     }
767 }
768 
SetupAVCEncoderParameters(const Format & format,std::optional<double> frameRate)769 int32_t HEncoder::SetupAVCEncoderParameters(const Format &format, std::optional<double> frameRate)
770 {
771     OMX_VIDEO_PARAM_AVCTYPE avcType;
772     InitOMXParam(avcType);
773     avcType.nPortIndex = OMX_DirOutput;
774     if (!GetParameter(OMX_IndexParamVideoAvc, avcType)) {
775         HLOGE("get OMX_IndexParamVideoAvc parameter fail");
776         return AVCS_ERR_UNKNOWN;
777     }
778     avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
779     avcType.nBFrames = 0;
780 
781     AVCProfile profile;
782     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) {
783         optional<OMX_VIDEO_AVCPROFILETYPE> omxAvcProfile = TypeConverter::InnerAvcProfileToOmxProfile(profile);
784         if (omxAvcProfile.has_value()) {
785             avcType.eProfile = omxAvcProfile.value();
786         }
787     }
788     int32_t iFrameInterval;
789     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) {
790         SetAvcFields(avcType, iFrameInterval, frameRate.value());
791     }
792 
793     if (avcType.nBFrames != 0) {
794         avcType.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
795     }
796     avcType.bEnableUEP = OMX_FALSE;
797     avcType.bEnableFMO = OMX_FALSE;
798     avcType.bEnableASO = OMX_FALSE;
799     avcType.bEnableRS = OMX_FALSE;
800     avcType.bFrameMBsOnly = OMX_TRUE;
801     avcType.bMBAFF = OMX_FALSE;
802     avcType.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
803 
804     if (!SetParameter(OMX_IndexParamVideoAvc, avcType)) {
805         HLOGE("failed to set OMX_IndexParamVideoAvc");
806         return AVCS_ERR_UNKNOWN;
807     }
808     return AVCS_ERR_OK;
809 }
810 
SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE & avcType,int32_t iFrameInterval,double frameRate)811 void HEncoder::SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE &avcType, int32_t iFrameInterval, double frameRate)
812 {
813     HLOGI("iFrameInterval:%d, frameRate:%.2f, eProfile:0x%x, eLevel:0x%x",
814           iFrameInterval, frameRate, avcType.eProfile, avcType.eLevel);
815 
816     if (avcType.eProfile == OMX_VIDEO_AVCProfileBaseline) {
817         avcType.nSliceHeaderSpacing = 0;
818         avcType.bUseHadamard = OMX_TRUE;
819         avcType.nRefFrames = 1;
820         avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
821         if (avcType.nPFrames == 0) {
822             avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
823         }
824         avcType.nRefIdx10ActiveMinus1 = 0;
825         avcType.nRefIdx11ActiveMinus1 = 0;
826         avcType.bEntropyCodingCABAC = OMX_FALSE;
827         avcType.bWeightedPPrediction = OMX_FALSE;
828         avcType.bconstIpred = OMX_FALSE;
829         avcType.bDirect8x8Inference = OMX_FALSE;
830         avcType.bDirectSpatialTemporal = OMX_FALSE;
831         avcType.nCabacInitIdc = 0;
832     } else if (avcType.eProfile == OMX_VIDEO_AVCProfileMain || avcType.eProfile == OMX_VIDEO_AVCProfileHigh) {
833         avcType.nSliceHeaderSpacing = 0;
834         avcType.bUseHadamard = OMX_TRUE;
835         avcType.nRefFrames = avcType.nBFrames == 0 ? 1 : 2; // 2 is number of reference frames
836         avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
837         avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
838         avcType.nRefIdx10ActiveMinus1 = 0;
839         avcType.nRefIdx11ActiveMinus1 = 0;
840         avcType.bEntropyCodingCABAC = OMX_TRUE;
841         avcType.bWeightedPPrediction = OMX_TRUE;
842         avcType.bconstIpred = OMX_TRUE;
843         avcType.bDirect8x8Inference = OMX_TRUE;
844         avcType.bDirectSpatialTemporal = OMX_TRUE;
845         avcType.nCabacInitIdc = 1;
846     }
847 }
848 
SetupHEVCEncoderParameters(const Format & format,std::optional<double> frameRate)849 int32_t HEncoder::SetupHEVCEncoderParameters(const Format &format, std::optional<double> frameRate)
850 {
851     CodecVideoParamHevc hevcType;
852     InitOMXParamExt(hevcType);
853     hevcType.portIndex = OMX_DirOutput;
854     if (!GetParameter(OMX_IndexParamVideoHevc, hevcType)) {
855         HLOGE("get OMX_IndexParamVideoHevc parameter fail");
856         return AVCS_ERR_UNKNOWN;
857     }
858 
859     HEVCProfile profile;
860     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) {
861         inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PROFILE, profile);
862         optional<CodecHevcProfile> omxHevcProfile = TypeConverter::InnerHevcProfileToOmxProfile(profile);
863         if (omxHevcProfile.has_value()) {
864             hevcType.profile = omxHevcProfile.value();
865             HLOGI("HEVCProfile %d, CodecHevcProfile 0x%x", profile, hevcType.profile);
866         }
867     }
868 
869     int32_t iFrameInterval;
870     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) {
871         if (iFrameInterval < 0) { // IPPPP...
872             hevcType.keyFrameInterval = UINT32_MAX - 1;
873         } else if (iFrameInterval == 0) { // all intra
874             hevcType.keyFrameInterval = 1;
875         } else {
876             hevcType.keyFrameInterval = iFrameInterval * frameRate.value() / TIME_RATIO_S_TO_MS;
877         }
878         HLOGI("frameRate %.2f, iFrameInterval %d, keyFrameInterval %u", frameRate.value(),
879               iFrameInterval, hevcType.keyFrameInterval);
880     }
881 
882     if (!SetParameter(OMX_IndexParamVideoHevc, hevcType)) {
883         HLOGE("failed to set OMX_IndexParamVideoHevc");
884         return AVCS_ERR_INVALID_VAL;
885     }
886     return AVCS_ERR_OK;
887 }
888 
RequestIDRFrame()889 int32_t HEncoder::RequestIDRFrame()
890 {
891     OMX_CONFIG_INTRAREFRESHVOPTYPE params;
892     InitOMXParam(params);
893     params.nPortIndex = OMX_DirOutput;
894     params.IntraRefreshVOP = OMX_TRUE;
895     if (!SetParameter(OMX_IndexConfigVideoIntraVOPRefresh, params, true)) {
896         HLOGE("failed to request IDR frame");
897         return AVCS_ERR_UNKNOWN;
898     }
899     HLOGI("Set IDR Frame success");
900     return AVCS_ERR_OK;
901 }
902 
SetSqrParam(const Format & format)903 void HEncoder::SetSqrParam(const Format &format)
904 {
905     StableControlRate bitrateType;
906     InitOMXParamExt(bitrateType);
907     bitrateType.portIndex = OMX_DirOutput;
908     if (!GetParameter(OMX_IndexParamControlRateSQR, bitrateType)) {
909         HLOGE("get OMX_IndexParamControlRateSQR failed");
910         return;
911     }
912     optional<uint32_t> sqrFactor = GetSQRFactorFromUser(format);
913     optional<uint32_t> maxBitrate = GetSQRMaxBitrateFromUser(format);
914     optional<uint32_t> bitRate = GetBitRateFromUser(format);
915     if (sqrFactor.has_value()) {
916         bitrateType.sqrFactor = sqrFactor.value();
917         LOGI("set dynamic sqr factor %u", bitrateType.sqrFactor);
918     }
919     if (maxBitrate.has_value() && !bitrateType.bitrateEnabled) {
920         bitrateType.sMaxBitrate = maxBitrate.value();
921         LOGI("set dynamic max bitrate %u bps", bitrateType.sMaxBitrate);
922     }
923     if (bitRate.has_value() && bitrateType.bitrateEnabled) {
924         bitrateType.sTargetBitrate = bitRate.value();
925         LOGI("set dynamic target bitrate %u bps", bitrateType.sTargetBitrate);
926     }
927     if (!SetParameter(OMX_IndexParamControlRateSQR, bitrateType, true)) {
928         HLOGW("failed to set OMX_IndexParamControlRateSQR");
929     }
930 }
931 
OnSetParameters(const Format & format)932 int32_t HEncoder::OnSetParameters(const Format &format)
933 {
934     optional<VideoEncodeBitrateMode> bitRateMode = GetBitRateModeFromUser(*outputFormat_);
935     if (bitRateMode.has_value() && bitRateMode.value() == SQR) {
936         SetSqrParam(format);
937     } else {
938         optional<uint32_t> bitRate = GetBitRateFromUser(format);
939         if (bitRate.has_value()) {
940             OMX_VIDEO_CONFIG_BITRATETYPE bitrateCfgType;
941             InitOMXParam(bitrateCfgType);
942             bitrateCfgType.nPortIndex = OMX_DirOutput;
943             bitrateCfgType.nEncodeBitrate = bitRate.value();
944             if (!SetParameter(OMX_IndexConfigVideoBitrate, bitrateCfgType, true)) {
945                 HLOGW("failed to config OMX_IndexConfigVideoBitrate");
946             }
947         }
948     }
949 // LCOV_EXCL_START
950     optional<uint32_t> targetQp = GetCRFtagetQpFromUser(format);
951     if (targetQp.has_value() && bitRateMode.has_value() && bitRateMode.value() == CRF) {
952         ControlQualityTargetQp bitrateType;
953         InitOMXParamExt(bitrateType);
954         bitrateType.portIndex = OMX_DirOutput;
955         bitrateType.targetQp = targetQp.value();
956         if (!SetParameter(OMX_IndexParamControlRateCRF, bitrateType, true)) {
957             HLOGW("failed to config OMX_IndexConfigVideoBitrate");
958         }
959     }
960 // LCOV_EXCL_STOP
961     optional<double> frameRate = GetFrameRateFromUser(format);
962     if (frameRate.has_value()) {
963         OMX_CONFIG_FRAMERATETYPE framerateCfgType;
964         InitOMXParam(framerateCfgType);
965         framerateCfgType.nPortIndex = OMX_DirInput;
966         framerateCfgType.xEncodeFramerate = frameRate.value() * FRAME_RATE_COEFFICIENT;
967         if (!SetParameter(OMX_IndexConfigVideoFramerate, framerateCfgType, true)) {
968             HLOGW("failed to config OMX_IndexConfigVideoFramerate");
969         }
970     }
971 
972     optional<double> operatingRate = GetOperatingRateFromUser(format);
973     if (operatingRate.has_value()) {
974         OMX_PARAM_U32TYPE config;
975         InitOMXParam(config);
976         config.nU32 = static_cast<uint32_t>(operatingRate.value());
977         if (!SetParameter(OMX_IndexParamOperatingRate, config, true)) {
978             HLOGW("failed to set OMX_IndexConfigOperatingRate");
979         }
980     }
981 
982     int32_t requestIdr;
983     if (format.GetIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, requestIdr) && requestIdr != 0) {
984         int32_t ret = RequestIDRFrame();
985         if (ret != AVCS_ERR_OK) {
986             return ret;
987         }
988     }
989 
990     int32_t ret = SetQpRange(format, true);
991     if (ret != AVCS_ERR_OK) {
992         return ret;
993     }
994     return AVCS_ERR_OK;
995 }
996 
SubmitOutBufToOmx()997 int32_t HEncoder::SubmitOutBufToOmx()
998 {
999     for (BufferInfo &info : outputBufferPool_) {
1000         if (info.owner == BufferOwner::OWNED_BY_US) {
1001             int32_t ret = NotifyOmxToFillThisOutBuffer(info);
1002             if (ret != AVCS_ERR_OK) {
1003                 return ret;
1004             }
1005         } else {
1006             HLOGE("buffer should be owned by us");
1007             return AVCS_ERR_UNKNOWN;
1008         }
1009     }
1010     return AVCS_ERR_OK;
1011 }
1012 
ReadyToStart()1013 bool HEncoder::ReadyToStart()
1014 {
1015     if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) {
1016         return false;
1017     }
1018     if (inputSurface_) {
1019         HLOGI("surface mode, surface id = %" PRIu64, inputSurface_->GetUniqueId());
1020     } else {
1021         HLOGI("buffer mode");
1022     }
1023     return true;
1024 }
1025 
AllocateBuffersOnPort(OMX_DIRTYPE portIndex)1026 int32_t HEncoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex)
1027 {
1028     if (portIndex == OMX_DirOutput) {
1029         return AllocateAvLinearBuffers(portIndex);
1030     }
1031     if (inputSurface_) {
1032         return AllocInBufsForDynamicSurfaceBuf();
1033     } else {
1034         int32_t ret = AllocateAvSurfaceBuffers(portIndex);
1035         if (ret == AVCS_ERR_OK) {
1036             UpdateFmtFromSurfaceBuffer();
1037         }
1038         return ret;
1039     }
1040 }
1041 
UpdateFmtFromSurfaceBuffer()1042 void HEncoder::UpdateFmtFromSurfaceBuffer()
1043 {
1044     if (inputBufferPool_.empty()) {
1045         return;
1046     }
1047     sptr<SurfaceBuffer> surfaceBuffer = inputBufferPool_.front().surfaceBuffer;
1048     if (surfaceBuffer == nullptr) {
1049         return;
1050     }
1051     int32_t stride = surfaceBuffer->GetStride();
1052     HLOGI("input stride = %d", stride);
1053     inputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, stride);
1054 }
1055 
ClearDirtyList()1056 void HEncoder::ClearDirtyList()
1057 {
1058     sptr<SurfaceBuffer> buffer;
1059     sptr<SyncFence> fence;
1060     int64_t pts = -1;
1061     OHOS::Rect damage;
1062     while (true) {
1063         GSError ret = inputSurface_->AcquireBuffer(buffer, fence, pts, damage);
1064         if (ret != GSERROR_OK || buffer == nullptr) {
1065             return;
1066         }
1067         HLOGI("return stale buffer to surface, seq = %u, pts = %" PRId64 "", buffer->GetSeqNum(), pts);
1068         inputSurface_->ReleaseBuffer(buffer, -1);
1069     }
1070 }
1071 
SubmitAllBuffersOwnedByUs()1072 int32_t HEncoder::SubmitAllBuffersOwnedByUs()
1073 {
1074     HLOGI(">>");
1075     if (isBufferCirculating_) {
1076         HLOGI("buffer is already circulating, no need to do again");
1077         return AVCS_ERR_OK;
1078     }
1079     int32_t ret = SubmitOutBufToOmx();
1080     if (ret != AVCS_ERR_OK) {
1081         return ret;
1082     }
1083     if (inputSurface_) {
1084         ClearDirtyList();
1085         sptr<IBufferConsumerListener> listener = new EncoderBuffersConsumerListener(m_token);
1086         inputSurface_->RegisterConsumerListener(listener);
1087         SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
1088     } else {
1089         for (BufferInfo &info : inputBufferPool_) {
1090             if (info.owner == BufferOwner::OWNED_BY_US) {
1091                 NotifyUserToFillThisInBuffer(info);
1092             }
1093         }
1094     }
1095 
1096     isBufferCirculating_ = true;
1097     return AVCS_ERR_OK;
1098 }
1099 
OnCreateInputSurface()1100 sptr<Surface> HEncoder::OnCreateInputSurface()
1101 {
1102     if (inputSurface_) {
1103         HLOGE("inputSurface_ already exists");
1104         return nullptr;
1105     }
1106 
1107     sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("HEncoderSurface");
1108     if (consumerSurface == nullptr) {
1109         HLOGE("Create the surface consummer fail");
1110         return nullptr;
1111     }
1112     GSError err = consumerSurface->SetDefaultUsage(SURFACE_MODE_CONSUMER_USAGE);
1113     if (err == GSERROR_OK) {
1114         HLOGI("set consumer usage 0x%x succ", SURFACE_MODE_CONSUMER_USAGE);
1115     } else {
1116         HLOGW("set consumer usage 0x%x failed", SURFACE_MODE_CONSUMER_USAGE);
1117     }
1118 
1119     sptr<IBufferProducer> producer = consumerSurface->GetProducer();
1120     if (producer == nullptr) {
1121         HLOGE("Get the surface producer fail");
1122         return nullptr;
1123     }
1124 
1125     sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
1126     if (producerSurface == nullptr) {
1127         HLOGE("CreateSurfaceAsProducer fail");
1128         return nullptr;
1129     }
1130 
1131     inputSurface_ = consumerSurface;
1132     if (inBufferCnt_ > inputSurface_->GetQueueSize()) {
1133         inputSurface_->SetQueueSize(inBufferCnt_);
1134     }
1135     HLOGI("succ, surface id = %" PRIu64 ", queue size %u",
1136           inputSurface_->GetUniqueId(), inputSurface_->GetQueueSize());
1137     return producerSurface;
1138 }
1139 
OnSetInputSurface(sptr<Surface> & inputSurface)1140 int32_t HEncoder::OnSetInputSurface(sptr<Surface> &inputSurface)
1141 {
1142     if (inputSurface_) {
1143         HLOGW("inputSurface_ already exists");
1144     }
1145 
1146     if (inputSurface == nullptr) {
1147         HLOGE("surface is null");
1148         return AVCS_ERR_INVALID_VAL;
1149     }
1150     if (!inputSurface->IsConsumer()) {
1151         HLOGE("expect consumer surface");
1152         return AVCS_ERR_INVALID_VAL;
1153     }
1154 
1155     inputSurface_ = inputSurface;
1156     if (inBufferCnt_ > inputSurface_->GetQueueSize()) {
1157         inputSurface_->SetQueueSize(inBufferCnt_);
1158     }
1159     HLOGI("succ");
1160     return AVCS_ERR_OK;
1161 }
1162 
WrapPerFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1163 void HEncoder::WrapPerFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1164                                               const shared_ptr<Media::Meta> &meta)
1165 {
1166     omxBuffer->alongParam.clear();
1167     WrapLTRParamIntoOmxBuffer(omxBuffer, meta);
1168     WrapRequestIFrameParamIntoOmxBuffer(omxBuffer, meta);
1169     WrapQPRangeParamIntoOmxBuffer(omxBuffer, meta);
1170     WrapStartQPIntoOmxBuffer(omxBuffer, meta);
1171     WrapIsSkipFrameIntoOmxBuffer(omxBuffer, meta);
1172     WrapRoiParamIntoOmxBuffer(omxBuffer, meta);
1173     WrapQPMapParamIntoOmxBuffer(omxBuffer, meta);
1174     meta->Clear();
1175 }
1176 
WrapLTRParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1177 void HEncoder::WrapLTRParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1178                                          const shared_ptr<Media::Meta> &meta)
1179 {
1180     if (!enableLTR_) {
1181         return;
1182     }
1183     AppendToVector(omxBuffer->alongParam, OMX_IndexParamLTR);
1184     CodecLTRPerFrameParam param;
1185     bool markLTR = false;
1186     meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_MARK_LTR, markLTR);
1187     param.markAsLTR = markLTR;
1188     int32_t useLtrPoc = 0;
1189     param.useLTR = meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrPoc);
1190     param.useLTRPoc = static_cast<uint32_t>(useLtrPoc);
1191     AppendToVector(omxBuffer->alongParam, param);
1192 }
1193 
WrapRequestIFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1194 void HEncoder::WrapRequestIFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1195                                                    const shared_ptr<Media::Meta> &meta)
1196 {
1197     bool requestIFrame = false;
1198     meta->GetData(OHOS::Media::Tag::VIDEO_REQUEST_I_FRAME, requestIFrame);
1199     if (!requestIFrame) {
1200         return;
1201     }
1202     AppendToVector(omxBuffer->alongParam, OMX_IndexConfigVideoIntraVOPRefresh);
1203     OMX_CONFIG_INTRAREFRESHVOPTYPE params;
1204     InitOMXParam(params);
1205     params.nPortIndex = OMX_DirOutput;
1206     params.IntraRefreshVOP = OMX_TRUE;
1207     AppendToVector(omxBuffer->alongParam, params);
1208     HLOGI("pts=%" PRId64 ", requestIFrame", omxBuffer->pts);
1209 }
1210 
1211 // LCOV_EXCL_START
WrapQPMapParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1212 void HEncoder::WrapQPMapParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1213                                            const shared_ptr<Media::Meta> &meta)
1214 {
1215     if (!enableQPMap_) {
1216         return;
1217     }
1218     bool isAbsQp;
1219     if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_ABS_QP_MAP, isAbsQp)) {
1220         isAbsQp = false;
1221     }
1222     vector<uint8_t> qpMap;
1223     if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_QP_MAP, qpMap) || qpMap.empty()) {
1224         return;
1225     }
1226     AppendToVector(omxBuffer->alongParam, OMX_IndexParamBlockQP);
1227     CodecBlockQpParam param;
1228     InitOMXParamExt(param);
1229     param.blockQpAddr = nullptr;
1230     param.blockQpSize = static_cast<uint32_t>(qpMap.size());
1231     param.blockQpSetByUser = true;
1232     param.absQp = isAbsQp;
1233     AppendToVector(omxBuffer->alongParam, param);
1234     AppendArrayToVector(omxBuffer->alongParam, qpMap);
1235 }
1236 // LCOV_EXCL_STOP
1237 
WrapQPRangeParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1238 void HEncoder::WrapQPRangeParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1239                                              const shared_ptr<Media::Meta> &meta)
1240 {
1241     int32_t minQp;
1242     int32_t maxQp;
1243     if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) ||
1244         !meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) {
1245         return;
1246     }
1247     AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPRange);
1248     CodecQPRangeParam param;
1249     InitOMXParamExt(param);
1250     param.minQp = static_cast<uint32_t>(minQp);
1251     param.maxQp = static_cast<uint32_t>(maxQp);
1252     AppendToVector(omxBuffer->alongParam, param);
1253     HLOGI("pts=%" PRId64 ", qp=(%d~%d)", omxBuffer->pts, minQp, maxQp);
1254 }
1255 
WrapStartQPIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1256 void HEncoder::WrapStartQPIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1257                                         const shared_ptr<Media::Meta> &meta)
1258 {
1259     int32_t startQp {};
1260     if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_START, startQp)) {
1261         return;
1262     }
1263     AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPStsart);
1264     AppendToVector(omxBuffer->alongParam, startQp);
1265 }
1266 
WrapIsSkipFrameIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1267 void HEncoder::WrapIsSkipFrameIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1268                                             const shared_ptr<Media::Meta> &meta)
1269 {
1270     bool isSkip {};
1271     if (!meta->GetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_SKIP, isSkip)) {
1272         return;
1273     }
1274     AppendToVector(omxBuffer->alongParam, OMX_IndexParamSkipFrame);
1275     AppendToVector(omxBuffer->alongParam, isSkip);
1276 }
1277 
CalculateSmoothFactorBasedPts(int64_t curPts,int64_t curDuration)1278 double HEncoder::CalculateSmoothFactorBasedPts(int64_t curPts, int64_t curDuration)
1279 {
1280     double smoothFactor = 0.0;
1281     int32_t instantFrameRate = round((1.0 / curDuration) * TIME_RATIO_US_TO_S);
1282     if (instantFrameRate > SMOOTH_FACTOR_CLIP_RANGE_MIN && instantFrameRate < SMOOTH_FACTOR_CLIP_RANGE_MAX) {
1283         smoothFactor = 1 - DURATION_SCALE_FACTOR / instantFrameRate;
1284     } else if (instantFrameRate <= SMOOTH_FACTOR_CLIP_RANGE_MIN) {
1285         smoothFactor = SMOOTH_FACTOR_CLIP_MIN;
1286     } else {
1287         smoothFactor = SMOOTH_FACTOR_CLIP_MAX;
1288     }
1289     return smoothFactor;
1290 }
1291 
CalculateSmoothFpsBasedPts(int64_t curPts,int64_t curDuration)1292 int32_t HEncoder::CalculateSmoothFpsBasedPts(int64_t curPts, int64_t curDuration)
1293 {
1294     int64_t previousDuration1st = previousPtsWindow_.back() - previousPtsWindow_[2];
1295     int64_t previousDuration2nd = previousPtsWindow_[2] - previousPtsWindow_[1];
1296     double smoothFactor = CalculateSmoothFactorBasedPts(curPts, curDuration);
1297     double previousSmoothFactor = CalculateSmoothFactorBasedPts(previousPtsWindow_.back(), previousDuration1st);
1298     double smoothDuration = curDuration * (1 - smoothFactor) + (previousDuration1st * (1 - previousSmoothFactor) +
1299         previousDuration2nd * previousSmoothFactor) * smoothFactor;
1300     int32_t smoothFrameRate = round((1.0 / smoothDuration) * TIME_RATIO_US_TO_S);
1301     HLOGD("pts: %ld, smoothFactor: %f, previousSmoothFactor: %f, smoothDuration: %f", curPts, smoothFactor,
1302         previousSmoothFactor, smoothDuration);
1303     return smoothFrameRate;
1304 }
1305 
UpdateTimeStampWindow(int64_t curPts,int32_t & frameRate)1306 int32_t HEncoder::UpdateTimeStampWindow(int64_t curPts, int32_t &frameRate)
1307 {
1308     int32_t previousPtsWindowSize = static_cast<int32_t>(previousPtsWindow_.size());
1309     if (previousPtsWindow_.empty()) {
1310         previousPtsWindow_.push_back(curPts);
1311         frameRate = defaultFrameRate_.value_or(DEFAULT_FRAME_RATE);
1312         HLOGD("pts: %ld, smoothFrameRate: %d, windowSize: %d", curPts, frameRate, previousPtsWindowSize);
1313         return 0;
1314     }
1315     if (curPts <= previousPtsWindow_.back()) {
1316         HLOGE("curPts less than last pts !");
1317         return -1;
1318     }
1319     int64_t curDuration = curPts - previousPtsWindow_.back();
1320     if (previousPtsWindowSize < PREVIOUS_PTS_RECORDED_COUNT) {
1321         frameRate = round((1.0 / curDuration) * TIME_RATIO_US_TO_S);
1322         previousPtsWindow_.push_back(curPts);
1323         previousSmoothFrameRate_ = frameRate;
1324     } else if (previousPtsWindowSize == PREVIOUS_PTS_RECORDED_COUNT) {
1325         int32_t instantFrameRate = round((1.0 / curDuration) * TIME_RATIO_US_TO_S);
1326         if (instantFrameRate == 0) {
1327             HLOGE("instantFrameRate is 0 !");
1328             return -1;
1329         }
1330         int32_t smoothFrameRate = CalculateSmoothFpsBasedPts(curPts, curDuration);
1331         double averageThreeFrameDurationError = (curDuration - (previousPtsWindow_[1] - previousPtsWindow_[0])) /
1332             AVERAGE_DURATION_ERROR_COUNT;
1333         double frameDurationErrorMin = (1.0 / instantFrameRate - 1.0 / (instantFrameRate -
1334             AVERAGE_DURATION_ERROR_FRAMERATE_RANGE)) * TIME_RATIO_US_TO_S;
1335         double frameDurationErrorMax = (1.0 / instantFrameRate - 1.0 / (instantFrameRate +
1336             AVERAGE_DURATION_ERROR_FRAMERATE_RANGE)) * TIME_RATIO_US_TO_S;
1337         if (averageThreeFrameDurationError > frameDurationErrorMin &&
1338             averageThreeFrameDurationError < frameDurationErrorMax) {
1339             frameRate = smoothFrameRate;
1340         } else {
1341             frameRate = previousSmoothFrameRate_;
1342         }
1343         previousPtsWindow_.push_back(curPts);
1344         previousPtsWindow_.pop_front();
1345         previousSmoothFrameRate_ = frameRate;
1346     } else {
1347         HLOGE("previousPtsWindow_ size:%d error !", previousPtsWindowSize);
1348         return -1;
1349     }
1350     HLOGD("pts: %ld, smoothFrameRate: %d, windowSize: %d", curPts, frameRate, previousPtsWindowSize);
1351     return 0;
1352 }
CalculateFrameRateParamIntoOmxBuffer(int64_t curPts)1353 int32_t HEncoder::CalculateFrameRateParamIntoOmxBuffer(int64_t curPts)
1354 {
1355     if (curPts <= 0) {
1356         HLOGE("curPts less than 0 !");
1357         return -1;
1358     }
1359     int32_t frameRate = 0;
1360     if (inputSurface_) {
1361         curPts /= TIME_RATIO_NS_TO_US;
1362     }
1363     if (UpdateTimeStampWindow(curPts, frameRate) != 0) {
1364         return -1;
1365     }
1366     if (frameRate < caps_.port.video.frameRate.min || frameRate > caps_.port.video.frameRate.max) {
1367         HLOGE("frameRate: %d over range, min: %d, max: %d", frameRate, caps_.port.video.frameRate.min,
1368             caps_.port.video.frameRate.max);
1369         return -1;
1370     }
1371     OMX_CONFIG_FRAMERATETYPE framerateCfgType;
1372     InitOMXParam(framerateCfgType);
1373     framerateCfgType.nPortIndex = OMX_DirInput;
1374     framerateCfgType.xEncodeFramerate = frameRate * FRAME_RATE_COEFFICIENT;
1375     if (!SetParameter(OMX_IndexConfigVideoFramerate, framerateCfgType, true)) {
1376         HLOGE("failed to config OMX_IndexConfigVideoFramerate");
1377         return -1;
1378     }
1379     return 0;
1380 }
1381 
ParseRoiStringValid(const std::string & roiValue,shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer)1382 void HEncoder::ParseRoiStringValid(const std::string &roiValue, shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer)
1383 {
1384     AppendToVector(omxBuffer->alongParam, OMX_IndexParamRoi);
1385     CodecRoiParam param;
1386     InitOMXParamExt(param);
1387     if (roiValue.empty()) { // roiValue string is empty, canceling historical roi configurations!
1388         AppendToVector(omxBuffer->alongParam, param);
1389         return;
1390     }
1391     // step1 parse the string
1392     // method regex roi: Top1,Left1-Bottom1,Right1=Offset1(option);Top2,Left2-Bottom2,Right2=Offset2;...
1393     std::regex pattern(R"((-?\d+),(-?\d+)-(-?\d+),(-?\d+)(?:=(-?\d+))?(?:;|$))");
1394     std::smatch match;
1395     std::string temp = roiValue;
1396     size_t vaildCount = 0;
1397     constexpr int TOP_INDEX = 1;
1398     constexpr int LEFT_INDEX = 2;
1399     constexpr int BOTTOM_INDEX = 3;
1400     constexpr int RIGHT_INDEX = 4;
1401     constexpr int QPOFFSET_INDEX = 5;
1402     constexpr int defaultOffset = -3; // default roi qp
1403     while (std::regex_search(temp, match, pattern) && vaildCount < roiNum) {
1404         int32_t qpOffset, left, top, right, bottom;
1405         top = std::clamp(static_cast<int>(std::strtol(match[TOP_INDEX].str().c_str(), nullptr, 10)), //10:Decimal
1406             0, static_cast<int>(height_));
1407         left = std::clamp(static_cast<int>(std::strtol(match[LEFT_INDEX].str().c_str(), nullptr, 10)), //10:Decimal
1408             0, static_cast<int>(width_));
1409         bottom = std::clamp(static_cast<int>(std::strtol(match[BOTTOM_INDEX].str().c_str(), nullptr, 10)), //10:Decimal
1410             0, static_cast<int>(height_));
1411         right = std::clamp(static_cast<int>(std::strtol(match[RIGHT_INDEX].str().c_str(), nullptr, 10)), //10:Decimal
1412             0, static_cast<int>(width_));
1413         if (match[QPOFFSET_INDEX].matched) {
1414             qpOffset = static_cast<int>(std::strtol(match[QPOFFSET_INDEX].str().c_str(), nullptr, 10)); //10:Decimal
1415         } else {
1416             qpOffset = defaultOffset;
1417         }
1418         temp = match.suffix().str();
1419         int32_t roiWidth = right - left;
1420         int32_t roiHeight = bottom - top;
1421         param.roiInfo[vaildCount].regionEnable = true;
1422         param.roiInfo[vaildCount].absQp = 0;
1423         param.roiInfo[vaildCount].roiQp = static_cast<int32_t>(qpOffset);
1424         param.roiInfo[vaildCount].roiStartX = static_cast<uint32_t>(left);
1425         param.roiInfo[vaildCount].roiStartY = static_cast<uint32_t>(top);
1426         param.roiInfo[vaildCount].roiWidth = static_cast<int32_t>(roiWidth);
1427         param.roiInfo[vaildCount].roiHeight = static_cast<int32_t>(roiHeight);
1428         vaildCount++;
1429     }
1430     AppendToVector(omxBuffer->alongParam, param);
1431 }
1432 
WrapRoiParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,const shared_ptr<Media::Meta> & meta)1433 void HEncoder::WrapRoiParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
1434                                          const shared_ptr<Media::Meta> &meta)
1435 {
1436     std::string roiValue;
1437     if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_ROI_PARAMS, roiValue)) { // historical configuration
1438         return;
1439     }
1440     ParseRoiStringValid(roiValue, omxBuffer);
1441 }
1442 
DealWithResolutionChange(uint32_t newWidth,uint32_t newHeight)1443 void HEncoder::DealWithResolutionChange(uint32_t newWidth, uint32_t newHeight)
1444 {
1445     if (width_ != newWidth || height_ != newHeight) {
1446         HLOGI("resolution changed, %ux%u -> %ux%u", width_, height_, newWidth, newHeight);
1447         width_ = newWidth;
1448         height_ = newHeight;
1449         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_);
1450         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_);
1451         outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_);
1452         outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_);
1453         HLOGI("output format changed: %s", outputFormat_->Stringify().c_str());
1454         callback_->OnOutputFormatChanged(*(outputFormat_.get()));
1455     }
1456 }
1457 
BeforeCbOutToUser(BufferInfo & info)1458 void HEncoder::BeforeCbOutToUser(BufferInfo &info)
1459 {
1460     std::shared_ptr<Media::Meta> meta = info.avBuffer->meta_;
1461     meta->Clear();
1462     BinaryReader reader(static_cast<uint8_t*>(info.omxBuffer->alongParam.data()), info.omxBuffer->alongParam.size());
1463     int* index = nullptr;
1464     while ((index = reader.Read<int>()) != nullptr) {
1465         switch (*index) {
1466             case OMX_IndexConfigCommonOutputSize: {
1467                 auto *param = reader.Read<OMX_FRAMESIZETYPE>();
1468                 IF_TRUE_RETURN_VOID(param == nullptr);
1469                 DealWithResolutionChange(param->nWidth, param->nHeight);
1470                 break;
1471             }
1472             case OMX_IndexParamEncOutQp:
1473                 ExtractPerFrameAveQpParam(reader, meta);
1474                 break;
1475             case OMX_IndexParamEncOutMse:
1476                 ExtractPerFrameMSEParam(reader, meta);
1477                 break;
1478             case OMX_IndexParamEncOutLTR:
1479                 ExtractPerFrameLTRParam(reader, meta);
1480                 break;
1481             case OMX_IndexParamEncOutFrameLayer:
1482                 ExtractPerFrameLayerParam(reader, meta);
1483                 break;
1484             case OMX_IndexParamEncOutRealBitrate:
1485                 ExtractPerFrameRealBitrateParam(reader, meta);
1486                 break;
1487             case OMX_IndexParamEncOutFrameQp:
1488                 ExtractPerFrameFrameQpParam(reader, meta);
1489                 break;
1490             case OMX_IndexParamEncOutMad:
1491                 ExtractPerFrameMadParam(reader, meta);
1492                 break;
1493             case OMX_IndexParamEncOutIRatio:
1494                 ExtractPerFrameIRitioParam(reader, meta);
1495                 break;
1496             default:
1497                 break;
1498         }
1499     }
1500     info.omxBuffer->alongParam.clear();
1501     if (debugMode_) {
1502         auto metaStr = StringifyMeta(meta);
1503         HLOGI("%s", metaStr.c_str());
1504     }
1505 }
1506 
ExtractPerFrameLTRParam(BinaryReader & reader,shared_ptr<Media::Meta> & meta)1507 void HEncoder::ExtractPerFrameLTRParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta)
1508 {
1509     auto *ltrParam = reader.Read<CodecEncOutLTRParam>();
1510     IF_TRUE_RETURN_VOID(ltrParam == nullptr);
1511     meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_LTR, ltrParam->isLTR);
1512     meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_POC, static_cast<int32_t>(ltrParam->poc));
1513 }
1514 
ExtractPerFrameMadParam(BinaryReader & reader,shared_ptr<Media::Meta> & meta)1515 void HEncoder::ExtractPerFrameMadParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta)
1516 {
1517     auto *madParam = reader.Read<CodecEncOutMadParam>();
1518     IF_TRUE_RETURN_VOID(madParam == nullptr);
1519     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADI, madParam->frameMadi);
1520     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADP, madParam->frameMadp);
1521     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_SUM_MADI, madParam->sumMadi);
1522 }
1523 
ExtractPerFrameRealBitrateParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1524 void HEncoder::ExtractPerFrameRealBitrateParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1525 {
1526     auto *realBitrate = reader.Read<OMX_S32>();
1527     IF_TRUE_RETURN_VOID(realBitrate == nullptr);
1528     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_REAL_BITRATE, *realBitrate);
1529 }
1530 
ExtractPerFrameFrameQpParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1531 void HEncoder::ExtractPerFrameFrameQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1532 {
1533     auto *frameQp = reader.Read<OMX_S32>();
1534     IF_TRUE_RETURN_VOID(frameQp == nullptr);
1535     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_QP, *frameQp);
1536 }
1537 
ExtractPerFrameIRitioParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1538 void HEncoder::ExtractPerFrameIRitioParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1539 {
1540     auto *iRatio = reader.Read<OMX_S32>();
1541     IF_TRUE_RETURN_VOID(iRatio == nullptr);
1542     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_I_RATIO, *iRatio);
1543 }
1544 
ExtractPerFrameAveQpParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1545 void HEncoder::ExtractPerFrameAveQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1546 {
1547     auto *averageQp = reader.Read<OMX_S32>();
1548     IF_TRUE_RETURN_VOID(averageQp == nullptr);
1549     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_AVERAGE, *averageQp);
1550 }
1551 
ExtractPerFrameMSEParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1552 void HEncoder::ExtractPerFrameMSEParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1553 {
1554     auto *averageMseLcu = reader.Read<double>();
1555     IF_TRUE_RETURN_VOID(averageMseLcu == nullptr);
1556     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_MSE, *averageMseLcu);
1557 }
1558 
ExtractPerFrameLayerParam(BinaryReader & reader,std::shared_ptr<Media::Meta> & meta)1559 void HEncoder::ExtractPerFrameLayerParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta)
1560 {
1561     auto *frameLayer = reader.Read<OMX_S32>();
1562     IF_TRUE_RETURN_VOID(frameLayer == nullptr);
1563     meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_TEMPORAL_ID, *frameLayer);
1564 }
1565 
AllocInBufsForDynamicSurfaceBuf()1566 int32_t HEncoder::AllocInBufsForDynamicSurfaceBuf()
1567 {
1568     inputBufferPool_.clear();
1569     for (uint32_t i = 0; i < inBufferCnt_; ++i) {
1570         shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer = DynamicSurfaceBufferToOmxBuffer();
1571         shared_ptr<CodecHDI::OmxCodecBuffer> outBuffer = make_shared<CodecHDI::OmxCodecBuffer>();
1572         int32_t ret = compNode_->UseBuffer(OMX_DirInput, *omxBuffer, *outBuffer);
1573         if (ret != HDF_SUCCESS) {
1574             HLOGE("Failed to UseBuffer on input port");
1575             return AVCS_ERR_UNKNOWN;
1576         }
1577         BufferInfo info(true, BufferOwner::OWNED_BY_SURFACE, record_);
1578         info.surfaceBuffer = nullptr;
1579         info.avBuffer = AVBuffer::CreateAVBuffer();
1580         info.omxBuffer = outBuffer;
1581         info.bufferId = outBuffer->bufferId;
1582         inputBufferPool_.push_back(info);
1583     }
1584 
1585     return AVCS_ERR_OK;
1586 }
1587 
EraseBufferFromPool(OMX_DIRTYPE portIndex,size_t i)1588 void HEncoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i)
1589 {
1590     vector<BufferInfo> &pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
1591     if (i >= pool.size()) {
1592         return;
1593     }
1594     const BufferInfo &info = pool[i];
1595     FreeOmxBuffer(portIndex, info);
1596     ReduceOwner(portIndex, info.owner);
1597     pool.erase(pool.begin() + i);
1598 }
1599 
OnQueueInputBuffer(const MsgInfo & msg,BufferOperationMode mode)1600 void HEncoder::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode)
1601 {
1602     if (inputSurface_ && !enableSurfaceModeInputCb_) {
1603         HLOGE("cannot queue input on surface mode");
1604         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
1605         return;
1606     }
1607     // buffer mode or surface callback mode
1608     uint32_t bufferId = 0;
1609     (void)msg.param->GetValue(BUFFER_ID, bufferId);
1610     SCOPED_TRACE_FMT("id: %u", bufferId);
1611     BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId);
1612     if (bufferInfo == nullptr) {
1613         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1614         return;
1615     }
1616     if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) {
1617         HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner));
1618         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
1619         return;
1620     }
1621     bool discard = false;
1622     if (inputSurface_ && bufferInfo->avBuffer->meta_->GetData(
1623         OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_DISCARD, discard) && discard) {
1624         HLOGI("inBufId = %u, discard by user, pts = %" PRId64, bufferId, bufferInfo->avBuffer->pts_);
1625         record_[OMX_DirInput].discardCntInterval_++;
1626         bufferInfo->avBuffer->meta_->Clear();
1627         ResetSlot(*bufferInfo);
1628         ReplyErrorCode(msg.id, AVCS_ERR_OK);
1629         return;
1630     }
1631     SetBufferPts(bufferInfo);
1632     ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US);
1633     WrapSurfaceBufferToSlot(*bufferInfo, bufferInfo->surfaceBuffer, bufferInfo->avBuffer->pts_,
1634         UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_)));
1635     if (enableVariableFrameRate_ && CalculateFrameRateParamIntoOmxBuffer(bufferInfo->omxBuffer->pts) != 0) {
1636         ReplyErrorCode(msg.id, AVCS_ERR_INPUT_DATA_ERROR);
1637     }
1638     WrapPerFrameParamIntoOmxBuffer(bufferInfo->omxBuffer, bufferInfo->avBuffer->meta_);
1639     ReplyErrorCode(msg.id, AVCS_ERR_OK);
1640     int32_t err = HCodec::OnQueueInputBuffer(mode, bufferInfo);
1641     if (err != AVCS_ERR_OK) {
1642         ResetSlot(*bufferInfo);
1643         callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR);
1644     }
1645 }
1646 
SetBufferPts(BufferInfo * info)1647 void HEncoder::SetBufferPts(BufferInfo* info)
1648 {
1649     HLOGD("avBuffer->pts_ before setted, absolute pts=%ld", info->avBuffer->pts_);
1650     bool bret = info->avBuffer->meta_->GetData(
1651         OHOS::Media::Tag::VIDEO_ENCODE_SET_FRAME_PTS, info->avBuffer->pts_);
1652     HLOGD("avBuffer->pts_ after setted, relative pts=%ld, bret=%d", info->avBuffer->pts_, bret);
1653 }
1654 
OnGetBufferFromSurface(const ParamSP & param)1655 void HEncoder::OnGetBufferFromSurface(const ParamSP& param)
1656 {
1657     if (GetOneBufferFromSurface()) {
1658         TraverseAvaliableBuffers();
1659     }
1660 }
1661 
GetOneBufferFromSurface()1662 bool HEncoder::GetOneBufferFromSurface()
1663 {
1664     SCOPED_TRACE();
1665     InSurfaceBufferEntry entry{};
1666     entry.item = make_shared<BufferItem>();
1667     GSError ret = inputSurface_->AcquireBuffer(
1668         entry.item->buffer, entry.item->fence, entry.pts, entry.item->damage);
1669     if (ret != GSERROR_OK || entry.item->buffer == nullptr) {
1670         return false;
1671     }
1672     if (!CheckBufPixFmt(entry.item->buffer)) {
1673         return false;
1674     }
1675     entry.item->generation = ++currGeneration_;
1676     entry.item->surface = inputSurface_;
1677     avaliableBuffers_.push_back(entry);
1678     newestBuffer_ = entry;
1679     HLOGD("generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", now list size = %zu",
1680           entry.item->generation, entry.item->buffer->GetSeqNum(), entry.pts, avaliableBuffers_.size());
1681     if (repeatUs_ != 0) {
1682         SendRepeatMsg(entry.item->generation);
1683     }
1684     return true;
1685 }
1686 
SendRepeatMsg(uint64_t generation)1687 void HEncoder::SendRepeatMsg(uint64_t generation)
1688 {
1689     ParamSP param = make_shared<ParamBundle>();
1690     param->SetValue("generation", generation);
1691     SendAsyncMsg(MsgWhat::CHECK_IF_REPEAT, param, repeatUs_);
1692 }
1693 
RepeatIfNecessary(const ParamSP & param)1694 void HEncoder::RepeatIfNecessary(const ParamSP& param)
1695 {
1696     uint64_t generation = 0;
1697     param->GetValue("generation", generation);
1698     if (inputPortEos_ || (repeatUs_ == 0) || newestBuffer_.item == nullptr ||
1699         newestBuffer_.item->generation != generation) {
1700         return;
1701     }
1702     if (repeatMaxCnt_ > 0 && newestBuffer_.repeatTimes >= repeatMaxCnt_) {
1703         HLOGD("stop repeat generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", which has been repeated %d times",
1704               generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newestBuffer_.repeatTimes);
1705         return;
1706     }
1707     if (avaliableBuffers_.size() >= MAX_LIST_SIZE) {
1708         HLOGW("stop repeat, list size to big: %zu", avaliableBuffers_.size());
1709         return;
1710     }
1711     int64_t newPts = newestBuffer_.pts + static_cast<int64_t>(repeatUs_);
1712     HLOGD("generation = %" PRIu64 ", seq = %u, pts %" PRId64 " -> %" PRId64,
1713           generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newPts);
1714     newestBuffer_.pts = newPts;
1715     newestBuffer_.repeatTimes++;
1716     avaliableBuffers_.push_back(newestBuffer_);
1717     SendRepeatMsg(generation);
1718     TraverseAvaliableBuffers();
1719 }
1720 
TraverseAvaliableBuffers()1721 void HEncoder::TraverseAvaliableBuffers()
1722 {
1723     while (!avaliableBuffers_.empty()) {
1724         auto it = find_if(inputBufferPool_.begin(), inputBufferPool_.end(),
1725                           [](const BufferInfo &info) { return info.owner == BufferOwner::OWNED_BY_SURFACE; });
1726         if (it == inputBufferPool_.end()) {
1727             return;
1728         }
1729         InSurfaceBufferEntry entry = avaliableBuffers_.front();
1730         avaliableBuffers_.pop_front();
1731         SubmitOneBuffer(entry, *it);
1732     }
1733 }
1734 
SubmitOneBuffer(InSurfaceBufferEntry & entry,BufferInfo & info)1735 void HEncoder::SubmitOneBuffer(InSurfaceBufferEntry& entry, BufferInfo &info)
1736 {
1737     if (entry.item == nullptr) {
1738         ChangeOwner(info, BufferOwner::OWNED_BY_US);
1739         HLOGI("got input eos");
1740         inputPortEos_ = true;
1741         info.omxBuffer->flag = OMX_BUFFERFLAG_EOS;
1742         info.omxBuffer->bufferhandle = nullptr;
1743         info.omxBuffer->filledLen = 0;
1744         info.surfaceBuffer = nullptr;
1745         InBufUsToOmx(info);
1746         return;
1747     }
1748     if (!WaitFence(entry.item->fence)) {
1749         return;
1750     }
1751     ChangeOwner(info, BufferOwner::OWNED_BY_US);
1752     WrapSurfaceBufferToSlot(info, entry.item->buffer, entry.pts, 0);
1753     encodingBuffers_[info.bufferId] = entry;
1754     if (enableSurfaceModeInputCb_) {
1755         info.avBuffer->pts_ = entry.pts;
1756         InBufUsToOmx(info);
1757     } else {
1758         CheckPts(info.omxBuffer->pts);
1759         int32_t err = InBufUsToOmx(info);
1760         if (err != AVCS_ERR_OK) {
1761             ResetSlot(info);
1762             callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR);
1763         }
1764     }
1765 }
1766 
CheckPts(int64_t currentPts)1767 void HEncoder::CheckPts(int64_t currentPts)
1768 {
1769     if (!pts_.has_value()) {
1770         pts_ = currentPts;
1771     } else {
1772         int64_t lastPts = pts_.value();
1773         if (lastPts != 0 && currentPts != 0 && lastPts >= currentPts) {
1774             HLOGW("pts not incremental: last %" PRId64 ", current %" PRId64, lastPts, currentPts);
1775         }
1776         pts_ = currentPts;
1777     }
1778 }
1779 
OnOMXEmptyBufferDone(uint32_t bufferId,BufferOperationMode mode)1780 void HEncoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode)
1781 {
1782     SCOPED_TRACE_FMT("id: %u", bufferId);
1783     BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId);
1784     if (info == nullptr) {
1785         HLOGE("unknown buffer id %u", bufferId);
1786         return;
1787     }
1788     if (info->owner != BufferOwner::OWNED_BY_OMX) {
1789         HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info->owner));
1790         return;
1791     }
1792     if (inputSurface_) {
1793         ResetSlot(*info);
1794         if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
1795             TraverseAvaliableBuffers();
1796         }
1797     } else {
1798         ChangeOwner(*info, BufferOwner::OWNED_BY_US);
1799         if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
1800             NotifyUserToFillThisInBuffer(*info);
1801         }
1802     }
1803 }
1804 
ResetSlot(BufferInfo & info)1805 void HEncoder::ResetSlot(BufferInfo& info)
1806 {
1807     ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE);
1808     encodingBuffers_.erase(info.bufferId);
1809     info.surfaceBuffer = nullptr;
1810 }
1811 
OnBufferAvailable()1812 void HEncoder::EncoderBuffersConsumerListener::OnBufferAvailable()
1813 {
1814     std::shared_ptr<MsgToken> codec = codec_.lock();
1815     if (codec != nullptr) {
1816         codec->SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
1817     }
1818 }
1819 
OnSignalEndOfInputStream(const MsgInfo & msg)1820 void HEncoder::OnSignalEndOfInputStream(const MsgInfo &msg)
1821 {
1822     if (inputSurface_ == nullptr) {
1823         HLOGE("can only be called in surface mode");
1824         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
1825         return;
1826     }
1827     ReplyErrorCode(msg.id, AVCS_ERR_OK);
1828     avaliableBuffers_.push_back(InSurfaceBufferEntry {});
1829     TraverseAvaliableBuffers();
1830 }
1831 
OnEnterUninitializedState()1832 void HEncoder::OnEnterUninitializedState()
1833 {
1834     if (inputSurface_) {
1835         inputSurface_->UnregisterConsumerListener();
1836     }
1837     avaliableBuffers_.clear();
1838     newestBuffer_.item.reset();
1839     encodingBuffers_.clear();
1840     pts_ = std::nullopt;
1841 }
1842 
~BufferItem()1843 HEncoder::BufferItem::~BufferItem()
1844 {
1845     if (surface && buffer) {
1846         LOGD("release seq = %u", buffer->GetSeqNum());
1847         surface->ReleaseBuffer(buffer, -1);
1848     }
1849 }
1850 
1851 } // namespace OHOS::MediaAVCodec
1852