#include "ctffmpeg.h"
#include <QImage>
#include "ctaudioplayer.h"
#include <QPixmap>
#include <QDate>
#include <QTime>
#include <QThread>
#pragma execution_character_set("utf-8")
static enum AVPixelFormat
HwGetFormat(AVCodecContext *pAvctx, const enum AVPixelFormat *pPixFmts)
{
const enum AVPixelFormat *p;
ctFFmpeg* pFFmpeg = (ctFFmpeg*)pAvctx->opaque;
for (p = pPixFmts; *p != -1; p++)
{
if (*p == pFFmpeg->m_hwPixFmt)
{
return *p;
}
}
MY_DEBUG << "Get HW surface format failed.";
return AV_PIX_FMT_NONE;
}
static int
HwDecoderInit(AVCodecContext *pAvctx, const enum AVHWDeviceType type)
{
MY_DEBUG << "HwDecoderInit 000";
ctFFmpeg* pFFmpeg = (ctFFmpeg *)pAvctx->opaque;
int nErr = av_hwdevice_ctx_create(&pFFmpeg->m_pHwDevCtx, type, nullptr, nullptr, 0);
if (nErr < 0)
{
MY_DEBUG << "Create specified HW device failed.";
return nErr;
}
MY_DEBUG << "HwDecoderInit 111";
pAvctx->hw_device_ctx = av_buffer_ref(pFFmpeg->m_pHwDevCtx);
MY_DEBUG << "HwDecoderInit 222";
return nErr;
}
ctFFmpeg::ctFFmpeg()
{
}
ctFFmpeg::~ctFFmpeg()
{
}
int ctFFmpeg::Init(QString sUrl, int nProtocolType, int nDecodeType, int nShowType, bool bEnablePush, QString sServerAddr, ShareQueue *pQueue)
{
MY_DEBUG << "ctFFmpeg::Init sUrl:" << sUrl << " start.";
//AVCodec *pvAVCodec = nullptr; // ffmpeg low than 5.1
const AVCodec *pvAVCodec = nullptr; //ffmpeg 5.1
m_bNeedToRecon = false;
m_bQuit = false;
if(sUrl.contains("rtsp://") || sUrl.contains("http://")) //实时流
m_nPlayWay = MEDIA_PLAY_STREAM;
else
m_nPlayWay = MEDIA_PLAY_FILE;
avformat_network_init();//初始化网络流
//参数设置
AVDictionary* pOptDict = NULL;
if(nProtocolType == MEDIA_PROTOCOL_UDP)
{
MY_DEBUG << "UDP";
av_dict_set(&pOptDict, "rtsp_transport", "udp", 0);
}
else
{
MY_DEBUG << "TCP";
av_dict_set(&pOptDict, "rtsp_transport", "tcp", 0);
}
m_nProtocolType = nProtocolType;
m_nDecodeType = nDecodeType;
m_nShowType = nShowType;
m_bEnablePush = bEnablePush;
m_pShareQueue = pQueue;
m_sRtmpServerAddr = sServerAddr;
av_dict_set(&pOptDict, "stimeout", "5000000", 0);
av_dict_set(&pOptDict, "buffer_size", "8192000", 0);
av_dict_set(&pOptDict, "recv_buffer_size", "4096000", 0); // 防止花屏, max 4M.
av_dict_set(&pOptDict, "tune", "stillimage,fastdecode,zerolatency", 0);//快速解码和低延时
if(nullptr == m_pAVFmtCxt)
m_pAVFmtCxt = avformat_alloc_context();
if(nullptr == m_pYuvFrame)
m_pYuvFrame = av_frame_alloc();
if(nullptr == m_pDstVideoFrame)
m_pDstVideoFrame = av_frame_alloc();
if(nullptr == m_pPcmFrame)
m_pPcmFrame = av_frame_alloc();
if(nullptr == m_pFilterFrame)
m_pFilterFrame = av_frame_alloc();
if(nullptr == m_pHwFrame)
m_pHwFrame = av_frame_alloc();
//加入中断处理
m_nLastReadPacktTime = av_gettime();
m_pAVFmtCxt->interrupt_callback.opaque = this;
m_pAVFmtCxt->interrupt_callback.callback = [](void* ctx)
{
ctFFmpeg* pThis = (ctFFmpeg*)ctx;
int nTimeout = 3;
if (av_gettime() - pThis->m_nLastReadPacktTime > nTimeout * 1000 * 1000)
{
return -1;
}
return 0;
};
//打开码流
MY_DEBUG << "Open Stream.";
int nRet;
if(m_nPlayWay == MEDIA_PLAY_FILE)
{
nRet = avformat_open_input(&m_pAVFmtCxt, sUrl.toStdString().c_str(), nullptr, nullptr);
if(m_pAVFmtCxt)
{
m_FileTotalTimes = m_pAVFmtCxt->duration/1000000.0;//获取总时长,转化为秒
MY_DEBUG << "m_FileTimes:" << m_FileTotalTimes;
emit sig_showTotalTime(static_cast<int>(m_FileTotalTimes));
}
}
else
nRet = avformat_open_input(&m_pAVFmtCxt, sUrl.toStdString().c_str(), nullptr, &pOptDict);
if(nRet < 0)
{
MY_DEBUG << "avformat_open_input failed nRet:" << nRet;
av_dict_free(&pOptDict);
return nRet;
}
av_dict_free(&pOptDict);
//设置探测时间,获取码流信息
MY_DEBUG << "Get Stream Info.";
m_pAVFmtCxt->probesize = MAX_PROBE_SIZE;
m_pAVFmtCxt->max_analyze_duration = MAX_ANALYZE_DURATION;
nRet = avformat_find_stream_info(m_pAVFmtCxt, nullptr);
if(nRet < 0)
{
MY_DEBUG << "avformat_find_stream_info failed nRet:" << nRet;
return nRet;
}
//打印码流信息
av_dump_format(m_pAVFmtCxt, 0, sUrl.toStdString().c_str(), 0);
//查找码流
MY_DEBUG << "av_find_best_stream.";
m_nVideoIndex = av_find_best_stream(m_pAVFmtCxt, AVMEDIA_TYPE_VIDEO, -1, -1, &pvAVCodec, 0);
m_nAudioIndex = av_find_best_stream(m_pAVFmtCxt, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if(nullptr == pvAVCodec)
{
MY_DEBUG << "nullptr == pvAVCodec error.";
return -1;
}
//初始化视频
MY_DEBUG << "Init Video.";
if(InitVideo(pvAVCodec) < 0)
{
MY_DEBUG << "InitVideo() error";
return -1;
}
#if FILTER_ENABLE
if(m_nPlayWay == MEDIA_PLAY_FILE)
{
m_bSupportFilter = InitOutFile();
if(!m_bSupportFilter)
{
MY_DEBUG << "InitOutFile() error.";
}
else
MY_DEBUG << "InitOutFile() success.";
}
#endif
//初始化音频
if(m_nAudioIndex >= 0)
{
if(InitAudio() < 0)
{
MY_DEBUG << "InitAudio() error";
m_bSupportAudioPlay = false;
}
else
m_bSupportAudioPlay = true;
}
m_nShowWidgetW = 0;
m_nShowWidgetH = 0;
if(m_nDecodeType == MEDIA_DECODE_HARD)
{
if(m_bSupportHw)
{
if(nullptr != m_pHwDevCtx)
av_buffer_unref(&m_pHwDevCtx);
}
}
else
{
m_bSupportPush = initPushStream();
}
MY_DEBUG << "ctFFmpeg::Init sUrl:" << sUrl << " success.";
return 0;
}
void ctFFmpeg::DeInit()
{
MY_DEBUG << "DeInit 000";
m_mutex.lock();
m_bQuit = true;
MY_DEBUG << "DeInit 111";
if(m_pSwsContext)
sws_freeContext(m_pSwsContext);
MY_DEBUG << "DeInit 222";
if (nullptr != m_pVideoSwsContext)
{
sws_freeContext(m_pVideoSwsContext);
}
MY_DEBUG << "DeInit 444";
if (nullptr != m_pAudioSwrContext)
{
swr_free(&m_pAudioSwrContext);
m_pAudioSwrContext = nullptr;
}
MY_DEBUG << "DeInit 555";
if (m_pDstVideoFrame)
av_frame_free(&m_pDstVideoFrame);
MY_DEBUG << "DeInit 666";
if(nullptr != m_pYuvFrame)
av_free(m_pYuvFrame);
MY_DEBUG << "DeInit 777";
if(nullptr != m_pPcmFrame)
av_free(m_pPcmFrame);
MY_DEBUG << "DeInit 888";
if(nullptr != m_pFilterFrame)
av_free(m_pFilterFrame);
MY_DEBUG << "DeInit 999";
if(nullptr != m_pFrameRGB)
av_free(m_pFrameRGB);
MY_DEBUG << "DeInit aaa";
if(nullptr != m_pOutBuffer)
{
av_free(m_pOutBuffer);
}
if(nullptr != m_pHwFrame)
{
av_free(m_pHwFrame);
}
MY_DEBUG << "DeInit bbb";
if(m_nDecodeType == MEDIA_DECODE_HARD)
{
if(m_bSupportHw)
{
if(nullptr != m_pVideoCodecCxt)
{
avcodec_free_context(&m_pVideoCodecCxt);
m_pVideoCodecCxt = nullptr;
}
}
else
{
if(nullptr != m_pVideoCodecCxt)
{
avcodec_close(m_pVideoCodecCxt);
m_pVideoCodecCxt = nullptr;
}
}
}
- 1
- 2
- 3
前往页