FFmpeg demo 分析之avio_reading.c

FFmpeg demo 分析之avio_reading.c


int main(int argc, char *argv[])
{
    /* AVFormatContext是用于描述了一个媒体文件或媒体流的构成和基本信息的结构体,
     * 主要用于封装和解封装。
     */
    AVFormatContext *fmt_ctx = NULL;

    /*
     * AVIOContext是用于管理输入输出数据的结构体
     */
    AVIOContext *avio_ctx = NULL;

    uint8_t *buffer = NULL, *avio_ctx_buffer = NULL;
    size_t buffer_size, avio_ctx_buffer_size = 4096;
    char *input_filename = NULL;
    int ret = 0;
    struct buffer_data bd = { 0 };

    if (argc != 2) {
        fprintf(stderr, "usage: %s input_file\n"
                "API example program to show how to read from a custom buffer "
                "accessed through AVIOContext.\n", argv[0]);
        return 1;
    }
    input_filename = argv[1];

    /* 将整个输入文件读进buffer中(包含申请buffer的动作) */
    ret = av_file_map(input_filename, &buffer, &buffer_size, 0, NULL);
    if (ret < 0)
        goto end;

    bd.ptr  = buffer;
    bd.size = buffer_size;

    /* avformat_alloc_context申请一个AVFormatContext */
    if (!(fmt_ctx = avformat_alloc_context())) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    /* av_malloc申请一块buffer */
    avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
    if (!avio_ctx_buffer) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    /* avio_alloc_context申请一个AVIOContext
     * 在本例中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;

    /* avformat_open_input打开输入流并读取头信息 */
    ret = avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open input\n");
        goto end;
    }

    /* avformat_find_stream_info获取流信息 */
    ret = avformat_find_stream_info(fmt_ctx, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not find stream information\n");
        goto end;
    }

    /* av_dump_format打印详细的格式信息 */
    av_dump_format(fmt_ctx, 0, input_filename, 0);

end:
    /* avformat_close_input关闭输入流 */
    avformat_close_input(&fmt_ctx);

    /* av_freep释放申请的buffer,因为此时avio_ctx->buffer即为avio_ctx_buffer */
    if (avio_ctx)
        av_freep(&avio_ctx->buffer);

    /* avio_context_free释放AVIOContext */
    avio_context_free(&avio_ctx);

    /* av_file_unmap,unmap和释放加载文件的buffer */
    av_file_unmap(buffer, buffer_size);

    if (ret < 0) {
        fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
        return 1;
    }

    return 0;
}

参考资料

1.FFmpeg结构体:AVFormatContext
2.FFmpeg结构体:AVIOContext
3.FFmpeg API查询

你可能感兴趣的:(FFmpeg demo 分析之avio_reading.c)