需要的解码的视频数据在一段内存中。例如,通过其他系统送来的视频数据。同样,有的时候编码后的视频数据也未必要保存成一个文件。例如,要求将编码后的视频数据送给其他的系统进行下一步的处理。以上两种情况就要求FFmpeg不仅仅是对文件进行“读,写”操作,而是要对内存进行“读,写”操作。
从内存中读取数据
经过分析ffmpeg的源代码,发现其是可以从内存中读取数据的:
  1. AVFormatContext *ic = NULL;
  2. ic = avformat_alloc_context();
  1. unsigned char * iobuffer=(unsigned char *)av_malloc(32768);
  2. AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL);
  3. ic->pb=avio;
  4. 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()读入内存。
  1. //读取数据的回调函数-------------------------
  2. //AVIOContext使用的回调函数!
  3. //注意:返回值是读取的字节数
  4. //手动初始化AVIOContext只需要两个东西:内容来源的buffer,和读取这个Buffer到FFmpeg中的函数
  5. //回调函数,功能就是:把buf_size字节数据送入buf即可
  6. //第一个参数(void *opaque)一般情况下可以不用
  7. int fill_iobuffer(void * opaque,uint8_t *buf, int bufsize){
  8. if(!feof(fp_open)){
  9. int true_size=fread(buf,1,buf_size,fp_open);
  10. return true_size;
  11. }else{
  12. return -1;
  13. }
  14. }
整体结构大致如下:
  1. FILE *fp_open;
  2. int fill_iobuffer(void *opaque, uint8_t *buf, int buf_size){
  3. ...
  4. }
  5. int main(){
  6. ...
  7. fp_open=fopen("test.h264","rb+");
  8. AVFormatContext *ic = NULL;
  9. ic = avformat_alloc_context();
  10. unsigned char * iobuffer=(unsigned char *)av_malloc(32768);
  11. AVIOContext *avio =avio_alloc_context(iobuffer, 32768,0,NULL,fill_iobuffer,NULL,NULL);
  12. ic->pb=avio;
  13. err = avformat_open_input(&ic, "nothing", NULL, NULL);
  14. ...//解码
  15. }
将数据输出到内存
也可以将处理后的数据输出到内存。
回调函数如下示例,可以将输出到内存的数据写入到文件中。
  1. //写文件的回调函数
  2. int write_buffer(void *opaque, uint8_t *buf, int buf_size){
  3. if(!feof(fp_write)){
  4. int true_size=fwrite(buf,1,buf_size,fp_write);
  5. return true_size;
  6. }else{
  7. return -1;
  8. }
  9. }
主函数如下所示。
  1. FILE *fp_write;
  2. int write_buffer(void *opaque, uint8_t *buf, int buf_size){
  3. ...
  4. }
  5. main(){
  6. ...
  7. fp_write=fopen("src01.h264","wb+"); //输出文件
  8. ...
  9. AVFormatContext* ofmt_ctx=NULL;
  10. avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL);
  11. unsigned char* outbuffer=(unsigned char*)av_malloc(32768);
  12. AVIOContext *avio_out =avio_alloc_context(outbuffer, 32768,0,NULL,NULL,write_buffer,NULL);
  13. ofmt_ctx->pb=avio_out;
  14. ofmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;
  15. ...
  16. }
关键点
关键点就两个:
1.      初始化自定义的AVIOContext,指定自定义的回调函数。示例代码如下:
  1. //AVIOContext中的缓存
  2. unsigned char *aviobuffer=(unsigned char*)av_malloc(32768);
  3. AVIOContext *avio=avio_alloc_context(aviobuffer, 32768,0,NULL,read_buffer,NULL,NULL);
  4. pFormatCtx->pb=avio;
  5. if(avformat_open_input(&pFormatCtx,NULL,NULL,NULL)!=0){
  6. printf("Couldn't open inputstream.(无法打开输入流)\n");
  7. return -1;
  8. }
上述代码中,自定义了回调函数read_buffer()。在使用avformat_open_input()打开媒体数据的时候,就可以不指定文件的URL了,即其第2个参数为NULL(因为数据不是靠文件读取,而是由read_buffer()提供)
2.      自己写回调函数。示例代码如下:
  1. //Callback
  2. int read_buffer(void *opaque, uint8_t *buf, int buf_size){
  3. if(!feof(fp_open)){
  4. int true_size=fread(buf,1,buf_size,fp_open);
  5. return true_size;
  6. }else{
  7. return -1;
  8. }
  9. }
