.h264 .h265 压缩率的直观感受

1.资源文件  

https://download.csdn.net/download/twicave/89579327


上面是.264 .265和原始的YUV420文件,各自的大小。

2.转换工具:

2.1 .h264 .h265互转

可以使用ffmpeg工具:Builds - CODEX FFMPEG @ gyan.dev

命令行参数:

ffmpeg -i Tennis1080p.h264 -c:v libx265 -preset medium -crf 28 Tennis1080p.h265 

2.2 .h264 转 yuv

我因为要测试rk3588上一个硬件解码器,使用的是一个.c代码:

mpp-test: Rockchip MPP的简单案例

2.3 yuv file reader

 这个可以使用python直接处理:

import cv2
import numpy as npyuv_frame_pack_file = "Tennis1080p.yuv"def yuv420sp_to_rgb(nv12, width, height):print('lenOfframe = ', len(nv12))nv12_array = np.frombuffer(nv12, dtype=np.uint8)#if len(nv12_array) > (width * height * 3 // 2):#    height += ((len(nv12_array) - (width * height * 3 // 2)) // width * 2) // 3y_plane_size = height * widthuv_plane_size = (height // 2) * (width // 2) * 2# Split the NV12 data into Y plane and UV planey_plane = nv12_array[0:y_plane_size].reshape(height, width)uv_plane = nv12_array[y_plane_size:y_plane_size+uv_plane_size].reshape(height // 2, width)  # UV plane is half the height of Y plane# Create a new NumPy array for the YUV image, with the same data as Y plane# but with a shape that OpenCV expects for YUV420sp (NV12)yuv420sp = np.zeros((height + height // 2, width), dtype=np.uint8)yuv420sp[:height, :] = y_plane  # Copy Y plane datayuv420sp[height:, ::2] = uv_plane[:, 1::2]  # Copy U plane datayuv420sp[height:, 1::2] = uv_plane[:, ::2]  # Copy V plane data'''# 文件路径file_path = 'yuv420sp.bin'# 打开文件并写入数据with open(file_path, 'wb') as file:file.write(nv12)sys.exit(0)'''# Use OpenCV to convert YUV420sp (NV12) to RGBrgb_image = cv2.cvtColor(yuv420sp, cv2.COLOR_YUV2RGB_NV12)return rgb_image# 设置图像的宽度和高度
width, height = 1920, 1080# 读取一帧YUV420数据
cnt = 23
with open(yuv_frame_pack_file , 'rb') as file:while(cnt>0):cnt -=1yuv420_frame = file.read(width * height * 3 // 2)  # YUV420格式,每帧大小为width * height * 3 / 2continueyuv420_frame = file.read(width * height * 3 // 2)  # YUV420格式,每帧大小为width * height * 3 / 2yuv420_frame = np.frombuffer(yuv420_frame, dtype=np.uint8)rgb_frame = yuv420sp_to_rgb(yuv420_frame, width, height)cv2.imshow('RGB Image', rgb_frame)cv2.waitKey(0)cv2.destroyAllWindows()

2.3.1解码效果

附录A h.265=>yuv frames file转换工具 

实际测试过程中,您可能需要对.h264, .h265的转换速度做比对,这里给出.h265转储为yuv frames file的C代码,相较2.2的原始c代码修改很少:

我只改了mpp_init,和需要处理的.h265文件名。

/*** 1. make* 2. ./mpp-dec-h264-to-yuv-file* 3. gst-launch-1.0 filesrc location=Tennis1080p.yuv ! videoparse width=1920 height=1080 format=nv12 ! videoconvert ! xvimagesink* 4. gst-launch-1.0 filesrc location=Tennis1080p.h264 ! h264parse ! mppvideodec ! xvimagesink*/
#include <unistd.h>
#include <stdio.h>
#include <rockchip/rk_mpi.h>#define __IN_FILE__ ("Tennis1080p.h265")
#define __OUT_FILE__ ("Tennis1080p.yuv")void dump_frame(MppFrame frame, FILE *out_fp)
{printf("dump_frame_to_file\n");RK_U32 width    = 0;RK_U32 height   = 0;RK_U32 h_stride = 0;RK_U32 v_stride = 0;MppFrameFormat fmt  = MPP_FMT_YUV420SP;MppBuffer buffer    = NULL;RK_U8 *base = NULL;width    = mpp_frame_get_width(frame);height   = mpp_frame_get_height(frame);h_stride = mpp_frame_get_hor_stride(frame);v_stride = mpp_frame_get_ver_stride(frame);fmt      = mpp_frame_get_fmt(frame);buffer   = mpp_frame_get_buffer(frame);RK_U32 buf_size = mpp_frame_get_buf_size(frame);printf("w x h: %dx%d hor_stride:%d ver_stride:%d buf_size:%d\n",width, height, h_stride, v_stride, buf_size);if (NULL == buffer) {printf("buffer is null\n");return ;}base = (RK_U8 *)mpp_buffer_get_ptr(buffer);// MPP_FMT_YUV420SPif (fmt != MPP_FMT_YUV420SP) {printf("fmt %d not supported\n", fmt);return;}RK_U32 i;RK_U8 *base_y = base;RK_U8 *base_c = base + h_stride * v_stride;for (i = 0; i < height; i++, base_y += h_stride) {fwrite(base_y, 1, width, out_fp);}for (i = 0; i < height / 2; i++, base_c += h_stride) {fwrite(base_c, 1, width, out_fp);}
}void dump_frame_to_file(MppCtx ctx, MppApi *mpi, MppFrame frame, FILE *out_fp)
{printf("decode_and_dump_to_file\n");MPP_RET ret;if (mpp_frame_get_info_change(frame)) {printf("mpp_frame_get_info_change\n");/*** 第一次解码会到这个分支,需要为解码器设置缓冲区.* 解码器缓冲区支持3种模式。参考【图像内存分配以及交互模式】Rockchip_Developer_Guide_MPP_CN.pdf* 这里使用纯内部模式。*/ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);if (ret) {printf("mpp_frame_get_info_change mpi->control error""MPP_DEC_SET_INFO_CHANGE_READY %d\n", ret);}return;}RK_U32 err_info = mpp_frame_get_errinfo(frame);RK_U32 discard = mpp_frame_get_discard(frame);    printf("err_info: %u discard: %u\n", err_info, discard);if (err_info) {return;}// savedump_frame(frame, out_fp);return;
}int main(void)
{printf("---------- mpp start ----------\n");// 1. 打开输入文件FILE *in_fp = fopen(__IN_FILE__, "rb");if (!in_fp) {printf("fopen error\n");return -1;}// 2. 打开输出文件FILE *out_fp = fopen(__OUT_FILE__, "wb+");if (!out_fp) {printf("fopen error\n");return -1;}// 3. 初始化解码器上下文,MppCtx MppApiMppCtx ctx = NULL;MppApi *mpi = NULL;MPP_RET ret = mpp_create(&ctx, &mpi);if (MPP_OK != ret) {printf("mpp_create error\n");return -1;}/*** 4. 配置解器*      - 解码文件需要 split 模式*      - 设置非阻塞模式,0非阻塞(默认),-1阻塞,+val 超时(ms)*/RK_U32 need_split = -1;ret = mpi->control(ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, (MppParam*)&need_split);if (MPP_OK != ret) {printf("mpi->control error MPP_DEC_SET_PARSER_SPLIT_MODE\n");return -1;}ret = mpp_init(ctx, MPP_CTX_DEC, MPP_VIDEO_CodingHEVC);  // 固定为H265 https://blog.csdn.net/weixin_38807927/article/details/135760601if (MPP_OK != ret) {printf("mpp_init error\n");return -1;}// 5. 初始化包,MppPacketint buf_size = 5 * 1024 * 1024;char *buf = (char*)malloc(buf_size);if (!buf) {printf("malloc error\n");return -1;}MppPacket pkt = NULL;ret = mpp_packet_init(&pkt, buf, buf_size);if (MPP_OK != ret) {printf("mpp_packet_init error\n");return -1;}// 6. 循环读取文件,输入解码器,解码,保存结果int over = 0;while (!over) {printf("decode...\n");int len = fread(buf, 1, buf_size, in_fp);printf("read file length:%d\n", len);if (0 < len) {mpp_packet_write(pkt, 0, buf, len);mpp_packet_set_pos(pkt, buf);mpp_packet_set_length(pkt, len);if (feof(in_fp) || len < buf_size) {  // 文件读完,设置结束标志位mpp_packet_set_eos(pkt);printf("mpp_packet_set_eos\n");}}/*** decode_put_packet返回失败,意味着内部缓冲区已满。* 非阻塞模式,使用pkt_is_send判断当前读取的数据包(buf)是否成功发送。*/int pkt_is_send = 0;while (!pkt_is_send && !over) {if (0 < len) {printf("pkt remain:%d\n", mpp_packet_get_length(pkt));ret = mpi->decode_put_packet(ctx, pkt);if (MPP_OK == ret) {printf("pkt send success remain:%d\n", mpp_packet_get_length(pkt));pkt_is_send = 1;}}MppFrame frame;MPP_RET ret;ret = mpi->decode_get_frame(ctx, &frame);if (MPP_OK != ret || !frame) {printf("decode_get_frame falied ret:%d\n", ret);usleep(2000);  // 等待一下2ms,通常1080p解码时间2mscontinue;}printf("decode_get_frame success\n");dump_frame_to_file(ctx, mpi, frame, out_fp);if (mpp_frame_get_eos(frame)) {printf("mpp_frame_get_eos\n");mpp_frame_deinit(&frame);over = 1;continue;}mpp_frame_deinit(&frame);}}// 7. 释放资源fclose(in_fp);fclose(out_fp);mpi->reset(ctx);mpp_packet_deinit(&pkt);mpp_destroy(ctx);free(buf);printf("---------- mpp over ----------\n");return 0;
}

