1. Codec模块简述:
Codec(Coder-Decoder)是指编解码器,用于压缩或解压缩视频、图像、音频等媒体数据;J6 Soc中存在两种硬件编解码单元,分别是VPU(Video process unit)和JPU(Jpeg process unit),可提供4K@90fps的视频编解码能力和4K@90fps的图像编解码能力。
1.1 硬件特性:
1.1.1 JPU硬件特性:

1.1.2 VPU硬件特性:


1.2 软件功能:
MediaCodec子系统会提供音视频和图像的编解码组件,原始流封装和视频录像等功能。该系统主要会封装底层codec硬件资源和软件编解码库,为上层提供编解码能力。开发者可以基于提供的编解码接口实现H265和H264视频的编解码功能,也可以使用JPEG编码功能将摄像头数据存成JPEG图片,还可以使用视频录像功能实现摄像头数据的录制。
1.2.1 整体框架:

1.2.2 控制接口:
hb_s32 hb_mm_mc_initialize(media_codec_context_t *context):初始化编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_INITIALIZED状态。
hb_s32 hb_mm_mc_configure(media_codec_context_t *context):配置编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_CONFIGURED状态。
hb_s32 hb_mm_mc_start(media_codec_context_t *context, const mc_av_codec_startup_params_t *info):启动编码/解码流程,MediaCodec将创建编解码实例、设置序列或解析数据流、注册Framebuffer、编码头信息等,调用成功后MediaCodec进入MEDIA_CODEC_STATE_STARTED状态。
hb_s32 hb_mm_mc_stop(media_codec_context_t *context):停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后MediaCodec回到MEDIA_CODEC_STATE_INITIALIZED状态。
hb_s32 hb_mm_mc_release(media_codec_context_t *context):释放MediaCodec内部所有资源,用户需要在调用该函数前调用hb_mm_mc_stop来停止编解码,操作成功后MediaCodec进入MEDIA_CODEC_STATE_UNINITIALIZED状态。
hb_s32 hb_mm_mc_queue_input_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):填充需要处理的buffer到MediaCodec中。
hb_s32 hb_mm_mc_dequeue_input_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):获取输入的buffer。
hb_s32 hb_mm_mc_queue_output_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, hb_s32 timeout):返还处理完的output buffer到MediaCodec中。
hb_s32 hb_mm_mc_dequeue_output_buffer(media_codec_context_t *context, media_codec_buffer_t *buffer, media_codec_output_buffer_info_t *info, hb_s32 timeout):获取输出的buffer。
1.2.3 码率控制模式:
MediaCodec支持对H264/H265和MJPEG协议的码率控制,分别支持H264/H265编码通道的CBR、VBR、AVBR、FixQp和QpMap五种码率控制方式,以及支持MJPGE编码通道的FixQp码率控制方式。
1.2.3.1 CBR说明:
CBR表示恒定码率,能够保证整体的编码码率稳定。下面是CBR模式下各个参数含义:


1.2.3.2 VBR说明:
VBR表示可变码率,简单场景分配比较大的qp,压缩率小,质量高。复杂场景分配较小qp,可以保证编码图像的质量稳定。下面是VBR模式下各个参数含义:

1.2.3.3 AVBR说明:
ABR表示恒定平均目标码率,简单场景分配较低码率,复杂场景分配足够码率,使得有限的码率能够在不同场景下合理分配,这类似VBR。同时一定时间内,平均码率又接近设置的目标码率,这样可以控制输出文件的大小,这又类似CBR。可以认为是CBR和VBR的折中方案,产生码率和图像质量相对稳定的码流。下面是AVBR模式下各个参数含义:


1.2.3.4 FixQp说明:
FixQp表示固定每一个I帧、P帧的QP值,对于I/P帧可以分别设值。下面是FixQp模式下各个参数含义:

1.2.3.5 QPMAP说明:

1.2.4 编码效果:
根据当前客户使用codec进行视频编码的场景,多将码率模式设置为CBR,当编码的场景较为复杂时,为了保证视频质量,硬件会自动提高码率值,导致输出的视频较预期更大。因此为了兼顾视频质量和实际码率,需要统筹bit_rate和max_qp_I/P值的设置。下面给出了全I帧模式下,不同复杂场景下,码率设置为15000kbps时,不同max_qp_I下实际码率和qp的情况(不同场景复杂程度不同,下列数据仅供参考):

H264/H265编码支持GOP结构的设置,用户可从预置的3种GOP结构种选择,也可自定义GOP结构。
GOP结构表可定义一组周期性的GOP结构,该GOP结构将用于整个编码过程。单个结构表中的元素如下表所示,其中可以指定该图像的参考帧,如果IDR帧后的其他帧指定的参考帧为IDR帧前的数据帧,编码器内部会自动处理这种情况使其不参考其他帧,用户无需关心这种情况。用户在自定义GOP结构时需要指明结构表的数量,最多可定义3个结构表,结构表的顺序需要按照解码顺序排列。 下面表示了结构表中各个元素的含义:

