• FFmpeg解复用器(解封装)简单测试【2】


    解复用器(解封装)的相关函数

    avformat_alloc_context();负责申请一个AVFormatContext结构的内存,并进行简单初始化
    avformat_free_context();释放该结构里的所有东西以及该结构本身
    avformat_close_input();关闭解复用器。关闭后就不再需要使用avformat_free_context 进行释放。
    avformat_open_input();打开输入视频文件
    avformat_find_stream_info();获取视频文件信息
    av_read_frame(); 读取音视频
    avformat_seek_file(); 定位文件
    av_seek_frame():定位帧

    流程

    在这里插入图片描述

    测试

    #include 
    #include 
    using namespace std;
    
    extern "C"
    {
    #include "libavformat/avformat.h"
    #include "libavcodec/avcodec.h"
    }
    #pragma comment(lib,"avformat.lib")
    #pragma comment(lib,"avutil.lib")
    #pragma comment(lib,"avcodec.lib")
    
    
    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);//延迟ms
    	this_thread::sleep_for(du);
    }
    
    int main(int argc, char* argv[])
    {
    //解封装
    cout << " test Demux FFmpeg club" << endl;
    
    	const char* path = "1.mp4";
    
    	//1、初始化封装库
    	av_register_all();
    
    	//初始化网络库(可以打开rtsp rtmp http 协议的流媒体视频)
    	//avformat_network_init();
    
    	//参数设置
    	AVDictionary* opts = NULL;
    
    	//设置rtsp流已tcp协议打开
    	//av_dict_set(&opts, "rtsp_transport", "tcp", 0);
    	//设置网络延迟时间
    	//av_dict_set(&opts, "max_delay", "500", 0);
    
    	//解封装上下文
    	AVFormatContext* ic = NULL;
    
    	int re = avformat_open_input(
    				&ic, //上下文结构体:保存音视频的构成和基本信息
    				path, //音视频文件路径
    				0, //自动选择解封器
    				&opts//参数设置,比如rtsp的延迟设置
    				);
    	if (re != 0)//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;
    
    
    	//获取音视频流信息,包含了视频和音频 
    	//mp4在这里flv有所不同
    	re = avformat_find_stream_info(ic, 0);
    
    	//AV_TIME_BASE是时间的计数百万, ic->duration / AV_TIME_BASE是秒。
    	//打印总时长 ms
    	int total_time = ic->duration / (AV_TIME_BASE/1000);
    	cout << "total time : " << total_time << " ms" << endl;
    
    	//打印视频流的详细信息
    	av_dump_format(ic,0,path,0);
    
    	//音视频索引
    	int videoStream = 0;
    	int audioStream = 1;
    
    	//获取音视频流信息(遍历,函数获取),ic->nb_streams是媒体流的数量
    	for (int i = 0; i < ic->nb_streams; i++)
    	{
    		AVStream* as = ic->streams[i];
    		//as->codecpar->codec_type 中保存流的类别
    		//音频
    		if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
    		{
    			audioStream = i;
    			cout << i << " : 音频信息" << endl;
    			cout << "sample_rate = " << as->codecpar->sample_rate << endl;
    			//cout << "format = " << as->codecpar->format << endl;//AVSampleFormat
    			cout << "channnels = " << as->codecpar->channels << endl;
    			//cout << "codec_id = " << as->codecpar->codec_id << endl;//AVCodecID
    			cout << "audio fps = " << r2d(as->avg_frame_rate) << endl;//存储浮点数是按照分子分母保存的
    			//音频一帧数据 是 一定量的样本数 单通道
    			cout<< "frame_size = " << as->codecpar->frame_size << endl;
    			//fps = sample_rate/frame_size
    		}
    		//视频
    		else 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 << "vedio fps = " << r2d(as->avg_frame_rate) << endl;
    			//打印时长
    			int as_duration =  (as->duration) * av_q2d(as->time_base);
    			cout << "视频的总时长为: " << as_duration / 3600 << ":" << as_duration % 3600 / 60 << ":" << as_duration % 60 << endl;
    			//av_q2d;
    
    		}
    	}
    
    	//获取视频流 另一种方法
    	//videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    	//ic->streams[videoStream];
    
    	//获取一个包的数据
    	AVPacket* pkt = av_packet_alloc();//分配包的内存(堆上),需要手动释放
    	int pkt_count = 0;
    	int print_max_count = 10;//打印10个包
    	cout << "*****av_read_frame start*****" << endl;
    
    	while (1)
    	{
    		int ret = av_read_frame(ic, pkt);
    		if (ret < 0)
    		{
    			cout << "******av_read_frame end*****" << endl;
    			break;//开辟空间失败,就不需要再释放,即减少引用计数
    
    			//循环播放,跳转帧的位置
    			//int ms = 100;//根据时间基数转换位置
    			//long long pos = (double)ms / 1000 * r2d(ic->streams[pkt->stream_index]->time_base);
    			//av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);//往后找一帧,且找到关键帧
    			//getchar();
    			//continue;
    		}
    		if (pkt_count++ < print_max_count)
    		{
    			if (pkt->stream_index == audioStream)
    			{
    				//显示时间
    				cout << "******audio pts :"<< pkt->pts << endl;
    				//显示为ms,方便同步
    				cout << pkt->pts * r2d(ic->streams[pkt->stream_index]->time_base) * 1000 << endl;
    				//解码时间
    				cout << "******audio dts :" << pkt->dts << endl;
    				cout << "******audio size :" << pkt->size << endl;
    				cout << "******audio pos :" << pkt->pos << endl;
    				cout << endl;
    			}
    			else if (pkt->stream_index == videoStream)
    			{
    				cout << "******video pts :" << pkt->pts << endl;
    				//显示为ms
    				cout << pkt->pts * r2d(ic->streams[pkt->stream_index]->time_base) * 1000 << endl;
    				cout << "******video dts :" << pkt->dts << endl;
    				cout << "******video size :" << pkt->size << endl;
    				cout << "******video pos :" << pkt->pos << endl;
    				cout << endl;
    			}
    			else
    				cout << "unknow stream_index" << pkt->stream_index << endl;
    		}
    		//每次拿到包的数据后减少引用计数
    		av_packet_unref(pkt);
    	}
    	//最后释放包的内存
    	av_packet_free(&pkt);
    	
    	if (ic)
    	{
    		//释放封装上下文,并且把ic置为0
    		avformat_close_input(&ic);
    	}
    
    	getchar();
    	return 0;
    }
    

    在这里插入图片描述

  • 相关阅读:
    通过Fuseki进行三元组数据的新增、删除和查询
    Java核心技术 卷1
    【光学】基于matlab GUI矩阵法和等效界面法光学薄膜对反射率影响【含Matlab源码 2102期】
    对DDD使用的一些建议
    2023年煤气证模拟考试题库及煤气理论考试试题
    Map和Set的详解
    接口测试--知识问答
    深入理解强化学习——多臂赌博机:增量式实现
    【第2次JavaWeb上机练习】
    JWT认证漏洞攻击详解总结
  • 原文地址:https://blog.csdn.net/weixin_45690131/article/details/139419905