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

相关博客列表 :

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

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

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

   在FFMPEG的官方例程中,有个avio_reading.c 的文件,他的主要功能是将音视频文件读取到内存,如果FFMPEG需要使用输入文件的数据,则直接从内存中调用。初学FFMPEG,给avio_reading.c 文件做了一个注释,如果不对,欢迎指正。

 

[objc] view plain copy

 
 print?

  1. /* 
  2.  * Copyright (c) 2014 Stefano Sabatini 
  3.  * 
  4.  * Permission is hereby granted, free of charge, to any person obtaining a copy 
  5.  * of this software and associated documentation files (the "Software"), to deal 
  6.  * in the Software without restriction, including without limitation the rights 
  7.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  8.  * copies of the Software, and to permit persons to whom the Software is 
  9.  * furnished to do so, subject to the following conditions: 
  10.  * 
  11.  * The above copyright notice and this permission notice shall be included in 
  12.  * all copies or substantial portions of the Software. 
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  15.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
  17.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  18.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
  19.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
  20.  * THE SOFTWARE. 
  21.  */  
  22.   
  23. /** 
  24.  * @file 
  25.  * libavformat AVIOContext API example. 
  26.  * 
  27.  * Make libavformat demuxer access media content through a custom 
  28.  * AVIOContext read callback. 
  29.  * @example avio_reading.c 
  30.  */  
  31.   
  32. #include <libavcodec/avcodec.h>  
  33. #include <libavformat/avformat.h>  
  34. #include <libavformat/avio.h>  
  35. #include <libavutil/file.h>  
  36.   
  37. struct buffer_data {  
  38.     uint8_t *ptr; /* 文件中对应位置指针 */  
  39.     size_t size; ///< size left in the buffer /* 文件当前指针到末尾 */   
  40. };  
  41.   
  42. /* 将文件中数据拷贝到缓冲区,同时文件指针位置偏移,数据大小改变 */  
  43. static int read_packet(voidvoid *opaque, uint8_t *buf, int buf_size)  
  44. {  
  45.     struct buffer_data *bd = (struct buffer_data *)opaque;  
  46.     buf_size = FFMIN(buf_size, bd->size);  
  47.   
  48.     printf("ptr:%p size:%zu\n", bd->ptr, bd->size);  
  49.   
  50.     /* copy internal buffer data to buf */  
  51.     memcpy(buf, bd->ptr, buf_size);  
  52.     bd->ptr  += buf_size;  
  53.     bd->size -= buf_size;  
  54.   
  55.     return buf_size;  
  56. }  
  57.   
  58. int main(int argc, charchar *argv[])  
  59. {  
  60.     AVFormatContext *fmt_ctx = NULL;  
  61.     AVIOContext *avio_ctx = NULL;  
  62.     uint8_t *buffer = NULL, *avio_ctx_buffer = NULL;  
  63.     size_t buffer_size, avio_ctx_buffer_size = 4096;  
  64.     charchar *input_filename = NULL;  
  65.     int ret = 0;  
  66.     struct buffer_data bd = { 0 };  
  67.   
  68.     if (argc != 2) {  
  69.         fprintf(stderr, "usage: %s input_file\n"  
  70.                 "API example program to show how to read from a custom buffer "  
  71.                 "accessed through AVIOContext.\n", argv[0]);  
  72.         return 1;  
  73.     }  
  74.     input_filename = argv[1];  
  75.   
  76.     /* register codecs and formats and other lavf/lavc components*/  
  77.     av_register_all();  
  78.   
  79.     /* slurp file content into buffer */  
  80.     /* input_filename : 输入文件的文件名 
  81.      * buffer : 文件开始地址 
  82.      * buffer_size : 文件大小 
  83.      * 类似于UNIX下的mmap函数所实现的功能,返回文件开始指针,文件大小 
  84.      * 经测试,并不耗内存,可视为UNIX下的文件映射 
  85.     */  
  86.     ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL);  
  87.     if (ret < 0)  
  88.         goto end;  
  89.   
  90.     /* fill opaque structure used by the AVIOContext read callback */  
  91.     /* bd 是指经过文件映射之后的文件,并不是指需要缓存区 */  
  92.     bd.ptr  = buffer;  
  93.     bd.size = buffer_size;  
  94.   
  95.     /* 初始化文件格式的结构体,就是分配内存 */  
  96.     if (!(fmt_ctx = avformat_alloc_context())) {  
  97.         ret = AVERROR(ENOMEM);  
  98.         goto end;  
  99.     }  
  100.   
  101.     /* 分配内存, 可以自己设置缓冲大小,这里设置的是4K */  
  102.     avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);  
  103.     if (!avio_ctx_buffer) {  
  104.         ret = AVERROR(ENOMEM);  
  105.         goto end;  
  106.     }  
  107.   
  108.     /* avio_ctx_buffer是缓冲区, 
  109.      * avio_ctx_buffer 的初始地址赋值到 avio_ctx->buffer 
  110.      * avio_ctx_buffer_size是缓冲区大小 , 也是每次读取数据的大小 
  111.      * bd 是输入文件文件的映射文件 
  112.      * read_packet 回调函数,读取数据的功能 , 具体在什么情况下才会回调 ? 
  113.      */  
  114.     avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,  
  115.                                   0, &bd, &read_packet, NULL, NULL);  
  116.     if (!avio_ctx) {  
  117.         ret = AVERROR(ENOMEM);  
  118.         goto end;  
  119.     }  
  120.     fmt_ctx->pb = avio_ctx;  
  121.     /* 配置初始化信息 
  122.     * read_packet 回调函数会在这里被调用, 它将输入文件的所有数据都先存入缓存中, 
  123.     * 如果后面有需要用到数据,那么它就从缓存中直接调用数据 
  124.     */  
  125.     ret = avformat_open_input(&fmt_ctx, NULL, NULL, NULL);  
  126.     if (ret < 0) {  
  127.         fprintf(stderr, "Could not open input\n");  
  128.         goto end;  
  129.     }  
  130.   
  131.     ret = avformat_find_stream_info(fmt_ctx, NULL);  
  132.     if (ret < 0) {  
  133.         fprintf(stderr, "Could not find stream information\n");  
  134.         goto end;  
  135.     }  
  136.       
  137.     /* 输出基本信息 */  
  138.     av_dump_format(fmt_ctx, 0, input_filename, 0);  
  139.   
  140. end:  
  141.     avformat_close_input(&fmt_ctx);  
  142.     /* note: the internal buffer could have changed, and be != avio_ctx_buffer */  
  143.     //应该就是av_free(&avio_ctx_buffer),但位置不对  
  144.     //两者有差异  
  145.     //printf("%p %p\n",avio_ctx_buffer,avio_ctx->buffer);  
  146.     if (avio_ctx) {  
  147.         av_freep(&avio_ctx->buffer);  
  148.         av_freep(&avio_ctx);  
  149.     }  
  150.     av_file_unmap(buffer, buffer_size);  
  151.   
  152.     if (ret < 0) {  
  153.         fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));  
  154.         return 1;  
  155.     }  
  156.   
  157.     return 0;  
  158. }  

    这里定义了一个avio_ctx_buffer_size 变量表示每次从文件中读取到少数据到内存。在该例子中,FFMPEG是先把输入的音视频数据全部读取到内存,而并不是需要使用的时候才去读取。

