1.这个函数做了什么?
avformat_find_stream_info主要是读一些包(packets ),然后从中提取出流的信息。有一些文件格式没有头,这个时候,这个函数就很有用,因为它可以从读取到的包中获得到流的信息。在MPEG-2重复帧模式的情况下,该函数还计算真实的帧率。
该函数将读取媒体文件的音视频包去获取流信息。本函数常用于avformat_open_input()函数之后,在avformat_open_input()函数中会调用输入文件格式的read_header()函数,比如flv格式的flv_read_header()函数来读取文件头,由于flv格式的头很简单,只能知道是否存在音频流和视频流,获取不到流的编码信息,因此,对于flv格式来说,本函数就非常重要,本函数会读取flv文件中的音视频包,从这些包中获知流的编解码信息。对于没有文件头的MPEG格式来说存在同样的情况
2.代码
#include<iostream>
extern "C"
{
#include "libavformat/avformat.h" //头文件不仅要在项目中鼠标点击配置,在代码中也要引入
}
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
int main(int argc, char* argv[])
{
const char* path = "E:\\ffmpeg\\test.mp4";
cout << "TEST DEMUX" << endl;
//初始化封装库
//av_register_all()被弃用了
AVDictionary* opts = NULL;//参数设置,比如rtsp的延时时间
av_dict_set(&opts, "rtsp_transport", "tcp", 0);//设置rtsp流以tcp协议打开
av_dict_set(&opts, "max_delay", "500", 0);//网络延迟时间
//初始化网络库(可以打开rtsp,rtmp,http协议的流媒体视频)
avformat_network_init();
//解封装上下文
AVFormatContext* ic = NULL;//将其地址做为输入,会申请一块空间,将这块空间的地址赋给ic
//解封装上下文AVFormatContext,是存储音视频封装格式中包含信息的结构体。
int re = avformat_open_input(&ic, path, 0, &opts);//0表示自动选择解封装器,设置一个返回值知道有无错误
if (re != 0)
{
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);
cout << "open" << path << "failed!:" << buf << endl;
getchar();
return -1;
}
cout << "open " << path << " success!" << endl;
//获取流信息
re = avformat_find_stream_info(ic, 0);
//总时长
int total = ic->duration /(AV_TIME_BASE / 1000);//毫秒
cout << "total ms =" << total << endl;
//视频流详细信息
av_dump_format(ic,1,"2",0);
if (ic)
{
//释放封装上下文,并且把ic置0
avformat_close_input(&ic);
}
getchar();
return 0;
}
}
int re = avformat_open_input(&ic, path, 0, &opts);
re = avformat_find_stream_info(ic, 0);
虽然返回值都是re,但是re只是一个标志位,用于判断过后可以继续使用,没有再去开辟一个变量,节省了空间,我们想要的是将指针(ic)传进去,让ic指向开辟的空间,该空间放的是结构体AVformatcontext,里面有视频的相关信息。
有些格式,比如MP4,
在int re = avformat_open_input(&ic, path, 0, &opts);中就能获得全部的格式信息。
但也有些格式,比如flv,
格式信息不在头索引文件中,在下面视频流中存放视频格式信息
总时长有时候会存放两份,在AVformatcontext中会存放,在流信息AVstream中也会存放
总时长 duration:经历时长,不是以秒或者毫秒为单位,而是以AV_TIME_BASE为单位,duration /(AV_TIME_BASE / 1000),除出来的结果为秒
3.结果
av_dump_format(ic,1,“2”,0); 1 和"2"为显示出来的东西,无影响,最后的0表示input。
5.使用flv文件
未读取流信息:
int re = avformat_open_input(&ic, path, 0, &opts);
读取流信息:
int re = avformat_open_input(&ic, path, 0, &opts);
re = avformat_find_stream_info(ic, 0);
观察可以发现FLV文件中的duration和比特率参数在流信息中放着在。
补充:https://blog.csdn.net/h514434485/article/details/77802382