1 /*
2  * Copyright (C) 2021 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 <cmath>
17 #include "avcodec_log.h"
18 #include "avcodec_errors.h"
19 #include "avcodec_info.h"
20 
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecInfo"};
23 constexpr int32_t FRAME_RATE_30 = 30;
24 constexpr int32_t BLOCK_SIZE_MIN = 2;
25 constexpr int32_t BASE_BLOCK_PER_FRAME = 99;
26 constexpr int32_t BASE_BLOCK_PER_SECOND = 1485;
27 } // namespace
28 namespace OHOS {
29 namespace MediaAVCodec {
30 const std::map<int32_t, LevelParams> AVC_PARAMS_MAP = {
31     {AVC_LEVEL_1, LevelParams(1485, 99)},      {AVC_LEVEL_1b, LevelParams(1485, 99)},
32     {AVC_LEVEL_11, LevelParams(3000, 396)},    {AVC_LEVEL_12, LevelParams(6000, 396)},
33     {AVC_LEVEL_13, LevelParams(11880, 396)},   {AVC_LEVEL_2, LevelParams(11880, 396)},
34     {AVC_LEVEL_21, LevelParams(19800, 792)},   {AVC_LEVEL_22, LevelParams(20250, 1620)},
35     {AVC_LEVEL_3, LevelParams(40500, 1620)},   {AVC_LEVEL_31, LevelParams(108000, 3600)},
36     {AVC_LEVEL_32, LevelParams(216000, 5120)}, {AVC_LEVEL_4, LevelParams(245760, 8192)},
37     {AVC_LEVEL_41, LevelParams(245760, 8192)}, {AVC_LEVEL_42, LevelParams(522240, 8704)},
38     {AVC_LEVEL_5, LevelParams(589824, 22080)}, {AVC_LEVEL_51, LevelParams(983040, 36864)},
39     {AVC_LEVEL_52, LevelParams(2073600, 36864)}, {AVC_LEVEL_6, LevelParams(4177920, 139264)},
40     {AVC_LEVEL_61, LevelParams(8355840, 139264)}, {AVC_LEVEL_62, LevelParams(16711680, 139264)},
41 };
42 
43 const std::map<int32_t, LevelParams> MPEG2_SIMPLE_PARAMS_MAP = {
44     {MPEG2_LEVEL_ML, LevelParams(40500, 1620, 30, 45, 36)},
45 };
46 
47 const std::map<int32_t, LevelParams> MPEG2_MAIN_PARAMS_MAP = {
48     {MPEG2_LEVEL_LL, LevelParams(11880, 396, 30, 22, 18)},
49     {MPEG2_LEVEL_ML, LevelParams(40500, 1620, 30, 45, 36)},
50     {MPEG2_LEVEL_H14, LevelParams(183600, 6120, 60, 90, 68)},
51     {MPEG2_LEVEL_HL, LevelParams(244800, 8160, 60, 120, 68)},
52 };
53 
54 const std::map<int32_t, LevelParams> MPEG4_ADVANCED_SIMPLE_PARAMS_MAP = {
55     {MPEG4_LEVEL_0, LevelParams(2970, 99, 30, 11, 9)},     {MPEG4_LEVEL_1, LevelParams(2970, 99, 30, 11, 9)},
56     {MPEG4_LEVEL_2, LevelParams(5940, 396, 30, 22, 18)},   {MPEG4_LEVEL_3, LevelParams(11880, 396, 30, 22, 18)},
57     {MPEG4_LEVEL_4, LevelParams(23760, 1200, 30, 44, 36)}, {MPEG4_LEVEL_5, LevelParams(48600, 1620, 30, 45, 36)},
58 };
59 
60 const std::map<int32_t, LevelParams> MPEG4_SIMPLE_PARAMS_MAP = {
61     {MPEG4_LEVEL_0, LevelParams(1485, 99, 15, 11, 9)},     {MPEG4_LEVEL_0B, LevelParams(1485, 99, 15, 11, 9)},
62     {MPEG4_LEVEL_1, LevelParams(1485, 99, 30, 11, 9)},     {MPEG4_LEVEL_2, LevelParams(5940, 396, 30, 22, 18)},
63     {MPEG4_LEVEL_3, LevelParams(11880, 396, 30, 22, 18)},  {MPEG4_LEVEL_4A, LevelParams(36000, 1200, 30, 40, 30)},
64     {MPEG4_LEVEL_5, LevelParams(40500, 1620, 30, 40, 36)},
65 };
66 
VideoCaps(CapabilityData * capabilityData)67 VideoCaps::VideoCaps(CapabilityData *capabilityData) : data_(capabilityData)
68 {
69     CHECK_AND_RETURN_LOG(capabilityData != nullptr, "capabilityData is null");
70     InitParams();
71     LoadLevelParams();
72     AVCODEC_LOGD("VideoCaps:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
73 }
74 
~VideoCaps()75 VideoCaps::~VideoCaps()
76 {
77     AVCODEC_LOGD("VideoCaps:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
78 }
79 
GetCodecInfo()80 std::shared_ptr<AVCodecInfo> VideoCaps::GetCodecInfo()
81 {
82     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, nullptr, "data is null");
83     std::shared_ptr<AVCodecInfo> codecInfo = std::make_shared<AVCodecInfo>(data_);
84     CHECK_AND_RETURN_RET_LOG(codecInfo != nullptr, nullptr, "create codecInfo failed");
85 
86     return codecInfo;
87 }
88 
GetSupportedBitrate()89 Range VideoCaps::GetSupportedBitrate()
90 {
91     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
92     return data_->bitrate;
93 }
94 
GetSupportedFormats()95 std::vector<int32_t> VideoCaps::GetSupportedFormats()
96 {
97     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
98     std::vector<int32_t> pixFormat = data_->pixFormat;
99     CHECK_AND_RETURN_RET_LOG(pixFormat.size() != 0, pixFormat, "GetSupportedFormats failed: format is null");
100     return pixFormat;
101 }
102 
GetSupportedHeightAlignment()103 int32_t VideoCaps::GetSupportedHeightAlignment()
104 {
105     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, 1, "data is null");
106     return data_->alignment.height;
107 }
108 
GetSupportedWidthAlignment()109 int32_t VideoCaps::GetSupportedWidthAlignment()
110 {
111     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, 1, "data is null");
112     return data_->alignment.width;
113 }
114 
GetSupportedWidth()115 Range VideoCaps::GetSupportedWidth()
116 {
117     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
118     return data_->width;
119 }
120 
GetSupportedHeight()121 Range VideoCaps::GetSupportedHeight()
122 {
123     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
124     return data_->height;
125 }
126 
GetSupportedProfiles()127 std::vector<int32_t> VideoCaps::GetSupportedProfiles()
128 {
129     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
130     std::vector<int32_t> profiles = data_->profiles;
131     CHECK_AND_RETURN_RET_LOG(profiles.size() != 0, profiles, "GetSupportedProfiles failed: profiles is null");
132     return profiles;
133 }
134 
GetSupportedLevels()135 std::vector<int32_t> VideoCaps::GetSupportedLevels()
136 {
137     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
138     std::vector<int32_t> levels;
139     return levels;
140 }
141 
GetSupportedEncodeQuality()142 Range VideoCaps::GetSupportedEncodeQuality()
143 {
144     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
145     return data_->encodeQuality;
146 }
147 
IsSizeSupported(int32_t width,int32_t height)148 bool VideoCaps::IsSizeSupported(int32_t width, int32_t height)
149 {
150     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
151     UpdateParams();
152     if (width <= 0 || height <= 0) {
153         return false;
154     }
155     if (data_->alignment.width == 0 || data_->alignment.height == 0 || width % data_->alignment.width != 0 ||
156         height % data_->alignment.height != 0) {
157         return false;
158     }
159     if (data_->width.minVal > width || data_->width.maxVal < width || data_->height.minVal > height ||
160         data_->height.maxVal < height) {
161         return false;
162     }
163     if (blockWidth_ != 0 && blockHeight_ != 0) {
164         int64_t blockPerFrame =
165             static_cast<int64_t>(DivCeil(width, blockWidth_)) * static_cast<int64_t>(DivCeil(height, blockHeight_));
166         if (blockPerFrame < blockPerFrameRange_.minVal || blockPerFrame > blockPerFrameRange_.maxVal) {
167             return false;
168         }
169     }
170     return true;
171 }
172 
GetVideoWidthRangeForHeight(int32_t height)173 Range VideoCaps::GetVideoWidthRangeForHeight(int32_t height)
174 {
175     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
176     if (height < data_->height.minVal || height > data_->height.maxVal) {
177         return Range(0, 0);
178     }
179     UpdateParams();
180     Range ret = data_->width;
181     if (blockWidth_ != 0 && blockHeight_ != 0) {
182         int64_t verticalBlockNum = static_cast<int64_t>(DivCeil(height, blockHeight_));
183         if (verticalBlockNum < verticalBlockRange_.minVal || verticalBlockNum > verticalBlockRange_.maxVal) {
184             return Range(0, 0);
185         }
186         Range horizontalBlockNum = horizontalBlockRange_.Intersect(
187             Range(blockPerFrameRange_.minVal / verticalBlockNum, blockPerFrameRange_.maxVal / verticalBlockNum));
188         ret = ret.Intersect(
189             Range((horizontalBlockNum.minVal - 1) * blockWidth_ + data_->alignment.width,
190                 horizontalBlockNum.maxVal * blockWidth_));
191     }
192     return ret;
193 }
194 
GetVideoHeightRangeForWidth(int32_t width)195 Range VideoCaps::GetVideoHeightRangeForWidth(int32_t width)
196 {
197     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
198     if (width < data_->width.minVal || width > data_->width.maxVal) {
199         return Range(0, 0);
200     }
201     UpdateParams();
202     Range ret = data_->height;
203     if (blockWidth_ != 0 && blockHeight_ != 0) {
204         int64_t horizontalBlockNum = static_cast<int64_t>(DivCeil(width, blockWidth_));
205         if (horizontalBlockNum < horizontalBlockRange_.minVal || horizontalBlockNum > horizontalBlockRange_.maxVal) {
206             return Range(0, 0);
207         }
208         Range verticalBlockNum = verticalBlockRange_.Intersect(
209             Range(blockPerFrameRange_.minVal / horizontalBlockNum, blockPerFrameRange_.maxVal / horizontalBlockNum));
210         ret = ret.Intersect(
211             Range((verticalBlockNum.minVal - 1) * blockHeight_ + data_->alignment.height,
212                 verticalBlockNum.maxVal * blockHeight_));
213     }
214     return ret;
215 }
216 
GetSupportedFrameRate()217 Range VideoCaps::GetSupportedFrameRate()
218 {
219     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
220     return data_->frameRate;
221 }
222 
GetSupportedFrameRatesFor(int32_t width,int32_t height)223 Range VideoCaps::GetSupportedFrameRatesFor(int32_t width, int32_t height)
224 {
225     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
226     if (!IsSizeSupported(width, height)) {
227         AVCODEC_LOGD("The %{public}s can not support of:%{public}d * %{public}d", data_->codecName.c_str(), width,
228                      height);
229         return Range(0, 0);
230     }
231     Range frameRatesRange;
232     int64_t blockPerFrame = DivCeil(width, blockWidth_) * static_cast<int64_t>(DivCeil(height, blockHeight_));
233     if (blockPerFrame != 0) {
234         frameRatesRange =
235             Range(std::max(static_cast<int32_t>(blockPerSecondRange_.minVal / blockPerFrame), frameRateRange_.minVal),
236                   std::min(static_cast<int32_t>(blockPerSecondRange_.maxVal / blockPerFrame), frameRateRange_.maxVal));
237     }
238     if (frameRatesRange.minVal > frameRatesRange.maxVal) {
239         return Range(0, 0);
240     }
241     return frameRatesRange;
242 }
243 
LoadLevelParams()244 void VideoCaps::LoadLevelParams()
245 {
246     std::shared_ptr<AVCodecInfo> codecInfo = this->GetCodecInfo();
247     if (codecInfo == nullptr || codecInfo->IsSoftwareOnly()) {
248         return;
249     }
250     if (data_->mimeType == CodecMimeType::VIDEO_AVC) {
251         LoadAVCLevelParams();
252     } else {
253         LoadMPEGLevelParams(data_->mimeType);
254     }
255 }
256 
LoadAVCLevelParams()257 void VideoCaps::LoadAVCLevelParams()
258 {
259     int32_t maxBlockPerFrame = BASE_BLOCK_PER_FRAME;
260     int32_t maxBlockPerSecond = BASE_BLOCK_PER_SECOND;
261     for (auto iter = data_->profileLevelsMap.begin(); iter != data_->profileLevelsMap.end(); iter++) {
262         for (auto levelIter = iter->second.begin(); levelIter != iter->second.end(); levelIter++) {
263             if (AVC_PARAMS_MAP.find(*levelIter) != AVC_PARAMS_MAP.end()) {
264                 maxBlockPerFrame = std::max(maxBlockPerFrame, AVC_PARAMS_MAP.at(*levelIter).maxBlockPerFrame);
265                 maxBlockPerSecond = std::max(maxBlockPerSecond, AVC_PARAMS_MAP.at(*levelIter).maxBlockPerSecond);
266             }
267         }
268     }
269     Range blockPerFrameRange = Range(1, maxBlockPerFrame);
270     Range blockPerSecondRange = Range(1, maxBlockPerSecond);
271     UpdateBlockParams(16, 16, blockPerFrameRange, blockPerSecondRange); // set AVC block size as 16x16
272 }
273 
LoadMPEGLevelParams(const std::string & mime)274 void VideoCaps::LoadMPEGLevelParams(const std::string &mime)
275 {
276     std::map<int32_t, LevelParams> PARAMS_MAP;
277     bool isMpeg2 = false;
278     if (mime == CodecMimeType::VIDEO_MPEG2) {
279         isMpeg2 = true;
280     } else if (mime != CodecMimeType::VIDEO_MPEG4) {
281         return;
282     }
283     int32_t firstSample = isMpeg2 ? MPEG2_PROFILE_SIMPLE : MPEG4_PROFILE_SIMPLE;
284     int32_t secondSample = isMpeg2 ? MPEG2_PROFILE_MAIN : MPEG4_PROFILE_ADVANCED_SIMPLE;
285     int32_t maxBlockPerFrame = BASE_BLOCK_PER_FRAME;
286     int32_t maxBlockPerSecond = BASE_BLOCK_PER_SECOND;
287     int32_t maxFrameRate = 0;
288     int32_t maxWidth = 0;
289     int32_t maxHeight = 0;
290     for (auto iter = data_->profileLevelsMap.begin(); iter != data_->profileLevelsMap.end(); iter++) {
291         if (iter->first == firstSample) {
292             PARAMS_MAP = isMpeg2 ? MPEG2_SIMPLE_PARAMS_MAP : MPEG4_SIMPLE_PARAMS_MAP;
293         } else if (iter->first == secondSample) {
294             PARAMS_MAP = isMpeg2 ? MPEG2_MAIN_PARAMS_MAP : MPEG4_ADVANCED_SIMPLE_PARAMS_MAP;
295         } else {
296             continue;
297         }
298         for (auto levelIter = iter->second.begin(); levelIter != iter->second.end(); levelIter++) {
299             if (PARAMS_MAP.find(*levelIter) != PARAMS_MAP.end()) {
300                 maxBlockPerFrame = std::max(maxBlockPerFrame, PARAMS_MAP.at(*levelIter).maxBlockPerFrame);
301                 maxBlockPerSecond = std::max(maxBlockPerSecond, PARAMS_MAP.at(*levelIter).maxBlockPerSecond);
302                 maxFrameRate = std::max(maxFrameRate, PARAMS_MAP.at(*levelIter).maxFrameRate);
303                 maxWidth = std::max(maxWidth, PARAMS_MAP.at(*levelIter).maxWidth);
304                 maxHeight = std::max(maxHeight, PARAMS_MAP.at(*levelIter).maxHeight);
305             }
306         }
307     }
308 
309     frameRateRange_ = frameRateRange_.Intersect(Range(1, maxFrameRate));
310     Range blockPerFrameRange = Range(1, maxBlockPerFrame);
311     Range blockPerSecondRange = Range(1, maxBlockPerSecond);
312     UpdateBlockParams(maxWidth, maxHeight, blockPerFrameRange, blockPerSecondRange);
313 }
314 
UpdateBlockParams(const int32_t & blockWidth,const int32_t & blockHeight,Range & blockPerFrameRange,Range & blockPerSecondRange)315 void VideoCaps::UpdateBlockParams(const int32_t &blockWidth, const int32_t &blockHeight, Range &blockPerFrameRange,
316                                   Range &blockPerSecondRange)
317 {
318     int32_t factor;
319     if (blockWidth > blockWidth_ && blockHeight > blockHeight_) {
320         if (blockWidth_ == 0 || blockHeight_ == 0) {
321             return;
322         }
323         factor = blockWidth * blockHeight / blockWidth_ / blockHeight_;
324         blockPerFrameRange_ = DivRange(blockPerFrameRange_, factor);
325         blockPerSecondRange_ = DivRange(blockPerSecondRange_, factor);
326         horizontalBlockRange_ = DivRange(horizontalBlockRange_, blockWidth / blockWidth_);
327         verticalBlockRange_ = DivRange(verticalBlockRange_, blockHeight / blockHeight_);
328     } else if (blockWidth < blockWidth_ && blockHeight < blockHeight_) {
329         if (blockWidth == 0 || blockHeight == 0) {
330             return;
331         }
332         factor = blockWidth_ * blockHeight_ / blockWidth / blockHeight;
333         blockPerFrameRange = DivRange(blockPerFrameRange, factor);
334         blockPerSecondRange = DivRange(blockPerSecondRange, factor);
335     }
336 
337     blockWidth_ = std::max(blockWidth_, blockWidth);
338     blockHeight_ = std::max(blockHeight_, blockHeight);
339     blockPerFrameRange_ = blockPerFrameRange_.Intersect(blockPerFrameRange);
340     blockPerSecondRange_ = blockPerSecondRange_.Intersect(blockPerSecondRange);
341 }
342 
InitParams()343 void VideoCaps::InitParams()
344 {
345     if (data_->blockPerSecond.minVal == 0 || data_->blockPerSecond.maxVal == 0) {
346         data_->blockPerSecond = Range(1, INT32_MAX);
347     }
348     if (data_->blockPerFrame.minVal == 0 || data_->blockPerFrame.maxVal == 0) {
349         data_->blockPerFrame = Range(1, INT32_MAX);
350     }
351     if (data_->supportSwapWidthHeight) {
352         Range side = Range(std::min(data_->width.minVal, data_->height.minVal),
353                            std::max(data_->width.maxVal, data_->height.maxVal));
354         data_->width = side;
355         data_->height = side;
356     }
357     if (data_->width.minVal == 0 || data_->width.maxVal == 0) {
358         data_->width = Range(1, INT32_MAX);
359     }
360     if (data_->height.minVal == 0 || data_->height.maxVal == 0) {
361         data_->height = Range(1, INT32_MAX);
362     }
363     if (data_->frameRate.maxVal == 0) {
364         data_->frameRate = Range(0, FRAME_RATE_30);
365     }
366     if (data_->blockSize.width == 0 || data_->blockSize.height == 0) {
367         data_->blockSize.width = BLOCK_SIZE_MIN;
368         data_->blockSize.height = BLOCK_SIZE_MIN;
369     }
370 
371     blockWidth_ = data_->blockSize.width;
372     blockHeight_ = data_->blockSize.height;
373     frameRateRange_ = data_->frameRate;
374     horizontalBlockRange_ = Range(1, INT32_MAX);
375     verticalBlockRange_ = Range(1, INT32_MAX);
376     blockPerFrameRange_ = Range(1, INT32_MAX);
377     blockPerSecondRange_ = Range(1, INT32_MAX);
378     widthRange_ = Range(1, INT32_MAX);
379     heightRange_ = Range(1, INT32_MAX);
380 }
381 
UpdateParams()382 void VideoCaps::UpdateParams()
383 {
384     if (data_->blockSize.width == 0 || data_->blockSize.height == 0 || blockWidth_ == 0 || blockHeight_ == 0 ||
385         verticalBlockRange_.maxVal == 0 || verticalBlockRange_.minVal == 0 || horizontalBlockRange_.maxVal == 0 ||
386         horizontalBlockRange_.minVal == 0 || blockPerFrameRange_.minVal == 0 || blockPerFrameRange_.maxVal == 0) {
387         AVCODEC_LOGE("Invalid param");
388         return;
389     }
390 
391     int32_t factor = (blockWidth_ * blockHeight_) / (data_->blockSize.width * data_->blockSize.height);
392 
393     blockPerFrameRange_ = blockPerFrameRange_.Intersect(DivRange(data_->blockPerFrame, factor));
394     blockPerSecondRange_ = blockPerSecondRange_.Intersect(DivRange(data_->blockPerSecond, factor));
395     horizontalBlockRange_ = horizontalBlockRange_.Intersect(
396         Range(data_->width.minVal / blockWidth_, DivCeil(data_->width.maxVal, blockWidth_)));
397     if (verticalBlockRange_.maxVal != 0 && verticalBlockRange_.minVal != 0) {
398         horizontalBlockRange_ =
399             horizontalBlockRange_.Intersect(Range(blockPerFrameRange_.minVal / verticalBlockRange_.maxVal,
400                                                   blockPerFrameRange_.maxVal / verticalBlockRange_.minVal));
401     }
402     verticalBlockRange_ = verticalBlockRange_.Intersect(
403         Range(data_->height.minVal / blockHeight_, DivCeil(data_->height.maxVal, blockHeight_)));
404     if (horizontalBlockRange_.maxVal != 0 && horizontalBlockRange_.minVal != 0) {
405         verticalBlockRange_ =
406             verticalBlockRange_.Intersect(Range(blockPerFrameRange_.minVal / horizontalBlockRange_.maxVal,
407                                                 blockPerFrameRange_.maxVal / horizontalBlockRange_.minVal));
408     }
409     blockPerFrameRange_ =
410         blockPerFrameRange_.Intersect(Range(horizontalBlockRange_.minVal * verticalBlockRange_.minVal,
411                                             horizontalBlockRange_.maxVal * verticalBlockRange_.maxVal));
412     blockPerSecondRange_ = blockPerSecondRange_.Intersect(blockPerFrameRange_.minVal * frameRateRange_.minVal,
413                                                           blockPerFrameRange_.maxVal * frameRateRange_.maxVal);
414     if (blockPerFrameRange_.maxVal != 0 && blockPerFrameRange_.minVal != 0) {
415         frameRateRange_ = frameRateRange_.Intersect(blockPerSecondRange_.minVal / blockPerFrameRange_.maxVal,
416                                                     blockPerSecondRange_.maxVal / blockPerFrameRange_.minVal);
417     }
418 }
419 
DivRange(const Range & range,const int32_t & divisor)420 Range VideoCaps::DivRange(const Range &range, const int32_t &divisor)
421 {
422     if (divisor == 0) {
423         AVCODEC_LOGD("The denominator cannot be 0");
424         return range;
425     } else if (divisor == 1) {
426         return range;
427     }
428     return Range(DivCeil(range.minVal, divisor), range.maxVal / divisor);
429 }
430 
DivCeil(const int32_t & dividend,const int32_t & divisor)431 int32_t VideoCaps::DivCeil(const int32_t &dividend, const int32_t &divisor)
432 {
433     if (divisor == 0) {
434         AVCODEC_LOGE("The denominator cannot be 0");
435         return INT32_MAX;
436     }
437     return (dividend + divisor - 1) / divisor;
438 }
439 
IsSizeAndRateSupported(int32_t width,int32_t height,double frameRate)440 bool VideoCaps::IsSizeAndRateSupported(int32_t width, int32_t height, double frameRate)
441 {
442     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
443     if (!IsSizeSupported(width, height)) {
444         AVCODEC_LOGD("The %{public}s can not support of:%{public}d * %{public}d", data_->codecName.c_str(), width,
445                      height);
446         return false;
447     }
448     const auto &frameRateRange = GetSupportedFrameRatesFor(width, height);
449     if (frameRateRange.minVal >= frameRate || frameRate > frameRateRange.maxVal) {
450         AVCODEC_LOGD("The %{public}s can not support frameRate:%{public}lf", data_->codecName.c_str(), frameRate);
451         return false;
452     }
453     return true;
454 }
455 
GetPreferredFrameRate(int32_t width,int32_t height)456 Range VideoCaps::GetPreferredFrameRate(int32_t width, int32_t height)
457 {
458     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
459     Range range;
460     if (!IsSizeSupported(width, height)) {
461         AVCODEC_LOGD("The %{public}s can not support of:%{public}d * %{public}d", data_->codecName.c_str(), width,
462                      height);
463         return range;
464     }
465 
466     if (data_->measuredFrameRate.size() == 0) {
467         AVCODEC_LOGD("The measuredFrameRate of %{public}s is null:", data_->codecName.c_str());
468         return range;
469     }
470     ImgSize closestSize = MatchClosestSize(ImgSize(width, height));
471     if (data_->measuredFrameRate.find(closestSize) == data_->measuredFrameRate.end()) {
472         AVCODEC_LOGD("can not match measuredFrameRate of %{public}d x  %{public}d :", width, width);
473         return range;
474     }
475     int64_t targetBlockNum = DivCeil(width, blockWidth_) * static_cast<int64_t>(DivCeil(height, blockHeight_));
476     int64_t closestBlockNum =
477         DivCeil(closestSize.width, blockWidth_) * static_cast<int64_t>(DivCeil(closestSize.height, blockHeight_));
478     Range closestFrameRate = data_->measuredFrameRate.at(closestSize);
479     int64_t minTargetBlockNum = 1;
480     double factor = static_cast<double>(closestBlockNum) / std::max(targetBlockNum, minTargetBlockNum);
481     return Range(closestFrameRate.minVal * factor, closestFrameRate.maxVal * factor);
482 }
483 
MatchClosestSize(const ImgSize & imgSize)484 ImgSize VideoCaps::MatchClosestSize(const ImgSize &imgSize)
485 {
486     int64_t targetBlockNum =
487         DivCeil(imgSize.width, blockWidth_) * static_cast<int64_t>(DivCeil(imgSize.height, blockHeight_));
488     int64_t minDiffBlockNum = INT32_MAX;
489 
490     ImgSize closestSize;
491     for (auto iter = data_->measuredFrameRate.begin(); iter != data_->measuredFrameRate.end(); iter++) {
492         int64_t blockNum =
493             DivCeil(iter->first.width, blockWidth_) * static_cast<int64_t>(DivCeil(iter->first.height, blockHeight_));
494         int64_t diffBlockNum = abs(targetBlockNum - blockNum);
495         if (minDiffBlockNum > diffBlockNum) {
496             minDiffBlockNum = diffBlockNum;
497             closestSize = iter->first;
498         }
499     }
500     AVCODEC_LOGD("%{public}s: The ClosestSize of %{public}d x %{public}d is %{public}d x %{public}d:",
501                  data_->codecName.c_str(), imgSize.width, imgSize.height, closestSize.width, closestSize.height);
502     return closestSize;
503 }
504 
GetSupportedBitrateMode()505 std::vector<int32_t> VideoCaps::GetSupportedBitrateMode()
506 {
507     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
508     std::vector<int32_t> bitrateMode = data_->bitrateMode;
509     CHECK_AND_RETURN_RET_LOG(bitrateMode.size() != 0, bitrateMode, "GetSupportedBitrateMode failed: get null");
510     return bitrateMode;
511 }
512 
GetSupportedQuality()513 Range VideoCaps::GetSupportedQuality()
514 {
515     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
516     Range quality;
517     return quality;
518 }
519 
GetSupportedComplexity()520 Range VideoCaps::GetSupportedComplexity()
521 {
522     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
523     return data_->complexity;
524 }
525 
IsSupportDynamicIframe()526 bool VideoCaps::IsSupportDynamicIframe()
527 {
528     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
529     return false;
530 }
531 
AudioCaps(CapabilityData * capabilityData)532 AudioCaps::AudioCaps(CapabilityData *capabilityData) : data_(capabilityData)
533 {
534     AVCODEC_LOGD("AudioCaps:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
535 }
536 
~AudioCaps()537 AudioCaps::~AudioCaps()
538 {
539     AVCODEC_LOGD("AudioCaps:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
540 }
541 
GetCodecInfo()542 std::shared_ptr<AVCodecInfo> AudioCaps::GetCodecInfo()
543 {
544     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, nullptr, "data is null");
545     std::shared_ptr<AVCodecInfo> codecInfo = std::make_shared<AVCodecInfo>(data_);
546     CHECK_AND_RETURN_RET_LOG(codecInfo != nullptr, nullptr, "create codecInfo failed");
547     return codecInfo;
548 }
549 
GetSupportedBitrate()550 Range AudioCaps::GetSupportedBitrate()
551 {
552     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
553     return data_->bitrate;
554 }
555 
GetSupportedChannel()556 Range AudioCaps::GetSupportedChannel()
557 {
558     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
559     return data_->channels;
560 }
561 
GetSupportedFormats()562 std::vector<int32_t> AudioCaps::GetSupportedFormats()
563 {
564     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
565     std::vector<int32_t> bitDepth = data_->bitDepth;
566     CHECK_AND_RETURN_RET_LOG(bitDepth.size() != 0, bitDepth, "GetSupportedFormats failed: format is null");
567     return bitDepth;
568 }
569 
GetSupportedSampleRates()570 std::vector<int32_t> AudioCaps::GetSupportedSampleRates()
571 {
572     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
573     std::vector<int32_t> sampleRate = data_->sampleRate;
574     CHECK_AND_RETURN_RET_LOG(sampleRate.size() != 0, sampleRate, "GetSupportedSampleRates failed: sampleRate is null");
575     return sampleRate;
576 }
577 
GetSupportedProfiles()578 std::vector<int32_t> AudioCaps::GetSupportedProfiles()
579 {
580     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
581     std::vector<int32_t> profiles = data_->profiles;
582     CHECK_AND_RETURN_RET_LOG(profiles.size() != 0, profiles, "GetSupportedProfiles failed: profiles is null");
583     return profiles;
584 }
585 
GetSupportedLevels()586 std::vector<int32_t> AudioCaps::GetSupportedLevels()
587 {
588     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, std::vector<int32_t>(), "data is null");
589     std::vector<int32_t> empty;
590     return empty;
591 }
592 
GetSupportedComplexity()593 Range AudioCaps::GetSupportedComplexity()
594 {
595     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, Range(), "data is null");
596     return data_->complexity;
597 }
598 
AVCodecInfo(CapabilityData * capabilityData)599 AVCodecInfo::AVCodecInfo(CapabilityData *capabilityData) : data_(capabilityData)
600 {
601     AVCODEC_LOGD("AVCodecInfo:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
602 }
603 
~AVCodecInfo()604 AVCodecInfo::~AVCodecInfo()
605 {
606     AVCODEC_LOGD("AVCodecInfo:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
607 }
608 
GetName()609 std::string AVCodecInfo::GetName()
610 {
611     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, "", "data is null");
612     std::string name = data_->codecName;
613     CHECK_AND_RETURN_RET_LOG(name != "", "", "get codec name is null");
614     return name;
615 }
616 
GetType()617 AVCodecType AVCodecInfo::GetType()
618 {
619     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, AVCODEC_TYPE_NONE, "data is null");
620     AVCodecType codecType = AVCodecType(data_->codecType);
621     CHECK_AND_RETURN_RET_LOG(codecType != AVCODEC_TYPE_NONE, AVCODEC_TYPE_NONE, "can not find codec type");
622     return codecType;
623 }
624 
GetMimeType()625 std::string AVCodecInfo::GetMimeType()
626 {
627     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, "", "data is null");
628     std::string mimeType = data_->mimeType;
629     CHECK_AND_RETURN_RET_LOG(mimeType != "", "", "get mimeType is null");
630     return mimeType;
631 }
632 
IsHardwareAccelerated()633 bool AVCodecInfo::IsHardwareAccelerated()
634 {
635     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
636     return data_->isVendor;
637 }
638 
GetMaxSupportedInstances()639 int32_t AVCodecInfo::GetMaxSupportedInstances()
640 {
641     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, 0, "data is null");
642     return data_->maxInstance;
643 }
644 
IsSoftwareOnly()645 bool AVCodecInfo::IsSoftwareOnly()
646 {
647     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
648     return !data_->isVendor;
649 }
650 
IsVendor()651 bool AVCodecInfo::IsVendor()
652 {
653     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
654     return data_->isVendor;
655 }
656 
GetSupportedLevelsForProfile()657 std::map<int32_t, std::vector<int32_t>> AVCodecInfo::GetSupportedLevelsForProfile()
658 {
659     std::map<int32_t, std::vector<int32_t>> empty = std::map<int32_t, std::vector<int32_t>>();
660     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, empty, "data is null");
661     return data_->profileLevelsMap;
662 }
663 
IsFeatureValid(AVCapabilityFeature feature)664 bool AVCodecInfo::IsFeatureValid(AVCapabilityFeature feature)
665 {
666     return feature >= AVCapabilityFeature::VIDEO_ENCODER_TEMPORAL_SCALABILITY &&
667         feature < AVCapabilityFeature::MAX_VALUE;
668 }
669 
IsFeatureSupported(AVCapabilityFeature feature)670 bool AVCodecInfo::IsFeatureSupported(AVCapabilityFeature feature)
671 {
672     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, false, "data is null");
673     CHECK_AND_RETURN_RET_LOG(IsFeatureValid(feature), false,
674         "Varified feature failed: feature %{public}d is invalid", feature);
675     return data_->featuresMap.count(static_cast<int32_t>(feature)) != 0;
676 }
677 
GetFeatureProperties(AVCapabilityFeature feature,Format & format)678 int32_t AVCodecInfo::GetFeatureProperties(AVCapabilityFeature feature, Format &format)
679 {
680     CHECK_AND_RETURN_RET_LOG(data_ != nullptr, AVCS_ERR_INVALID_VAL, "data is null");
681     CHECK_AND_RETURN_RET_LOG(IsFeatureValid(feature), AVCS_ERR_INVALID_VAL,
682         "Get feature properties failed: invalid feature %{public}d", feature);
683     auto itr = data_->featuresMap.find(static_cast<int32_t>(feature));
684     CHECK_AND_RETURN_RET_LOG(itr != data_->featuresMap.end(), AVCS_ERR_INVALID_OPERATION,
685         "Get feature properties failed: feature %{public}d is not supported", feature);
686     format = itr->second;
687     return AVCS_ERR_OK;
688 }
689 } // namespace MediaAVCodec
690 } // namespace OHOS