利用FFmpeg和管道(pipe),解决非URL和非文件的输入形式
、http://my.oschina.net/michaelyuanyuan/blog/66275
0人收藏此文章, 发表于5个月前(2012-07-10 11:41) , 已有
290次阅读 ,共
1个评论
利用FFmpeg和管道(pipe),解决非URL和非文件的输入形式
问题描述:利用FFmpeg来解码,但是输入方式不是URL,也不是文件系统中的文件,而是内存中的buffer。
解决此问题有两个思路,首先明确一点,libavformat中有几个类,有URLProtocol(虽然叫URLxxx,但是不仅仅是URL的,它可是掌管了所有的输入方式),AVOutputFormat(有muxer也有demuxer),AVInputFormat(有muxer也有demu xer)。
它们对应实例可以举几个例子:
URLProtocol::ff_pipe_protocol、ff_http_protocol、ff_file_protocol。。。
AVOutputFormat:ff_mpegts_demuxer、ff_mp3_demuxer。。。
AVInputFormat:ff_mpegts_demuxer、ff_mp3_demuxer。。。
然后来说int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);函数,它的filename参数只接受URL或者文件名,但是对于问题中所说的情况,就不适合了,所以我们可以用第一个简单的办法来解决。
下面举实例说明。
现在假如是要用mpegts流的数据来源,每次我们都能调用某个接口(例如:get_ts_packet(fd, ts_buf, 188);)来获得一个完整的188字节的ts包存入buf里面,如何传给FFmpeg呢?
假设线程1是主线程,线程2是获取ts包的线程,不断调用get_ts_packet接口,线程3来调用FFmpeg。思路是
线程1:利用mkfifo新建一个命名管道(MY_FIFO_PIPE);
线程2:不断去获得ts包,然后就转存到MY_FIFO_PIPE里面;
线程3:设计为FFmpeg,直接调用avformat_open_input(&avfmtctx, MY_FIFO_PIPE, NULL, NULL);
这样在不修改FFmpeg的前提下使用FFmpeg来进行解复用解码。
还有另一种思路,就是修改URLProtocol中的某一个实例(比如file.c中的ff_file_protocol),或者新建一个URLProtocol的实例(ff_xxx_protocol),然后实现下列几个函数指针:open、read、seek(如不需要seek可不用实现),以此来适配相应的数据来源方式,最终达到使用ffmpeg标准流程来编解码的目的。