mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-13 19:51:49 +08:00
解决播放成功与中途断开事件触发紊乱的问题:#143
This commit is contained in:
@@ -42,11 +42,17 @@ using namespace mediakit::Client;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
enum PlayType {
|
||||
type_play = 0,
|
||||
type_pause,
|
||||
type_seek
|
||||
};
|
||||
|
||||
RtspPlayer::RtspPlayer(const EventPoller::Ptr &poller) : TcpClient(poller){
|
||||
RtpReceiver::setPoolSize(64);
|
||||
}
|
||||
RtspPlayer::~RtspPlayer(void) {
|
||||
DebugL<<endl;
|
||||
DebugL << endl;
|
||||
}
|
||||
void RtspPlayer::teardown(){
|
||||
if (alive()) {
|
||||
@@ -56,7 +62,6 @@ void RtspPlayer::teardown(){
|
||||
|
||||
_rtspMd5Nonce.clear();
|
||||
_rtspRealm.clear();
|
||||
|
||||
_aTrackInfo.clear();
|
||||
_strSession.clear();
|
||||
_strContentBase.clear();
|
||||
@@ -135,7 +140,7 @@ void RtspPlayer::play(bool isSSL,const string &strUrl, const string &strUser, co
|
||||
}
|
||||
|
||||
if(ip.empty()){
|
||||
onPlayResult_l(SockException(Err_other,StrPrinter << "illegal rtsp url:" << strUrl));
|
||||
onPlayResult_l(SockException(Err_other,StrPrinter << "illegal rtsp url:" << strUrl),false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -148,7 +153,7 @@ void RtspPlayer::play(bool isSSL,const string &strUrl, const string &strUser, co
|
||||
if(!strongSelf) {
|
||||
return false;
|
||||
}
|
||||
strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"));
|
||||
strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"),false);
|
||||
return false;
|
||||
},getPoller()));
|
||||
|
||||
@@ -158,8 +163,8 @@ void RtspPlayer::play(bool isSSL,const string &strUrl, const string &strUser, co
|
||||
startConnect(ip, port , playTimeOutSec);
|
||||
}
|
||||
void RtspPlayer::onConnect(const SockException &err){
|
||||
if(err.getErrCode()!=Err_success) {
|
||||
onPlayResult_l(err);
|
||||
if(err.getErrCode() != Err_success) {
|
||||
onPlayResult_l(err,false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,7 +175,8 @@ void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
|
||||
input(pBuf->data(),pBuf->size());
|
||||
}
|
||||
void RtspPlayer::onErr(const SockException &ex) {
|
||||
onPlayResult_l(ex);
|
||||
//定时器_pPlayTimer为空后表明握手结束了
|
||||
onPlayResult_l(ex,!_pPlayTimer);
|
||||
}
|
||||
// from live555
|
||||
bool RtspPlayer::handleAuthenticationFailure(const string ¶msStr) {
|
||||
@@ -403,8 +409,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
|
||||
WarnL << "收到其他地址的rtcp数据:" << inet_ntoa(((struct sockaddr_in *) addr)->sin_addr);
|
||||
return;
|
||||
}
|
||||
strongSelf->onRtcpPacket(uiTrackIndex, strongSelf->_aTrackInfo[uiTrackIndex],
|
||||
(unsigned char *) buf->data(), buf->size());
|
||||
strongSelf->onRtcpPacket(uiTrackIndex, strongSelf->_aTrackInfo[uiTrackIndex], (unsigned char *) buf->data(), buf->size());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -416,14 +421,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
|
||||
}
|
||||
//所有setup命令发送完毕
|
||||
//发送play命令
|
||||
sendPause(false, 0,false);
|
||||
}
|
||||
|
||||
void RtspPlayer::sendOptions() {
|
||||
_onHandshake = [](const Parser& parser){
|
||||
// DebugL << "options response";
|
||||
};
|
||||
sendRtspRequest("OPTIONS",_strContentBase);
|
||||
sendPause(type_play, 0);
|
||||
}
|
||||
|
||||
void RtspPlayer::sendDescribe() {
|
||||
@@ -432,46 +430,67 @@ void RtspPlayer::sendDescribe() {
|
||||
sendRtspRequest("DESCRIBE",_strUrl,{"Accept","application/sdp"});
|
||||
}
|
||||
|
||||
|
||||
void RtspPlayer::sendPause(bool bPause,uint32_t seekMS,bool range){
|
||||
void RtspPlayer::sendPause(int type , uint32_t seekMS){
|
||||
_onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,type);
|
||||
//开启或暂停rtsp
|
||||
_onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,bPause);
|
||||
if(!bPause && range){
|
||||
sendRtspRequest(bPause ? "PAUSE" : "PLAY", _strContentBase,
|
||||
{"Range",StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-"});
|
||||
} else{
|
||||
sendRtspRequest(bPause ? "PAUSE" : "PLAY", _strContentBase);
|
||||
}
|
||||
|
||||
switch (type){
|
||||
case type_pause:
|
||||
sendRtspRequest("PAUSE", _strContentBase);
|
||||
break;
|
||||
case type_play:
|
||||
sendRtspRequest("PLAY", _strContentBase);
|
||||
break;
|
||||
case type_seek:
|
||||
sendRtspRequest("PLAY", _strContentBase, {"Range",StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-"});
|
||||
break;
|
||||
default:
|
||||
WarnL << "unknown type : " << type;
|
||||
_onHandshake = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void RtspPlayer::pause(bool bPause) {
|
||||
sendPause(bPause, getProgressMilliSecond(),false);
|
||||
sendPause(bPause ? type_pause : type_seek, getProgressMilliSecond());
|
||||
}
|
||||
|
||||
void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) {
|
||||
void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
|
||||
if (parser.Url() != "200") {
|
||||
WarnL <<(bPause ? "Pause" : "Play") << " failed:" << parser.Url() << " " << parser.Tail() << endl;
|
||||
switch (type) {
|
||||
case type_pause:
|
||||
WarnL << "Pause failed:" << parser.Url() << " " << parser.Tail() << endl;
|
||||
break;
|
||||
case type_play:
|
||||
WarnL << "Play failed:" << parser.Url() << " " << parser.Tail() << endl;
|
||||
break;
|
||||
case type_seek:
|
||||
WarnL << "Seek failed:" << parser.Url() << " " << parser.Tail() << endl;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!bPause) {
|
||||
uint32_t iSeekTo = 0;
|
||||
//修正时间轴
|
||||
auto strRange = parser["Range"];
|
||||
if (strRange.size()) {
|
||||
auto strStart = FindField(strRange.data(), "npt=", "-");
|
||||
if (strStart == "now") {
|
||||
strStart = "0";
|
||||
}
|
||||
iSeekTo = 1000 * atof(strStart.data());
|
||||
DebugL << "seekTo(ms):" << iSeekTo ;
|
||||
}
|
||||
//设置相对时间戳
|
||||
_stamp[0].setRelativeStamp(iSeekTo);
|
||||
_stamp[1].setRelativeStamp(iSeekTo);
|
||||
onPlayResult_l(SockException(Err_success, "rtsp play success"));
|
||||
} else {
|
||||
|
||||
if (type == type_pause) {
|
||||
//暂停成功!
|
||||
_pRtpTimer.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
//play或seek成功
|
||||
uint32_t iSeekTo = 0;
|
||||
//修正时间轴
|
||||
auto strRange = parser["Range"];
|
||||
if (strRange.size()) {
|
||||
auto strStart = FindField(strRange.data(), "npt=", "-");
|
||||
if (strStart == "now") {
|
||||
strStart = "0";
|
||||
}
|
||||
iSeekTo = 1000 * atof(strStart.data());
|
||||
DebugL << "seekTo(ms):" << iSeekTo;
|
||||
}
|
||||
//设置相对时间戳
|
||||
_stamp[0].setRelativeStamp(iSeekTo);
|
||||
_stamp[1].setRelativeStamp(iSeekTo);
|
||||
onPlayResult_l(SockException(Err_success, type == type_seek ? "resum rtsp success" : "rtsp play success"), type == type_seek);
|
||||
}
|
||||
|
||||
void RtspPlayer::onWholeRtspPacket(Parser &parser) {
|
||||
@@ -483,8 +502,8 @@ void RtspPlayer::onWholeRtspPacket(Parser &parser) {
|
||||
}
|
||||
parser.Clear();
|
||||
} catch (std::exception &err) {
|
||||
SockException ex(Err_other, err.what());
|
||||
onPlayResult_l(ex);
|
||||
//定时器_pPlayTimer为空后表明握手结束了
|
||||
onPlayResult_l(SockException(Err_other, err.what()),!_pPlayTimer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +693,7 @@ uint32_t RtspPlayer::getProgressMilliSecond() const{
|
||||
return MAX(_stamp[0].getRelativeStamp(),_stamp[1].getRelativeStamp());
|
||||
}
|
||||
void RtspPlayer::seekToMilliSecond(uint32_t ms) {
|
||||
sendPause(false,ms, true);
|
||||
sendPause(type_seek,ms);
|
||||
}
|
||||
|
||||
void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const std::initializer_list<string> &header) {
|
||||
@@ -764,7 +783,7 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pkt, const SdpTrack::Ptr &tra
|
||||
|
||||
|
||||
}
|
||||
void RtspPlayer::onPlayResult_l(const SockException &ex) {
|
||||
void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeCompleted) {
|
||||
WarnL << ex.getErrCode() << " " << ex.what();
|
||||
|
||||
if(!ex){
|
||||
@@ -772,33 +791,31 @@ void RtspPlayer::onPlayResult_l(const SockException &ex) {
|
||||
_rtpTicker.resetTime();
|
||||
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
||||
int timeoutMS = (*this)[kMediaTimeoutMS].as<int>();
|
||||
_pRtpTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() {
|
||||
//创建rtp数据接收超时检测定时器
|
||||
_pRtpTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() {
|
||||
auto strongSelf=weakSelf.lock();
|
||||
if(!strongSelf) {
|
||||
return false;
|
||||
}
|
||||
if(strongSelf->_rtpTicker.elapsedTime()> timeoutMS) {
|
||||
//recv rtp timeout!
|
||||
strongSelf->onPlayResult_l(SockException(Err_timeout,"recv rtp timeout"));
|
||||
//接收rtp媒体数据包超时
|
||||
strongSelf->onPlayResult_l(SockException(Err_timeout,"receive rtp timeout"), true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},getPoller()));
|
||||
}
|
||||
|
||||
if (_pPlayTimer) {
|
||||
if (!handshakeCompleted) {
|
||||
//开始播放阶段
|
||||
_pPlayTimer.reset();
|
||||
onPlayResult(ex);
|
||||
}else {
|
||||
//播放中途阶段
|
||||
if (ex) {
|
||||
//播放成功后异常断开回调
|
||||
onShutdown(ex);
|
||||
}else{
|
||||
//恢复播放
|
||||
onResume();
|
||||
}
|
||||
} else if (ex) {
|
||||
//播放成功后异常断开回调
|
||||
onShutdown(ex);
|
||||
} else {
|
||||
//恢复播放
|
||||
onResume();
|
||||
}
|
||||
|
||||
if(ex){
|
||||
|
||||
Reference in New Issue
Block a user