C++处理YUV格式视频【帧平均法】
1.原理图
2.处理函数,
class YuvOperationtwo {public:void averageFrame(int totalPix,unsigned char* before_data, unsigned char* write_data, unsigned char* after_data);};
void YuvOperationtwo::averageFrame(int totalPix,unsigned char* before_frame, unsigned char* write_frame, unsigned char* after_frame) {//前一帧,写入帧,后一帧的活动指针unsigned char* activity_before_frame = before_frame;unsigned char* w_write_frame = write_frame;unsigned char* activity_after_frame = after_frame;for (int j = 1; j <= totalPix; j++) {//除2是因为d1与d2相同*w_write_frame = *activity_before_frame / 2 + *activity_after_frame / 2;w_write_frame++;activity_before_frame++;activity_after_frame++;}
}
调用
const char* inPath = "D:\\YUM\\experiment three\\RaceHorses_416x240_30.yuv";const char* outOddPath = "D:\\YUM\\experiment three\\RaceHorses_416x240_30_odd.yuv";FILE* fin = fopen(inPath, "rb+");if (!fin) {cout << "Open file failed!" << endl;return -1;}FILE* fout = fopen(outOddPath, "a");if (!fout) {cout << "Open file failed!" << endl;return -1;}int width = 416;int height = 240; int totalPix = int(width * height * 1.5);//每帧像素个数为416×240,420视频序列yuv每个像素占用1.5byte的像素空间。int nFrame, size;fseek(fin, 0, SEEK_END); //将文件指针移到文件末尾,偏移0个字节;fseek(fp,50L,0);或fseek(fp,50L,SEEK_SET);解释:其作用是将位置指针移到离文件头50个字节处size = ftell(fin); //得到文件尾相对于文件首的位移,即文件的总字节数rewind(fin); //重置文件指针指向文件头部nFrame = size / totalPix; //得到视频文件的总帧数cout << "视频总帧数:" << nFrame << endl;//这里只能用unsigned char 不能用char。unsigned char* before_frame = new unsigned char[totalPix](); //前一帧unsigned char* write_frame = new unsigned char[totalPix](); //预测帧unsigned char* after_frame = new unsigned char[totalPix](); //后一帧//nFrame可理解为生成的帧数,10--》生成10帧for (int frame = 0; frame < nFrame; frame++) {//读取1-2-3。。。帧fread(before_frame, 1, totalPix, fin); //读取2-3-4。。。帧fread(after_frame, 1, totalPix, fin);//第二次读取时候文件指针移动到第2帧处,需要向后移动一帧大小的位数fseek(fin, -totalPix, SEEK_CUR); YuvOperationtwo y;y.averageFrame(totalPix, before_frame, write_frame, after_frame);fwrite(write_frame, 1, totalPix, fout);}fclose(fin);fclose(fout);system("pause");return 0;
踩坑1
unsigned char 和 char的区别:
虽然都是占用1个字节,8位,且都能表示256个数字,但是char表示的范围为-128~127,而unsigned char表示的范围为0-255。在读取yuv二进制文件时候出现单个位数大于127的情况,就会导致出问题。如
unsigned char uc=255; char c=255; printf("%d %d",uc,c); 结果为: 255 -1
因为char类型表示有符号数,而二进制中最高位表示正负,255二进制表示为11111111在计算机内进行存储,为补码形式,转化为原码即为-1。
踩坑2
在进行测试不使用函数的情况下,活动指针必须要放在循环体里边,不能放在循环体外部。
踩坑3
在仅处理1,2帧得到1和2之间的插入帧时候也要使用中间指针,不能使用原定义的数组,这里不是多清楚原因,从java到c++底子太弱了。
分开处理YUV的写法
1.函数
class YuvOperationtwo {public:void averageFrameYuv(int width, int hegith,unsigned char* before_y_read_data, unsigned char* before_u_read_data, unsigned char* before_v_read_data, unsigned char* y_write_data, unsigned char* u_write_data, unsigned char* v_write_data, unsigned char* after_y_read_data, unsigned char* after_u_read_data, unsigned char* after_v_read_data);
};void YuvOperationtwo::averageFrameYuv(int width,int hegith,unsigned char* before_y_read_data, unsigned char* before_u_read_data, unsigned char* before_v_read_data, unsigned char* y_write_data, unsigned char*u_write_data, unsigned char* v_write_data, unsigned char* after_y_read_data, unsigned char* after_u_read_data, unsigned char* after_v_read_data) {//前一帧的yuv--游标指针unsigned char* read_before_y = before_y_read_data;unsigned char* read_before_u = before_u_read_data;unsigned char* read_before_v = before_v_read_data;//后一帧的yuv--游标指针unsigned char* read_after_y = after_y_read_data;unsigned char* read_after_u = after_u_read_data;unsigned char* read_after_v = after_v_read_data;//要写入的yuvunsigned char* write_img_y = y_write_data;unsigned char* write_img_u = u_write_data;unsigned char* write_img_v = v_write_data;int yWidth = width;int yHeight = hegith;int uvWidth = width / 2;int uvHeight = hegith / 2;int i = 0, j = 0;//对Y分量进行前后平均预测for (i = 0; i < yHeight; i++) {for (j = 0; j < yWidth; j++) {*write_img_y = *read_before_y / 2 + *read_after_y / 2;write_img_y++;read_before_y++;read_after_y++;}}//对UV分量进行前后预测for (i = 0; i < uvHeight; i++) {for (j = 0; j < uvWidth; j++) {*write_img_u = *read_before_u / 2 + *read_after_u / 2;write_img_u++;read_before_u++;read_after_u++;*write_img_v = *read_before_v / 2 + *read_after_v / 2;write_img_v++;read_before_v++;read_after_v++;}}
主函数
const char* inPath = "D:\\YUM\\experiment three\\RaceHorses_416x240_30.yuv";const char* outOddPath = "D:\\YUM\\experiment three\\RaceHorses_416x240_30_odd.yuv";FILE* fin = fopen(inPath, "rb+");if (!fin) {cout << "Open file failed!" << endl;return -1;}FILE* fout = fopen(outOddPath, "a");if (!fout) {cout << "Open file failed!" << endl;return -1;}int width = 416;int height = 240;int totalSize = width * height;int nFrame = 0, fileTotalSize = 0;int totalPix = int(width * height * 1.5);//每帧像素个数为416×240,420视频序列yuv每个像素占用1.5byte的像素空间。unsigned char* before_frame_y = new unsigned char[totalSize]();unsigned char* before_frame_u = new unsigned char[totalSize / 4]();unsigned char* before_frame_v = new unsigned char[totalSize / 4]();unsigned char* write_frame_y = new unsigned char[totalSize]();unsigned char* write_frame_u = new unsigned char[totalSize / 4]();unsigned char* write_frame_v = new unsigned char[totalSize / 4]();unsigned char* after_frame_y = new unsigned char[totalSize]();unsigned char* after_frame_u = new unsigned char[totalSize / 4]();unsigned char* after_frame_v = new unsigned char[totalSize / 4]();for (int frame = 0; frame < 10; frame++) {fread(before_frame_y, totalSize, 1, fin);fread(before_frame_u, totalSize/4, 1, fin);fread(before_frame_v, totalSize/4, 1, fin);fread(after_frame_y, totalSize, 1, fin);fread(after_frame_u, totalSize / 4, 1, fin);fread(after_frame_v, totalSize / 4, 1, fin);fseek(fin, -totalPix, SEEK_CUR);YuvOperationtwo y;y.averageFrameYuv(width, height, before_frame_y, before_frame_u, before_frame_v,write_frame_y, write_frame_u, write_frame_v, after_frame_y, after_frame_u, after_frame_v);fwrite(write_frame_y, totalSize, 1, fout);fwrite(write_frame_u, totalSize / 4, 1, fout);fwrite(write_frame_v, totalSize / 4, 1, fout);}fclose(fin);fclose(fout);system("pause");return 1;
C++处理YUV格式视频【帧平均法】相关推荐
- vs2010MFC D3D播放YUV格式视频详细制作全过程
1.环境配置 1.1 Microsoft Visual Studio 2010安装 先下载Visual Studio 2010,然后双击setup.exe安装,安装时有一步选择vc++安装就可以了,其 ...
- vs2010MFC D3D播放YUV格式视频详细制作全过程
目录(?)[+] 1.环境配置 1.1 Microsoft Visual Studio 2010安装 先下载Visual Studio 2010,然后双击setup.exe安装,安装时有一步选择vc+ ...
- FFmpeg4入门07:解码视频并保存为YUV格式文件
上一篇我们解码并保存了其中的几帧确保解码过程和结果是对的.本篇我们将解码整个视频并保存为标准的YUV格式(YUV格式具体信息详见YUV格式介绍),我们就选YUV420P(I420)作为输出格式. 保存 ...
- 使用v4l2音、视频协议实现USB摄像头的图像、视频YUV格式采集功能(ubuntu16.04LTS)
第一感觉是首先得了解v4l2协议,它的功能.以及与之对应的实现逻辑,还有与硬件.操作系统的交互等内容.再试着根据功能逻辑和软硬件交互关系,借助硬件设备,实现基础的功能,如查询设备信息.帧类型等.然后, ...
- 视频和视频帧:图像,从自然光到01串
视频和视频帧:图像,从自然光到01串 视频和视频帧:图像,从自然光到01串 资料来源 视频和视频帧:图像,从自然光到01串 写在前面 从今年(2019年)年中接手AI摄像头开发项目,笔者第一次真的到了 ...
- 【Bug修复】yuv生成mp4格式文件帧数(时间)与原视频不一致
问题描述 需要将一系列的视频从yuv格式的文件编码成每秒30帧的视频,但是在yuv生成mp4格式时,存在帧数不对齐的问题. 1.准备两个视频 Animation_1080P-209f.mkv,25fp ...
- 音视频处理基础知识扫盲:数字视频YUV像素表示法以及视频帧和编解码概念介绍
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...
- 关于视频的YUV格式介绍
本文转载于图文详解YUV420数据格式 YUV格式有两大类:planar和packed. 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V. 对于 ...
- AVI格式视频转YUV
网上找这一方面找的还蛮困难的,开始只能找到别人写的一长串的代码,但不想用这种方式,觉得麻烦.现在也不知道这个问题算解决没有,因为感觉播放不是很清楚,打算明天找找比较两个视频的异同的指标乃至代码,看转换 ...
最新文章
- Android安全问题 抢先接收广播 - 内因篇之广播接收器注册流程
- Java程序的运行原理及JVM的启动是多线程的吗?
- 在WAS中得到OracleConnection
- java编译器使用教程_Java编译器API简介
- SD 胡策 Round 1 T3 彩尾巴猹的二进制数
- 微信开源项目讲解使用公开课
- 类的定义 java 1613806383
- [工具]将xml文件转换为html显示
- 带有记忆的菲波那切数列
- matlab积分器的工作原理,Simulink积分器详解(图)
- springboot 返回二进制文件流
- win2008R2 AD域 网络驱动映射
- Springboot文件上传报错:failed to convert java.lang.String to org.springframework.util.unit.DataSize
- word中如何制作三线表
- Probability and Stochastic Models(1) —— 研一新课学习笔记
- Android Kotlin - 监听耳机的插入和拔出
- 资源分享:嵌入式stm32项目开发 心率检测仪的设计与实现
- ViSual Studio美化插件设置背景图片
- HADOOP组成部分
- 云终端服务器的单价是多少_电子阅览室云终端报价方案