mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
初步添加RTCP包接收接口已经发送接口
This commit is contained in:
parent
7997c06010
commit
3e0e0ce2aa
@ -63,7 +63,8 @@ void RtspPlayer::teardown(){
|
|||||||
_strContentBase.clear();
|
_strContentBase.clear();
|
||||||
RtpReceiver::clear();
|
RtpReceiver::clear();
|
||||||
|
|
||||||
CLEAR_ARR(_apUdpSock);
|
CLEAR_ARR(_apRtpSock);
|
||||||
|
CLEAR_ARR(_apRtcpSock);
|
||||||
CLEAR_ARR(_aui16FirstSeq)
|
CLEAR_ARR(_aui16FirstSeq)
|
||||||
CLEAR_ARR(_aui64RtpRecv)
|
CLEAR_ARR(_aui64RtpRecv)
|
||||||
CLEAR_ARR(_aui64RtpRecv)
|
CLEAR_ARR(_aui64RtpRecv)
|
||||||
@ -248,13 +249,20 @@ void RtspPlayer::sendSetup(unsigned int trackIndex) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Rtsp::RTP_UDP: {
|
case Rtsp::RTP_UDP: {
|
||||||
_apUdpSock[trackIndex].reset(new Socket());
|
_apRtpSock[trackIndex].reset(new Socket());
|
||||||
if (!_apUdpSock[trackIndex]->bindUdpSock(0, get_local_ip().data())) {
|
if (!_apRtpSock[trackIndex]->bindUdpSock(0, get_local_ip().data())) {
|
||||||
_apUdpSock[trackIndex].reset();
|
_apRtpSock[trackIndex].reset();
|
||||||
throw std::runtime_error("open udp sock err");
|
throw std::runtime_error("open rtp sock err");
|
||||||
}
|
}
|
||||||
int port = _apUdpSock[trackIndex]->get_local_port();
|
_apRtcpSock[trackIndex].reset(new Socket());
|
||||||
sendRtspRequest("SETUP",baseUrl,{"Transport",StrPrinter << "RTP/AVP;unicast;client_port=" << port << "-" << port + 1});
|
if (!_apRtcpSock[trackIndex]->bindUdpSock(0, get_local_ip().data())) {
|
||||||
|
_apRtcpSock[trackIndex].reset();
|
||||||
|
throw std::runtime_error("open rtcp sock err");
|
||||||
|
}
|
||||||
|
sendRtspRequest("SETUP",baseUrl,{"Transport",
|
||||||
|
StrPrinter << "RTP/AVP;unicast;client_port="
|
||||||
|
<< _apRtpSock[trackIndex]->get_local_port() << "-"
|
||||||
|
<< _apRtcpSock[trackIndex]->get_local_port()});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -290,30 +298,69 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
|
|||||||
}else{
|
}else{
|
||||||
const char *strPos = (_eType == Rtsp::RTP_MULTICAST ? "port=" : "server_port=") ;
|
const char *strPos = (_eType == Rtsp::RTP_MULTICAST ? "port=" : "server_port=") ;
|
||||||
auto port_str = FindField((strTransport + ";").data(), strPos, ";");
|
auto port_str = FindField((strTransport + ";").data(), strPos, ";");
|
||||||
uint16_t port = atoi(FindField(port_str.data(), NULL, "-").data());
|
uint16_t rtp_port = atoi(FindField(port_str.data(), NULL, "-").data());
|
||||||
auto &pUdpSockRef = _apUdpSock[uiTrackIndex];
|
uint16_t rtcp_port = atoi(FindField(port_str.data(), "-",NULL).data());
|
||||||
if(!pUdpSockRef){
|
auto &pRtpSockRef = _apRtpSock[uiTrackIndex];
|
||||||
pUdpSockRef.reset(new Socket());
|
auto &pRtcpSockRef = _apRtcpSock[uiTrackIndex];
|
||||||
}
|
|
||||||
|
|
||||||
if (_eType == Rtsp::RTP_MULTICAST) {
|
if (_eType == Rtsp::RTP_MULTICAST) {
|
||||||
|
//udp组播
|
||||||
auto multiAddr = FindField((strTransport + ";").data(), "destination=", ";");
|
auto multiAddr = FindField((strTransport + ";").data(), "destination=", ";");
|
||||||
if (!pUdpSockRef->bindUdpSock(port, "0.0.0.0")) {
|
pRtpSockRef.reset(new Socket());
|
||||||
pUdpSockRef.reset();
|
if (!pRtpSockRef->bindUdpSock(rtp_port, "0.0.0.0")) {
|
||||||
|
pRtpSockRef.reset();
|
||||||
throw std::runtime_error("open udp sock err");
|
throw std::runtime_error("open udp sock err");
|
||||||
}
|
}
|
||||||
auto fd = pUdpSockRef->rawFD();
|
auto fd = pRtpSockRef->rawFD();
|
||||||
if (-1 == SockUtil::joinMultiAddrFilter(fd, multiAddr.data(), get_peer_ip().data(),get_local_ip().data())) {
|
if (-1 == SockUtil::joinMultiAddrFilter(fd, multiAddr.data(), get_peer_ip().data(),get_local_ip().data())) {
|
||||||
SockUtil::joinMultiAddr(fd, multiAddr.data(),get_local_ip().data());
|
SockUtil::joinMultiAddr(fd, multiAddr.data(),get_local_ip().data());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//udp单播
|
||||||
struct sockaddr_in rtpto;
|
struct sockaddr_in rtpto;
|
||||||
rtpto.sin_port = ntohs(port);
|
rtpto.sin_port = ntohs(rtp_port);
|
||||||
rtpto.sin_family = AF_INET;
|
rtpto.sin_family = AF_INET;
|
||||||
rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
||||||
pUdpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto));
|
pRtpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto));
|
||||||
pUdpSockRef->send("\xce\xfa\xed\xfe", 4);
|
//发送rtp打洞包
|
||||||
|
pRtpSockRef->send("\xce\xfa\xed\xfe", 4);
|
||||||
|
|
||||||
|
//设置rtcp发送目标,为后续发送rtcp做准备
|
||||||
|
rtpto.sin_port = ntohs(rtcp_port);
|
||||||
|
rtpto.sin_family = AF_INET;
|
||||||
|
rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data());
|
||||||
|
pRtcpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto srcIP = inet_addr(get_peer_ip().data());
|
||||||
|
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
||||||
|
//设置rtp over udp接收回调处理函数
|
||||||
|
pRtpSockRef->setOnRead([srcIP, uiTrackIndex, weakSelf](const Buffer::Ptr &buf, struct sockaddr *addr) {
|
||||||
|
auto strongSelf = weakSelf.lock();
|
||||||
|
if (!strongSelf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (((struct sockaddr_in *) addr)->sin_addr.s_addr != srcIP) {
|
||||||
|
WarnL << "收到其他地址的rtp数据:" << inet_ntoa(((struct sockaddr_in *) addr)->sin_addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strongSelf->handleOneRtp(uiTrackIndex, strongSelf->_aTrackInfo[uiTrackIndex], (unsigned char *) buf->data(), buf->size());
|
||||||
|
});
|
||||||
|
|
||||||
|
if(pRtcpSockRef) {
|
||||||
|
//设置rtcp over udp接收回调处理函数
|
||||||
|
pRtcpSockRef->setOnRead([srcIP, uiTrackIndex, weakSelf](const Buffer::Ptr &buf, struct sockaddr *addr) {
|
||||||
|
auto strongSelf = weakSelf.lock();
|
||||||
|
if (!strongSelf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (((struct sockaddr_in *) addr)->sin_addr.s_addr != srcIP) {
|
||||||
|
WarnL << "收到其他地址的rtcp数据:" << inet_ntoa(((struct sockaddr_in *) addr)->sin_addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strongSelf->onRecvRtcp(uiTrackIndex, strongSelf->_aTrackInfo[uiTrackIndex], (unsigned char *) buf->data(), buf->size());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uiTrackIndex < _aTrackInfo.size() - 1) {
|
if (uiTrackIndex < _aTrackInfo.size() - 1) {
|
||||||
@ -321,41 +368,19 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
|
|||||||
sendSetup(uiTrackIndex + 1);
|
sendSetup(uiTrackIndex + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//所有setup命令发送完毕
|
||||||
|
//设置心跳包发送定时器
|
||||||
|
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
||||||
|
_pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as<int>() / 1000.0, [weakSelf](){
|
||||||
|
auto strongSelf = weakSelf.lock();
|
||||||
|
if (!strongSelf){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strongSelf->sendRtcpPacket();
|
||||||
|
return true;
|
||||||
|
},getPoller()));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < _aTrackInfo.size() && _eType != Rtsp::RTP_TCP; i++) {
|
//发送play命令
|
||||||
auto &pUdpSockRef = _apUdpSock[i];
|
|
||||||
if(!pUdpSockRef){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto srcIP = inet_addr(get_peer_ip().data());
|
|
||||||
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
|
||||||
pUdpSockRef->setOnRead([srcIP,i,weakSelf](const Buffer::Ptr &buf, struct sockaddr *addr) {
|
|
||||||
auto strongSelf=weakSelf.lock();
|
|
||||||
if(!strongSelf) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(((struct sockaddr_in *)addr)->sin_addr.s_addr != srcIP) {
|
|
||||||
WarnL << "收到其他地址的UDP数据:" << inet_ntoa(((struct sockaddr_in *) addr)->sin_addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strongSelf->handleOneRtp(i,strongSelf->_aTrackInfo[i],(unsigned char *)buf->data(),buf->size());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/////////////////////////心跳/////////////////////////////////
|
|
||||||
//有些设备在rtp over tcp的情况下也需要定时发送心跳包(比较坑爹)
|
|
||||||
//if(_eType != Rtsp::RTP_TCP)
|
|
||||||
{
|
|
||||||
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
|
|
||||||
_pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as<int>() / 1000.0, [weakSelf](){
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if (!strongSelf){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
strongSelf->sendOptions();
|
|
||||||
return true;
|
|
||||||
},getPoller()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pause(false);
|
pause(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,14 +474,27 @@ void RtspPlayer::onWholeRtspPacket(Parser &parser) {
|
|||||||
void RtspPlayer::onRtpPacket(const char *data, uint64_t len) {
|
void RtspPlayer::onRtpPacket(const char *data, uint64_t len) {
|
||||||
int trackIdx = -1;
|
int trackIdx = -1;
|
||||||
uint8_t interleaved = data[1];
|
uint8_t interleaved = data[1];
|
||||||
if(interleaved %2 ==0){
|
if(interleaved %2 == 0){
|
||||||
trackIdx = getTrackIndexByInterleaved(interleaved);
|
trackIdx = getTrackIndexByInterleaved(interleaved);
|
||||||
}
|
if (trackIdx != -1) {
|
||||||
if (trackIdx != -1) {
|
handleOneRtp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4);
|
||||||
handleOneRtp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4);
|
}
|
||||||
|
}else{
|
||||||
|
trackIdx = getTrackIndexByInterleaved(interleaved - 1);
|
||||||
|
if (trackIdx != -1) {
|
||||||
|
onRecvRtcp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtspPlayer::onRecvRtcp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtspPlayer::sendRtcpPacket(){
|
||||||
|
//目前只实现了通过options命令实现心跳包
|
||||||
|
sendOptions();
|
||||||
|
}
|
||||||
|
|
||||||
void RtspPlayer::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx){
|
void RtspPlayer::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx){
|
||||||
//统计丢包率
|
//统计丢包率
|
||||||
|
@ -84,13 +84,28 @@ protected:
|
|||||||
* @param trackidx track索引
|
* @param trackidx track索引
|
||||||
*/
|
*/
|
||||||
void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override;
|
void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收到RTCP包回调
|
||||||
|
* @param iTrackidx
|
||||||
|
* @param track
|
||||||
|
* @param pucData
|
||||||
|
* @param uiLen
|
||||||
|
*/
|
||||||
|
virtual void onRecvRtcp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送rtcp包维持心跳
|
||||||
|
*/
|
||||||
|
virtual void sendRtcpPacket();
|
||||||
private:
|
private:
|
||||||
void onRecvRTP_l(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track);
|
void onRecvRTP_l(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track);
|
||||||
void onPlayResult_l(const SockException &ex);
|
void onPlayResult_l(const SockException &ex);
|
||||||
|
|
||||||
int getTrackIndexByControlSuffix(const string &controlSuffix) const;
|
int getTrackIndexByControlSuffix(const string &controlSuffix) const;
|
||||||
int getTrackIndexByInterleaved(int interleaved) const;
|
int getTrackIndexByInterleaved(int interleaved) const;
|
||||||
int getTrackIndexByTrackType(TrackType trackId) const;
|
int getTrackIndexByTrackType(TrackType trackType) const;
|
||||||
|
|
||||||
void play(const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType);
|
void play(const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType);
|
||||||
void onConnect(const SockException &err) override;
|
void onConnect(const SockException &err) override;
|
||||||
@ -115,8 +130,10 @@ private:
|
|||||||
SdpAttr _sdpAttr;
|
SdpAttr _sdpAttr;
|
||||||
vector<SdpTrack::Ptr> _aTrackInfo;
|
vector<SdpTrack::Ptr> _aTrackInfo;
|
||||||
function<void(const Parser&)> _onHandshake;
|
function<void(const Parser&)> _onHandshake;
|
||||||
Socket::Ptr _apUdpSock[2];
|
Socket::Ptr _apRtpSock[2]; //RTP端口,trackid idx 为数组下标
|
||||||
//rtsp鉴权相关
|
Socket::Ptr _apRtcpSock[2];//RTCP端口,trackid idx 为数组下标
|
||||||
|
|
||||||
|
//rtsp鉴权相关
|
||||||
string _rtspMd5Nonce;
|
string _rtspMd5Nonce;
|
||||||
string _rtspRealm;
|
string _rtspRealm;
|
||||||
//rtsp info
|
//rtsp info
|
||||||
|
Loading…
Reference in New Issue
Block a user