当前位置: 首页 > news >正文

纯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吧。

相关文章:

  • 系列十三、SpringBoot的自动配置原理分析
  • 【工具使用-Audition】如何使用Audition频谱分析
  • 鸿蒙(HarmonyOS)应用开发——管理组件状态
  • [ISCTF 2023]——Web、Misc较全详细Writeup、Re、Crypto部分Writeup
  • spring日志输出到elasticsearch
  • 视频文件+EasyDarwin做摄像机模拟器模拟RTSP流很方便,还能做成系统服务,方法与流程
  • 数据结构——二叉树(相关术语、性质、遍历过程)
  • 数据库表的管理
  • 【使用类、全局变量、函数参数进行传参在工程代码中的优缺点】
  • 如何使用gdb调试fork程序
  • Android 使用aapt工具获取apk信息
  • Hadoop YARN组件
  • 初学Flink 学后总结
  • WordPress采集器自动采集发布的工具
  • 鸿蒙开发:Stage模型开发-应用/组件级配置以及UIAbility组件初步使用【鸿蒙专栏-20】
  • 《Java编程思想》读书笔记-对象导论
  • 【翻译】babel对TC39装饰器草案的实现
  • Angular2开发踩坑系列-生产环境编译
  • C# 免费离线人脸识别 2.0 Demo
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • C学习-枚举(九)
  • express如何解决request entity too large问题
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • Java IO学习笔记一
  • Java,console输出实时的转向GUI textbox
  • js算法-归并排序(merge_sort)
  • JS题目及答案整理
  • laravel5.5 视图共享数据
  • PaddlePaddle-GitHub的正确打开姿势
  • Python打包系统简单入门
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • windows下mongoDB的环境配置
  • 阿里云购买磁盘后挂载
  • 前端自动化解决方案
  • 通过git安装npm私有模块
  • 微信开放平台全网发布【失败】的几点排查方法
  • Mac 上flink的安装与启动
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #100天计划# 2013年9月29日
  • (7)STL算法之交换赋值
  • (C语言)逆序输出字符串
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (附源码)php投票系统 毕业设计 121500
  • (学习日记)2024.01.09
  • (循环依赖问题)学习spring的第九天
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)大道至简,职场上做人做事做管理
  • (转载)虚函数剖析
  • ***通过什么方式***网吧
  • *p++,*(p++),*++p,(*p)++区别?
  • .NET CLR基本术语
  • .NET NPOI导出Excel详解
  • .net 获取url的方法