zoukankan      html  css  js  c++  java
  • 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 ", 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 "  
    70.                 "API example program to show how to read from a custom buffer "  
    71.                 "accessed through AVIOContext. ", 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 ");  
    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 ");  
    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 ",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 ", av_err2str(ret));  
    154.         return 1;  
    155.     }  
    156.   
    157.     return 0;  
    158. }  

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

  • 相关阅读:
    怎样从外网访问内网Django?
    怎样从外网访问内网Jboss?
    怎样从外网访问内网php-fpm?
    python中关于发邮件的示例
    python中关于局部变量与全局变量的认识
    python实现二分查找与冒泡排序
    自动化测试框架中关于selenium api的二次封装
    python 的日志相关应用
    python中关于字符串的操作
    EBS 物料单位换算
  • 原文地址:https://www.cnblogs.com/lidabo/p/7346345.html
Copyright © 2011-2022 走看看