福州大学《嵌入式系统综合设计》 实验九:ROI视频编码

news2024/11/20 12:22:27

一、实验目的

ROI视频编码即感兴趣区域视频编码,即针对感兴趣区域进行重点编码,提高编码质量,而对非感兴趣区域采用低质量编码。通过这种方法可以降低码率。本实验即让同学们能够在算能的FFMPEG接口下实现基于ROI的视频编码。

二、实验内容

在实验8的基础上,进一步实现ROI编码。即对图像不同区域设置不同的QP进行视频编码。

三、开发环境

开发主机:Ubuntu 20.04.6 LTS

硬件:算能SE5

四、实验器材

开发主机 + 云平台(或SE5硬件)

五、实验过程与结论

ROI视频编码原理

整帧视频图像的视觉质量很大程度上取决于感兴趣区域ROI部分的视觉质量,而非ROI的图像质量下降不易被察觉,对整帧图像的视觉质量影响较小, 感兴趣区域并不局限于人眼的感兴趣区域,在某些具体的工程应用中,可以将某些具体的场景或者事物定义为感兴趣区域。

感兴趣区域ROI的视频编码的基本方法如图所示,对于输入视频帧序列,通过特定的算法和视频帧本身的特性,提取出感兴趣区域和不感兴趣区域掩膜,并将其作为控制信息输入到视频编码器中,用其控制编码器编码当前帧相应的编码参数,包括量化参数,运动估计时的搜索区域大小和参考帧数目,以及预测模式范围等。感兴趣区域ROI提取模块起到预处理和控制器的作用,感兴趣区域提取涉及视觉显著性等,显著性是指视频帧序列中的能够引起 HVS 注意的物体所具有的特性,一般感兴趣区域的显著性可以表现为纹理、亮度、色度、对比度、形态、对比度等特征。

码率控制的目的是在给定的码率条件下,保证良好稳定的输出码流。按照粒度大小码率控制可分为 GOP 层、帧层以及宏块层(或者CTU层)。编码器通过对不同层级中编码单元分配不同的码率比计算相应的QP值。QP 越大,编码单元丢失的细节越多,图像的失真度增加,质量下降,同时码率也降低,随着 QP 的减小,编码单元的细节保留的增多,在提高质量的同时增大了码率。

在固定目标比特率的 CBR 编码模式中,编码器通过编码结果对每帧、每个宏块或者CTU分配不同的码率,动态计算调整 QP 大小,让最终编码的整体码率与给定码率接近。在基于ROI的编码方法中,在ROI 分析与提取的基础上,基于CBR 的码率控制模型,对宏块级的 QP 进行调整,即对 ROI 降低 QP 提高编码质量,对非 ROI 相应提高 QP。通过这种方式,视觉关注区域得到了更多的码率,而非视觉关注区域节省了非必要的码率分配,进而达到在整体码率不变的条件下,提升视频的主观视觉质量的目的。

关键核心代码讲解

设置ROI有效

ROI的设置是在编码过程中通过设置不同区域的QP来设置ROI,在设置之前需要在初始化编码器时设置ROI有效,因此,我们需要在实验8的openEnc函数中设置ROI有效,具体如下:

//av_dict_set_int(&dict, "qp", 25, 0);
av_dict_set_int(&dict, "roi_enable", 1, 0);

注意,上式中的av_dict_set_int(&dict, "qp", 25, 0)是实验8的代码,更换为ROI后需要删除。

设置QP

我们在实验8的基础上,在编码前设置图像不同区域的编码QP。本次实验对编码图像分成四个区域,如图所示,其中不同区域设置成不同的量化参数。在视频编码中,量化参数QP是非常重要的参数,它直接影响着视频的编码比特率。对于某些应用场合,尤其是当传输速率受限时,灵活地控制量化 参数使得编码速率尽量接近给定速率尤为重要。图中右下角区域每个编码单元(宏块或者CTB)QP设为较小的值,QP=10,该区域经过编码后,保留较多的细节信息。而其他三个区域QP=40,这几个区域可以获得较小的码率和较少的计算资源。

H264中ROI代码:

对于H.264编码器,首先计算每个宏块的索引位置(i,j),当判断当前宏块位于右下角区域时,QP设置为40,其他则设置为10。

