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是先把輸入的音視頻數據全部讀取到內存,而並不是需要使用的時候才去讀取。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM