• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 获取支持的编解码能力
2
3<!--Kit: AVCodec Kit-->
4<!--Subsystem: Multimedia-->
5<!--Owner: @yang-xiaoyu5-->
6<!--Designer: @dpy2650-->
7<!--Tester: @cyakee-->
8<!--Adviser: @zengyawen-->
9
10因来源、编解码协议及设备能力的不同,导致不同设备上可用的编解码器及其能力存在差异。
11
12为确保编解码行为符合预期,请通过音视频编解码能力接口查询系统支持的编解码器及其能力,选择符合开发需求的编解码器,并正确配置参数。
13
14## 通用开发指导
151. 在CMake脚本中链接动态库。
16
17   ``` cmake
18   target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
19   target_link_libraries(sample PUBLIC libnative_media_core.so)
20   target_link_libraries(sample PUBLIC libnative_media_venc.so)
21   target_link_libraries(sample PUBLIC libnative_media_vdec.so)
22   target_link_libraries(sample PUBLIC libnative_media_acodec.so)
23   ```
24   > **说明:**
25   >
26   > 上述'sample'字样仅为示例,此处由开发者根据实际工程目录自定义。
27   >
28
292. 添加头文件。
30
31   ```c++
32   #include <algorithm>
33   #include <multimedia/player_framework/native_avcapability.h>
34   #include <multimedia/player_framework/native_avcodec_audiocodec.h>
35   #include <multimedia/player_framework/native_avcodec_videoencoder.h>
36   #include <multimedia/player_framework/native_avcodec_videodecoder.h>
37   ```
38
393. 获得音视频编解码能力实例。
40
41   支持两种方式获取音视频编解码能力实例。
42
43   方式一:通过`OH_AVCodec_GetCapability`获取系统推荐的音视频编解码器能力实例。推荐策略与`OH_XXX_CreateByMime`系列接口一致。
44   ```c++
45   // 获取系统推荐的音频AAC解码器能力实例。
46   OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, false);
47   ```
48
49   方式二:通过`OH_AVCodec_GetCapabilityByCategory`获取指定软硬件的编解码能力实例。
50   ```c++
51   // 获取指定硬件的视频AVC编码器能力实例。
52   OH_AVCapability *capability = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true, HARDWARE);
53   ```
54   若获取能力实例成功,继续向下执行。实例无显性释放接口,使用完毕后系统会自动回收。
55
564. 按需调用相应的查询接口。详细的API说明请参考[API文档](../../reference/apis-avcodec-kit/_a_v_capability.md)。
57
58## 场景化开发
59基于开发过程中可能遇到的具体场景,此处将举例说明能力查询接口的使用方法。
60
61### 创建指定名称的编解码器
62
63如果系统存在多个相同MIME类型的编解码器,使用`OH_XXX_CreateByMime`系列接口创建系统推荐的编解码器。如需创建其他编解码器,先获取名称,再通过`OH_XXX_CreateByName`系列接口创建指定名称的编解码器。
64
65| 接口     | 功能描述                         |
66| -------- | -------------------------------- |
67| OH_AVCapability_GetName     | 获取能力实例对应编解码器的名称。 |
68
69当H.264软件解码器和H.264硬件解码器同时存在时,创建H.264软件解码器的示例代码如下。
70
71```c++
72// 1. 获取H.264软件解码器能力实例。
73OH_AVCapability *capability = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false, SOFTWARE);
74if (capability != nullptr) {
75   // 2. 获取H.264软件解码器名称。
76   const char *codecName = OH_AVCapability_GetName(capability);
77   // 3. 创建H.264软件解码器实例。
78   OH_AVCodec *videoDec = OH_VideoDecoder_CreateByName(codecName);
79}
80```
81
82### 针对软硬件类别差异化配置编解码器参数
83
84以下是软件编解码器和硬件编解码器的定义。
85
86* **软件编解码器:** 指在CPU上工作的编解码器,具有迭代灵活、兼容性好和扩展能力强等特点。
87
88* **硬件编解码器:** 指在专有硬件上工作的编解码器,具有低功耗、高性能和减少CPU负载等特点。
89
90在硬件编解码器充足且满足能力要求时,优先使用硬件编解码器;否则使用软件编解码器。开发者可根据编解码器类别配置不同的编解码参数。
91
92| 接口     | 功能描述                         |
93| -------- | -------------------------------- |
94| OH_AVCapability_IsHardware  | 确认能力实例对应的编解码器是否为硬件编解码器。 |
95
96视频编码的软硬件类别差异化配置帧率示例如下。
97
98```c++
99// 1. 确认推荐的H.264编码器的软硬件类别。
100OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
101if (capability == nullptr) {
102   // 异常处理。
103}
104bool isHardware = OH_AVCapability_IsHardware(capability);
105// 2. 基于软硬件类别差异化配置。
106OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
107if (videoEnc == nullptr) {
108   // 异常处理。
109}
110OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1920, 1080);
111if (format == nullptr) {
112   // 异常处理。
113}
114double frameRate = isHardware ? 60.0 : 30.0;
115if (!OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate)) {
116   // 异常处理。
117}
118if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
119   // 异常处理。
120}
121OH_AVFormat_Destroy(format);
122```
123
124### 创建多路编解码器
125
126部分业务场景涉及创建多路编解码器,基于系统内存、处理器和带宽等资源的限制,某一编解码器的实例数是有限的,不能无限制创建。
127
128| 接口     | 功能描述                         |
129| -------- | -------------------------------- |
130| OH_AVCapability_GetMaxSupportedInstances  | 获取能力实例对应编解码器的最大实例数。实际创建数还受系统内存、处理器和带宽等资源的约束。 |
131
132优先创建硬件解码器实例,资源不足时创建软件解码器实例。示例如下。
133
134```c++
135constexpr int32_t NEEDED_VDEC_NUM = 8;
136// 1. 创建硬件解码器实例。
137OH_AVCapability *capHW = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false, HARDWARE);
138if (capHW == nullptr) {
139   // 异常处理。
140}
141int32_t vDecNumHW = std::min(OH_AVCapability_GetMaxSupportedInstances(capHW), NEEDED_VDEC_NUM);
142int32_t createdVDecNum = 0;
143for (int i = 0; i < vDecNumHW; i++) {
144   OH_AVCodec *videoDec = OH_VideoDecoder_CreateByName(OH_AVCapability_GetName(capHW));
145   if (videoDec != nullptr) {
146      // 维护在videoDecVector中。
147      createdVDecNum++;
148   }
149}
150if (createdVDecNum < NEEDED_VDEC_NUM) {
151   // 2. 不够时,创建软件解码器实例。
152   OH_AVCapability *capSW = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false, SOFTWARE);
153   if (capSW == nullptr) {
154      // 异常处理。
155   }
156   int32_t vDecNumSW = std::min(OH_AVCapability_GetMaxSupportedInstances(capSW), NEEDED_VDEC_NUM - createdVDecNum);
157   for (int i = 0; i < vDecNumSW; i++) {
158      OH_AVCodec *videoDec = OH_VideoDecoder_CreateByName(OH_AVCapability_GetName(capSW));
159      if (videoDec != nullptr) {
160         // 维护在videoDecVector中。
161         createdVDecNum++;
162      }
163   }
164}
165```
166
167### 控制编码质量
168
169提供四种码控模式供开发者选择:恒定码率(CBR)、动态码率(VBR)、恒定质量(CQ)及质量稳定(SQR)。
170- CBR和VBR码控模式下,编码质量取决于码率参数。
171- CQ码控模式下,编码质量取决于质量参数。
172- SQR码控模式下,编码质量由质量稳定码率因子和最大码率决定,且仅支持H.265(HEVC)编码。
173
174| 接口     | 功能描述                         |
175| -------- | ---------------------------- |
176| OH_AVCapability_IsEncoderBitrateModeSupported  | 确认当前编码器是否支持给定的码控模式。 |
177| OH_AVCapability_GetEncoderBitrateRange     | 获取当前编码器支持的码率范围,适用于CBR、VBR和SQR码控模式。 |
178| OH_AVCapability_GetEncoderQualityRange  | 获取当前编码器支持的质量范围,适用于CQ码控模式。  |
179
180CBR和VBR码控模式示例如下。
181
182```c++
183OH_BitrateMode bitrateMode = BITRATE_MODE_CBR;
184int32_t bitrate = 3000000;
185OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
186if (capability == nullptr) {
187   // 异常处理。
188}
189// 1. 确认待配置码控模式是否支持。
190bool isSupported = OH_AVCapability_IsEncoderBitrateModeSupported(capability, bitrateMode);
191if (!isSupported) {
192   // 异常处理。
193}
194// 2. 获取码率范围,判断待配置码率参数是否在范围内。
195OH_AVRange bitrateRange = {-1, -1};
196int32_t ret = OH_AVCapability_GetEncoderBitrateRange(capability, &bitrateRange);
197if (ret != AV_ERR_OK || bitrateRange.maxVal <= 0) {
198   // 异常处理。
199}
200if (bitrate > bitrateRange.maxVal || bitrate < bitrateRange.minVal) {
201   // 3.(可选)调整待配置码率参数。
202}
203// 4. 配置编码参数。
204OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
205if (videoEnc == nullptr) {
206   // 异常处理。
207}
208OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1920, 1080);
209if (format == nullptr) {
210   // 异常处理。
211}
212if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode) ||
213   !OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, static_cast<int64_t>(bitrate))) {
214   // 异常处理。
215}
216if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
217   // 异常处理。
218}
219OH_AVFormat_Destroy(format);
220```
221
222CQ码控模式示例如下。
223
224```c++
225OH_BitrateMode bitrateMode = BITRATE_MODE_CQ;
226int32_t quality = 0;
227OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
228if (capability == nullptr) {
229   // 异常处理。
230}
231// 1. 确认待配置码控模式是否支持。
232bool isSupported = OH_AVCapability_IsEncoderBitrateModeSupported(capability, bitrateMode);
233if (!isSupported) {
234   // 异常处理。
235}
236// 2. 获取质量范围,判断待配置质量参数是否在范围内。
237OH_AVRange qualityRange = {-1, -1};
238int32_t ret = OH_AVCapability_GetEncoderQualityRange(capability, &qualityRange);
239if (ret != AV_ERR_OK || qualityRange.maxVal < 0) {
240   // 异常处理。
241}
242if (quality > qualityRange.maxVal || quality < qualityRange.minVal) {
243   // 3.(可选)调整待配置质量参数。
244}
245// 5. 配置编码参数。
246OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
247if (videoEnc == nullptr) {
248   // 异常处理。
249}
250OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1920, 1080);
251if (format == nullptr) {
252   // 异常处理。
253}
254if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode) ||
255   !OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality)) {
256   // 异常处理。
257}
258if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
259   // 异常处理。
260}
261OH_AVFormat_Destroy(format);
262```
263
264SQR码控模式示例如下。
265
266```c++
267OH_BitrateMode bitrateMode = BITRATE_MODE_SQR;
268int32_t sqrFactor = 30; // 质量稳定码率因子。
269int32_t maxBitrate = 20000000; // 最大码率。
270OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, true);
271if (capability == nullptr) {
272   // 异常处理。
273}
274// 1. 确认待配置码控模式是否支持。
275bool isSupported = OH_AVCapability_IsEncoderBitrateModeSupported(capability, bitrateMode);
276if (!isSupported) {
277   // 异常处理。
278}
279// 2. 获取码率范围,判断待配置最大码率参数是否在范围内。
280OH_AVRange bitrateRange = {-1, -1};
281// 最大码率参数的取值范围同码率参数,故复用OH_AVCapability_GetEncoderBitrateRange获取取值范围。
282int32_t ret = OH_AVCapability_GetEncoderBitrateRange(capability, &bitrateRange);
283if (ret != AV_ERR_OK || bitrateRange.maxVal <= 0) {
284   // 异常处理。
285}
286
287// 质量稳定码率因子取值范围为[0, 51](同编码量化参数QP)。
288if (sqrFactor > 51 || sqrFactor < 0) {
289   // 3.(可选)调整待配置质量稳定码率因子参数。
290}
291
292if (maxBitrate > bitrateRange.maxVal || maxBitrate < bitrateRange.minVal) {
293   // 4.(可选)调整待配置最大码率参数。
294}
295
296// 5. 配置编码参数。
297OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
298if (videoEnc == nullptr) {
299   // 异常处理。
300}
301OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, 1920, 1080);
302if (format == nullptr) {
303   // 异常处理。
304}
305if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, bitrateMode) ||
306   !OH_AVFormat_SetIntValue(format, OH_MD_KEY_SQR_FACTOR, sqrFactor) ||
307   !OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_BITRATE, maxBitrate)) {
308   // 异常处理。
309}
310if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
311   // 异常处理。
312}
313OH_AVFormat_Destroy(format);
314
315// 6.启动编码器,开始编码。
316ret = OH_VideoEncoder_Prepare(videoEnc);
317if (ret != AV_ERR_OK) {
318   // 异常处理。
319}
320ret = OH_VideoEncoder_Start(videoEnc);
321if (ret != AV_ERR_OK) {
322   // 异常处理。
323}
324
325// 7.(可选)OH_VideoEncoder_SetParameter()在运行过程中动态配置质量稳定码率因子参数和最大码率参数。
326OH_AVFormat *dynamicFormat = OH_AVFormat_Create();
327// SQR码控支持动态配置最大码率参数和质量稳定码率因子参数。
328sqrFactor = 25; // 更新质量稳定码率因子。
329maxBitrate = 10000000; // 更新最大码率参数。
330OH_AVFormat_SetLongValue(dynamicFormat, OH_MD_KEY_MAX_BITRATE, maxBitrate);
331OH_AVFormat_SetIntValue(dynamicFormat, OH_MD_KEY_SQR_FACTOR, sqrFactor);
332ret = OH_VideoEncoder_SetParameter(videoEnc, dynamicFormat);
333if (ret != AV_ERR_OK) {
334   // 异常处理。
335}
336OH_AVFormat_Destroy(dynamicFormat);
337```
338
339### 查询编码器支持复杂度范围
340
341复杂度等级决定了编码器使用的工具数量,但并非所有编码器都支持这一功能。
342
343| 接口     | 功能描述                         |
344| -------- | ---------------------------- |
345| OH_AVCapability_GetEncoderComplexityRange | 获取当前编码器支持的复杂度等级范围。 |
346
347```c++
348OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
349if (capability == nullptr) {
350   // 异常处理。
351}
352// 确认支持的编码复杂度范围。
353OH_AVRange complexityRange = {-1, -1};
354int32_t ret = OH_AVCapability_GetEncoderComplexityRange(capability, &complexityRange);
355```
356
357### 设置正确的音频编解码参数
358
359在音频编解码场景中,需要设置采样率和通道数。对于音频编码,还需要设置码率。
360
361| 接口     | 功能描述                         |
362| -------- | ---------------------------- |
363| OH_AVCapability_GetAudioSupportedSampleRateRanges     | 获取当前音频编解码器支持的采样率范围。 |
364| OH_AVCapability_GetAudioChannelCountRange  | 获取当前音频编解码器支持的通道数范围。 |
365| OH_AVCapability_GetEncoderBitrateRange     | 获取当前编码器支持的码率范围。 |
366
367音频编解码参数查询示例如下。
368
369```c++
370int32_t sampleRate = 44100;
371int32_t channelCount = 2;
372int32_t bitrate = 261000;
373OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
374if (capability == nullptr) {
375   // 异常处理。
376}
377// 1. 确认待配置采样率是否支持。
378OH_AVRange *sampleRateRanges = nullptr;
379uint32_t rangesNum = 0;
380int32_t ret = OH_AVCapability_GetAudioSupportedSampleRateRanges(capability, &sampleRateRanges, &rangesNum);
381if (ret != AV_ERR_OK || sampleRateRanges == nullptr || rangesNum == 0) {
382   // 异常处理。
383}
384bool isMatched = false;
385for (uint32_t i = 0; i < rangesNum; i++) {
386   if (sampleRate >= sampleRateRanges[i].minVal && sampleRate <= sampleRateRanges[i].maxVal) {
387      isMatched = true;
388      break;
389   }
390}
391if (!isMatched) {
392   // 2.(可选)调整待配置采样率。
393}
394// 3. 获取通道数范围,判断待配置通道数参数是否在范围内。
395OH_AVRange channelRange = {-1, -1};
396ret = OH_AVCapability_GetAudioChannelCountRange(capability, &channelRange);
397if (ret != AV_ERR_OK || channelRange.maxVal <= 0) {
398   // 异常处理。
399}
400if (channelCount > channelRange.maxVal || channelCount < channelRange.minVal ) {
401   // 4.(可选)调整待配置通道数。
402}
403// 5. 获取码率范围,判断待配置码率参数是否在范围内。
404OH_AVRange bitrateRange = {-1, -1};
405ret = OH_AVCapability_GetEncoderBitrateRange(capability, &bitrateRange);
406if (ret != AV_ERR_OK || bitrateRange.maxVal <= 0) {
407   // 异常处理。
408}
409if (bitrate > bitrateRange.maxVal || bitrate < bitrateRange.minVal ) {
410   // 7.(可选)调整待配置码率值。
411}
412// 8. 配置编码参数。
413OH_AVCodec *audioEnc = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
414if (audioEnc == nullptr) {
415   // 异常处理。
416}
417OH_AVFormat *format = OH_AVFormat_Create();
418if (format == nullptr) {
419   // 异常处理。
420}
421if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, sampleRate) ||
422   !OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, channelCount) ||
423   !OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, static_cast<int64_t>(bitrate))) {
424   // 异常处理。
425}
426if (OH_AudioCodec_Configure(audioEnc, format) != AV_ERR_OK) {
427   // 异常处理。
428}
429OH_AVFormat_Destroy(format);
430```
431
432### 查询编解码档次和级别支持情况
433
434编解码标准包含多种编码工具,适用于不同的编码场景。对于特定应用场景,编解码标准按档次确定所需编码工具的开启与关闭情况(例如,H.264有基本档次、主档次和高档次)。详情参见 [OH_AVCProfile](../../reference/apis-avcodec-kit/_codec_base.md#oh_avcprofile-1)。
435
436级别划分了编解码器所需的处理能力和存储空间。H.264有1到6.2的20个级别,参考[OH_AVCLevel](../../reference/apis-avcodec-kit/_codec_base.md#oh_avclevel-1)。
437
438| 接口     | 功能描述                         |
439| -------- | ---------------------------- |
440| OH_AVCapability_GetSupportedProfiles                    | 获取当前编解码器支持的档次。 |
441| OH_AVCapability_GetSupportedLevelsForProfile            | 获取当前编解码器在给定档次的情况下支持的级别信息。 |
442| OH_AVCapability_AreProfileAndLevelSupported             | 确认当前编解码器是否支持特定的档次和级别组合。 |
443
444确认待配置的档次是否支持,并查询该档次下支持的级别,示例如下。
445
446```c++
447OH_AVCProfile profile = AVC_PROFILE_MAIN;
448OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
449if (capability == nullptr) {
450   // 异常处理。
451}
452// 1. 确认待配置档次是否支持。
453const int32_t *profiles = nullptr;
454uint32_t profileNum = 0;
455int32_t ret = OH_AVCapability_GetSupportedProfiles(capability, &profiles, &profileNum);
456if (ret != AV_ERR_OK || profiles == nullptr || profileNum == 0) {
457   // 异常处理。
458}
459bool isMatched = false;
460for (int i = 0; i < profileNum; i++) {
461   if (profiles[i] == profile) {
462      isMatched = true;
463      break;
464   }
465}
466// 2. 查询待配置档次能支持的级别范围。
467const int32_t *levels = nullptr;
468uint32_t levelNum = 0;
469ret = OH_AVCapability_GetSupportedLevelsForProfile(capability, profile, &levels, &levelNum);
470if (ret != AV_ERR_OK || levels == nullptr || levelNum == 0) {
471   // 异常处理。
472}
473OH_AVCLevel maxLevel = static_cast<OH_AVCLevel>(levels[0]);
474for (int32_t i = 1; i < levelNum; i++) {
475   OH_AVCLevel tmp = static_cast<OH_AVCLevel>(levels[i]);
476   if (tmp > maxLevel) {
477      maxLevel = tmp;
478   }
479}
480// 3.(可选)基于支持的最大级别做业务逻辑区分。
481if (maxLevel >= AVC_LEVEL_51) {
482   // level5.1以上,宽、高可配置3840x2160。
483} else if (maxLevel >= AVC_LEVEL_4) {
484   // level4.0以上,宽、高可配1920x1080。
485} else if (maxLevel >= AVC_LEVEL_31) {
486   // level3.1以上,宽、高可配1280x720。
487} else {
488   // 报错,不做编码。
489}
490// 4. 配置档次参数。
491OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
492if (videoEnc == nullptr) {
493   // 异常处理。
494}
495OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1920, 1080);
496if (format == nullptr) {
497   // 异常处理。
498}
499if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile)) {
500   // 异常处理。
501}
502if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
503   // 异常处理。
504}
505OH_AVFormat_Destroy(format);
506```
507
508已知需要的编码档次和级别组合,直接查询支持情况示例如下。
509
510```c++
511// 1. 获取H.264编码器能力实例。
512OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
513if (capability == nullptr) {
514   // 异常处理。
515}
516// 2. 查询编码档次和级别是否支持。
517bool isSupported = OH_AVCapability_AreProfileAndLevelSupported(capability, AVC_PROFILE_MAIN, AVC_LEVEL_51);
518```
519
520### 设置正确的视频宽高
521
522视频编解码器对宽度和高度有对齐约束。例如,主流编解码器默认编解码像素格式为YUV420系列,UV分量在宽度和高度两个方向都会下采样为原始尺寸的一半,因此视频编解码的宽度和高度至少要按2对齐。其他因素也可能导致更严格的对齐约束。
523
524视频编解码的宽高不仅会受帧级编解码能力限制,同时也会受协议级别对帧级能力的限制。以H.264为例,AVC_LEVEL_51限定最大每帧宏块数目为36864个。
525
526根据视频高度计算最大视频宽度的公式如下。
527
528![](figures/formula-maxmbsperframe.png)
529
530*MaxMBsPerFrameLevelLimits*表示协议限定的编解码器最大每帧宏块数,*MaxMBsPerFrameSubmit*表示编解码器上报的最大每帧宏块数,实际能力取这两者的最小值。
531
532| 接口     | 功能描述                         |
533| -------- | ---------------------------- |
534| OH_AVCapability_GetVideoWidthAlignment     | 获取当前视频编解码器的宽对齐。 |
535| OH_AVCapability_GetVideoHeightAlignment    | 获取当前视频编解码器的高对齐。 |
536| OH_AVCapability_GetVideoWidthRange             | 获取当前视频编解码器支持的宽的范围。 |
537| OH_AVCapability_GetVideoHeightRange            | 获取当前视频编解码器支持的高的范围。 |
538| OH_AVCapability_GetVideoWidthRangeForHeight    | 获取当前视频编解码器在给定高情况下的宽的范围。 |
539| OH_AVCapability_GetVideoHeightRangeForWidth    | 获取当前视频编解码器在给定宽情况下的高的范围。 |
540| OH_AVCapability_IsVideoSizeSupported           | 校验当前视频编解码器是否支持给定的宽高组合。 |
541
542校验视频高度和宽度是否支持,示例如下。
543
544```c++
545int32_t width = 1920;
546int32_t height = 1080;
547OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
548if (capability == nullptr) {
549   // 异常处理。
550}
551// 1. 确认视频宽高是否支持。
552bool isSupported = OH_AVCapability_IsVideoSizeSupported(capability, width, height);
553if (!isSupported) {
554   // 2. (可选) 按已知视频高或已知视频宽查询详细限制,并调整。
555}
556```
557
558如果视频高度和视频宽度校验不支持或配置失败,可尝试以下方法确定正确的视频宽高范围。
559
560已知视频宽度,可以按照以下示例找到正确的尺寸配置。
561
562```c++
563int32_t width = 1920;
564OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
565if (capability == nullptr) {
566   // 异常处理。
567}
568// 1. 确认视频宽符合宽对齐要求。
569int32_t widthAlignment = 0;
570int32_t ret = OH_AVCapability_GetVideoWidthAlignment(capability, &widthAlignment);
571if (ret != AV_ERR_OK || widthAlignment <= 0) {
572   // 异常处理。
573} else if (width % widthAlignment != 0) {
574   // 2. (可选) 对齐视频宽。
575   width = (width + widthAlignment - 1) / widthAlignment * widthAlignment;
576}
577// 3. 确认视频宽处在可支持宽范围内。
578OH_AVRange widthRange = {-1, -1};
579ret = OH_AVCapability_GetVideoWidthRange(capability, &widthRange);
580if (ret != AV_ERR_OK || widthRange.maxVal <= 0) {
581   // 异常处理。
582} else if (width < widthRange.minVal || width > widthRange.maxVal) {
583   // 4. (可选) 调整视频宽。
584   width = std::min(std::max(width, widthRange.minVal), widthRange.maxVal);
585}
586// 5. 基于视频宽,获取可选视频高的范围。
587OH_AVRange heightRange = {-1, -1};
588ret = OH_AVCapability_GetVideoHeightRangeForWidth(capability, width, &heightRange);
589if (ret != AV_ERR_OK || heightRange.maxVal <= 0) {
590   // 异常处理。
591}
592// 6. 从可选高度范围中挑选合适的高度配置。
593```
594
595已知视频高度,可以按照以下示例找到正确的尺寸配置。
596
597```c++
598int32_t height = 1080;
599OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
600if (capability == nullptr) {
601   // 异常处理。
602}
603// 1. 确认视频高符合高对齐要求。
604int32_t heightAlignment = 0;
605int32_t ret = OH_AVCapability_GetVideoHeightAlignment(capability, &heightAlignment);
606if (ret != AV_ERR_OK || heightAlignment <= 0) {
607   // 异常处理。
608} else if (height % heightAlignment != 0) {
609   // 2. (可选) 对齐视频高。
610   height = (height + heightAlignment - 1) / heightAlignment * heightAlignment;
611}
612// 3. 确认视频高处在可支持高范围内。
613OH_AVRange heightRange = {-1, -1};
614ret = OH_AVCapability_GetVideoHeightRange(capability, &heightRange);
615if (ret != AV_ERR_OK || heightRange.maxVal <= 0) {
616   // 异常处理。
617} else if (height < heightRange.minVal || height > heightRange.maxVal) {
618   // 4. (可选) 调整视频高。
619   height = std::min(std::max(height, heightRange.minVal), heightRange.maxVal);
620}
621// 5. 基于视频高,获取可选视频宽的范围。
622OH_AVRange widthRange = {-1, -1};
623ret = OH_AVCapability_GetVideoWidthRangeForHeight(capability, height, &widthRange);
624if (ret != AV_ERR_OK || widthRange.maxVal <= 0) {
625   // 异常处理。
626}
627// 6. 从可选宽度范围中挑选合适的宽度配置。
628```
629
630### 设置正确的视频帧率
631
632视频编解码的帧率受编解码器的每秒编解码能力和协议级别的每秒处理能力限制。例如,H.264的AVC_LEVEL_51限定最大每秒宏块数目为983040个。
633
634根据视频的宽度和高度,计算最大帧率的公式如下。
635
636![](figures/formula-maxmbspersecond.png)
637
638*MaxMBsPerSecondLevelLimits*表示协议限定的编解码器最大每秒宏块数,*MaxMBsPerSecondSubmit*表示编解码器上报的最大每秒宏块数,实际能力取这两者的最小值。
639
640| 接口     | 功能描述                         |
641| -------- | ---------------------------- |
642| OH_AVCapability_GetVideoFrameRateRange             | 获取当前视频编解码器支持的帧率的范围。 |
643| OH_AVCapability_GetVideoFrameRateRangeForSize      | 获取当前视频编解码器在给定图像尺寸情况下的帧率的范围。 |
644| OH_AVCapability_AreVideoSizeAndFrameRateSupported  | 校验视频编解码器是否支持视频大小和帧率的特定组合。 |
645
646有帧率目标需求时,校验帧率是否在可选范围内。示例如下。
647
648```c++
649int32_t frameRate = 120;
650OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
651if (capability == nullptr) {
652   // 异常处理。
653}
654// 1. 获取支持的帧率范围。
655OH_AVRange frameRateRange = {-1, -1};
656int32_t ret = OH_AVCapability_GetVideoFrameRateRange(capability, &frameRateRange);
657if (ret != AV_ERR_OK || frameRateRange.maxVal <= 0) {
658   // 异常处理。
659}
660// 2. 判断是否在可选帧率范围内。
661bool isSupported = frameRate >= frameRateRange.minVal && frameRate <= frameRateRange.maxVal;
662```
663
664根据待配置的尺寸选择合适的帧率配置,示例代码如下。
665
666```c++
667constexpr int32_t width = 1920;
668constexpr int32_t height = 1080;
669int32_t frameRate = 120;
670OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
671if (capability == nullptr) {
672   // 异常处理。
673}
674// 1. 确认待配置尺寸是否能达到理想帧率。
675bool isSupported = OH_AVCapability_AreVideoSizeAndFrameRateSupported(capability, width, height, frameRate);
676if (!isSupported) {
677   // 2. 基于待配置视频尺寸,查询支持的帧率范围,并基于查询到的帧率调整待配置帧率。
678   OH_AVRange frameRateRange = {-1, -1};
679   int32_t ret = OH_AVCapability_GetVideoFrameRateRangeForSize(capability, width, height, &frameRateRange);
680   if (ret != AV_ERR_OK || frameRateRange.maxVal <= 0) {
681      // 异常处理。
682   }
683   frameRate = std::min(std::max(frameRate, frameRateRange.minVal), frameRateRange.maxVal);
684}
685
686// 3. 配置尺寸和帧率参数。
687OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
688if (videoEnc == nullptr) {
689   // 异常处理。
690}
691OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, width, height);
692if (format == nullptr) {
693   // 异常处理。
694}
695if (!OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, static_cast<double>(frameRate))) {
696   // 异常处理。
697}
698if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
699   // 异常处理。
700}
701OH_AVFormat_Destroy(format);
702```
703
704### 设置正确的视频像素格式信息
705
706视频像素格式指示的编码输入图像或解码输出图像的像素排布方式,参考[OH_AVPixelFormat](../../reference/apis-avcodec-kit/_core.md#oh_avpixelformat-1)。
707
708| 接口     | 功能描述                         |
709| -------- | ---------------------------- |
710| OH_AVCapability_GetVideoSupportedPixelFormats             | 获取当前视频编解码器支持的像素格式。 |
711
712```c++
713constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_NV12;
714OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
715if (capability == nullptr) {
716   // 异常处理。
717}
718// 1. 获取当前视频编解码器支持的像素格式。
719const int32_t *pixFormats = nullptr;
720uint32_t pixFormatNum = 0;
721int32_t ret = OH_AVCapability_GetVideoSupportedPixelFormats(capability, &pixFormats, &pixFormatNum);
722if (ret != AV_ERR_OK || pixFormats == nullptr || pixFormatNum == 0) {
723   // 异常处理。
724}
725// 2. 校验是否支持对应像素格式。
726bool isMatched = false;
727for (int i = 0; i < pixFormatNum; i++) {
728   if (pixFormats[i] == DEFAULT_PIXELFORMAT) {
729      isMatched = true;
730      break;
731   }
732}
733if (!isMatched) {
734   // 3. 替换其他像素格式输入或选择其他编解码器。
735}
736```
737
738### 查询编解码特性支持情况并获取特性属性信息
739
740编解码特性是指在特定编解码场景中使用的可选特性,例如视频编码场景的时域可分级编码、 低时延编解码等。具体请参考[OH_AVCapabilityFeature](../../reference/apis-avcodec-kit/_a_v_capability.md#oh_avcapabilityfeature-1)。
741| 接口     | 功能描述                         |
742| -------- | ---------------------------- |
743| OH_AVCapability_IsFeatureSupported              | 确认当前编解码器是否支持给定的特性。 |
744| OH_AVCapability_GetFeatureProperties            | 获取当前编解码器支持的指定特性的属性。|
745
746查询H.264编码器是否支持长期参考帧特性,示例如下。
747
748```c++
749constexpr int32_t NEEDED_LTR_NUM = 2;
750OH_AVFormat *format = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1920, 1080);
751OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
752if (capability == nullptr) {
753   // 异常处理。
754}
755// 1. 查询是否支持长期参考帧特性。
756bool isSupported = OH_AVCapability_IsFeatureSupported(capability,VIDEO_ENCODER_LONG_TERM_REFERENCE);
757if (isSupported) {
758   // 2. 查询支持的长期参考帧个数。
759   OH_AVFormat *properties = OH_AVCapability_GetFeatureProperties(capability, VIDEO_ENCODER_LONG_TERM_REFERENCE);
760   if (properties == nullptr) {
761      // 异常处理。
762   }
763   int32_t maxLTRCount = -1;
764   bool ret = OH_AVFormat_GetIntValue(properties, OH_FEATURE_PROPERTY_KEY_VIDEO_ENCODER_MAX_LTR_FRAME_COUNT, &maxLTRCount);
765   if (ret && maxLTRCount >= NEEDED_LTR_NUM) {
766      if (!OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT, NEEDED_LTR_NUM)) {
767         // 异常处理。
768      }
769   }
770}
771// 3. 编码器创建和配置。
772OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
773if (OH_VideoEncoder_Configure(videoEnc, format) != AV_ERR_OK) {
774   // 异常处理。
775}
776```