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