FFmpeg学习之解封装

根据上篇的方法配置继续学习解封装

#include <iostream>
#include <thread>

using namespace std;

//测试解封装
extern "C"{
#include "libavformat/avformat.h"
}

//引用库
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")

//static修饰的分数转浮点函数,避免功能性函数重定义
static double r2d(AVRational r)
{
	return (r.den == 0) ? 0 : (double)r.num/(double)r.den;
}

void XSleep(int ms)
{
	// c++11
	chrono::milliseconds du(ms);
	this_thread::sleep_for(du);
}

int main(int argc, char* argv[])
{
	cout << "Test Demux FFmpeg.club" << endl;

	//初始化封装库
	av_register_all();

	//初始化网络库 可以打开rtsp rtmp http 协议的流媒体视频)
	avformat_network_init();

	//参数设置
	AVFormatContext *ic = NULL;
	const char* path = "abc.mp4";

	AVDictionary *opts = NULL;//NULL表示使用默认配置
	//设置rtsp流,以tcp协议打开
	//av_dict_set(&opts, "rtsp_transport", "tcp", 0);

	//设置网络延时时间
	//av_dict_set(&opts, "max_delay", "500", 0);

	//解封装上下文
	int ret = avformat_open_input(
		&ic,
		path,		//视频源
		0,			//0表示自动选择解封装器
		&opts		//参数设置,比如rtsp的延时时间
		);

	if (ret != 0)
	{
		char buff[1024] = { 0 };
		av_strerror(ret, buff, sizeof(buff) - 1);
		cout << "open " << path << " failed ! :" << buff << endl;
		getchar();
		return -1;
	}
	cout << "open " << path << " succeed !" << endl;

	//获取流信息
	ret = avformat_find_stream_info(ic, 0);

	//总时长
	int totalTime = ic->duration/AV_TIME_BASE;
	cout << path << " total time is " << totalTime << " s." << endl;

	//打印视频流详细信息
	av_dump_format(ic, 0, path, 0);

	//音视频索引,用于读取时区分音视频数据
	int audioStream = 0;
	int videoStream = 1;

	//获取音视频流信息 (通过遍历,或函数获取)
	//遍历方式
	for (int i = 0; i < ic->nb_streams; i++)
	{
		AVStream *as = ic->streams[i];
		cout << "format = " << as->codecpar->format << endl;
		cout << "codec_id = " << as->codecpar->codec_id << endl;
		//音频
		if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			audioStream = i;
			cout << i << "音频信息" << endl;
			cout << "sample_rate = " <<as->codecpar->sample_rate << endl;
			//AVSampleFormat
			cout << "channels = " << as->codecpar->channels << endl;
			//一帧数据:单通道样本数
			cout << "frame size = " << as->codecpar->frame_size << endl;
		}
		//视频
		if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			videoStream = i;
			cout << i << "视频信息" << endl;
			//这里边可能没有宽高参数
			cout << "width = " << as->codecpar->width << endl;
			cout << "height = " << as->codecpar->height << endl;
			//帧率 fps 
			cout << "video FPS = " << r2d(as->avg_frame_rate) << endl;
		}
	}
	//函数方式获取
	audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);

	//AVPacket 申请空间、初始化
	AVPacket *pkt = av_packet_alloc();
	while (1)
	{
		int ret = av_read_frame(ic, pkt);
		if (ret)
		{
			//读到结尾
			cout << "==============end==============" << endl;
   			break;//退出

			//跳转到3秒位置
			int ms = 3000;//3秒,根据时间基数转换
			int64_t pos = (double)ms / (double)1000 * r2d(ic->streams[pkt->stream_index]->time_base);
			av_seek_frame(ic, 0, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
			cout << " \\ \\ \\ \\ \\ \\ \\ \\ at 3 ms" << endl;
            //continue;//循环
		}
		cout << "pkt->size = " << pkt->size << endl;
		//显示的时间
		cout << "pkt->pts = " << pkt->pts << endl;
		cout << "pkt->pts ms = " << pkt->pts * (r2d(ic->streams[pkt->stream_index]->time_base) * 1000) << endl;

		//XSleep(500);//避免刷屏太快

		//解码的时间
		cout << "pkt->dts = " << pkt->dts << endl;
		if (pkt->stream_index == videoStream)
		{
			cout << "图像" << endl;
		}
		if (pkt->stream_index == audioStream)
		{
			cout << "音频" << endl;
		}
		//释放库内部单次使用的内存,并将引用计数-1
		av_packet_unref(pkt);
	}
	//释放空间
	av_packet_free(&pkt);

	if (ic)
	{
		//释放封装上下文,并把ic并置0
		avformat_close_input(&ic);
	}

	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值