#define BM_ALIGN16(_x)             (((_x)+0x0f)&~0x0f)
#define BM_ALIGN32(_x)             (((_x)+0x1f)&~0x1f)
#define BM_ALIGN64(_x)             (((_x)+0x3f)&~0x3f)  
AVFrameSideData *fside = av_frame_get_side_data(picture, AV_FRAME_DATA_BM_ROI_INFO);
    if (fside) {
        AVBMRoiInfo *roiinfo = (AVBMRoiInfo*)fside->data;
        memset(roiinfo, 0, sizeof(AVBMRoiInfo));
        if (enc_ctx->codec_id  == AV_CODEC_ID_H264) {
             roiinfo->customRoiMapEnable = 1;
             roiinfo->customModeMapEnable = 0;
             for (int i = 0;i <(BM_ALIGN16(height) >> 4);i++) {
                 for (int j=0;j < (BM_ALIGN16(width) >> 4);j++) {
                     int pos = i*(BM_ALIGN16(width) >> 4) + j;
                     // test_1
                     if ( (j >= (BM_ALIGN16(width) >> 4)/2) && (i >= (BM_ALIGN16(height) >> 4)/2) ) {
                          roiinfo->field[pos].H264.mb_qp = 10;
                      }else{
                          roiinfo->field[pos].H264.mb_qp = 40;
                      }
                 }
             }
         } else if (enc_ctx->codec_id  == AV_CODEC_ID_H265) {
            roiinfo->customRoiMapEnable    = 1;
            roiinfo->customModeMapEnable   = 0;
            roiinfo->customLambdaMapEnable = 0;
            roiinfo->customCoefDropEnable  = 0;

            for (int i = 0;i <(BM_ALIGN64(height) >> 6);i++) {
                for (int j=0;j < (BM_ALIGN64(width) >> 6);j++) {
                    int pos = i*(BM_ALIGN64(width) >> 6) + j;

                    // test_1
                    if ( (j > (BM_ALIGN64(width) >> 6)/2) && (i > (BM_ALIGN64(height) >> 6)/2) ) {
                        roiinfo->field[pos].HEVC.sub_ctu_qp_0 = 10;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_1 = 10;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_2 = 10;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_3 = 10;
                    } else {
                        roiinfo->field[pos].HEVC.sub_ctu_qp_0 = 40;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_1 = 40;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_2 = 40;
                        roiinfo->field[pos].HEVC.sub_ctu_qp_3 = 40;
                    }

                    roiinfo->field[pos].HEVC.ctu_force_mode = 0;
                    roiinfo->field[pos].HEVC.ctu_coeff_drop = 0;
                    roiinfo->field[pos].HEVC.lambda_sad_0 = 0;
                    roiinfo->field[pos].HEVC.lambda_sad_1 = 0;
                    roiinfo->field[pos].HEVC.lambda_sad_2 = 0;
                    roiinfo->field[pos].HEVC.lambda_sad_3 = 0;
                }

H265中ROI代码:

对于H.265/HEVC编码器,编码标准制定了一种非常灵活的QP控制机制,它引入了量化组(Quantization Group, QG)的概念,规定一个CTB可以包含一个或多个固定大小的QG,同一个QG内的所有含有非零系数的CU共享一个QP,不同的QG可以使用不同的QP。这样一来,编码器能够更灵活地进行速率控制。

QG是指将一幅图像分成的固定大小(NxN)的正方形像素块。其大小N由图像参数集(PPS)指定,且必须处于最大CU与最小CU之间(包含最大与最小CU)。图中给出了一个32x32 QG的示意图,其中粗实线为CTB边界,粗虚线表示CU划分方式,细线为QG分界线。CU与QG没有固定的大小关系。由于在一幅图像中,QG为固定大小,而CU是根据视频内容自适应划分出来的,因此可能出现一个QG包含一个或多个CU的情形,也可能存在一个CU包含多个QG的情形。

实验过程

生成可执行文件:

makefile的写法与前面的例程基本相同,按照前面实验1、实验2步骤,生成可执行文件并上传到算能盒子或者云平台中。如果是在云平台上测试,则可将编译好的执行文件通过云空间文件系统上传。

root@d11ae417e206:/tmp/test# ls

ffmpeg_encode_withRoi  1080p.yuv

给可执行文件赋权限并执行。

root@d11ae417e206:/tmp/test# chmod 777 ffmpeg_encode_withRoi

运行指令:

生成并上传编译文件后,根据如下指令在目标开发机终端运行。

./ffmpeg_encode_withRoi 1080.yuv output.h264

运行结果如下:

[h264_bm @ 0x429a90] width =1920

[h264_bm @ 0x429a90] height=1080 src/allocator.c:136 (ion_dmabufalloc_map)  

DEBUG: retrieved virtual address for physical memory

src/allocator.c:144 (ion_dmabufalloc_map)  

DEBUG: Invalidated physical memory

src/allocator.c:155 (ion_dmabufalloc_map)  

DEBUG: virtual address:  0x7f820c8000  aligned: 0x7f820c8000

src/allocator.c:176 (ion_dmabufalloc_unmap)  

DEBUG: shut down virtual address for 3133440 bytes of physical memory

[h264_bm @ 0x429a90] input frame: context=(nil), pts=100, dts=-9223372036854775808

[85fb6010] src/enc.c:2264 (Wave5BitIssueCommand)  

instanceIndex=0: cmd=0x100

[85fb6010] src/enc.c:1647 (enc_start_one_frame)  

instance Index: 0. instance Queue Count: 1, total Queue Count: 1

[85fb6010] src/enc.c:733 (VpuHandlingInterruptFlag)  

INTR Done: enc pic. reason=0x100

[85fb6010] src/enc.c:2264 (Wave5BitIssueCommand)  

instanceIndex=0: cmd=0x4000

[h264_bm @ 0x429a90] output frame: context=(nil), pts=91, dts=87

enc_pkt.pts=91, enc_pkt.dts=87

rescaled enc_pkt.pts=46592, enc_pkt.dts=44544

Muxing frame

The end of file!

Flushing video encoder

[85fb6010] src/enc.c:2264 (Wave5BitIssueCommand)  

instanceIndex=0: cmd=0x100

[85fb6010] src/enc.c:1647 (enc_start_one_frame)  

instance Index: 0. instance Queue Count: 1, total Queue Count: 1

[85fb6010] src/enc.c:733 (VpuHandlingInterruptFlag)  

INTR Done: enc pic. reason=0x100

[85fb6010] src/enc.c:2264 (Wave5BitIssueCommand)  

instanceIndex=0: cmd=0x4000 [h264_bm @ 0x429a90] encoding end!

src/encoder.c:804 (bmvpu_enc_close)  

DEBUG: closing encoder src/allocator.c:112 (ion_dmabufalloc_deallocate)  

DEBUG: deallocated 262144 bytes of physical memory

src/allocator.c:112 (ion_dmabufalloc_deallocate)  

DEBUG: deallocated 262144 bytes of physical memory

src/allocator.c:112 (ion_dmabufalloc_deallocate)  

DEBUG: deallocated 262144 bytes of physical memory

src/allocator.c:112 (ion_dmabufalloc_deallocate)  

DEBUG: deallocated 262144 bytes of physical memory

src/encoder.c:295 (bmvpu_enc_unload)  

DEBUG: unloaded VPU [AVIOContext @ 0x499190] Statistics: 2 seeks, 7 writeouts

encode finish!

#######VideoEnc_FFMPEG exit

注:上图展示为部分关键运行结果,详细运行结果请见运行界面。

Elecard StreamEye分析

对视频文件进行ROI编码后,用Elecard StreamEye分析码流。通过播放编码后的视频可以看出,右下角区域比其他区域的清晰度更高,细节保留的更多。左下角使用较大的QP,使得图像细节丢失,木板的间隙模糊,人工效应明显。而右下角区域使用较小的QP编码,则相对清晰。

同时可以调出MB信息查看每一个编码单元的QP值,可以看出,右下角的QP值更低,其他区域的QP值更高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1269507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

燃料电池汽车市场分析:预计2028年将达到118亿美元

燃料电池汽车( FCV) 是一种用车载燃料电池装置产生的电力作为动力的汽车。车载燃料电池装置所使用的燃料为高纯度氢气或含氢燃料经重整所得到的高含氢重整气。与通常的电动汽车比较, 其动力方面的不同在于FCV 用的电力来自车载燃料电池装置, 电动汽车所用的电力来自由电网充电的…

C++ AVL 树

AVL树的概念 当数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;此时二叉搜索树的搜索效率低下 解决方法&#xff1a;AVL树&#xff08;降低树的高度&#xff0c;从而减少平均搜索长度) 一棵AVL树或者是空树&#xff0c;或者是具有以下性质的二叉搜索树&#xff1…

C++ 通过CryptoPP计算Hash值

Crypto (CryptoPP) 是一个用于密码学和加密的 C 库。它是一个开源项目&#xff0c;提供了大量的密码学算法和功能&#xff0c;包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto 的目标是提供高性能和可靠的密码学工具&#xff0c;以满足软件开发中对…

Android 10.0 Launcher3定制之首页时钟小部件字体大小的修改

1.前言 在10.0的产品开发中,在一些Launcher3的定制化开发中,在对于一些小屏幕的产品开发中,在首页添加时钟小部件会显得字体有点小, 所以为了整体布局美观就需要改动小部件的布局日期字体的大小来实现整体的布局美观效果,接下来来具体实现相关的功能 具体效果图: 2.Lau…

悠络客受邀出席2023上海区域零售(餐饮)数字化运营实战沙龙研讨会

11月23日&#xff0c;由中国零售&#xff08;餐饮&#xff09;CIO俱乐部、《智慧零售与餐饮》主办的2023上海区域零售&#xff08;餐饮&#xff09;数字化运营实战沙龙研讨会在上海召开&#xff0c;悠络客合伙人兼销售副总裁张勇作为演讲嘉宾受邀出席了本次大会。 本次研讨会汇…

Android中使用Google Map

在app的使用过程中&#xff0c;我们经常会跟地图进行交互&#xff0c;如果是海外的应用&#xff0c;那选择使用Google Map 是最合适的选择。 在Android中如何使用Google Map&#xff0c;这里做一个简要的说明。 Google API_KEY的申请 Google Map 的使用并不是免费的&#xf…

小航助学题库蓝桥杯题库c++选拔赛(22年1月)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09; 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;

C++面向对象复习笔记暨备忘录

C指针 指针作为形参 交换两个实际参数的值 #include <iostream> #include<cassert> using namespace std;int swap(int *x, int* y) {int a;a *x;*x *y;*y a;return 0; } int main() {int a 1;int b 2;swap(&a, &b);cout << a << &quo…

el-select多选框,数据拼接

将多选框数据 按照逗号拼接为字符串 getTagIds(data, type) {if (type "array") {let array data.join(",")return array} else {let string data.split(",");return string}}, 在调用这个方法时需要&#xff0c;另外传一个字符串type,以此来…

前端:实现二级菜单(点击实现二级菜单展开)

效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

Spring 日志

日志的作用: 1.定位和发现问题 2.系统监控 3.数据采集 观察日志 先写一段打印日志的代码 日志内容 日志级别分类 默认日志级别是Info,级别一下的就不打印了 Spring 帮我们集成了日志框架,我们直接使用即可 我们测试一下用日志框架打印日志是如何 我们就会发现打印的结果跟…

TypeScript 5.3

导入属性 TypeScript 5.3支持导入属性提案的最新更新。 导入属性的一个用例是向运行库提供有关模块预期格式的信息。 // We only want this to be interpreted as JSON, // not a runnable/malicious JavaScript file with a .json extension. import obj from "./somet…

VSCODE 在新窗口中打开

使用VS习惯了&#xff0c;经常在新窗口中打开查看 但是VSCODE&#xff0c;无法拖动标签到一个新窗口中&#xff0c;一直以为没这个功能 后来发现 使用快捷健 ctlk,o 可以将标签页在新窗口中打开&#xff0c;虽然不如vsstudio方便&#xff0c;不过也可实现在新窗口打开的功能…

Mac 浏览器下载的文件名总是「乱码」

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 本文所说的方法是在出现文件名乱码情况下&#xff0c;如何恢复文件名的正确中文名称&#xff0c;并非一劳永逸地避免乱码的出现。这是由于下载文件名称乱码的出现&#xff0c;往往是系统、浏览器、网站三方面因素共…

基于containerd容器运行时,kubeadmin部署k8s 1.28集群

一.主机准备 1.1主机配置与操作系统说明 centos7u9 1.2主机硬件配置说明 序号主机名ip地址CPU内存硬盘1k8s-master1192.168.1.2002C2G100G2k8s-worker1192.168.1.2012C2G100G3k8s-worker2192.168.1.2022C2G100G 1.3主机配置 1.3.1主机名配置 hostnamectl set-hostname k…

【滑动窗口】长度最小的数组

长度最小的数组 长度最小的数组 文章目录 长度最小的数组题目描述解法暴力解法滑动窗口Java示例代码c示例代码 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, num…

【web安全】CSRF漏洞攻击与防御

前言 总结&#xff0c;仅供学习。 csrf的理解 我们了解一个网站有修改信息&#xff0c;密码&#xff0c;添加删除管理&#xff0c;支付转账的功能之后。 通过抓包抓取对方修改操作的数据包样式&#xff0c; 然后在自己网站搭建一个指令。 当别人来访时&#xff0c; 如果…

el-select实现分屏效果

动态绑定class值 &#xff0c;多种判断 :class"type 8 ? home-stye-2 : type 24 ? home-stye-1 : home-stye-3" <div class"home-right-top"><div class"home-right-top-video"><el-row :gutter"20"><el-c…

身份验证和电子邮件的网络安全即将迎来地震

任何拥有 Gmail 或 Yahoo 电子邮件帐户的人都清楚&#xff0c;如果不是明确的欺诈企图&#xff0c;他们的收件箱中可能充满了未经请求的邮件。 这些服务的用户很可能多次想知道他们的提供商是否可以采取措施至少减少垃圾邮件的数量以及随之而来的诈骗风险。 好消息是&#xf…

深入理解网络阻塞 I/O:BIO

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…