跳到主要内容

Linux Encoder 开发指南

前言

文档简介

本文档重点阐述 Allwinner 平台视频编码的驱动开发方法、使用规范与调试技巧。目的是为了视频编码系统开发与支持等相关技术人员,能对 Allwinner 平台视频编码器的驱动体系有更深入的理解,并通过实际应用指导快速开展高效开发、定位问题与解决问题。文档详细介绍了编码器的接口设计、数据结构、配置方法及最佳实践,为开发者提供全面的技术参考。

目标读者

视频编码系统开发人员、视频编码系统技术支持人员

符号约定

本文档中会使用不同符号区分信息类型,具体释义如下:

备注

用于呈现技术核心信息(如功能原理、核心参数定义)、流程补充内容(如步骤细节说明)等。

提示

用于分享技术操作中的高效方法(如命令行快捷指令、配置项优化窍门)与实践技巧。

注意

用于突出技术操作中易出错的环节(如参数配置边界、操作顺序要求)的提示。

适用平台

平台内核版本
V861Linux 5.10及以上内核版本

相关术语

术语解释
CABACContext-based Adaptive Binary Arithmetic Coding,基于上下文的自适应二进制算术编码
CAVLCContext-based Adaptive Variable Length Coding,基于上下文的自适应可变长度编码
Encoder视频编码器,将原始视频数据压缩编码为特定格式(如H.264、JPEG等)的硬件或软件模块
H.264一种高效的视频压缩编码标准,也称为MPEG-4 AVC
I帧Intra-frame,帧内编码帧,可独立编码的完整图像帧
JPEG联合图像专家小组制定的静态图像压缩标准
P帧Predicted-frame,预测帧,基于前面的I帧或P帧进行预测编码
QPQuantization Parameter,量化参数,影响编码质量和码率
ROIRegion of Interest,感兴趣区域,可对视频中特定区域进行特殊处理
SVCScalable Video Coding,可伸缩视频编码,支持时域、空域等多种可伸缩性
VBVVideo Buffer Verifier,视频缓冲验证器,用于控制码率输出

概述

本章节主要介绍Allwinner平台V861芯片的视频编码技术规格及编码特性。

Encoder功能概述

Allwinner平台Encoder模块支持JPEG、H.264、H265格式编码,本节将详细介绍其主要特性,包括支持的编码格式、分辨率范围、编码模式等关键参数,帮助开发者充分了解编码器的能力边界和优化空间。

H.264编码特性

H.264编码是Encoder模块的核心功能之一,具有以下特性:

  • Profile支持:支持Baseline Profile、Main Profile、High Profile 5.1
  • 编码模式:支持I帧、P帧编码
  • 熵编码方式:支持CABAC和CAVLC
  • 码率控制:支持CBR(恒定码率)、VBR(可变码率)、AVBR(适配式可变码率控制方式)等多种码率控制方式
  • 特殊功能:支持ROI编码、循环帧内刷新、时域SVC等高级特性
  • 最大性能:4k@30fps

H.265编码特性

H.264编码是Encoder模块的核心功能之一,具有以下特性:

  • Profile支持:支持Main Profile 5.0
  • 编码模式:支持I帧、P帧编码
  • 熵编码方式:支持CABAC
  • 码率控制:支持CBR(恒定码率)、VBR(可变码率)、AVBR(适配式可变码率控制方式)等多种码率控制方式
  • 特殊功能:支持ROI编码、循环帧内刷新、时域SVC等高级特性
  • 最大性能:4k@35fps

JPEG编码特性

JPEG编码主要用于静态图像压缩,具有以下特性:

  • 质量控制:支持0-100级的质量参数调整
  • EXIF支持:支持嵌入图像元数据信息
  • 编码模式:支持单帧JPEG编码和MJPEG序列编码
  • 最大性能:4k@30fps

模块驱动开发

本章节介绍Allwinner平台视频编码的结构设计、核心模块功能及API接口规范,帮助开发者理解编码系统的整体架构和模块间的交互关系。

视频编码的模块架构简介

视频编码库采用模块化架构设计,主要由四个核心模块组成,分别为帧缓冲输入管理模块、视频编码设备、码流输出管理模块、编码控制模块,各模块职责明确,协同工作完成视频编码功能,如下图所示:

视频编码库模块结构图

模块名称英文全称主要职责
帧缓冲输入管理模块Frame Buffer Manager管理编码输入图像帧,支持外部内存管理和内部内存分配两种模式,提供高效的帧数据存取接口
视频编码设备Video Encoder Device负责将输入图像帧编码为压缩码流,提供硬件编码能力接口,支持H.264、H.265、JPEG等编码格式
码流输出管理模块Bitstream Manager管理编码输出码流,维护码流缓冲区,记录帧结构信息,支持循环缓冲区管理
编码控制模块vencoder协调各模块工作,控制整体编码流程,对外提供统一的编码库接口函数,实现功能封装

源码清单

编码器驱动源码主要包含头文件、实现文件和配置文件,整体组织结构清晰。

代码工程结构概述

驱动的主要源码文件及说明如下:

.
├── base/ # Core utility modules: logging, message queue, INI parser, ION memory utils, etc.
│ ├── cdcIniparser/ # Custom INI configuration file parser implementation
│ ├── filesink/ # Output sink modules for bitstream and picture data dumping or MD5 checksum
│ └── include/ # Public headers for base utilities (log, memory list, platform config, etc.)
├── conf/ # System and hardware configuration files (e.g., video engine parameters)
├── demo/ # Example applications demonstrating SDK usage
│ ├── jpegdemo/ # JPEG decoding demo
│ ├── vdecoderDemo/ # Raw video stream decoding demo
│ └── vencoderDemo/ # Video encoding demo (v2 architecture)
├── include/ # Global public headers for video codec APIs (decoder/encoder interfaces, types, adapters)
├── install/ # Staging directory for final system installation (e.g., /etc, /usr/lib)
├── InstallDev/ # Development package layout (headers and libs for SDK integration)
├── library/ # Pre-built static and shared libraries
│ ├── glibc/ # Libraries compiled against glibc C runtime
│ ├── musl/ # Libraries compiled against musl C runtime (for lightweight systems)
│ └── out/ # Intermediate static libraries generated during build
├── memory/ # Memory management abstraction layer
│ ├── ionMemory/ # ION-based memory allocator for Linux kernel (Allwinner SoC)
│ └── secureMemory/ # Secure memory allocation for protected content (e.g., DRM)
└── vencoder/ # Video encoder implementation
├── base/ # Encoder core components: bitstream/frame buffer managers
└── libcodec/v2/ # V2 architecture of the video encoding codec backend

视频编码库使用

本章详细介绍Allwinner视频编码库的使用方法,包括编码流程、接口调用顺序、参数配置以及常见问题处理,帮助开发者快速掌握编码功能的实现。

必备条件

在开始使用视频编码库前,请确保满足以下条件:

  • 了解基本的视频编码概念(I帧、P帧、码率、像素格式等)
  • 熟悉C/C++编程语言和Linux/Android开发环境
  • 准备好待编码的原始视频帧数据(支持YUV420P、NV12等像素格式)
  • 确保系统有足够的内存资源分配给编码器

编码控制模块使用流程

Allwinner视频编码库提供了一套完整的接口流程,用户需按照规范的步骤进行操作。具体的使用流程可参考下图所示:

编码流程图

该图展示了视频编码的整体流程,包括初始化、编码循环和资源释放三个主要阶段,接下来会对这三部分进行说明:

  1. 创建编码器实例并初始化

在开始编码前,必须调用以下函数进行初始化:

// 初始化编码器参数
encode_param_t encode_param;
memset(&encode_param, 0, sizeof(encode_param));
encode_param.src_width = 1280;
encode_param.src_height = 736;
encode_param.dst_width = 1280;
encode_param.dst_height = 736;
encode_param.bit_rate = 2*1024*1024;
encode_param.frame_rate = 30;
encode_param.maxKeyFrame = 30;
encode_param.encode_format = VENC_CODEC_H264;
...

// 创建视频编码器实例
VENC_HANDLE pVideoEnc = VencCreate(encode_param.encode_format);

// 初始化编码器
int ret = VencInit(pVideoEnc, &baseConfig);
if (ret != 0) {
printf("初始化编码器失败!\n");
VideoEncDestroy(pVideoEnc);
return -1;
}
  1. 执行编码处理

初始化完成后,执行核心编码流程。该流程需在每次处理一帧数据时重复执行,分为输入帧处理和输出码流获取两个子流程:

a. 输入帧处理流程

// 从编码器获取一个已分配的输入缓冲区
pInputBufInfo = dequeueInputBuf(&pEncContext->mInputBufMgr.valid_quene);
memcpy(&mCurInputBuf, &pInputBufInfo->inputbuffer, sizeof(VencInputBuffer));

if(pInputBufInfo == NULL)
{
logv(" get input buffer failed");
USLEEP(10*1000);
return 1;
}

// 读取YUV数据到缓冲区(假设已打开输入文件in_file)
// Y分量
fread(mCurInputBuf.pAddrVirY, 1, bufferParam->nSizeY, in_file);
// UV分量
fread(mCurInputBuf.pAddrVirY, 1, bufferParam->nSizeY, in_file);

// 添加缓冲区并执行编码
enqueueInputBuf(&pEncContext->mInputBufMgr.empty_quene, pInputBufInfo);
VencQueueInputBuf(pEncContext->pVideoEnc, &mCurInputBuf);
VencStart(pVideoEnc);

if (ret != 0) {
printf("编码一帧失败!\n");
return -1;
}

b. 输出码流获取流程

// 获取编码后的码流帧
result = VencDequeueOutputBuf(pVideoEnc, &outputBuffer);

if(result == VENC_RESULT_BITSTREAM_IS_EMPTY)
{
logv("bitstream is empty ,continue");
break;
}

FWRITE(outputBuffer.pData0, 1, outputBuffer.nSize0, out_file);

//归还outputBuffer
VencQueueOutputBuf(pVideoEnc, &outputBuffer);
备注

输入和输出流程可以并行处理,但需注意线程安全。

  1. 销毁编码器

当所有视频帧处理完毕后,应按以下步骤释放编码器资源:

// 销毁编码器实例
VencDestroy(pVideoEnc);
pVideoEnc = NULL; // 避免悬空指针
注意

确保在程序退出前释放所有编码资源。

编码demo程序使用说明

由于编码demo程序的迭代速度较快,且会针对不同产品做出特性功能开发,故以下说明仅供参考,具体情况请以实际情况为准。

  1. demo路径

编码demo在Android的sdk中的具体路径为:android/frameworks/av/media/libcedarc/demo/vencoderDemo;

若开发环境为linux,则位于platform/Allwinner/multimedia/libcedarc/demo/vencoderDemo文件夹下。

  1. 基本参数介绍

在运行编码器demo时,即demoVencoder(以下简称demo),通过输入不同参数来实现不同的编码功能,目前demo中主流的参数配置如下所示:(以下所属环境为linux5.15系统)

在无法确定当前所使用编码器支持哪些参数输入时,则可以运行demo加上参数-h,即

./demoVencoder -h

将当前demo所支持的输入参数打印出来,可以根据该提示进行使用。

-i           --input                          Input file path
-n --encode_frame_num After encoder n frames, encoder stop
-f --encode_format 0:h264 encoder, 1:jpeg_encoder, 3:h265 encoder
-o --output output file path
-s --srcsize src_size,can be 1920x1080 or 2160,1080,720,480,288
-d --dstsize dst_size,can be 1920x1080 or 2160,1080,720,480,288
-c --compare compare file:reference file path
-q --frequency frequency: the frequency of video engine
-b --bitrate bitRate:kbps
-sr --src_framerate src_framerate:fps
-dr --dst_framerate dst_framerate:fps
-v --vbv_size vbv_size:byte
-gs --gop_size Gop Size:
-kp --key_frm_period Key Frame Period
-gm --gop_mode Gop Mode
-rm --rc_mode RC Mode
-pm --product_mode ProductMode
-in --is_night Is Night
-st --sensor_type Sensor Type
-mt --moving_th Moving Th
-qua --quality Quality
-t --test_cycle Cycle num of testing
-l --logfile Log file path
-overlay --overlay add the overlay function
-overlay_in --overlay_int overlay intput data file
-lbc --lbc 1: no lossy lbc, 2: lossy_2x, 3: lossy_2.5x
-afbc --afbc 1: test afbc input data format
-limit_sp --limit speed 1: limit encoder speed by framerate
-i_qp_min --i qp min set the i_qp_min value
-i_qp_max --i qp max set the i_qp_max value
-p_qp_min --p qp min set the p_qp_min value
-p_qp_max --p qp max set the p_qp_max value
-qp_init --qp init set the qp_init value
-enc_num --encoder num create multi encoder
-pformat --pixel formatt set pixel format
-profile --profile set profile
-level --level set level
-ext_flag --ext_flag --ext_flag
-roi_wb --roi_wb test roi wbyuv.
-rotate --rotate test rotate, 0, 90, 180, 270
-hflip --hflip test hflip
-wb --wb test YUV WB
-wb_ratio --wb_ratio test YUV WB scaler ratio 1: 1/8; 2: 1/2; 3: 1/4
-gdc --gdc test gdc function
-gdc_mode --gdc_mode set gdc mode. 8: Warp_User
-ispbe --ispbe test ispbe function
-crop --crop test sw(1) hw(2) crop
-virz --vir_zoom test virtual zoom
-ir --intra_refresh test intra refresh
-vcu_on --vcu_on vcu: 0-vcu disable, 1-vcu enable
-vcu_auto --vcu auto mode vcu: 1-auto mode, 0-triger mode
-share_num --share buf num --share buf num
-share_bk --share buf bk --share buf bk
-enc_ch0 --enc channle0 --enc channle0
-enc_ch1 --enc channle1 --enc channle1
-enc_ch2 --enc channle2 --enc channle2
-enc_ch3 --enc channle3 --enc channle3
-enc_ch4 --enc channle4 --enc channle4
-enc_ch5 --enc channle5 --enc channle4
-enc_ch6 --enc channle6 --enc channle4
-enc_ch7 --enc channle7 --enc channle4
-enc_ch8 --enc channle8 --enc channle4
-s_1 --srcsize1 src_size2,can be 1920x1080 or 2160,1080,720,480,288
-d_1 --dstsize1 dst_size1,can be 1920x1080 or 2160,1080,720,480,288
-bb --bb test bounding box.
-gray --gray test gray.
-rec_lbc_mode --rec_lbc_mode --0: disable, 1:1.5x , 2: 2.0x, 3: 2.5x, 4: no_lossy
-sei --sei_num -----------
  1. 实例分析

本节提供编码器的详细使用示例,包括不同参数配置场景、日志分析方法以及结果验证步骤,帮助开发者快速上手并解决常见问题。

a. 基础参数配置

Ⅰ. 标准H.264编码示例

使用标准YUV420P视频源进行H.264编码测试:

./demoVencoder -f 0 -n 50 -pformat 2 -i 720p.yuv -o output.h264 -s 1280x720 -d 1280x720 -vcu_on 1 -vcu_auto 1
参数说明取值范围示例值
-i输入YUV文件路径有效文件路径7720p.yuv
-o输出码流文件路径可写文件路径output.h264
-s视频源尺寸W×H格式,支持多种分辨率1280x720
-d输出码流尺寸W×H格式,与源尺寸一致或缩放1280x720
-f编码器类型0:H264, 1:JPEG0
-pformat视频源像素格式0:YUYV, 1:NV12, 2:YUV420P2
-n编码总帧数>0100
-vcu_on开启VCU模式0-11
-vcu_auto开启vcu_auto模式0-11
注意

视频源分辨率和输出码流的尺寸必须严格按照 W×H(宽×高)的格式进行配置。

vcu_on和vcu_auto在V861上必须开启

Ⅱ. 不同编码场景示例

运动编码场景

./demoVencoder -f 0 -n 50 -pformat 2 -i 720p.yuv -o output.h264 -s 1280x720 -d 1280x720 -vcu_on 1 -vcu_auto 1 -i_qp_min 5 -i_qp_max 15

高画质编码场景

./demoVencoder -f 0 -n 50 -pformat 2 -i 720p.yuv -o output.h264 -s 1280x720 -d 1280x720 -vcu_on 1 -vcu_auto 1 -b 5242880

JPEG编码示例

./demoVencoder -f 1 -n 1 -pformat 2 -i 720p.yuv -o output.jpeg -s 1280x720 -d 1280x720 -vcu_on 1 -vcu_auto 1

b. 日志分析详解

运行日志包含丰富的编码信息,以下是关键日志解析:

***************************************************************
*******test begin time[13318s] *******
***************************************************************

*************[0] cycle demo start time[13318s]**************
******************************
encode_format:3 0:h264,1:jpeg,3:h265
encode:50 frames
test lbc: 0
pixel_format: 2
get input file: ./720P.yuv
get output file: 1280x720
get src_size: 1280x720
get dst_size: 1280x720
vbv size: 8388608byte
share_buf_num: 2
extend_flag: 0
hflip: 0
rotate_value: 0
bEnCrop: 0, l320t120w640h480
gdc_en: 0
gdc_mode: 0
test overlay flag: 0
get overlay file: /tmp/01_argb_464x32_time.dat
ispbe_en: 0
wb_yuv: 0
******************************
[13318.239] DEBUG : cdc <ChannelThread:3794>: tmpOutput_path = 1280x720_0.h265
[13318.240] DEBUG : cdc <ChannelThread:3808>: open log_file fail

[13318.240] DEBUG : cdc <veEnvInit:182>: VeContext 0x84af9820, encoder 0, decodec 1
[13318.240] INFO : cdc <veEnvInit:211>: open /dev/cedar_dev fd = 5
[13318.240] DEBUG : cdc <veEnvInit:220>: get ve_reg_addr = 0x84a3a000
[13318.240] DEBUG : cdc <getIcVersion:43>: ** address_macc 0x84a3a000 ve_top_offset = 0x800
[13318.240] DEBUG : cdc <getIcVersion:94>: *** ic_version = 0x1001000021410
[13318.241] DEBUG : cdc <checkFeatureSupport:1525>: bEnableVcuFuncFlag = 0, nEncoderFlag = 0
[13318.241] DEBUG : cdc <VeInitialize:1798>: address_macc = 0x84a3a000, address_vetop = 0x84a3a800
[13318.241] DEBUG : cdc <getSocInfo:1316>: not exist SocInfo plugin, use SocInfo node
[13318.241] DEBUG : cdc <VeInitialize:1801>: *** ic_version = 0x1001000021410
[13318.241] DEBUG : cdc <VeInitialize:1858>: *** nPhyOffset = 0x0
[13318.241] DEBUG : cdc <CdcIonOpen:320>: open /dev/dma_heap/size_pool
[13318.241] DEBUG : cdc <ChannelThread:3878>: baseConfig.eInputFormat = 2
[13318.241] DEBUG : cdc <ChannelThread:3985>: encode_param.encode_format:3

[13318.242] DEBUG : cdc <CdcIniParserInit:38>: load conf file /etc/cedarc.conf ok!
[13318.242] DEBUG : cdc <VencCreate:717>: now cedarc log level:5
[13318.243] WARNING: cdc <setEncParamBeforeInit:2578>: sei_num:0, nType:0, nLength:12, pBuffer(0):(null)
[13318.244] WARNING: cdc <H265SetFbm:7705>: not implement now
[13318.267] WARNING: cdc <offlineGroupNum_init:318>: ** bEnableDynamicConfig = 1
[13318.269] WARNING: cdc <h265regConfig_getDdrBufSize:848>: size info: mE3dFilter:3680, mDblk:10240, mMapInput:14720, mQpMadSseOut:22080
[13318.269] WARNING: cdc <h265regConfig_getDdrBufSize:852>: size info: mRefRecInfo:16384, mRefRecData:955392, mRefRecColMv:14720, mRefRecSubImg:61440, mRgnMv:16512, mColorBBox:1840
**had encoder frame num = 20
[13319.018] WARNING: cdc <ChannelThread:4385>: ch 0 encode stream fps 32
**had encoder frame num = 40
output file is saved:1280x720
*******[0]cycle demo end time[13319s] cur_cycle_time[1s]*******


***************************************************************
*******test end time[13319s] test_total_time[1s]*******
***************************************************************

c. 结果验证与分析

编码完成后,需要进行以下验证以确保编码质量和正确性:

Ⅰ. 文件存在性检查:

ls -lh 1280x720.h265

Ⅱ. 码流格式验证:

使用ffmpeg工具验证码流格式:

ffprobe -v quiet -print_format json -show_format -show_streams 1280x720.h265

预期输出应包含编码格式、分辨率、帧率等信息,确认与输入参数一致。

Ⅲ. 视频播放测试:

ffplay 1280x720.h265

调试方法

编译编码库

编码库编译是视频编码功能开发的基础环节,通过正确的编译配置可以生成适用于不同平台的编码器库文件。本小节介绍在Linux环境下编译libcedarc编码库的具体步骤,帮助开发者快速搭建编码开发环境。

必备条件

  • 已获取完整的SDK源码包
  • 配置好交叉编译工具链
  • 具备基本的Linux命令行操作能力
  • 足够的磁盘空间(建议至少100MB)

确认代码路径

根据开发平台定位编码库源码位置:

平台源码路径说明
Tinaplatform/Allwinner/multimedia/libcedarcTina Linux系统路径

注意:由于SDK结构可能更新,请以实际源码路径为准,必要时联系技术支持确认。

Linux环境编译配置

  1. 在SDK根目录设置编译工具链环境
source buile/envsetup.sh
lunch
  1. 跳转至编码库目录
clibcedarc_p
  1. 编译
mm -b

配置编码日志系统

简介

libcedarc编码器提供完整的日志记录系统,通过配置cedarc.conf文件可灵活控制日志输出级别和内容。合理配置日志系统有助于跟踪编码过程、快速定位问题并优化编码性能。本任务将指导您完成日志系统的配置,实现对编码过程的精准监控。

必备条件

  • 已获取目标平台的cedarc.conf配置文件访问权限
  • 了解基本的日志级别概念(ERROR/WARN/INFO/DEBUG)
  • 确认编码器已正确部署并可运行
  • 具备文件编辑权限

了解日志级别配置

日志系统提供五个级别,根据不同的调试场景选择合适的级别:

级别数值说明使用场景
VERBOSE2详细信息深度调试,开发阶段使用
DEBUG3调试信息功能调试,问题排查
INFO4一般信息正常流程状态、关键操作记录
WARNING5警告信息非致命异常、性能瓶颈等
ERROR6错误信息编码失败、参数错误等严重问题

定位cedarc.conf配置文件

不同平台的配置文件路径如下:

平台配置文件路径
Tina/etc/cedarc.conf
提示

若配置文件不存在,请手动创建或修改源码中的默认配置。创建时需确保文件权限正确设置,以便编码器进程能够读取配置。

访问配置文件的命令示例

cd /etc
cat cedarc.conf

配置日志级别参数

在cedarc.conf文件中配置以下参数控制日志输出:

## 日志输出规则: level >= log_level
## VERBOSE = 2,
## DEBUG = 3,
## INFO = 4,
## WARNING = 5,
## ERROR = 6,
cdc_log_level = 5
vdec_log_level = 5
venc_log_level = 5

确认成功

完成配置后,按以下步骤验证日志系统配置成功:

  1. 重新运行编码程序

    ./demoVencoder -f 0 -n 50 -pformat 2 -i 720p.yuv -o output.h264 -s 1280x720 -d 1280x720 -vcu_on 1 -vcu_auto 1
  2. 查看日志输出

    • 由于当前配置为WARNING级别(5),应只看到WARNING和ERROR级别的日志

    • 检查日志中是否包含关键警告信息,如资源限制、参数建议等

    • 在Linux系统上,可使用以下命令过滤日志:

      dmesg | grep -i "cedarc"

典型问题排查

初始化失败

编码器初始化失败是常见问题,本节介绍排查方法。

可能原因

  • 设备节点不存在:检查驱动是否正确加载
  • 权限问题:确认应用程序有设备访问权限
  • 资源不足:检查内存和其他系统资源是否充足
  • 硬件问题:编码器硬件可能存在故障

排查步骤

  1. 检查设备节点:ls -la /dev/cedar_dev
  2. 检查权限设置:sudo chmod +x ./demoVencoder
  3. 查看内核日志:dmesg | grep -i error

FAQ

编码质量问题

图像模糊

问题描述:编码后的视频图像模糊不清,细节丢失。

可能原因及解决方案

  • 码率过低:增加编码码率,提高图像质量
  • 量化参数过大:减小QP值,降低压缩率
  • 图像预处理不当:检查输入图像是否经过不当处理
  • 编码预设设置不合理:调整编码预设,平衡质量和性能

优化建议

// 设置更高的码率
int bitrate = 8000000; // 8Mbps
VencSetParameter(pVideoEnc, VENC_IndexParamBitrate, &bitRate);

// 调整QP范围
VencQPRange qpRange;
QpRange.nMaxqp = encode_param->h264_func.h264Param.sQPRange.nMaxqp;
QpRange.nMinqp = encode_param->h264_func.h264Param.sQPRange.nMinqp;
VencSetParameter(pVideoEnc, VENC_IndexParamH264QPRange, (void *)&QpRange);

运动模糊

问题描述:运动场景中出现严重的模糊或拖尾。

可能原因及解决方案

  • 帧率过低:提高编码帧率,减少运动模糊
  • 码率分配不合理:调整码率控制策略,为运动场景分配更多码率

优化配置

// 提高帧率
int framerate = 60;
VencSetParameter(pVideoEnc, VENC_IndexParamFramerate, &framerate);

// 调整QP范围
VencQPRange qpRange;
QpRange.nMaxqp = encode_param->h264_func.h264Param.sQPRange.nMaxqp;
QpRange.nMinqp = encode_param->h264_func.h264Param.sQPRange.nMinqp;
VencSetParameter(pVideoEnc, VENC_IndexParamH264QPRange, (void *)&QpRange);

性能优化

编码速度慢

问题描述:编码速度达不到实时要求,延迟较高。

可能原因及解决方案

  • 分辨率过高:适当降低编码分辨率
  • 复杂度过高:调整编码复杂度参数
  • 硬件资源不足:检查CPU使用率和内存占用
  • 编码器未正确初始化:确保编码器参数设置合理

内存泄漏

问题描述:长时间运行后系统内存不足,出现内存泄漏。

可能原因及解决方案

  • 缓冲区未释放:确保正确释放输入输出缓冲区
  • 编码器未销毁:编码结束后调用销毁函数
  • 重复初始化:避免重复创建编码器实例

正确的资源管理

// 正确释放编码器资源
VencDestroy(pVideoEnc);

// 释放申请的内存
EncAdapterMemPfree(pRoiConfig.pRoiYAddrVir);

// 释放码流缓冲区
EncAdapterMemPfree(pRoiConfig.pRoiCAddrVir);

常见错误处理

编码失败

问题描述:调用VencStart返回错误。

可能原因及解决方案

  • 输入数据异常:检查输入缓冲区数据是否正确
  • 参数设置错误:验证编码器参数设置
  • 硬件故障:检查编码器硬件状态

