5.12. 音视频编解码 - Codec
5.12.1. 模块说明
5.12.1.1. 规格参数
H.265/HEVC 编码器
支持 HEVC Main and Main Still Picture Profile @L5.1 High Tier
最大分辨率为 8192 x 4096
性能为 4k60fps@500MHz
最小分辨率为 256x128
输入图片的宽度或高度必须是 8 的倍数
图像格式: YUV420
支持 I 帧和 P 帧,不支持 B 帧
完全兼容 ISO/IEC 23008-2 高效视频编码主配置标准
H.264/AVC 编码器
支持 Baseline/Constrained Baseline/Main/High Profile @5.2 的编码能力
性能为 4k60fps@500MHz
最大分辨率为 8192 x 4096
最小分辨率为 256x128
输入图片的宽度或高度必须是 8 的倍数
图像格式: YUV420
支持 I 帧和 P 帧,不支持 B 帧
兼容 ITU-T 推荐的 H.264 规范,支持 Baseline、 Constrained Baseline、 Main 和 High 配置中的所有编码工具,除了以下几个例外:
不支持交错编码工具( Interlaced Coding Tools)
不支持 H.264 的 FMO/ASO 工具
H.265/HEVC 解码器
支持 HEVC Main and Main Still Picture Profile @L5.1 High Tier
支持的最大分辨率为 8192 x 4096
性能为 4k60fps@500MHz
支持的最小分辨率为 8x8
图像格式: YUV420
完全兼容 ISO/IEC 23008-2 ISO/IEC 23008-2 high efficiency video coding main/MSP (main still picture)
H.264/AVC 解码器
支持 Baseline/Constrained Baseline/Main/High Profile @5.2 的编码能力
支持的最大分辨率为 8192 x 4096
性能为 4k60fps@500MHz
支持的最小分辨率为 64x64
图像格式: YUV420
完全兼容 ITU-T 推荐的 H.264 规范,支持 Baseline、 Constrained Baseline、 Main 和 High 配置中的所有编码工具,除了以下几个例外:
不支持交错编码工具( Interlaced Coding Tools)
不支持 H.264 的 FMO/ASO 工具
JPEG 与 MJPEG 编/解码器
支持 JPEG baseline/extended sequential and M-JPEG 编解码
最大分辨率为 32768x32768
支持最小编码分辨率: 16x16 pixels
支持 YUV444/YUV422/YUV420/YUV400/YUV440 color format
性能为:同时进行编码和解码时, 4k30fps@500MHz 的性能
对于 4:2:2 色彩格式图像,支持高达 210M 像素 / 秒的编码
对于 4:0:0 色彩格式图像,支持高达 430M 像素 / 秒的编码
符合 ISO/IEC 10918-1 JPEG 标准的 Baseline 和 Extended 顺序配置
音频编解码
X5 芯片不具备音频编解码的硬件加速单元,但其 MediaCodec 接口基于 FFMPEG 软件库,通过软件的方式实现乐多种编解码器,如下 :
无损压缩:
FLAC有损压缩:
G.711 A-law/Mu-law,G.726 ADPCM,ADPCM IMA WAV,AAC 系列:
AAC LC,AAC Main,AAC SSR,AAC LTP,AAC LD,AAC HE,AAC HEv2
注意: AAC 系列编解码器需要 向 AAC 技术的管理组织申请 AAC license 授权
5.12.1.2. 使用说明
输入输出 buffer 管理
MediaCodec 的 buffer 包括输入和输出 buffer 两种,并且输入 buffer 的来源有两种情况:
内部输入 buffer 模式:输入源来自 MediaCodec 内部通过 hbmem 接口 分配
外部输入 buffer 模式:输入源来自其他模块输出的内存,这些内存也必须是通过 hbmem 接口 分配,比如 VSE 模块输出的内存
注意:
输入 buffer 的来源通过结构体 mc_video_codec_enc_params_t 中的
external_frame_buf成员控制输入 buffer 的具体来源可以是任意物理地址连续的内存,比如 hbn 框架输出的内存,具体示例参考 sunrise_camera 的源代码。
内部输入 buffer 模式
用户不需要关心 buffer 的分配,只需要在操作 buffer 前执行 dequeue 操作获取空闲的 buffer,处理完后执行 queue 操作返还该 buffer。 如下图描述 :

外部输入 buffer 模式
外部输入 buffer 模式的功能是为了减少 输入 buffer 的拷贝操作。举例如下:
比如 VSE 的输出 buffer 用来编码时,该 buffer 是由 VSE 内部通过 hbmem 接口 分配,可直接作为 MediaCodec 的输入 buffer。
注意: 即使用户使用外部输入 buffer,在 buffer 操作时,用户仍然需要执行 dequeue 操作获取队列信息,然后对队列中的信息进行赋值(主要是虚拟地址和物理地址),再执行 queue 操作
GOP
H264/H265 编码支持 GOP 结构的设置,用户可从预置的 9 种 GOP 结构中选择( X5 支持 2 种),也可自定义 GOP 结构。
注意:
X5 编码仅支持 I 帧 和 P 帧编码 , 不支持 B 帧和多帧参考 , 故 9 种 GOP 预设值中 , 仅支持 GOP Preset 1 和 GOP Preset 9 (后面会详细描述) 。
结构体 mc_video_codec_enc_params_t 中的成员gop_params.gop_preset_idx只能取值 1 和 9下面表格和描述也仅描述此两种支持的 GOP Preset
GOP 结构表
GOP 结构表可定义一组周期性的 GOP 结构,该 GOP 结构将用于整个编码过程。
单个结构表中的元素如下表所示,其中可以指定该图像的参考帧
如果 IDR 帧后的其他帧指定的参考帧为 IDR 帧前的数据帧,编码器内部会自动处理这种情况使其不参考其他帧,用户无需关心这种情况。
用户在自定义 GOP 结构时需要指明结构表的数量,最多可定义 3 个结构表,结构表的顺序需要按照解码顺序排列。
| Element | Description |
|---|---|
| Type | Slice type( I, P) |
| POC | Display order of the frame within a GOP, ranging from 1 to GOP size |
| QPoffset | A quantization parameter of the picture in the custom GOP |
| NUM_REF_PIC_L0 | Flag to use multi reference picture for P picture It is valid only if PIC_TYPE is P |
| temporal_id | Temporal layer of the frame. A frame cannot predict from a frame with a higher temporal id(0~6). |
| 1st_ref_POC | The POC of the 1st reference picture of L0 |
| 2nd_ref_POC | The POC of 1st reference picture of L1 in case that Type is equal to B |
| The POC of 2nd reference picture of L0 in case that Type is equal to P | |
| Note that reference_L1can have the same POC as reference in B slice. But for | |
| compression efficiency it is recommended that reference_L1 have | |
| a different POCfrom reference_L0 |
GOP 预置结构
| Index | GOP Structure | Low Delay (encoding order and display order are same) |
GOP Sise | Encoding Order | Minimum Source Frame Buffer |
Minimum Decoded Picture Buffer |
Intra Period (I Frame Interval) Requirement |
|---|---|---|---|---|---|---|---|
| 1 | I | Yes | 1 | I0-I1-I2 … | 1 | 1 | - |
| 9 | P | Yes | 1 | P0 | 1 | 2 | - |
GOP Preset 1
只有 I 帧,没有相互参考;
低延时;

GOP Preset 9
只有 I 帧和 P 帧;
P 帧参考 1 个前向参考帧;
低延时;

长期参考帧
用户可指定长期参考帧的模式:
如下图所示:

Intra Refresh
Intra Refresh 模式通过在非 I 帧内部周期性的插入帧内编码的 MB/CTU 来提高容错性。它能够为解码器提供更多的修复点来避免时域错误造成的图像损坏。
用户可以指定 MB/CTU 的连续行数、列数或者步长来强制编码器插入帧内编码单元 , 详细见:mc_video_intra_refresh_params_t
用户还可指定帧内编码单元的大小由编码器内部决定哪一块需要帧内编码。
ROI
ROI 编码的实现和 QPMAP 类似,需要用户按照光栅扫描的方向为每一个块设定 QP 值,如下图:

