ZLMediaKit/src/Rtsp/RtpReceiver.cpp

170 lines
5.8 KiB
C++
Raw Normal View History

2018-12-14 17:46:12 +08:00
/*
* MIT License
*
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Common/config.h"
#include "RtpReceiver.h"
#define POP_HEAD(trackidx) \
auto it = _amapRtpSort[trackidx].begin(); \
onRtpSorted(it->second, trackidx); \
_amapRtpSort[trackidx].erase(it);
# define AV_RB16(x) \
((((const uint8_t*)(x))[0] << 8) | \
((const uint8_t*)(x))[1])
namespace mediakit {
RtpReceiver::RtpReceiver() {}
RtpReceiver::~RtpReceiver() {}
bool RtpReceiver::handleOneRtp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen) {
auto pt_ptr=_pktPool.obtain();
auto &rtppt=*pt_ptr;
rtppt.interleaved = track->_interleaved;
rtppt.length = uiLen + 4;
rtppt.mark = pucData[1] >> 7;
rtppt.PT = pucData[1] & 0x7F;
//序列号
memcpy(&rtppt.sequence,pucData+2,2);//内存对齐
rtppt.sequence = ntohs(rtppt.sequence);
//时间戳
memcpy(&rtppt.timeStamp, pucData+4, 4);//内存对齐
2018-12-14 18:24:27 +08:00
if(!track->_samplerate){
return false;
}
2018-12-14 17:46:12 +08:00
//时间戳转换成毫秒
2018-12-25 09:30:49 +08:00
rtppt.timeStamp = ntohl(rtppt.timeStamp) * 1000LL / track->_samplerate;
2018-12-14 17:46:12 +08:00
//ssrc
memcpy(&rtppt.ssrc,pucData+8,4);//内存对齐
rtppt.ssrc = ntohl(rtppt.ssrc);
rtppt.type = track->_type;
if (track->_ssrc == 0) {
track->_ssrc = rtppt.ssrc;
//保存SSRC
} else if (track->_ssrc != rtppt.ssrc) {
//ssrc错误
2019-04-11 22:35:37 +08:00
WarnL << "ssrc错误:" << rtppt.ssrc << " != " << track->_ssrc;
2018-12-14 17:46:12 +08:00
if (_aui32SsrcErrorCnt[iTrackidx]++ > 10) {
2019-04-11 22:35:37 +08:00
//ssrc切换后清除老数据
WarnL << "ssrc更换:" << track->_ssrc << " -> " << rtppt.ssrc;
_amapRtpSort[iTrackidx].clear();
2018-12-14 17:46:12 +08:00
track->_ssrc = rtppt.ssrc;
}
return false;
}
_aui32SsrcErrorCnt[iTrackidx] = 0;
rtppt.payload[0] = '$';
rtppt.payload[1] = rtppt.interleaved;
rtppt.payload[2] = uiLen >> 8;
2018-12-14 17:46:12 +08:00
rtppt.payload[3] = (uiLen & 0x00FF);
rtppt.offset = 16;
int csrc = pucData[0] & 0x0f;
int ext = pucData[0] & 0x10;
rtppt.offset += 4 * csrc;
if (ext) {
if(uiLen < rtppt.offset){
return false;
}
/* calculate the header extension length (stored as number of 32-bit words) */
ext = (AV_RB16(pucData + rtppt.offset - 2) + 1) << 2;
rtppt.offset += ext;
}
2019-04-24 11:40:54 +08:00
2019-04-24 09:25:08 +08:00
if(rtppt.length - rtppt.offset <= 0){
2019-04-24 11:40:54 +08:00
WarnL << "无有效负载的rtp包:" << rtppt.length << "<=" << (int)rtppt.offset;
return false;
}
if(uiLen > sizeof(rtppt.payload) - 4){
WarnL << "超长的rtp包:" << uiLen << ">" << sizeof(rtppt.payload) - 4;
2019-04-24 09:25:08 +08:00
return false;
}
2018-12-14 17:46:12 +08:00
memcpy(rtppt.payload + 4, pucData, uiLen);
/////////////////////////////////RTP排序逻辑///////////////////////////////////
if(rtppt.sequence != _aui16LastSeq[iTrackidx] + 1 && _aui16LastSeq[iTrackidx] != 0){
2018-12-14 17:46:12 +08:00
//包乱序或丢包
_aui32SeqOkCnt[iTrackidx] = 0;
2018-12-14 17:46:12 +08:00
_abSortStarted[iTrackidx] = true;
2019-04-11 22:35:37 +08:00
// WarnL << "包乱序或丢包:" << iTrackidx <<" " << rtppt.sequence << " " << _aui16LastSeq[iTrackidx];
if(_aui16LastSeq[iTrackidx] > rtppt.sequence && _aui16LastSeq[iTrackidx] - rtppt.sequence > 0x7FFF){
//sequence回环清空所有排序缓存
while (_amapRtpSort[iTrackidx].size()) {
POP_HEAD(iTrackidx)
}
}
2018-12-14 17:46:12 +08:00
}else{
//正确序列的包
_aui32SeqOkCnt[iTrackidx]++;
2018-12-14 17:46:12 +08:00
}
_aui16LastSeq[iTrackidx] = rtppt.sequence;
//开始排序缓存
if (_abSortStarted[iTrackidx]) {
_amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr);
GET_CONFIG_AND_REGISTER(uint32_t,clearCount,Rtp::kClearCount);
GET_CONFIG_AND_REGISTER(uint32_t,maxRtpCount,Rtp::kMaxRtpCount);
if (_aui32SeqOkCnt[iTrackidx] >= clearCount) {
2018-12-14 17:46:12 +08:00
//网络环境改善,需要清空排序缓存
_aui32SeqOkCnt[iTrackidx] = 0;
2018-12-14 17:46:12 +08:00
_abSortStarted[iTrackidx] = false;
while (_amapRtpSort[iTrackidx].size()) {
POP_HEAD(iTrackidx)
}
} else if (_amapRtpSort[iTrackidx].size() >= maxRtpCount) {
//排序缓存溢出
POP_HEAD(iTrackidx)
}
}else{
//正确序列
onRtpSorted(pt_ptr, iTrackidx);
}
//////////////////////////////////////////////////////////////////////////////////
return true;
}
void RtpReceiver::clear() {
CLEAR_ARR(_aui16LastSeq)
CLEAR_ARR(_aui32SsrcErrorCnt)
CLEAR_ARR(_aui32SeqOkCnt)
2018-12-14 17:46:12 +08:00
CLEAR_ARR(_abSortStarted)
_amapRtpSort[0].clear();
_amapRtpSort[1].clear();
}
void RtpReceiver::setPoolSize(int size) {
_pktPool.setSize(size);
}
}//namespace mediakit