From 9fa6e9d8d9f75651fb7224a291d21237c3ec90e8 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 14 Jan 2020 10:04:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0dts=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=AE=97=E6=B3=95=EF=BC=8C=E5=85=BC=E5=AE=B9=E5=90=ABB?= =?UTF-8?q?=E5=B8=A7=E7=9A=84rtsp=E6=8E=A8=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Device.cpp | 20 ++++++------- src/Common/Stamp.cpp | 57 +++++++++++++++++++++++++++++++++++--- src/Common/Stamp.h | 24 +++++++++++++++- src/Extension/AACRtmp.cpp | 2 +- src/Extension/AACRtp.cpp | 2 +- src/Extension/Frame.h | 7 ----- src/Extension/H264.h | 38 ++++++++++++------------- src/Extension/H264Rtmp.cpp | 16 +++++------ src/Extension/H264Rtp.cpp | 42 +++++++++++++++------------- src/Extension/H264Rtp.h | 2 ++ src/Extension/H265.h | 46 +++++++++++++++--------------- src/Extension/H265Rtp.cpp | 38 +++++++++++++------------ src/Extension/H265Rtp.h | 2 ++ src/Player/PlayerProxy.cpp | 2 +- 14 files changed, 187 insertions(+), 111 deletions(-) diff --git a/src/Common/Device.cpp b/src/Common/Device.cpp index 39a76825..58fd53cb 100644 --- a/src/Common/Device.cpp +++ b/src/Common/Device.cpp @@ -106,11 +106,11 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32 } H264Frame::Ptr frame = std::make_shared(); - frame->timeStamp = dts; - frame->ptsStamp = pts; - frame->buffer.assign("\x00\x00\x00\x01",4); - frame->buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); - frame->iPrefixSize = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01",4); + frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); + frame->_prefix_size = 4; inputFrame(frame); } @@ -131,11 +131,11 @@ void DevChannel::inputH265(const char* pcData, int iDataLen, uint32_t dts,uint32 } H265Frame::Ptr frame = std::make_shared(); - frame->timeStamp = dts; - frame->ptsStamp = pts; - frame->buffer.assign("\x00\x00\x00\x01",4); - frame->buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); - frame->iPrefixSize = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01",4); + frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); + frame->_prefix_size = 4; inputFrame(frame); } diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index e01887e3..3a0ed5bf 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -42,13 +42,14 @@ int64_t DeltaStamp::deltaStamp(int64_t stamp) { } int64_t ret = stamp - _last_stamp; - if(ABS(ret) < MAX_DELTA_STAMP){ - //时间戳变化不明显 + if(ret >= 0){ + //时间戳增量为正,返回之 _last_stamp = stamp; - return ret; + //在直播情况下,时间戳增量不得大于MAX_DELTA_STAMP + return ret < MAX_DELTA_STAMP ? ret : (_playback ? ret : 0); } - //时间戳变化太明显,可能回环了或者seek了 + //时间戳增量为负,说明时间戳回环了或回退了 _last_stamp = stamp; return _playback ? ret : 0; } @@ -99,4 +100,52 @@ int64_t Stamp::getRelativeStamp() const { } +bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){ + bool ret = false; + if(pts == _last_pts){ + //pts未变,返回上次结果 + if(_last_dts){ + dts = _last_dts; + ret = true; + } + return ret; + } + + ret = getDts_l(pts,dts); + if(ret){ + //保存本次结果 + _last_dts = dts; + } + //记录上次pts + _last_pts = pts; + return ret; +} + +bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){ + if(pts > _last_max_pts){ + if(!_sorter_max_size && _frames_since_last_max_pts && _count_sorter_max_size++ > 0){ + _sorter_max_size = _frames_since_last_max_pts; + _dts_pts_offset = (pts - _last_max_pts) / 2; + InfoL << _sorter_max_size << " " << _dts_pts_offset; + } + _frames_since_last_max_pts = 0; + _last_max_pts = pts; + } + + _pts_sorter.emplace(pts); + ++_frames_since_last_max_pts; + + if(_sorter_max_size && _pts_sorter.size() > _sorter_max_size){ + auto it = _pts_sorter.begin(); + dts = *it + _dts_pts_offset; + if(dts > pts){ + //dts不能大于pts(基本不可能到达这个逻辑) + dts = pts; + } + _pts_sorter.erase(it); + return true; + } + return false; +} + }//namespace mediakit \ No newline at end of file diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index 09e77338..43d11159 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -27,8 +27,9 @@ #ifndef ZLMEDIAKIT_STAMP_H #define ZLMEDIAKIT_STAMP_H -#include "Util/TimeTicker.h" +#include #include +#include "Util/TimeTicker.h" using namespace toolkit; namespace mediakit { @@ -88,6 +89,27 @@ private: SmoothTicker _ticker; }; + +class DtsGenerator{ +public: + DtsGenerator() = default; + ~DtsGenerator() = default; + bool getDts(uint32_t pts, uint32_t &dts); +private: + bool getDts_l(uint32_t pts, uint32_t &dts); +private: + uint32_t _dts_pts_offset = 0; + uint32_t _last_dts = 0; + uint32_t _last_pts = 0; + uint32_t _last_max_pts = 0; + int _frames_since_last_max_pts = 0; + int _sorter_max_size = 0; + int _count_sorter_max_size = 0; + set _pts_sorter; + + +}; + }//namespace mediakit #endif //ZLMEDIAKIT_STAMP_H diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index 71ea9e66..c3efddb1 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -102,7 +102,7 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { rtmpPkt->bodySize = rtmpPkt->strBuf.size(); rtmpPkt->chunkId = CHUNK_AUDIO; rtmpPkt->streamId = STREAM_MEDIA; - rtmpPkt->timeStamp = frame->stamp(); + rtmpPkt->timeStamp = frame->dts(); rtmpPkt->typeId = MSG_AUDIO; RtmpCodec::inputRtmp(rtmpPkt, false); } diff --git a/src/Extension/AACRtp.cpp b/src/Extension/AACRtp.cpp index 7b436fb0..a84c22be 100644 --- a/src/Extension/AACRtp.cpp +++ b/src/Extension/AACRtp.cpp @@ -41,7 +41,7 @@ AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc, void AACRtpEncoder::inputFrame(const Frame::Ptr &frame) { GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS); - auto uiStamp = frame->stamp(); + auto uiStamp = frame->dts(); auto pcData = frame->data() + frame->prefixSize(); auto iLen = frame->size() - frame->prefixSize(); diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index 5e5121f9..d4cbca6b 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -81,13 +81,6 @@ class Frame : public Buffer, public CodecInfo { public: typedef std::shared_ptr Ptr; virtual ~Frame(){} - /** - * 时间戳,已经废弃,请使用dts() 、pts()接口 - */ - inline uint32_t stamp() const { - return dts(); - }; - /** * 返回解码时间戳,单位毫秒 diff --git a/src/Extension/H264.h b/src/Extension/H264.h index 3ffb058d..b4c71a6b 100644 --- a/src/Extension/H264.h +++ b/src/Extension/H264.h @@ -53,21 +53,21 @@ public: } NalType; char *data() const override{ - return (char *)buffer.data(); + return (char *)_buffer.data(); } uint32_t size() const override { - return buffer.size(); + return _buffer.size(); } uint32_t dts() const override { - return timeStamp; + return _dts; } uint32_t pts() const override { - return ptsStamp ? ptsStamp : timeStamp; + return _pts ? _pts : _dts; } uint32_t prefixSize() const override{ - return iPrefixSize; + return _prefix_size; } TrackType getTrackType() const override{ @@ -79,11 +79,11 @@ public: } bool keyFrame() const override { - return H264_TYPE(buffer[iPrefixSize]) == H264Frame::NAL_IDR; + return H264_TYPE(_buffer[_prefix_size]) == H264Frame::NAL_IDR; } bool configFrame() const override{ - switch(H264_TYPE(buffer[iPrefixSize]) ){ + switch(H264_TYPE(_buffer[_prefix_size]) ){ case H264Frame::NAL_SPS: case H264Frame::NAL_PPS: return true; @@ -92,10 +92,10 @@ public: } } public: - uint32_t timeStamp; - uint32_t ptsStamp = 0; - string buffer; - uint32_t iPrefixSize = 4; + uint32_t _dts = 0; + uint32_t _pts = 0; + uint32_t _prefix_size = 4; + string _buffer; }; @@ -340,19 +340,19 @@ private: if(!_sps.empty()){ auto spsFrame = std::make_shared(); - spsFrame->iPrefixSize = 4; - spsFrame->buffer.assign("\x0\x0\x0\x1",4); - spsFrame->buffer.append(_sps); - spsFrame->timeStamp = frame->stamp(); + spsFrame->_prefix_size = 4; + spsFrame->_buffer.assign("\x0\x0\x0\x1",4); + spsFrame->_buffer.append(_sps); + spsFrame->_dts = frame->dts(); VideoTrack::inputFrame(spsFrame); } if(!_pps.empty()){ auto ppsFrame = std::make_shared(); - ppsFrame->iPrefixSize = 4; - ppsFrame->buffer.assign("\x0\x0\x0\x1",4); - ppsFrame->buffer.append(_pps); - ppsFrame->timeStamp = frame->stamp(); + ppsFrame->_prefix_size = 4; + ppsFrame->_buffer.assign("\x0\x0\x0\x1",4); + ppsFrame->_buffer.append(_pps); + ppsFrame->_dts = frame->dts(); VideoTrack::inputFrame(ppsFrame); } } diff --git a/src/Extension/H264Rtmp.cpp b/src/Extension/H264Rtmp.cpp index 9ee877e7..c995317f 100644 --- a/src/Extension/H264Rtmp.cpp +++ b/src/Extension/H264Rtmp.cpp @@ -35,8 +35,8 @@ H264RtmpDecoder::H264RtmpDecoder() { H264Frame::Ptr H264RtmpDecoder::obtainFrame() { //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 auto frame = obtainObj(); - frame->buffer.clear(); - frame->iPrefixSize = 4; + frame->_buffer.clear(); + frame->_prefix_size = 4; return frame; } @@ -78,10 +78,10 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) { inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t dts,uint32_t pts) { #if 1 - _h264frame->timeStamp = dts; - _h264frame->ptsStamp = pts; - _h264frame->buffer.assign("\x0\x0\x0\x1", 4); //添加264头 - _h264frame->buffer.append(pcData, iLen); + _h264frame->_dts = dts; + _h264frame->_pts = pts; + _h264frame->_buffer.assign("\x0\x0\x0\x1", 4); //添加264头 + _h264frame->_buffer.append(pcData, iLen); //写入环形缓存 RtmpCodec::inputFrame(_h264frame); @@ -144,7 +144,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { return; } - if(_lastPacket && _lastPacket->timeStamp != frame->stamp()) { + if(_lastPacket && _lastPacket->timeStamp != frame->dts()) { RtmpCodec::inputRtmp(_lastPacket, _lastPacket->isVideoKeyFrame()); _lastPacket = nullptr; } @@ -165,7 +165,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { _lastPacket->chunkId = CHUNK_VIDEO; _lastPacket->streamId = STREAM_MEDIA; - _lastPacket->timeStamp = frame->stamp(); + _lastPacket->timeStamp = frame->dts(); _lastPacket->typeId = MSG_VIDEO; } diff --git a/src/Extension/H264Rtp.cpp b/src/Extension/H264Rtp.cpp index c9861f16..f90f3c56 100644 --- a/src/Extension/H264Rtp.cpp +++ b/src/Extension/H264Rtp.cpp @@ -70,8 +70,8 @@ H264RtpDecoder::H264RtpDecoder() { H264Frame::Ptr H264RtpDecoder::obtainFrame() { //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 auto frame = ResourcePoolHelper::obtainObj(); - frame->buffer.clear(); - frame->iPrefixSize = 4; + frame->_buffer.clear(); + frame->_prefix_size = 4; return frame; } @@ -113,9 +113,9 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { if (nal.type >= 0 && nal.type < 24) { //a full frame - _h264frame->buffer.assign("\x0\x0\x0\x1", 4); - _h264frame->buffer.append((char *)frame, length); - _h264frame->timeStamp = rtppack->timeStamp; + _h264frame->_buffer.assign("\x0\x0\x0\x1", 4); + _h264frame->_buffer.append((char *)frame, length); + _h264frame->_pts = rtppack->timeStamp; auto key = _h264frame->keyFrame(); onGetH264(_h264frame); return (key); //i frame @@ -142,9 +142,9 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { //过小的帧丢弃 NALU nal; MakeNalu(ptr[0], nal); - _h264frame->buffer.assign("\x0\x0\x0\x1", 4); - _h264frame->buffer.append((char *)ptr, len); - _h264frame->timeStamp = rtppack->timeStamp; + _h264frame->_buffer.assign("\x0\x0\x0\x1", 4); + _h264frame->_buffer.append((char *)ptr, len); + _h264frame->_pts = rtppack->timeStamp; if(nal.type == H264Frame::NAL_IDR){ haveIDR = true; } @@ -162,10 +162,10 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { if (fu.S) { //该帧的第一个rtp包 FU-A start char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type); - _h264frame->buffer.assign("\x0\x0\x0\x1", 4); - _h264frame->buffer.push_back(tmp); - _h264frame->buffer.append((char *)frame + 2, length - 2); - _h264frame->timeStamp = rtppack->timeStamp; + _h264frame->_buffer.assign("\x0\x0\x0\x1", 4); + _h264frame->_buffer.push_back(tmp); + _h264frame->_buffer.append((char *)frame + 2, length - 2); + _h264frame->_pts = rtppack->timeStamp; //该函数return时,保存下当前sequence,以便下次对比seq是否连续 _lastSeq = rtppack->sequence; return _h264frame->keyFrame(); @@ -173,22 +173,22 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { if (rtppack->sequence != _lastSeq + 1 && rtppack->sequence != 0) { //中间的或末尾的rtp包,其seq必须连续(如果回环了则判定为连续),否则说明rtp丢包,那么该帧不完整,必须得丢弃 - _h264frame->buffer.clear(); + _h264frame->_buffer.clear(); WarnL << "rtp sequence不连续: " << rtppack->sequence << " != " << _lastSeq << " + 1,该帧被废弃"; return false; } if (!fu.E) { //该帧的中间rtp包 FU-A mid - _h264frame->buffer.append((char *)frame + 2, length - 2); + _h264frame->_buffer.append((char *)frame + 2, length - 2); //该函数return时,保存下当前sequence,以便下次对比seq是否连续 _lastSeq = rtppack->sequence; return false; } //该帧最后一个rtp包 FU-A end - _h264frame->buffer.append((char *)frame + 2, length - 2); - _h264frame->timeStamp = rtppack->timeStamp; + _h264frame->_buffer.append((char *)frame + 2, length - 2); + _h264frame->_pts = rtppack->timeStamp; auto key = _h264frame->keyFrame(); onGetH264(_h264frame); return key; @@ -209,8 +209,12 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { } void H264RtpDecoder::onGetH264(const H264Frame::Ptr &frame) { - //写入环形缓存 - RtpCodec::inputFrame(frame); + //根据pts计算dts + auto flag = _dts_generator.getDts(frame->_pts,frame->_dts); + if(flag){ + //写入环形缓存 + RtpCodec::inputFrame(frame); + } _h264frame = obtainFrame(); } @@ -232,7 +236,7 @@ H264RtpEncoder::H264RtpEncoder(uint32_t ui32Ssrc, void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) { GET_CONFIG(uint32_t,cycleMS,Rtp::kCycleMS); auto pcData = frame->data() + frame->prefixSize(); - auto uiStamp = frame->stamp(); + auto uiStamp = frame->pts(); auto iLen = frame->size() - frame->prefixSize(); //获取NALU的5bit 帧类型 unsigned char naluType = H264_TYPE(pcData[0]); diff --git a/src/Extension/H264Rtp.h b/src/Extension/H264Rtp.h index 5ccac81d..da4aa2d6 100644 --- a/src/Extension/H264Rtp.h +++ b/src/Extension/H264Rtp.h @@ -30,6 +30,7 @@ #include "Rtsp/RtpCodec.h" #include "Util/ResourcePool.h" #include "Extension/H264.h" +#include "Common/Stamp.h" using namespace toolkit; namespace mediakit{ @@ -66,6 +67,7 @@ private: H264Frame::Ptr obtainFrame(); private: H264Frame::Ptr _h264frame; + DtsGenerator _dts_generator; int _lastSeq = 0; }; diff --git a/src/Extension/H265.h b/src/Extension/H265.h index 021ef3d1..80591e32 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -74,23 +74,23 @@ public: } NaleType; char *data() const override { - return (char *) buffer.data(); + return (char *) _buffer.data(); } uint32_t size() const override { - return buffer.size(); + return _buffer.size(); } uint32_t dts() const override { - return timeStamp; + return _dts; } uint32_t pts() const override { - return ptsStamp ? ptsStamp : timeStamp; + return _pts ? _pts : _dts; } uint32_t prefixSize() const override { - return iPrefixSize; + return _prefix_size; } TrackType getTrackType() const override { @@ -102,11 +102,11 @@ public: } bool keyFrame() const override { - return isKeyFrame(H265_TYPE(buffer[iPrefixSize])); + return isKeyFrame(H265_TYPE(_buffer[_prefix_size])); } bool configFrame() const override{ - switch(H265_TYPE(buffer[iPrefixSize])){ + switch(H265_TYPE(_buffer[_prefix_size])){ case H265Frame::NAL_VPS: case H265Frame::NAL_SPS: case H265Frame::NAL_PPS: @@ -131,10 +131,10 @@ public: } public: - uint32_t timeStamp; - uint32_t ptsStamp = 0; - string buffer; - uint32_t iPrefixSize = 4; + uint32_t _dts = 0; + uint32_t _pts = 0; + uint32_t _prefix_size = 4; + string _buffer; }; @@ -356,27 +356,27 @@ private: } if(!_vps.empty()){ auto vpsFrame = std::make_shared(); - vpsFrame->iPrefixSize = 4; - vpsFrame->buffer.assign("\x0\x0\x0\x1", 4); - vpsFrame->buffer.append(_vps); - vpsFrame->timeStamp = frame->stamp(); + vpsFrame->_prefix_size = 4; + vpsFrame->_buffer.assign("\x0\x0\x0\x1", 4); + vpsFrame->_buffer.append(_vps); + vpsFrame->_dts = frame->dts(); VideoTrack::inputFrame(vpsFrame); } if (!_sps.empty()) { auto spsFrame = std::make_shared(); - spsFrame->iPrefixSize = 4; - spsFrame->buffer.assign("\x0\x0\x0\x1", 4); - spsFrame->buffer.append(_sps); - spsFrame->timeStamp = frame->stamp(); + spsFrame->_prefix_size = 4; + spsFrame->_buffer.assign("\x0\x0\x0\x1", 4); + spsFrame->_buffer.append(_sps); + spsFrame->_dts = frame->dts(); VideoTrack::inputFrame(spsFrame); } if (!_pps.empty()) { auto ppsFrame = std::make_shared(); - ppsFrame->iPrefixSize = 4; - ppsFrame->buffer.assign("\x0\x0\x0\x1", 4); - ppsFrame->buffer.append(_pps); - ppsFrame->timeStamp = frame->stamp(); + ppsFrame->_prefix_size = 4; + ppsFrame->_buffer.assign("\x0\x0\x0\x1", 4); + ppsFrame->_buffer.append(_pps); + ppsFrame->_dts = frame->dts(); VideoTrack::inputFrame(ppsFrame); } } diff --git a/src/Extension/H265Rtp.cpp b/src/Extension/H265Rtp.cpp index 6d164dde..4b8df94c 100644 --- a/src/Extension/H265Rtp.cpp +++ b/src/Extension/H265Rtp.cpp @@ -70,8 +70,8 @@ H265RtpDecoder::H265RtpDecoder() { H265Frame::Ptr H265RtpDecoder::obtainFrame() { //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 auto frame = ResourcePoolHelper::obtainObj(); - frame->buffer.clear(); - frame->iPrefixSize = 4; + frame->_buffer.clear(); + frame->_prefix_size = 4; return frame; } @@ -99,11 +99,11 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { MakeFU(frame[2], fu); if (fu.S) { //该帧的第一个rtp包 - _h265frame->buffer.assign("\x0\x0\x0\x1", 4); - _h265frame->buffer.push_back(fu.type << 1); - _h265frame->buffer.push_back(0x01); - _h265frame->buffer.append((char *) frame + 3, length - 3); - _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->_buffer.assign("\x0\x0\x0\x1", 4); + _h265frame->_buffer.push_back(fu.type << 1); + _h265frame->_buffer.push_back(0x01); + _h265frame->_buffer.append((char *) frame + 3, length - 3); + _h265frame->_pts = rtppack->timeStamp; //该函数return时,保存下当前sequence,以便下次对比seq是否连续 _lastSeq = rtppack->sequence; return (_h265frame->keyFrame()); //i frame @@ -111,22 +111,22 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { if (rtppack->sequence != _lastSeq + 1 && rtppack->sequence != 0) { //中间的或末尾的rtp包,其seq必须连续(如果回环了则判定为连续),否则说明rtp丢包,那么该帧不完整,必须得丢弃 - _h265frame->buffer.clear(); + _h265frame->_buffer.clear(); WarnL << "rtp sequence不连续: " << rtppack->sequence << " != " << _lastSeq << " + 1,该帧被废弃"; return false; } if (!fu.E) { //该帧的中间rtp包 - _h265frame->buffer.append((char *) frame + 3, length - 3); + _h265frame->_buffer.append((char *) frame + 3, length - 3); //该函数return时,保存下当前sequence,以便下次对比seq是否连续 _lastSeq = rtppack->sequence; return false; } //该帧最后一个rtp包 - _h265frame->buffer.append((char *) frame + 3, length - 3); - _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->_buffer.append((char *) frame + 3, length - 3); + _h265frame->_pts = rtppack->timeStamp; auto key = _h265frame->keyFrame(); onGetH265(_h265frame); return key; @@ -134,9 +134,9 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { default: // 4.4.1. Single NAL Unit Packets (p24) //a full frame - _h265frame->buffer.assign("\x0\x0\x0\x1", 4); - _h265frame->buffer.append((char *)frame, length); - _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->_buffer.assign("\x0\x0\x0\x1", 4); + _h265frame->_buffer.append((char *)frame, length); + _h265frame->_pts = rtppack->timeStamp; auto key = _h265frame->keyFrame(); onGetH265(_h265frame); return key; @@ -144,8 +144,12 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { } void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) { - //写入环形缓存 - RtpCodec::inputFrame(frame); + //计算dts + auto flag = _dts_generator.getDts(frame->_pts,frame->_dts); + if(flag){ + //写入环形缓存 + RtpCodec::inputFrame(frame); + } _h265frame = obtainFrame(); } @@ -167,7 +171,7 @@ H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc, void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) { GET_CONFIG(uint32_t,cycleMS,Rtp::kCycleMS); uint8_t *pcData = (uint8_t*)frame->data() + frame->prefixSize(); - auto uiStamp = frame->stamp(); + auto uiStamp = frame->pts(); auto iLen = frame->size() - frame->prefixSize(); unsigned char naluType = H265_TYPE(pcData[0]); //获取NALU的5bit 帧类型 uiStamp %= cycleMS; diff --git a/src/Extension/H265Rtp.h b/src/Extension/H265Rtp.h index 8b51f880..a2844092 100644 --- a/src/Extension/H265Rtp.h +++ b/src/Extension/H265Rtp.h @@ -30,6 +30,7 @@ #include "Rtsp/RtpCodec.h" #include "Util/ResourcePool.h" #include "Extension/H265.h" +#include "Common/Stamp.h" using namespace toolkit; @@ -67,6 +68,7 @@ private: H265Frame::Ptr obtainFrame(); private: H265Frame::Ptr _h265frame; + DtsGenerator _dts_generator; int _lastSeq = 0; }; diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 250ea932..6b5fca6e 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -219,7 +219,7 @@ public: virtual ~MuteAudioMaker(){} void inputFrame(const Frame::Ptr &frame) override { if(frame->getTrackType() == TrackVideo){ - auto iAudioIndex = frame->stamp() / MUTE_ADTS_DATA_MS; + auto iAudioIndex = frame->dts() / MUTE_ADTS_DATA_MS; if(_iAudioIndex != iAudioIndex){ _iAudioIndex = iAudioIndex; auto aacFrame = std::make_shared((char *)MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS);