我们知道,ffmpeg可以读取本地文件, 网络数据http,ftp, udp, http, rtsp等, 但是这些都只需要一个简单的-i参数,后面接所需要的数据地址就可以了.之所以如此方便, 是因为ffmpeg的open_intput_file()等函数封装了很多特性,以至于我们不需要关注这些细节.
但是, 当我们需要开发特定的程序时, 即所需要的数据, 既不是本地的, 也不是从网络传输过来的, 这样就无法直接使用ffmpeg的上述方便的特性. 比如, 我们接收的是pcie传输过来的数据, 总不能先把传输过来的数据先存入本地, 然后接收完毕后再通过ffmpeg或者ffplay来操作吧. 这样肯定是不允许或者是不实际的.
如何解决上述问题, 首先想到的是改写ffmpeg的avformat_open_input()函数, 具体到如何处理filename这个数据, 这将异常麻烦. 但ffmpeg可以直接接收标准输入和管道里的数据,这样,我们可以通过管道转化,实现ffmpeg直接从内存中读取数据
具体应用
这里,用本地文件模拟, 读取本地文件到内存, 当然, 这里内存的数据,可以是从其它地方获取, 下面只是一个简单的将内存的数据写入stdin的小程序, 无实际意义. 作用是把内存的数据放入到标准输出
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #define MAX_LINE 1024*1024 int main() { int ret; char buf[MAX_LINE]; FILE *fp = fopen("aa.h264","r"); // ret = mkfifo("pipe:1",0777); // if(ret !=0) // printf("pipe error "); // fpp = fopen("pipe:1","r"); while((ret=fread(buf,1,1024,fp))!=0) { fwrite(buf,1,ret,stdout); } return 0; }
下一步, ffmpeg或者ffplay可以直接接收这些数据而不需要作任何改进.
命令是:
./test | ffplay -i -
./test | ffmpeg -i - -s 1920x1080 test.h264
这样就可以直接播放或者用ffmpeg处理这些数据了
当然, 这里的fwrite()函数只是一个简单的示例, 你可以换成特定的写入stdio的操作, 可以实现特定的协议