在 H.264 编码中,每个块的大小为 16x16 像素,而在 H.265 编码中,块大小扩展至 32x32 像素。 在 ROI( Region of Interest)映射表中,每个 QP(量化参数)值占用 1 个字节,取值范围为 0 至 51 。
ROI 编码可以和 CBR 和 AVBR 一起工作,当不使能 CBR 或 AVBR 时,每个块区域的实际 QP 值就为 ROI map 中指定的值,当使能 CBR 或 AVBR 时,则每个块区域的实际值由以下公式得到:
QP(i) = MQP(i)+ RQP(i) - ROIAvgQP
其中 MQP 为 ROI map 中的值, RQP 为编码器内部码率控制得到的值, ROIAvaQP 为 ROI map 中 QP 的平均值。
示例代码请参考:hb_mm_mc_get_longterm_ref_mode
帧 Skip 设置
用户可调用 hb_mm_mc_skip_pic 设置下一次 queue 操作输入的图像的编码模式为 skip 模式,
该模式只对非 I 帧编码有效;
skip 模式下编码器内部会忽略输入帧,利用上一帧的重构帧生成该次输入的的重构帧,输入帧则被编码成 P 帧。
5.12.2. 参考示例
MediaCodec 接口示例代码可以参考 sample_codec 章节
MediaCodec 与 Camera Sencosr 对接的示例代码可以参考 single-pipe-vin-isp-vse-vpu 章节
5.12.3. API 参考
5.12.3.1. MediaCodec API
| API 接口 | 接口功能 |
|---|---|
| hb_mm_mc_get_descriptor | 根据 codec_id 获取 MediaCodec 支持的 codec 信息,信息包括 codec 名字,详细描述, MIME 类型以及 codec 支持的 profile 类型等 |
| hb_mm_mc_get_default_context | 获取指定的 codec 的默认属性 |
| hb_mm_mc_initialize | 初始化编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_INITIALIZED 状态 |
| hb_mm_mc_set_callback | 设置回调函数指针,调用该函数后 MediaCodec 会进入异步工作模式 |
| hb_mm_mc_set_input_buffer_listener | 设置回调函数指针,当应用程序 queue input buffer 后 , 可以带上相应的 user ptr, 在 media_codec_buffer_t |
| hb_mm_mc_configure | 根据输入信息配置编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_CONFIGURED 状态 |
| hb_mm_mc_start | 启动编码 / 解码流程, MediaCodec 将创建编解码实例、设置序列或解析数据流、注册 Framebuffer、编码头信息等,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_STARTED 状态 |
| hb_mm_mc_stop | 停止编码 / 解码流程,退出所有子线程并释放相关资源,调用成功后 MediaCodec 回到 MEDIA_CODEC_STATE_INITIALIZED 状态 |
| hb_mm_mc_pause | 停止编码 / 解码流程,暂停所有子线程,调用成功后 MediaCodec 进入到 MEDIA_CODEC_STATE_PAUSED 状态 |
| hb_mm_mc_flush | 刷新输入输出 buffer 缓冲区,强制编码器 / 解码器刷新未处理的输入输出 buffer,函数调用后 MediaCodec 进入 MEDIA_CODEC_STATE_FLUSHING 状态,操作成功后, MediaCodec 会再次进入 MEDIA_CODEC_STATE_STARTED 状态 |
| hb_mm_mc_release | 释放 MediaCodec 内部所有资源,用户需要在调用该函数前调用 hb_mm_mc_stop 来停止编解码,操作成功后 MediaCodec 进入 MEDIA_CODEC_STATE_UNINITIALIZED 状态 |
| hb_mm_mc_get_state | 获取 MediaCodec 当前的状态 |
| hb_mm_mc_get_status | 获取 MediaCodec 当前内部的状态信息 |
| hb_mm_mc_queue_input_buffer | 填充需要处理的 buffer 到 MediaCodec 中 |
| hb_mm_mc_dequeue_input_buffer | 获取输入的 buffer |
| hb_mm_mc_queue_output_buffer | 返还处理完的 output buffer 到 MediaCodec 中 |
| hb_mm_mc_dequeue_output_buffer | 获取输出的 buffer |
| hb_mm_mc_get_longterm_ref_mode | 获取长期参考帧模式的参数,适用于 H264/H265 |
| hb_mm_mc_set_longterm_ref_mode | 设置长期参考帧模式的参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_intra_refresh_config | 获取帧内刷新参数,适用于 H264/H265 |
| hb_mm_mc_set_intra_refresh_config | 设置帧内刷新模式参数,该参数为静态参数,适用于 H264/H265 |
| hb_mm_mc_get_rate_control_config | 获取码率控制参数,该参数为动态参数,适用于 H264/H265/MJPEG |
| hb_mm_mc_set_rate_control_config | 设置码率控制参数,该参数为动态参数,适用于 H264/H265/MJPEG |
| hb_mm_mc_get_deblk_filter_config | 获取去块滤波参数,适用于 H264/H265 |
| hb_mm_mc_set_deblk_filter_config | 设置去块滤波参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_sao_config | 获取 SAO 参数,适用于 H265 |
| hb_mm_mc_set_sao_config | 设置 SAO 参数,该参数为静态参数,适用于 H265 |
| hb_mm_mc_get_entropy_config | 获取 entropy 参数,适用于 H264 |
| hb_mm_mc_set_entropy_config | 设置 entropy 参数,适用于 H264 |
| hb_mm_mc_get_vui_timing_config | 获取 VUI Timing 参数,适用于 H264/H265 |
| hb_mm_mc_set_vui_timing_config | 设置 VUI Timing 参数,该参数为静态参数,适用于 H264/H265 |
| hb_mm_mc_get_slice_config | 获取 slice 编码参数,适用于 H264/H265 |
| hb_mm_mc_set_slice_config | 设置 slice 编码参数,该参数为动态参数,适用于 H264/H265 。限制每帧 slice 个数小于等于 1500 |
| hb_mm_mc_insert_user_data | 在编码流中插入用户数据,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_request_idr_frame | 请求 IDR 帧,该接口可动态设置,适用于 H264/H265 |
| hb_mm_mc_skip_pic | 使能指定的图像的 skip 模式编码,该接口可动态设置,适用于 H264/H265 |
| hb_mm_mc_get_smart_bg_enc_config | 获取智能背景编码参数,适用于 H264/H265 |
| hb_mm_mc_set_smart_bg_enc_config | 设置智能背景编码参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_pred_unit_config | 获取预测单元参数,适用于 H264/H265 |
| hb_mm_mc_set_pred_unit_config | 设置预测单元参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_transform_config | 获取 Transform 参数,适用于 H264/H265 |
| hb_mm_mc_set_transform_config | 设置 Transform 参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_roi_config | 获取 ROI 编码参数,适用于 H264/H265 |
| hb_mm_mc_set_roi_config | 设置 ROI 编码参数,该参数为动态参数,适用于 H264/H265 |
| hb_mm_mc_get_mode_decision_config | 获取 ROI 编码参数,适用于 H265 |
| hb_mm_mc_set_mode_decision_config | 设置模式决策参数,该参数为动态参数,适用于 H265 |
| hb_mm_mc_get_user_data | 获取解码流中的用户数据,适用于 H264/H265 |
| hb_mm_mc_release_user_data | 释放解码流中的用户数据,适用于 H264/H265 |
| hb_mm_mc_get_mjpeg_config | 获取 MJPEG 编码参数,适用于 MJPEG |
| hb_mm_mc_set_mjpeg_config | 设置 MJPEG 编码参数,该参数为动态参数,适用于 MJPEG |
| hb_mm_mc_get_jpeg_config | 获取 JPEG 编码参数,适用于 JPEG |
| hb_mm_mc_set_jpeg_config | 设置 JPEG 编码参数,该参数为动态参数,适用于 JPEG |
| hb_mm_mc_get_fd | 获取设备节点 fd,可用于 select 操作,监听编解码结果 |
| hb_mm_mc_close_fd | 关闭设备节点 |
| hb_mm_mc_get_vui_config | 获取 VUI 参数 |
| hb_mm_mc_set_vui_config | 设置 VUI 参数,该参数为静态参数 |
| hb_mm_mc_get_3dnr_enc_config | 获取 3DNR 参数,该参数为动态参数,适用于 H265. |
| hb_mm_mc_set_3dnr_enc_config | 设置 3DNR 参数,该参数为动态参数,适用于 H265 |
| hb_mm_mc_request_idr_header | 请求帧头 IDR 帧头信息,适用于 H264/H265 |
| hb_mm_mc_enable_idr_frame | 使能 IDR 帧,适用于 H264/H265 |
| hb_mm_mc_register_audio_encoder | 注册 audio 编码器,适用于 Audio |
| hb_mm_mc_unregister_audio_encoder | 注销 audio 编码器,适用于 Audio |
| hb_mm_mc_register_audio_decoder | 注册 audio 解码器,适用于 Audio |
| hb_mm_mc_unregister_audio_decoder | 注销 audio 解码器,适用于 Audio |
| hb_mm_mc_get_explicit_header_config | 获取头信息和 IDR 帧是否编码成一帧的配置, 0 : IDR 和头信息独立, 1 : IDR 和头信息合成一帧,适用于 H264/H265 |
| hb_mm_mc_set_explicit_header_config | 使能 / 不使能头信息和 I 帧编码成一帧,该参数为静态参数, 0 : IDR 和头信息独立, 1 : IDR 和头信息合成一帧,适用于 H264/H265 |
| hb_mm_mc_get_roi_avg_qp | 获取 ROI 平均 QP 值 , 适用于 H264/H265 |
| hb_mm_mc_set_roi_avg_qp | 设置 ROI 编码平均 QP 值,该参数为动态参数,表示使用设置的 QPMap |
5.12.3.2. MediaMuxer API
| API 接口 | 接口功能 |
|---|---|
| hb_mm_mx_get_default_context | 获得默认的上下文参数值 |
| hb_mm_mx_initialize | 初始化 MediaMuxer 内部状态,调用成功后 MediaMuxer 进入 MEDIA_MUXER_STATE_INITIALIZED 状态 |
| hb_mm_mx_add_stream | 添加音视频轨道 |
| hb_mm_mx_start | 启动 MediaMuxer 内部流程,调用成功后进入 MEDIA_MUXER_STATE_STARTED 状态 |
| hb_mm_mx_stop | 停止 MediaMuxer 内部流程,调用成功后进入 MEDIA_MUXER_STATE_UNINITIALIZED 状态 |
| hb_mm_mx_write_stream | 写入音频或视频数据 |
| hb_mm_mx_get_state | 获取 MediaMuxer 当前的状态 |
| hb_mm_mx_probe_stream | 检查 MP4 文件是否异常 |
| hb_mm_mx_repair_stream | 修复异常 MP4 文件并生成正常 MP4 |
5.12.4. 接口说明
5.12.4.1. hb_mm_mc_get_descriptor
【函数声明】
const media_codec_descriptor_t*hb_mm_mc_get_descriptor(media_codec_id_t
codec_id);
【参数描述】
[IN] media_codec_id_t codec_id:表示 codec 类型
【返回值】
非空: codec 描述信息
NULL:表示查询不到该 codec id 对应的描述符
【功能描述】
根据 codec_id 获取 MediaCodec 支持的 codec 信息,信息包括 codec 名字,详细描述, MIME 类型以及 codec 支持的 profile 类型等。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
int main(int argc, char *argv[])
{
const media_codec_descriptor_t *desc = NULL;
desc = hb_mm_mc_get_descriptor(MEDIA_CODEC_ID_H265);
return 0;
}
5.12.4.2. hb_mm_mc_get_default_context
【函数声明】
hb_s32 hb_mm_mc_get_default_context(media_codec_id_t codec_id, hb_bool
encoder, media_codec_context_t *context)
【参数描述】
[IN] media_codec_id_t codec_id:表示 codec 类型
[IN] hb_bool encoder:指定 codec 是编码器还是解码器
[OUT] media_codec_context_t *context:指定 codec 类型默认的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_INVALID_PARAMS: 参数非法
【功能描述】
获取指定的 codec 的默认属性。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
int main(int argc, char *argv[])
{
int ret = 0;
media_codec_context_t context;
memset(&context, 0x00, sizeof(context));
ret = hb_mm_mc_get_default_context(MEDIA_CODEC_ID_H265, 1, &context);
return 0;
}
5.12.4.3. hb_mm_mc_initialize
【函数声明】
hb_s32 hb_mm_mc_initialize(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_NO_FREE_INSTANCE:没有可用的 instance( Video 最多 32 个, MJPEG/JPEG 最多 64 个, Audio 最多 32 个)
【功能描述】
初始化编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_INITIALIZED 状态。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
static Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
} MediaCodecTestContext;
typedef struct AsyncMediaCtx {
media_codec_context_t *ctx;
FILE *inFile;
FILE *outFile;
int lastStream;
Uint64 startTime;
int32_t duration;
} AsyncMediaCtx;
static void on_encoder_input_buffer_available(hb_ptr userdata,
media_codec_buffer_t *inputBuffer) {
AsyncMediaCtx *asyncCtx = (AsyncMediaCtx *)userdata;
Int noMoreInput = 0;
hb_s32 ret = 0;
Uint64 curTime = 0;
if (!noMoreInput) {
curTime = osal_gettime();
if ((curTime - asyncCtx->startTime)/1000 < (uint32_t)asyncCtx->duration) {
ret = fread(inputBuffer->vframe_buf.vir_ptr[0], 1,
inputBuffer->vframe_buf.size, asyncCtx->inFile);
if (ret <= 0) {
if(fseek(asyncCtx->inFile, 0, SEEK_SET)) {
printf("Failed to rewind input filen");
} else {
ret = fread(inputBuffer->vframe_buf.vir_ptr[0], 1,
inputBuffer->vframe_buf.size, asyncCtx->inFile);
if (ret <= 0) {
printf("Failed to read input filen");
}
}
}
}
if (!ret) {
printf("%s There is no more input data!n", TAG);
inputBuffer->vframe_buf.frame_end = TRUE;
noMoreInput = 1;
} else {
inputBuffer->vframe_buf.frame_end = TRUE;
inputBuffer->vframe_buf.size = 0;
}
}
static void on_encoder_output_buffer_available(hb_ptr userdata,
media_codec_buffer_t *outputBuffer,
media_codec_output_buffer_info_t *extraInfo) {
AsyncMediaCtx *asyncCtx = (AsyncMediaCtx *)userdata;
mc_265_output_stream_info_t info = extraInfo->video_stream_info;
fwrite(outputBuffer->vstream_buf.vir_ptr,
outputBuffer->vstream_buf.size, 1, asyncCtx->outFile);
if (outputBuffer->vstream_buf.stream_end) {
printf("There is no more output data!n");
asyncCtx->lastStream = 1;
}
}
static void on_encoder_media_codec_message(hb_ptr userdata, hb_s32
error) {
AsyncMediaCtx *asyncCtx = (AsyncMediaCtx *)userdata;
if (error) {
asyncCtx->lastStream = 1;
printf("ERROR happened!n");
}
}
static void on_vlc_buffer_message(hb_ptr userdata, hb_s32 * vlc_buf)
{
MediaCodecTestContext *ctx = (MediaCodecTestContext *)userdata;
printf("%s %s VLC Buffer size = %d; Reset to %d.n", TAG,
__FUNCTION__,
*vlc_buf, ctx->vlc_buf_size);
*vlc_buf = ctx->vlc_buf_size;
}
static void do_async_encoding(void *arg) {
hb_s32 ret = 0;
FILE *outFile;
FILE *inFile;
int step = 0;
AsyncMediaCtx asyncCtx;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
memset(&asyncCtx, 0x00, sizeof(AsyncMediaCtx));
asyncCtx.ctx = context;
asyncCtx.inFile = inFile;
asyncCtx.outFile = outFile;
asyncCtx.lastStream = 0;
asyncCtx.duration = 5;
asyncCtx.startTime = osal_gettime();
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
media_codec_callback_t callback;
callback.on_input_buffer_available =
on_encoder_input_buffer_available;
callback.on_output_buffer_available =
on_encoder_output_buffer_available;
callback.on_media_codec_message = on_encoder_media_codec_message;
ret = hb_mm_mc_set_callback(context, &callback, &asyncCtx);
if (ret) {
goto ERR;
}
media_codec_callback_t callback2;
callback2.on_vlc_buffer_message = on_vlc_buffer_message;
if (ctx->vlc_buf_size > 0) {
ret = hb_mm_mc_set_vlc_buffer_listener(context, &callback2, ctx);
if (ret) {
goto ERR;
}
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
while(!asyncCtx.lastStream) {
sleep(1);
}
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state !=
MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
if (outFile)
fclose(outFile);
}
int main(int argc, char *argv[])
{
int ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.h265";
mc_video_codec_enc_params_t *params = NULL;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = 1;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = 0;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
do_async_encoding(&ctx);
return 0;
}
5.12.4.4. hb_mm_mc_set_callback
【函数声明】
hb_s32 hb_mm_mc_set_callback(media_codec_context_t *context, const
media_codec_callback_t *callback, hb_ptr userdata)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const media_codec_callback_t *callback:用户回调函数
[IN] hb_ptr userdata:用户数据指针,该值会在回调函数被调用时作为入参传入
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
【功能描述】
设置回调函数指针,调用该函数后 MediaCodec 会进入异步工作模式。
【示例代码】
5.12.4.5. hb_mm_mc_set_input_buffer_listener
【函数声明】
hb_s32 hb_mm_mc_set_input_buffer_listener(media_codec_context_t *context, const
media_codec_callback_t *callback, hb_ptr userdata)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const media_codec_callback_t *callback:用户回调函数
[IN] hb_ptr userdata:用户数据指针,该值会在回调函数被调用时作为入参传入
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
【功能描述】
设置回调函数指针,当应用程序 queue input buffer 后 , 可以带上相应的 user ptr, 在 media_codec_buffer_t 结构体中。当编解码器内部对 input buffer 使用完成后 , 会主动调用 on_input_buffer_consumed 回调函数。 用户 可以在回调函数中做想做的操作 , 比如通过 user ptr 释放掉对应的资源。
典型用法 , 使用 external buffer 时 , sensor–>isp–>vse–>vpu–>ethernet 的数据通路 , 可以通过回调函数去释放使用 完成的 vse 资源。而无需应用去存储和记录送进编码器的 vse 数据。
【示例代码】
请参考 sample_codec 示例代码。其中有 external buffer 配合 input buffer consumed callback 机制 的实现。
5.12.4.6. hb_mm_mc_configure
【函数声明】
hb_s32 hb_mm_mc_configure(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
根据输入信息配置编码或解码器,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_CONFIGURED 状态。
【示例代码】
5.12.4.7. hb_mm_mc_start
【函数声明】
hb_s32 hb_mm_mc_start(media_codec_context_t *context, const
mc_av_codec_startup_params_t *info)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] mc_av_codec_startup_params_t *info:指定音视频编解码时的启动参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
启动编码 / 解码流程, MediaCodec 将创建编解码实例、设置序列或解析数据流、注册 Framebuffer、编码头信息等,调用成功后 MediaCodec 进入 MEDIA_CODEC_STATE_STARTED 状态。
【示例代码】
5.12.4.8. hb_mm_mc_stop
【函数声明】
hb_s32 hb_mm_mc_stop(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
停止编码 / 解码流程,退出所有子线程并释放相关资源,调用成功后 MediaCodec 回到 MEDIA_CODEC_STATE_INITIALIZED 状态。
【示例代码】
5.12.4.9. hb_mm_mc_pause
【函数声明】
hb_s32 hb_mm_mc_pause(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
停止编码 / 解码流程,暂停所有子线程,调用成功后 MediaCodec 进入到 MEDIA_CODEC_STATE_PAUSED 状态。
【示例代码】
参考 :hb_mm_mc_queue_input_buffer
5.12.4.10. hb_mm_mc_flush
【函数声明】
hb_s32 hb_mm_mc_flush(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
刷新输入输出 buffer 缓冲区,强制编码器 / 解码器刷新未处理的输入输出 buffer,函数调用后 MediaCodec 进入 MEDIA_CODEC_STATE_FLUSHING 状态,操作成功后, MediaCodec 会再次进入 MEDIA_CODEC_STATE_STARTED 状态。
【示例代码】
参考 :hb_mm_mc_queue_input_buffer
5.12.4.11. hb_mm_mc_release
【函数声明】
hb_s32 hb_mm_mc_release(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
释放 MediaCodec 内部所有资源,用户需要在调用该函数前调用 hb_mm_mc_stop 来停止编解码,操作成功后 MediaCodec 进入 MEDIA_CODEC_STATE_UNINITIALIZED 状态。
【示例代码】
5.12.4.12. hb_mm_mc_get_state
【函数声明】
hb_s32 hb_mm_mc_get_state(media_codec_context_t *context,
media_codec_state_t *state)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] media_codec_state_t *state: MediaCodec 当前状态
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 MediaCodec 当前的状态。
【示例代码】
5.12.4.13. hb_mm_mc_get_status
【函数声明】
hb_s32 hb_mm_mc_get_status(media_codec_context_t *context,
mc_inter_status_t *status)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_inter_status_t *status: MediaCodec 当前内部状态
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 MediaCodec 当前内部的状态信息。
【示例代码】
参考 :hb_mm_mc_get_fd
5.12.4.14. hb_mm_mc_queue_input_buffer
【函数声明】
hb_s32 hb_mm_mc_queue_input_buffer(media_codec_context_t *context,
media_codec_buffer_t *buffer, hb_s32 timeout)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] media_codec_buffer_t *buffer:输入的 buffer 信息
[IN] hb_s32 timeout:超时时间
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_INVALID_BUFFER:无效 buffer
HB_MEDIA_ERR_WAIT_TIMEOUT:等待超时
【功能描述】
填充需要处理的 buffer 到 MediaCodec 中。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
int32_t duration; // s
} MediaCodecTestContext;
Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
static void do_sync_encoding(void *arg) {
hb_s32 ret = 0;
FILE *inFile;
FILE *outFile;
int noMoreInput = 0;
int lastStream = 0;
Uint64 lastTime = 0;
Uint64 curTime = 0;
int needFlush = 1;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
//get current time
lastTime = osal_gettime();
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_pause(context);
if (ret) {
goto ERR;
}
do {
if (!noMoreInput) {
media_codec_buffer_t inputBuffer;
memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 100);
if (!ret) {
curTime = osal_gettime();
if ((curTime - lastTime)/1000 < (uint32_t)ctx->duration) {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
if(fseek(inFile, 0, SEEK_SET)) {
printf("Failed to rewind input filen");
} else {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
printf("Failed to read input filen");
}
}
}
} else {
printf("Time up(%d)n",ctx->duration);
ret = 0;
}
if (!ret) {
printf("There is no more input data!n");
inputBuffer.vframe_buf.frame_end = TRUE;
noMoreInput = 1;
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
if (ret) {
printf("Queue input buffer fail.n");
break;
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue input buffer fail.n");
break;
}
}
if (!lastStream) {
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info,
3000);
if (!ret && outFile) {
fwrite(outputBuffer.vstream_buf.vir_ptr,
outputBuffer.vstream_buf.size, 1, outFile);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
if (ret) {
printf("Queue output buffer fail.n");
break;
}
if (outputBuffer.vstream_buf.stream_end) {
printf("There is no more output data!n");
lastStream = 1;
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue output buffer fail.n");
break;
}
}
}
if (needFlush) {
ret = hb_mm_mc_flush(context);
needFlush = 0;
if (ret) {
break;
}
}
}while(TRUE);
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state !=
MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
if (outFile)
fclose(outFile);
}
int main(int argc, char *argv[])
{
hb_s32 ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.stream";
mc_video_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = TRUE;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = FALSE;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
ctx.duration = 5;
do_sync_encoding(&ctx);
}
5.12.4.15. hb_mm_mc_dequeue_input_buffer
【函数声明】
hb_s32 hb_mm_mc_dequeue_input_buffer(media_codec_context_t *context,
media_codec_buffer_t *buffer, hb_s32 timeout)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_s32 timeout:超时时间
[OUT] media_codec_buffer_t *buffer:输入的 buffer 信息
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_INVALID_BUFFER:无效 buffer
HB_MEDIA_ERR_WAIT_TIMEOUT:等待超时
【功能描述】
获取输入的 buffer。
【示例代码】
参考 :hb_mm_mc_queue_input_buffer
5.12.4.16. hb_mm_mc_queue_output_buffer
【函数声明】
hb_s32 hb_mm_mc_queue_output_buffer(media_codec_context_t *context,
media_codec_buffer_t *buffer, hb_s32 timeout)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] media_codec_buffer_t *buffer:输出的 buffer 信息
[IN] hb_s32 timeout:超时时间
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_INVALID_BUFFER:无效 buffer
HB_MEDIA_ERR_WAIT_TIMEOUT:等待超时
【功能描述】
返还处理完的 output buffer 到 MediaCodec 中。
【示例代码】
参考 :hb_mm_mc_queue_input_buffer
5.12.4.17. hb_mm_mc_dequeue_output_buffer
【函数声明】
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)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_s32 timeout:超时时间
[OUT] media_codec_buffer_t *buffer:输出的 buffer 信息
[IN] media_codec_output_buffer_info_t *info:输出数据流的信息
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_INVALID_BUFFER:无效 buffer
HB_MEDIA_ERR_WAIT_TIMEOUT:等待超时
【功能描述】
获取输出的 buffer。
【示例代码】
参考 :hb_mm_mc_queue_input_buffer
5.12.4.18. hb_mm_mc_get_longterm_ref_mode
【函数声明】
hb_s32 hb_mm_mc_get_longterm_ref_mode(media_codec_context_t *context,
mc_video_longterm_ref_mode_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_longterm_ref_mode_t *params:长期参考帧模式参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取长期参考帧模式的参数,适用于 H264/H265 。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
typedef enum ENC_CONFIG_MESSAGE {
ENC_CONFIG_NONE = (0 << 0),
ENC_CONFIG_LONGTERM_REF = (1 << 0),
ENC_CONFIG_INTRA_REFRESH = (1 << 1),
ENC_CONFIG_RATE_CONTROL = (1 << 2),
ENC_CONFIG_DEBLK_FILTER = (1 << 3),
ENC_CONFIG_SAO = (1 << 4),
ENC_CONFIG_ENTROPY = (1 << 5),
ENC_CONFIG_VUI_TIMING = (1 << 6),
ENC_CONFIG_SLICE = (1 << 7),
ENC_CONFIG_REQUEST_IDR = (1 << 8),
ENC_CONFIG_SKIP_PIC = (1 << 9),
ENC_CONFIG_SMART_BG = (1 << 10),
ENC_CONFIG_MONOCHROMA = (1 << 11),
ENC_CONFIG_PRED_UNIT = (1 << 12),
ENC_CONFIG_TRANSFORM = (1 << 13),
ENC_CONFIG_ROI = (1 << 14),
ENC_CONFIG_MODE_DECISION = (1 << 15),
ENC_CONFIG_USER_DATA = (1 << 16),
ENC_CONFIG_MJPEG = (1 << 17),
ENC_CONFIG_JPEG = (1 << 18),
ENC_CONFIG_CAMERA = (1 << 19),
ENC_CONFIG_INSERT_USERDATA = (1 << 20),
ENC_CONFIG_VUI = (1 << 21),
ENC_CONFIG_3DNR = (1 << 22),
ENC_CONFIG_REQUEST_IDR_HEADER = (1 << 23),
ENC_CONFIG_ENABLE_IDR = (1 << 24),
ENC_CONFIG_TOTAL = (1 << 25),
} ENC_CONFIG_MESSAGE;
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
int32_t duration; // s
ENC_CONFIG_MESSAGE message;
mc_video_longterm_ref_mode_t ref_mode;
mc_rate_control_params_t rc_params;
mc_video_intra_refresh_params_t intra_refr;
mc_video_deblk_filter_params_t deblk_filter;
mc_h265_sao_params_t sao;
mc_h264_entropy_params_t entropy;
mc_video_vui_params_t vui;
mc_video_vui_timing_params_t vui_timing;
mc_video_slice_params_t slice;
mc_video_3dnr_enc_params_t noise_reduction;
mc_video_smart_bg_enc_params_t smart_bg;
mc_video_pred_unit_params_t pred_unit;
mc_video_transform_params_t transform;
mc_video_roi_params_t roi;
mc_video_mode_decision_params_t mode_decision;
} MediaCodecTestContext;
Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
uint8_t uuid[] =
"dc45e9bd-e6d948b7-962cd820-d923eeef+HorizonAI";
static void set_message(MediaCodecTestContext *ctx) {
int ret = 0;
media_codec_context_t *context = ctx->context;
mc_video_longterm_ref_mode_t *ref_mode = &ctx->ref_mode;
hb_mm_mc_get_longterm_ref_mode(context, ref_mode);
ref_mode->use_longterm = TRUE;
ref_mode->longterm_pic_using_period = 20;
ref_mode->longterm_pic_period = 30;
//ctx->message = ENC_CONFIG_LONGTERM_REF;
if (ctx->message & ENC_CONFIG_LONGTERM_REF) {
ret = hb_mm_mc_set_longterm_ref_mode(context, &ctx->ref_mode);
}
if (ctx->message & ENC_CONFIG_INTRA_REFRESH) {
hb_mm_mc_get_intra_refresh_config(context, &ctx->intra_refr);
ret = hb_mm_mc_set_intra_refresh_config(context, &ctx->intra_refr);
}
if (ctx->message & ENC_CONFIG_SAO) {
hb_mm_mc_get_sao_config(context, &ctx->sao);
ret = hb_mm_mc_set_sao_config(context, &ctx->sao);
}
if (ctx->message & ENC_CONFIG_ENTROPY) {
hb_mm_mc_get_entropy_config(context, &ctx->entropy);
ret = hb_mm_mc_set_entropy_config(context, &ctx->entropy);
}
if (ctx->message & ENC_CONFIG_VUI) {
hb_mm_mc_get_vui_config(context, &ctx->vui);
ret = hb_mm_mc_set_vui_config(context, &ctx->vui);
}
if (ctx->message & ENC_CONFIG_VUI_TIMING) {
hb_mm_mc_get_vui_timing_config(context, &ctx->vui_timing);
ret = hb_mm_mc_set_vui_timing_config(context, &ctx->vui_timing);
}
mc_rate_control_params_t *rc_params = &ctx->rc_params;
rc_params->mode = context->video_enc_params.rc_params.mode;
hb_mm_mc_get_rate_control_config(context, rc_params);
switch (rc_params->mode) {
case MC_AV_RC_MODE_H264CBR:
rc_params->h264_cbr_params.bit_rate = 5000;
rc_params->h264_cbr_params.intra_period = 60;
break;
case MC_AV_RC_MODE_H264VBR:
rc_params->h264_vbr_params.intra_qp = 20;
rc_params->h264_vbr_params.intra_period = 30;
break;
case MC_AV_RC_MODE_H264AVBR:
rc_params->h264_avbr_params.intra_period = 15;
rc_params->h264_avbr_params.intra_qp = 25;
rc_params->h264_avbr_params.bit_rate = 2000;
rc_params->h264_avbr_params.vbv_buffer_size = 3000;
rc_params->h264_avbr_params.min_qp_I = 15;
rc_params->h264_avbr_params.max_qp_I = 50;
rc_params->h264_avbr_params.min_qp_P = 15;
rc_params->h264_avbr_params.max_qp_P = 45;
rc_params->h264_avbr_params.min_qp_B = 15;
rc_params->h264_avbr_params.max_qp_B = 48;
rc_params->h264_avbr_params.hvs_qp_enable = 0;
rc_params->h264_avbr_params.hvs_qp_scale = 2;
rc_params->h264_avbr_params.max_delta_qp = 5;
rc_params->h264_avbr_params.qp_map_enable = 0;
break;
case MC_AV_RC_MODE_H264FIXQP:
rc_params->h264_fixqp_params.force_qp_I = 23;
rc_params->h264_fixqp_params.force_qp_P = 23;
rc_params->h264_fixqp_params.force_qp_B = 23;
rc_params->h264_fixqp_params.intra_period = 23;
break;
case MC_AV_RC_MODE_H264QPMAP:
break;
case MC_AV_RC_MODE_H265CBR:
rc_params->h265_cbr_params.bit_rate = 5000;
rc_params->h265_cbr_params.intra_period = 60;
break;
case MC_AV_RC_MODE_H265VBR:
rc_params->h265_vbr_params.intra_qp = 20;
rc_params->h265_vbr_params.intra_period = 30;
break;
case MC_AV_RC_MODE_H265AVBR:
rc_params->h265_avbr_params.intra_period = 15;
rc_params->h265_avbr_params.intra_qp = 25;
rc_params->h265_avbr_params.bit_rate = 2000;
rc_params->h265_avbr_params.vbv_buffer_size = 3000;
rc_params->h265_avbr_params.min_qp_I = 15;
rc_params->h265_avbr_params.max_qp_I = 50;
rc_params->h265_avbr_params.min_qp_P = 15;
rc_params->h265_avbr_params.max_qp_P = 45;
rc_params->h265_avbr_params.min_qp_B = 15;
rc_params->h265_avbr_params.max_qp_B = 48;
rc_params->h265_avbr_params.hvs_qp_enable = 0;
rc_params->h265_avbr_params.hvs_qp_scale = 2;
rc_params->h265_avbr_params.max_delta_qp = 5;
rc_params->h265_avbr_params.qp_map_enable = 0;
break;
case MC_AV_RC_MODE_H265FIXQP:
rc_params->h265_fixqp_params.force_qp_I = 23;
rc_params->h265_fixqp_params.force_qp_P = 23;
rc_params->h265_fixqp_params.force_qp_B = 23;
rc_params->h265_fixqp_params.intra_period = 23;
break;
case MC_AV_RC_MODE_H265QPMAP:
break;
default:
break;
}
//ctx->message = ENC_CONFIG_RATE_CONTROL;
if (ctx->message & ENC_CONFIG_RATE_CONTROL) {
ret = hb_mm_mc_set_rate_control_config(context, &ctx->rc_params);
}
mc_video_deblk_filter_params_t *deblk_filter = &ctx->deblk_filter;
hb_mm_mc_get_deblk_filter_config(context, deblk_filter);
if (context->codec_id == MEDIA_CODEC_ID_H264) {
deblk_filter->h264_deblk.disable_deblocking_filter_idc = 2;
deblk_filter->h264_deblk.slice_alpha_c0_offset_div2 = 6;
deblk_filter->h264_deblk.slice_beta_offset_div2 = 6;
} else {
deblk_filter->h265_deblk.slice_deblocking_filter_disabled_flag = 1;
deblk_filter->h265_deblk.slice_beta_offset_div2 = 6;
deblk_filter->h265_deblk.slice_tc_offset_div2 = 6;
deblk_filter->h265_deblk.slice_loop_filter_across_slices_enabled_flag = 1;
}
//ctx->message = ENC_CONFIG_DEBLK_FILTER;
if (ctx->message & ENC_CONFIG_DEBLK_FILTER) {
ret = hb_mm_mc_set_deblk_filter_config(context, &ctx->deblk_filter);
}
if (context->codec_id == MEDIA_CODEC_ID_H264) {
mc_h264_entropy_params_t *entropy = &ctx->entropy;
hb_mm_mc_get_entropy_config(context, entropy);
entropy->entropy_coding_mode = 0;
ctx->message = ENC_CONFIG_ENTROPY;
if (ctx->message & ENC_CONFIG_ENTROPY) {
ret = hb_mm_mc_set_entropy_config(context, &ctx->entropy);
}
}
//ctx->message = ENC_CONFIG_SKIP_PIC;
if (ctx->message & ENC_CONFIG_SKIP_PIC) {
ret = hb_mm_mc_skip_pic(context, 0);
}
//ctx->message = ENC_CONFIG_REQUEST_IDR;
if (ctx->message & ENC_CONFIG_REQUEST_IDR) {
ret = hb_mm_mc_request_idr_frame(context);
}
mc_video_slice_params_t *slice = &ctx->slice;
hb_mm_mc_get_slice_config(context, slice);
if (context->codec_id == MEDIA_CODEC_ID_H264) {
slice->h264_slice.h264_slice_mode = 0;
slice->h264_slice.h264_slice_arg = 60;
} else {
slice->h265_slice.h265_dependent_slice_mode = 0;
slice->h265_slice.h265_dependent_slice_arg = 80;
slice->h265_slice.h265_independent_slice_mode = 1;
slice->h265_slice.h265_independent_slice_arg = 100;
}
//ctx->message = ENC_CONFIG_SLICE;
if (ctx->message & ENC_CONFIG_SLICE) {
ret = hb_mm_mc_set_slice_config(context, &ctx->slice);
}
mc_video_smart_bg_enc_params_t *smart_bg = &ctx->smart_bg;
hb_mm_mc_get_smart_bg_enc_config(context, smart_bg);
smart_bg->bg_detect_enable = 0;
smart_bg->bg_threshold_diff = 8;
smart_bg->bg_threshold_mean_diff = 1;
smart_bg->bg_lambda_qp = 32;
smart_bg->bg_delta_qp = 3;
smart_bg->s2fme_disable = 0;
//ctx->message = ENC_CONFIG_SMART_BG;
if (ctx->message & ENC_CONFIG_SMART_BG) {
ret = hb_mm_mc_set_smart_bg_enc_config(context, &ctx->smart_bg);
}
mc_video_pred_unit_params_t *pred_unit = &ctx->pred_unit;
hb_mm_mc_get_pred_unit_config(context, pred_unit);
if (context->codec_id == MEDIA_CODEC_ID_H264) {
pred_unit->h264_intra_pred.constrained_intra_pred_flag = 1;
} else {
pred_unit->h265_pred_unit.intra_nxn_enable = 1;
pred_unit->h265_pred_unit.constrained_intra_pred_flag = 1;
pred_unit->h265_pred_unit.strong_intra_smoothing_enabled_flag = 0;
pred_unit->h265_pred_unit.max_num_merge = 2;
}
//ctx->message = ENC_CONFIG_PRED_UNIT;
if (ctx->message & ENC_CONFIG_PRED_UNIT) {
ret = hb_mm_mc_set_pred_unit_config(context, &ctx->pred_unit);
}
mc_video_transform_params_t *transform = &ctx->transform;
hb_mm_mc_get_transform_config(context, transform);
if (context->codec_id == MEDIA_CODEC_ID_H264) {
transform->h264_transform.transform_8x8_enable = 1;
transform->h264_transform.chroma_cb_qp_offset = 4;
transform->h264_transform.chroma_cr_qp_offset = 3;
transform->h264_transform.user_scaling_list_enable = 0;
} else {
transform->h265_transform.chroma_cb_qp_offset = 6;
transform->h265_transform.chroma_cr_qp_offset = 5;
transform->h265_transform.user_scaling_list_enable = 0;
}
//ctx->message = ENC_CONFIG_TRANSFORM;
if (ctx->message & ENC_CONFIG_TRANSFORM) {
ret = hb_mm_mc_set_transform_config(context, &ctx->transform);
}
mc_video_roi_params_t *roi = &ctx->roi;
hb_mm_mc_get_roi_config(context, roi);
roi->roi_enable = 0;
//ctx->message = ENC_CONFIG_ROI;
if (ctx->message & ENC_CONFIG_ROI) {
ret = hb_mm_mc_set_roi_config(context, &ctx->roi);
}
mc_video_mode_decision_params_t *mode_decision = &ctx->mode_decision;
hb_mm_mc_get_mode_decision_config(context, mode_decision);
mode_decision->mode_decision_enable = FALSE;
mode_decision->pu04_delta_rate = 76;
mode_decision->pu08_delta_rate = 80;
mode_decision->pu16_delta_rate = 86;
mode_decision->pu32_delta_rate = 87;
mode_decision->pu04_intra_planar_delta_rate = 0;
mode_decision->pu04_intra_dc_delta_rate = 0;
mode_decision->pu04_intra_angle_delta_rate = 0;
mode_decision->pu08_intra_planar_delta_rate = 0;
mode_decision->pu08_intra_dc_delta_rate = 0;
mode_decision->pu08_intra_angle_delta_rate = 0;
mode_decision->pu16_intra_planar_delta_rate = 0;
mode_decision->pu16_intra_dc_delta_rate = 0;
mode_decision->pu16_intra_angle_delta_rate = 0;
mode_decision->pu32_intra_planar_delta_rate = 0;
mode_decision->pu32_intra_dc_delta_rate = 0;
mode_decision->pu32_intra_angle_delta_rate = 0;
mode_decision->cu08_intra_delta_rate = 0;
mode_decision->cu08_inter_delta_rate = 0;
mode_decision->cu08_merge_delta_rate = 0;
mode_decision->cu16_intra_delta_rate = 0;
mode_decision->cu16_inter_delta_rate = 0;
mode_decision->cu16_merge_delta_rate = 0;
mode_decision->cu32_intra_delta_rate = 0;
mode_decision->cu32_inter_delta_rate = 0;
mode_decision->cu32_merge_delta_rate = 0;
//ctx->message = ENC_CONFIG_MODE_DECISION;
if (ctx->message & ENC_CONFIG_MODE_DECISION) {
ret = hb_mm_mc_set_mode_decision_config(context, &ctx->mode_decision);
}
if (ctx->message & ENC_CONFIG_INSERT_USERDATA) {
hb_u32 length = sizeof(uuid)/sizeof(uuid[0]);
ret = hb_mm_mc_insert_user_data(context, uuid, length);
}
if (ctx->message & ENC_CONFIG_3DNR) {
hb_mm_mc_get_3dnr_enc_config(context, &ctx->noise_reduction);
ret = hb_mm_mc_set_3dnr_enc_config(context, &ctx->noise_reduction);
}
if (ctx->message & ENC_CONFIG_ENABLE_IDR) {
// disable idr frame first
if (ctx->enable_idr_num) {
ret = hb_mm_mc_enable_idr_frame(context, 0);
}
}
if (ctx->message & ENC_CONFIG_REQUEST_IDR_HEADER) {
ret = hb_mm_mc_request_idr_header(context, ctx->force_idr_header);
}
}
static void do_sync_encoding(void *arg) {
hb_s32 ret = 0;
FILE *inFile;
FILE *outFile;
int noMoreInput = 0;
int lastStream = 0;
Uint64 lastTime = 0;
Uint64 curTime = 0;
int needFlush = 1;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
//get current time
lastTime = osal_gettime();
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_pause(context);
if (ret) {
goto ERR;
}
do {
set_message(ctx);
if (!noMoreInput) {
media_codec_buffer_t inputBuffer;
memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 100);
if (!ret) {
curTime = osal_gettime();
if ((curTime - lastTime)/1000 < (uint32_t)ctx->duration) {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
if(fseek(inFile, 0, SEEK_SET)) {
printf("Failed to rewind input file\n");
} else {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
printf("Failed to read input file\n");
}
}
}
} else {
printf("Time up(%d)\n",ctx->duration);
ret = 0;
}
if (!ret) {
printf("There is no more input data!\n");
inputBuffer.vframe_buf.frame_end = TRUE;
noMoreInput = 1;
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
if (ret) {
printf("Queue input buffer fail.\n");
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue input buffer fail.\n");
break;
}
}
}
if (!lastStream) {
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info, 3000);
if (!ret && outFile) {
fwrite(outputBuffer.vstream_buf.vir_ptr, outputBuffer.vstream_buf.size, 1, outFile);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
if (ret) {
printf("Queue output buffer fail.\n");
break;
}
if (outputBuffer.vstream_buf.stream_end) {
printf("There is no more output data!\n");
lastStream = 1;
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue output buffer fail.\n");
break;
}
}
}
if (needFlush) {
ret = hb_mm_mc_flush(context);
needFlush = 0;
if (ret) {
break;
}
}
}while(TRUE);
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state != MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
if (outFile)
fclose(outFile);
}
int main(int argc, char *argv[])
{
hb_s32 ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.stream";
mc_video_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = TRUE;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = FALSE;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
ctx.duration = 5;
do_sync_encoding(&ctx);
}
5.12.4.19. hb_mm_mc_set_longterm_ref_mode
【函数声明】
hb_s32 hb_mm_mc_set_longterm_ref_mode(media_codec_context_t *context,
const mc_video_longterm_ref_mode_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_longterm_ref_mode_t *params:长期参考帧模式参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置长期参考帧模式的参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.20. hb_mm_mc_get_intra_refresh_config
【函数声明】
hb_s32 hb_mm_mc_get_intra_refresh_config(media_codec_context_t
*context, mc_video_intra_refresh_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_intra_refresh_params_t *params:帧内刷新参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取帧内刷新参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.21. hb_mm_mc_set_intra_refresh_config
【函数声明】
hb_s32 hb_mm_mc_set_intra_refresh_config(media_codec_context_t
*context, const mc_video_intra_refresh_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_intra_refresh_params_t *params:帧内刷新参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置帧内刷新模式参数,该参数为静态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.22. hb_mm_mc_get_rate_control_config
【函数声明】
hb_s32 hb_mm_mc_get_rate_control_config(media_codec_context_t *context,
mc_rate_control_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_rate_control_params_t *params:码率控制参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取码率控制参数,该参数为动态参数,适用于 H264/H265/MJPEG。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.23. hb_mm_mc_set_rate_control_config
【函数声明】
hb_s32 hb_mm_mc_set_rate_control_config(media_codec_context_t *context,
const mc_rate_control_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_rate_control_params_t *params:码率控制参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置码率控制参数,该参数为动态参数,适用于 H264/H265/MJPEG。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.24. hb_mm_mc_get_deblk_filter_config
【函数声明】
hb_s32 hb_mm_mc_get_deblk_filter_config(media_codec_context_t *context,
mc_video_deblk_filter_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_deblk_filter_params_t * params:去块滤波参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取去块滤波参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.25. hb_mm_mc_set_deblk_filter_config
【函数声明】
hb_s32 hb_mm_mc_set_deblk_filter_config(media_codec_context_t *context,
const mc_video_deblk_filter_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_deblk_filter_params_t *params:去块滤波参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置去块滤波参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.26. hb_mm_mc_get_sao_config
【函数声明】
hb_s32 hb_mm_mc_get_sao_config(media_codec_context_t *context,
mc_h265_sao_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_h265_sao_params_t *params: SAO 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 SAO 参数,适用于 H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.27. hb_mm_mc_set_sao_config
【函数声明】
hb_s32 hb_mm_mc_set_sao_config(media_codec_context_t *context, const
mc_h265_sao_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_h265_sao_params_t *params: SAO 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 SAO 参数,该参数为静态参数,适用于 H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.28. hb_mm_mc_get_entropy_config
【函数声明】
hb_s32 hb_mm_mc_get_entropy_config(media_codec_context_t *context, mc_h264_entropy_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] mc_h264_entropy_params_t *params: entropy 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 entropy 参数,适用于 H264 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.29. hb_mm_mc_set_entropy_config
【函数声明】
extern hb_s32 hb_mm_mc_set_entropy_config(media_codec_context_t *context, const mc_h264_entropy_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_h264_entropy_params_t *params: entropy 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 entropy 参数,适用于 H264 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.30. hb_mm_mc_get_vui_timing_config
【函数声明】
hb_s32 hb_mm_mc_get_vui_timing_config(media_codec_context_t *context,
mc_video_vui_timing_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_vui_timing_params_t *params: VUI Timing 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 VUI Timing 参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.31. hb_mm_mc_set_vui_timing_config
【函数声明】
hb_s32 hb_mm_mc_set_vui_timing_config(media_codec_context_t *context,
const mc_video_vui_timing_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_vui_timing_params_t *params: VUI Timing 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 VUI Timing 参数,该参数为静态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.32. hb_mm_mc_get_slice_config
【函数声明】
hb_s32 hb_mm_mc_get_slice_config(media_codec_context_t *context,
mc_video_slice_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_slice_params_t *params: slice 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 slice 编码参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.33. hb_mm_mc_set_slice_config
【函数声明】
hb_s32 hb_mm_mc_set_slice_config(media_codec_context_t *context, const
mc_video_slice_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_slice_params_t *params: slice 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 slice 编码参数,该参数为动态参数,适用于 H264/H265 。限制每帧 slice 个数小于等于 1500 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.34. hb_mm_mc_insert_user_data
【函数声明】
hb_s32 hb_mm_mc_insert_user_data(media_codec_context_t * context, hb_u8
*data, hb_u32 length)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_u8 *data:用户数据
[IN] hb_u32 length:用户数据长度
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
在编码流中插入用户数据,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.35. hb_mm_mc_request_idr_frame
【函数声明】
hb_s32 hb_mm_mc_request_idr_frame(media_codec_context_t *context)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
请求 IDR 帧,该接口可动态设置,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.36. hb_mm_mc_skip_pic
【函数声明】
hb_s32 hb_mm_mc_skip_pic(media_codec_context_t *context, hb_s32
src_idx)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_s32 src_idx: source buffer 索引值
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
使能指定的图像的 skip 模式编码,该接口可动态设置,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.37. hb_mm_mc_get_smart_bg_enc_config
【函数声明】
extern hb_s32 hb_mm_mc_get_smart_bg_enc_config(media_codec_context_t *context, mc_video_smart_bg_enc_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_smart_bg_enc_params_t *params:智能背景编码模式参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取智能背景编码参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.38. hb_mm_mc_set_smart_bg_enc_config
【函数声明】
hb_s32 hb_mm_mc_set_smart_bg_enc_config(media_codec_context_t *context, const mc_video_smart_bg_enc_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_smart_bg_enc_params_t *params:智能背景编码模式参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置智能背景编码参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.39. hb_mm_mc_get_pred_unit_config
【函数声明】
hb_s32 hb_mm_mc_get_pred_unit_config(media_codec_context_t *context,
mc_video_pred_unit_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_pred_unit_params_t *params:预测单元参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取预测单元参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.40. hb_mm_mc_set_pred_unit_config
【函数声明】
hb_s32 hb_mm_mc_set_pred_unit_config(media_codec_context_t *context,
const mc_video_pred_unit_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_pred_unit_params_t *params:预测单元参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置预测单元参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.41. hb_mm_mc_get_transform_config
【函数声明】
hb_s32 hb_mm_mc_get_transform_config(media_codec_context_t *context,
mc_video_transform_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_transform_params_t *params: Transform 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 Transform 参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.42. hb_mm_mc_set_transform_config
【函数声明】
hb_s32 hb_mm_mc_set_transform_config(media_codec_context_t *context,
const mc_video_transform_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_transform_params_t *params: Transform 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 Transform 参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.43. hb_mm_mc_get_roi_config
【函数声明】
hb_s32 hb_mm_mc_get_roi_config(media_codec_context_t *context,
mc_video_roi_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_roi_params_t *params: ROI 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 ROI 编码参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.44. hb_mm_mc_set_roi_config
【函数声明】
hb_s32 hb_mm_mc_set_roi_config(media_codec_context_t *context, const
mc_video_roi_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_roi_params_t *params: ROI 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 ROI 编码参数,该参数为动态参数,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.45. hb_mm_mc_get_mode_decision_config
【函数声明】
hb_s32 hb_mm_mc_get_mode_decision_config(media_codec_context_t *context, mc_video_mode_decision_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_mode_decision_params_t *params:模式决策参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 ROI 编码参数,适用于 H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.46. hb_mm_mc_set_mode_decision_config
【函数声明】
hb_s32 hb_mm_mc_set_mode_decision_config(media_codec_context_t *context, const mc_video_mode_decision_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_mode_decision_params_t *params:模式决策参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置模式决策参数,该参数为动态参数,适用于 H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.47. hb_mm_mc_get_user_data
【函数声明】
hb_s32 hb_mm_mc_get_user_data(media_codec_context_t *context,
mc_user_data_buffer_t *params , hb_s32 timeout)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_user_data_buffer_t *params:用户数据
[IN] timeout:超时时间
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取解码流中的用户数据,适用于 H264/H265 。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
static int check_and_init_test(MediaCodecTestContext *ctx) {
int32_t ret = 0;
char *inputFileName, *outputFileName, *inputMd5FileName;
EXPECT_NE(ctx, nullptr);
EXPECT_NE(ctx->context, nullptr);
if (ctx == NULL || ctx->context == NULL) {
return -1;
}
inputFileName = ctx->inputFileName;
outputFileName = ctx->outputFileName;
inputMd5FileName = ctx->inputMd5FileName;
printf("%s[%d:%d] Thread work in %s mode\n", TAG, getpid(), gettid(),
ctx->workMode == THREAD_WORK_MODE_SYNC ? "sync" :
(ctx->workMode == THREAD_WORK_MODE_ASYNC ? "async" : "poll"));
printf("%s[%d:%d] InputFileName = %s\n", TAG, getpid(), gettid(), inputFileName);
printf("%s[%d:%d] OutputFileName = %s\n", TAG, getpid(), gettid(), outputFileName);
printf("%s[%d:%d] InputMd5File = %s\n", TAG, getpid(), gettid(), inputMd5FileName);
EXPECT_NE(inputFileName, nullptr);
EXPECT_NE(outputFileName, nullptr);
if (inputFileName == NULL || outputFileName == NULL) {
return -1;
}
ctx->inFile = fopen(inputFileName, "rb");
EXPECT_NE(ctx->inFile, nullptr);
ctx->outFile = fopen(outputFileName, "wb+");
EXPECT_NE(ctx->outFile, nullptr);
if (ctx->inFile == NULL || ctx->outFile == NULL) {
return -1;
}
if (ctx->md5Test == TRUE) {
if (inputMd5FileName) {
ctx->inMd5File = fopen(inputMd5FileName, "rb");
}
EXPECT_NE(ctx->inMd5File, nullptr);
if (ctx->inMd5File == NULL) {
return -1;
}
}
// allocate ion buffers
ctx->ionFd = ion_open();
EXPECT_GT(ctx->ionFd, 0);
if (ctx->ionFd <= 0) {
return -1;
}
if (ctx->context->encoder == TRUE) {
printf("%s[%d:%d] Thread use %s buffer mode, %d rc mode\n", TAG, getpid(), gettid(),
ctx->context->video_enc_params.external_frame_buf ?
"external" : "internal",
ctx->context->video_enc_params.rc_params.mode);
if (ctx->context->video_enc_params.external_frame_buf) {
ctx->exFb = (ExternalFrameBuffer *) malloc(
ctx->context->video_enc_params.frame_buf_count * sizeof(ExternalFrameBuffer));
EXPECT_NE(ctx->exFb, nullptr);
if (ctx->exFb == NULL) {
return -1;
}
for (Uint32 i=0; i<ctx->context->video_enc_params.frame_buf_count; i++) {
ctx->exFb[i].buf.size = ctx->context->video_enc_params.width
* ctx->context->video_enc_params.height * 3/2; // only for yuv420;
ret = allocate_ion_mem(ctx->ionFd, &ctx->exFb[i].buf);
EXPECT_EQ(ret, 0);
if (ret != 0) {
return ret;
}
ctx->exFb[i].valid = 1;
ctx->exFb[i].src_idx = i;
}
}
} else {
printf("%s[%d:%d] Thread use %s buffer mode, %d feed mode.\n", TAG, getpid(), gettid(),
ctx->context->video_dec_params.external_bitstream_buf ?
"external" : "internal",
ctx->context->video_dec_params.feed_mode);
if (ctx->context->video_dec_params.external_bitstream_buf) {
ctx->exBs = (ExternalStreamBuffer *) malloc(
ctx->context->video_dec_params.bitstream_buf_count * sizeof(ExternalStreamBuffer));
EXPECT_NE(ctx->exBs, nullptr);
if (ctx->exBs == NULL) {
return -1;
}
for (Uint32 i=0; i<ctx->context->video_dec_params.bitstream_buf_count; i++) {
ctx->exBs[i].buf.size = ctx->context->video_dec_params.bitstream_buf_size;
ret = allocate_ion_mem(ctx->ionFd, &ctx->exBs[i].buf);
EXPECT_EQ(ret, 0);
if (ret != 0) {
return ret;
}
ctx->exBs[i].valid = 1;
ctx->exBs[i].src_idx = i;
}
}
}
// open decode files
if (ctx->context->encoder != TRUE) {
if (ctx->context->video_dec_params.feed_mode == MC_FEEDING_MODE_FRAME_SIZE) {
ret = avformat_open_input(&ctx->avContext, ctx->inputFileName, 0, 0);
EXPECT_GE(ret, 0);
if (ret < 0) {
return ret;
}
ret = avformat_find_stream_info(ctx->avContext, 0);
EXPECT_GE(ret, 0);
if (ret < 0) {
return ret;
}
ctx->videoIndex = av_find_best_stream(ctx->avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
EXPECT_GE(ctx->videoIndex, 0);
if (ctx->videoIndex < 0) {
return -1;
}
av_init_packet(&ctx->avpacket);
} else {
if (ctx->feedingSize == 0) {
uint32_t KB = 1024;
int32_t probability10;
srand((uint32_t)time(NULL));
ctx->feedingSize = rand() % MAX_FEEDING_SIZE;
probability10 = (ctx->feedingSize % 100) < 10;
if (ctx->feedingSize < KB) {
if (probability10 == FALSE)
ctx->feedingSize *= 100;
}
}
printf("%s[%d:%d] Feeding size = %d\n", TAG,
getpid(), gettid(), ctx->feedingSize);
}
ctx->firstPacket = 1;
}
return 0;
}
static int check_and_release_test(MediaCodecTestContext *ctx) {
int32_t ret = 0;
int md5Match, wholeFileSize = 0;
uint8_t *md5Buffer = NULL;
EXPECT_NE(ctx, nullptr);
EXPECT_NE(ctx->context, nullptr);
EXPECT_NE(ctx->inFile, nullptr);
EXPECT_NE(ctx->outFile, nullptr);
if (ctx == NULL || ctx->context == NULL || ctx->inFile == NULL ||
ctx->outFile == NULL) {
return -1;
}
if (ctx->context->encoder != TRUE) {
if (ctx->context->video_dec_params.feed_mode == MC_FEEDING_MODE_FRAME_SIZE) {
if (ctx->avContext) {
avformat_close_input(&ctx->avContext);
}
}
}
if (ctx->context->encoder == TRUE) {
if (ctx->context->video_enc_params.external_frame_buf) {
if (ctx->exFb) {
for (Uint32 i=0; i<ctx->context->video_enc_params.frame_buf_count; i++) {
ret = release_ion_mem(ctx->ionFd, &ctx->exFb[i].buf);
EXPECT_EQ(ret, 0);
}
free(ctx->exFb);
}
}
} else {
if (ctx->context->video_dec_params.external_bitstream_buf) {
if (ctx->exBs) {
for (Uint32 i=0; i<ctx->context->video_dec_params.bitstream_buf_count; i++) {
ret = release_ion_mem(ctx->ionFd, &ctx->exBs[i].buf);
EXPECT_EQ(ret, 0);
}
free(ctx->exBs);
}
}
}
if (ctx->ionFd)
ion_close(ctx->ionFd);
if (ctx->md5Test && ctx->inMd5File) {
fseek(ctx->outFile, 0, SEEK_END);
wholeFileSize = ftell(ctx->outFile);
fseek(ctx->outFile, 0, SEEK_SET);
md5Buffer = (uint8_t *)malloc(wholeFileSize);
EXPECT_NE(md5Buffer, nullptr);
if (md5Buffer == NULL) {
return -1;
}
fread(md5Buffer, wholeFileSize, 1, ctx->outFile);
md5Match = compare_md5_value(MD5_SIZE, ctx->inMd5File,
md5Buffer, wholeFileSize);
free(md5Buffer);
fclose(ctx->inMd5File);
EXPECT_EQ(md5Match, 1);
if (md5Match != 1) {
return -1;
}
}
if (ctx->outFile)
fclose(ctx->outFile);
if (ctx->inFile)
fclose(ctx->inFile);
return 0;
}
static void on_vlc_buffer_message(hb_ptr userdata, hb_s32 * vlc_buf) {
MediaCodecTestContext *ctx = (MediaCodecTestContext *)userdata;
ASSERT_NE(vlc_buf, nullptr);
ASSERT_NE(ctx, nullptr);
ASSERT_GE(ctx->vlc_buf_size, 0);
if (ctx->testLog) {
printf("%s %s VLC Buffer size = %d; Reset to %d.\n", TAG, __FUNCTION__,
*vlc_buf, ctx->vlc_buf_size);
}
*vlc_buf = ctx->vlc_buf_size;
}
static int read_input_streams(MediaCodecTestContext *ctx,
media_codec_buffer_t *inputBuffer) {
Uint64 curTime = 0;
int ret = 0, ret2 = 0;
Uint32 bufIdx = 0, srcIdx = 0;
Int32 doRead = TRUE, doRewind = FALSE;
uint8_t *seqHeader = NULL;
int seqHeaderSize = 0;
void *bufPtr = NULL;
int avalBufSize = 0;
EXPECT_NE(ctx, nullptr);
EXPECT_NE(ctx->context, nullptr);
EXPECT_NE(ctx->inFile, nullptr);
EXPECT_NE(ctx->outFile, nullptr);
EXPECT_NE(inputBuffer, nullptr);
if (ctx == NULL || ctx->context == NULL || ctx->inFile == NULL ||
ctx->outFile == NULL || inputBuffer == NULL) {
printf("%s[%d:%d] Invalid parameters(%s).\n",
TAG, getpid(), gettid(), __FUNCTION__);
return -1;
}
if (ctx->stabilityTest || ctx->pfTest) {
doRewind = TRUE;
curTime = osal_gettime();
if ((curTime - ctx->testStartTime)/1000 < (uint32_t)ctx->duration) {
doRead = TRUE;
} else {
printf("%s[%d:%d] Time up(%d)\n",
TAG, getpid(), gettid(), ctx->duration);
doRead = FALSE;
ret = 0;
}
}
if (ctx->context->video_dec_params.external_bitstream_buf) {
// release input buffer and take it as the new input buffer
for (bufIdx = 0;
bufIdx < ctx->context->video_dec_params.bitstream_buf_count;
bufIdx++) {
if (ctx->exBs[bufIdx].valid &&
ctx->exBs[bufIdx].src_idx == inputBuffer->vstream_buf.src_idx) {
srcIdx = inputBuffer->vstream_buf.src_idx;
break;
}
}
EXPECT_NE(bufIdx, ctx->context->video_dec_params.bitstream_buf_count);
if (bufIdx == ctx->context->video_dec_params.bitstream_buf_count) {
return -1;
}
bufPtr = (void *)ctx->exBs[srcIdx].buf.virt_addr;
if (ctx->context->video_dec_params.feed_mode ==
MC_FEEDING_MODE_FRAME_SIZE) {
avalBufSize = ctx->exBs[srcIdx].buf.size;
} else {
avalBufSize = (ctx->exBs[srcIdx].buf.size < (int)ctx->feedingSize) ?
ctx->exBs[srcIdx].buf.size : ctx->feedingSize;
}
inputBuffer->vstream_buf.fd = ctx->exBs[srcIdx].buf.fd;
inputBuffer->vstream_buf.phy_ptr =
ctx->exBs[srcIdx].buf.phys_addr;
inputBuffer->vstream_buf.vir_ptr =
(hb_u8 *)ctx->exBs[srcIdx].buf.virt_addr;
} else {
bufPtr = (void *)inputBuffer->vstream_buf.vir_ptr;
if (ctx->context->video_dec_params.feed_mode ==
MC_FEEDING_MODE_FRAME_SIZE) {
avalBufSize = inputBuffer->vstream_buf.size;
} else {
avalBufSize = (inputBuffer->vstream_buf.size < ctx->feedingSize) ?
inputBuffer->vstream_buf.size : ctx->feedingSize;
}
}
if (doRead == FALSE) {
return ret;
}
// MC_FEEDING_MODE_FRAME_SIZE mode
if (ctx->context->video_dec_params.feed_mode == MC_FEEDING_MODE_FRAME_SIZE) {
do {
if (ctx->avpacket.size == 0) {
ret = av_read_frame(ctx->avContext, &ctx->avpacket);
if (ret < 0 && doRewind == FALSE) {
printf("%s[%d:%d] Failed to read input file (error=0x%x)\n",
TAG, getpid(), gettid(), ret);
}
if (ret < 0 && doRewind == TRUE) {
avformat_close_input(&ctx->avContext);
ret2 = avformat_open_input(&ctx->avContext, ctx->inputFileName, 0, 0);
EXPECT_GE(ret2, 0);
if (ret2 < 0) {
ret = ret2;
break;
}
/*ret = avformat_find_stream_info(ctx->avContext, 0);
EXPECT_GE(ret, 0);
if (ret < 0) {
break;
}
ctx->videoIndex = av_find_best_stream(ctx->avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
EXPECT_GE(ctx->videoIndex, 0);
if (ctx->videoIndex < 0) {
ret = -1;
break;
}*/
av_init_packet(&ctx->avpacket);
}
} else {
if (ctx->testLog) {
printf("%s[%d:%d] Reuse previous stream packet size %d\n",
TAG, getpid(), gettid(), ctx->avpacket.size);
}
}
} while (ret < 0 && doRewind == TRUE);
if (ret < 0) {
if (ret == AVERROR_EOF || ctx->avContext->pb->eof_reached == TRUE) {
printf("%s[%d:%d] End of file!\n", TAG, getpid(), gettid());
ret = 0;
} else {
printf("%s[%d:%d] Failed to av_read_frame error(0x%08x)\n",
TAG, getpid(), gettid(), ret);
}
return ret;
}
if (ctx->testLog) {
printf("%s[%d:%d] Read packet size %d\n",
TAG, getpid(), gettid(), ctx->avpacket.size);
}
seqHeaderSize = 0;
if (ctx->firstPacket) {
AVCodecParameters* codec;
int retSize = 0;
codec = ctx->avContext->streams[ctx->videoIndex]->codecpar;
seqHeader = (uint8_t*)malloc(codec->extradata_size + 1024);
if (seqHeader == NULL) {
printf("%s[%d:%d] Failed to mallock seqHeader\n",
TAG, getpid(), gettid());
ret = -1;
return ret;
}
memset((void*)seqHeader, 0x00, codec->extradata_size + 1024);
seqHeaderSize = build_dec_seq_header(seqHeader,
ctx->context->codec_id,
ctx->avContext->streams[ctx->videoIndex], &retSize);
if (seqHeaderSize < 0) {
printf("%s[%d:%d] Failed to build seqHeader\n",
TAG, getpid(), gettid());
ret = -1;
return ret;
}
ctx->firstPacket = 0;
}
if ((ctx->avpacket.size <= avalBufSize)
&& (seqHeaderSize <= avalBufSize)) {
int bufSize = 0;
if (seqHeaderSize) {
memcpy(bufPtr, seqHeader, seqHeaderSize);
bufSize = seqHeaderSize;
/*memcpy((char *)bufPtr+bufSize,ctx->avpacket.data, ctx->avpacket.size);
bufSize += ctx->avpacket.size;
av_packet_unref(&ctx->avpacket);
ctx->avpacket.size = 0;*/
} else {
memcpy(bufPtr,ctx->avpacket.data, ctx->avpacket.size);
bufSize = ctx->avpacket.size;
av_packet_unref(&ctx->avpacket);
ctx->avpacket.size = 0;
}
inputBuffer->vstream_buf.size = bufSize;
} else {
printf("%s[%d:%d] The stream buffer is too "
"small!\n", TAG, getpid(), gettid());
return -1;
}
if (seqHeader) {
free(seqHeader);
seqHeader = NULL;
}
return 1;
}
// MC_FEEDING_MODE_STREAM_SIZE mode
do {
ret = fread(bufPtr, 1, avalBufSize, ctx->inFile);
if (ret <= 0 && doRewind == FALSE) {
printf("%s[%d:%d] Failed to read input file (error=0x%x)\n",
TAG, getpid(), gettid(), ret);
}
if (ret <= 0 && doRewind == TRUE) {
if(fseek(ctx->inFile, 0, SEEK_SET)) {
printf("%s Failed to rewind input file (pid=%d, tid=%d)\n",
TAG, getpid(), gettid());
break;
}
}
} while (ret == 0 && doRewind == TRUE);
inputBuffer->vstream_buf.size = ret > 0 ? ret : 0;
return ret;
}
static int write_output_frames(MediaCodecTestContext *ctx,
media_codec_buffer_t *outputBuffer) {
int32_t ret = 0;
EXPECT_NE(ctx, nullptr);
EXPECT_NE(ctx->context, nullptr);
EXPECT_NE(ctx->inFile, nullptr);
EXPECT_NE(ctx->outFile, nullptr);
EXPECT_NE(outputBuffer, nullptr);
if (ctx == NULL || ctx->context == NULL || ctx->inFile == NULL ||
ctx->outFile == NULL || outputBuffer == NULL) {
printf("%s[%d:%d] Invalid parameters(%s).\n",
TAG, getpid(), gettid(), __FUNCTION__);
return -1;
}
if (!ctx->stabilityTest && !ctx->pfTest) {
fwrite(outputBuffer->vframe_buf.vir_ptr[0], outputBuffer->vframe_buf.size,
1, ctx->outFile);
}
return ret;
}
static int do_decode_params_checking(MediaCodecTestContext *ctx,
media_codec_buffer_t *outputBuffer) {
media_codec_context_t *context;
int32_t ret = 0;
EXPECT_NE(ctx, nullptr);
EXPECT_NE(ctx->context, nullptr);
if (ctx == NULL || ctx->context == NULL || ctx->inFile == NULL ||
ctx->outFile == NULL || outputBuffer == NULL) {
printf("%s[%d:%d] Invalid parameters(%s).\n",
TAG, getpid(), gettid(), __FUNCTION__);
return -1;
}
context = ctx->context;
if (ctx->enable_get_userdata) {
mc_user_data_buffer_t userdata = {0};
ret = hb_mm_mc_get_user_data(context, &userdata, 0);
if (!ret) {
printf("%s[%d:%d] Get userdata %d:\n", TAG, getpid(), gettid(), userdata.size);
for (uint32_t i = 0; i < userdata.size; i++) {
if (i < 16) {
printf("%s[%d:%d] userdata[i]:%x\n", TAG, getpid(), gettid(), userdata.virt_addr[i]);
} else {
printf("%s[%d:%d] userdata[i]:%c\n", TAG, getpid(), gettid(), userdata.virt_addr[i]);
}
}
ret = hb_mm_mc_release_user_data(context, &userdata);
} else {
ret = 0;
}
}
return ret;
}
static void do_sync_decoding(void *arg) {
int ret = 0;
int step = 0;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context;
media_codec_callback_t callback;
media_codec_buffer_t inputBuffer;
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
int32_t decStartTime = 0, decFinishTime = 0;
ctx->workMode = THREAD_WORK_MODE_SYNC;
ASSERT_EQ(check_and_init_test(ctx), 0);
context = ctx->context;
//get current time
ctx->testStartTime = osal_gettime();
if (ctx->testLog) {
printf("%s[%d:%d] Step %d initialize (outFile=%s, FileFd=%p)\n",
TAG, getpid(), gettid(), step++, ctx->outputFileName, ctx->outFile);
}
ret = hb_mm_mc_initialize(context);
ASSERT_EQ(ret, (int32_t)0);
callback.on_vlc_buffer_message = on_vlc_buffer_message;
if (ctx->vlc_buf_size > 0) {
ret = hb_mm_mc_set_vlc_buffer_listener(context, &callback, ctx);
ASSERT_EQ(ret, (int32_t)0);
}
if (ctx->testLog) {
printf("%s[%d:%d] Step %d configure\n", TAG, getpid(), gettid(), step++);
}
ret = hb_mm_mc_configure(context);
EXPECT_EQ(ret, (int32_t)0);
if (ctx->testLog) {
printf("%s[%d:%d] Step %d start\n", TAG, getpid(), gettid(), step++);
}
mc_av_codec_startup_params_t startup_params;
memset(&startup_params, 0x00, sizeof(mc_av_codec_startup_params_t));
ret = hb_mm_mc_start(context, &startup_params);
EXPECT_EQ(ret, (int32_t)0);
do {
if (!ctx->lastStream) {
if (ctx->testLog) {
printf("%s[%d:%d] Step %d dequeue input\n", TAG, getpid(), gettid(), step++);
}
// process input buffers
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 3000);
//EXPECT_EQ(ret, (int32_t)0);
if (!ret) {
if (ctx->testLog) {
printf("%s[%d:%d] input buffer viraddr %p phy addr %x, size = %d\n",
TAG, getpid(), gettid(), inputBuffer.vstream_buf.vir_ptr,
inputBuffer.vstream_buf.phy_ptr,
inputBuffer.vstream_buf.size);
}
if (ctx->testLog) {
printf("%s[%d:%d] Step %d feed input (pid=%d, tid=%d)\n", TAG, getpid(), gettid(), step++);
}
ret = read_input_streams(ctx, &inputBuffer);
if (ret <= 0) {
printf("%s[%d:%d] There is no more input data(ret=%d)!\n",
TAG, getpid(), gettid(), ret);
inputBuffer.vstream_buf.stream_end = TRUE;
inputBuffer.vstream_buf.size = 0;
ctx->lastStream = 1;
}
//EXPECT_EQ(ret, (int32_t)TRUE);
if (ctx->testLog) {
printf("%s[%d:%d] Step %d queue input(size=%d)\n",
TAG, getpid(), gettid(), step++, inputBuffer.vstream_buf.size);
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
EXPECT_EQ(ret, (int32_t)0);
if (ret != 0) {
break;
}
if (ctx->delaytest) {
decStartTime = osal_gettime();
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
EXPECT_EQ(ret, (int32_t)0);
char info[256];
hb_mm_strerror(ret, info, 256);
printf("%s[%d:%d] dequeue input buffer fail.(%s)\n", TAG, getpid(), gettid(), info);
break;
}
}
}
if (!ctx->lastFrame) {
if (ctx->testLog) {
printf("%s[%d:%d] Step %d dequeue output\n", TAG, getpid(), gettid(), step++);
}
// process output buffers
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info, 100);
//EXPECT_EQ(ret, (int32_t)0);
if (!ret) {
if (ctx->testLog) {
printf("%s[%d:%d] output bufferviraddr %p phy addr %x, size = %d, outFile = %p\n",
TAG, getpid(), gettid(), outputBuffer.vframe_buf.vir_ptr[0],
outputBuffer.vframe_buf.phy_ptr[0],
outputBuffer.vframe_buf.size, ctx->outFile);
}
if (ctx->testLog) {
printf("%s[%d:%d] Step %d write output file\n", TAG, getpid(), gettid(), step++);
}
if (ctx->delaytest) {
decFinishTime = osal_gettime();
if ((decFinishTime - decStartTime) >= ctx->delaytime) {
printf("%s[%d:%d] Decoding time is %d, more than %dms\n",
TAG, getpid(), gettid(), (decFinishTime - decStartTime), ctx->delaytime);
ASSERT_LE((decFinishTime - decStartTime), ctx->delaytime);
}
}
ASSERT_EQ(write_output_frames(ctx, &outputBuffer), 0);
if (ctx->testLog) {
printf("%s[%d:%d] Step %d queue output\n", TAG, getpid(), gettid(), step++);
}
ASSERT_EQ(do_decode_params_checking(ctx, &outputBuffer), 0);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
EXPECT_EQ(ret, (int32_t)0);
if (outputBuffer.vframe_buf.frame_end) {
printf("%s[%d:%d] There is no more output data!\n", TAG, getpid(), gettid());
ctx->lastFrame = 1;
break;
}
if (ret) {
break;
}
} else {
char info[256];
hb_mm_strerror(ret, info, 256);
printf("%s[%d:%d] dequeue output buffer fail.(%s)\n", TAG, getpid(), gettid(), info);
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
EXPECT_EQ(ret, (int32_t)0);
break;
}
if (ctx->stabilityTest && ctx->lastStream ==1) {
break;
}
}
}
}while(TRUE);
ret = hb_mm_mc_stop(context);
EXPECT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_release(context);
EXPECT_EQ(ret, (int32_t)0);
ASSERT_EQ(check_and_release_test(ctx), 0);
}
int main(int argc, char *argv[])
{
char outputFileName[MAX_FILE_PATH] = "input.h265";
char inputFileName[MAX_FILE_PATH] = "output.yuv";
mTestWidth = 640;
mTestHeight = 480;
mTestPixFmt = MC_PIXEL_FORMAT_YUV420P;
mTestFeedMode = MC_FEEDING_MODE_FRAME_SIZE;
mTestCodec = TEST_CODEC_ID_H265;
mc_video_codec_dec_params_t *params;
media_codec_context_t *context = (media_codec_context_t *)malloc(sizeof(media_codec_context_t ));
ASSERT_NE(context, nullptr);
memset(context, 0x00, sizeof(media_codec_context_t));
context->codec_id = get_codec_id(mTestCodec);
context->encoder = FALSE;
params = &context->video_dec_params;
params->feed_mode = mTestFeedMode;
params->pix_fmt = mTestPixFmt;
params->bitstream_buf_size = mTestWidth * mTestHeight * 3 / 2;
params->bitstream_buf_count = 6;
params->frame_buf_count = 8;
if (context->codec_id == MEDIA_CODEC_ID_H265) {
params->h265_dec_config.bandwidth_Opt = TRUE;
params->h265_dec_config.reorder_enable = TRUE;
params->h265_dec_config.skip_mode = 0;
params->h265_dec_config.cra_as_bla = FALSE;
params->h265_dec_config.dec_temporal_id_mode = 0;
params->h265_dec_config.target_dec_temporal_id_plus1 = 0;
}
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
char inputMd5FileName[MAX_FILE_PATH];
if (ctx.md5Test) {
char inputMd5Suffix[MAX_FILE_PATH] = ".md5";
snprintf(dedicatedSuffix, MAX_FILE_PATH, "%s", "dec");
snprintf(inputMd5FileName, MAX_FILE_PATH, "%s%s_%s_%s%s",
dedicatedInputPrefix, mGlobalPixFmtName[mTestPixFmt],
dedicatedSuffix, mGlobalCodecName[mTestCodec], inputMd5Suffix);
ctx.inputMd5FileName = inputMd5FileName;
}
do_sync_decoding(&ctx);
if (context != NULL) {
free(context);
}
}
5.12.4.48. hb_mm_mc_release_user_data
【函数声明】
hb_s32 hb_mm_mc_release_user_data(media_codec_context_t * context,
const mc_user_data_buffer_t * params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_user_data_buffer_t * params: 用户数据
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
释放解码流中的用户数据,适用于 H264/H265 。
【示例代码】
5.12.4.49. hb_mm_mc_get_mjpeg_config
【函数声明】
hb_s32 hb_mm_mc_get_mjpeg_config(media_codec_context_t *context,
mc_mjpeg_enc_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_mjpeg_enc_params_t *params: MJPEG 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 MJPEG 编码参数,适用于 MJPEG。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
int main(int argc, char *argv[])
{
int ret = 0;
char outputFileName[MAX_FILE_PATH];
char inputFileName[MAX_FILE_PATH];
mTestCodec = TEST_CODEC_ID_MJPEG;
mTestPixFmt = MC_PIXEL_FORMAT_NV12;
char dedicatedSuffix[MAX_FILE_PATH] = "_test";
char inputSuffix[MAX_FILE_PATH] = ".yuv";
char outputSuffixJpeg[MAX_FILE_PATH] = ".jpg";
char outputSuffixMjpg[MAX_FILE_PATH] = ".mjpg";
snprintf(inputFileName, MAX_FILE_PATH, "%s%s%s",
mInputSpecPrefix, mTest12Bit ? mGlobal12BPixFmtName[mTestPixFmt]
: mGlobalPixFmtName[mTestPixFmt], inputSuffix);
snprintf(outputFileName, MAX_FILE_PATH, "%s%s%s%s",
mOutputSpecPrefix, mTest12Bit ? mGlobal12BPixFmtName[mTestPixFmt]
: mGlobalPixFmtName[mTestPixFmt], dedicatedSuffix,
mTestCodec == TEST_CODEC_ID_JPEG ? outputSuffixJpeg : outputSuffixMjpg);
mc_video_codec_enc_params_t *params;
media_codec_context_t *context = (media_codec_context_t *)malloc(sizeof(media_codec_context_t ));
ASSERT_NE(context, nullptr);
memset(context, 0x00, sizeof(media_codec_context_t));
context->codec_id = mTestCodec == TEST_CODEC_ID_JPEG ?
MEDIA_CODEC_ID_JPEG : MEDIA_CODEC_ID_MJPEG;
context->encoder = TRUE;
params = &context->video_enc_params;
params->width = mTestWidth;
params->height = mTestHeight;
params->pix_fmt = mTestPixFmt;
params->frame_buf_count = 5;
params->bitstream_buf_count = 5;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
params->external_frame_buf = FALSE;
if (context->codec_id == MEDIA_CODEC_ID_MJPEG) {
params->rc_params.mode = MC_AV_RC_MODE_MJPEGFIXQP;
ret = hb_mm_mc_get_rate_control_config(context, ¶ms->rc_params);
ASSERT_EQ(ret, (int32_t)0);
params->mjpeg_enc_config.restart_interval = mTestWidth/16;
params->mjpeg_enc_config.extended_sequential = mTest12Bit;
} else {
params->jpeg_enc_config.restart_interval = mTestWidth/16;
params->jpeg_enc_config.extended_sequential = mTest12Bit;
}
mc_mjpeg_enc_params_t mjpeg_params;
memset(&mjpeg_params, 0x00, sizeof(mjpeg_params));
ret = hb_mm_mc_get_mjpeg_config(context, &mjpeg_params);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_initialize(context);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_set_mjpeg_config(context, &mjpeg_params);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_stop(context);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_release(context);
ASSERT_EQ(ret, (int32_t)0);
if (context != NULL) {
free(context);
}
}
5.12.4.50. hb_mm_mc_set_mjpeg_config
【函数声明】
hb_s32 hb_mm_mc_set_mjpeg_config(media_codec_context_t *context, const
mc_mjpeg_enc_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_mjpeg_enc_params_t *params: MJPEG 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 MJPEG 编码参数,该参数为动态参数,适用于 MJPEG。
【示例代码】
5.12.4.51. hb_mm_mc_get_jpeg_config
【函数声明】
hb_s32 hb_mm_mc_get_jpeg_config(media_codec_context_t *context,
mc_jpeg_enc_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_jpeg_enc_params_t *params: JPEG 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 JPEG 编码参数,适用于 JPEG。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
int main(int argc, char *argv[])
{
int ret = 0;
char outputFileName[MAX_FILE_PATH];
char inputFileName[MAX_FILE_PATH];
mTestCodec = TEST_CODEC_ID_JPEG;
mTestPixFmt = MC_PIXEL_FORMAT_NV12;
char dedicatedSuffix[MAX_FILE_PATH] = "_test";
char inputSuffix[MAX_FILE_PATH] = ".yuv";
char outputSuffixJpeg[MAX_FILE_PATH] = ".jpg";
char outputSuffixMjpg[MAX_FILE_PATH] = ".mjpg";
snprintf(inputFileName, MAX_FILE_PATH, "%s%s%s",
mInputSpecPrefix, mTest12Bit ? mGlobal12BPixFmtName[mTestPixFmt]
: mGlobalPixFmtName[mTestPixFmt], inputSuffix);
snprintf(outputFileName, MAX_FILE_PATH, "%s%s%s%s",
mOutputSpecPrefix, mTest12Bit ? mGlobal12BPixFmtName[mTestPixFmt]
: mGlobalPixFmtName[mTestPixFmt], dedicatedSuffix,
mTestCodec == TEST_CODEC_ID_JPEG ? outputSuffixJpeg : outputSuffixMjpg);
mc_video_codec_enc_params_t *params;
media_codec_context_t *context = (media_codec_context_t *)malloc(sizeof(media_codec_context_t ));
ASSERT_NE(context, nullptr);
memset(context, 0x00, sizeof(media_codec_context_t));
context->codec_id = mTestCodec == TEST_CODEC_ID_JPEG ?
MEDIA_CODEC_ID_JPEG : MEDIA_CODEC_ID_MJPEG;
context->encoder = TRUE;
params = &context->video_enc_params;
params->width = mTestWidth;
params->height = mTestHeight;
params->pix_fmt = mTestPixFmt;
params->frame_buf_count = 5;
params->bitstream_buf_count = 5;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
params->external_frame_buf = FALSE;
if (context->codec_id == MEDIA_CODEC_ID_MJPEG) {
params->rc_params.mode = MC_AV_RC_MODE_MJPEGFIXQP;
ret = hb_mm_mc_get_rate_control_config(context, ¶ms->rc_params);
ASSERT_EQ(ret, (int32_t)0);
params->mjpeg_enc_config.restart_interval = mTestWidth/16;
params->mjpeg_enc_config.extended_sequential = mTest12Bit;
} else {
params->jpeg_enc_config.restart_interval = mTestWidth/16;
params->jpeg_enc_config.extended_sequential = mTest12Bit;
}
mc_jpeg_enc_params_t jpeg_params;
memset(&jpeg_params, 0x00, sizeof(jpeg_params));
ret = hb_mm_mc_get_jpeg_config(context, &jpeg_params);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_initialize(context);
ASSERT_EQ(ret, (int32_t)0);
jpeg_params.quality_factor = 30;
jpeg_params.restart_interval = (((params->width+15)>>4) *
((params->height+15)>>4) * 2) + 1;
jpeg_params.crop_en = FALSE;
ret = hb_mm_mc_set_jpeg_config(context, &jpeg_params);
ASSERT_EQ(ret, (int32_t)HB_MEDIA_ERR_INVALID_PARAMS);
jpeg_params.restart_interval = 70;
ret = hb_mm_mc_set_jpeg_config(context, &jpeg_params);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_stop(context);
ASSERT_EQ(ret, (int32_t)0);
ret = hb_mm_mc_release(context);
ASSERT_EQ(ret, (int32_t)0);
if (context != NULL) {
free(context);
}
}
5.12.4.52. hb_mm_mc_set_jpeg_config
【函数声明】
hb_s32 hb_mm_mc_set_jpeg_config(media_codec_context_t *context, const
mc_jpeg_enc_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_jpeg_enc_params_t *params: JPEG 编码参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 JPEG 编码参数,该参数为动态参数,适用于 JPEG。
【示例代码】
5.12.4.53. hb_mm_mc_get_fd
【函数声明】
hb_s32 hb_mm_mc_get_fd(media_codec_context_t * context, hb_s32 *fd)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] hb_s32 *fd:设备节点 fd
【返回值】
0 :操作成功
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取设备节点 fd,可用于 select 操作,监听编解码结果。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
int abnormal;
int32_t duration; // s
} MediaCodecTestContext;
Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
static void do_poll_encoding_select(void *arg) {
hb_s32 ret = 0;
int pollFd = -1;
FILE *outFile;
int lastStream = 0;
fd_set readFds;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *outputFileName = ctx->outputFileName;
mc_inter_status_t status;
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
ret = hb_mm_mc_get_fd(context, &pollFd);
if (ret) {
goto ERR;
}
do {
FD_ZERO(&readFds);
FD_SET(pollFd, &readFds);
ret = select(pollFd+1, &readFds, NULL, NULL, NULL);
if (ret < 0) {
printf("Failed to select fd = %d.(err %s)\n", pollFd, strerror(errno));
ctx->abnormal = TRUE;
break;
} else if (ret == 0) {
printf("Time out to select fd = %d.\n", pollFd);
ctx->abnormal = TRUE;
break;
} else {
if (FD_ISSET(pollFd, &readFds)) {
ASSERT_EQ(hb_mm_mc_get_status(context, &status), (int32_t)0);
if (ctx->testLog) {
printf("%s[%d:%d] output count %d input count %d\n", TAG, getpid(), gettid(),
status.cur_output_buf_cnt, status.cur_input_buf_cnt);
}
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info, 100);
if (!ret && outFile) {
fwrite(outputBuffer.vstream_buf.vir_ptr, outputBuffer.vstream_buf.size, 1, outFile);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
if (outputBuffer.vstream_buf.stream_end) {
printf("%There is no more output data!\n");
lastStream = 1;
break;
}
if (ret) {
ctx->abnormal = TRUE;
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue output buffer fail.\n");
break;
}
}
}
}
} while (!lastStream && !ctx->abnormal);
ERR:
if (pollFd) {
hb_mm_mc_close_fd(context, pollFd);
}
if (outFile)
fclose(outFile);
}
static void do_poll_encoding(void *arg) {
pthread_t thread_id;
void* retVal;
hb_s32 ret = 0;
FILE *inFile;
int noMoreInput = 0;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
pthread_create(&thread_id, NULL, (void* (*)(void*))do_poll_encoding_select, ctx);
do {
media_codec_buffer_t inputBuffer;
memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 100);
if (!ret) {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (!ret) {
printf("There is no more input data!\n");
inputBuffer.vframe_buf.frame_end = TRUE;
noMoreInput = 1;
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
if (ret) {
printf("Queue input buffer fail.\n");
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue input buffer fail.\n");
break;
}
}
}while(!noMoreInput && !ctx->abnormal);
pthread_join(thread_id, &retVal);
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state != MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
}
int main(int argc, char *argv[])
{
hb_s32 ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.stream";
mc_video_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = TRUE;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = FALSE;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
ctx.duration = 5;
do_poll_encoding(&ctx);
}
5.12.4.54. hb_mm_mc_close_fd
【函数声明】
hb_s32 hb_mm_mc_close_fd(media_codec_context_t * context, hb_s32 fd)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_s32 fd:设备节点 fd
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
关闭设备节点。
【示例代码】
参考 :hb_mm_mc_get_fd
5.12.4.55. hb_mm_mc_get_vui_config
【函数声明】
hb_s32 hb_mm_mc_get_vui_config(media_codec_context_t *context,
mc_video_vui_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] mc_video_vui_ params_t *params: VUI 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 VUI 参数。
【其它说明】
目前 video 编码时设置头信息中的默认 color range 为 full range 模式,如果设置 limit range 需要显式调用 hb_mm_mc_set_vui_config 接口。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
typedef enum ENC_CONFIG_MESSAGE {
ENC_CONFIG_NONE = (0 << 0),
ENC_CONFIG_LONGTERM_REF = (1 << 0),
ENC_CONFIG_INTRA_REFRESH = (1 << 1),
ENC_CONFIG_RATE_CONTROL = (1 << 2),
ENC_CONFIG_DEBLK_FILTER = (1 << 3),
ENC_CONFIG_SAO = (1 << 4),
ENC_CONFIG_ENTROPY = (1 << 5),
ENC_CONFIG_VUI_TIMING = (1 << 6),
ENC_CONFIG_SLICE = (1 << 7),
ENC_CONFIG_REQUEST_IDR = (1 << 8),
ENC_CONFIG_SKIP_PIC = (1 << 9),
ENC_CONFIG_SMART_BG = (1 << 10),
ENC_CONFIG_MONOCHROMA = (1 << 11),
ENC_CONFIG_PRED_UNIT = (1 << 12),
ENC_CONFIG_TRANSFORM = (1 << 13),
ENC_CONFIG_ROI = (1 << 14),
ENC_CONFIG_MODE_DECISION = (1 << 15),
ENC_CONFIG_USER_DATA = (1 << 16),
ENC_CONFIG_MJPEG = (1 << 17),
ENC_CONFIG_JPEG = (1 << 18),
ENC_CONFIG_CAMERA = (1 << 19),
ENC_CONFIG_INSERT_USERDATA = (1 << 20),
ENC_CONFIG_VUI = (1 << 21),
ENC_CONFIG_3DNR = (1 << 22),
ENC_CONFIG_REQUEST_IDR_HEADER = (1 << 23),
ENC_CONFIG_ENABLE_IDR = (1 << 24),
ENC_CONFIG_TOTAL = (1 << 25),
} ENC_CONFIG_MESSAGE;
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
int32_t duration; // s
ENC_CONFIG_MESSAGE message;
mc_video_longterm_ref_mode_t ref_mode;
mc_rate_control_params_t rc_params;
mc_video_intra_refresh_params_t intra_refr;
mc_video_deblk_filter_params_t deblk_filter;
mc_h265_sao_params_t sao;
mc_h264_entropy_params_t entropy;
mc_video_vui_params_t vui;
mc_video_vui_timing_params_t vui_timing;
mc_video_slice_params_t slice;
mc_video_3dnr_enc_params_t noise_reduction;
mc_video_smart_bg_enc_params_t smart_bg;
mc_video_pred_unit_params_t pred_unit;
mc_video_transform_params_t transform;
mc_video_roi_params_t roi;
mc_video_mode_decision_params_t mode_decision;
} MediaCodecTestContext;
Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
uint8_t uuid[] =
"dc45e9bd-e6d948b7-962cd820-d923eeef+HorizonAI";
static void set_message(MediaCodecTestContext *ctx) {
int ret = 0;
media_codec_context_t *context = ctx->context;
if (ctx->message & ENC_CONFIG_VUI) {
hb_mm_mc_get_vui_config(context, &ctx->vui);
ret = hb_mm_mc_set_vui_config(context, &ctx->vui);
}
}
static void do_sync_encoding(void *arg) {
hb_s32 ret = 0;
FILE *inFile;
FILE *outFile;
int noMoreInput = 0;
int lastStream = 0;
Uint64 lastTime = 0;
Uint64 curTime = 0;
int needFlush = 1;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
//get current time
lastTime = osal_gettime();
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_pause(context);
if (ret) {
goto ERR;
}
do {
set_message(ctx);
if (!noMoreInput) {
media_codec_buffer_t inputBuffer;
memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 100);
if (!ret) {
curTime = osal_gettime();
if ((curTime - lastTime)/1000 < (uint32_t)ctx->duration) {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
if(fseek(inFile, 0, SEEK_SET)) {
printf("Failed to rewind input filen");
} else {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
printf("Failed to read input filen");
}
}
}
} else {
printf("Time up(%d)n",ctx->duration);
ret = 0;
}
if (!ret) {
printf("There is no more input data!n");
inputBuffer.vframe_buf.frame_end = TRUE;
noMoreInput = 1;
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
if (ret) {
printf("Queue input buffer fail.n");
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue input buffer fail.n");
break;
}
}
}
if (!lastStream) {
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info,
3000);
if (!ret && outFile) {
fwrite(outputBuffer.vstream_buf.vir_ptr,
outputBuffer.vstream_buf.size, 1, outFile);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
if (ret) {
printf("Queue output buffer fail.n");
break;
}
if (outputBuffer.vstream_buf.stream_end) {
printf("There is no more output data!n");
lastStream = 1;
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue output buffer fail.n");
break;
}
}
}
if (needFlush) {
ret = hb_mm_mc_flush(context);
needFlush = 0;
if (ret) {
break;
}
}
}while(TRUE);
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state!=
MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
if (outFile)
fclose(outFile);
}
int main(int argc, char *argv[])
{
hb_s32 ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.stream";
mc_video_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = TRUE;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = FALSE;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
mc_video_vui_params_t *vui = &ctx.vui;
ret = hb_mm_mc_get_vui_config(context, vui);
if (ret != 0) {
return -1;
}
vui->h265_vui.video_signal_type_present_flag = 1;
vui->h265_vui.video_format = 0;
vui->h265_vui.video_full_range_flag = 0;
ctx.message = ENC_CONFIG_VUI;
do_sync_encoding(&ctx);
}
5.12.4.56. hb_mm_mc_set_vui_config
【函数声明】
hb_s32 hb_mm_mc_set_vui_config(media_codec_context_t *context, const
mc_video_vui_params_t *params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_vui_params_t *params: VUI 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 VUI 参数,该参数为静态参数。
【示例代码】
5.12.4.57. hb_mm_mc_get_3dnr_enc_config
【函数声明】
hb_s32 hb_mm_mc_get_3dnr_enc_config(media_codec_context_t *context, mc_video_3dnr_enc_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] mc_video_3dnr_enc_params_t *params: 3DNR 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 3DNR 参数,该参数为动态参数,适用于 H265.
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
typedef enum ENC_CONFIG_MESSAGE {
ENC_CONFIG_NONE = (0 << 0),
ENC_CONFIG_LONGTERM_REF = (1 << 0),
ENC_CONFIG_INTRA_REFRESH = (1 << 1),
ENC_CONFIG_RATE_CONTROL = (1 << 2),
ENC_CONFIG_DEBLK_FILTER = (1 << 3),
ENC_CONFIG_SAO = (1 << 4),
ENC_CONFIG_ENTROPY = (1 << 5),
ENC_CONFIG_VUI_TIMING = (1 << 6),
ENC_CONFIG_SLICE = (1 << 7),
ENC_CONFIG_REQUEST_IDR = (1 << 8),
ENC_CONFIG_SKIP_PIC = (1 << 9),
ENC_CONFIG_SMART_BG = (1 << 10),
ENC_CONFIG_MONOCHROMA = (1 << 11),
ENC_CONFIG_PRED_UNIT = (1 << 12),
ENC_CONFIG_TRANSFORM = (1 << 13),
ENC_CONFIG_ROI = (1 << 14),
ENC_CONFIG_MODE_DECISION = (1 << 15),
ENC_CONFIG_USER_DATA = (1 << 16),
ENC_CONFIG_MJPEG = (1 << 17),
ENC_CONFIG_JPEG = (1 << 18),
ENC_CONFIG_CAMERA = (1 << 19),
ENC_CONFIG_INSERT_USERDATA = (1 << 20),
ENC_CONFIG_VUI = (1 << 21),
ENC_CONFIG_3DNR = (1 << 22),
ENC_CONFIG_REQUEST_IDR_HEADER = (1 << 23),
ENC_CONFIG_ENABLE_IDR = (1 << 24),
ENC_CONFIG_TOTAL = (1 << 25),
} ENC_CONFIG_MESSAGE;
typedef struct MediaCodecTestContext {
media_codec_context_t *context;
char *inputFileName;
char *outputFileName;
int32_t duration; // s
ENC_CONFIG_MESSAGE message;
mc_video_longterm_ref_mode_t ref_mode;
mc_rate_control_params_t rc_params;
mc_video_intra_refresh_params_t intra_refr;
mc_video_deblk_filter_params_t deblk_filter;
mc_h265_sao_params_t sao;
mc_h264_entropy_params_t entropy;
mc_video_vui_params_t vui;
mc_video_vui_timing_params_t vui_timing;
mc_video_slice_params_t slice;
mc_video_3dnr_enc_params_t noise_reduction;
mc_video_smart_bg_enc_params_t smart_bg;
mc_video_pred_unit_params_t pred_unit;
mc_video_transform_params_t transform;
mc_video_roi_params_t roi;
mc_video_mode_decision_params_t mode_decision;
} MediaCodecTestContext;
Uint64 osal_gettime(void)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return ((Uint64)tp.tv_sec*1000 + tp.tv_nsec/1000000);
}
uint8_t uuid[] =
"dc45e9bd-e6d948b7-962cd820-d923eeef+HorizonAI";
static void set_message(MediaCodecTestContext *ctx) {
int ret = 0;
media_codec_context_t *context = ctx->context;
if (ctx->message & ENC_CONFIG_VUI) {
hb_mm_mc_get_vui_config(context, &ctx->vui);
ret = hb_mm_mc_set_vui_config(context, &ctx->vui);
}
}
static void do_sync_encoding(void *arg) {
hb_s32 ret = 0;
FILE *inFile;
FILE *outFile;
int noMoreInput = 0;
int lastStream = 0;
Uint64 lastTime = 0;
Uint64 curTime = 0;
int needFlush = 1;
MediaCodecTestContext *ctx = (MediaCodecTestContext *)arg;
media_codec_context_t *context = ctx->context;
char *inputFileName = ctx->inputFileName;
char *outputFileName = ctx->outputFileName;
media_codec_state_t state = MEDIA_CODEC_STATE_NONE;
inFile = fopen(inputFileName, "rb");
if (!inFile) {
goto ERR;
}
outFile = fopen(outputFileName, "wb");
if (!outFile) {
goto ERR;
}
//get current time
lastTime = osal_gettime();
ret = hb_mm_mc_initialize(context);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_configure(context);
if (ret) {
goto ERR;
}
mc_av_codec_startup_params_t startup_params;
startup_params.video_enc_startup_params.receive_frame_number = 0;
ret = hb_mm_mc_start(context, &startup_params);
if (ret) {
goto ERR;
}
ret = hb_mm_mc_pause(context);
if (ret) {
goto ERR;
}
do {
set_message(ctx);
if (!noMoreInput) {
media_codec_buffer_t inputBuffer;
memset(&inputBuffer, 0x00, sizeof(media_codec_buffer_t));
ret = hb_mm_mc_dequeue_input_buffer(context, &inputBuffer, 100);
if (!ret) {
curTime = osal_gettime();
if ((curTime - lastTime)/1000 < (uint32_t)ctx->duration) {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
if(fseek(inFile, 0, SEEK_SET)) {
printf("Failed to rewind input filen");
} else {
ret = fread(inputBuffer.vframe_buf.vir_ptr[0], 1,
inputBuffer.vframe_buf.size, inFile);
if (ret <= 0) {
printf("Failed to read input filen");
}
}
}
} else {
printf("Time up(%d)n",ctx->duration);
ret = 0;
}
if (!ret) {
printf("There is no more input data!n");
inputBuffer.vframe_buf.frame_end = TRUE;
noMoreInput = 1;
}
ret = hb_mm_mc_queue_input_buffer(context, &inputBuffer, 100);
if (ret) {
printf("Queue input buffer fail.n");
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue input buffer fail.n");
break;
}
}
}
if (!lastStream) {
media_codec_buffer_t outputBuffer;
media_codec_output_buffer_info_t info;
memset(&outputBuffer, 0x00, sizeof(media_codec_buffer_t));
memset(&info, 0x00, sizeof(media_codec_output_buffer_info_t));
ret = hb_mm_mc_dequeue_output_buffer(context, &outputBuffer, &info,
3000);
if (!ret && outFile) {
fwrite(outputBuffer.vstream_buf.vir_ptr,
outputBuffer.vstream_buf.size, 1, outFile);
ret = hb_mm_mc_queue_output_buffer(context, &outputBuffer, 100);
if (ret) {
printf("Queue output buffer fail.n");
break;
}
if (outputBuffer.vstream_buf.stream_end) {
printf("There is no more output data!n");
lastStream = 1;
break;
}
} else {
if (ret != (int32_t)HB_MEDIA_ERR_WAIT_TIMEOUT) {
printf("Dequeue output buffer fail.n");
break;
}
}
}
if (needFlush) {
ret = hb_mm_mc_flush(context);
needFlush = 0;
if (ret) {
break;
}
}
}while(TRUE);
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
context = NULL;
ERR:
hb_mm_mc_get_state(context, &state);
if (context && state!=
MEDIA_CODEC_STATE_UNINITIALIZED) {
hb_mm_mc_stop(context);
hb_mm_mc_release(context);
}
if (inFile)
fclose(inFile);
if (outFile)
fclose(outFile);
}
int main(int argc, char *argv[])
{
hb_s32 ret = 0;
char outputFileName[MAX_FILE_PATH] = "./tmp.yuv";
char inputFileName[MAX_FILE_PATH] = "./output.stream";
mc_video_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_H265;
context.encoder = TRUE;
params = &context.video_enc_params;
params->width = 640;
params->height = 480;
params->pix_fmt = MC_PIXEL_FORMAT_YUV420P;
params->frame_buf_count = 5;
params->external_frame_buf = FALSE;
params->bitstream_buf_count = 5;
params->rc_params.mode = MC_AV_RC_MODE_H265CBR;
ret = hb_mm_mc_get_rate_control_config(&context, ¶ms->rc_params);
if (ret) {
return -1;
}
params->rc_params.h265_cbr_params.bit_rate = 5000;
params->rc_params.h265_cbr_params.frame_rate = 30;
params->rc_params.h265_cbr_params.intra_period = 30;
params->gop_params.decoding_refresh_type = 2;
params->gop_params.gop_preset_idx = 9;
params->rot_degree = MC_CCW_0;
params->mir_direction = MC_DIRECTION_NONE;
params->frame_cropping_flag = FALSE;
MediaCodecTestContext ctx;
memset(&ctx, 0x00, sizeof(ctx));
ctx.context = &context;
ctx.inputFileName = inputFileName;
ctx.outputFileName = outputFileName;
mc_video_3dnr_enc_params_t *noise_rd = &ctx.noise_reduction;
ret = hb_mm_mc_get_3dnr_enc_config(context, noise_rd);
noise_rd->nr_y_enable = 0;
noise_rd->nr_cb_enable = 0;
noise_rd->nr_cr_enable = 0;
noise_rd->nr_est_enable = 0;
ctx.message = ENC_CONFIG_3DNR;
do_sync_encoding(&ctx);
}
5.12.4.58. hb_mm_mc_set_3dnr_enc_config
【函数声明】
hb_s32 hb_mm_mc_set_3dnr_enc_config(media_codec_context_t *context, const mc_video_3dnr_enc_params_t *params);
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] const mc_video_3dnr_enc_params_t *params: 3DNR 参数
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 3DNR 参数,该参数为动态参数,适用于 H265 。
【示例代码】
参考 :hb_mm_mc_get_3dnr_enc_config
5.12.4.59. hb_mm_mc_request_idr_header
【函数声明】
hb_s32 hb_mm_mc_request_idr_header(media_codec_context_t *context,
hb_u32 force_header)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_u32 force_header:
0 : No froced header(VPS/SPS/PPS)
1 : Forced header before IDR frame
2 : Forced header before I frame for H264 or forced header before CRA and IDR frame for H265
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
请求帧头 IDR 帧头信息,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.60. hb_mm_mc_enable_idr_frame
【函数声明】
hb_s32 hb_mm_mc_enable_idr_frame(media_codec_context_t *context,
hb_bool enable)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_bool enable: 0 :不使能; 1 :使能;
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
使能 IDR 帧,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.61. hb_mm_mc_register_audio_encoder
【函数声明】
hb_s32 hb_mm_mc_register_audio_encoder(hb_s32 *handle,
mc_audio_encode_param_t *encoder)
【参数描述】
[IN] hb_s32 *handle:编码器句柄
[IN] mc_audio_encode_param_t *encoder: audio 编码器描述符;
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
注册 audio 编码器,适用于 Audio。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
#include "include/aac.h"
int main(int argc, char *argv[])
{
mc_audio_codec_enc_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_AAC;
context.encoder = TRUE;
params = &context.audio_enc_params;
params->bit_rate = 128000;
params->frame_buf_count = 5;
params->packet_count = 5;
params->sample_fmt = MC_AV_SAMPLE_FMT_S16;
params->sample_rate = MC_AV_SAMPLE_RATE_16000;
params->channel_layout = MC_AV_CHANNEL_LAYOUT_STEREO;
params->channels = 2;
mc_aac_enc_config_t config;
config.profile = MC_AAC_PROFILE_LOW;
config.type = MC_AAC_DATA_TYPE_ADTS;
params->enc_config = &config;
int ret;
int handle;
mc_audio_encode_param_t encoder;
encoder.ff_type = MEDIA_CODEC_ID_AAC;
snprintf(encoder.ff_codec_name, sizeof(encoder.ff_codec_name), "aacenc");
encoder.ff_audio_open_encoder = ff_audio_aac_open_encoder;
encoder.ff_audio_encode_frame = ff_audio_aac_encode_frm;
encoder.ff_audio_close_encoder = ff_audio_aac_close_encoder;
ret = hb_mm_mc_register_audio_encoder(&handle, &encoder);
printf("handle = %d\n", handle);
ASSERT_EQ(ret, 0);
ret = hb_mm_mc_unregister_audio_encoder(handle);
ASSERT_EQ(ret, 0);
}
5.12.4.62. hb_mm_mc_unregister_audio_encoder
【函数声明】
hb_s32 hb_mm_mc_unregister_audio_encoder(hb_s32 handle)
【参数描述】
[IN] hb_s32 *handle:编码器句柄
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
注销 audio 编码器,适用于 Audio。
【示例代码】
参考 :hb_mm_mc_register_audio_encoder
5.12.4.63. hb_mm_mc_register_audio_decoder
【函数声明】
hb_s32 hb_mm_mc_register_audio_decoder(hb_s32 *handle,
mc_audio_decode_param_t *decoder)
【参数描述】
[IN] hb_s32 *handle:解码器句柄
[IN] mc_audio_decode_param_t *decoder: audio 解码器描述符;
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
注册 audio 解码器,适用于 Audio。
【示例代码】
#include "hb_media_codec.h"
#include "hb_media_error.h"
#include "include/aac.h"
int main(int argc, char *argv[])
{
mc_audio_codec_dec_params_t *params;
media_codec_context_t context;
memset(&context, 0x00, sizeof(media_codec_context_t));
context.codec_id = MEDIA_CODEC_ID_AAC;
context.encoder = FALSE;
params = &context.audio_dec_params;
params->feed_mode = MC_FEEDING_MODE_FRAME_SIZE;
params->packet_buf_size = 1024;
params->packet_count = 5;
params->frame_cache_size = 5;
params->frame_buf_count = 5;
mc_aac_dec_config_t config;
config.sample_rate = MC_AV_SAMPLE_RATE_8000;
config.channels = 1;
config.sample_fmt = MC_AV_SAMPLE_FMT_S16;
params->dec_config = &config;
mc_audio_decode_param_t decoder;
decoder.ff_type = MEDIA_CODEC_ID_AAC;
snprintf(decoder.ff_codec_name, sizeof(decoder.ff_codec_name), "aacdec");
decoder.ff_audio_open_decoder = ff_audio_aac_open_decoder;
decoder.ff_audio_decode_frame = ff_audio_aac_decode_frm;
decoder.ff_audio_close_decoder = ff_audio_aac_close_decoder;
ret = hb_mm_mc_register_audio_decoder(&handle, &decoder);
ASSERT_EQ(ret, 0);
ret = hb_mm_mc_unregister_audio_decoder(handle);
ASSERT_EQ(ret, 0);
}
5.12.4.64. hb_mm_mc_unregister_audio_decoder
【函数声明】
hb_s32 hb_mm_mc_unregister_audio_decoder(hb_s32 handle)
【参数描述】
[IN] hb_s32 *handle:解码器句柄;
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
注销 audio 解码器,适用于 Audio。
【示例代码】
参考 :hb_mm_mc_register_audio_decoder
5.12.4.65. hb_mm_mc_get_explicit_header_config
【函数声明】
hb_s32 hb_mm_mc_get_explicit_header_config (media_codec_context_t
*context, hb_s32 *status)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] hb_s32 *status:是否使能该功能 ( 头信息和 IDR 帧编码成一帧 )
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取头信息和 IDR 帧是否编码成一帧的配置, 0 : IDR 和头信息独立, 1 : IDR 和头信息合成一帧,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.66. hb_mm_mc_set_explicit_header_config
【函数声明】
hb_s32 hb_mm_mc_set_explicit_header_config (media_codec_context_t
*context, hb_s32 status)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_s32 status:使能 / 不使能头信息和 IDR 帧编码成一帧
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
使能 / 不使能头信息和 I 帧编码成一帧,该参数为静态参数, 0 : IDR 和头信息独立, 1 : IDR 和头信息合成一帧,适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.67. hb_mm_mc_get_roi_avg_qp
【函数声明】
hb_s32 hb_mm_mc_get_roi_avg_qp(media_codec_context_t * context, hb_u32
* params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[OUT] hb_u32 *params: ROI 平均 QP
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
获取 ROI 平均 QP 值 , 适用于 H264/H265 。
【示例代码】
参考 :hb_mm_mc_get_longterm_ref_mode
5.12.4.68. hb_mm_mc_set_roi_avg_qp
【函数声明】
hb_s32 hb_mm_mc_set_roi_avg_qp(media_codec_context_t * context, hb_u32
params)
【参数描述】
[IN] media_codec_context_t *context:指定 codec 类型的 context
[IN] hb_u32 params: ROI 平均 QP 值 [0 - 51]
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
设置 ROI 编码平均 QP 值,该参数为动态参数,表示使用设置的 QPMap 中所有值的平均值,该值在 RC 模式为 CBR 或者 AVBR 时才能使编码效果生效,适用于 H264/H265 。
【示例代码】
5.12.5. MediaMuxer 接口说明
MediaMuxer 模块主要用于封装编码后的视频流和音频流到 MP4 容器中。本模块会介绍一系列接口用于支持音视频轨道添加和数据流的填充。用户可向 MediaMuxer 添加音频或视频轨道,然后填充音频或视频流, MediaMuxer 就可以将原始流混合到 MP4 文件中。如下表所示为 MediaMuxer 所支持的格式。
| Module | 音频流格式 | 轨道数 | 视频流格式 | 轨道数 | 输出格式 |
|---|---|---|---|---|---|
| MediaMuxer | FLAC/AAC | 1 | H264/H265 | 1 | MP4 |
5.12.5.1. hb_mm_mx_get_default_context
【函数声明】
hb_s32 hb_mm_mx_get_default_context(media_muxer_context_t *context)
【参数描述】
[OUT] media_codec_context_t *context:默认的 muxer context
【返回值】
0 :操作成功
HB_MEDIA_ERR_INVALID_PARAMS: 参数非法
【功能描述】
获得默认的上下文参数值。
【示例代码】
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <libavformat/avformat.h>
#include <libavutil/timestamp.h>
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "hb_media_codec.h"
#include "hb_media_error.h"
#include "hb_media_muxer.h"
int main(int argc, char *argv[])
{
int ret = 0;
char inputAudioFileName[256] = "./tmp.h265";
char inputVideoFileName[256] = "./input.aac";
char outputFileName[256] = "./output.mp4";
int doAudioExit = 0, doVideoExit = 0;
media_muxer_context_t muxerCtx;
memset(&muxerCtx, 0x00, sizeof(media_muxer_context_t));
ret = hb_mm_mx_get_default_context(&muxerCtx);
if (ret) {
return -1;
}
muxerCtx.output_file_name = outputFileName;
media_muxer_state_t state = MEDIA_MUXER_STATE_NONE;
hb_mm_mx_get_state(&muxerCtx, &state);
mx_stream_params_t videoStream;
memset(&videoStream, 0x00, sizeof(mx_stream_params_t));
videoStream.codec_id = MEDIA_CODEC_ID_H265;
videoStream.video_params.bit_rate = 5000;
videoStream.video_params.frame_rate = 25;
videoStream.video_params.pix_fmt = MC_PIXEL_FORMAT_YUV420P;
videoStream.video_params.width = 640;
videoStream.video_params.height = 480;
videoStream.video_params.intra_period = 30;
videoStream.numerator = 1;
videoStream.denominator = videoStream.video_params.frame_rate;
mx_stream_params_t audioStream;
memset(&audioStream, 0x00, sizeof(mx_stream_params_t));
audioStream.codec_id = MEDIA_CODEC_ID_AAC;
audioStream.audio_params.bit_rate = 135000;
audioStream.audio_params.sample_fmt = MC_AV_SAMPLE_FMT_FLTP;
audioStream.audio_params.sample_rate = MC_AV_SAMPLE_RATE_48000;
audioStream.audio_params.channel_layout =MC_AV_CHANNEL_LAYOUT_MONO;
audioStream.audio_params.channels = 1;
mx_stream_t mxStream;
memset(&mxStream, 0x00, sizeof(mx_stream_t));
AVFormatContext *iVFmtCtx = NULL;
ret = avformat_open_input(&iVFmtCtx, inputVideoFileName, 0, 0);
if (ret < 0) {
goto ERR;
}
ret = avformat_find_stream_info(iVFmtCtx, 0);
if (ret < 0) {
goto ERR;
}
AVFormatContext *iAFmtCtx = NULL;
ret = avformat_open_input(&iAFmtCtx, inputAudioFileName, 0, 0);
if (ret < 0) {
goto ERR;
}
ret = avformat_find_stream_info(iAFmtCtx, 0);
if (ret < 0) {
goto ERR;
}
if (iAFmtCtx->nb_streams != (unsigned int)1) {
goto ERR;
}
audioStream.numerator = iAFmtCtx->streams[0]->time_base.num;
audioStream.denominator = iAFmtCtx->streams[0]->time_base.den;
ret hb_mm_mx_initialize(&muxerCtx);
if (ret < 0) {
goto ERR;
}
ret = hb_mm_mx_add_stream(&muxerCtx, &videoStream);
if (ret < 0) {
goto ERR;
}
ret = hb_mm_mx_add_stream(&muxerCtx, &audioStream);
if (ret < 0) {
goto ERR;
}
ret = hb_mm_mx_start(&muxerCtx);
if (ret < 0) {
goto ERR;
}
AVPacket pkt = {0};
int64_t v_next_pts = 0, a_next_pts = 0;
while (!doAudioExit || !doVideoExit) {
if ((!doVideoExit) && (doAudioExit ||
hb_mm_mx_compare_ts(&muxerCtx, v_next_pts,
a_next_pts, COMPARE_PTS_VIDEO_AUDIO))) {
if (av_read_frame(iVFmtCtx, &pkt) >= 0) {
static int count = 0;
mxStream.is_audio = 0;
mxStream.vir_ptr = (unsigned char*)pkt.data;
mxStream.phy_ptr = 0;
mxStream.size = pkt.size;
mxStream.pts = count++;//outputBuffer.vstream_buf.pts;
mxStream.is_key_frame = 0;
ret = hb_mm_mx_write_stream(&muxerCtx, &mxStream);
if (ret < 0) {
goto ERR;
}
v_next_pts += videoStream.denominator/videoStream.numerator/videoStream.video_params.frame_rate;
av_packet_unref(&pkt);
} else {
doVideoExit = TRUE;
}
} else {
if (av_read_frame(iAFmtCtx, &pkt) >= 0) {
mxStream.is_audio = 1;
mxStream.vir_ptr = (unsigned char*)pkt.data;
mxStream.phy_ptr = 0;
mxStream.size = pkt.size;
mxStream.pts = pkt.pts;
mxStream.is_key_frame = 0;
ret = hb_mm_mx_write_stream(&muxerCtx, &mxStream);
if (ret < 0) {
goto ERR;
}
a_next_pts += audioStream.denominator/audioStream.numerator/audioStream.audio_params.sample_rate;
av_packet_unref(&pkt);
} else {
doAudioExit = TRUE;
}
}
}
ERR:
if (muxerCtx)
hb_mm_mx_stop(&muxerCtx);
if (iVFmtCtx)
avformat_close_input(&iVFmtCtx);
if (iAFmtCtx)
avformat_close_input(&iAFmtCtx);
return -1;
}
5.12.5.2. hb_mm_mx_initialize
【函数声明】
hb_s32 hb_mm_mx_initialize(media_muxer_context_t *context)
【参数描述】
[IN] media_muxer_context_t *context:复用器上下文
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_NO_FREE_INSTANCE:无法分配更多实例 ( 最多 32 个 )
HB_MEDIA_ERR_FILE_OPERATION_FAILURE: 无法打开或者创建文件
【功能描述】
初始化 MediaMuxer 内部状态,调用成功后 MediaMuxer 进入 MEDIA_MUXER_STATE_INITIALIZED 状态。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.3. hb_mm_mx_add_stream
【函数声明】
hb_s32 hb_mm_mx_add_stream(media_muxer_context_t *context, const
mx_stream_params_t *params)
【参数描述】
[IN] media_muxer_context_t *context: muxer context
[IN] const mx_stream_params_t *params:轨道信息
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
添加音视频轨道。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.4. hb_mm_mx_start
【函数声明】
hb_s32 hb_mm_mx_start(media_muxer_context_t *context)
【参数描述】
[IN] media_muxer_context_t *context: muxer context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INSUFFICIENT_RES:内部内存资源不足
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
启动 MediaMuxer 内部流程,调用成功后进入 MEDIA_MUXER_STATE_STARTED 状态。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.5. hb_mm_mx_stop
【函数声明】
hb_s32 hb_mm_mx_stop(media_muxer_context_t *context)
【参数描述】
[IN] media_muxer_context_t *context: muxer context
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
停止 MediaMuxer 内部流程,调用成功后进入 MEDIA_MUXER_STATE_UNINITIALIZED 状态。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.6. hb_mm_mx_write_stream
【函数声明】
hb_s32 hb_mm_mx_write_stream(media_muxer_context_t *context, const
mx_stream_t *buffer)
【参数描述】
[IN] media_muxer_context_t *context: muxer context
[IN] const mx_stream_t *buffer:音频或视频数据流
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_OPERATION_NOT_ALLOWED:操作不允许
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
HB_MEDIA_ERR_INVALID_BUFFER:无效 buffer
HB_MEDIA_ERR_FILE_OPERATION_FAILURE:文件操作失败
【功能描述】
写入音频或视频数据。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.7. hb_mm_mx_get_state
【函数声明】
hb_s32 hb_mm_mx_get_state (media_muxer_context_t *context,
media_muxer_state_t *state)
【参数描述】
[IN] media_muxer_context_t *context: muxer context
[OUT] const mx_stream_t *buffer:音频或视频数据流
【返回值】
0 :操作成功
HB_MEDIA_ERR_UNKNOWN: 未知错误
HB_MEDIA_ERR_INVALID_INSTANCE:无效实例
【功能描述】
获取 MediaMuxer 当前的状态。
【示例代码】
参考 :hb_mm_mx_get_default_context
5.12.5.8. hb_mm_mx_probe_stream
【函数声明】
hb_s32 hb_mm_mx_probe_stream(hb_string input_file_name)
【参数描述】
[IN] hb_string input_file_name:输入文件名
【返回值】
0 :操作成功
HB_MEDIA_ERR_INVALID_PARAMS:参数非法
【功能描述】
检查 MP4 文件是否异常。
【示例代码】
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <libavformat/avformat.h>
#include <libavutil/timestamp.h>
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "hb_media_codec.h"
#include "hb_media_error.h"
#include "hb_media_muxer.h"
int main(int argc, char *argv[])
{
int ret = 0;
char inputFileName[256] = "./damaged.mp4";
char outputFileName[256] = "./repaired.mp4";
ASSERT_EQ(hb_mm_mx_probe_stream(inputFileName), (int32_t)0);
}
5.12.5.9. hb_mm_mx_repair_stream
【函数声明】
hb_s32 hb_mm_mx_repair_stream(hb_string input_file_name, hb_string
output_file_name);
【参数描述】
[IN] hb_string input_file_name:待检查 MP4 文件名
[IN] hb_string output_file_name:修复后的 MP4 文件名
【返回值】
0 :操作成功
HB_MEDIA_ERR_INVALID_PARAMS:参数异常
【功能描述】
修复异常 MP4 文件并生成正常 MP4
【示例代码】
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <libavformat/avformat.h>
#include <libavutil/timestamp.h>
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "hb_media_codec.h"
#include "hb_media_error.h"
#include "hb_media_muxer.h"
int main(int argc, char *argv[])
{
int ret = 0;
char inputFileName[256] = "./damaged.mp4";
char outputFileName[256] = "./repaired.mp4";
ASSERT_EQ(hb_mm_mx_repair_stream(inputFileName, outputFileName), (int32_t)0);
}
5.12.6. 数据结构
5.12.6.1. media_codec_state_t
typedef enum _media_codec_state {
MEDIA_CODEC_STATE_NONE = -1,
MEDIA_CODEC_STATE_UNINITIALIZED,
MEDIA_CODEC_STATE_INITIALIZED,
MEDIA_CODEC_STATE_CONFIGURED,
MEDIA_CODEC_STATE_STARTED,
MEDIA_CODEC_STATE_PAUSED,
MEDIA_CODEC_STATE_FLUSHING,
MEDIA_CODEC_STATE_ERROR,
MEDIA_CODEC_STATE_TOTAL,
} media_codec_state_t;
5.12.6.2. media_codec_id_t
typedef enum _media_codec_id {
MEDIA_CODEC_ID_NONE = -1,
/* Video Codecs */
MEDIA_CODEC_ID_H264,
MEDIA_CODEC_ID_H265,
MEDIA_CODEC_ID_MJPEG,
MEDIA_CODEC_ID_JPEG,
/* Audio Codecs */
MEDIA_CODEC_ID_FLAC,
MEDIA_CODEC_ID_PCM_MULAW,
MEDIA_CODEC_ID_PCM_ALAW,
MEDIA_CODEC_ID_ADPCM_G726,
MEDIA_CODEC_ID_ADPCM,
MEDIA_CODEC_ID_AAC,
MEDIA_CODEC_ID_MP3,
MEDIA_CODEC_ID_MP2,
MEDIA_CODEC_ID_TAK,
MEDIA_CODEC_ID_AC3,
MEDIA_CODEC_ID_WMA,
MEDIA_CODEC_ID_AMR,
MEDIA_CODEC_ID_APE,
MEDIA_CODEC_ID_G729,
MEDIA_CODEC_ID_G723,
MEDIA_CODEC_ID_G722,
MEDIA_CODEC_ID_IAC,
MEDIA_CODEC_ID_RALF,
MEDIA_CODEC_ID_QDMC,
MEDIA_CODEC_ID_DTS,
MEDIA_CODEC_ID_GSM,
MEDIA_CODEC_ID_TTA,
MEDIA_CODEC_ID_QCELP,
MEDIA_CODEC_ID_MLP,
MEDIA_CODEC_ID_ATRAC1,
MEDIA_CODEC_ID_IMC,
MEDIA_CODEC_ID_EAC,
MEDIA_CODEC_ID_MP1,
MEDIA_CODEC_ID_SIPR,
MEDIA_CODEC_ID_OPUS,
MEDIA_CODEC_ID_CELT,
MEDIA_CODEC_ID_MOV_TEXT,
MEDIA_CODEC_ID_TOTAL,
} media_codec_id_t;
5.12.6.3. mc_video_rate_control_mode_t
typedef enum _mc_video_rate_control_mode {
MC_AV_RC_MODE_NONE = -1,
MC_AV_RC_MODE_H264CBR,
MC_AV_RC_MODE_H264VBR,
MC_AV_RC_MODE_H264AVBR,
MC_AV_RC_MODE_H264FIXQP,
MC_AV_RC_MODE_H264QPMAP,
MC_AV_RC_MODE_H265CBR,
MC_AV_RC_MODE_H265VBR,
MC_AV_RC_MODE_H265AVBR,
MC_AV_RC_MODE_H265FIXQP,
MC_AV_RC_MODE_H265QPMAP,
MC_AV_RC_MODE_MJPEGFIXQP,
MC_AV_RC_MODE_TOTAL,
} mc_video_rate_control_mode_t;
5.12.6.4. mc_h265_cbr_params_t
typedef struct _mc_h265_cbr_params {
hb_u32 intra_period;
hb_u32 intra_qp;
hb_u32 bit_rate;
hb_u32 frame_rate;
hb_u32 initial_rc_qp;
hb_s32 vbv_buffer_size;
hb_u32 ctu_level_rc_enable;
hb_u32 min_qp_I;
hb_u32 max_qp_I;
hb_u32 min_qp_P;
hb_u32 max_qp_P;
hb_u32 min_qp_B;
hb_u32 max_qp_B;
hb_u32 hvs_qp_enable;
hb_s32 hvs_qp_scale;
hb_u32 max_delta_qp;
hb_bool qp_map_enable;
} mc_h265_cbr_params_t;
5.12.6.5. mc_h265_vbr_params_t
typedef struct _mc_h265_vbr_params {
hb_u32 intra_period;
hb_u32 intra_qp;
hb_u32 frame_rate;
hb_bool qp_map_enable;
} mc_h265_vbr_params_t;
5.12.6.6. mc_h265_avbr_params_t
typedef struct _mc_h265_avbr_params {
hb_u32 intra_period;
hb_u32 intra_qp;
hb_u32 bit_rate;
hb_u32 frame_rate;
hb_u32 initial_rc_qp;
hb_s32 vbv_buffer_size;
hb_u32 ctu_level_rc_enalbe;
hb_u32 min_qp_I;
hb_u32 max_qp_I;
hb_u32 min_qp_P;
hb_u32 max_qp_P;
hb_u32 min_qp_B;
hb_u32 max_qp_B;
hb_u32 hvs_qp_enable;
hb_s32 hvs_qp_scale;
hb_u32 max_delta_qp;
hb_bool qp_map_enable;
} mc_h265_avbr_params_t;
5.12.6.7. mc_h265_fix_qp_params_t
typedef struct _mc_h265_fix_qp_params {
hb_u32 intra_period;
hb_u32 frame_rate;
hb_u32 force_qp_I;
hb_u32 force_qp_P;
hb_u32 force_qp_B;
} mc_h265_fix_qp_params_t;
5.12.6.8. mc_h265_qp_map_params_t
typedef struct _mc_h265_qp_map_params {
hb_u32 intra_period;
hb_u32 frame_rate;
hb_byte qp_map_array;
hb_u32 qp_map_array_count;
} mc_h265_qp_map_params_t;
5.12.6.9. mc_video_longterm_ref_mode_t
/**
* Define the parameters of longterm reference mode.
**/
typedef struct _mc_video_longterm_ref_mode {
/**
* It enables long-term reference mode.
* The valid numbers are as follows.
* 0 : disable
* 1 : enable
*
* - Note: It's unchangable parameters in the same sequence.
* - Encoding: Support.
* - Decoding: Unsupport.
* - Default: 0
*/
hb_u32 use_longterm;
/**
* It specifies the period of long-term reference picture.
* Values[0,2 ^ 31-1]
*
* - Note: It's changable parameters in the same sequence.
* - Encoding: Support.
* - Decoding: Unsupport.
* - Default: 0
*/
hb_u32 longterm_pic_period;
/**
* It specifies the period of using long-term reference picture.
* Values[0,2 ^ 31-1]
*
* - Note: It's changable parameters in the same sequence.
* - Encoding: Support.
* - Decoding: Unsupport.
* - Default: 0
*/
hb_u32 longterm_pic_using_period;
} mc_video_longterm_ref_mode_t;
5.12.6.10. mc_video_intra_refresh_params
/**
* Define the parameters of H264/H265 intra refresh.
**/
typedef struct _mc_video_intra_refresh_params {
/**
* An intra refresh mode, only applied in H264/H265.
* IntraRefresh can be enabled for error robustness. Host application
* can specify the number of intra MBs or CTBs in a non-intra picture and
* IntraRefresh mode.
* The valid IntraRefresh modes are as follows.
* 0: no intra refresh
* 1: row
* 2: column
* 3: step size in MB or CTU
* 4: adaptive intra refresh (only for H265 of XJ3/J6)
*
* - Note: It's unchangable parameter in the same sequence.
* - Encoding: Support.
* - Decoding: Unsupport.
* - Default: 0.
*/
hb_s32 intra_refresh_mode;
/**
* It specifies an intra MB or CTU refresh interval. Depending on
* intra_refresh_mode, it can be one of the followings.
* intra_refresh_mode = 1: The number of consecutive MB/CTU rows.
* Values(0, Max Mb(16x16) or CTU(64x64) number in row]
* intra_refresh_mode = 2: The number of consecutive MB/CTU columns.
* Values(0, Max Mb(16x16) or CTU(64x64) number in column]
* intra_refresh_mode = 3: A step size in MB/CTU.
* Values(0, Max Mb(16x16) or CTU(64x64) number in picture]
* intra_refresh_mode = 4: The number of intra MB/CTU to be encoded
* in a picture.
* Values(0, Max Mb(16x16) or CTU(64x64) number in picture]
*
* Values[0,2 ^ 31-1]
*
* - Note:It's unchangable parameter in the same sequence.
* The intra_refresh_mode 4 can't work with lossless and ROI mode.
* - Encoding: Support.
* - Decoding: Unsupport.
* - Default: 0.
*/
hb_u32 intra_refresh_arg;
} mc_video_intra_refresh_params_t;
5.12.6.11. mc_mjpeg_fix_qp_params_t
typedef struct _mc_mjpeg_fix_qp_params {
hb_u32 frame_rate;
hb_u32 quality_factor;
} mc_mjpeg_fix_qp_params_t;
5.12.6.12. mc_video_custom_gop_pic_params_t
typedef struct _mc_video_custom_gop_pic_params {
hb_u32 pic_type;
hb_s32 poc_offset;
hb_u32 pic_qp;
hb_s32 num_ref_picL0;
hb_s32 ref_pocL0;
hb_s32 ref_pocL1;
hb_u32 temporal_id;
} mc_video_custom_gop_pic_params_t;
5.12.6.13. mc_inter_status_t
typedef struct _mc_inter_status {
hb_u32 cur_input_buf_cnt;
hb_u64 cur_input_buf_size;
hb_u32 cur_output_buf_cnt;
hb_u64 cur_output_buf_size;
hb_u32 left_recv_frame;
hb_u32 left_enc_frame;
hb_u32 total_input_buf_cnt;
hb_u32 total_output_buf_cnt;
hb_s32 pipeline;
hb_s32 channel_port_id;
} mc_inter_status_t;
5.12.6.14. media_codec_context_t
typedef struct _media_codec_context {
media_codec_id_t codec_id;
hb_bool encoder;
hb_s32 instance_index;
union {
mc_video_codec_enc_params_t video_enc_params;
mc_video_codec_dec_params_t video_dec_params;
mc_audio_codec_enc_params_t audio_enc_params;
mc_audio_codec_dec_params_t audio_dec_params;
};
hb_ptr vpf_context;
mc_video_cmd_prio_t priority;
} media_codec_context_t;
5.12.6.15. mc_video_codec_enc_params_t
typedef struct _mc_video_codec_enc_params {
hb_s32 width, height;
mc_pixel_format_t pix_fmt;
hb_u32 frame_buf_count;
hb_bool external_frame_buf;
hb_u32 bitstream_buf_count;
hb_u32 bitstream_buf_size;
mc_rate_control_params_t rc_params;
mc_video_gop_params_t gop_params;
mc_rotate_degree_t rot_degree;
mc_mirror_direction_t mir_direction;
hb_u32 frame_cropping_flag;
mc_av_codec_rect_t crop_rect;
hb_bool enable_user_pts;
union {
mc_h264_enc_config_t h264_enc_config;
mc_h265_enc_config_t h265_enc_config;
mc_mjpeg_enc_config_t mjpeg_enc_config;
mc_jpeg_enc_config_t jpeg_enc_config;
};
} mc_video_codec_enc_params_t;
5.12.6.16. mc_video_codec_dec_params_t
typedef struct _mc_video_codec_dec_params {
mc_av_stream_feeding_mode_t feed_mode;
mc_pixel_format_t pix_fmt;
hb_u32 bitstream_buf_size;
hb_u32 bitstream_buf_count;
hb_bool external_bitstream_buf;
hb_u32 frame_buf_count;
union {
mc_h264_dec_config_t h264_dec_config;
mc_h265_dec_config_t h265_dec_config;
mc_mjpeg_dec_config_t mjpeg_dec_config;
mc_jpeg_dec_config_t jpeg_dec_config;
};
} mc_video_codec_dec_params_t;
5.12.6.17. mc_audio_codec_enc_params_t
typedef struct _mc_audio_codec_enc_params {
hb_u32 bit_rate;
hb_s32 frame_size;
hb_s32 frame_buf_count;
hb_s32 packet_count;
mc_audio_sample_format_t sample_fmt;
mc_audio_sample_rate_t sample_rate;
mc_audio_channel_layout_t channel_layout;
hb_s32 channels;
hb_ptr enc_config;
} mc_audio_codec_enc_params_t;
5.12.6.18. mc_audio_codec_dec_params_t
typedef struct _mc_audio_codec_dec_params {
mc_av_stream_feeding_mode_t feed_mode;
hb_s32 packet_buf_size;
hb_s32 packet_count;
hb_s32 frame_cache_size;
hb_s32 internal_frame_size;
hb_s32 frame_buf_count;
hb_ptr dec_config;
} mc_audio_codec_dec_params_t;
5.12.6.19. media_muxer_state_t
typedef enum _media_muxer_state {
MEDIA_MUXER_STATE_NONE = -1,
MEDIA_MUXER_STATE_UNINITIALIZED,
MEDIA_MUXER_STATE_INITIALIZED,
MEDIA_MUXER_STATE_STARTED,
MEDIA_MUXER_STATE_ERROR,
MEDIA_MUXER_STATE_TOTAL
} media_muxer_state_t;
5.12.6.20. mx_audio_stream_input_params_t
typedef struct _mx_audio_stream_input_params {
hb_s64 bit_rate;
mc_audio_sample_format_t sample_fmt;
mc_audio_sample_rate_t sample_rate;
mc_audio_channel_layout_t channel_layout;
hb_s32 channels;
} mx_audio_stream_input_params_t;
5.12.6.21. mx_video_stream_input_params_t
typedef struct _mx_video_stream_input_params {
hb_u32 bit_rate;
hb_u32 frame_rate;
mc_pixel_format_t pix_fmt;
hb_s32 width, height;
hb_s32 intra_period;
} mx_video_stream_input_params_t;
5.12.6.22. mx_stream_params_t
typedef struct _mx_stream_params {
media_codec_id_t codec_id;
hb_s32 numerator;
hb_s32 denominator;
union {
mx_audio_stream_input_params_t audio_params;
mx_video_stream_input_params_t video_params;
mx_subtitle_stream_input_params_t subtitle_params;
};
} mx_stream_params_t;
5.12.6.23. mx_stream_t
typedef struct _mx_stream {
hb_s32 is_audio;
hb_u8 *vir_ptr;
hb_u64 phy_ptr;
hb_u32 size;
hb_u64 pts;
hb_bool is_key_frame;
} mx_stream_t;
5.12.6.24. media_muxer_context_t
typedef struct _media_muxer_context {
hb_string output_file_name,
mx_output_format_t output_format;
hb_s32 instance_index;
} media_muxer_context_t;
5.12.7. 返回值说明
| 错误码 | 宏定义 | 描述 |
|---|---|---|
| 0xF0000001 | HB_MEDIA_ERR_UNKNOWN | 未知的错误 |
| 0xF0000002 | HB_MEDIA_ERR_CODEC_NOT_FOUND | 找不到对应的 codec |
| 0xF0000003 | HB_MEDIA_ERR_CODEC_OPEN_FAIL | 无法打开 codec 设备 |
| 0xF0000004 | HB_MEDIA_ERR_CODEC_RESPONSE_TIMEOUT | codec 响应超时 |
| 0xF0000005 | HB_MEDIA_ERR_CODEC_INIT_FAIL | codec 初始化失败 |
| 0xF0000006 | HB_MEDIA_ERR_OPERATION_NOT_ALLOWED | 操作不允许 |
| 0xF0000007 | HB_MEDIA_ERR_INSUFFICIENT_RES | 内部内存资源不足 |
| 0xF0000008 | HB_MEDIA_ERR_NO_FREE_INSTANCE | 没有可用的 instance( VPU 最多 32 个, JPU 最多 64 个, Audio 最多 32 个) |
| 0xF0000009 | HB_MEDIA_ERR_INVALID_PARAMS | 无效的参数 |
| 0xF000000A | HB_MEDIA_ERR_INVALID_INSTANCE | 无效的实例 |
| 0xF000000B | HB_MEDIA_ERR_INVALID_BUFFER | 无效的 buffer |
| 0xF000000C | HB_MEDIA_ERR_INVALID_COMMAND | 无效的指令 |
| 0xF000000D | HB_MEDIA_ERR_WAIT_TIMEOUT | 等待超时 |
| 0xF000000E | HB_MEDIA_ERR_FILE_OPERATION_FAILURE | 文件操作失败 |
| 0xF000000F | HB_MEDIA_ERR_PARAMS_SET_FAILURE | 参数设置失败 |
| 0xF0000010 | HB_MEDIA_ERR_PARAMS_GET_FAILURE | 参数获取失败 |
| 0xF0000011 | HB_MEDIA_ERR_CODING_FAILED | 编解码失败 |
| 0xF0000012 | HB_MEDIA_ERR_OUTPUT_BUF_FULL | 输出 buffer 满 |
| 0xF0000013 | HB_MEDIA_ERR_UNSUPPORTED_FEATURE | 不支持的功能 |
| 0xF0000014 | HB_MEDIA_ERR_INVALID_PRIORITY | 不支持的优先级 |