5.4. 内存管理 - hbmem
5.4.1. 模块描述
X5 SoC 提供
由于
尽管
详细信息
hbmem 模块
| 功能 |
功能 |
|---|---|
| 内存 |
从 |
| 内存 |
支持 |
| 内存 |
提供 内存 |
| 内存 |
支持 |
| 共享内存 |
支持 |
5.4.1.1. 内存分配
内存
内存
提供
最 基本 的 连续 物理 内存 的 分配、释放 接口,详细 见:内存 分配 接口 内存
分配 成功 后,用户 可 获得 对应 的 文件 句柄,基于 该 文件 句柄,用户 可 对 相关 的 物理 内存 进行:
Cache 操作、 DMA 拷贝、获取 buffer 信息等,详细 见:内存 分配 接口 支持
设置 多种 属性 配置,包括 Cache 属性、内存 heap 属性、硬件加速 单元 标识 属性,详细 见:内存 分配 属性 内存
分配 软件 模块,提供 了 三 种类 别的 内存 单元:整块 连续 内存 单元、图像 数据 内存 单元、图像 数据 内存 组 单元
注意:不
内存分配单元说明
| 内存 |
结构 |
场景 | 特点 |
|---|---|---|---|
| 整块 |
hb_mem_common_buf_t | 编码器 |
简单 |
| 图像 |
hb_mem_graphic_buf_t | ISP、 GDC、 VSE 使用 |
支持 |
| 图像 |
hb_mem_graphic_buf_group_t | PYM 模块 |
多个 |
Cache 操作说明
现代 CPU 为了
CPU 写 DDR 操作:当 CPU 修改
某块 数据 时,通常 不会 立即 将 数据 写回 DDR,而是 先 更新 Cache 中 的 副本。
这种机制 称为“写回 缓存”,有效 减少 了 对 DDR 的 直接 写 操作,提高 性能。 CPU 读 DDR 操作:当 CPU 从 DDR 中
读取数据 时,会 优先 检查 Cache。如果 Cache 中 已经 存在 目标 数据 的 副本,
CPU 将直接 从 Cache 中 读取,而 无需 访问 DDR。这种 机制 显著 提升 了 读 操作 效率。
Cache 是
然而,当
会
因此 hbmem 模块
Cache 刷新 : hb_mem_flush_buf
Cache 无效 : hb_mem_invalidate_buf
下面
Cache 刷新
Cache 刷新
下面
左图:没有
调用 Cache 刷新 的 情况 右图:在
合适 的 时机 调用 Cache 刷新 的 情况(hb_mem_flush_buf)

左图
步骤 1: CPU 从 eMMC 读取
视频 数据,数据传输 过程 中 经过 Cache 缓存 步骤 2: 读取
的 视频 数据 被 存储 到 DDR 中。然而,在 视频 数据 读取 完成 后,部分 数据 可能 在 Cache 中未 完全 写入 DDR 步骤 3: VSE 从 DDR 读取
视频 数据 进行 处理,但 由于 数据 不 完整 ( 部分 数据 在 Cache 中 ),导致 VSE 处理 后 的 数据 是 错误 的
右图
步骤 1: 同
左图 步骤 2: 同
左图 步骤 3: 调用 Cache 刷新
接口 hb_mem_flush_buf,将 Cache 中 的 数据 回写 到 DDR 中 步骤 4: VSE 从 DDR 中
读取 视频 数据,进行 处理,可以 读 到 完整 的 视频 数据
Cache 无效
Cache 无效
当
下面
左图:没有
调用 Cache 无效 接口 的 情况 右图:在
合适 的 时机 调用 Cache 无效 接口 的 情况(hb_mem_invalidate_buf)

左图
步骤 1: CPU 读取 DDR 中
的 视频 数据 进行 某种 算法 处理 后,此时 Cache 中 缓存 了 部分 DDR 中 的 数据 步骤 2: VSE 从 DDR 中
读取 视频 数据 步骤 3: VSE 内部
进行 OSD 叠加 文字 后,继续 回写 到 DDR 中 步骤 4: CPU 继续
读取 DDR 中 的 视频 数据,由于 步骤 3 中 的 VSE 写入 了 新 的 数据,但是 Cache 中 有步骤 1 缓存 了 部分 DDR 数据,
因此 CPU 只会从 DDR 中 读取 未 在 Cache 中 的 数据 步骤 5: CPU 将
读取 的 数据 写入 到 EMMC 中,由于 步骤 4 只 读取 了 部分 新 数据,导致 写入 EMMC 中 的 数据 是 错误 的。
右图
步骤 1: 同
左图 步骤 2: 同
左图 步骤 3: 同
左图 步骤 4: 调用 Cache 无效
接口 hb_mem_invalidate_buf,将 Cache 中 的 数据 丢弃,使 其 进入 未 命中 状态。 步骤 5: CPU 读取 DDR 中
的 视频 数据,由于 步骤 4 将 Cache 中 的 旧 数据 丢弃 了,所以 CPU 会 从 DDR 中 读取 全部 的 最新 视频 数据 步骤 6: CPU 将
读取 的 数据 写入 到 EMMC 中,由于 步骤 5 中 读取 的 数据 全部都是 最新 的 数据,所以 写入 EMMC 的 数据 是 没 问题 的
5.4.1.2. 内存共享
内存
用户
可 直接 传递 内存 分配 单元 对应 的 结构 体到 到 另 一个 线程 或 进程 中 另外
一个 进程 接收 到 结构 体 信息 后,通过 hb_mem_import_xxx接口(参见下面 的 表格) 完成 导入,实现 buffer 的 安全 共享。
内存
整块
连续 内存: hb_mem_common_buf_t图像
数据 内存: hb_mem_graphic_buf_t图像
数据 内存 组: hb_mem_graphic_buf_group_t
| 内存 |
结构 |
hb_mem_import_xxx 接口 |
|---|---|---|
| 整块 |
hb_mem_common_buf_t | hb_mem_import_com_buf |
| 图像 |
hb_mem_graphic_buf_t | hb_mem_import_graph_buf |
| 图像 |
hb_mem_graphic_buf_group_t | hb_mem_import_graph_buf_group |
下图hb_mem_common_buf_t 在

5.4.1.3. 内存队列管理
内存
内存空数据队列 和 有效数据队列,通过
具体步骤
生产者
从 空数据队列中获取 一个 Item,然后 填充 有效 数据 生产者
将 填充 了 有效 数据 的 Item, 存储 到 有效数据队列中消费者
从 有效数据队列中获取 一个 Item,读出 其中 的 有效 数据 消费者
把 已经 处理 后 的 Item, 再 存储 到 空数据队列中