处理示例

int result = VencStart(pVideoEnc);
if(result < 0)
{
logd("encoder error, goto out");
// 执行清理操作
goto out;
}

文件读取失败

问题描述:无法正确读取输入文件数据。

可能原因及解决方案

  • 文件路径错误:检查输入文件路径是否正确
  • 文件权限问题:确认有文件读取权限
  • 文件格式不支持:确保文件格式与编码器匹配

文件读取检查

FILE* in_file = fopen(input_file_path, "rb");
if(in_file == NULL)
{
loge("open input file error\n");
return -1;
}

// 检查读取的数据大小
unsigned int size1 = fread(inputBuffer.pAddrVirY, 1, bufferParam.nSizeY, in_file);
if(size1 != bufferParam.nSizeY)
{
loge("read file data error\n");
return -1;
}

参数配置

如何设置ROI区域

说明:感兴趣区域(ROI)可以为特定区域分配更多码率,提高该区域的编码质量。

配置方法

VencROIConfig roiConfig[4];

// 配置第一个ROI区域
sRoiConfig[0].bEnable = 1;
sRoiConfig[0].index = 0;
sRoiConfig[0].nQPoffset = 10;
sRoiConfig[0].sRect.nLeft = 0;
sRoiConfig[0].sRect.nTop = 0;
sRoiConfig[0].sRect.nWidth = 1280;
sRoiConfig[0].sRect.nHeight = 320;

// 设置ROI参数
VencSetParameter(pVideoEnc, VENC_IndexParamROIConfig, &h264_func.sRoiConfig[0]);

附录

vencoder 函数文档

vencoderDeviceCreate

【目的】

创建编码器设备实例。

【语法】

VENC_DEVICE* vencoderDeviceCreate(VENC_CODEC_TYPE type);

【参数】

  • type: 编码器类型,详见 VENC_CODEC_TYPE 枚举

【返回值】

成功返回指向新创建设备的指针,失败返回NULL。

【结构体定义】

// 编码器类型枚举
typedef enum VENC_CODEC_TYPE {
VENC_CODEC_H264, // H.264编码器
VENC_CODEC_JPEG, // JPEG编码器
VENC_CODEC_H264_VER2, // H.264版本2编码器
VENC_CODEC_H265, // H.265编码器
VENC_CODEC_VP8, // VP8编码器
VENC_CODEC_CNT, // 编码器数量计数
} VENC_CODEC_TYPE;

// 设备结构体
typedef struct VENC_DEVICE
{
const char *codecType; // 编码器类型描述

// 设备操作函数指针
void* (*open)(VencBaseConfig* pBaseConfig, unsigned int nIcVersion);
int (*init)(void *handle, VencBaseConfig* pBaseConfig);
int (*uninit)(void *handle);
void (*close)(void *handle);
int (*encode)(void *handle, VencInputBuffer* pInBuffer);
int (*GetParameter)(void *handle, int indexType, void* param);
int (*SetParameter)(void *handle, int indexType, void* param);
int (*ValidBitStreamFrameNum)(void *handle);
int (*GetOneBitStreamFrame)(void *handle, VencOutputBuffer *pOutBuffer);
int (*FreeOneBitStreamFrame)(void *handle, VencOutputBuffer *pOutBuffer);
int (*ResetBitStreamFrame)(void *handle);
int (*GetBitStreamUnReturnNum)(void *handle);
int (*GetBitStreamUnReadNum)(void *handle);
int (*SetCallback)(void *handle, VencDeviceCbType* pCallbacks, void* pPrivateData);
void* (*GetVcs)(void *handle);
int (*SetFbm)(void *handle, FrameBufferManager *pFbm);
int (*RequestHwStaticBuf)(void *handle);
int (*ReturnHwStaticBuf)(void *handle);
} VENC_DEVICE;

【使用示例】


// 创建H.264编码器设备
VENC_DEVICE* pDevice = vencoderDeviceCreate(VENC_CODEC_H264);
if (pDevice == NULL) {
printf("创建编码器设备失败\n");
return -1;
}

【注意事项】

type参数必须为有效的VENC_CODEC_TYPE枚举值,需要足够的系统内存来创建设备对象,设备创建成功后必须调用vencoderDeviceDestroy释放资源,该函数为内部函数通常通过高级接口VencCreate间接调用

enableCheckOnlineStatus

【目的】

启用或禁用编码器的在线检查状态功能。

【语法】

static void enableCheckOnlineStatus(void);

【参数】

【返回值】

【使用示例】

unsigned int bEnableCheckOnlineStatus = 1;  // 1-启用,0-禁用
VencSetParameter(pEncoder, VENC_IndexParamEnableCheckOnlineStatus, &bEnableCheckOnlineStatus);

【注意事项】

参数 bEnableCheckOnlineStatus 为 unsigned int 类型,取值范围:1(启用在线检查)、0(禁用在线检查)。仅在在线模式下有效。该函数为内部静态函数,通常通过VencSetParameter间接调用。

flushInputBuffer

【目的】

刷新编码器的输入缓冲区,清空所有未处理的输入帧数据。

【语法】

