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
25 namespace OHOS::MediaAVCodec {
26 using namespace std;
27 using namespace OHOS::HDI::Codec::V1_0;
28
OnConfigure(const Format & format)29 int32_t HEncoder::OnConfigure(const Format &format)
30 {
31 configFormat_ = make_shared<Format>(format);
32 optional<double> frameRate = GetFrameRateFromUser(format);
33 int32_t ret = SetupPort(format, frameRate);
34 if (ret != AVCS_ERR_OK) {
35 return ret;
36 }
37 switch (static_cast<int>(codingType_)) {
38 case OMX_VIDEO_CodingAVC:
39 ret = SetupAVCEncoderParameters(format, frameRate);
40 break;
41 case CODEC_OMX_VIDEO_CodingHEVC:
42 ret = SetupHEVCEncoderParameters(format, frameRate);
43 break;
44 default:
45 break;
46 }
47 if (ret != AVCS_ERR_OK) {
48 HLOGW("set protocol param failed");
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 return AVCS_ERR_OK;
59 }
60
SetColorAspects(const Format & format)61 int32_t HEncoder::SetColorAspects(const Format &format)
62 {
63 int range = -1;
64 ColorPrimary primary = COLOR_PRIMARY_UNSPECIFIED;
65 TransferCharacteristic transfer = TRANSFER_CHARACTERISTIC_UNSPECIFIED;
66 MatrixCoefficient matrix = MATRIX_COEFFICIENT_UNSPECIFIED;
67
68 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, range)) {
69 HLOGI("user set range flag %{public}d", range);
70 }
71 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, *(int*)&primary)) {
72 HLOGI("user set primary %{public}d", primary);
73 }
74 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, *(int*)&transfer)) {
75 HLOGI("user set transfer %{public}d", transfer);
76 }
77 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, *(int*)&matrix)) {
78 HLOGI("user set matrix %{public}d", matrix);
79 }
80 if (range == -1 && primary == COLOR_PRIMARY_UNSPECIFIED &&
81 transfer == TRANSFER_CHARACTERISTIC_UNSPECIFIED &&
82 matrix == MATRIX_COEFFICIENT_UNSPECIFIED) {
83 return AVCS_ERR_OK;
84 }
85
86 CodecVideoColorspace param;
87 InitOMXParamExt(param);
88 param.portIndex = OMX_DirInput;
89
90 param.aspects.range = RANGE_UNSPECIFIED;
91 if (range != -1) {
92 param.aspects.range = TypeConverter::RangeFlagToOmxRangeType(static_cast<bool>(range));
93 }
94 param.aspects.primaries = TypeConverter::InnerPrimaryToOmxPrimary(primary);
95 param.aspects.transfer = TypeConverter::InnerTransferToOmxTransfer(transfer);
96 param.aspects.matrixCoeffs = TypeConverter::InnerMatrixToOmxMatrix(matrix);
97
98 if (!SetParameter(OMX_IndexColorAspects, param, true)) {
99 HLOGE("failed to set CodecVideoColorSpace");
100 return AVCS_ERR_UNKNOWN;
101 }
102 HLOGI("set omx color aspects (full range:%{public}d, primary:%{public}d, "
103 "transfer:%{public}d, matrix:%{public}d) succ",
104 param.aspects.range, param.aspects.primaries, param.aspects.transfer, param.aspects.matrixCoeffs);
105 return AVCS_ERR_OK;
106 }
107
CalcInputBufSize(PortInfo & info,VideoPixelFormat pixelFmt)108 void HEncoder::CalcInputBufSize(PortInfo& info, VideoPixelFormat pixelFmt)
109 {
110 uint32_t inSize = AlignTo(info.width, 128u) * AlignTo(info.height, 128u); // 128: block size
111 if (pixelFmt == RGBA) {
112 inSize = inSize * 4; // 4 byte per pixel
113 } else {
114 inSize = inSize * 3 / 2; // 3: nom, 2: denom
115 }
116 info.inputBufSize = inSize;
117 }
118
SetupPort(const Format & format,std::optional<double> frameRate)119 int32_t HEncoder::SetupPort(const Format &format, std::optional<double> frameRate)
120 {
121 int32_t width;
122 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0) {
123 HLOGE("format should contain width");
124 return AVCS_ERR_INVALID_VAL;
125 }
126 int32_t height;
127 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0) {
128 HLOGE("format should contain height");
129 return AVCS_ERR_INVALID_VAL;
130 }
131 HLOGI("user set width %{public}d, height %{public}d", width, height);
132 if (!GetPixelFmtFromUser(format)) {
133 return AVCS_ERR_INVALID_VAL;
134 }
135
136 if (!frameRate.has_value()) {
137 HLOGI("user don't set valid frame rate, use default 60.0");
138 frameRate = 60.0; // default frame rate 60.0
139 }
140
141 PortInfo inputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), std::nullopt,
142 OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()};
143 CalcInputBufSize(inputPortInfo, configuredFmt_.innerFmt);
144 int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo);
145 if (ret != AVCS_ERR_OK) {
146 return ret;
147 }
148
149 PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), std::nullopt,
150 codingType_, std::nullopt, frameRate.value()};
151 ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo);
152 if (ret != AVCS_ERR_OK) {
153 return ret;
154 }
155 return AVCS_ERR_OK;
156 }
157
UpdateInPortFormat()158 int32_t HEncoder::UpdateInPortFormat()
159 {
160 OMX_PARAM_PORTDEFINITIONTYPE def;
161 InitOMXParam(def);
162 def.nPortIndex = OMX_DirInput;
163 if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
164 HLOGE("get input port definition failed");
165 return AVCS_ERR_UNKNOWN;
166 }
167 PrintPortDefinition(def);
168 uint32_t w = def.format.video.nFrameWidth;
169 uint32_t h = def.format.video.nFrameHeight;
170 inBufferCnt_ = def.nBufferCountActual;
171
172 if (inputFormat_ == nullptr) {
173 inputFormat_ = make_shared<Format>();
174 }
175 inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w);
176 inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h);
177 inputFormat_->PutIntValue("stride", def.format.video.nStride);
178 sharedBufferFormat_ = { w, h, def.format.video.nStride, OMX_VIDEO_CodingUnused, configuredFmt_ };
179 return AVCS_ERR_OK;
180 }
181
UpdateOutPortFormat()182 int32_t HEncoder::UpdateOutPortFormat()
183 {
184 OMX_PARAM_PORTDEFINITIONTYPE def;
185 InitOMXParam(def);
186 def.nPortIndex = OMX_DirOutput;
187 if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
188 HLOGE("get output port definition failed");
189 return AVCS_ERR_UNKNOWN;
190 }
191 PrintPortDefinition(def);
192 if (outputFormat_ == nullptr) {
193 outputFormat_ = make_shared<Format>();
194 }
195 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth);
196 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight);
197 return AVCS_ERR_OK;
198 }
199
SetPFramesSpacing(int32_t iFramesIntervalInMs,double frameRate,uint32_t bFramesSpacing=0)200 static uint32_t SetPFramesSpacing(int32_t iFramesIntervalInMs, double frameRate, uint32_t bFramesSpacing = 0)
201 {
202 if (iFramesIntervalInMs < 0) { // IPPPP...
203 return UINT32_MAX - 1;
204 }
205 if (iFramesIntervalInMs == 0) { // IIIII...
206 return 0;
207 }
208 uint32_t iFramesInterval = iFramesIntervalInMs * frameRate / 1000;
209 uint32_t pFramesSpacing = iFramesInterval / (bFramesSpacing + 1);
210 return pFramesSpacing > 0 ? pFramesSpacing - 1 : 0;
211 }
212
GetBitRateFromUser(const Format & format)213 std::optional<uint32_t> HEncoder::GetBitRateFromUser(const Format &format)
214 {
215 int64_t bitRateLong;
216 if (format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateLong) &&
217 bitRateLong > 0 && bitRateLong <= UINT32_MAX) {
218 LOGI("user set bit rate %" PRId64 "", bitRateLong);
219 return static_cast<uint32_t>(bitRateLong);
220 }
221 int32_t bitRateInt;
222 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateInt) &&
223 bitRateInt > 0) {
224 LOGI("user set bit rate %d", bitRateInt);
225 return static_cast<uint32_t>(bitRateInt);
226 }
227 return nullopt;
228 }
229
ConfigureOutputBitrate(const Format & format)230 int32_t HEncoder::ConfigureOutputBitrate(const Format &format)
231 {
232 VideoEncodeBitrateMode mode;
233 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, *reinterpret_cast<int*>(&mode))) {
234 return AVCS_ERR_OK;
235 }
236 switch (mode) {
237 case CBR:
238 case VBR: {
239 optional<uint32_t> bitRate = GetBitRateFromUser(format);
240 if (!bitRate.has_value()) {
241 HLOGW("user set CBR/VBR mode but not set valid bitrate");
242 return AVCS_ERR_INVALID_VAL;
243 }
244 OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
245 InitOMXParam(bitrateType);
246 bitrateType.nPortIndex = OMX_DirOutput;
247 bitrateType.eControlRate = (mode == CBR) ? OMX_Video_ControlRateConstant : OMX_Video_ControlRateVariable;
248 bitrateType.nTargetBitrate = bitRate.value();
249 if (!SetParameter(OMX_IndexParamVideoBitrate, bitrateType)) {
250 HLOGE("failed to set OMX_IndexParamVideoBitrate");
251 return AVCS_ERR_UNKNOWN;
252 }
253 HLOGI("set %{public}s mode and target bitrate %{public}u bps succ",
254 (mode == CBR) ? "CBR" : "VBR", bitrateType.nTargetBitrate);
255 return AVCS_ERR_OK;
256 }
257 case CQ: {
258 int32_t quality;
259 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality) || quality < 0) {
260 HLOGW("user set CQ mode but not set valid quality");
261 return AVCS_ERR_INVALID_VAL;
262 }
263 ControlRateConstantQuality bitrateType;
264 InitOMXParamExt(bitrateType);
265 bitrateType.portIndex = OMX_DirOutput;
266 bitrateType.qualityValue = static_cast<uint32_t>(quality);
267 if (!SetParameter(OMX_IndexParamControlRateConstantQuality, bitrateType)) {
268 HLOGE("failed to set OMX_IndexParamControlRateConstantQuality");
269 return AVCS_ERR_UNKNOWN;
270 }
271 HLOGI("set CQ mode and target quality %{public}u succ", bitrateType.qualityValue);
272 return AVCS_ERR_OK;
273 }
274 default:
275 return AVCS_ERR_INVALID_VAL;
276 }
277 }
278
SetupAVCEncoderParameters(const Format & format,std::optional<double> frameRate)279 int32_t HEncoder::SetupAVCEncoderParameters(const Format &format, std::optional<double> frameRate)
280 {
281 int32_t iFrameInterval;
282 AVCProfile profile;
283 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) ||
284 !frameRate.has_value() ||
285 !format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int*>(&profile))) {
286 return AVCS_ERR_OK;
287 }
288 optional<OMX_VIDEO_AVCPROFILETYPE> omxAvcProfile = TypeConverter::InnerAvcProfileToOmxProfile(profile);
289 if (!omxAvcProfile.has_value()) {
290 return AVCS_ERR_INVALID_VAL;
291 }
292
293 OMX_VIDEO_PARAM_AVCTYPE avcType;
294 InitOMXParam(avcType);
295 avcType.nPortIndex = OMX_DirOutput;
296 if (!GetParameter(OMX_IndexParamVideoAvc, avcType)) {
297 HLOGE("get OMX_IndexParamVideoAvc parameter fail");
298 return AVCS_ERR_UNKNOWN;
299 }
300 avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
301 avcType.eProfile = omxAvcProfile.value();
302 avcType.nBFrames = 0;
303
304 SetAvcFields(avcType, iFrameInterval, frameRate.value());
305 if (avcType.nBFrames != 0) {
306 avcType.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
307 }
308 avcType.bEnableUEP = OMX_FALSE;
309 avcType.bEnableFMO = OMX_FALSE;
310 avcType.bEnableASO = OMX_FALSE;
311 avcType.bEnableRS = OMX_FALSE;
312 avcType.bFrameMBsOnly = OMX_TRUE;
313 avcType.bMBAFF = OMX_FALSE;
314 avcType.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
315
316 if (!SetParameter(OMX_IndexParamVideoAvc, avcType)) {
317 HLOGE("failed to set OMX_IndexParamVideoAvc");
318 return AVCS_ERR_UNKNOWN;
319 }
320 return AVCS_ERR_OK;
321 }
322
SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE & avcType,int32_t iFrameInterval,double frameRate)323 void HEncoder::SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE& avcType, int32_t iFrameInterval, double frameRate)
324 {
325 HLOGI("iFrameInterval:%{public}d, frameRate:%{public}.2f, eProfile:0x%{public}x, eLevel:0x%{public}x",
326 iFrameInterval, frameRate, avcType.eProfile, avcType.eLevel);
327
328 if (avcType.eProfile == OMX_VIDEO_AVCProfileBaseline) {
329 avcType.nSliceHeaderSpacing = 0;
330 avcType.bUseHadamard = OMX_TRUE;
331 avcType.nRefFrames = 1;
332 avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
333 if (avcType.nPFrames == 0) {
334 avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
335 }
336 avcType.nRefIdx10ActiveMinus1 = 0;
337 avcType.nRefIdx11ActiveMinus1 = 0;
338 avcType.bEntropyCodingCABAC = OMX_FALSE;
339 avcType.bWeightedPPrediction = OMX_FALSE;
340 avcType.bconstIpred = OMX_FALSE;
341 avcType.bDirect8x8Inference = OMX_FALSE;
342 avcType.bDirectSpatialTemporal = OMX_FALSE;
343 avcType.nCabacInitIdc = 0;
344 } else if (avcType.eProfile == OMX_VIDEO_AVCProfileMain || avcType.eProfile == OMX_VIDEO_AVCProfileHigh) {
345 avcType.nSliceHeaderSpacing = 0;
346 avcType.bUseHadamard = OMX_TRUE;
347 avcType.nRefFrames = avcType.nBFrames == 0 ? 1 : 2; // 2 is number of reference frames
348 avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames);
349 avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
350 avcType.nRefIdx10ActiveMinus1 = 0;
351 avcType.nRefIdx11ActiveMinus1 = 0;
352 avcType.bEntropyCodingCABAC = OMX_TRUE;
353 avcType.bWeightedPPrediction = OMX_TRUE;
354 avcType.bconstIpred = OMX_TRUE;
355 avcType.bDirect8x8Inference = OMX_TRUE;
356 avcType.bDirectSpatialTemporal = OMX_TRUE;
357 avcType.nCabacInitIdc = 1;
358 }
359 }
360
SetupHEVCEncoderParameters(const Format & format,std::optional<double> frameRate)361 int32_t HEncoder::SetupHEVCEncoderParameters(const Format &format, std::optional<double> frameRate)
362 {
363 CodecVideoParamHevc hevcType;
364 InitOMXParamExt(hevcType);
365 hevcType.portIndex = OMX_DirOutput;
366 if (!GetParameter(OMX_IndexParamVideoHevc, hevcType)) {
367 HLOGE("get OMX_IndexParamVideoHevc parameter fail");
368 return AVCS_ERR_UNKNOWN;
369 }
370
371 HEVCProfile profile;
372 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int*>(&profile))) {
373 optional<CodecHevcProfile> omxHevcProfile = TypeConverter::InnerHevcProfileToOmxProfile(profile);
374 if (omxHevcProfile.has_value()) {
375 hevcType.profile = omxHevcProfile.value();
376 HLOGI("HEVCProfile %{public}d, CodecHevcProfile 0x%{public}x", profile, hevcType.profile);
377 }
378 }
379
380 int32_t iFrameInterval;
381 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) &&
382 iFrameInterval >= 0 && frameRate.has_value()) {
383 if (iFrameInterval == 0) { // all intra
384 hevcType.keyFrameInterval = 1;
385 } else {
386 hevcType.keyFrameInterval = iFrameInterval * frameRate.value() / TIME_RATIO_S_TO_MS;
387 }
388 HLOGI("frameRate %{public}.2f, iFrameInterval %{public}d, keyFrameInterval %{public}u",
389 frameRate.value(), iFrameInterval, hevcType.keyFrameInterval);
390 }
391
392 if (!SetParameter(OMX_IndexParamVideoHevc, hevcType)) {
393 HLOGE("failed to set OMX_IndexParamVideoHevc");
394 return AVCS_ERR_INVALID_VAL;
395 }
396 return AVCS_ERR_OK;
397 }
398
RequestIDRFrame()399 int32_t HEncoder::RequestIDRFrame()
400 {
401 OMX_CONFIG_INTRAREFRESHVOPTYPE params;
402 InitOMXParam(params);
403 params.nPortIndex = OMX_DirOutput;
404 params.IntraRefreshVOP = OMX_TRUE;
405 if (!SetParameter(OMX_IndexConfigVideoIntraVOPRefresh, params, true)) {
406 HLOGE("failed to request IDR frame");
407 return AVCS_ERR_UNKNOWN;
408 }
409 HLOGI("Set IDR Frame success");
410 return AVCS_ERR_OK;
411 }
412
OnSetParameters(const Format & format)413 int32_t HEncoder::OnSetParameters(const Format &format)
414 {
415 int32_t requestIdr;
416 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, requestIdr) && requestIdr != 0) {
417 int32_t ret = RequestIDRFrame();
418 if (ret != AVCS_ERR_OK) {
419 return ret;
420 }
421 }
422 return AVCS_ERR_OK;
423 }
424
SubmitOutputBuffersToOmxNode()425 int32_t HEncoder::SubmitOutputBuffersToOmxNode()
426 {
427 for (BufferInfo& info : outputBufferPool_) {
428 if (info.owner == BufferOwner::OWNED_BY_US) {
429 int32_t ret = NotifyOmxToFillThisOutBuffer(info);
430 if (ret != AVCS_ERR_OK) {
431 return ret;
432 }
433 } else {
434 HLOGE("buffer should be owned by us");
435 return AVCS_ERR_UNKNOWN;
436 }
437 }
438 return AVCS_ERR_OK;
439 }
440
ReadyToStart()441 bool HEncoder::ReadyToStart()
442 {
443 if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) {
444 return false;
445 }
446 if (inputSurface_ == nullptr) {
447 inputBufferType_ = BufferType::PRESET_ASHM_BUFFER;
448 HLOGI("buffer mode");
449 } else {
450 inputBufferType_ = BufferType::DYNAMIC_SURFACE_BUFFER;
451 avaliableBuffers.clear();
452 HLOGI("surface mode");
453 }
454 return true;
455 }
456
SubmitAllBuffersOwnedByUs()457 int32_t HEncoder::SubmitAllBuffersOwnedByUs()
458 {
459 HLOGI(">>");
460 if (isBufferCirculating_) {
461 HLOGI("buffer is already circulating, no need to do again");
462 return AVCS_ERR_OK;
463 }
464 int32_t ret = SubmitOutputBuffersToOmxNode();
465 if (ret != AVCS_ERR_OK) {
466 return ret;
467 }
468
469 if (inputBufferType_ == BufferType::PRESET_ASHM_BUFFER) {
470 for (BufferInfo& info : inputBufferPool_) {
471 if (info.owner == BufferOwner::OWNED_BY_US) {
472 NotifyUserToFillThisInBuffer(info);
473 }
474 }
475 }
476
477 isBufferCirculating_ = true;
478 return AVCS_ERR_OK;
479 }
480
OnCreateInputSurface()481 sptr<Surface> HEncoder::OnCreateInputSurface()
482 {
483 if (inputSurface_ != nullptr) {
484 HLOGE("inputSurface_ already exists");
485 return nullptr;
486 }
487
488 sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("HEncoderSurface");
489 if (consumerSurface == nullptr) {
490 HLOGE("Create the surface consummer fail");
491 return nullptr;
492 }
493
494 sptr<IBufferProducer> producer = consumerSurface->GetProducer();
495 if (producer == nullptr) {
496 HLOGE("Get the surface producer fail");
497 return nullptr;
498 }
499
500 sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
501 if (producerSurface == nullptr) {
502 HLOGE("CreateSurfaceAsProducer fail");
503 return nullptr;
504 }
505
506 UseBufferType useBufferTypes;
507 InitOMXParamExt(useBufferTypes);
508 useBufferTypes.portIndex = OMX_DirInput;
509 useBufferTypes.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
510 if (!SetParameter(OMX_IndexParamUseBufferType, useBufferTypes)) {
511 HLOGE("set OMX_IndexParamUseBufferType failed");
512 return nullptr;
513 }
514
515 sptr<IBufferConsumerListener> listener = new EncoderBuffersConsumerListener(this);
516 consumerSurface->RegisterConsumerListener(listener);
517
518 inputSurface_ = consumerSurface;
519 if (inBufferCnt_ > inputSurface_->GetQueueSize()) {
520 inputSurface_->SetQueueSize(inBufferCnt_);
521 }
522 HLOGI("queue size %u", inputSurface_->GetQueueSize());
523 return producerSurface;
524 }
525
OnSetInputSurface(sptr<Surface> & inputSurface)526 int32_t HEncoder::OnSetInputSurface(sptr<Surface>& inputSurface)
527 {
528 if (inputSurface_ != nullptr) {
529 HLOGE("inputSurface_ already exists");
530 return AVCS_ERR_INVALID_OPERATION;
531 }
532
533 if (inputSurface == nullptr) {
534 HLOGE("surface is null");
535 return AVCS_ERR_INVALID_VAL;
536 }
537 if (inputSurface->IsConsumer()) {
538 HLOGE("expect a producer surface but got a consumer surface");
539 return AVCS_ERR_INVALID_VAL;
540 }
541 inputSurface_ = inputSurface;
542 HLOGI("succ");
543 return AVCS_ERR_OK;
544 }
545
AllocOmxBufferOfDynamicType()546 shared_ptr<OmxCodecBuffer> HEncoder::AllocOmxBufferOfDynamicType()
547 {
548 auto omxBuffer = make_shared<OmxCodecBuffer>();
549 omxBuffer->size = sizeof(OmxCodecBuffer);
550 omxBuffer->version.version.majorVersion = 1;
551 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE;
552 omxBuffer->allocLen = 0;
553 omxBuffer->fenceFd = -1;
554 omxBuffer->pts = 0;
555 omxBuffer->flag = 0;
556 return omxBuffer;
557 }
558
WrapSurfaceBufferIntoOmxBuffer(shared_ptr<OmxCodecBuffer> & omxBuffer,const sptr<SurfaceBuffer> & surfaceBuffer,int64_t pts)559 int32_t HEncoder::WrapSurfaceBufferIntoOmxBuffer(shared_ptr<OmxCodecBuffer>& omxBuffer,
560 const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts)
561 {
562 BufferHandle* bufferHandle = surfaceBuffer->GetBufferHandle();
563 if (bufferHandle == nullptr) {
564 HLOGE("null BufferHandle");
565 return AVCS_ERR_UNKNOWN;
566 }
567 omxBuffer->bufferhandle = new NativeBuffer(bufferHandle);
568 omxBuffer->filledLen = surfaceBuffer->GetSize();
569 omxBuffer->fenceFd = -1;
570 omxBuffer->pts = pts;
571 omxBuffer->flag = 0;
572 return AVCS_ERR_OK;
573 }
574
AllocInBufsForDynamicSurfaceBuf()575 int32_t HEncoder::AllocInBufsForDynamicSurfaceBuf()
576 {
577 inputBufferPool_.clear();
578 for (uint32_t i = 0; i < inBufferCnt_; ++i) {
579 shared_ptr<OmxCodecBuffer> omxBuffer = AllocOmxBufferOfDynamicType();
580 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
581 int32_t ret = compNode_->UseBuffer(OMX_DirInput, *omxBuffer, *outBuffer);
582 if (ret != HDF_SUCCESS) {
583 HLOGE("Failed to UseBuffer on input port");
584 return AVCS_ERR_UNKNOWN;
585 }
586 BufferInfo info {};
587 info.isInput = true;
588 info.owner = BufferOwner::OWNED_BY_US;
589 info.surfaceBuffer = nullptr;
590 info.sharedBuffer = nullptr;
591 info.omxBuffer = outBuffer;
592 info.bufferId = outBuffer->bufferId;
593 inputBufferPool_.push_back(info);
594 }
595
596 return AVCS_ERR_OK;
597 }
598
AllocateBuffersOnPort(OMX_DIRTYPE portIndex)599 int32_t HEncoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex)
600 {
601 if ((portIndex == OMX_DirInput) && (inputBufferType_ == BufferType::DYNAMIC_SURFACE_BUFFER)) {
602 return AllocInBufsForDynamicSurfaceBuf();
603 } else {
604 return AllocateSharedBuffers(portIndex, (portIndex == OMX_DirInput));
605 }
606 }
607
EraseBufferFromPool(OMX_DIRTYPE portIndex,size_t i)608 void HEncoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i)
609 {
610 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
611 if (i >= pool.size()) {
612 return;
613 }
614 const BufferInfo& info = pool[i];
615 FreeOmxBuffer(portIndex, info);
616 pool.erase(pool.begin() + i);
617 }
618
OnQueueInputBuffer(const MsgInfo & msg,BufferOperationMode mode)619 void HEncoder::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode)
620 {
621 if (inputBufferType_ == BufferType::DYNAMIC_SURFACE_BUFFER) {
622 HLOGE("The current input buffer is surface buffer");
623 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
624 return;
625 }
626 HCodec::OnQueueInputBuffer(msg, mode);
627 }
628
OnGetBufferFromSurface()629 void HEncoder::OnGetBufferFromSurface()
630 {
631 InSurfaceBufferEntry entry;
632 GSError ret = inputSurface_->AcquireBuffer(entry.buffer, entry.fence, entry.timestamp, entry.damage);
633 if (ret != GSERROR_OK || entry.buffer == nullptr) {
634 HLOGW("AcquireBuffer failed");
635 return;
636 }
637 avaliableBuffers.push_back(entry);
638 HLOGD("now we have %{public}zu buffer wait to be encode", avaliableBuffers.size());
639 FindAllIdleSlotAndSubmit();
640 }
641
FindAllIdleSlotAndSubmit()642 void HEncoder::FindAllIdleSlotAndSubmit()
643 {
644 while (true) {
645 if (avaliableBuffers.empty()) {
646 return;
647 }
648 auto it = find_if(inputBufferPool_.begin(), inputBufferPool_.end(), [](const BufferInfo& info) {
649 return info.owner == BufferOwner::OWNED_BY_US;
650 });
651 if (it == inputBufferPool_.end()) {
652 return;
653 }
654 SubmitOneBuffer(*it);
655 }
656 }
657
SubmitOneBuffer(BufferInfo & info)658 void HEncoder::SubmitOneBuffer(BufferInfo& info)
659 {
660 InSurfaceBufferEntry entry = avaliableBuffers.front();
661 avaliableBuffers.pop_front();
662 if (entry.fence != nullptr && entry.fence->IsValid()) {
663 int waitRes = entry.fence->Wait(WAIT_FENCE_MS);
664 if (waitRes != 0) {
665 HLOGW("wait fence time out");
666 }
667 }
668 int32_t err = WrapSurfaceBufferIntoOmxBuffer(info.omxBuffer, entry.buffer, entry.timestamp);
669 if (err != AVCS_ERR_OK) {
670 inputSurface_->ReleaseBuffer(entry.buffer, -1);
671 return;
672 }
673 info.surfaceBuffer = entry.buffer;
674 err = NotifyOmxToEmptyThisInBuffer(info);
675 if (err != AVCS_ERR_OK) {
676 inputSurface_->ReleaseBuffer(entry.buffer, -1);
677 return;
678 }
679 }
680
OnOMXEmptyBufferDone(uint32_t bufferId,BufferOperationMode mode)681 void HEncoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode)
682 {
683 BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId);
684 if (info == nullptr) {
685 HLOGE("unknown buffer id %{public}u", bufferId);
686 return;
687 }
688 if (info->owner != BufferOwner::OWNED_BY_OMX) {
689 HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", bufferId, ToString(info->owner));
690 return;
691 }
692 ChangeOwner(*info, BufferOwner::OWNED_BY_US);
693 if (inputBufferType_ == BufferType::DYNAMIC_SURFACE_BUFFER) {
694 if (info->surfaceBuffer != nullptr) {
695 inputSurface_->ReleaseBuffer(info->surfaceBuffer, -1);
696 }
697 if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
698 FindAllIdleSlotAndSubmit();
699 }
700 } else {
701 if (mode == RESUBMIT_BUFFER && !inputPortEos_) {
702 NotifyUserToFillThisInBuffer(*info);
703 }
704 }
705 }
706
OnBufferAvailable()707 void HEncoder::EncoderBuffersConsumerListener::OnBufferAvailable()
708 {
709 codec_->SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
710 }
711
OnSignalEndOfInputStream(const MsgInfo & msg)712 void HEncoder::OnSignalEndOfInputStream(const MsgInfo &msg)
713 {
714 if (inputBufferType_ == BufferType::PRESET_ASHM_BUFFER) {
715 HLOGE("can only be called in surface mode");
716 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
717 return;
718 }
719 ReplyErrorCode(msg.id, AVCS_ERR_OK);
720
721 inputPortEos_ = true;
722 for (auto &item : inputBufferPool_) {
723 if (item.owner == BufferOwner::OWNED_BY_US) {
724 item.omxBuffer->flag = OMX_BUFFERFLAG_EOS;
725 item.surfaceBuffer = nullptr;
726 if (NotifyOmxToEmptyThisInBuffer(item) == AVCS_ERR_OK) {
727 return;
728 }
729 }
730 }
731 HLOGI("can not find any input buffer currently owned by us, we will try later");
732 MsgHandleLoop::SendAsyncMsg(MsgWhat::NOTIFY_EOS, nullptr, THIRTY_MILLISECONDS_IN_US);
733 }
734 } // namespace OHOS::MediaAVCodec
735