注意事项:
只
支持 单 进程 内 操作 内存
队列 本身 使用 malloc 申请 内存, 队列 中 存储 的 数据 可以 是 内存 分配 单元 中 提到 的 数据结构 体 内存
队 列为 一个 环形 队列,所以 要 当 队列 满 了 之后,再 往 队列 中 写入 事件,就 会 将 之前 的 第一个 事件 给 覆盖
5.4.1.4. 内存池
内存
实现
方法:在 程序 初始化 阶段,预先 分配 一块 大 内存 作为 内存 池 资源,后续 通过 内存 池 分配 接口 从 该 大 内存 中 分配 所 需 的 小 块内存。 实现目标:通过
内存 池 模块,用户 可 在 用户 态 快速 完成 内存 分配,无需 频繁 切换 到 内核 态,从而 提升 内存 管理效率。
5.4.1.5. 共享内存池
共享内存
共享内存
池 分配 的 内存 支持 多 进程 共享 从
共享内存 池上 分配 的 buffer 大小 相同,且 buffer 的 大小 只能 在 创建 共享内存 池时 指定。
5.4.2. 参考示例
hbmem 部分
示例 代码 可以 参考 sample_hbmem 章节
5.4.3. API 参考
链接库: libhbmem.so
头文件: hb_mem_mgr.h、 hbmem.h 和 hb_mem_err.h。
5.4.3.1. 内存分配接口
| API 接口 | 接口 |
|---|---|
| hb_mem_get_version | 获取 |
| hb_mem_module_open | 打开 |
| hb_mem_module_close | 关闭 |
| hb_mem_alloc_com_buf | 分配 common buffer |
| hb_mem_get_com_buf | 通过 fd 获取 common buffer 信息 |
| hb_mem_alloc_graph_buf | 分配 graphic buffer |
| hb_mem_get_graph_buf | 通过 fd 获取 graphic buffer 信息 |
| hb_mem_free_buf | 通过 fd 释放 buffer |
| hb_mem_invalidate_buf | 使 fd 对应 |
| hb_mem_flush_buf | Flush fd 对应 |
| hb_mem_is_valid_buf | 判断 |
| hb_mem_get_phys_addr | 获取 |
| hb_mem_get_buf_info | 获取 |
| hb_mem_invalidate_buf_with_vaddr | 使 |
| hb_mem_flush_buf_with_vaddr | Flush 虚拟地址 |
| hb_mem_get_com_buf_with_vaddr | 通过 |
| hb_mem_get_graph_buf_with_vaddr | 通过 |
| hb_mem_free_buf_with_vaddr | 通过 |
| hb_mem_alloc_graph_buf_group | 申请 |
| hb_mem_get_graph_buf_group | 通过 fd( graphic buffer group 中 |
| hb_mem_get_graph_buf_group_with_vaddr | 通过 |
| hb_mem_dma_copy | 将 |
5.4.3.2. 内存共享接口
| API 接口 | 接口 |
|---|---|
| hb_mem_import_com_buf | 导入 common buffer 的 |
| hb_mem_import_com_buf_with_paddr | 通过 |
| hb_mem_import_graph_buf | 导入 graphic buffer 的 |
| hb_mem_import_graph_buf_group | 共享 |
| hb_mem_get_share_info | 通过 fd 获取 |
| hb_mem_get_share_info_with_vaddr | 通过 |
| hb_mem_wait_share_status | 等待 fd 对应 buffer 的 |
| hb_mem_wait_share_status_with_vaddr | 等待 |
5.4.3.3. 内存队列管理接口
| API 接口 | 接口 |
|---|---|
| hb_mem_create_buf_queue | 创建 |
| hb_mem_destroy_buf_queue | 销毁 |
| hb_mem_dequeue_buf | 生产者 |
| hb_mem_queue_buf | 生产者 |
| hb_mem_request_buf | 消费者 |
| hb_mem_release_buf | 消费者 |
| hb_mem_cancel_buf | 生产者 |
5.4.3.4. 内存池接口
| API 接口 | 接口 |
|---|---|
| hb_mem_pool_create | 创建 |
| hb_mem_pool_destroy | 销毁 |
| hb_mem_pool_alloc_buf | 从 |
| hb_mem_pool_free_buf | 释放 |
| hb_mem_pool_get_info | 获取 |
5.4.3.5. 共享内存池接口
| API 接口 | 接口 |
|---|---|
| hb_mem_share_pool_create | 创建 |
| hb_mem_share_pool_destroy | 销毁 |
| hb_mem_share_pool_alloc_buf | 从 |
| hb_mem_share_pool_free_buf | 释放 |
| hb_mem_share_pool_get_info | 获取 |
5.4.3.6. 通用信息获取或设置接口
| API 接口 | 接口 |
|---|---|
| hb_mem_get_buf_type_with_vaddr | 获取 virt_addr 对应 buffer 的 |
| hb_mem_get_buf_type_and_buf_with_vaddr | 获取 virt_addr 对应 buffer 的 |
| hb_mem_get_buffer_process_info | 通过 |
| hb_mem_get_buffer_process_info_with_share_id | 通过 share_id 获取 |
| hb_mem_get_consume_info | 通过 fd 获取 |
| hb_mem_get_consume_info_with_vaddr | 通过 virt_addr 获取 |
| hb_mem_wait_consume_status | 等待 fd 对应 buffer 的 consume cnt 变成 share_consume_cnt,超时 |
| hb_mem_wait_consume_status_with_vaddr | 等待 virt_addr 对应 buffer 的 consume cnt 变成 share_consume_cnt,超时 |
| hb_mem_inc_com_buf_consume_cnt | 增加 |
| hb_mem_inc_graph_buf_consume_cnt | 增加 |
| hb_mem_inc_graph_buf_group_consume_cnt | 增加 graphic buffer group 中 |
| hb_mem_dec_consume_cnt | 通过 fd 减少 |
| hb_mem_dec_consume_cnt_with_vaddr | 通过 |
| hb_mem_get_buf_and_type_with_vaddr | 通过 |
| hb_mem_inc_user_consume_cnt | 通过 fd 增加 |
| hb_mem_dec_user_consume_cnt | 通过 fd 减少 |
| hb_mem_inc_user_consume_cnt_with_vaddr | 通过 |
| hb_mem_dec_user_consume_cnt_with_vaddr | 通过 |
5.4.3.7. 兼容性接口 ( 新功能开发时不建议使用 )
| API 接口 | 接口 |
|---|---|
| hbmem_alloc | 分配 |
| hbmem_free | 释放 |
| hbmem_mmap | 将 |
| hbmem_munmap | 释放 |
| hbmem_phyaddr | 获取 hbmem 内存空间 |
| hbmem_dmacpy | 使用 |
| hbmem_virtaddr | 获取 hbmem 内存空间 |
| hbmem_info | 获取 |
| hbmem_version | 获取 |
| hbmem_is_cacheable | 获取 hbmem_addr_t 对应 hbmem 空间 |
| hbmem_cache_invalid | 对 hbmem 内存空间 |
| hbmem_cache_clean | 对 hbmem 内存空间 |
| hbmem_mmap_with_share_id | 使用 share_id 将 |
| hbmem_get_share_id | 获取 |
5.4.4. 接口说明
5.4.4.1. hb_mem_get_version
【函数
int32_t hb_mem_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
【参数
[OUT] major:主
版本号 [OUT] minor:次
版本号 [OUT] patch:补丁
版本号
【返回值】
0 :成功
HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
获取
【示例
int main(int argc, char *argv[])
{
uint32_t major, minor, patch;
hb_mem_get_version(&major, &minor, &patch);
return 0;
}
5.4.4.2. hb_mem_module_open
【函数
int32_t hb_mem_module_open(void);
【参数
NA
【返回值】
0 :操作
成功 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_MODULE_OPEN_FAIL:内存模块
打开 失败
【功能
打开
【注意事项】
hbn_vflow_create内部已经 调用 了 hb_mem_module_open,不需要 再 额外 调用 一次 hb_mem_module_open。多线程
场景 下 调用 hb_mem_module_open后再 调用 hbn_vflow_create可能导致 主 进程 占用 的 fd 超过 上限,进而 导致 内存 分配 失败。 需要
与 hb_mem_module_close成对 调用
【示例
int main(int argc, char *argv[])
{
hb_mem_module_open();
hb_mem_module_close();
return 0;
}
5.4.4.3. hb_mem_module_close
【函数
int32_t hb_mem_module_close(void);
【参数
NA
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块
【功能
关闭
【注意事项】
需要
与 hb_mem_module_open成对 调用。
【示例
5.4.4.4. hb_mem_alloc_com_buf
【函数
int32_t hb_mem_alloc_com_buf(uint64_t size, int64_t flags, hb_mem_common_buf_t *buf);
【参数
[IN] size: buffer 大小
[IN] flags: buffer 属性,见 : hbmem 内存
分配 属性 [OUT] buf:分配
得到 的 common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
分配 common buffer。
【示例
int main(int argc, char *argv[])
{
int32_t w = 1920, h = 1080, format = MEM_PIX_FMT_NV12, stride = 0,
vstride = 0;
int64_t flags;
uint64_t size = 1024 * 4; // 4k
uint64_t offset = 0, offset_size;
hb_mem_common_buf_t com_buf = {0, };
hb_mem_common_buf_t com_buf_info = {0, };
hb_mem_graphic_buf_t graph_buf = {0, };
hb_mem_module_open();
// test cached graph buffer
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_graph_buf(w, h, format, flags, stride, vstride,
&graph_buf);
offset_size = graph_buf.size[0];
hb_mem_invalidate_buf(graph_buf.fd[0], offset, offset_size);
hb_mem_free_buf(graph_buf.fd[0]);
// test cached common buffer
hb_mem_alloc_com_buf(size, flags, &com_buf);
offset_size = size;
hb_mem_get_com_buf(com_buf.fd, &com_buf_info);
hb_mem_invalidate_buf(com_buf.fd, offset, offset_size);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.5. hb_mem_get_com_buf
【函数
int32_t hb_mem_get_com_buf(int32_t fd, hb_mem_common_buf_t *buf);
【参数
[IN] fd: buffer 相关
文件 描述符 [OUT] buf: common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 获取 common buffer 信息。
【示例
5.4.4.6. hb_mem_alloc_graph_buf
【函数
int32_t hb_mem_alloc_graph_buf(int32_t w, int32_t h, int32_t format, int64_t flags, int32_t stride, int32_t vstride, hb_mem_graphic_buf_t * buf);
【参数
[IN] w:图像
宽度,(0 , ) [IN] h:图像
高度,(0 , ) [IN] format:图像格式 , 见 :hbmem 图像格式
[IN] flags: buffer 属性,见 : hbmem 内存
分配 属性 [IN] stride:图像
水平 跨距, 0 或者 [w, ), 0 表示 内部 决定 [IN] vstride:图像
垂直 跨距, 0 或者 [h, ), 0 表示 内部 决定 [OUT] buf: graphic buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
分配 graphic buffer。
【示例
int main(int argc, char *argv[])
{
int32_t w = 1280, h = 720, format = MEM_PIX_FMT_NV12, stride = 0, vstride = 0;
int64_t flags = HB_MEM_USAGE_CPU_READ_NEVER;
hb_mem_graphic_buf_t graph_buf = {0, };
hb_mem_graphic_buf_t info = {0, };
hb_mem_module_open();
hb_mem_alloc_graph_buf(w, h, format, flags, stride, vstride,
&graph_buf);
hb_mem_get_graph_buf(graph_buf.fd[0], &info);
hb_mem_free_buf(graph_buf.fd[0]);
hb_mem_module_close();
return 0;
}
5.4.4.7. hb_mem_get_graph_buf
【函数
int32_t hb_mem_get_graph_buf(int32_t fd, hb_mem_graphic_buf_t *buf);
【参数
[IN] fd: buffer 相关
文件 描述符,取值 范围 [0, ) [OUT] buf: graphic buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 获取 graphic buffer 信息。
【示例
5.4.4.8. hb_mem_free_buf
【函数
int32_t hb_mem_free_buf(int32_t fd);
【参数
[IN] fd: buffer 相关
文件 描述符,取值 范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 释放 buffer。
【示例
5.4.4.9. hb_mem_invalidate_buf
【函数
int32_t hb_mem_invalidate_buf(int32_t fd, uint64_t offset, uint64_t size);
【参数
[IN] fd: buffer 相关
文件 描述符,取值 范围 是 [0, ) [IN] offset:需要 invalidate 的 buffer 地址
偏移,取值 范围 是 [0, ) [IN] size:需要 invalidate 的 buffer 大小,取值
范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
使 fd 对应
【示例
5.4.4.10. hb_mem_flush_buf
【函数
int32_t hb_mem_flush_buf(int32_t fd, uint64_t offset, uint64_t size);
【参数
[IN] fd: buffer 相关
文件 描述符,取值 范围 [0, ) [IN] offset:需要 flush 的 buffer 地址
偏移,取值 范围 是 [0, ) [IN] size:需要 flush 的 buffer 大小,取值
范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
Flush fd 对应
【示例
int main(int argc, char *argv[])
{
int64_t flags = HB_MEM_USAGE_CPU_READ_OFTEN |
HB_MEM_USAGE_CPU_WRITE_OFTEN | HB_MEM_USAGE_CACHED;
uint64_t size = 1024 * 4; // 4k
uint64_t offset = 0;
int32_t valid;
uint64_t phys_addr;
uint64_t start_virt;
uint64_t total_size;
int64_t out_flags;
hb_mem_common_buf_t com_buf = {0, };
hb_mem_module_open();
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_is_valid_buf((uint64_t)com_buf.virt_addr, com_buf.size,
&valid);
hb_mem_get_phys_addr((uint64_t)com_buf.virt_addr, &phys_addr);
hb_mem_get_buf_info((uint64_t)com_buf.virt_addr, &start_virt,
&total_size, &out_flags);
hb_mem_flush_buf(com_buf.fd, offset, size);
hb_mem_module_close();
return 0;
}
5.4.4.11. hb_mem_is_valid_buf
【函数
int32_t hb_mem_is_valid_buf(uint64_t virt_addr, uint64_t size, int32_t *valid);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [IN] size: buffer 大小,取值
范围 是 (0, ) [OUT] valid:该
虚拟地址 是否 有效, 0 :无效, 1 :有效
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
判断
【示例
参考 :hb_mem_flush_buf
5.4.4.12. hb_mem_get_phys_addr
【函数
int32_t hb_mem_get_phys_addr(uint64_t virt_addr, uint64_t *phys_addr);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [OUT] phys_addr:对应
的 物理地址,取值 范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
获取
【示例
参考 :hb_mem_flush_buf
5.4.4.13. hb_mem_get_buf_info
【函数
int32_t hb_mem_get_buf_info(uint64_t virt_addr, uint64_t *start, uint64_t *size, int64_t *flags);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [OUT] start:对应
的 起始 虚拟地址,取值 范围 是 (0, ) [OUT] size:对应
的 buffer 大小,取值 范围 是 (0, ) [OUT] flags:对应
的 buffer 属性,见 : hbmem 内存 分配 属性
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
获取
【示例
参考 :hb_mem_flush_buf
5.4.4.14. hb_mem_invalidate_buf_with_vaddr
【函数
int32_t hb_mem_invalidate_buf_with_vaddr(uint64_t virt_addr, uint64_t size);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [IN] size:需要 invalidate 的 buffer 大小,取值
范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
使
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_invalidate_buf_with_vaddr((uint64_t)com_buf.virt_addr, size);
hb_mem_module_close();
return 0;
}
5.4.4.15. hb_mem_flush_buf_with_vaddr
【函数
int32_t hb_mem_flush_buf_with_vaddr(uint64_t virt_addr, uint64_t size);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [IN] size:需要 flush 的 buffer 大小,取值
范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
Flush 虚拟地址
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
hb_mem_common_buf_t info = {0, };
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_com_buf_with_vaddr((uint64_t)com_buf.virt_addr, &info);
hb_mem_flush_buf_with_vaddr((uint64_t)com_buf.virt_addr, size);
hb_mem_module_close();
return 0;
}
5.4.4.16. hb_mem_get_com_buf_with_vaddr
【函数
int32_t hb_mem_get_com_buf_with_vaddr(uint64_t virt_addr, hb_mem_common_buf_t *buf);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [OUT] buf: common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_flush_buf_with_vaddr
5.4.4.17. hb_mem_get_graph_buf_with_vaddr
【函数
int32_t hb_mem_get_graph_buf_with_vaddr(uint64_t virt_addr, hb_mem_graphic_buf_t *buf);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, ) [OUT] buf: graphic buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
int main(int argc, char *argv[])
{
int32_t w = 1920, h = 1080, format = MEM_PIX_FMT_NV12, stride = 0,
vstride = 0;
int64_t flags = HB_MEM_USAGE_CPU_READ_NEVER;
uint64_t tmp_vaddr;
hb_mem_graphic_buf_t graph_buf = {0, };
hb_mem_graphic_buf_t info = {0, };
hb_mem_module_open();
hb_mem_alloc_graph_buf(w, h, format, flags, stride, vstride,
&graph_buf);
for (int i = 0; i < graph_buf.plane_cnt; i++) {
tmp_vaddr = (uint64_t)graph_buf.virt_addr[i] + graph_buf.size[i]/2;
hb_mem_get_graph_buf_with_vaddr(tmp_vaddr, &info);
}
hb_mem_free_buf_with_vaddr(tmp_vaddr);
hb_mem_module_close();
return 0;
}
5.4.4.18. hb_mem_free_buf_with_vaddr
【函数
int32_t hb_mem_free_buf_with_vaddr(uint64_t virt_addr);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 是 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_get_graph_buf_with_vaddr
5.4.4.19. hb_mem_import_com_buf
【函数
int32_t hb_mem_import_com_buf(hb_mem_common_buf_t *buf, hb_mem_common_buf_t *out_buf);
【参数
[IN] buf:输入
的 common buffer [OUT] out_buf:导出
的 common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
导入 common buffer 的
【示例
int main(int argc, char *argv[])
{
int32_t ret;
pid_t child;
uint64_t size = 1024 * 4; // 4k
int64_t flags = HB_MEM_USAGE_CPU_READ_NEVER;
int32_t sd[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
child = fork();
if (child < 0) {
printf("%s Fail to create child process(current %d, parent %d)!\n",
__func__, getpid(), getppid());
exit(1);
} else if (child == 0) {
hb_mem_common_buf_t recv_buf = {0, };
hb_mem_common_buf_t out_buf = {0, };
struct msghdr msg;
struct iovec io;
printf("%s In child process %d(parent %d).\n",
getpid(), getppid());
close(sd[1]);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[0], &msg, 0);
printf("%s [%d:%d] child recv msg 1\n", __func__, getpid(),
getppid());
hb_mem_module_open();
hb_mem_import_com_buf(&recv_buf, &out_buf);
ret = sendmsg(sd[0], &msg, 0);
printf("%s [%d:%d] child send msg to parent to free buffer safely\n",
__func__, getpid(), getppid());
// do anything to the buffer
hb_mem_free_buf(out_buf.fd);
hb_mem_module_close();
close(sd[0]);
printf("%s [%d:%d] child quit\n", __func__, getpid(), getppid());
exit(0);
} else {
hb_mem_common_buf_t recv_buf = {0, };
hb_mem_common_buf_t in_buf = {0, };
struct msghdr msg;
struct iovec io;
printf( "%s In parent process %d(pparent %d).\n",
__func__, getpid(), getppid());
hb_mem_module_open();
hb_mem_alloc_com_buf(size, flags, &in_buf);
close(sd[0]);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &in_buf;
io.iov_len = sizeof(in_buf);
ret = sendmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent send msg to share the buffer\n", __func__,
getpid(), getppid());
// wait message to free buffer
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent recv msg to free the buffer safely\n",
__func__, getpid(), getppid());
hb_mem_free_buf(in_buf.fd);
hb_mem_module_close();
printf("%s [%d:%d] parent quit\n", __func__, getpid(), getppid());
close(sd[1]);
exit(0);
}
return 0;
}
5.4.4.20. hb_mem_import_graph_buf
【函数
int32_t hb_mem_import_graph_buf(hb_mem_graphic_buf_t * buf, hb_mem_graphic_buf_t * out_buf);
【参数
[IN] buf:输入
的 graphic buffer [OUT] out_buf:导出
的 graphic buffer
【返回值】
0 :操作
成功 HB_MEM_ERR_UNKNOWN: 未知
的 错误 HB_MEM_ERR_NOT_ALLOW:操作
不 允许 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
导入 graphic buffer 的
【示例
int main(int argc, char *argv[])
{
int32_t ret;
pid_t child;
int32_t w = 1920, h = 1080, format = MEM_PIX_FMT_NV12, stride = 0,
vstride = 0;
int64_t flags = HB_MEM_USAGE_CPU_READ_OFTEN |
HB_MEM_USAGE_CPU_WRITE_OFTEN;
hb_mem_graphic_buf_t in_info = {0, };
int32_t sd[2];
int32_t status;
for (format = MEM_PIX_FMT_RGB565; format <= MEM_PIX_FMT_YUV400;
format++) {
printf("%s [%d:%d] Start Test format %d scenario 1.\n", TAG,
getpid(), getppid(), format);
socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
child = fork();
if (child < 0) {
printf("%s [%d:%d] Fail to create child process!\n",
TAG, getpid(), getppid());
exit(1);
} else if (child == 0) {
hb_mem_graphic_buf_t recv_buf = {0, };
hb_mem_graphic_buf_t out_buf = {0, };
struct msghdr msg;
struct iovec io;
printf("%s [%d:%d] In child process.\n",
TAG, getpid(), getppid());
close(sd[1]);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[0], &msg, 0);
ASSERT_NE(ret, 0);
ASSERT_EQ(flags, recv_buf.flags);
printf("%s [%d:%d] child recv msg 1\n", TAG, getpid(), getppid());
ASSERT_EQ(hb_mem_import_graph_buf(&recv_buf, &out_buf),
(int32_t)HB_MEM_ERR_MODULE_NOT_FOUND);
ASSERT_EQ(hb_mem_module_open(), 0);
recv_buf.offset[0] = recv_buf.size[0]/2;
recv_buf.offset[1] = recv_buf.size[1]/2;
recv_buf.offset[2] = recv_buf.size[2]/2;
ASSERT_EQ(hb_mem_import_graph_buf(&recv_buf, &out_buf), (int32_t)0);
//compare_import_graphic_buf(&recv_buf, &out_buf, out_buf.plane_cnt);
ASSERT_EQ(out_buf.offset[0], recv_buf.offset[0]);
ASSERT_EQ(out_buf.offset[1], recv_buf.offset[1]);
ASSERT_EQ(out_buf.offset[2], recv_buf.offset[2]);
ASSERT_EQ(do_sys_command(flags & HB_MEM_USAGE_PRIV_MASK), 0);
ret = sendmsg(sd[0], &msg, 0);
ASSERT_NE(ret, 0);
printf("%s [%d:%d] child send msg 2\n", TAG, getpid(), getppid());
ASSERT_EQ(hb_mem_free_buf(out_buf.fd[0]), 0);
ASSERT_NE(do_sys_command(flags & HB_MEM_USAGE_PRIV_MASK), 0);
ASSERT_EQ(hb_mem_module_close(), 0);
ASSERT_NE(do_sys_command(HB_MEM_USAGE_PRIV_MASK), 0);
printf("%s [%d:%d] child quit\n", TAG, getpid(), getppid());
close(sd[0]);
exit(0);
} else {
hb_mem_graphic_buf_t in_buf = {0, };
hb_mem_graphic_buf_t recv_buf = {0, };
struct msghdr msg;
struct iovec io;
printf( "%s [%d:%d] In parent process.\n",
TAG, getpid(), getppid());
close(sd[0]);
ASSERT_EQ(hb_mem_module_open(), 0);
ASSERT_EQ(hb_mem_alloc_graph_buf(w, h, format, flags, stride,
vstride, &in_buf),
(int32_t)0);
ASSERT_EQ(hb_mem_get_graph_buf(in_buf.fd[0], &in_info), (int32_t)0);
ASSERT_EQ(do_sys_command(flags & HB_MEM_USAGE_PRIV_MASK), 0);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &in_buf;
io.iov_len = sizeof(in_buf);
ret = sendmsg(sd[1], &msg, 0);
ASSERT_NE(ret, 0);
printf("%s [%d:%d] parent send msg 1\n", TAG, getpid(), getppid());
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent recv msg 2\n", TAG, getpid(), getppid());
ASSERT_EQ(hb_mem_wait_share_status(in_buf.fd[0], 1, -1), (int32_t)0);
ASSERT_EQ(hb_mem_free_buf(in_buf.fd[0]), 0);
ASSERT_EQ(hb_mem_module_close(), 0);
printf("%s [%d:%d] parent quit\n", TAG, getpid(), getppid());
waitpid(child, &status, 0);
close(sd[1]);
}
return 0;
}
5.4.4.25. hb_mem_create_buf_queue
【函数
int32_t hb_mem_create_buf_queue(hb_mem_buf_queue_t *queue);
【参数
[IN] queue->count:内存
队列 元素 数量,取值 范围 (0, ] [IN] queue->item_size:内存
队列 元素 size,取值 范围 (0, ] [OUT] queue->unique_id:内存
队列 标识符
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_QUEUE_ALREADY_EXIST:内存
队列 已经 创建
【功能
创建
【示例
int main(int argc, char *argv[])
{
hb_mem_common_buf_t com_buf = {0, };
hb_mem_common_buf_t out_buf = {0, };
hb_mem_common_buf_t in_buf = {0, };
hb_mem_buf_queue_t queue;
#define QUEUE_ITEM_CNT 5
int64_t timeout = 0;
int32_t slot_array[QUEUE_ITEM_CNT];
uint32_t i;
memset(&queue, 0x00, sizeof(queue));
// test after open
hb_mem_module_open();
queue.count = QUEUE_ITEM_CNT;
queue.item_size = sizeof(com_buf);
hb_mem_create_buf_queue(&queue);
// producer do dequeue/queue
for (i = 0; i < queue.count; i++) {
hb_mem_dequeue_buf(&queue, &slot_array[i], &out_buf, timeout);
}
for (i = 0; i < queue.count; i++) {
hb_mem_queue_buf(&queue, slot_array[i], &in_buf);
}
for (i = 0; i < queue.count; i++) {
hb_mem_request_buf(&queue, &slot_array[i], &out_buf, timeout);
}
for (i = 0; i < queue.count; i++) {
hb_mem_cancel_buf(&queue, slot_array[i]);
}
// comsumer do request/release
for (i = 0; i < queue.count; i++) {
hb_mem_request_buf(&queue, &slot_array[i], &out_buf, timeout);
}
for (i = 0; i < queue.count; i++) {
hb_mem_release_buf(&queue, slot_array[i]);
}
hb_mem_destroy_buf_queue(&queue);
hb_mem_module_close();
return 0;
}
5.4.4.26. hb_mem_destroy_buf_queue
【函数
int32_t hb_mem_destroy_buf_queue(hb_mem_buf_queue_t *queue);
【参数
[IN] queue:要
销毁 的 内存 队列
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_QUEUE_NOT_FOUND:无法
找到 指定 的 queue,请 检查 queue 的 参数 是否 正常
【功能
销毁
【示例
5.4.4.27. hb_mem_dequeue_buf
【函数
int32_t hb_mem_dequeue_buf(hb_mem_buf_queue_t *queue, int32_t *slot, void *buf, int64_t timeout);
【参数
[IN] queue:内存
队列,参数 应该 非空 [IN] timeout:超时
时间( ms),<0 :阻塞 等待;=0 :立即 返回;>0 :超时 时间 [OUT] slot:内存
队列 元素 索引,取值 范围 [0, count) [OUT] buffer:元素
信息,大小 为 创建 内存 队列 时 指定 的 item_size,参数 应该 非空
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_QUEUE_NOT_FOUND:无法
找到 指定 的 queue,请 检查 queue 的 参数 是否 正常 HB_MEM_ERR_QUEUE_DESTROYED: queue 已经
被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_QUEUE_NO_AVAILABLE_SLOT:没有
可用 的 slot,建议 继续 dequeue HB_MEM_ERR_TIMEOUT: dequeue 超时,可能
的 原因 有 空闲 队列 没有 可用 的 slot,建议 继续 dequeue
【功能
生产者
【示例
5.4.4.28. hb_mem_queue_buf
【函数
int32_t hb_mem_queue_buf(hb_mem_buf_queue_t * queue, int32_t slot, const void *buf);
【参数
[IN] queue:内存
队列,参数 应该 非空 [IN] slot:内存
队列 元素 索引,取值 范围 [0, ) [IN] buf:元素
信息,大小 为 创建 内存 队列 时 指定 的 item_size,参数 应该 非空
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_QUEUE_NOT_FOUND:无法
找到 指定 的 queue,请 检查 queue 的 参数 是否 正常 HB_MEM_ERR_QUEUE_DESTROYED: queue 已经
被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_QUEUE_WRONG_SLOT: slot 异常,建议
检查 slot 是否 为 dequeue 获得
【功能
生产者
【示例
5.4.4.29. hb_mem_request_buf
【函数
int32_t hb_mem_request_buf(hb_mem_buf_queue_t *queue, int32_t *slot, void *buf, int64_t timeout);
【参数
[IN] queue:内存
队列,参数 应该 非空 [IN] timeout:超时
时间( ms),<0 :阻塞 等待;=0 :立即 返回;>0 :超时 时间 [OUT] slot:内存
队列 元素 索引,取值 范围 [0, count) [OUT] buf:元素
信息,大小 为 创建 内存 队列 时 指定 的 item_size,参数 应该 非空
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_QUEUE_NOT_FOUND:无法
找到 指定 的 queue,请 检查 queue 的 参数 是否 正常 HB_MEM_ERR_QUEUE_DESTROYED: queue 已经
被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_QUEUE_NO_AVAILABLE_SLOT:没有
可用 的 slot,建议 继续 request HB_MEM_ERR_TIMEOUT: request 超时,可能
的 原因 有 queued 队列 没有 可用 的 slot,建议 继续 request
【功能
消费者
【示例
5.4.4.30. hb_mem_release_buf
【函数
int32_t hb_mem_release_buf(hb_mem_buf_queue_t * queue, int32_t slot);
【参数
[IN] queue:内存
队列,参数 应该 非空 [IN] slot:内存
队列 元素 索引,取值 范围 [0, count)
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_QUEUE_NOT_FOUND:无法
找到 指定 的 queue,请 检查 queue 的 参数 是否 正常 HB_MEM_ERR_QUEUE_DESTROYED: queue 已经
被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_QUEUE_WRONG_SLOT: slot 异常,建议
检查 slot 是否 为 request 获得
【功能
消费者
【示例
5.4.4.31. hb_mem_cancel_buf
【函数
int32_t hb_mem_cancel_buf(hb_mem_buf_queue_t *queue, int32_t slot);
【参数
[IN] queue:内存
队列,参数 应该 非空 [IN] slot:内存
队列 元素 索引,取值 范围 [0, count)
【返回值】
0 :操作
成功 HB_MEM_ERR_UNKNOWN:未知
的 错误 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
生产者
【示例
5.4.4.32. hb_mem_pool_create
【函数
int32_t hb_mem_pool_create(uint64_t size, int64_t flags, hb_mem_pool_t * pool);
【参数
[IN] size: Memory pool 的
大小,取值 范围 (0 ,] [IN] flags: Memory pool 的 buffer 属性,见 :hbmem 内存
分配 属性 [OUT] pool:导出
的 memory pool
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
创建
【示例
int main(int argc, char *argv[])
{
uint64_t i, num, size = 1024 * 1024 * 4, alloc_size; // 4M
int64_t flags;
hb_mem_common_buf_t com_buf = {0, };
hb_mem_common_buf_t out_buf = {0, };
hb_mem_pool_t pool = {0, };
hb_mem_pool_t out_pool = {0, };
hb_mem_common_buf_t import_buf = {0, };
char * tmp_vaddr;
char tmp_val = 0x5a;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN |
HB_MEM_USAGE_CPU_WRITE_OFTEN ;
hb_mem_pool_create(size, flags, &pool);
hb_mem_get_com_buf(pool.fd, &com_buf);
num = size / pool.page_size;
alloc_size = pool.page_size;
for (i = 0; i < num; i++) {
hb_mem_pool_alloc_buf(pool.fd, alloc_size, &out_buf);
tmp_vaddr = (char *)out_buf.virt_addr;
*tmp_vaddr = tmp_val;
hb_mem_pool_get_info(pool.fd, &out_pool);
hb_mem_pool_free_buf((uint64_t)out_buf.virt_addr);
}
hb_mem_pool_destroy(pool.fd);
hb_mem_module_close();
return 0;
}
5.4.4.33. hb_mem_pool_destroy
【函数
int32_t hb_mem_pool_destroy(int32_t fd);
【参数
[IN] fd: Memory pool 的
文件 描述符,取值 范围 [0,)
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_POOL_DESTROYED:内存
池已 被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_POOL_BUSY:内存
池 无法 销毁,内存 池中 有 未 释放 内存 片,建议 用户 先 释放 从 内存 池中 分配 的 内存 片,再 销毁 内存 池
【功能
销毁
【示例
5.4.4.34. hb_mem_pool_alloc_buf
【函数
int32_t hb_mem_pool_alloc_buf(int32_t fd, uint64_t size, hb_mem_common_buf_t * buf);
【参数
[IN] fd: Memory pool 的
文件 描述符,取值 范围 [0,) [IN] size: Buffer 的
大小,取值 范围 [0,) [OUT] buf: common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_POOL_NOT_FOUND:无法
找到 指定 的 memory pool,请 检查 参数 是否 正常 HB_MEM_ERR_POOL_DESTROYED:内存
池已 被 销毁,建议 检查 代码 逻辑
【功能
从
【示例
5.4.4.35. hb_mem_pool_free_buf
【函数
int32_t hb_mem_pool_free_buf(uint64_t virt_addr);
【参数
[IN] virt_addr:虚拟地址,取值
范围 (0,]
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级) HB_MEM_ERR_POOL_DESTROYED:内存
池已 被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_POOL_NOT_FOUND:无法
找到 指定 的 memory pool,请 检查 参数 是否 正常
【功能
释放
【示例
5.4.4.36. hb_mem_pool_get_info
【函数
int32_t hb_mem_pool_get_info(int32_t fd, hb_mem_pool_t *pool);
【参数
[IN] fd: Memory pool 的
文件 描述符,取值 范围 [0,) [OUT] pool: memory pool 信息
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_POOL_DESTROYED:内存
池已 被 销毁,建议 检查 代码 逻辑 HB_MEM_ERR_POOL_NOT_FOUND:无法
找到 指定 的 memory pool,请 检查 参数 是否 正常
【功能
获取
【示例
5.4.4.42. hb_mem_get_buf_type_with_vaddr
【函数
int32_t hb_mem_get_buf_type_with_vaddr(uint64_t virt_addr, hb_mem_buffer_type_t * type);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [OUT] type: buffer 类型
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
获取 virt_addr 对应 buffer 的
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
hb_mem_buffer_type_t type;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_buf_type_with_vaddr((uint64_t)com_buf.virt_addr, &type);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.43. hb_mem_get_buf_type_and_buf_with_vaddr
【函数
int32_t hb_mem_get_buf_type_and_buf_with_vaddr(uint64_t virt_addr, hb_mem_buffer_type_t * type, hb_mem_common_buf_t * com_buf, hb_mem_graphic_buf_t * graph_buf);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [OUT] type: buffer 类型
[OUT] com_buf: common buffer
[OUT] graph_buf: graph buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
获取 virt_addr 对应 buffer 的
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
hb_mem_buffer_type_t type;
hb_mem_common_buf_t com_outbuf = {0, };
hb_mem_graphic_buf_t graph_outbuf = {0, };
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_buf_type_and_buf_with_vaddr((uint64_t)com_buf.virt_addr, &type, &com_outbuf, &graph_outbuf);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.44. hb_mem_get_buffer_process_info
【函数
int32_t hb_mem_get_buffer_process_info(uint64_t virt_addr, int32_t * pid, int32_t num, int32_t * ret_num);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [IN] pid:进程 pid 数组,存储
返回 的 进程 pid [IN] num:进程 pid 数组
大小,取值 范围 (0, ) [OUT] ret_num:持有 virt_addr 对应 buffer 的
进程 个数,取值 范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t pid[16];
int32_t ret_num = 0;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_buffer_process_info((uint64_t)com_buf.virt_addr, pid, 16, &ret_num);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.46. hb_mem_get_consume_info
【函数
int32_t hb_mem_get_consume_info(int32_t fd, int32_t * share_consume_cnt);
【参数
[IN] fd: buffer fd,取值
范围 (0, ) [OUT] share_consume_cnt: buffer consume cnt,取值
范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 获取
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t share_consume_cnt;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_consume_info(com_buf.fd, &share_consume_cnt);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.47. hb_mem_get_consume_info_with_vaddr
【函数
int32_t hb_mem_get_consume_info_with_vaddr(uint64_t virt_addr, int32_t * share_consume_cnt);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [OUT] share_consume_cnt: buffer consume cnt,取值
范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过 virt_addr 获取
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t share_consume_cnt;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_get_consume_info_with_vaddr((uint64_t)com_buf.virt_addr, &share_consume_cnt);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.48. hb_mem_wait_consume_status
【函数
int32_t hb_mem_wait_consume_status(int32_t fd, int32_t share_consume_cnt, int64_t timeout);
【参数
[IN] fd: buffer fd,取值
范围 (0, ) [IN] share_consume_cnt: buffer consume cnt,取值
范围 [0, ) [IN] timeout:超时
时间,取值 范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_WAIT_SHARE_FAILURE:等待 share client 状态
失败
【功能
等待 fd 对应 buffer 的 consume cnt 变成 share_consume_cnt,超时
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t share_consume_cnt = 0;
int32_t timeout = 100;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_wait_consume_status(com_buf.fd, share_consume_cnt, timeout);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.49. hb_mem_wait_consume_status_with_vaddr
【函数
int32_t hb_mem_wait_consume_status_with_vaddr(uint64_t virt_addr, int32_t share_consume_cnt, int64_t timeout);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [IN] share_consume_cnt: consume cnt,取值
范围 [0, ) [IN] timeout:超时
时间,取值 范围 [0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级) HB_MEM_ERR_WAIT_SHARE_FAILURE:等待 share client 状态
失败
【功能
等待 virt_addr 对应 buffer 的 consume cnt 变成 share_consume_cnt,超时
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t share_consume_cnt = 0;
int32_t timeout = 100;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_wait_consume_status_with_vaddr((uint64_t)com_buf.virt_addr, share_consume_cnt, timeout);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.50. hb_mem_inc_com_buf_consume_cnt
【函数
int32_t hb_mem_inc_com_buf_consume_cnt(hb_mem_common_buf_t * buf);
【参数
[IN] buf: common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
增加
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t timeout = 100;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_inc_com_buf_consume_cnt(&com_buf);
hb_mem_dec_consume_cnt(com_buf.fd);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.51. hb_mem_inc_graph_buf_consume_cnt
【函数
int32_t hb_mem_inc_graph_buf_consume_cnt(hb_mem_graphic_buf_t * buf);
【参数
[IN] buf: graphic buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
增加
【示例
int main(int argc, char *argv[])
{
int64_t flags;
hb_mem_graphic_buf_t graph_buf = {0, };
int32_t w = 1920, h = 1080, format = MEM_PIX_FMT_NV12, stride = 0, vstride = 0;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_graph_buf(w, h, format, flags, stride, vstride,
&graph_buf);
hb_mem_inc_graph_buf_consume_cnt(&graph_buf);
hb_mem_dec_consume_cnt(graph_buf.fd[0]);
hb_mem_free_buf(graph_buf.fd[0]);
hb_mem_module_close();
return 0;
}
5.4.4.52. hb_mem_dec_consume_cnt
【函数
int32_t hb_mem_dec_consume_cnt(int32_t fd);
【参数
[IN] fd: buffer fd,取值
范围 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 减少
【示例
参考 :hb_mem_inc_com_buf_consume_cnt
5.4.4.53. hb_mem_dec_consume_cnt_with_vaddr
【函数
int32_t hb_mem_dec_consume_cnt_with_vaddr(uint64_t virt_addr);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t com_buf = {0, };
int32_t timeout = 100;
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN
| HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &com_buf);
hb_mem_inc_com_buf_consume_cnt(&com_buf);
hb_mem_dec_consume_cnt_with_vaddr((uint64_t)com_buf.virt_addr);
hb_mem_free_buf(com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.54. hb_mem_import_com_buf_with_paddr
【函数
int32_t hb_mem_import_com_buf_with_paddr(uint64_t phys_addr,
uint64_t size, int64_t flags, hb_mem_common_buf_t * buf);
【参数
[IN] phys_addr:需要 import 的 buffer 的
地址,可以 带 偏移量,取值 范围 (0, ) [IN] size: import 的 buffer size,需要
针对 PAGE_SIZE 对齐,取值 范围 (0, ) [IN] flags: import 的 buffer flag,取值
范围 [0, ) [OUT] buf: import 返回
的 common buffer
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
通过
由于hb_mem_import_com_buf。 hb_mem_import_com_buf_with_paddr 导
入hb_mem_free_buf_with_vaddr 接口
【示例
int main(int argc, char *argv[])
{
uint32_t size = 1024 * 8, out_size; // 8k
uint64_t flags;
const char * lable = NULL;
hbmem_addr_t start, vaddr;
uint64_t paddr = 0;
hb_mem_common_buf_t com_buf = {0, };
hb_mem_common_buf_t out_buf = {0, };
flags = BACKEND_TYPE(BACKEND_ION_CMA) | MEM_CACHEABLE;
vaddr = hbmem_alloc(size, flags, lable);
hbmem_info(vaddr, &start, &out_size);
paddr = hbmem_phyaddr(vaddr);
hb_mem_get_com_buf_with_vaddr(vaddr, &com_buf);
hb_mem_import_com_buf_with_paddr(paddr, com_buf.size, flags, &out_buf);
hb_mem_free_buf_with_vaddr((uint64_t)out_buf.virt_addr);
hbmem_free(vaddr);
return 0;
}
5.4.4.55. hb_mem_dma_copy
【函数
int32_t hb_mem_dma_copy(uint64_t dst_vaddr, uint64_t src_vaddr, uint64_t size);
【参数
[IN] dst_vaddr:目的
虚拟地址,可以 是 偏移 后 的 虚拟地址,取值 范围 (0, ) [IN] src_vaddr:源
虚拟地址,可以 是 偏移 后 的 虚拟地址,取值 范围 (0, ) [IN] size: dma 的
内存大小,取值 范围 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
将
【示例
int main(int argc, char *argv[])
{
int64_t flags;
uint64_t size = 1024 * 4; // 4k
hb_mem_common_buf_t dst_com_buf = {0, };
hb_mem_common_buf_t src_com_buf = {0, };
hb_mem_module_open();
flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN | HB_MEM_USAGE_CACHED;
hb_mem_alloc_com_buf(size, flags, &dst_com_buf);
hb_mem_alloc_com_buf(size, flags, &src_com_buf);
hb_mem_dma_copy((uint64_t)dst_com_buf.virt_addr, (uint64_t)src_com_buf.virt_addr, size);
hb_mem_free_buf(dst_com_buf.fd);
hb_mem_free_buf(src_com_buf.fd);
hb_mem_module_close();
return 0;
}
5.4.4.56. hb_mem_alloc_graph_buf_group
【函数
int32_t hb_mem_alloc_graph_buf_group(int32_t * w, int32_t * h, int32_t * format, int64_t * flags, int32_t * stride,
int32_t * vstride, hb_mem_graphic_buf_group_t * buf_group, uint32_t bitmap);
【参数
[IN] w:图像
宽度 数组 [IN] h:图像
高度 数组 [IN] format:图像格式
数组 , 见 :hbmem 图像格式 [IN] flags: buffer 属性
数组,见 : hbmem 内存 分配 属性 [IN] stride:图像
水平 跨距 数组 [IN] vstride:图像
垂直 跨距 数组 [OUT] buf_group: graphic buffer group
[IN] bitmap:表示
有效 graphic buffer 的 位 图
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
申请
【示例
int main(int argc, char *argv[])
{
hb_mem_graphic_buf_group_t buf_group = {0, };
hb_mem_graphic_buf_group_t info = {0, };
hb_mem_graphic_buf_group_t out_buf = {0, };
hb_mem_graphic_buf_t graph_buf = {0, };
hb_mem_common_buf_t com_buf = {0, };
hb_mem_buffer_type_t *type;
uint32_t bitmap = 0xFF;
int32_t w[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t h[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t format[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t stride[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t vstride[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int64_t flags[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t i;
// open module
hb_mem_module_open();
// test DMA heap type
for (i = 0; i < HB_MEM_MAXIMUM_GRAPH_BUF; i++) {
if (bitmap & (1u << i)) {
w[i] = 1280;
h[i] = 720;
format[i] = MEM_PIX_FMT_NV12;
flags[i] = HB_MEM_USAGE_PRIV_HEAP_DMA | HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN;
stride[i] = 0;
vstride[i] = 0;
}
}
hb_mem_alloc_graph_buf_group(w, h, format, flags, stride, vstride, &buf_group, bitmap);
hb_mem_get_graph_buf_group(buf_group.graph_group[0].fd[0], &info);
hb_mem_get_graph_buf_group_with_vaddr((uint64_t)buf_group.graph_group[0].virt_addr[0], &info);
hb_mem_get_buf_and_type_with_vaddr((uint64_t)buf_group.graph_group[0].virt_addr[0], type, &com_buf, &graph_buf, &info);
hb_mem_import_graph_buf_group(&buf_group, &out_buf);
hb_mem_inc_graph_buf_group_consume_cnt(&buf_group);
hb_mem_dec_consume_cnt(buf_group.graph_group[0].fd[0]);
hb_mem_free_buf(buf_group.graph_group[0].fd[0]);
hb_mem_free_buf(out_buf.graph_group[0].fd[0]);
hb_mem_module_close();
return 0;
}
5.4.4.57. hb_mem_import_graph_buf_group
【函数
int32_t hb_mem_import_graph_buf_group(hb_mem_graphic_buf_group_t * in_group, hb_mem_graphic_buf_group_t * out_group);
【参数
[IN] in_group:输入
的 graphic buffer group [OUT] out_group:输出
共享 的 graphic buffer group
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INSUFFICIENT_MEM:内存不足,建议
检查 ion 预留 内存空间 和 系统 内存 使用 情况 HB_MEM_ERR_TOO_MANY_FD:文件
句柄 个数 超过 上限,无法 分配 更 多 文件 句柄,建议 使用 ulimit增加用户 可 打开 的 文件 句柄 上限
【功能
共享
【示例
int main(int argc, char *argv[])
{
int32_t ret;
pid_t child;
int32_t input_format = MEM_PIX_FMT_NV12, i;
hb_mem_graphic_buf_group_t in_info = {0, };
int32_t sd[2];
int32_t status, m;
uint32_t bitmap = 0xFF;
int32_t w[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t h[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t format[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t stride[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int32_t vstride[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
int64_t flags[HB_MEM_MAXIMUM_GRAPH_BUF] = {0, };
for (m = 0; m < HB_MEM_MAXIMUM_GRAPH_BUF; m++) {
if (bitmap & (1u << m)) {
w[m] = 1280;
h[m] = 720;
flags[m] = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN;
stride[m] = 0;
vstride[m] = 0;
}
}
printf("%s [%d:%d] Start Test format %d scenario 1.\n", TAG, getpid(), getppid(), input_format);
socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
child = fork();
if (child < 0) {
printf("%s [%d:%d] Fail to create child process!\n",
TAG, getpid(), getppid());
exit(1);
} else if (child == 0) {
hb_mem_graphic_buf_group_t recv_buf = {0, };
hb_mem_graphic_buf_group_t out_buf = {0, };
struct msghdr msg;
struct iovec io;
printf("%s [%d:%d] In child process.\n",
TAG, getpid(), getppid());
close(sd[1]);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[0], &msg, 0);
printf("%s [%d:%d] child recv msg 1\n", TAG, getpid(), getppid());
hb_mem_module_open();
hb_mem_import_graph_buf_group(&recv_buf, &out_buf);
ret = sendmsg(sd[0], &msg, 0);
printf("%s [%d:%d] child send msg 2\n", TAG, getpid(), getppid());
ret = recvmsg(sd[0], &msg, 0);
printf("%s [%d:%d] child recv msg 3\n", TAG, getpid(), getppid());
hb_mem_free_buf(out_buf.graph_group[0].fd[0]);
ASSERT_EQ(hb_mem_module_close(), 0);
printf("%s [%d:%d] child quit\n", TAG, getpid(), getppid());
close(sd[0]);
exit(0);
} else {
hb_mem_graphic_buf_group_t in_buf = {0, };
hb_mem_graphic_buf_group_t recv_buf = {0, };
struct msghdr msg;
struct iovec io;
printf( "%s [%d:%d] In parent process.\n",
TAG, getpid(), getppid());
close(sd[0]);
hb_mem_module_open();
for (m = 0; m < HB_MEM_MAXIMUM_GRAPH_BUF; m++) {
if (bitmap & (1u << m)) {
format[m] = input_format;
}
}
hb_mem_alloc_graph_buf_group(w, h, format, flags, stride, vstride, &in_buf, bitmap);
hb_mem_get_graph_buf_group(in_buf.graph_group[0].fd[0], &in_info);
memset(&msg, 0x00, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
io.iov_base = &in_buf;
io.iov_len = sizeof(in_buf);
ret = sendmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent send msg 1\n", TAG, getpid(), getppid());
io.iov_base = &recv_buf;
io.iov_len = sizeof(recv_buf);
ret = recvmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent recv msg 2\n", TAG, getpid(), getppid());
hb_mem_free_buf(in_buf.graph_group[0].fd[0]);
io.iov_base = &in_buf;
io.iov_len = sizeof(in_buf);
ret = sendmsg(sd[1], &msg, 0);
printf("%s [%d:%d] parent send msg 3\n", TAG, getpid(), getppid());
hb_mem_module_close();
printf("%s [%d:%d] parent quit\n", TAG, getpid(), getppid());
waitpid(child, &status, 0);
close(sd[1]);
}
return 0;
}
5.4.4.58. hb_mem_get_graph_buf_group
【函数
int32_t hb_mem_get_graph_buf_group(int32_t fd, hb_mem_graphic_buf_group_t * buf_group);
【参数
[IN] fd: buffer fd, graphic buffer group 中
任意 一个 fd,取值 范围 (0, ) [OUT] buf_group:通过 fd 获取
到 的 graphic buffer group
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd( graphic buffer group 中
【示例
参考 :hb_mem_alloc_graph_buf_group
5.4.4.59. hb_mem_get_graph_buf_group_with_vaddr
【函数
int32_t hb_mem_get_graph_buf_group_with_vaddr(uint64_t virt_addr, hb_mem_graphic_buf_group_t * buf_group);
【参数
[IN] virt_addr:虚拟地址, graphic buffer group 中
任意 一个 虚拟地址,可以 是 偏移 后 的 虚拟地址,取值 范围 (0, ) [OUT] buf_group:通过
虚拟地址 获取 到 的 graphic buffer group
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_alloc_graph_buf_group
5.4.4.60. hb_mem_inc_graph_buf_group_consume_cnt
【函数
int32_t hb_mem_inc_graph_buf_group_consume_cnt(hb_mem_graphic_buf_group_t * buf_group);
【参数
[IN] buf_group: graphic buffer group
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性
【功能
增加 graphic buffer group 中
5.4.4.61. hb_mem_get_buf_and_type_with_vaddr
【函数
int32_t hb_mem_get_buf_and_type_with_vaddr(uint64_t virt_addr, hb_mem_buffer_type_t * type, hb_mem_common_buf_t * com_buf,
hb_mem_graphic_buf_t * graph_buf, hb_mem_graphic_buf_group_t * graph_group);
【参数
[IN] virt_addr:虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, ) [OUT] type: buffer 类型
[OUT] com_buf: common buffer
[OUT] graph_buf: graphic buffer
[OUT] graph_group: graphic buffer group
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_alloc_graph_buf_group
5.4.4.62. hbmem_alloc
【函数
hbmem_addr_t hbmem_alloc(uint32_t size, uint64_t flag, const char
label);
【参数
[IN] size:需要
分配 的 内存空间 大小 [IN] flag:申请
标识符,具体 见 下 对 flag 的 详细 说明 [IN] label:字符串
以 标识 该 内存空间(后续 增加 的 debug 功能 会 使用 该字段 进行 区分,取 <10 字符 部分),如果 不 对 内存空间 做 标记 设置 为 NULL
【返回值】
0 :申请
失败 非 0 :申请
成功,该 hbmem_addr_t 的 值 可 作为 虚拟地址 被 用户 直接 使用
【功能
分配 hobot memory, 分配
【示例
int main(int argc, char *argv[])
{
uint32_t major, minor, patch;
uint32_t size = 1024 * 8, i, out_size, size2; // 8k
uint64_t flags = BACKEND_ION_CMA;
const char * lable = NULL;
hbmem_addr_t dst_vaddr, src_vaddr, start, vaddr, vaddr2, vaddr_out;
uint64_t paddr = 0;
uint8_t *tmp_vaddr;
uint8_t value = 55;
int32_t share_id = 1;
hb_mem_common_buf_t com_buf = {0, };
flags = BACKEND_TYPE(BACKEND_ION_CMA) | MEM_CACHEABLE;
hbmem_version(&major, &minor, &patch);
vaddr = hbmem_alloc(size, flags, lable);
hbmem_info(vaddr, &start, &out_size);
paddr = hbmem_phyaddr(vaddr);
vaddr_out = hbmem_virtaddr(vaddr);
hbmem_is_cacheable(vaddr);
hb_mem_get_com_buf_with_vaddr(vaddr, &com_buf);
paddr = com_buf.phys_addr;
size2 = com_buf.size;
share_id = com_buf.share_id;
vaddr2 = hbmem_mmap_with_share_id(paddr, size2, flags, share_id);
share_id = 0;
hbmem_get_share_id(vaddr2, &share_id);
hbmem_munmap(vaddr2);
vaddr2 = hbmem_mmap(paddr, size, flags);
hbmem_munmap(vaddr2);
hbmem_free(vaddr);
dst_vaddr = hbmem_alloc(size, flags, lable);
src_vaddr = hbmem_alloc(size, flags, lable);
tmp_vaddr = (uint8_t *)src_vaddr;
for (i = 0; i < size; i++) {
tmp_vaddr[i] = value;
}
hbmem_cache_clean(src_vaddr, size);
hbmem_dmacpy(dst_vaddr, src_vaddr, size);
hbmem_cache_invalid(dst_vaddr, size);
hbmem_free(src_vaddr);
hbmem_free(dst_vaddr);
return 0;
}
5.4.4.63. hbmem_free
【函数
void hbmem_free(hbmem_addr_t addr);
【参数
[IN] addr: hbmem_alloc 返回
的 有效 hbmem_addr_t
【返回值】
无
【功能
释放
【示例
参考 :hbmem_alloc
5.4.4.64. hbmem_mmap
【函数
hbmem_addr_t hbmem_mmap(uint64_t phyaddr, uint32_t size, uint64_t
flag);
【参数
[IN] phyaddr:合法
物理地址 内存空间 的 起始 地址( PAGE_SIZE 对齐) [IN] size:需要
映射 的 内存空间 大小 [IN] flag:申请
标识符
【返回值】
0 :映射
失败 非 0 :映射
成功,该 hbmem_addr_t 的 值 可 作为 虚拟地址 被 用户 直接 使用
【功能
将
【示例
参考 :hbmem_alloc
5.4.4.65. hbmem_munmap
【函数
void hbmem_munmap(hbmem_addr_t addr);
【参数
[IN] addr: hbmem_mmap 返回
的 有效 hbmem_addr_t
【返回值】
无
【功能
释放
【示例
参考 :hbmem_alloc
5.4.4.66. hbmem_phyaddr
【函数
uint64_t hbmem_phyaddr(hbmem_addr_t addr);
【参数
[IN] addr: hbmem_mmap 返回
的 有效 hbmem_addr_t
【返回值】
0 :无效
物理地址,表明 传入 的 hbmem_addr_t 非 有效 hbmem 中 的 地址 非 0 :物理地址
【功能
获取 hbmem 内存空间
【示例
参考 :hbmem_alloc
5.4.4.67. hbmem_dmacpy
【函数
int32_t hbmem_dmacpy(hbmem_addr_t dst, hbmem_addr_t src, uint32_t
size);
【参数
[IN] dst:目标 hbmem 空间
的 起始 地址 [IN] src:源 hbmem 空间
的 起始 地址 [IN] size:需要
拷贝 的 内存空间 大小
【返回值】
0 :传输
成功 <0 :失败
【功能
使用
【示例
参考 :hbmem_alloc
5.4.4.68. hbmem_virtaddr
【函数
uint64_t hbmem_virtaddr(hbmem_addr_t addr);
【参数
[IN] addr:有效 hbmem_addr_t
【返回值】
0 :无效
虚拟地址,表明 传入 的 hbmem_addr_t 非 有效 hbmem 中 的 地址 非 0 :虚拟地址
【功能
获取 hbmem 内存空间
【示例
参考 :hbmem_alloc
5.4.4.69. hbmem_info
【函数
int32_t hbmem_info(hbmem_addr_t addr, hbmem_addr_t *start, uint32_t
*size);
【参数
[IN] addr: 有效 hbmem_addr_t
[IN] start: 传入
归属 hbmem 内存空间 的 buffer 起始 地址 [IN] size: 传入
归属 的 hbmem 内存空间 的 buffer 大小
【返回值】
<0: 该 hbmem_addr_t 不
属于 任何 hbmem 内存空间,此时 start/size 参数 不会 被 赋值 =0: 该 hbmem_addr_t 所属
任何 hbmem 内存空间 的 类型。 0 : UNKNOWN 未知; 1 : ALLOCED 通过 hbmem_alloc 申请 的 空间; 2 : MAPPED 通过 hbmem_mmap 映射 的 空间
【功能
获取
【示例
参考 :hbmem_alloc
5.4.4.70. hbmem_version
【函数
int32_t hbmem_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
【参数
[OUT] major:版本 major 值
[OUT] minor:版本 minor 值
[OUT] patch:版本 patch 值
【返回值】
0 :获取
成功 <0: 参数
异常,有 为 NULL 的 参数 传入
【功能
获取
【示例
参考 :hbmem_alloc
5.4.4.71. hbmem_is_cacheable
【函数
int32_t hbmem_is_cacheable(hbmem_addr_t addr);
【参数
[IN] addr:有效 hbmem_addr_t
【返回值】
<0 :该
地址 为 无效 hbmem_addr_t 0 : uncache 类型
0 : cacheable 类型
【功能
获取 hbmem_addr_t 对应 hbmem 空间
【示例
参考 :hbmem_alloc
5.4.4.72. hbmem_cache_invalid
【函数
void hbmem_cache_invalid(hbmem_addr_t addr, uint32_t size);
【参数
[IN] addr:有效 hbmem_addr_t
[IN] size:操作
的 空间 大小
【返回值】
无
【功能
对 hbmem 内存空间
【示例
参考 :hbmem_alloc
5.4.4.73. hbmem_cache_clean
【函数
void hbmem_cache_clean(hbmem_addr_t addr, uint32_t size);
【参数
[IN] addr:有效 hbmem_addr_t
[IN] size:操作
的 空间 大小
【返回值】
无
【功能
对 hbmem 内存空间
【示例
参考 :hbmem_alloc
5.4.4.76. hb_mem_inc_user_consume_cnt
【函数
int32_t hb_mem_inc_user_consume_cnt(int32_t hb_fd);
【参数
[IN] hb_fd: buffer 相关
文件 描述符
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 增加
【示例
int main(int argc, char *argv[])
{
int32_t ret = 0;
uint64_t size = 4 * 1024 * 1024;
int64_t flags = HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN | HB_MEM_USAGE_CACHED;
hb_mem_common_buf_t com_buf = {0, };
ret = hb_mem_module_open();
if (ret != 0) {
printf("hb_mem_module_open failed\n");
return ret;
}
ret = hb_mem_alloc_com_buf(size, flags, &com_buf);
if (ret != 0) {
printf("hb_mem_alloc_com_buf failed\n");
(void)hb_mem_module_close();
return ret;
}
printf("alloc com buf, share_id: %d\n", com_buf.share_id);
do_sys_command(flags & HB_MEM_USAGE_PRIV_MASK);
//inc/dec user consume with fd
ret = hb_mem_inc_user_consume_cnt(com_buf.fd);
if (ret != 0) {
printf("hb_mem_inc_user_consume_cnt failed\n");
(void)hb_mem_module_close();
return ret;
}
ret = hb_mem_dec_user_consume_cnt(com_buf.fd);
if (ret != 0) {
printf("hb_mem_dec_user_consume_cnt failed\n");
(void)hb_mem_module_close();
return ret;
}
//inc/dec user consume with vaddr
ret = hb_mem_inc_user_consume_cnt_with_vaddr((uint64_t)com_buf.virt_addr);
if (ret != 0) {
printf("hb_mem_inc_user_consume_cnt_with_vaddr failed\n");
(void)hb_mem_module_close();
return ret;
}
ret = hb_mem_dec_user_consume_cnt_with_vaddr((uint64_t)com_buf.virt_addr);
if (ret != 0) {
printf("hb_mem_dec_user_consume_cnt_with_vaddr failed\n");
(void)hb_mem_module_close();
return ret;
}
ret = hb_mem_free_buf(com_buf.fd);
if (ret != 0) {
printf("hb_mem_free_buf failed\n");
(void)hb_mem_module_close();
return ret;
}
printf("free com buf\n");
do_sys_command(flags & HB_MEM_USAGE_PRIV_MASK);
ret = hb_mem_module_close();
if (ret != 0) {
printf("hb_mem_module_close failed\n");
return ret;
}
return 0;
}
5.4.4.77. hb_mem_dec_user_consume_cnt
【函数
int32_t hb_mem_dec_user_consume_cnt(int32_t hb_fd);
【参数
[IN] hb_fd: buffer 相关
文件 描述符
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_FD:文件
句柄 异常,存在 异常 的 文件 句柄,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息
【功能
通过 fd 减少
【示例
参考 :hb_mem_inc_user_consume_cnt
5.4.4.78. hb_mem_inc_user_consume_cnt_with_vaddr
【函数
int32_t hb_mem_inc_user_consume_cnt_with_vaddr(uint64_t virt_addr);
【参数
[IN] virt_addr: 虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_inc_user_consume_cnt
5.4.4.79. hb_mem_dec_user_consume_cnt_with_vaddr
【函数
int32_t hb_mem_dec_user_consume_cnt_with_vaddr(uint64_t virt_addr);
【参数
[IN] virt_addr: 虚拟地址,可以
是 偏移 后 的 虚拟地址,取值 范围 (0, )
【返回值】
0 :成功
HB_MEM_ERR_MODULE_NOT_FOUND:内存模块
并未 打开,建议 先 打开 内存模块 HB_MEM_ERR_INVALID_PARAMS:无效
参数,建议 按照 日志 提醒 检查 输入 参数 的 有效性 HB_MEM_ERR_INVALID_VADDR:虚拟地址
异常,存在 异常 的 虚拟地址,无法 找到 对应 的 buffer 信息,可 查看 日志 获取 具体 信息(调 高 日志 等级)
【功能
通过
【示例
参考 :hb_mem_inc_user_consume_cnt
5.4.5. 数据结构
5.4.5.1. hb_mem_common_buf_t
/**
* @struct hb_mem_common_buf_t
* Define the descriptor of common buffer.
*/
typedef struct hb_mem_common_buf_t {
int32_t fd; /**< File descriptors of the buffer.*/
int32_t share_id; /**< Share id of the buffer.*/
int64_t flags; /**< Buffer flags for allocation */
uint64_t size; /**< Total Buffer size specified by user during allocation.*/
uint8_t *virt_addr; /**< Buffer starting virtual address.*/
/**
* - Note: It's not recommended to use or transfer the physical address directly.
* There is no memory object to keep track of the physical address.
*/
uint64_t phys_addr; /**< Buffer starting physical address.*/
uint64_t offset; /**< Buffer offset.*/
} hb_mem_common_buf_t;
5.4.5.2. hb_mem_graphic_buf_t
/**
* @struct hb_mem_graphic_buf_t
* Define the descriptor of graphic buffer.
*/
typedef struct hb_mem_graphic_buf_t {
//#define MAX_GRAPHIC_BUF_COMP 3
int32_t fd[MAX_GRAPHIC_BUF_COMP]; /**< File descriptors of the buffer for each component.*/
/**
* Values [1, MAX_GRAPHIC_BUF_COMP]
*/
int32_t plane_cnt; /**< Plane count of this graphic buffer*/
int32_t format; /**< Buffer format for allocation.@mem_pixel_format_t*/
int32_t width; /**< Buffer width.*/
int32_t height; /**< Buffer height.*/
int32_t stride; /**< Buffer horizontal stride.*/
int32_t vstride; /**< Buffer vertical stride.*/
int32_t is_contig; /**< Buffer physical memory is contiguous.@mem_usage_t*/
int32_t share_id[MAX_GRAPHIC_BUF_COMP]; /**< Share id of the buffer.*/
int64_t flags; /**< Buffer flags for allocation.@mem_usage_t*/
uint64_t size[MAX_GRAPHIC_BUF_COMP]; /**< Total Buffer size for each component.*/
uint8_t *virt_addr[MAX_GRAPHIC_BUF_COMP]; /**< Buffer virtual address for each component.*/
/**
* - Note: It's not recommended to use or transfer the physical address directly.
* There is no memory object to keep track of the physical address.
*/
uint64_t phys_addr[MAX_GRAPHIC_BUF_COMP]; /**< Buffer physical address for each component.*/
uint64_t offset[MAX_GRAPHIC_BUF_COMP]; /**< Buffer offset.*/
} hb_mem_graphic_buf_t;
5.4.5.3. hb_mem_graphic_buf_group_t
/**
* @struct hb_mem_graphic_buf_group_t
* Define the descriptor of graphic buffer group
*/
typedef struct hb_mem_graphic_buf_group_t {
//#define HB_MEM_MAXIMUM_GRAPH_BUF 8
hb_mem_graphic_buf_t graph_group[HB_MEM_MAXIMUM_GRAPH_BUF]; /**graphic buffer array*/
int32_t group_id; /**< graphic buffer group id which alloc from ION driver*/
uint32_t bit_map; /**< graphic buffer group bitmap*/
} hb_mem_graphic_buf_group_t;
5.4.5.4. hb_mem_buf_queue_t
/**
* @struct hb_mem_buf_queue_t
* Define the descriptor of buffer queue.
*/
typedef struct hb_mem_buf_queue_t {
uint64_t unique_id; /**< Uinque id specified by memory manager. Should no be modified.*/
uint32_t count; /**< Total items of the buffer queue.*/
uint32_t item_size; /**< Size of each item.*/
} hb_mem_buf_queue_t;
5.4.5.5. hb_mem_pool_t
/**
* @struct hb_mem_pool_t
* Define the descriptor of memory pool.
*/
typedef struct hb_mem_pool_t {
int64_t flags; /**< Buffer flags for allocation.@mem_usage_t*/
uint64_t size; /**< Total Buffer size specified by user during allocation.*/
int32_t fd; /**< File descriptors of the pool.*/
int32_t page_size; /**< Page size in byte.*/
int32_t total_page_cnt; /**< Total page count.*/
int32_t avail_page_cnt; /**< Available page count.*/
int32_t cur_client_cnt; /**< Current pool client count.*/
int32_t reserved; /**< reserved*/
} hb_mem_pool_t;
5.4.5.7. hbmem 内存分配属性
内存
| 数据项 | 描述 |
|---|---|
| HB_MEM_USAGE_CPU_READ_NEVER | CPU 不会 |
| HB_MEM_USAGE_CPU_READ_OFTEN | CPU 经常 |
| HB_MEM_USAGE_CPU_READ_MASK | 用于 |
| HB_MEM_USAGE_CPU_WRITE_NEVER | CPU 不会 |
| HB_MEM_USAGE_CPU_WRITE_OFTEN | CPU 经常 |
| HB_MEM_USAGE_CPU_WRITE_MASK | 用于 |
| HB_MEM_USAGE_HW_CIM | 表明 |
| HB_MEM_USAGE_HW_PYRAMID | 表明 |
| HB_MEM_USAGE_HW_GDC | 表明 |
| HB_MEM_USAGE_HW_GDC_OUT | 表明 |
| HB_MEM_USAGE_HW_STITCH | 表明 |
| HB_MEM_USAGE_HW_OPTICAL_FLOW | 表明 |
| HB_MEM_USAGE_HW_BPU | 表明 |
| HB_MEM_USAGE_HW_ISP | 表明 |
| HB_MEM_USAGE_HW_DISPLAY | 表明 |
| HB_MEM_USAGE_HW_VIDEO_CODEC | 表明 |
| HB_MEM_USAGE_HW_JPEG_CODEC | 表明 |
| HB_MEM_USAGE_HW_VDSP | 表明 |
| HB_MEM_USAGE_HW_IPC | 表明 |
| HB_MEM_USAGE_HW_PCIE | 表明 |
| HB_MEM_USAGE_HW_YNR | 表明 |
| HB_MEM_USAGE_HW_MASK | 用于 |
| HB_MEM_USAGE_MAP_INITIALIZED | 需要 |
| HB_MEM_USAGE_MAP_UNINITIALIZED | 不 |
| HB_MEM_USAGE_CACHED | 表明 |
| HB_MEM_USAGE_GRAPHIC_CONTIGUOUS_BUF | 指定 graphic buffer 分配 |
| HB_MEM_USAGE_MEM_POOL | 用于 |
| HB_MEM_USAGE_MEM_SHARE_POOL | 用于 |
| HB_MEM_USAGE_TRIVIAL_MASK | 用于 |
| HB_MEM_USAGE_PRIV_HEAP_DMA | 指定 |
| HB_MEM_USAGE_PRIV_HEAP_RESERVERD | 指定 |
| HB_MEM_USAGE_PRIV_HEAP_2_RESERVERD | 指定 |
| HB_MEM_USAGE_PRIV_MASK | 用于 |
5.4.5.8. hbmem 图像格式
| 数据项 | 描述 |
|---|---|
| MEM_PIX_FMT_NONE | 无效 |
| MEM_PIX_FMT_RGB565 | packed RGB 5:6:5, 16bpp |
| MEM_PIX_FMT_RGB24 | packed RGB 8:8:8, 24bpp |
| MEM_PIX_FMT_BGR24 | packed RGB 8:8:8, 24bpp |
| MEM_PIX_FMT_ARGB | packed ARGB 8:8:8:8, 32bpp |
| MEM_PIX_FMT_RGBA | packed RGBA 8:8:8:8, 32bpp |
| MEM_PIX_FMT_ABGR | packed ABGR 8:8:8:8, 32bpp |
| MEM_PIX_FMT_BGRA | packed BGRA 8:8:8:8 |
| MEM_PIX_FMT_YUV420P | planar YUV 4:2:0, 12bpp (1 Cr & Cb sample per 2x2 Y samples) |
| MEM_PIX_FMT_NV12 | planar YUV 4:2:0, 12bpp (1 plane for Y and 1 plane for the UV component) |
| MEM_PIX_FMT_NV21 | planar YUV 4:2:0, 12bpp (1 plane for Y and 1 plane for the VU component) |
| MEM_PIX_FMT_YUV422P | planar YUV 4:2:2, 16bpp (1 Cr & Cb sample per 2x1 Y samples) |
| MEM_PIX_FMT_NV16 | planar YUV 4:2:2, 16bpp (interleaved chroma (first byte U and the following byte V)) |
| MEM_PIX_FMT_NV61 | planar YUV 4:2:2, 16bpp (interleaved chroma (first byte V and the following byte U)) |
| MEM_PIX_FMT_YUYV422 | packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr |
| MEM_PIX_FMT_YVYU422 | packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb |
| MEM_PIX_FMT_UYVY422 | packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 |
| MEM_PIX_FMT_VYUY422 | packed YUV 4:2:2, 16bpp, Cr Y0 Cb Y1 |
| MEM_PIX_FMT_YUV444 | packed YUV 4:4:4, 24bpp |
| MEM_PIX_FMT_YUV444P | planar YUV 4:4:4, 24bpp |
| MEM_PIX_FMT_NV24 | YUV 4:4:4, 24bpp (interleaved chroma (first byte U and the following byte V)) |
| MEM_PIX_FMT_NV42 | YUV 4:4:4, 24bpp (interleaved chroma (first byte V and the following byte U)) |
| MEM_PIX_FMT_YUV440P | planar YUV 4:4:0 |
| MEM_PIX_FMT_YUV400 | Gray Y, YUV 4:0:0 |
| MEM_PIX_FMT_RAW8 | raw8 format |
| MEM_PIX_FMT_RAW10 | raw10 format |
| MEM_PIX_FMT_RAW12 | raw12 format |
| MEM_PIX_FMT_RAW14 | raw14 format |
| MEM_PIX_FMT_RAW16 | raw16 format |
| MEM_PIX_FMT_RAW20 | raw20 format |
| MEM_PIX_FMT_RAW24 | raw24 format |
| MEM_PIX_FMT_TOTAL | total format count |
5.4.6. hbmem 返回值
错误码
| 错误码 | 宏 |
描述 |
|---|---|---|
| 0xFF000001 | HB_MEM_ERR_UNKNOWN | 未知 |
| 0xFF000002 | HB_MEM_ERR_INVALID_PARAMS | 无效 |
| 0xFF000003 | HB_MEM_ERR_INVALID_FD | 无效 fd |
| 0xFF000004 | HB_MEM_ERR_INVALID_VADDR | 无效 |
| 0xFF000005 | HB_MEM_ERR_INSUFFICIENT_MEM | 内存 |
| 0xFF000006 | HB_MEM_ERR_TOO_MANY_FD | 文件 |
| 0xFF000007 | HB_MEM_ERR_TIMEOUT | 超时 |
| 0xFF000008 | HB_MEM_ERR_MODULE_NOT_FOUND | 内存模块 |
| 0xFF000009 | HB_MEM_ERR_MODULE_OPEN_FAIL | 内存模块 |
| 0xFF00000A | HB_MEM_ERR_QUEUE_NOT_FOUND | 内存 |
| 0xFF00000B | HB_MEM_ERR_QUEUE_DESTROYED | 内存 |
| 0xFF00000C | HB_MEM_ERR_QUEUE_WRONG_SLOT | 错误 |
| 0xFF00000D | HB_MEM_ERR_QUEUE_NO_AVAILABLE_SLOT | 无法 |
| 0xFF00000E | HB_MEM_ERR_QUEUE_ALREADY_EXIST | 内存 |
| 0xFF00000F | HB_MEM_ERR_POOL_NOT_FOUND | 内存 |
| 0xFF000010 | HB_MEM_ERR_POOL_DESTROYED | 内存 |
| 0xFF000011 | HB_MEM_ERR_POOL_BUSY | 内存 |
| 0xFF000012 | HB_MEM_ERR_WAIT_SHARE_FAILURE | 等待 share client 状态 |
| 0xFF000013 | HB_MEM_ERR_NOT_ALLOW | 该 |
| 0xFF000014 | HB_MEM_ERR_CHECK_VER_FAIL | 版本 |
| 0xFF000015 | HB_MEM_ERR_REGISTER_FAIL | register graphic buffer group 失败 |
| 0xFF000016 | HB_MEM_ERR_INVALID_GROUPID | 无效 |