ffmpeg 从内存中读取数据(或将数据输出到内存)(转)
更新记录(2014.7.24):
1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开。
2.增加了将数据输出到内存的方法。
从内存中读取数据
ffmpeg一般情况下支持打开一个本地文件,例如“C:\test.avi”
或者是一个流媒体协议的URL,例如“rtmp://222.31.64.208/vod/test.flv”
其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了。
但其是否支持从内存中读取数据呢?这个问题困扰了我很长时间。当时在做项目的时候,通过Winpcap抓取网络上的RTP包,打算直接送给ffmpeg进行解码。一直没能找到合适的方法。因为抓取的数据包是存在内存中的,所以无法传递给avformat_open_input()函数其路径(根本没有路径= =)。当然也可以将抓取的数据报存成文件,然后用ffmpeg打开这个文件,但是这样的话,程序的就太难控制了。
后来经过分析ffmpeg的源代码,发现其竟然是可以从内存中读取数据的,代码很简单,如下所示:
- AVFormatContext *ic = NULL;
- ic = avformat_alloc_context();
- unsigned char * iobuffer=(unsigned char *)av_malloc(32768);
- AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL);
- ic->pb=avio;
- err = avformat_open_input(&ic, "nothing", NULL, NULL);
关键要在avformat_open_input()之前初始化一个AVIOContext,而且将原本的AVFormatContext的指针pb(AVIOContext类型)指向这个自行初始化AVIOContext。当自行指定了AVIOContext之后,avformat_open_input()里面的URL参数就不起作用了。示例代码开辟了一块空间iobuffer作为AVIOContext的缓存。
fill_iobuffer则是将数据读取至iobuffer的回调函数。fill_iobuffer()形式(参数,返回值)是固定的,是一个回调函数,如下所示(只是个例子,具体怎么读取数据可以自行设计)。示例中回调函数将文件中的内容通过fread()读入内存。
- //读取数据的回调函数-------------------------
- //AVIOContext使用的回调函数!
- //注意:返回值是读取的字节数
- //手动初始化AVIOContext只需要两个东西:内容来源的buffer,和读取这个Buffer到FFmpeg中的函数
- //回调函数,功能就是:把buf_size字节数据送入buf即可
- //第一个参数(void *opaque)一般情况下可以不用
- int fill_iobuffer(void * opaque,uint8_t *buf, int bufsize){
- if(!feof(fp_open)){
- int true_size=fread(buf,1,buf_size,fp_open);
- return true_size;
- }else{
- return -1;
- }
- }
整体结构大致如下:
- FILE *fp_open;
- int fill_iobuffer(void *opaque, uint8_t *buf, int buf_size){
- ...
- }
- int main(){
- ...
- fp_open=fopen("test.h264","rb+");
- AVFormatContext *ic = NULL;
- ic = avformat_alloc_context();
- unsigned char * iobuffer=(unsigned char *)av_malloc(32768);
- AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL);
- ic->pb=avio;
- err = avformat_open_input(&ic, "nothing", NULL, NULL);
- ...//解码
- }
将数据输出到内存
和从内存中读取数据类似,ffmpeg也可以将处理后的数据输出到内存。
回调函数如下示例,可以将输出到内存的数据写入到文件中。
- //写文件的回调函数
- int write_buffer(void *opaque, uint8_t *buf, int buf_size){
- if(!feof(fp_write)){
- int true_size=fwrite(buf,1,buf_size,fp_write);
- return true_size;
- }else{
- return -1;
- }
- }
主函数如下所示。
- FILE *fp_write;
- int write_buffer(void *opaque, uint8_t *buf, int buf_size){
- ...
- }
- main(){
- ...
- fp_write=fopen("src01.h264","wb+"); //输出文件
- ...
- AVFormatContext* ofmt_ctx=NULL;
- avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL);
- unsigned char* outbuffer=(unsigned char*)av_malloc(32768);
- AVIOContext *avio_out =avio_alloc_context(outbuffer, 32768,0,NULL,NULL,write_buffer,NULL);
- ofmt_ctx->pb=avio_out;
- ofmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;
- ...
- }
- http://blog.csdn.net/leixiaohua1020/article/details/12980423
ffmpeg 从内存中读取数据(或将数据输出到内存)(转)的更多相关文章
- ffmpeg 从内存中读取数据(或将数据输出到内存)
更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法. 从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件, ...
- ffmpeg 从内存中读取数据 .
http://blog.csdn.net/leixiaohua1020/article/details/12980423 ——————————————————————————————————————— ...
- FFMPEG内存操作(二)从内存中读取数及数据格式的转换
相关博客列表: FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 在雷神 ...
- C# 操作地址 从内存中读取写入数据(初级)
本示例以植物大战僵尸为例, 实现功能为 每1秒让阳光刷新为 9999.本示例使用的游戏版本为 [植物大战僵尸2010年度版], 使用的辅助查看内存地址的工具是 CE. 由于每次启动游戏, 游戏中阳光 ...
- 数据库的应用——直接从内存中读取osg节点 (转)
数据库的应用——直接从内存中读取osg节点 目的:要从数据库中读取节点数据到osg. 一开始的方法是这样的,每当我要添加一个数据库中的节点数据时,首先把它读取到内存中,然后写入一个文件,最后再次从文件 ...
- 从文件中读取yuv和h264数据
1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...
- arcgis python 使用光标和内存中的要素类将数据加载到要素集 学习:http://zhihu.esrichina.com.cn/article/634
学习:http://zhihu.esrichina.com.cn/article/634使用光标和内存中的要素类将数据加载到要素集 import arcpy arcpy.env.overwriteOu ...
- php 如何在有限的内存中读取大文件
突然遇到了一个要读取超过80M文件的需求,很悲剧的,不管是file_get_content还是file什么的,都会将读取的文件一次性加载到内存中. 正常情况下,我们可以使用fseek来读取,好处就是不 ...
- 面试题:java内存中的堆区和数据结构中的堆有什么区别
java内存中的堆是一个 链表, 数据结构中的堆:就是一个栈
随机推荐
- 通过自动回复机器人学Mybatis:MySQL脚本 + db >> dao >> service >> servlet
留着参考 makeData.sql delimiter // create procedure make_data() begin declare i int ; do insert into mes ...
- confluence wiki 安装
1. 下载 wget https://www.atlassian.com/software/confluence/downloads/binary/atlassian-confluence-5.6.6 ...
- 通用Linux内核优化配置
通用Linux内核优化配置 针对CentOS6.CentOS7.Redhat6.Redhat7等系统 net.ipv4.ip_forward = net.ipv4.conf. net.ipv4.con ...
- HDU 5934 Bomb(tarjan/SCC缩点)题解
思路:建一个有向图,指向能引爆对象,把强连通分量缩成一点,只要点燃图中入度为0的点即可.因为入度为0没人能引爆,不为0可以由别人引爆. 思路很简单,但是早上写的一直错,改了半天了,推倒重来才过了... ...
- Android中的代理模式
代理的概念:为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类处 ...
- angular大牛的博客
对angular的了解比亲娘还了解,http://each.sinaapp.com/angular/index.html 对angular比较深入的研究,这个人的所有博客都值得一看,这是7. http ...
- DOM window的事件和方法; Rails查询语法query(查询结构继承); turbolinks的局限;
window.innerHeight 是浏览器窗口可用的高度. window.outerHeight 是浏览器窗口最大的高度. 打开chrome-inspector,上下移动inspector,看到s ...
- Mybatis四种分页方式
数组分页 查询出全部数据,然后再list中截取需要的部分. mybatis接口 List<Student> queryStudentsByArray(); xml配置文件 <sele ...
- hdu3032sg打表找规律
先打个表冷静一下 #include<map> #include<set> #include<cmath> #include<queue> #includ ...
- C# 格式化一些知识点
这是在看<C#本质论>偶然遇见的一个问题,看不懂,那后面的就没有法看了,于是百度搜索了“C#格式化”这一关键字,于是有了下面的内容.很多一下子记不住,又怕自己忘记,还是做一个笔记吧,方便自 ...