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*>(¶m);
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