【鸿蒙实战开发】媒体开发-视频编码详解

开发者可以调用本模块的Native API接口,完成视频编码,即将未压缩的视频数据压缩成视频码流。

当前支持的编码能力如下:

image.png

目前仅支持硬件编码,基于MimeType创建编码器时,支持配置为H264 (OH_AVCODEC_MIMETYPE_VIDEO_AVC) 和 H265 (OH_AVCODEC_MIMETYPE_VIDEO_HEVC)。

如果需要对HDRVivid视频进行编码,需要配置MimeType为H265 (OH_AVCODEC_MIMETYPE_VIDEO_HEVC),本功能从API version 11开始支持。

通过视频编码,应用可以实现以下重点能力,包括:
image.png

限制约束

  1. buffer模式不支持10bit的图像数据。
  2. 由于硬件编码器资源有限,每个编码器在使用完毕后都必须调用OH_VideoEncoder_Destroy()函数来销毁实例并释放资源。
  3. 在调用Flush,Reset,Stop的过程中,开发者不应对之前回调函数获取到的OH_AVBuffer继续进行操作。

Surface输入与Buffer输入

  1. 两者的数据来源不同。

  2. 两者的适用场景不同。

  • Surface输入是指用OHNativeWindow来传递输入数据,可以与其他模块对接,例如相机模块。
  • Buffer输入是指有一块预先分配好的内存区域,调用者需要将原始数据拷贝进这块内存区域中。更适用于从文件中读取视频数据等场景。
  1. 在接口调用的过程中,两种方式的接口调用方式基本一致,但存在以下差异点:
  • Buffer模式下,应用调用OH_VideoEncoder_PushInputBuffer()输入数据;Surface模式下,应用应在编码器就绪前调用OH_VideoEncoder_GetSurface(),获取OHNativeWindow用于传递视频数据。
  • Buffer模式下,应用调用OH_VideoEncoder_PushInputBuffer()传入结束flag,编码器读取到尾帧后,停止编码;Surface模式下,需要调用OH_VideoEncoder_NotifyEndOfStream()通知编码器输入流结束。

两种模式的开发步骤详细说明请参考:Surface模式和Buffer模式。

状态机调用关系

如下为状态机调用关系图:

image.png

  1. 有两种方式可以使编码器进入Initialized状态:

    • 初始创建编码器实例时,编码器处于Initialized状态
    • 任何状态下调用OH_VideoEncoder_Reset()方法,编码器将会移回Initialized状态
  2. Initialized状态下,调用OH_VideoEncoder_Configure()方法配置编码器,配置成功后编码器进入Configured状态。

  3. Configured状态下调用OH_VideoEncoder_Prepare()进入Prepared状态。

  4. Prepared状态调用OH_VideoEncoder_Start()方法使编码器进入Executing状态。

    • 处于Executing状态时,调用OH_VideoEncoder_Stop()方法可以使编码器返回到Prepared状态
  5. 在极少数情况下,编码器可能会遇到错误并进入Error状态。编码器的错误传递,可以通过队列操作返回无效值或者抛出异常。

    • Error状态下可以调用OH_VideoEncoder_Reset()方法将编码器移到Initialized状态;或者调用OH_VideoEncoder_Destroy()方法移动到最后的Released状态
  6. 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子状态。在此状态下,编码器不再接受新的输入,但是仍然会继续生成输出,直到输出到达尾帧。
  7. 使用完编码器后,必须调用OH_VideoEncoder_Destroy()方法销毁编码器实例。使编码器进入Released 状态。

开发指导

详细的API说明请参考API文档。

如下为视频编码调用关系图:

image.png

在 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格式为例。

本模块目前仅支持异步模式的数据轮转。

  1. 添加头文件。
#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>
  1. 全局变量。
// 配置视频帧宽度(必须)
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;
  1. 创建编码器实例对象。

    应用可以通过名称或媒体类型创建编码器。示例中的变量说明如下:

    • 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值