文档章节

ffmpeg 从内存中读取数据(或将数据输出到内存)

雷霄骅
 雷霄骅
发布于 2014/08/16 13:58
字数 814
阅读 282
收藏 0

更新记录(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中的函数
int fill_iobuffer(void * buffer,uint8_t *iobuf, 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 * buffer,uint8_t *iobuf, int bufsize){
...
}

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;
	}
}


主函数如下所示,也是先初始化AVIOContext。

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

共有 人打赏支持
雷霄骅
粉丝 205
博文 419
码字总数 2129
作品 4
朝阳
程序员
私信 提问
wasm + ffmpeg实现前端截取视频帧功能

有没有那么一种可能,在前端页面处理音视频?例如用户选择一个视频,然后支持他设置视频的任意一帧作为封面,就不用把整一个视频上传到后端处理了。经过笔者的一番摸索,基本实现了这个功能,...

人人网FED
2018/07/28
0
0
一步步教ffmpeg的C语言音视频编程

欢迎访问我的博客原文:https://lightfish.cn/2018-12-20-ffmpeg-primer 前言 本文以 ffmpeg 工具,讲述如何认识音视频编程,你可以了解到常见视频格式的大概样子,一步步学会如何使用 ffmp...

光鱼
01/22
0
0
学习FFmpeg API – 解码视频

ffmpeg是编解码的利器,用了很久,以前看过dranger 的教程,非常精彩,受益颇多,是学习ffmpeg api很好的材料。可惜的是其针对的ffmpeg版本已经比较老了,而ffmpeg的更新又很快,有些API已经...

霄霄月月
2012/05/08
0
32
FFmpeg编写一个简单播放器 -1

指导1:制作屏幕录像 概要 电影文件有很多基本的组成部分。首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。AVI和Quicktime就是容器的例子。接着,你有一组流...

GuoKai
2012/09/19
0
1
最简单的基于FFMPEG+SDL的视频播放器:拆分-解码器和播放器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leixiaohua1020/article/details/46889389 ===================================================== 最简单的...

雷霄骅
2015/07/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JS 调用Angularjs 的方法

// 1. 获取 Controllerlet appElement = document.querySelector('[data-ng-controller=MessagesCtrl]');let scope = angular.element(appElement).scope();// 2. 调用方法scope.l......

Moks角木
19分钟前
0
0
dubbo+zookeeper与 eureka的区别

CAP CAP 原则指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得 在分布式架构里, P必须有 Zookeeper保证C P 当...

群星纪元
28分钟前
0
0
云计算之边缘计算大势所趋

如果说边缘计算是公同认定的目标,那么我们看到,不同类型的厂商基于自身的特点,会从不同的起点、沿着不同的路径,向这个目标奔跑。上次参加阿里云的一次活动,看到他们将边缘计算的厂商分成...

linuxCool
33分钟前
0
0
前端通过后端传过来的'\n' ,''等字符串换行失败问题

后台推送换行符 '\n' 或 '<br/>' 等字符串到前台不会换行 详细描述 后台逻辑处理返回String字符串,其中包含\n或<br/>等换行符号,但是前端渲染时候却并没有真正的换行 也尝试了大佬的各种 ...

下次用oschina
40分钟前
2
0
volatile能保证有序性吗?

在前面提到volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性。   volatile关键字禁止指令重排序有两层意思:   1)当程序执行到volatile变量的读操作或者写操作时...

无精疯
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部