当系统需要数据的时候,会自动调用该回调函数以获取数据。这个例子为了简单,直接使用fread()读取数据至内存。回调函数需要格外注意它的参数和返回值。
avio_alloc_context第3个参数Set to 1 if the buffer should be writable, 0 otherwise. 为0时表示ffmpeg要从回调函数里读取数据。为1表示ffmpeg会将数据输出到回调函数中。
参考:

ffmpeg 内存读写相关的更多相关文章

  1. 基于最简单的FFmpeg采样读取内存读写:存储转

    ===================================================== 基于最简单的FFmpeg样品系列读写内存列表: 最简单的基于FFmpeg的内存读写的样例:内 ...

  2. 基于最简单的FFmpeg采样读取内存读写:内存玩家

    ===================================================== 基于最简单的FFmpeg样品系列读写内存列表: 最简单的基于FFmpeg的内存读写的样例:内 ...

  3. 最简单的基于FFmpeg的内存读写的例子:内存转码器

    ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...

  4. 最简单的基于FFmpeg的内存读写的例子:内存播放器

    ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...

  5. (转)最简单的基于FFmpeg的内存读写的例子:内存播放器

    ffmpeg内存播放解码 目录(?)[+] ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章 ...

  6. FFMPEG内存操作(二)从内存中读取数及数据格式的转换

    相关博客列表: FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 在雷神 ...

  7. FFmpeg内存操作(三)内存转码器

    相关博客列表 : FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 本文 ...

  8. FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析

    相关博客列表 : FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 在F ...

  9. Java内存模型相关原则详解

    在<Java内存模型(JMM)详解>一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则.而Java内存模型又是围绕着在并发过程中如何处理原子性.可见性以及有序性这三个特征来构 ...

随机推荐

  1. GOPATH 使用总结

    GOPATH 环境变量用于指定这样一些目录:除 $GOROOT 之外的包含 Go 项目源代码和二进制文件的目录.go install 和 go 工具会用到 GOPATH:作为编译后二进制的存放目的地 ...

  2. 盘点8种CSS实现垂直居中水平居中的绝对定位居中技术

    Ⅰ.绝对定位居中(Absolute Centering)技术 我们经常用margin:0 auto来实现水平居中,而一直认为margin:auto不能实现垂直居中--实际上,实现垂直居中仅需要声明元素 ...

  3. 渐进式框架、自底向上增量开发的vue

    官网对vue.js的介绍是这样的: 一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计. 那么到底什么是渐进式框架.自底向上增量开发又是什么呢? 其实我觉得这 ...

  4. combobox实现模糊查询自动填充

    利用winform设计软件界面时,经常用到combobox控件,但有时需要绑定数据表中的数据,更进一步,需要实现对数据表中数据的模糊查询功能.本文就讲讲述如何用C#实现combobox下拉列表的模糊查 ...

  5. trap命令

    一. [root@OEL6-38 arun]# vim yy.sh --------------------- 参考: http://blog.csdn.net/holandstone/article ...

  6. 33个超级有用必须要收藏的PHP代码样例

    作为一个正常的程序员,会好几种语言是十分正常的,相信大部分程序员也都会编写几句PHP程序,如果是WEB程序员,PHP一定是必备的,即使你没用开发过大型软件项目,也一定多少了解它的语法. 在PHP的流行 ...

  7. KRPano资源分析工具使用说明(KRPano XML/JS解密 切片图批量下载 球面图还原 加密混淆JS还原美化)

    软件交流群:571171251(软件免费版本在群内提供) krpano技术交流群:551278936(软件免费版本在群内提供) 最新博客地址:blog.turenlong.com 限时下载地址:htt ...

  8. Solr4.0 如何配置使用UUID自动生成id值

    原文链接http://blog.csdn.net/keepthinking_/article/details/8501058#comments 最近学习了Lucene,随便也学习了Solr,Solr规 ...

  9. select初始化添加option,通过标签给出回显值,由于回显值和初始化值option中有一个值重复,去重等问题!

    第一张图片: 第二张图片 /** *该方法是为了去重,所谓去重就是 因为回显给select附上了值并设置为selected选中状态,而在我们初始化所有的select添加option元素中于回显的值重复 ...

  10. svn上传工程之后下载,打开下载之后的工程缺少文件

    当我们把iOS的工程上传到SVN中,当我们再从SVN中下载下来,就会出现错误,这是什么原因呢?我这里出现的错误是找不到文件,后来知道原来是被屏蔽掉了,就是上传的时候不上传某个类型的文件.例如我出错就是 ...