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

目录
相关文章
|
1月前
|
存储 缓存 编解码
AVFormatContext封装层:理论与实战(一)
AVFormatContext封装层:理论与实战(一)
33 1
|
1月前
|
编解码 算法 容器
AVFormatContext封装层:理论与实战(二)
AVFormatContext封装层:理论与实战(二)
30 0
|
8月前
|
XML 存储 JSON
【面试题精讲】序列化协议对应于 TCP/IP 4 层模型的哪一层?
【面试题精讲】序列化协议对应于 TCP/IP 4 层模型的哪一层?
|
1月前
|
大数据 测试技术 API
AVFormatContext协议层:理论与实战(一)
AVFormatContext协议层:理论与实战(一)
20 0
|
1月前
|
编解码 缓存 大数据
AVFormatContext编解码层:理论与实战(一)
AVFormatContext编解码层:理论与实战(一)
42 0
|
1月前
|
编解码
AVFormatContext编解码层:理论与实战(二)
AVFormatContext编解码层:理论与实战(二)
30 0
|
1月前
|
编解码 内存技术
AVFormatContext编解码层:理论与实战(三)
AVFormatContext编解码层:理论与实战(三)
24 0
|
22天前
|
缓存
计算机网络——数据链路层-可靠传输的实现机制:选择重传协议SR(介绍、工作原理、窗口尺寸、题目练习)
计算机网络——数据链路层-可靠传输的实现机制:选择重传协议SR(介绍、工作原理、窗口尺寸、题目练习)
21 0
|
1月前
|
编解码 内存技术
AVFormatContext封装层:理论与实战(三)
AVFormatContext封装层:理论与实战(三)
15 1
AVFormatContext封装层:理论与实战(三)
|
1月前
|
测试技术
AVFormatContext协议层:理论与实战(三)
AVFormatContext协议层:理论与实战(三)
21 4