main.cpp
#include "XPlay2.h"
#include <QApplication>
#include <iostream>
using namespace std;
#include "XDemux.h"
int main(int argc, char *argv[])
{
///测试XDemux
XDemux demux;
//香港卫视
const char *url = "rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp";
// url = "001111.mp4";
cout<<"demux.Open = "<<demux.Open(url);
QApplication a(argc, argv);
XPlay2 w;
w.show();
return a.exec();
}
XDemux.h
#ifndef XDEMUX_H
#define XDEMUX_H
#include <mutex>
struct AVFormatContext;
class XDemux
{
public:
//打开媒体文件,或者流媒体 rtmp http rstp
virtual bool Open(const char *url);
XDemux();
virtual ~XDemux();
//媒体总时长(毫秒)
int totalMs = 0;
protected:
std::mutex mux;
//解封装上下文
AVFormatContext *ic = NULL;
//音视频索引,读取时区分音视频
int videoStream = 0;
int audioStream = 1;
};
#endif // XDEMUX_H
XDemux.cpp
#include "XDemux.h"
#include <iostream>
using namespace std;
extern "C" {
#include "libavformat/avformat.h"
}
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
static double r2d(AVRational r)
{
return r.den == 0 ? 0 : (double)r.num / (double)r.den;
}
bool XDemux::Open(const char *url)
{
//参数设置
AVDictionary *opts = NULL;
//设置rtsp流已tcp协议打开
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
//网络延时时间
av_dict_set(&opts, "max_delay", "5000", 0);
mux.lock();
int re = avformat_open_input(
&ic,
url,
0, // 0表示自动选择解封器
&opts //参数设置,比如rtsp的延时时间
);
if (re != 0)
{
mux.unlock();
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);
cout << "open " << url << " failed! :" << buf << endl;
return false;
}
cout << "open " << url << " success! " << endl;
//获取流信息
re = avformat_find_stream_info(ic, 0);
//总时长 毫秒
int totalMs = ic->duration / (AV_TIME_BASE / 1000);
cout << "totalMs = " << totalMs << endl;
//打印视频流详细信息
av_dump_format(ic, 0, url, 0);
//获取视频流
videoStream = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
AVStream *as = ic->streams[videoStream];
cout << "=======================================================" << endl;
cout << videoStream << "视频信息" << endl;
cout << "codec_id = " << as->codecpar->codec_id << endl;
cout << "format = " << as->codecpar->format << endl;
cout << "width=" << as->codecpar->width << endl;
cout << "height=" << as->codecpar->height << endl;
//帧率 fps 分数转换
cout << "video fps = " << r2d(as->avg_frame_rate) << endl;
cout << "=======================================================" << endl;
cout << audioStream << "音频信息" << endl;
//获取音频流
audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
as = ic->streams[audioStream];
cout << "codec_id = " << as->codecpar->codec_id << endl;
cout << "format = " << as->codecpar->format << endl;
cout << "sample_rate = " << as->codecpar->sample_rate << endl;
//AVSampleFormat;
cout << "channels = " << as->codecpar->channels << endl;
//一帧数据?? 单通道样本数
cout << "frame_size = " << as->codecpar->frame_size << endl;
//1024 * 2 * 2 = 4096 fps = sample_rate/frame_size
mux.unlock();
return true;
}
XDemux::XDemux()
{
static bool isFirst = true;
static std::mutex dmux;
dmux.lock();
if (isFirst)
{
//初始化封装库
av_register_all();
//初始化网络库 (可以打开rtsp rtmp http 协议的流媒体视频)
avformat_network_init();
isFirst = false;
}
dmux.unlock();
}
XDemux::~XDemux()
{
}