J6中一共支持设置九种GOP预置结构:

2. Codec-Sample使用:
编码 yuv 图像, 生成 h264/h265 视频或 jpg 图片。
2.1 encoder:
2.1.1 调用流程
采用MediaCodec的poll模式来解耦输入和输出,可使编码帧率性能达到最优。 在主线程中灌YUV数据:取出一个空的input buffer,配置YUV数据的地址信息(如phys addr),再queue input buffer并通知编码器处理该帧数据; 另一个线程取输出码流:通过select接收硬件编码完成通知,取出一个硬件填满输出码流的output buffer,将编码结果写到文件中后归还output buffer。

check_and_init_test:打开输入文件(yuv),并打开内存管理模块申请内存缓冲;
hb_mm_mc_initialize:初始化编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_INITIALIZED状态;
hb_mm_mc_configure:配置编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_CONFIGURED状态;
hb_mm_mc_start:启动编码/解码流程,MediaCodec将创建编解码实例、设置序列或解析数据流、注册Framebuffer、编码头信息等,调用成功后MediaCodec进入MEDIA_CODEC_STATE_STARTED状态;
hb_mm_mc_dequeue_input_buffer:获取输入的buffer;
read_input_frames:从输入文件(yuv)中读取视频帧数据,并将其刷新到buffer中;
hb_mm_mc_queue_input_buffer:填充需要处理的buffer到MediaCodec中;
hb_mm_mc_dequeue_output_buffer:获取输出的buffer;
write_output_streams:outputbuffer写入outFile中;
hb_mm_mc_queue_output_buffer:返还处理完的output buffer到MediaCodec中;
hb_mm_mc_stop:停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后MediaCodec回到MEDIA_CODEC_STATE_INITIALIZED状态;
hb_mm_mc_release:释放MediaCodec内部所有资源,操作成功后MediaCodec进入MEDIA_CODEC_STATE_UNINITIALIZED状态。
2.1.2 源码主干:
Encoder:
2.2 decoder
VPU/JPU从DDR中获得H265/H264/JPG输入源,经过硬件解码后生成yuv图像
2.2.1 调用流程

check_and_init_test:打开输入文件(h265),并打开内存管理模块申请内存缓冲;
hb_mm_mc_initialize:初始化编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_INITIALIZED状态;
hb_mm_mc_configure:配置编码或解码器,调用成功后MediaCodec进入MEDIA_CODEC_STATE_CONFIGURED状态;
hb_mm_mc_start:启动编码/解码流程,MediaCodec将创建编解码实例、设置序列或解析数据流、注册Framebuffer、编码头信息等,调用成功后MediaCodec进入MEDIA_CODEC_STATE_STARTED状态;
hb_mm_mc_dequeue_input_buffer:获取输入的buffer;
hb_mm_mc_dequeue_output_buffer:获取输出的buffer;
write_output_streams:outputbuffer写入outFile中;
hb_mm_mc_queue_output_buffer:返还处理完的output buffer到MediaCodec中;
hb_mm_mc_stop:停止编码/解码流程,退出所有子线程并释放相关资源,调用成功后MediaCodec回到MEDIA_CODEC_STATE_INITIALIZED状态;
hb_mm_mc_release:释放MediaCodec内部所有资源,操作成功后MediaCodec进入MEDIA_CODEC_STATE_UNINITIALIZED状态。
2.2.2 源码主干:
2.3 编译&运行:
获取AppSDK包后,进入appuser执行:
*其中hbrootfs-sdk_0.0.1.XXX_all.deb是地平线自己的库和头文件,rootfs-sdk-focal_0.0.1.XXX_all.deb是系统库,aarch64-linux-hb-gcc_12.2.0_amd64.deb是gcc 12.2.0工具链,目前在ubuntu22.04非docker环境下运行正常。其它环境不能保证。
进入toolchain执行:
Sample代码路径:
运行参数说明:

复制/src源码到新建文件夹codec并构建新Makefile:
Makefile:
执行make完成编译,生成的文件为./program

使用WinScp将program传输到单板上。*需要encode的yuv文件请用户自行准备,本文档使用PYM生成的yuv文件。
通过ssh或串口进入/home/hobot/执行:*w和h需要进行16字节对齐,如原始yuv不支持则会出现数据丢失
Sample运行时日志:
生成的缩放jpg文件存放在指定-o目录下。
生成的Jpeg效果如下:

*有关jpg工具查看1080p图片时出现绿边问题:

问题说明:这是因为当前ip进行编码时按照16位对齐进行,假如到最后如果是8位对齐而不是16位对齐,那么编码器就会在后面补齐,这部分补齐的数据是随机产生的,不属于有效数据;

使用YUView打开生成的3840x2160.yuv:

*注意配置offset:




