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_input
的 fmt_ctx
为 NULL
,该函数内部会调用 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 来打开文件。
重点理解 AVFormatContext
的 pb
字段指向一个 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