A.1相应的make file :

将文件放置在.c文件的同级目录,命名为:makefile

app: mpp-dec-h264-to-yuv-file.c mpp-multi-thread-demo.c mpp-dec-h265-to-yuv-file.cgcc mpp-dec-h264-to-yuv-file.c -o mpp-dec-h264-to-yuv-file -lrockchip_mppgcc mpp-dec-h265-to-yuv-file.c -o mpp-dec-h265-to-yuv-file -lrockchip_mppgcc mpp-multi-thread-demo.c -o mpp-multi-thread-demo -lrockchip_mpp -lpthread -I/usr/include/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include -lglib-2.0

需要编译时:执行

make

即可。

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

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

相关文章

liteos定时器回调时间过长造成死机问题解决思路

项目需求 原代码是稳定的&#xff0c;现我实现EMQ平台断开连接的时候&#xff0c;把HSL的模拟点位数据采集到网关&#xff0c;然后存入Flash&#xff0c;当EMQ平台连接的时候&#xff0c;把Flash里面的点位数据放在消息队列里面&#xff0c;不影响实时采集。 核心1&#xff1a…

godot新建项目及设置外部编辑器为vscode

一、新建项目 初次打开界面如下所示&#xff0c;点击取消按钮先关闭掉默认弹出的框 点击①新建弹出中间的弹窗②中填入项目的名称 ③中设置项目的存储路径&#xff0c;点击箭头所指浏览按钮&#xff0c;会弹出如下所示窗口 根据图中所示可以选择或新建自己的游戏存储路径&…

鸿蒙(HarmonyOS)自定义Dialog实现时间选择控件

一、操作环境 操作系统: Windows 11 专业版、IDE:DevEco Studio 3.1.1 Release、SDK:HarmonyOS 3.1.0&#xff08;API 9&#xff09; 二、效果图 三、代码 SelectedDateDialog.ets文件/*** 时间选择*/ CustomDialog export struct SelectedDateDialog {State selectedDate:…

Linux系统上安装Redis

百度网盘&#xff1a; 通过网盘分享的文件&#xff1a;redis_linux 链接: https://pan.baidu.com/s/1ZcECygWA15pQWCuiVdjCtg?pwd8888 提取码: 8888 1.把安装包拖拽到/ruanjian/redis/文件夹中&#xff08;自己选择&#xff09; 2.进入压缩包所在文件夹&#xff0c;解压压缩…

ROM修改进阶教程------修改rom 开机自动安装指定apk 自启脚本完整步骤解析

rom修改的初期认识 在解包修改系统分区过程中。很多客户需求刷完rom后自动安装指定apk。这种与内置apk有区别。而且一些极个别apk无法内置。今天对这种修改rom刷入机型后第一次启动后自动安装指定apk的需求做个步骤解析。 在前期博文中我有做过说明。官方系统固件解…

按图搜索新体验:阿里巴巴拍立淘API返回值详解

阿里巴巴拍立淘API是一项基于图片搜索的商品搜索服务&#xff0c;它允许用户通过上传商品图片&#xff0c;系统自动识别图片中的商品信息&#xff0c;并返回与之相关的搜索结果。以下是对阿里巴巴拍立淘API返回值的详细解析&#xff1a; 一、主要返回值内容 商品信息 商品列表…

Java面试题(每日更新)

每日五道&#xff01;学会就去面试&#xff01; 本文的宗旨是为读者朋友们整理一份详实而又权威的面试清单&#xff0c;下面一起进入主题吧。 目录 1.概述 2.Java 基础 2.1 JDK 和 JRE 有什么区别&#xff1f; 2.2 和 equals 的区别是什么&#xff1f; 2.3 两个对象的…

ECharts实现按月统计和MTBF统计

一、数据准备 下表是小明最近一年的旅游记录 create_datecity_namecost_money2023-10-10 10:10:10北京14992023-11-11 11:11:11上海29992023-12-12 12:12:12上海19992024-01-24 12:12:12北京1232024-01-24 12:12:12上海2232024-02-24 12:12:12广州5642024-02-24 12:12:12北京…

