美文网首页音视频
ffmpeg_sample解读_avio_reading

ffmpeg_sample解读_avio_reading

作者: 刘佳阔 | 来源:发表于2020-10-21 11:27 被阅读0次

    title: ffmpeg_sample解读_avio_reading
    date: 2020-10-21 10:15:02
    tags: [读书笔记]
    typora-copy-images-to: ./imgs
    typora-root-url: ./imgs


    概括

    Ffmpeg 项目中的 实例解读. 把他移到安卓项目中来开发了.

    这个项目是读取 文件.解码出文件信息.

    使用方式 使用 ./avio_reading 1.mp4 读入文件

    输出如下

    ptr:0x10e1b9000 size:23014356
    ptr:0x10e1ba000 size:23010260
    ptr:0x10e1bb000 size:23006164
    ptr:0x10e1bce2a size:22998442
    ptr:0x10e1bde2a size:22994346
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1.mp4':
      Metadata:
        major_brand     : isom
        minor_version   : 1
        compatible_brands: isomavc1
        creation_time   : 2013-05-03T22:51:07.000000Z
      Duration: 00:00:46.61, start: 0.000000, bitrate: N/A
        Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 960x400 [SAR 1:1 DAR 12:5], 3859 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
        Metadata:
          creation_time   : 2013-05-03T22:50:47.000000Z
          handler_name    : GPAC ISO Video Handler
        Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo立体生, fltp, 92 kb/s (default)
        Metadata:
          creation_time   : 2013-05-03T22:51:07.000000Z
          handler_name    : GPAC ISO Audio Handler
    

    这个源码相对简单.就直接看注释就行了

    
    /**
     * @file
     * libavformat AVIOContext API example.
     *
     * Make libavformat demuxer access media content through a custom
     * AVIOContext read callback.
     * @example avio_reading.c
     */
    
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavformat/avio.h>
    #include <libavutil/file.h>
    #include "../macro.h"
    
    
    /**
     * 使用   ./avio_reading 1.mp4 读入文件 解码出文件信息
     * ptr:0x10e1b9000 size:23014356
    ptr:0x10e1ba000 size:23010260
    ptr:0x10e1bb000 size:23006164
    ptr:0x10e1bce2a size:22998442
    ptr:0x10e1bde2a size:22994346
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1.mp4':
      Metadata:
        major_brand     : isom
        minor_version   : 1
        compatible_brands: isomavc1
        creation_time   : 2013-05-03T22:51:07.000000Z
      Duration: 00:00:46.61, start: 0.000000, bitrate: N/A
        Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 960x400 [SAR 1:1 DAR 12:5], 3859 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
        Metadata:
          creation_time   : 2013-05-03T22:50:47.000000Z
          handler_name    : GPAC ISO Video Handler
        Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo立体生, fltp, 92 kb/s (default)
        Metadata:
          creation_time   : 2013-05-03T22:51:07.000000Z
          handler_name    : GPAC ISO Audio Handler
     */
    struct buffer_data {
        uint8_t *ptr;
        size_t size; ///< size left in the buffer
    };
    
    //把 opaque(也就是bd) 中的数据拷贝到 buf中,bd的数据就是读取的文件的数据
    //猜测这个buf 应该是 avioContext 内部的buf
    static int read_packet(void *opaque, uint8_t *buf, int buf_size) {
        struct buffer_data *bd = (struct buffer_data *) opaque;
        buf_size = FFMIN(buf_size, bd->size);
    
        if (!buf_size)
            return AVERROR_EOF;
        LOGE("ptr:%p size:%zu\n", bd->ptr, bd->size);
    
        /* copy internal buffer data to buf */
        //从bd 拷贝到buf中. 每次拷贝buf_size个
        memcpy(buf, bd->ptr, buf_size);
        bd->ptr += buf_size;
        bd->size -= buf_size;
    
        return buf_size;
    }
    
    int reading_main(int argc, char *argv[]) {
        AVFormatContext *fmt_ctx = NULL;
        AVIOContext *avio_ctx = NULL;
        uint8_t *buffer = NULL, *avio_ctx_buffer = NULL;
        //size_t可能会提高代码的可移植性、有效性或者可读 无符号整形
        size_t buffer_size, avio_ctx_buffer_size = 4096;
        char *input_filename = NULL;
        int ret = 0;
        struct buffer_data bd = {0};
    
    
        for (int i = 0; i < argc; ++i) {
            LOGE("paramets is %s",argv[i]);
        }
        if (argc != 2) {
            LOGE("usage: %s input_file\n API example program to show how to read from a custom buffer accessed through AVIOContext."
            ,argv[0]);
    
    
            return 1;
        }
        input_filename = argv[1];
    
        /* slurp file content into buffer */
        //读取文件.写入到buff中,buffer_size指明大小 --buf里没数据.只是分配了空间,建立buffer和文件的映射
        ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL);
        if (ret < 0)
            goto end;
    
        //把读取的数据封装到bd结构中, 此时buf 中还没数据.
        /* fill opaque structure used by the AVIOContext read callback */
        bd.ptr = buffer;
        bd.size = buffer_size;
    
        //初始化格式上下文
        if (!(fmt_ctx = avformat_alloc_context())) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
    
        //分配一个buffer,具有合适的对齐格式,4096字节大小.此时avio_ctx_buffer 也是空
        avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
        if (!avio_ctx_buffer) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
        //分配io读写上下文 回调是read_packet   0表示从buffer中读数据
        //相当于就是可以通过avio_ctx  从 bd 里读去数据,会回调read_packet方法
        avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,
                                      0, &bd, &read_packet, NULL, NULL);
        if (!avio_ctx) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
        fmt_ctx->pb = avio_ctx;
    
        //打开 输入流,读取数据.这里才是从bd中把数据写入到avio_ctx_buffer中.回调read_packet 函数
        ret = avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
        if (ret < 0) {
            LOGE(stderr, "Could not open input\n");
            goto end;
        }
    
        // 找到数据中的流信息,此时数据已经都写到 avoiContext中了,
        ret = avformat_find_stream_info(fmt_ctx, NULL);
        if (ret < 0) {
            LOGE(stderr, "Could not find stream information\n");
            goto end;
        }
    
        //打印数据文件信息
        av_dump_format(fmt_ctx, 0, input_filename, 0);
    
        end:
        //关闭上下文
        avformat_close_input(&fmt_ctx);
    
        /* note: the internal buffer could have changed, and be != avio_ctx_buffer */
        if (avio_ctx)//是否内部buffer及io上下问
            av_freep(&avio_ctx->buffer);
        avio_context_free(&avio_ctx);
    
        av_file_unmap(buffer, buffer_size);
    
        if (ret < 0) {
            LOGE(stderr, "Error occurred: %s\n", av_err2str(ret));
            return 1;
        }
    
        return 0;
    }
    
    

    相关文章

      网友评论

        本文标题:ffmpeg_sample解读_avio_reading

        本文链接:https://www.haomeiwen.com/subject/xvvsmktx.html