AVFormatContext协议层:理论与实战(二)

简介: AVFormatContext协议层:理论与实战(二)

AVFormatContext协议层:理论与实战(一)https://developer.aliyun.com/article/1473889

这里有 avformat_alloc_context 操作,但是没有 avformat_free_context()操作,既然官方用例都这么做,那我也索性按照官方测试用例的方法来。

我看到网上相关的资料要求必须要有这个 free 操作,但这里一旦加了 free 操作就会出现这样的错误,这个问题暂时放在这儿吧,也希望有懂得兄弟可以解释一下。

屏蔽 avformat_free_context()

再次运行,可以看到如下输出结果:

hello,ffmpeg
hello,avformat_alloc_context
hello,avformat_open_input
open stream success!
av_find_stream_info success 
******nb_streams=2

可以看到输出信息为找到了两路流,分别是视频流与音频流,用 MediaInfo 查看 test.mp4 可以看到一致的效果

②、解决方法 2

使用时可以通过 avformat_alloc_context 分配后使用,也可以直接 avformat_open_input

>//1、方法一
AVFormatContext *fmt_ctx = NULL;
string filename = "test.avi" ;
fmt_ctx = avformat_alloc_context();
avformat_open_input(&fmt_ctx, ilename.c_str(), NULL, NULL);
avformat_close_input(&fmt_ctx);
>//2、方法二
AVFormatContext *fmt_ctx = NULL;
string filename = "test.avi" ;
int ret = avformat_open_input(&fmt_ctx, filename.c_str(), NULL, NULL);
avformat_close_input(&fmt_ctx);

推荐使用方法二,因为若传进 avformat_open_inputfmt_ctxNULL,该函数内部会调用 avformat_alloc_context 函数。相应的 avformat_close_input 内部会调用 avformat_free_context

修改后的源码:

