本文主要是介绍纯C读取文件实现解析H264裸流每一帧数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近研究硬解解码,需要解码H264流文件。
imx的例程是设置一个大的缓冲区,一次性读入不超过10M字节数据,然后全部送到解码器进行解码,对于小于10M字节的视频数据确实很方便的解码了,但是文件大了这种方式就不行了。
如果暴力分段送入解码器,因为无法找到H264的起始码,解码器会报错。
还有一种处理方式是使用FFMpeg来读取每一帧数据,然后送入解码器,是可行的。参考这篇博文。
使用FFmpeg开发2-比特流过滤器-CSDN博客
但是为了简化方便,不想用FFMpeg来实现。
这里写个纯C读取文件实现分离H264帧。
首先分析下H264裸流文件,发现每一帧数据的起始码是00 00 00 01,那么就可以利用这个起始码来拆分每一帧数据。
代码很简单,就是持续读取文件,碰到00 00 00 01则表示一帧读完,然后把这一帧数据送到解码器处理即可。
因为每一帧的开头都是这个起始码,所以开始直接读取四字节。
//读取一帧H264数据
int read_one_frame(FILE *fp, unsigned char *ptr){int size=0;static unsigned char ts[4]={0};printf("read one frame\n");//防止文件数据错误if(fread(ptr,1,4,fp)<4){printf("read start error\n");return size;}if((*ptr==0x00) && (*(ptr+1)==0x00) && (*(ptr+2)==0x00) && (*(ptr+3)==0x01)){size=4;while(1){if(fread(ptr+size,1,1,fp)){ts[0]=ts[1];ts[1]=ts[2];ts[2]=ts[3];ts[3]=*(ptr+size);size++;if((ts[0]==0x00) && (ts[1]==0x00) && (ts[2]==0x00) && (ts[3]==0x01) ){//读取到下一帧的起始码,即表示这帧读完了,后移文件指针size-=4;fseek(fp,-4,SEEK_CUR);//printf("read one frame end \n");break;}}elsebreak;//读完文件退出循环}}//读取到的数据大小return size;
}
再写个小小的main来测试下
#include <stdio.h>
#include <stdlib.h>int main(void){int readbytes;int totalReadSize=0;int length=1024*1024*10;unsigned char *ptr;ptr=malloc(length);FILE *fp=fopen("200frames_count.h264", "rb");int fileSize;fseek(fp, 0L, SEEK_END);fileSize = ftell(fp);fseek(fp, 0L, SEEK_SET);printf("fileSize=0x%x\n", fileSize);while(totalReadSize<fileSize){readbytes=read_one_frame(fp, ptr);if(readbytes==0){printf("read end\n");break;}else{for(int i=0;i<readbytes;i++)printf("%x ", *(ptr+i));}totalReadSize+=readbytes;printf("readbytes: 0x%X total read size: 0x%X \r\n",readbytes, totalReadSize);}return 0;}
从打印数据看,成功实现了每一帧数据的读取,经过测试可用,老铁们可以自己拿去优化使用。
对于H264裸流文件可以这么处理,如果是带格式的,老铁们还是用FFMpeg吧。
这篇关于纯C读取文件实现解析H264裸流每一帧数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!