时间: 2024-11-02 02:18:37

FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析的相关文章

从XML中读取数据到内存的实例

xml|数据 public clsSimuResultByOneGoods GetOneGoodsSimulationXML(string PathAndFileName)        {            clsSimuResultByOneGoods OneGoods = new clsSimuResultByOneGoods();//自己定义的一个类            Hashtable AllLocationResult = new Hashtable();          

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

相关博客列表:     FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析      FFMPEG内存操作(二)从内存中读取数及数据格式的转换      FFmpeg内存操作(三)内存转码器     在雷神的<最简单的基于FFmpeg的内存读写例子(内存播放器)>中,它是设计回调函数从输入文件中读取数据.与FFMPEG 官方给出的avio_reading.c不同的是,雷神给的例子是当需要数据的时候,回调函数才去从输入文件读取数据,而avio_reading.c 则

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

更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法.   从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件,例如"C:\test.avi" 或者是一个流媒体协议的URL,例如"rtmp://222.31.64.208/vod/test.flv" 其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了. 但其

FFMPEG基于内存的转码实例——输入输出视频均在内存

我在6月份写了篇文章<FFMPEG基于内存的转码实例>,讲如何把视频转码后放到内存,然后通过网络发送出去.但该文章只完成了一半,即输入的数据依然是从磁盘文件中读取.在实际应用中,有很多数据是放到内存的,比如播放从服务器接收到的视频,就是在内存中的.时隔2个月,项目终于完成了,虽然在收尾阶段会花费大量时间,但也算空闲了点.于是就继续完善. 本文中,假定的使用场合是,有一个已经放到内存的视频,需要将它转码成另一种封装格式,还是放到内存中.由于是测试,首先将视频从文件中读取到内存,最后会将转换好的视

malloc-C程序内存不能为read错误,包含文件和内存操作

问题描述 C程序内存不能为read错误,包含文件和内存操作 各个方法每个都没问题,放一块儿就冒出个不明原因的错误 #include <stdio.h>#include <math.h>#include <time.h>//get time difference//days from 2015/6/9 to here.int getTD();//free()!char* getTextFileContent(char*);long getFileSize(FILE*);/

Java基础-22总结登录注册IO版,数据操作流,内存操作流,打印流,标准输入输出流,转换流,随机访问流,合并流,序列化流,Properties

你需要的是什么,直接评论留言. 获取更多资源加微信公众号"Java帮帮" (是公众号,不是微信好友哦) 还有"Java帮帮"今日头条号,技术文章与新闻,每日更新,欢迎阅读 学习交流请加Java帮帮交流QQ群553841695 分享是一种美德,分享更快乐! 1:登录注册IO版本案例(掌握) 要求,对着写一遍. cn.itcast.pojo User cn.itcast.dao UserDao cn.itcast.dao.impl UserDaoImpl(实现我不管)

C语言嵌入式系统编程修炼(内存操作)

在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力.在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力.以指针直接操作内存多发生在如下几种情况: (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址: (2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断: (3) 读

C#调用C++出现尝试读取写入保护的内存错误

问题描述 代码如下,问题如题:在运行到最后一句的时候出现了尝试读取写入保护的内存错误,该句调用的是外部API,不知道怎么解决,改程序功能是大华网络摄像头的. 解决方案 解决方案二:这一般是由于参数类型不匹配造成的NET_TIME是啥类型,DLL里认识这个类型?解决方案三:你应该先看DLL里的函数到底是啥类型的参数不管是啥类型,你也不该把C#里定义的类当做类型传进去,它能认识才怪除非这个DLL本身就是C#编写的,那它顶多认识.net类库里的类型,你自定义类型它保证不认识解决方案四:引用2楼Z654

JavaScript操作XML文件之XML读取方法

 本文实例讲述了JavaScript操作XML文件之XML读取方法.分享给大家供大家参考.具体分析如下: 假设我们现在要读取下面的 info.xml 文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="gb2312"?> <root> <data id="1"> <name