extern "C"
{
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavformat/avio.h>
    #include <libavutil/file.h>
};
int main(int argc, char* argv[])
{
    /av_register_all();
    avformat_network_init();
    printf("hello,ffmpeg\n");
    AVFormatContext* pFormatCtx = NULL;
    printf("hello,avformat_open_input\n");
    //打开本地文件或网络直播流
    //rtsp://127.0.0.1:8554/rtsp1
    //./debug/test.mp4
    if (avformat_open_input(&pFormatCtx, "./debug/test.mp4", NULL, NULL) < 0) {
        printf("avformat open failed.\n");
        goto quit;
    }
    else {
        printf("open stream success!\n");
    }
    if (avformat_find_stream_info(pFormatCtx, NULL)<0)
    {
        printf("av_find_stream_info error \n");
        goto quit;
    }
    else {
        printf("av_find_stream_info success \n");
        printf("******nb_streams=%d\n",pFormatCtx->nb_streams);
    }
quit:
    avformat_close_input(&pFormatCtx);
    avformat_network_deinit();
    return 0;

运行结果:

hello,ffmpeg
hello,avformat_open_input
open stream success!
av_find_stream_info success 
******nb_streams=2

四、avio 实战 2:自定义 AVIO

本次实战的目的与实战 1 的目的一致,均是分析输入文件的流数量,只不过本次实战重点突出使用我们自定义的 AVIO 来打开文件。

重点理解 AVFormatContextpb 字段指向一个 AVIOContext,如何完成的关联和绑定

1、示例源码

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
int read_func(void* ptr, uint8_t* buf, int buf_size)
{
    FILE* fp = (FILE*)ptr;
    size_t size = fread(buf, 1, buf_size, fp);
    int ret = size;
    printf("Read Bytes:%d\n", size);
    return ret;
}
int64_t seek_func(void *opaque, int64_t offset, int whence)
{
    int64_t ret;
    FILE *fp = (FILE*)opaque;
    if (whence == AVSEEK_SIZE) {
        return -1;
    }
    fseek(fp, offset, whence);
    return ftell(fp);
}
int main(int argc, char *argv[]){
    ///av_register_all();
    printf("hello,ffmpeg\n");
    int ret = 0;
    FILE* fp = fopen("./debug/test.mp4", "rb");
    int nBufferSize = 1024;
    unsigned char* pBuffer = (unsigned char*)malloc(nBufferSize);
    AVFormatContext* pFormatCtx = NULL;
    AVInputFormat *piFmt = NULL;
    printf("hello,avio_alloc_context\n");
    // Allocate the AVIOContext:
    AVIOContext* pIOCtx = avio_alloc_context(
        pBuffer,
        nBufferSize,
        0,
        fp,
        read_func,
        0,
        seek_func);
    printf("hello,avformat_alloc_context\n");
    // Allocate the AVFormatContext:
    pFormatCtx = avformat_alloc_context();
    // Set the IOContext:
    pFormatCtx->pb = pIOCtx;//关联,绑定
    pFormatCtx->flags = AVFMT_FLAG_CUSTOM_IO;
    printf("hello,avformat_open_input\n");
    //打开流
    if (avformat_open_input(&pFormatCtx, "", piFmt, NULL) < 0) {
        printf("avformat open failed.\n");
        goto quit;
    }
    else {
        printf("open stream success!\n");
    }
    if (avformat_find_stream_info(pFormatCtx, NULL)<0)
    {
        printf("av_find_stream_info error \n");
        goto quit;
    }
    else {
        printf("av_find_stream_info success \n");
        printf("******nb_streams=%d\n",pFormatCtx->nb_streams);
    }
quit:
    //avformat_free_context(pFormatCtx);
    avformat_close_input(&pFormatCtx);
    free(pBuffer);
    return 0;
}
  • avio_alloc_context():用于分配和初始化 AVIOContext 结构体。AVIOContext 结构体表示用于读取或写入数据的 I/O 上下文,它提供了一个抽象的层次,用于访问各种类型的数据。

2、运行结果

10:38:51: Starting D:\Project\Qt_Project\1-2_fmpeg431s5qtcodes\build-HelloFFmpeg-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\debug\HelloFFmpeg.exe ...
hello,ffmpeg
hello,avio_alloc_context
hello,avformat_alloc_context
hello,avformat_open_input
Read Bytes:2048
Read Bytes:1024
Read Bytes:11457
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:21496
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:1024
Read Bytes:580
open stream success!
Read Bytes:1024
Read Bytes:105165
av_find_stream_info success 
******nb_streams=2

AVFormatContext协议层:理论与实战(三)https://developer.aliyun.com/article/1473891

目录
相关文章
|
存储 缓存 编解码
AVFormatContext封装层:理论与实战(一)
AVFormatContext封装层:理论与实战(一)
200 1
|
JavaScript IDE Java
初学鸿蒙OS之分析一下鸿蒙项目的组成结构
初学鸿蒙OS之分析一下鸿蒙项目的组成结构
315 0
|
机器学习/深度学习 人工智能 自然语言处理
从此告别PPT制作的烦恼:ChatGPT和MindShow帮你快速完成
从此告别PPT制作的烦恼:ChatGPT和MindShow帮你快速完成
|
大数据 测试技术 API
AVFormatContext协议层:理论与实战(一)
AVFormatContext协议层:理论与实战(一)
155 0
|
Python
Python中遇到奇怪的错误ValueError: bad marshal data
不是代码出的问题,是*.pyc文件被改动了。解决方法,删除所有*.pyc文件再运行
4841 0
|
6月前
|
人工智能 搜索推荐
基于 PAI-ArtLab 使用 ComfyUI 生成人像写真
本实验基于SDXL、InstantID技术,解决AI人像摄影中人物面部特征在风格迁移与图像放大后无法高度还原的问题。内置6种儿童风格提示词模板及提示词翻译模块,支持中文书写相关图像提示词测试个性化风格。需登录阿里云PAI ArtLab平台操作,领取免费试用资源后,通过ComfyUI(专享版)拉起服务并加载工作流,上传图片、选择草图、更换连线等步骤生成不同风格成果。还提供自定义风格模块和常见问题解答,方便用户解锁更多玩法。
|
安全 网络协议 Ubuntu
【常见开源库的二次开发】HTTP之libcurl库——libcurl使用(二)
【常见开源库的二次开发】HTTP之libcurl库——libcurl使用(二)
2580 2
|
11月前
|
API
FFmpeg中AVPacket、AVFrame结构的基本使用
FFmpeg中AVPacket和AVFrame结构的内存分配、释放和引用计数处理,以及如何避免内存泄漏。
299 3
|
11月前
|
机器学习/深度学习 存储 自然语言处理
基础与构建:GraphRAG架构解析及其在知识图谱中的应用
【10月更文挑战第11天】随着数据的不断增长和复杂化,传统的信息检索和生成方法面临着越来越多的挑战。特别是在处理结构化和半结构化数据时,如何高效地提取、理解和生成内容变得尤为重要。近年来,一种名为Graph Retrieval-Augmented Generation (GraphRAG) 的新架构被提出,它结合了图神经网络(GNNs)和预训练语言模型,以提高多模态数据的理解和生成能力。本文将深入探讨GraphRAG的基础原理、架构设计,并通过实际代码示例展示其在知识图谱中的应用。
1125 0
|
Android开发 计算机视觉 C++
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架
音视频编程对许多程序员来说是一片充满挑战的领域,但借助如OpenCV、LearnOpenGL、FFmpeg、OBS Studio及VLC media player等强大的开源工具,可以降低入门门槛。这些框架不仅覆盖了计算机视觉、图形渲染,还包括多媒体处理与直播技术,通过多种编程语言如Python、C++的应用,使得音视频开发更为便捷。例如,OpenCV支持跨平台的视觉应用开发,FFmpeg则擅长多媒体文件的处理与转换,而VLC media player则是验证音视频文件质量的有效工具。
327 0
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架