//实现功能:把某一个1080p的yuv文件重复写入新的yuv文件 //N:表示重复写入的次数,生成一个更大的yuv文件,用来测试 //得注意一个问题:feof() #include <stdio.h> #include <memory.h> #include <stdlib.h> #define VIDEO_SOURCE_FILE "D:\\cudaEncode\\data\\ED_1920_1080.yuv"//214帧 #define VIDEO_OUTPUT_FILE "D:\\cudaEncode\\data\\ED_1920_1080_2.yuv" #define SIZE 1920*1080*3/2 #define N 2 int main() { FILE *fpIn,*fpOut; int count=1; if ((fpIn=fopen(VIDEO_SOURCE_FILE,"rb"))==NULL) { printf("fopen() error!\n"); } if((fpOut=fopen(VIDEO_OUTPUT_FILE,"wb"))==NULL) { printf("fopen() error!\n"); } char *buf; buf=(char *)malloc(SIZE); memset(buf,0,SIZE); for (int i=0;i<N;i++) { fread(buf,1,SIZE,fpIn); while (!feof(fpIn)) { printf("第 %d 次写入第 %3d 帧\n",i,count); fwrite(buf,1,SIZE,fpOut); fread(buf,1,SIZE,fpIn); count++; } /* while (!feof(fpIn)) { fread(buf,1,SIZE,fpIn); printf("第 %d 次写入第 %3d 帧\n",i,count); fwrite(buf,1,SIZE,fpOut); count++; } //这种写法会把最后一帧重复写一遍 //为什么呢?因为feof判断最后一帧的时候,并不能确定是最后一帧, //只有再接着fread才能确定,此时才返回1值 */ rewind(fpIn);//或fseek(fpIn,0L,SEEK_SET); count=1; } printf("完成!\n"); free(buf); buf=NULL; fclose(fpIn); fclose(fpOut); return 0; }
上面针对的是1080p的yuv文件,4:2:0,分辨率为1920x1080.
如果是其他格式的yuv分辨率,只需把SIZE修改下,4:2:0下,一帧的大小:分辨率乘积*3/2
为什么是先乘以3再除以2呢,这与采样格式有关。
对于4:4:4没有压缩的格式,8比特量化后,每个像素占用3个字节,那么4:4:4采样格式的文件每一帧大小为:分辨率乘积*3
对于4:2:2采样格式,每4个像素,需要字节数为4+2+2=8,则每个像素占用8/4=2个字节,则每一帧大小为:分辨率乘积*2
对于4:1:1采样格式,每4个像素,需要字节数为4+1+1=6,则每个像素占用6/4=1.5个字节,则每一帧大小为:分辨率乘积*3/2
对于4:2:0采样格式(最常用),同时对水平方向和垂直方向采样
两行8个像素,需要字节数为:第一行4+2,第二行4+2,总共需要字节数为12,则每个像素占用12/8=1.5个字节,则每一帧大小为:分辨率乘积*3/2