纯C读取文件实现解析H264裸流每一帧数据

2023-12-01 09:44

本文主要是介绍纯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裸流每一帧数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/440661

相关文章

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依

利用python实现对excel文件进行加密

《利用python实现对excel文件进行加密》由于文件内容的私密性,需要对Excel文件进行加密,保护文件以免给第三方看到,本文将以Python语言为例,和大家讲讲如何对Excel文件进行加密,感兴... 目录前言方法一:使用pywin32库(仅限Windows)方法二:使用msoffcrypto-too

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot整合mybatisPlus实现批量插入并获取ID详解

《SpringBoot整合mybatisPlus实现批量插入并获取ID详解》这篇文章主要为大家详细介绍了SpringBoot如何整合mybatisPlus实现批量插入并获取ID,文中的示例代码讲解详细... 目录【1】saveBATch(一万条数据总耗时:2478ms)【2】集合方式foreach(一万条数