更新记录(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的源代码,发现其竟然是可以从内存中读取数据的,代码很简单,如下所示:

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

将数据输出到内存

和从内存中读取数据类似,ffmpeg也可以将处理后的数据输出到内存。

回调函数如下示例,可以将输出到内存的数据写入到文件中。

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

ffmpeg 从内存中读取数据(或将数据输出到内存)的更多相关文章

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

    更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法. 从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件, ...

  2. ffmpeg 从内存中读取数据 .

    http://blog.csdn.net/leixiaohua1020/article/details/12980423 ——————————————————————————————————————— ...

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

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

  4. C# 操作地址 从内存中读取写入数据(初级)

    本示例以植物大战僵尸为例, 实现功能为 每1秒让阳光刷新为 9999.本示例使用的游戏版本为 [植物大战僵尸2010年度版], 使用的辅助查看内存地址的工具是  CE. 由于每次启动游戏, 游戏中阳光 ...

  5. 数据库的应用——直接从内存中读取osg节点 (转)

    数据库的应用——直接从内存中读取osg节点 目的:要从数据库中读取节点数据到osg. 一开始的方法是这样的,每当我要添加一个数据库中的节点数据时,首先把它读取到内存中,然后写入一个文件,最后再次从文件 ...

  6. 从文件中读取yuv和h264数据

    1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...

  7. arcgis python 使用光标和内存中的要素类将数据加载到要素集 学习:http://zhihu.esrichina.com.cn/article/634

    学习:http://zhihu.esrichina.com.cn/article/634使用光标和内存中的要素类将数据加载到要素集 import arcpy arcpy.env.overwriteOu ...

  8. php 如何在有限的内存中读取大文件

    突然遇到了一个要读取超过80M文件的需求,很悲剧的,不管是file_get_content还是file什么的,都会将读取的文件一次性加载到内存中. 正常情况下,我们可以使用fseek来读取,好处就是不 ...

  9. 面试题:java内存中的堆区和数据结构中的堆有什么区别

    java内存中的堆是一个  链表, 数据结构中的堆:就是一个栈

随机推荐

  1. 20160723数据结构节alexandrali

    大坑最后再填. 20160803:心情好回来填啦(5/7) 做的题目是: poj2970 我们先每个人都不给钱qwq 然后我们发现有一位的工作时间超过了d 那么我们就从以前安排过工作的人里,a最大的, ...

  2. texCUBE() to CubemapSampler.Sample()

    update dx9 to dx11 refers to   CUBEMAP sampler texCUBE(CubeMpaSampler,normal) maybe change to Cubema ...

  3. UDP TCP 消息边界

    先明确一个问题,如果定义了一个数据结构,大小是,比方说 32 个字节,然后 UDP 客户端连续向服务端发了两个包.现在假设这两个包都已经到达了服务器,那么服务端调用 recvfrom 来接收数据,并且 ...

  4. spoj 147

    dfs枚举真值 #include <cstdio> #include <cstring> #include <cstdlib> #include <stack ...

  5. 学习笔记--Grunt、安装、图文详解

    学习笔记--Git安装.图文详解 安装Git成功后,现在安装Gruntjs,官网:http://gruntjs.com/ 一.安装node 参考node.js 安装.图文详解 (最新的node会自动安 ...

  6. 分享一个安装PE到硬盘的软件

    Ton8pe_v5.0下载地址:http://pan.baidu.com/share/link?shareid=424350&uk=4180312589 电脑是XP,有光驱,但是没win8.1 ...

  7. 转:UGUI与NGUI的区别与优缺点

    1. NGUI与UGUI的区别 1) uGUI的Canvas 有世界坐标和屏幕坐标   2) uGUI的Image可以使用material     3) UGUI通过Mask来裁剪,而NGUI通过Pa ...

  8. Linux实时网络监控工具:iftop

    iftop是类似于top的实时流量监控工具,可以用来实时监控网卡的实时流量(可以指定网段).反向解析IP.显示端口信息等.夜间值班的童鞋如果发现有邮局流量异常时可以使用该软件查看详细流量状况. 下面介 ...

  9. React测试Mixin

    1.test.jsx var randomNumberMixin = require("./randomNumberMixin.jsx"); describe("test ...

  10. wxpython 中 用鼠标拖动控件 总结

    #encoding: utf-8 import wx import os import noname class Frame( noname.MyFrame1 ): def __init__(self ...