ffmpeg解封装代码示例

视频封装概述

ffmpeg解封装代码示例_第1张图片

MP4 格式分析

ffmpeg解封装代码示例_第2张图片

ffmpeg解封装代码示例_第3张图片

解封装流程

ffmpeg解封装代码示例_第4张图片

AVFormatContext 

ffmpeg解封装代码示例_第5张图片

nb_streams: 有多少条流,比如视频流、音频流

streams: 流的相关信息

 AVStream

ffmpeg解封装代码示例_第6张图片

AVCodecParameters 

ffmpeg解封装代码示例_第7张图片

avformat_open_input 打开文件或者网络地址 

ffmpeg解封装代码示例_第8张图片

ffmpeg解封装代码示例_第9张图片

 

avformat_find_stream_info 

av_read_frame 读取一帧数 

ffmpeg解封装代码示例_第10张图片

测试代码

121_test_demux.cpp

 

#include 

using 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;
}

测试结果如下图所示:

ffmpeg解封装代码示例_第11张图片 

你可能感兴趣的:(音视频,音视频)