.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.xdnf.cn/news/1488966.html

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

相关文章

Linux冯诺依曼体系、操作系统、进程概念、进程状态、进程切换

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;Linux 目录 一、冯诺依曼体系结构 二、操作系统 1、概念 2、为什么要有操作系统&#xff1f; 3、理解操作系统 1.管理的本质 2.管理的概念 3.操作系统结构图 4.为什么要有操作系统&#xff1f; 三…

Windows版本免费PyMol的安装

技术背景 在前面一篇博客中&#xff0c;我们介绍过在Linux平台下安装和使用免费版本的PyMol。其实同样的这个免费版在Windows平台上(这里以win11为例)也是支持的。 安装流程 这个免费版本的PyMol依赖于Conda&#xff0c;因此首先需要访问conda官网下载一个miniconda到本地进行安…

鸿蒙UI系统组件10——菜单(Menu)

果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下面名片&#xff0c;关注公众号。 Menu是菜单接口&#xff0c;一般用于鼠标右键弹窗、点击弹窗等。 1、创建默认样式的菜单 菜单需要调用bindMenu接口来实现。bindMenu响应绑定组件的点击事件&am…

【权威发布】第二届机械电子工程与软件工程国际会议(MEESE 2024)

第二届机械电子工程与软件工程国际会议 2024 International Conference on Mechanical and Electronic Engineering and Software Engineering 【1】会议简介 第二届机械电子工程与软件工程国际会议是一个专注于机械电子工程与软件工程领域交叉融合的国际盛会。会议旨在汇聚全球…

充满惊喜与欢乐的老友

在这个充满惊喜与欢笑的娱乐圈里&#xff0c;每一个不经意的可能成为网友热议的焦点&#xff0c;而《快乐老友记》的花絮&#xff0c;无疑为这个多彩的世界又添上了一抹亮丽的色彩。当“王栎鑫被路人认成张艺兴”这一话题如春风般拂过网络&#xff0c;不仅让两位才华横溢的艺人…

concrt140.dll丢失是什么情况?有效的解决dll!

concrt140.dll文件丢失是电脑中少见的文件&#xff0c;但也会因为某些原因会导致电脑丢失concrt140.dll文件&#xff0c;那么出现这文件的原因是什么呢&#xff1f;出现这样的问题有什么办法可以将concrt140.dll修复呢&#xff1f;一起来看看吧。 为什么会缺失concrt140.dll文件…

Java企业微信服务商代开发获取AccessToken示例

这里主要针对的是企业微信服务商代开发模式 文档地址 可以看到里面大致有三种token&#xff0c;一个是服务商的token&#xff0c;一个是企业授权token&#xff0c;还有一个是应用的token 这里面主要有下面几个参数 首先是服务商的 corpid 和 provider_secret &#xff0c;这个可…

多域DNS服务器搭建

搭建dns服务器&#xff0c;可以同时解析多个域名 www.yuanyu.zhang 10.1.1.10 bbs.yuanyu.zm co.yuanyu.cc vim /etc/named.rfc1912.zones 58 zone "yuanyu.zm" IN { 59 type master; 60 file "yuanyu.zm.zone"; 61 all…

Java基础入门14:常用API(Object(s)类、包装类、Math、Arrays、日期时间、Lambda表达式、方法引用)

Object类 Object类是Java中所有类的祖宗类&#xff0c;因此&#xff0c;Java中所有类的对象都可以直接使用Object类中提供的一些方法。 Object类的常见方法&#xff1a; package com.itchinajie.d12_api_object;public class Test {public static void main(String[] args) {…

bgp 简单认证功能

原理概述 路由协议通常分为内部网关协议&#xff08;IGP: Interior Gateway Protocol&#xff09;和外部网关协议(EGP: Exterior Gateway Protocol)两大类。一般来讲&#xff0c;IGP用于自治系统AS(AutonomousSystem)内部&#xff0c;EGP用于AS之间。最早的IGP是一种称为GGP (G…

【iOS】——通知机制及底层原理

通知传值概要 通知传值可以跨越多个界面进行传值&#xff0c;一般用于后一个界面向前一个界面传值。 通知传值支持多个接收者&#xff0c;多个对象可以同时接收同一个通知并进行处理。这样可以实现一对多的通信&#xff0c;方便跨多个对象进行值传递。 使用步骤 1.在发送者中…

微前端--qiankun

qiankun qiankun分为accpication和parcel模式。 aplication模式基于路由工作&#xff0c;将应用分为两类&#xff0c;基座应用和子应用&#xff0c;基座应用维护路由注册表&#xff0c;根据路由的变化来切换子应用。子应用是一个独立的应用&#xff0c;需要提供生命周期方法供…

【NPU 系列专栏 4 -- 高带宽内存 HBM3 详细介绍】

请阅读【嵌入式及芯片开发学必备专栏】 文章目录 高带宽内存 (HBM3) 简介高带宽低功耗高容量紧凑的封装 HBM3 应用场景深度学习与人工智能高性能计算 (HPC)数据分析与大数据处理图形处理与游戏 HBM3 应用举例英伟达 H100 GPUAMD MI200 系列 GPUSummary 高带宽内存 (HBM3) 简介 …

有什么好用的AI工具推荐吗?

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 所有打工人集合&#xff01;根据你问题中的描述&#xff0c;本小白正好都有涉及过相关领域的AI工具。 今天一次性讲清能处理所有办公场景的AI工具…

HarmonyOs之 路由简单跳转

Navigation路由相关的操作都是基于页面栈NavPathStack提供的方法进行&#xff0c;每个Navigation都需要创建并传入一个NavPathStack对象&#xff0c;用于管理页面。主要涉及页面跳转、页面返回、页面替换、页面删除、参数获取、路由拦截等功能。 Entry Component struct Index …

2024最新 Navicat Premium 17.0.12简体中文版破解激活永久使用(保姆级教程)

2024最新 Navicat Premium 17.0.12 简体中文版破解激活永久使用&#xff08;保姆级教程&#xff09; 一、Navicat Premium 17下载二、Navicat Premium 17安装三、激活永久使用 一、Navicat Premium 17下载 官网-安装包 官网地址&#xff1a;https://www.navicat.com.cn/downlo…

永磁同步电机无速度算法--非线性磁链观测器

非线性磁链观测器顾名思义观测器的状态变量为磁链值&#xff0c;观测的磁链值收敛于电机实际磁链值&#xff0c;观测器收敛。非线性是由于观测器存在sin和cos项&#xff0c;所以是非线性观测器 一、原理介绍 表贴式永磁同步电机αβ轴电压方程: 将公式变换 定义状态变量X: 定…

Java学习笔记(六)面向对象编程(基础部分)

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍Java面向对象编程&#xff08;基础部分&#xff09;类与对象、方法重载、作用域、构造器细节、this关键字、可变参数使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1…

零食商城管理系统

目录 一、项目背景与目标 1.1 项目背景 1.2 项目意义 1.3 国内外研究现状 1.4 开发工具介绍 二、项目内容与分工 三、 时间表与进度 1. 需求分析阶段&#xff1a; 2. 系统设计阶段&#xff1a; 3. 系统开发阶段&#xff1a; 4. 系统测试阶段&#xff1a; 5. 部署与上…

python项目通过docker部署到Linux系统并实现远程访问

背景需求&#xff1a;在Windows系统编写了简单的python代码&#xff0c;希望能通过docker打包到Linux Ubuntu系统中&#xff0c;并运行起来&#xff0c;并且希望在本地Windows系统中能通过postman访问。 目录 一、原本的python代码 二、创建一个简单的Flask应用程序 三、创…