• 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 
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