播放器支持超时时间的配置项

优化函数命名
This commit is contained in:
xiongziliang 2019-03-01 14:23:28 +08:00
parent e240044f2f
commit 40a7913bf9
10 changed files with 111 additions and 68 deletions

View File

@ -39,8 +39,13 @@ const char PlayerBase::kRtspUser[] = "rtsp_user" ;
const char PlayerBase::kRtspPwd[] = "rtsp_pwd"; const char PlayerBase::kRtspPwd[] = "rtsp_pwd";
const char PlayerBase::kRtspPwdIsMD5[] = "rtsp_pwd_md5"; const char PlayerBase::kRtspPwdIsMD5[] = "rtsp_pwd_md5";
const char PlayerBase::kPlayTimeoutMS[] = "play_timeout_ms";
const char PlayerBase::kMediaTimeoutMS[] = "media_timeout_ms";
const char PlayerBase::kBeatIntervalMS[] = "beat_interval_ms";
const char PlayerBase::kMaxAnalysisMS[] = "max_analysis_ms";
PlayerBase::Ptr PlayerBase::createPlayer(const char* strUrl) {
PlayerBase::Ptr PlayerBase::createPlayer(const char* strUrl) {
static auto releasePlayer = [](PlayerBase *ptr){ static auto releasePlayer = [](PlayerBase *ptr){
onceToken token(nullptr,[&](){ onceToken token(nullptr,[&](){
delete ptr; delete ptr;
@ -57,6 +62,13 @@ PlayerBase::Ptr PlayerBase::createPlayer(const char* strUrl) {
return PlayerBase::Ptr(new RtspPlayerImp(),releasePlayer); return PlayerBase::Ptr(new RtspPlayerImp(),releasePlayer);
} }
PlayerBase::PlayerBase() {
this->mINI::operator[](kPlayTimeoutMS) = 10000;
this->mINI::operator[](kMediaTimeoutMS) = 5000;
this->mINI::operator[](kBeatIntervalMS) = 5000;
this->mINI::operator[](kMaxAnalysisMS) = 2000;
}
///////////////////////////Demuxer////////////////////////////// ///////////////////////////Demuxer//////////////////////////////
bool Demuxer::isInited(int analysisMs) { bool Demuxer::isInited(int analysisMs) {
if(_ticker.createdTime() < analysisMs){ if(_ticker.createdTime() < analysisMs){

View File

@ -56,7 +56,7 @@ public:
* @param analysisMs * @param analysisMs
* @return * @return
*/ */
virtual bool isInited(int analysisMs = 2000) { return true; } virtual bool isInited(int analysisMs) { return true; }
/** /**
* Track * Track
@ -103,10 +103,19 @@ public:
static const char kRtspUser[]; static const char kRtspUser[];
//rtsp认证用用户密码可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password) //rtsp认证用用户密码可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password)
static const char kRtspPwd[]; static const char kRtspPwd[];
//rtsp认证用用户密码是否为md5 //rtsp认证用用户密码是否为md5类型
static const char kRtspPwdIsMD5[]; static const char kRtspPwdIsMD5[];
//播放超时时间默认10,000 毫秒
static const char kPlayTimeoutMS[];
//rtp/rtmp包接收超时时间默认5000秒
static const char kMediaTimeoutMS[];
//rtsp/rtmp心跳时间,默认5000毫秒
static const char kBeatIntervalMS[];
//Track编码格式探测最大时间单位毫秒默认2000
static const char kMaxAnalysisMS[];
PlayerBase(){}
PlayerBase();
virtual ~PlayerBase(){} virtual ~PlayerBase(){}
/** /**
@ -187,7 +196,7 @@ public:
_playResultCB = cb; _playResultCB = cb;
} }
bool isInited(int analysisMs = 2000) override{ bool isInited(int analysisMs) override{
if (_parser) { if (_parser) {
return _parser->isInited(analysisMs); return _parser->isInited(analysisMs);
} }
@ -243,21 +252,20 @@ protected:
_playResultCB = nullptr; _playResultCB = nullptr;
return; return;
} }
//播放成功 //播放成功后我们还必须等待各个Track初始化完毕才能回调告知已经初始化完毕
if(isInited(INT_MAX)){
if(isInited()){
//初始化完毕则立即回调 //初始化完毕则立即回调
_playResultCB(ex); _playResultCB(ex);
_playResultCB = nullptr; _playResultCB = nullptr;
return; return;
} }
//播放成功却未初始化完毕 //播放成功却未初始化完毕,这个时候不回调汇报播放成功
} }
void checkInited(){ void checkInited(int analysisMs){
if(!_playResultCB){ if(!_playResultCB){
return; return;
} }
if(isInited()){ if(isInited(analysisMs)){
_playResultCB(SockException(Err_success,"play success")); _playResultCB(SockException(Err_success,"play success"));
_playResultCB = nullptr; _playResultCB = nullptr;
} }
@ -285,7 +293,7 @@ public:
* @param analysisMs * @param analysisMs
* @return * @return
*/ */
bool isInited(int analysisMs = 2000) override; bool isInited(int analysisMs) override;
/** /**
* TrackisInited()true时调用 * TrackisInited()true时调用

View File

@ -80,7 +80,7 @@ void RtmpPlayer::play(const char* strUrl) {
_strTcUrl = string("rtmp://") + strHost + "/" + _strApp; _strTcUrl = string("rtmp://") + strHost + "/" + _strApp;
if (!_strApp.size() || !_strStream.size()) { if (!_strApp.size() || !_strStream.size()) {
_onPlayResult(SockException(Err_other,"rtmp url非法")); onPlayResult_l(SockException(Err_other,"rtmp url非法"));
return; return;
} }
DebugL << strHost << " " << _strApp << " " << _strStream; DebugL << strHost << " " << _strApp << " " << _strStream;
@ -96,27 +96,30 @@ void RtmpPlayer::play(const char* strUrl) {
if(!(*this)[PlayerBase::kNetAdapter].empty()){ if(!(*this)[PlayerBase::kNetAdapter].empty()){
setNetAdapter((*this)[PlayerBase::kNetAdapter]); setNetAdapter((*this)[PlayerBase::kNetAdapter]);
} }
startConnect(strHost, iPort);
}
void RtmpPlayer::onErr(const SockException &ex){
_onShutdown(ex);
}
void RtmpPlayer::onConnect(const SockException &err){
if(err.getErrCode()!=Err_success) {
_onPlayResult(err);
return;
}
weak_ptr<RtmpPlayer> weakSelf= dynamic_pointer_cast<RtmpPlayer>(shared_from_this()); weak_ptr<RtmpPlayer> weakSelf= dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
_pPlayTimer.reset( new Timer(10, [weakSelf]() { float playTimeOutSec = (*this)[kPlayTimeoutMS].as<int>() / 1000.0;
_pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() {
auto strongSelf=weakSelf.lock(); auto strongSelf=weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
return false; return false;
} }
strongSelf->_onPlayResult(SockException(Err_timeout,"play rtmp timeout")); strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtmp timeout"));
strongSelf->teardown(); strongSelf->teardown();
return false; return false;
},getPoller())); },getPoller()));
startConnect(strHost, iPort , playTimeOutSec);
}
void RtmpPlayer::onErr(const SockException &ex){
onShutdown_l(ex);
}
void RtmpPlayer::onConnect(const SockException &err){
if(err.getErrCode()!=Err_success) {
onPlayResult_l(err);
return;
}
weak_ptr<RtmpPlayer> weakSelf= dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
startClientSession([weakSelf](){ startClientSession([weakSelf](){
auto strongSelf=weakSelf.lock(); auto strongSelf=weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
@ -130,8 +133,8 @@ void RtmpPlayer::onRecv(const Buffer::Ptr &pBuf){
onParseRtmp(pBuf->data(), pBuf->size()); onParseRtmp(pBuf->data(), pBuf->size());
} catch (exception &e) { } catch (exception &e) {
SockException ex(Err_other, e.what()); SockException ex(Err_other, e.what());
_onPlayResult(ex); onPlayResult_l(ex);
_onShutdown(ex); onShutdown_l(ex);
teardown(); teardown();
} }
} }
@ -210,7 +213,7 @@ inline void RtmpPlayer::send_pause(bool bPause) {
}else{ }else{
_bPaused = bPause; _bPaused = bPause;
if(!bPause){ if(!bPause){
_onPlayResult(SockException(Err_success, "rtmp resum success")); onPlayResult_l(SockException(Err_success, "rtmp resum success"));
}else{ }else{
//暂停播放 //暂停播放
_pMediaTimer.reset(); _pMediaTimer.reset();
@ -222,7 +225,7 @@ inline void RtmpPlayer::send_pause(bool bPause) {
_pBeatTimer.reset(); _pBeatTimer.reset();
if(bPause){ if(bPause){
weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this()); weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
_pBeatTimer.reset(new Timer(3,[weakSelf](){ _pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as<int>() / 1000.0,[weakSelf](){
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if (!strongSelf){ if (!strongSelf){
return false; return false;
@ -279,12 +282,12 @@ void RtmpPlayer::onCmd_onMetaData(AMFDecoder &dec) {
if(!onCheckMeta(val)){ if(!onCheckMeta(val)){
throw std::runtime_error("onCheckMeta faied"); throw std::runtime_error("onCheckMeta faied");
} }
_onPlayResult(SockException(Err_success,"play rtmp success")); onPlayResult_l(SockException(Err_success,"play rtmp success"));
} }
void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) { void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) {
//TraceL << ui32StreamId; //TraceL << ui32StreamId;
_onShutdown(SockException(Err_other,"rtmp stream dry")); onShutdown_l(SockException(Err_other,"rtmp stream dry"));
} }
@ -311,7 +314,7 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
if (_aNowStampTicker[idx].elapsedTime() > 500) { if (_aNowStampTicker[idx].elapsedTime() > 500) {
_aiNowStamp[idx] = chunkData.timeStamp; _aiNowStamp[idx] = chunkData.timeStamp;
} }
_onMediaData(std::make_shared<RtmpPacket>(std::move(chunkData))); onMediaData_l(std::make_shared<RtmpPacket>(std::move(chunkData)));
} }
break; break;
default: default:

View File

@ -58,32 +58,33 @@ protected:
uint32_t getProgressMilliSecond() const; uint32_t getProgressMilliSecond() const;
void seekToMilliSecond(uint32_t ms); void seekToMilliSecond(uint32_t ms);
protected: protected:
void _onShutdown(const SockException &ex) { void onShutdown_l(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what(); WarnL << ex.getErrCode() << " " << ex.what();
_pPlayTimer.reset(); _pPlayTimer.reset();
_pMediaTimer.reset(); _pMediaTimer.reset();
_pBeatTimer.reset(); _pBeatTimer.reset();
onShutdown(ex); onShutdown(ex);
} }
void _onMediaData(const RtmpPacket::Ptr &chunkData) { void onMediaData_l(const RtmpPacket::Ptr &chunkData) {
_mediaTicker.resetTime(); _mediaTicker.resetTime();
onMediaData(chunkData); onMediaData(chunkData);
} }
void _onPlayResult(const SockException &ex) { void onPlayResult_l(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what(); WarnL << ex.getErrCode() << " " << ex.what();
_pPlayTimer.reset(); _pPlayTimer.reset();
_pMediaTimer.reset(); _pMediaTimer.reset();
if (!ex) { if (!ex) {
_mediaTicker.resetTime(); _mediaTicker.resetTime();
weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this()); weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
_pMediaTimer.reset( new Timer(5, [weakSelf]() { int timeoutMS = (*this)[kMediaTimeoutMS].as<int>();
_pMediaTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() {
auto strongSelf=weakSelf.lock(); auto strongSelf=weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
return false; return false;
} }
if(strongSelf->_mediaTicker.elapsedTime()>10000) { if(strongSelf->_mediaTicker.elapsedTime()> timeoutMS) {
//recv media timeout! //recv media timeout!
strongSelf->_onShutdown(SockException(Err_timeout,"recv rtmp timeout")); strongSelf->onShutdown_l(SockException(Err_timeout,"recv rtmp timeout"));
strongSelf->teardown(); strongSelf->teardown();
return false; return false;
} }

View File

@ -56,6 +56,10 @@ public:
fProgress = MAX(float(0),MIN(fProgress,float(1.0))); fProgress = MAX(float(0),MIN(fProgress,float(1.0)));
seekToMilliSecond(fProgress * getDuration() * 1000); seekToMilliSecond(fProgress * getDuration() * 1000);
}; };
void play(const char* strUrl) override {
_analysisMs = (*this)[PlayerBase::kMaxAnalysisMS].as<int>();
PlayerImp<RtmpPlayer,RtmpDemuxer>::play(strUrl);
}
private: private:
//派生类回调函数 //派生类回调函数
bool onCheckMeta(AMFValue &val) override { bool onCheckMeta(AMFValue &val) override {
@ -71,15 +75,16 @@ private:
_pRtmpMediaSrc->onWrite(chunkData); _pRtmpMediaSrc->onWrite(chunkData);
} }
if(!_parser){ if(!_parser){
//这个流没有metedata那么尝试在音视频包里面还原出相关信息
_parser.reset(new RtmpDemuxer()); _parser.reset(new RtmpDemuxer());
_onPlayResult(SockException(Err_success,"play rtmp success")); onPlayResult_l(SockException(Err_success,"play rtmp success"));
} }
_parser->inputRtmp(chunkData); _parser->inputRtmp(chunkData);
checkInited(); checkInited(_analysisMs);
} }
private: private:
RtmpMediaSource::Ptr _pRtmpMediaSrc; RtmpMediaSource::Ptr _pRtmpMediaSrc;
int _analysisMs;
}; };

View File

@ -59,15 +59,15 @@ public:
} }
virtual ~RtmpToRtspMediaSource(){} virtual ~RtmpToRtspMediaSource(){}
void onGetMetaData(const AMFValue &_metadata) override { void onGetMetaData(const AMFValue &metadata) override {
_rtmpDemuxer = std::make_shared<RtmpDemuxer>(_metadata); _rtmpDemuxer = std::make_shared<RtmpDemuxer>(metadata);
RtmpMediaSource::onGetMetaData(_metadata); RtmpMediaSource::onGetMetaData(metadata);
} }
void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos) override { void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos) override {
if(_rtmpDemuxer){ if(_rtmpDemuxer){
_rtmpDemuxer->inputRtmp(pkt); _rtmpDemuxer->inputRtmp(pkt);
if(!_rtspMuxer && _rtmpDemuxer->isInited()){ if(!_rtspMuxer && _rtmpDemuxer->isInited(2000)){
_rtspMuxer = std::make_shared<RtspMediaSourceMuxer>(getVhost(), _rtspMuxer = std::make_shared<RtspMediaSourceMuxer>(getVhost(),
getApp(), getApp(),
getId(), getId(),

View File

@ -54,7 +54,7 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
return false; return false;
} }
if (_sps.size() && pkt->strBuf.size() > 9) { if (pkt->strBuf.size() > 9) {
uint32_t iTotalLen = pkt->strBuf.size(); uint32_t iTotalLen = pkt->strBuf.size();
uint32_t iOffset = 5; uint32_t iOffset = 5;
uint8_t *cts_ptr = (uint8_t *) (pkt->strBuf.data() + 2); uint8_t *cts_ptr = (uint8_t *) (pkt->strBuf.data() + 2);
@ -81,9 +81,15 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
switch (H264_TYPE(pcData[0])) { switch (H264_TYPE(pcData[0])) {
case H264Frame::NAL_IDR: { case H264Frame::NAL_IDR: {
//I frame //I frame
onGetH264(_sps.data(), _sps.length(), dts , pts); if(_sps.length()){
onGetH264(_pps.data(), _pps.length(), dts , pts); onGetH264(_sps.data(), _sps.length(), dts , pts);
}
if(_pps.length()){
onGetH264(_pps.data(), _pps.length(), dts , pts);
}
onGetH264(pcData, iLen, dts , pts);
} }
break;
case H264Frame::NAL_B_P: { case H264Frame::NAL_B_P: {
//I or P or B frame //I or P or B frame
onGetH264(pcData, iLen, dts , pts); onGetH264(pcData, iLen, dts , pts);

View File

@ -133,7 +133,20 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
if(!(*this)[PlayerBase::kNetAdapter].empty()){ if(!(*this)[PlayerBase::kNetAdapter].empty()){
setNetAdapter((*this)[PlayerBase::kNetAdapter]); setNetAdapter((*this)[PlayerBase::kNetAdapter]);
} }
startConnect(ip.data(), port);
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
float playTimeOutSec = (*this)[kPlayTimeoutMS].as<int>() / 1000.0;
_pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
}
strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"));
strongSelf->teardown();
return false;
},getPoller()));
startConnect(ip.data(), port , playTimeOutSec);
} }
void RtspPlayer::onConnect(const SockException &err){ void RtspPlayer::onConnect(const SockException &err){
if(err.getErrCode()!=Err_success) { if(err.getErrCode()!=Err_success) {
@ -143,17 +156,6 @@ void RtspPlayer::onConnect(const SockException &err){
} }
sendDescribe(); sendDescribe();
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
_pPlayTimer.reset( new Timer(10, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
}
strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"));
strongSelf->teardown();
return false;
},getPoller()));
} }
void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) { void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
@ -346,7 +348,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
} }
/////////////////////////心跳///////////////////////////////// /////////////////////////心跳/////////////////////////////////
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this()); weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
_pBeatTimer.reset(new Timer(5, [weakSelf](){ _pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as<int>() / 1000.0, [weakSelf](){
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if (!strongSelf){ if (!strongSelf){
return false; return false;
@ -591,12 +593,13 @@ void RtspPlayer::onPlayResult_l(const SockException &ex) {
if (!ex) { if (!ex) {
_rtpTicker.resetTime(); _rtpTicker.resetTime();
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this()); weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
_pRtpTimer.reset( new Timer(5, [weakSelf]() { int timeoutMS = (*this)[kMediaTimeoutMS].as<int>();
_pRtpTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() {
auto strongSelf=weakSelf.lock(); auto strongSelf=weakSelf.lock();
if(!strongSelf) { if(!strongSelf) {
return false; return false;
} }
if(strongSelf->_rtpTicker.elapsedTime()>10000) { if(strongSelf->_rtpTicker.elapsedTime()> timeoutMS) {
//recv rtp timeout! //recv rtp timeout!
strongSelf->onShutdown_l(SockException(Err_timeout,"recv rtp timeout")); strongSelf->onShutdown_l(SockException(Err_timeout,"recv rtp timeout"));
strongSelf->teardown(); strongSelf->teardown();

View File

@ -74,10 +74,15 @@ private:
_pRtspMediaSrc->onWrite(rtppt,true); _pRtspMediaSrc->onWrite(rtppt,true);
} }
_parser->inputRtp(rtppt); _parser->inputRtp(rtppt);
checkInited();
//由于我们重载isInited方法强制认为一旦获取sdp那么就初始化Track成功
//所以我们不需要在后续检验是否初始化成功
//checkInited(0);
} }
bool isInited(int analysisMs = 2000) override{ bool isInited(int analysisMs) override{
//rtsp是通过sdp来完成track的初始化的所以我们强制返回true
//认为已经初始化完毕这样可以提高rtsp打开速度
return true; return true;
} }
private: private:

View File

@ -61,7 +61,7 @@ public:
virtual void onWrite(const RtpPacket::Ptr &rtp, bool bKeyPos) override { virtual void onWrite(const RtpPacket::Ptr &rtp, bool bKeyPos) override {
if (_rtspDemuxer) { if (_rtspDemuxer) {
bKeyPos = _rtspDemuxer->inputRtp(rtp); bKeyPos = _rtspDemuxer->inputRtp(rtp);
if (!_rtmpMuxer && _rtspDemuxer->isInited()) { if (!_rtmpMuxer && _rtspDemuxer->isInited(2000)) {
_rtmpMuxer = std::make_shared<RtmpMediaSourceMuxer>(getVhost(), _rtmpMuxer = std::make_shared<RtmpMediaSourceMuxer>(getVhost(),
getApp(), getApp(),
getId(), getId(),