static int flushInputBuffer(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针(VideoEncoder*类型)

【返回值】

  • 成功返回0
  • 失败返回负值错误码

【使用示例】

int ret = flushInputBuffer(pEncoder);
if(ret != 0) {
printf("刷新输入缓冲区失败\n");
}

【注意事项】

pEncoder 必须为有效的编码器指针,编码器需已初始化。调用后会丢弃所有未处理的输入帧,在实时编码场景中需谨慎使用。

VencCreate

【目的】

创建视频编码器实例。

【语法】

VideoEncoder* VencCreate(VENC_CODEC_TYPE eCodecType);

【参数】

  • eCodecType: 编码器类型,指定要创建的编码器种类

【VideoEncoder类型定义】

typedef void VideoEncoder;  // 编码器句柄类型,用于安全访问内部实现

【使用示例】

VideoEncoder* pEncoder = VencCreate(VENC_CODEC_H264);
if(pEncoder == NULL) {
printf("创建编码器失败\n");
return -1;
}

【VencContext结构体关键成员】

typedef struct VencContext {
VENC_CODEC_TYPE codecType; // 编码器类型
int bInit; // 初始化标志
VENC_DEVICE* pVEncDevice; // 编码设备指针
void* pEncoderHandle; // 编码器句柄
VencBaseConfig baseConfig; // 基础配置
// ... 其他成员 ...
} VencContext;

【注意事项】

参数 eCodecTypeVENC_CODEC_TYPE 类型,可选值包括 VENC_CODEC_H264VENC_CODEC_JPEGVENC_CODEC_H265 等。需要足够的系统内存和硬件资源。使用完毕后必须调用 VencDestroy 释放资源。

VencDestroy

【目的】

销毁视频编码器实例并释放所有相关资源。

【语法】

void VencDestroy(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向要销毁的视频编码器实例的指针

【返回值】

【资源清理流程】

  1. 检查编码器状态,如果是运行状态则停止编码线程
  2. 如果是在线模式,清理在线通道资源
  3. 销毁消息队列和信号量
  4. 释放VencContext结构体内存
  5. 清理视频引擎(VE)资源

【使用示例】

VencDestroy(pEncoder);
pEncoder = NULL; // 避免悬空指针

【注意事项】

参数 pEncoder 必须为有效的编码器指针。建议在非运行状态下调用,避免并发访问。销毁后编码器句柄变为无效,应将指针设为NULL避免误用。

VencInit

【目的】

初始化视频编码器,使用指定配置参数完成硬件配置、缓冲区管理、回调设置等初始化工作。

【语法】

int VencInit(VideoEncoder* pEncoder, VencBaseConfig* pConfig);

【参数】

  • pEncoder: 指向视频编码器实例的指针
  • pConfig: 指向基础配置结构体的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码(如VENC_RESULT_NULL_PTR、VENC_RESULT_NO_MEMORY等)

【VencBaseConfig结构体详解】 基础配置结构体定义:

typedef struct VencBaseConfig {
unsigned char bEncH264Nalu; // H264 NALU输出标志
unsigned int nInputWidth; // 输入图像宽度
unsigned int nInputHeight; // 输入图像高度
unsigned int nDstWidth; // 输出图像宽度
unsigned int nDstHeight; // 输出图像高度
unsigned int nStride; // 图像步长
VENC_PIXEL_FMT eInputFormat; // 输入像素格式
VENC_OUTPUT_FMT eOutputFormat; // 输出格式
struct ScMemOpsS *memops; // 内存操作集
VeOpsS *veOpsS; // VE操作集
void *pVeOpsSelf; // VE操作集自指针

unsigned char bOnlyWbFlag; // 仅写回标志

//* LBC压缩配置(适用于特定硬件平台)
unsigned char bLbcLossyComEnFlag1_5x; // 1.5x LBC压缩
unsigned char bLbcLossyComEnFlag2x; // 2.0x LBC压缩
unsigned char bLbcLossyComEnFlag2_5x; // 2.5x LBC压缩
unsigned char bIsVbvNoCache; // VBV无缓存标志

unsigned int extend_flag; // 扩展标志
unsigned int nChannel; // 通道号
unsigned int bVcuOn; // VCU开关
unsigned int bVcuAutoMode; // VCU自动模式
unsigned int bOnlineMode; // 在线模式标志
unsigned int bOnlineChannel; // 在线通道标志
unsigned int nOnlineShareBufNum; // 在线共享缓冲区数量
unsigned int nOnlineShareBufBk; // 在线共享缓冲区备份
unsigned int sensor_id; // 传感器ID
unsigned int bk_id; // 备份ID
eVeLbcMode rec_lbc_mode; // LBC模式

int channel_id; // 通道ID
unsigned int bEnableMultiOnlineSensor; // 多在线传感器
unsigned int bEnableImageStitching; // 图像拼接
unsigned int bEnableRxInputBufmultiplex; // 输入缓冲区复用
unsigned int bEnableInsertPicture; // 插入图像
} VencBaseConfig;

【VENC_PIXEL_FMT枚举】 输入像素格式定义:

typedef enum VENC_PIXEL_FMT {
VENC_PIXEL_FMT_YUV420SP = 0, // YUV420SemiPlanar
VENC_PIXEL_FMT_YUV420P, // YUV420Planar
VENC_PIXEL_FMT_RGB565, // RGB565格式
VENC_PIXEL_FMT_BGR565, // BGR565格式
VENC_PIXEL_FMT_RGB888, // RGB888格式
VENC_PIXEL_FMT_BGR888, // BGR888格式
VENC_PIXEL_FMT_ARGB8888, // ARGB8888格式
VENC_PIXEL_FMT_ABGR8888, // ABGR8888格式
VENC_PIXEL_FMT_RGBA8888, // RGBA8888格式
VENC_PIXEL_FMT_BGRA8888, // BGRA8888格式
} VENC_PIXEL_FMT;

【使用示例】

int ret = VencInit(pEncoder, &baseConfig);
if(ret != VENC_RESULT_OK) {
printf("初始化编码器失败\n");
return -1;
}

【注意事项】

参数 pEncoder 必须为有效指针,pConfig 必须为完整的配置结构体指针。编码器需已创建且配置参数需在硬件支持范围内。

VencStart

【目的】

启动视频编码过程,将编码器状态从INITED或PAUSE状态转换为EXECUTING状态,开始处理输入帧数据并生成编码输出。

【语法】

int VencStart(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【编码器状态管理】 编码器状态枚举定义:

typedef enum VENCODER_STATE {
VENCODER_STATE_IDLE = 0, // 空闲状态
VENCODER_STATE_INITED, // 已初始化状态
VENCODER_STATE_EXCUTING, // 执行中状态
VENCODER_STATE_PAUSE, // 暂停状态
} VENCODER_STATE;

【使用示例】

int ret = VencStart(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("启动编码器失败\n");
return -1;
}

【注意事项】

参数 pEncoder 必须为有效指针。编码器需已成功初始化且状态为INITED或PAUSE。在线模式需确保通道状态正常。

VencPause

【目的】

暂停视频编码过程,将编码器状态从EXECUTING状态转换为PAUSE状态,停止处理新的输入帧,但保持内部状态和缓冲区数据。

【语法】

int VencPause(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

int ret = VencPause(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("暂停编码器失败\n");
return -1;
}

【注意事项】

参数 pEncoder 必须为有效指针。编码器需处于EXECUTING状态。暂停期间应避免调用需要编码器运行的方法。

VencReset

【目的】

重置视频编码器状态和内部缓冲区,清除所有缓冲数据,释放部分资源,保留编码器实例但不释放。

【语法】

int VencReset(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

int ret = VencReset(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("重置编码器失败\n");
return -1;
}

【注意事项】

参数 pEncoder 必须为有效指针。编码器需处于PAUSE或STOPPED状态。重置后需重新调用VencInit初始化。

VencFlush

【目的】

刷新视频编码器的输入和输出缓冲区,强制处理完所有等待编码的输入帧,刷新剩余编码数据。

【语法】

int VencFlush(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

int ret = VencFlush(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("刷新编码器失败\n");
return -1;
}

【注意事项】

参数 pEncoder 必须为有效指针。编码器需已创建并初始化,状态为EXECUTING或PAUSE。刷新过程可能引入延迟。

SetVeSuspend

【目的】

设置视频编码器进入挂起状态,使VE硬件进入低功耗状态,释放硬件资源占用降低能耗。

【语法】

int SetVeSuspend(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

int ret = SetVeSuspend(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("挂起编码器失败\n");
return -1;
}

【注意事项】

pEncoder为指向视频编码器实例的指针,用于挂起编码器进入低功耗状态,编码器必须处于EXECUTING或PAUSE状态。

SetVeResume

【目的】

恢复视频编码器从挂起状态,重新激活编码器恢复VE硬件占用,使编码器恢复到挂起前的工作状态。

【语法】

int SetVeResume(VideoEncoder* pEncoder);

【参数】

  • pEncoder: 指向视频编码器实例的指针

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

int ret = SetVeResume(pEncoder);
if(ret != VENC_RESULT_OK) {
printf("恢复编码器失败\n");
return -1;
}

【注意事项】

pEncoder为指向视频编码器实例的指针,用于恢复挂起状态的编码器,编码器必须处于SUSPENDED状态。

updateOverlayParam

【目的】

更新视频编码器中的覆盖层参数,用于动态更新叠加到视频帧上的图像或文本内容,实现水印、字幕、logo等实时叠加效果。

【语法】

int updateOverlayParam(VideoEncoder* pEncoder, OverlayParam* pParam);

【参数】

  • pEncoder: 指向视频编码器实例的指针
  • pParam: 指向OverlayParam结构体的指针,包含要更新的叠加层参数

【返回值】

  • 成功返回VENC_RESULT_OK (0)
  • 失败返回负值错误码

【使用示例】

OverlayParam overlayParam;
memset(&overlayParam, 0, sizeof(OverlayParam));
overlayParam.enable = 1;
overlayParam.x = 50;
overlayParam.y = 50;
overlayParam.width = 100;
overlayParam.height = 50;
overlayParam.alpha = 128;

int ret = updateOverlayParam(pEncoder, &overlayParam);
if(ret != VENC_RESULT_OK) {
printf("更新overlay参数失败\n");
return -1;
}

【注意事项】

pEncoder为指向视频编码器实例的指针,pParam为指向OverlayParam结构体的指针,用于动态更新叠加到视频帧上的水印、字幕等内容,参数更新将在下一个编码帧中生效。

VencGetParameter

【目的】 获取视频编码器的各种运行时参数,查询编码器当前配置状态、性能指标和运行时信息。

【语法】

int VencGetParameter(VideoEncoder* pEncoder, int nIndex, void* pParam);

【参数】

  • pEncoder: 指向视频编码器实例的指针

  • nIndex: 参数索引,决定了要获取的具体参数类型

  • pParam: 指向存储参数值的缓冲区指针,内存由调用方分配

【返回值】 成功返回VENC_RESULT_OK (0),失败返回负值错误码

【使用示例】

VencGetParameter(pEncoder, VENC_IndexParamBitrate, &bitrate);

【注意事项】 pEncoder为指向视频编码器实例指针,nIndex为参数索引指定获取的参数类型,pParam为存储参数的缓冲区指针,缓冲区大小需与参数类型匹配,成功返回VENC_RESULT_OK。

VencSetParameter

【目的】 设置编码器的各种运行时参数。

【语法】

int VencSetParameter(VideoEncoder* pEncoder, int indexType, void* paramData);

【参数】

  • pEncoder: 指向编码器实例的指针

  • indexType: 参数类型标识符,决定了要设置的具体参数类别

  • paramData: 指向具体参数数据的指针,其类型取决于indexType

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

VencSetParameter(pEncoder, VENC_IndexParamBitrate, &bitrate);

【常用参数类型示例】

以下是常用VENC_INDEXTYPE参数的使用示例和说明:

1. 码率控制参数

Ⅰ. VENC_IndexParamBitrate

功能说明:设置编码目标码率,单位bps

取值范围:根据编码器支持能力,通常为1000~50000000

用法示例:

// 设置编码器码率为2Mbps
int bitrate = 2000000;
VencSetParameter(pEncoder, VENC_IndexParamBitrate, &bitrate);

Ⅱ. VENC_IndexParamFramerate

功能说明:设置输入视频帧率,单位fps

取值范围:1~60,常用值为25/30

用法示例:

// 设置帧率为30fps
int framerate = 30;
VencSetParameter(pEncoder, VENC_IndexParamFramerate, &framerate);

Ⅲ. VENC_IndexParamMaxKeyInterval

功能说明:设置最大关键帧间隔,单位帧数

取值范围:1~255,0表示仅第一帧为关键帧

用法示例:

// 设置关键帧间隔为2秒
int keyInterval = 60; // 30fps * 2s = 60帧
VencSetParameter(pEncoder, VENC_IndexParamMaxKeyInterval, &keyInterval);

2. 视频编码参数

Ⅰ. VENC_IndexParamH264Param

功能说明:设置H.264编码基本参数,包括profile、level、量化参数和熵编码模式

取值范围:

  • nProfile:66(baseline), 77(main), 100(high)

  • nLevel:10~51,表示H.264 level

  • nQP:0~51,值越小质量越高码率越大

  • bEntropyCABAC:0(CAVLC), 1(CABAC)

用法示例:

// 设置H.264编码参数
VencH264Param h264Param = {0};
h264Param.sProfileLevel.nProfile = 66; // 66: baseline, 77: main, 100: high
h264Param.sProfileLevel.nLevel = 31; // H.264 level 3.1
h264Param.sQPRange.nMaxqp = 28; // 量化参数
h264Param.bEntropyCodingCABAC = 1; // 启用CABAC熵编码
VencSetParameter(pEncoder, VENC_IndexParamH264Param, &h264Param);

Ⅱ. VENC_IndexParamColorFormat

功能说明:设置输入图像颜色格式

取值范围:VENC_PIXEL_YUV420SP, VENC_PIXEL_YUV420P, VENC_PIXEL_YVU420SP等

用法示例:

// 设置颜色格式
VENC_PIXEL_FMT colorFormat = VENC_PIXEL_YUV420SP;
VencSetParameter(pEncoder, VENC_IndexParamColorFormat, &colorFormat);

3. 图像处理参数

I. 图像旋转 (VENC_IndexParamRotation)

功能说明:设置图像旋转角度,支持四种旋转方向

取值范围:

  • 0:不旋转

  • 1:顺时针旋转90度

  • 2:旋转180度

  • 3:顺时针旋转270度

用法示例:

int rotation = 1;  // 顺时针旋转90度
VencSetParameter(pEncoder, VENC_IndexParamRotation, &rotation);

II. 水平翻转 (VENC_IndexParamHorizonFlip)

功能说明:设置图像水平翻转,将图像沿垂直轴镜像

取值范围:

  • 0:不翻转

  • 1:水平翻转

用法示例:

unsigned int horizonFlip = 1;  // 启用水平翻转
VencSetParameter(pEncoder, VENC_IndexParamHorizonFlip, &horizonFlip);

4. ROI区域配置

I. ROI配置 (VENC_IndexParamROIConfig)

功能说明:设置感兴趣区域,ROI区域将获得更高质量,可用于重点区域增强

参数说明:

bEnable:启用/禁用ROI功能

  • 取值范围:

    • 0:禁用

    • 1:启用

nRectNum:ROI矩形数量

  • 取值范围:1~8

sRect:ROI矩形区域数组

  • nLeft/nTop:矩形左上角坐标

  • nWidth/nHeight:矩形宽度和高度

  • nQPDelta:ROI区域QP偏移值

    • 取值范围:-51~51

    • 负值:提高ROI区域质量

    • 正值:降低ROI区域质量

用法示例:

VencROIConfig roiConfig = {0};
roiConfig.bEnable = 1; // 启用ROI功能
roiConfig.nRectNum = 1; // 设置1个ROI区域
roiConfig.sRect[0].nLeft = 100; // ROI区域左上角X坐标
roiConfig.sRect[0].nTop = 100; // ROI区域左上角Y坐标
roiConfig.sRect[0].nWidth = 200; // ROI区域宽度
roiConfig.sRect[0].nHeight = 150; // ROI区域高度
roiConfig.sRect[0].nQPDelta = -2; // ROI区域质量提升
VencSetParameter(pEncoder, VENC_IndexParamROIConfig, &roiConfig);

5. 包围盒功能

I. 包围盒配置 (VENC_IndexParamBoundingBox)

功能说明:在视频输出中绘制对象边界框,用于目标检测和跟踪可视化

结构体定义:

VencBoundingBoxCfg:包围盒配置结构体

  • bEnable:启用标志

    • 0:禁用包围盒功能
    • 1:启用包围盒功能
  • num:包围盒数量 取值范围:0~32

  • box_info:包围盒信息数组

  • color_info:颜色配置数组

VencBBoxInfo:单个包围盒信息结构体

  • box_line_width:包围盒边框线宽

    • 取值范围:2~8,必须为2的倍数
  • box_color_id:边框颜色ID

    • 取值范围:1~15,对应不同预设颜色
  • box_base_coor_x/y:包围盒左上角坐标

    • 取值范围:0~8192,必须为2的倍数
  • box_width/heigh:包围盒宽高

    • 取值范围:6~4096,必须为2的倍数

用法示例:

VencBoundingBoxCfg bbox_cfg = {0};
bbox_cfg.bEnable = 1; // 启用包围盒功能
bbox_cfg.num = 1; // 设置1个包围盒

// 配置第一个包围盒
bbox_cfg.box_info[0].box_line_width = 2; // 2像素线宽
bbox_cfg.box_info[0].box_color_id = 1; // 红色边框
bbox_cfg.box_info[0].box_base_coor_x = 100; // X坐标起点
bbox_cfg.box_info[0].box_base_coor_y = 50; // Y坐标起点
bbox_cfg.box_info[0].box_width = 200; // 宽度200像素
bbox_cfg.box_info[0].box_heigh = 150; // 高度150像素

// 设置包围盒参数
VencSetParameter(pEncoder, VENC_IndexParamBoundingBox, &bbox_cfg);

6. 量化参数设置

I. 固定QP值 (VENC_IndexParamH264FixQP)

功能说明:设置固定量化参数,不使用码率控制,适用于需要恒定质量的场景

参数说明:

bEnable:固定QP开关

  • 0:禁用固定QP,使用码率控制

  • 1:启用固定QP,不使用码率控制

nIQp:I帧QP值

取值范围:0~51

  • 值越小,I帧质量越高,码率越大

nPQp:P帧QP值

取值范围:0~51

  • 值越小,P帧质量越高,码率越大

用法示例:

VencFixQP fixQP = {0};
fixQP.bEnable = 1; // 启用固定QP
fixQP.nIQp = 25; // I帧QP值
fixQP.nPQp = 28; // P帧QP值
VencSetParameter(pEncoder, VENC_IndexParamH264FixQP, &fixQP);

II. QP范围设置 (VENC_IndexParamH264QPRange)

功能说明:设置量化参数波动范围,控制码率和质量波动,适用于码率控制模式

参数说明:

nMaxQp:最大QP值

取值范围:0~51

  • 值越大,最低质量越低

nMinQp:最小QP值

取值范围:0~51

  • 值越小,最高质量越高

nMaxPqp:最大P帧QP值

取值范围:0~51

  • 控制预测帧的最大量化参数

nMinPqp:最小P帧QP值

取值范围:0~51

  • 控制预测帧的最小量化参数

用法示例:

VencQPRange qpRange = {0};
qpRange.nMaxQp = 40; // 最大QP值
qpRange.nMinQp = 20; // 最小QP值
qpRange.nMaxPqp = 35; // 最大P帧QP
qpRange.nMinPqp = 25; // 最小P帧QP
VencSetParameter(pEncoder, VENC_IndexParamH264QPRange, &qpRange);

III. 色度QP偏移 (VENC_IndexParamChromaQPOffset)

功能说明:设置色度分量相对于亮度分量的QP偏移,调整色彩质量

取值范围:-12~12

  • 负值:提高色度质量,增加色度码率

  • 正值:降低色度质量,减少色度码率

  • 0:色度与亮度使用相同QP

用法示例:

int chromaQPOffset = -2;  // 提高色度质量
VencSetParameter(pEncoder, VENC_IndexParamChromaQPOffset, &chromaQPOffset);

7. 码率控制增强

I. 码率范围设置 (VENC_IndexParamSetBitRateRange)

功能说明:设置编码码率的波动范围,用于VBR码率控制,优化码率分配

参数说明: nMaxBitRate:最大码率

  • 取值范围:1000~50000000bps

  • 控制码率波动的上限

nMinBitRate:最小码率

  • 取值范围:1000~50000000bps

  • 控制码率波动的下限

用法示例:

VencBitRateRange bitRateRange = {0};
bitRateRange.nMaxBitRate = 3000000; // 最大码率:3Mbps
bitRateRange.nMinBitRate = 1000000; // 最小码率:1Mbps
VencSetParameter(pEncoder, VENC_IndexParamSetBitRateRange, &bitRateRange);

II. VBR优化启用 (VENC_IndexParamVbrOptEnable)

功能说明:启用VBR优化算法,提高变码率编码质量,优化码率分配

取值范围:

  • 0:禁用VBR优化

  • 1:启用VBR优化

用法示例:

unsigned int vbrOptEnable = 1;  // 启用VBR优化
VencSetParameter(pEncoder, VENC_IndexParamVbrOptEnable, &vbrOptEnable);

8. 特殊功能配置

I. 强制I帧 (VENC_IndexParamForceKeyFrame)

功能说明:强制下一帧编码为I帧,用于场景切换或关键点标记

用法示例:

VencSetParameter(pEncoder, VENC_IndexParamForceKeyFrame, NULL);

II. 虚拟I帧 (VENC_IndexParamVirtualIFrame)

功能说明:启用虚拟I帧技术,提高随机访问性能,减少I帧数量

用法示例:

unsigned int virtualIFrame = 600;  // 600个虚拟I帧
VencSetParameter(pEncoder, VENC_IndexParamVirtualIFrame, &virtualIFrame);

III. 填充CBR (VENC_IndexParamFillingCbr)

功能说明:启用CBR填充,确保恒定码率输出,适用于需要稳定码率的场景

取值范围:

  • 0:禁用CBR填充

  • 1:启用CBR填充

用法示例:

unsigned char fillingCbr = 1;  // 启用CBR填充
VencSetParameter(pEncoder, VENC_IndexParamFillingCbr, &fillingCbr);

9. 文件描述符

I. VBV共享文件描述符 (VENC_IndexParamGetVbvShareFd)

功能说明:获取VBV缓冲区的共享文件描述符,用于跨进程数据共享

用法示例:

int vbvShareFd = -1;
VencGetParameter(pEncoder, VENC_IndexParamGetVbvShareFd, &vbvShareFd);
if (vbvShareFd != -1) {
printf("VBV共享文件描述符: %d\n", vbvShareFd);
// 使用共享文件描述符进行跨进程数据共享
} else {
printf("获取VBV共享文件描述符失败\n");
}

【注意事项】 pEncoder为指向编码器实例指针,indexType为参数类型标识符指定要设置的参数类别,paramData为参数数据指针需与indexType匹配,设置后立即生效影响后续编码操作。

VencFbmCreate

【目的】

创建帧缓冲管理器实例,用于管理编码器的输入缓冲区。

【语法】

FrameBufferManager* VencFbmCreate(int num, struct ScMemOpsS *memops, void *veOps, void *pVeOpsSelf);

【参数】

  • num: 缓冲区数量
  • memops: 内存操作接口指针
  • veOps: VE操作接口指针
  • pVeOpsSelf: VE操作上下文指针

【返回值】

成功返回指向新创建帧缓冲管理器的指针,失败返回NULL。

【使用示例】

FrameBufferManager* pFbm = VencFbmCreate(8, memops, veOps, pVeOpsSelf);
if (pFbm == NULL) {
printf("创建帧缓冲管理器失败\n");
return -1;
}

【注意事项】

num为缓冲区数量(建议4-16),memops为内存操作接口指针,用于创建帧缓冲管理器实例,必须确保内存操作接口有效。

VencFbmDestroy

【目的】

销毁帧缓冲管理器实例并释放所有相关资源。

【语法】

void VencFbmDestroy(FrameBufferManager* fbm);

【参数】

  • fbm: 指向要销毁的帧缓冲管理器的指针

【返回值】

【使用示例】

VencFbmDestroy(pFbm);
pFbm = NULL;

【注意事项】

fbm为指向要销毁的帧缓冲管理器指针,用于销毁帧缓冲管理器并释放所有相关资源,销毁后不应再使用该管理器。

VencFbmAllocateBuffer

【目的】

分配帧缓冲区,为编码器提供输入缓冲区。

【语法】

int VencFbmAllocateBuffer(FrameBufferManager* fbm, VencAllocateBufferParam *buffer_param, VencInputBuffer* dst_inputBuf);

【参数】

  • fbm: 指向帧缓冲管理器的指针
  • buffer_param: 指向缓冲区参数的指针
  • dst_inputBuf: 指向目标输入缓冲区的指针

【返回值】

成功返回0,失败返回负值错误码。

【使用示例】

VencAllocateBufferParam bufferParam = {0};
bufferParam.nSize = 1920 * 1080 * 3/2;
bufferParam.nAlign = 32;

VencInputBuffer inputBuffer;
int ret = VencFbmAllocateBuffer(pFbm, &bufferParam, &inputBuffer);
if (ret != 0) {
printf("分配缓冲区失败\n");
return -1;
}

【注意事项】

fbm为帧缓冲管理器指针,buffer_param为缓冲区参数指针,用于分配帧缓冲区为编码器提供输入缓冲区,必须确保缓冲区参数有效。

BitstreamManager 函数文档

BitStreamManager 结构体

【目的】

BitStreamManager 结构体是编码器中用于管理输出比特流数据的核心数据结构,提供了缓冲区管理、数据同步和多帧处理功能。

【结构体定义】

typedef struct BitStreamManager
{
unsigned char bEncH264Nalu;
MUTEX_STRUCT mutex;
char* pStreamBuffer;
char* pStreamBufferPhyAddrEnd;
char* pStreamBufferPhyAddr;
int nStreamBufferSize;
int nWriteOffset;
int nValidDataSize;
BSListQ nBSListQ;
struct ScMemOpsS *memops;
void *veOps;
void *pVeopsSelf;
int bSetVbvBufEnable;
int buf_share_fd;
}BitStreamManager;

【字段说明】

  • bEncH264Nalu: 标识是否为H.264 NALU格式编码,用于控制输出数据格式
  • mutex: 互斥锁,用于多线程环境下的数据同步保护
  • pStreamBuffer: 指向比特流缓冲区的虚拟地址指针
  • pStreamBufferPhyAddrEnd: 比特流缓冲区物理地址的结束位置
  • pStreamBufferPhyAddr: 比特流缓冲区的物理地址起始位置
  • nStreamBufferSize: 比特流缓冲区的总大小(字节)
  • nWriteOffset: 当前写入位置在缓冲区中的偏移量
  • nValidDataSize: 缓冲区中有效数据的大小
  • nBSListQ: 比特流队列,用于管理多个帧的比特流信息
  • memops: 内存操作接口指针,提供内存分配、释放等功能
  • veOps: 视频引擎操作接口指针,提供硬件加速功能
  • pVeopsSelf: 视频引擎操作接口的上下文指针
  • bSetVbvBufEnable: 标识是否启用VBV(Video Buffering Verifier)缓冲区
  • buf_share_fd: 缓冲区共享文件描述符,用于进程间共享缓冲区

【注意事项】

  1. 比特流管理器是编码器输出数据管理的核心组件,负责维护编码后的数据缓冲区
  2. 多线程环境下访问结构体时,应通过互斥锁mutex进行同步保护
  3. 物理地址字段主要用于硬件加速编码器直接访问内存
  4. VBV缓冲区启用与否会影响编码器的码率控制行为
  5. 缓冲区共享文件描述符用于多进程间的数据共享,提高系统效率

BitStreamCreate

【目的】

创建比特流管理器实例,用于管理编码器的输出比特流数据。

【语法】

BitStreamManager *BitStreamCreate(unsigned char bIsVbvNoCache, int nSetBufferEnable, int nBufferSize, struct ScMemOpsS *memops, void *veOps, void *pVeOpsSelf);

【参数】

  • bIsVbvNoCache: 是否为非缓存VBV
  • nSetBufferEnable: 是否启用设置缓冲区
  • nBufferSize: 缓冲区大小
  • memops: 内存操作接口指针
  • veOps: VE操作接口指针
  • pVeOpsSelf: VE操作上下文指针

【返回值】

成功返回指向新创建比特流管理器的指针,失败返回NULL。

【使用示例】

BitStreamManager* pBsMgr = BitStreamCreate(0, 1, 1024*1024, memops, veOps, pVeOpsSelf);
if (pBsMgr == NULL) {
printf("创建比特流管理器失败\n");
return -1;
}

【注意事项】

bIsVbvNoCache用于控制VBV缓存模式,nBufferSize为缓冲区大小,用于创建比特流管理器实例,必须确保内存操作接口有效。

BitStreamDestroy

【目的】

销毁比特流管理器实例并释放所有相关资源。

【语法】

void BitStreamDestroy(BitStreamManager* handle);

【参数】

  • handle: 指向要销毁的比特流管理器的指针

【返回值】

【使用示例】

BitStreamDestroy(pBsMgr);
pBsMgr = NULL;

【注意事项】

handle为指向要销毁的比特流管理器指针,用于销毁比特流管理器并释放所有相关资源,销毁后不应再使用该管理器。

BitStreamAddOneBitstream

【目的】

添加一个比特流到管理器中。

【语法】

int BitStreamAddOneBitstream(BitStreamManager* pBsMgr, BitStreamInfo* pInfo);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • pInfo: 指向比特流信息的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamAddOneBitstream(pBsMgr, &bsInfo1);

【注意事项】

pBsMgr为指向比特流管理器指针,pInfo为指向比特流信息的指针,包含数据、长度、时间戳等信息,用于添加比特流段到管理器中。

BitStreamGetOneBitstream

【目的】

从管理器中获取一个比特流。

【语法】

int BitStreamGetOneBitstream(BitStreamManager* pBsMgr, BitStreamInfo* pInfo);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • pInfo: 指向存储比特流信息的结构指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamGetOneBitstream(pBsMgr, &outputBsInfo);

【注意事项】

pBsMgr为指向比特流管理器指针,pInfo为指向存储比特流信息的结构指针,用于从管理器中获取一个比特流数据。

BitStreamGetOneBitstreamInfo

【目的】

获取特定比特流的信息。

【语法】

int BitStreamGetOneBitstreamInfo(BitStreamManager* pBsMgr, int nIndex, BitStreamInfo* pInfo);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • nIndex: 比特流索引
  • pInfo: 指向存储比特流信息的结构指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamGetOneBitstreamInfo(pBsMgr, 0, &firstBsInfo);

【注意事项】

pBsMgr为指向比特流管理器指针,nIndex为比特流索引从0开始,pInfo为指向存储比特流信息的结构指针,用于获取特定比特流的信息。

BitStreamGetUnReturnNum

【目的】

获取未归还的比特流数量。

【语法】

int BitStreamGetUnReturnNum(BitStreamManager* pBsMgr);

【参数】

  • pBsMgr: 指向比特流管理器的指针

【返回值】

返回未归还的比特流数量

【注意事项】

pBsMgr为指向比特流管理器指针,用于获取当前未归还的比特流数量,可用于检查缓冲区状态。

BitStreamGetUnReadNum

【目的】 获取未读取的比特流数量。

【语法】

int BitStreamGetUnReadNum(BitStreamManager* pBsMgr);

【参数】

  • pBsMgr: 指向比特流管理器的指针

【返回值】 返回未读取的比特流数量

【使用示例】

BitStreamGetUnReadNum(pBsMgr);

【注意事项】 pBsMgr为指向比特流管理器指针,返回值表示等待读取的比特流块数量,与BitStreamAddOneBitstream和BitStreamGetOneBitstream操作同步,0表示无未读取数据。

BitStreamReturnOneBitstream

【目的】

归还一个比特流。

【语法】

int BitStreamReturnOneBitstream(BitStreamManager* pBsMgr, int nIndex);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • nIndex: 比特流索引

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamReturnOneBitstream(pBsMgr, 0);

【注意事项】

pBsMgr为指向比特流管理器指针,nIndex为比特流索引用于指定归还的数据块位置,归还操作必须与获取操作成对出现以防止内存泄漏。

BitStreamReset

【目的】

重置比特流管理器。

【语法】

int BitStreamReset(BitStreamManager* pBsMgr);

【参数】

  • pBsMgr: 指向比特流管理器的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamReset(pBsMgr);

【注意事项】

pBsMgr为指向比特流管理器指针,重置操作会清除所有内部数据,包括已添加、已获取和未归还的数据,管理器恢复到初始状态但对象本身不被销毁。

BitStreamSkipBuf

【目的】

跳过指定数量的比特流缓冲区。

【语法】

int BitStreamSkipBuf(BitStreamManager* pBsMgr, int nSkipNum);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • nSkipNum: 要跳过的缓冲区数量

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitStreamSkipBuf(pBsMgr, 3);

【注意事项】

pBsMgr为指向比特流管理器指针,nSkipNum为要跳过的缓冲区数量,跳过操作会永久性地移除指定数量的最早数据,操作不可逆。

BitstreamUpdatePackInfo

【目的】

更新比特流包信息。

【语法】

int BitstreamUpdatePackInfo(BitStreamManager* pBsMgr, int nIndex, PackInfo* pPackInfo);

【参数】

  • pBsMgr: 指向比特流管理器的指针
  • nIndex: 比特流索引
  • pPackInfo: 指向包信息的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

BitstreamUpdatePackInfo(pBsMgr, 0, &packInfo);

【注意事项】

pBsMgr为指向比特流管理器指针,nIndex为要更新的比特流索引,pPackInfo为指向包信息的指针,更新操作会覆盖之前的包信息,需确保索引有效。

FrameBufferManager 函数文档

FrameBufferManager 结构体

【目的】

FrameBufferManager 结构体是编码器中用于管理输入帧缓冲区的核心数据结构,提供了缓冲区分配、管理和同步功能。

【结构体定义】

typedef struct FrameBufferManager
{
VencInputBuffer selfAllocateBufArry[MAX_SELF_ALLOCATE_FBM_BUF_NUM];
unsigned int selfAllocateBufValidNum;
InputBufferList inputbuffer_list;
unsigned int size_y;
unsigned int size_c;
struct ScMemOpsS *memops;
VeOpsS* veops;
void* pVeOpsSelf;
}FrameBufferManager;

【字段说明】

  • selfAllocateBufArry: 自分配的输入缓冲区数组,最大数量为MAX_SELF_ALLOCATE_FBM_BUF_NUM(8)
  • selfAllocateBufValidNum: 当前有效的自分配缓冲区数量
  • inputbuffer_list: 输入缓冲区链表,管理所有缓冲区的状态
  • size_y: Y分量缓冲区大小
  • size_c: C分量(UV)缓冲区大小
  • memops: 内存操作接口指针,提供内存分配、释放等功能
  • veops: 视频引擎操作接口指针,提供硬件加速功能
  • pVeOpsSelf: 视频引擎操作接口的上下文指针

【注意事项】

  1. 帧缓冲管理器是编码器输入数据管理的核心组件,负责维护编码前的帧数据缓冲区
  2. 自分配缓冲区数组用于内部管理,提高缓冲区分配效率
  3. 输入缓冲区链表维护了所有缓冲区的状态,包括有效队列和空队列
  4. size_y和size_c字段用于表示YUV格式中Y分量和C分量的大小
  5. 多线程环境下访问结构体时,应通过互斥锁进行同步保护

VencFbmCreate

【目的】

创建帧缓冲管理器实例。

【语法】

FrameBufferManager* VencFbmCreate(int num, struct ScMemOpsS *memops, void *veOps, void *pVeOpsSelf);

【参数】

  • num: 缓冲区数量
  • memops: 内存操作接口指针
  • veOps: VE操作接口指针
  • pVeOpsSelf: VE操作上下文指针

【返回值】

成功返回指向新创建帧缓冲管理器的指针,失败返回NULL

【使用示例】

FrameBufferManager* pFbm = VencFbmCreate(4, memops, veOps, pVeOpsSelf);

【注意事项】

num为缓冲区数量,memops为内存操作接口,veOps为视频引擎操作接口,创建后需调用VencFbmDestroy释放资源。

VencFbmDestroy

【目的】

销毁帧缓冲管理器实例并释放所有相关资源。

【语法】

void VencFbmDestroy(FrameBufferManager* fbm);

【参数】

  • fbm: 指向帧缓冲管理器的指针。

【返回值】

【需求】

帧缓冲管理器必须是有效的。

【注意事项】

此函数会释放所有与帧缓冲管理器相关的资源,调用后不应再使用该管理器。

VencFbmAllocateBuffer

【目的】

添加一个有效的帧缓冲区。

【语法】

int VencFbmAddValidBuffer(FrameBufferManager* pFbm, ValidFrameBuffer* pBuffer);

【参数】

  • pFbm: 指向帧缓冲管理器的指针
  • pBuffer: 指向有效帧缓冲区的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

VencFbmAddValidBuffer(pFbm, pBuffer);

【注意事项】

pFbm为指向帧缓冲管理器的指针,pBuffer为指向有效帧缓冲区的指针,缓冲区信息会被复制到内部存储。

VencFbmRequestValidBuffer

【目的】

请求一个有效的帧缓冲区。

【语法】

int VencFbmRequestValidBuffer(FrameBufferManager* pFbm, ValidFrameBuffer* pBuffer);

【参数】

  • pFbm: 指向帧缓冲管理器的指针
  • pBuffer: 指向存储帧缓冲区信息的结构指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

VencFbmRequestValidBuffer(pFbm, pBuffer);

【注意事项】

pFbm为指向帧缓冲管理器的指针,pBuffer为指向存储帧缓冲区信息的结构指针,请求的缓冲区信息是副本。

VencFbmReturnValidBuffer

【目的】

归还一个有效的帧缓冲区。

【语法】

int VencFbmReturnValidBuffer(FrameBufferManager* pFbm, int nIndex);

【参数】

  • pFbm: 指向帧缓冲管理器的指针
  • nIndex: 帧缓冲区索引

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

VencFbmReturnValidBuffer(pFbm, 0);

【注意事项】

pFbm为指向帧缓冲管理器的指针,nIndex为帧缓冲区索引,索引必须在有效范围内。

VencFbmReset

【目的】

重置帧缓冲区管理器。

【语法】

int VencFbmReset(FrameBufferManager* pFbm);

【参数】

  • pFbm: 指向帧缓冲区管理器的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

VencFbmReset(pFbm);

【注意事项】

pFbm为指向帧缓冲区管理器的指针,重置操作会清除所有内部状态,将管理器恢复到初始状态。

VencFbmGetValidBufferNum

【目的】

获取有效帧缓冲区的数量。

【语法】

int VencFbmGetValidBufferNum(FrameBufferManager* pFbm);

【参数】

  • pFbm: 指向帧缓冲区管理器的指针

【返回值】

返回有效帧缓冲区的数量

【使用示例】

int validCount = VencFbmGetValidBufferNum(pFbm);

【注意事项】

pFbm为指向帧缓冲区管理器的指针,返回值表示当前有效的帧缓冲区数量,可能会动态变化。

QueueFrameBuffer

【目的】

将帧缓冲区加入队列。

【语法】

int QueueFrameBuffer(FrameBufferManager* pFbm, FrameBufferNode* pNode);

【参数】

  • pFbm: 指向帧缓冲区管理器的指针
  • pNode: 指向帧缓冲区节点的指针

【返回值】

成功返回0,失败返回负值错误码

【使用示例】

QueueFrameBuffer(pFbm, pNode);

【注意事项】

pFbm为指向帧缓冲区管理器的指针,pNode为指向帧缓冲区节点的指针,节点信息会被复制到内部队列。