开发者可以调用本模块的Native API接口,完成视频编码,即将未压缩的视频数据压缩成视频码流。
当前支持的编码能力如下:
目前仅支持硬件编码,基于MimeType创建编码器时,支持配置为H264 (OH_AVCODEC_MIMETYPE_VIDEO_AVC) 和 H265 (OH_AVCODEC_MIMETYPE_VIDEO_HEVC)。
如果需要对HDRVivid视频进行编码,需要配置MimeType为H265 (OH_AVCODEC_MIMETYPE_VIDEO_HEVC),本功能从API version 11开始支持。
通过视频编码,应用可以实现以下重点能力,包括:
限制约束
- buffer模式不支持10bit的图像数据。
- 由于硬件编码器资源有限,每个编码器在使用完毕后都必须调用OH_VideoEncoder_Destroy()函数来销毁实例并释放资源。
- 在调用Flush,Reset,Stop的过程中,开发者不应对之前回调函数获取到的OH_AVBuffer继续进行操作。
Surface输入与Buffer输入
-
两者的数据来源不同。
-
两者的适用场景不同。
- Surface输入是指用OHNativeWindow来传递输入数据,可以与其他模块对接,例如相机模块。
- Buffer输入是指有一块预先分配好的内存区域,调用者需要将原始数据拷贝进这块内存区域中。更适用于从文件中读取视频数据等场景。
- 在接口调用的过程中,两种方式的接口调用方式基本一致,但存在以下差异点:
- Buffer模式下,应用调用OH_VideoEncoder_PushInputBuffer()输入数据;Surface模式下,应用应在编码器就绪前调用OH_VideoEncoder_GetSurface(),获取OHNativeWindow用于传递视频数据。
- Buffer模式下,应用调用OH_VideoEncoder_PushInputBuffer()传入结束flag,编码器读取到尾帧后,停止编码;Surface模式下,需要调用OH_VideoEncoder_NotifyEndOfStream()通知编码器输入流结束。
两种模式的开发步骤详细说明请参考:Surface模式和Buffer模式。
状态机调用关系
如下为状态机调用关系图:
-
有两种方式可以使编码器进入Initialized状态:
- 初始创建编码器实例时,编码器处于Initialized状态
- 任何状态下调用OH_VideoEncoder_Reset()方法,编码器将会移回Initialized状态
-
Initialized状态下,调用OH_VideoEncoder_Configure()方法配置编码器,配置成功后编码器进入Configured状态。
-
Configured状态下调用OH_VideoEncoder_Prepare()进入Prepared状态。
-
Prepared状态调用OH_VideoEncoder_Start()方法使编码器进入Executing状态。
- 处于Executing状态时,调用OH_VideoEncoder_Stop()方法可以使编码器返回到Prepared状态
-
在极少数情况下,编码器可能会遇到错误并进入Error状态。编码器的错误传递,可以通过队列操作返回无效值或者抛出异常。
- Error状态下可以调用OH_VideoEncoder_Reset()方法将编码器移到Initialized状态;或者调用OH_VideoEncoder_Destroy()方法移动到最后的Released状态
-
Executing 状态具有三个子状态:Flushed、Running和End-of-Stream:
- 在调用了OH_VideoEncoder_Start()之后,编码器立即进入Running子状态。
- 对于处于Executing状态的编码器,可以调用OH_VideoEncoder_Flush()方法返回到Flushed子状态。
- 当待处理数据全部传递给编码器后,可以在input buffers队列中为最后一个入队的input buffer中添加AVCODEC_BUFFER_FLAGS_EOS标记,遇到这个标记时,编码器会转换为End-of-Stream子状态。在此状态下,编码器不再接受新的输入,但是仍然会继续生成输出,直到输出到达尾帧。
-
使用完编码器后,必须调用OH_VideoEncoder_Destroy()方法销毁编码器实例。使编码器进入Released 状态。
开发指导
详细的API说明请参考API文档。
如下为视频编码调用关系图:
在 CMake 脚本中链接动态库
target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
target_link_libraries(sample PUBLIC libnative_media_core.so)
target_link_libraries(sample PUBLIC libnative_media_venc.so)
Surface模式
参考以下示例代码,开发者可以完成Surface模式下视频编码的全流程。此处以surface数据输入,编码成H.264格式为例。
本模块目前仅支持异步模式的数据轮转。
- 添加头文件。
#include <multimedia/player_framework/native_avcodec_videoencoder.h>
#include <multimedia/player_framework/native_avcapability.h>
#include <multimedia/player_framework/native_avcodec_base.h>
#include <multimedia/player_framework/native_avformat.h>
#include <multimedia/player_framework/native_avbuffer.h>
#include <fstream>
- 全局变量。
// 配置视频帧宽度(必须)
int32_t width = 320;
// 配置视频帧高度(必须)
int32_t height = 240;
// 配置视频像素格式(必须)
constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_NV12;
int32_t widthStride = 0;
int32_t heightStride = 0;
-
创建编码器实例对象。
应用可以通过名称或媒体类型创建编码器。示例中的变量说明如下:
- videoEnc:视频编码器实例的指针;
- capability:编解码器能力查询实例的指针;
- OH_AVCODEC_MIMETYPE_VIDEO_AVC:AVC格式视频码流的名称。
创建方式示例如下:
// 通过codec name创建编码器,应用有特殊需求,比如选择支持某种分辨率规格的编码器,可先查询capability,再根据codec name创建编码器。
OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
const char *codecName = OH_AVCapability_GetName(capability);
OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
// 通过MIME TYPE创建编码器,只能创建系统推荐的特定编解码器
// 涉及创建多路编解码器时,优先创建硬件编码器实例,硬件资源不够时再创建软件编码器实例
OH_AVCodec *vide