nb_streams: 有多少条流,比如视频流、音频流
streams: 流的相关信息
AVStream AVCodecParameters avformat_open_input 打开文件或者网络地址avformat_find_stream_info av_read_frame 读取一帧数 测试代码
121_test_demux.cpp
#includeusing namespace std; extern "C" // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C" { // 引用 ffmpeg 头文件 #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" } // 预处理指令导入库 #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #define CERR(err) if(err != 0) { PrintError(err); return -1; } static void PrintError(int err) { char buf[1024] = { 0 }; av_strerror(err, buf, sizeof(buf) - 1); cerr << buf << endl; } int main() { int ret = 0; AVFormatContext* ic = nullptr; // 解封装输入上下文 const char* url = "v1080.mp4"; AVPacket packet; AVStream* vs = nullptr; //视频流 AVStream* as = nullptr; //音频流 ret = avformat_open_input(&ic, url, nullptr, // 封装器格式 nullptr 自动探测 根据后缀名或者文件头 nullptr // 参数设置,rtsp需要设置 ); CERR(ret); // 获取媒体信息 无头部格式 ret = avformat_find_stream_info(ic, nullptr); CERR(ret); // 打印封装信息 av_dump_format(ic, 0, url, 0 // 0表示上下文是输入 1 输出 ); for (int i = 0; i < ic->nb_streams; i++) { if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { vs = ic->streams[i]; cout << "video: " << "width = " << vs->codecpar->width << " hwight = " << vs->codecpar->height << " bitrate = " << vs->codecpar->bit_rate << endl; } else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { as = ic->streams[i]; cout << "audio: " << "sample rate = " << as->codecpar->sample_rate << endl; } } while (1) { ret = av_read_frame(ic, &packet); // 此函数不会是否 packet 中原先的 buf 空间,需要手动调用 av_packet_unref 来释放 buf 空间 CERR(ret); if (vs && (packet.stream_index == vs->codecpar->codec_type)) { cout << "video "; } else if (as && (packet.stream_index == as->codecpar->codec_type)) { cout << "audio "; } cout << packet.pts << " : " << packet.dts << endl; av_packet_unref(&packet); } avformat_close_input(&ic); return 0; }
测试结果如下图所示:



