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