• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hencoder.h"
17 #include <map>
18 #include <utility>
19 #include "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*>(&param);
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