根据上篇的方法配置继续学习解封装
#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;
}