leetcode-148. 排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5]示例 3&#x…

react18+

主要是围绕函数式组件讲&#xff0c;18主要用就是函数式组件&#xff0c;学习前先熟悉下原生js的基本使用&#xff0c;主要是事件 1、UI操作 1.1、书写jsx标签语言 基本写法和原生如同一则&#xff0c;只是放在一个方法里面返回而已&#xff0c;我们称这样的写法为函数式组件…

OrangePi Zero2 全志H616 开发初探

目录&#xff1a; 一、刷机和系统启动1、TF 卡格式化&#xff1a;2、镜像烧录&#xff1a;3、登录系统&#xff1a; 二、基于官方外设开发1、wiringPi 外设 SDK 安装&#xff1a;2、C 文件编译&#xff1a;3、基于官方外设的应用开发&#xff1a;① GPIO 输入输出&#xff1a;②…

【个人亲试最新】WSL2中的Ubuntu 22.04安装Docker

文章目录 Wsl2中的Ubuntu22.04安装Docker其他问题wsl中执行Ubuntu 报错&#xff1a;System has not been booted with systemd as init system (PID 1). Can‘t operate. 参考博客 &#x1f60a;点此到文末惊喜↩︎ Wsl2中的Ubuntu22.04安装Docker 确定为wsl2ubuntu22.04&#…

vue接入google map自定义marker教程

需求背景 由于客户需求&#xff0c;原来系统接入的高德地图&#xff0c;他们不接受&#xff0c;需要换成google地图。然后就各种百度&#xff0c;各种Google&#xff0c;却不能实现。----无语&#xff0c;就连google地图官方的api也是一坨S-H-I。所以才出现这篇文章。 google地…

【Python实战因果推断】56_因果推理概论6

目录 Causal Quantities: An Example Bias Causal Quantities: An Example 让我们看看在我们的商业问题中&#xff0c;你如何定义这些量。首先&#xff0c;你要注意到&#xff0c;你永远无法知道价格削减&#xff08;即促销活动&#xff09;对某个特定商家的确切影响&#xf…

AMEsim液压阀伯德图绘制方法

之前也在液压圈论坛里面发过类似的贴子&#xff0c;具体可以看这个网址&#x1f6aa;&#x1f449;&#xff1a;如何得出说明书里面的伯德图曲线&#xff1f;&#xff0c;回复的人还是比较少&#xff0c;这个方法重要信息是参考百度文库这篇文章&#x1f6aa;&#x1f449;&…

【系统架构设计师】计算机组成与体系结构 ⑯ ( 奇偶校验码 | CRC 循环冗余码 | 海明码 | 模 2 除法 )

文章目录 一、校验码1、校验码由来2、奇偶校验码3、CRC 循环冗余码 ( 重点考点 )4、海明码校验 ( 软考不经常考到 ) 二、CRC 循环冗余码 ( 重点考点 )1、模 2 除法概念2、模 2 除法步骤3、模 2 除法示例4、CRC 循环冗余码示例 15、CRC 循环冗余码示例 2 参考之前的博客 : 【计…

Webshell管理工具:AntSword(中国蚁剑)

中国蚁剑是一款开源的跨平台网站管理工具&#xff0c;它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。 通俗的讲&#xff1a;中国蚁剑是 一 款比菜刀还牛的shell控制端软件。 一、中国蚁剑下载 1. 下载 AntSword-Loader https://github.com/AntSwordP…

面试前端实习常问的关于【ES6新特性】的问题

ES6新特性 日常前端代码开发中&#xff0c;有哪些值得用 ES6 去改进的编程优化或者规范? 常用箭头函数来取代有this指向的函数常用 let 取代 var 命令常用数组/对象的结构赋值来命名变量&#xff08;结构更清晰&#xff0c;语义更明确&#xff0c;可读性更好&#xff09;在长字…

【C语言报错已解决】“Undefined Reference”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言&#xff1a; 在开发过程中&#xff0c;我们经常会遇到各种编译错误或运行时错误。其中&#xff0c;“Undefined Referenc…

Axure Web端元件库:从Quick UI到500+组件的飞跃

在快速变化的数字世界中&#xff0c;产品设计不仅仅是功能的堆砌&#xff0c;更是用户体验的精心雕琢。原型设计作为产品开发过程中的关键环节&#xff0c;其重要性不言而喻。Axure&#xff0c;作为业界领先的原型设计工具&#xff0c;凭借其强大的交互设计和丰富的功能&#x…