From 5f511eb2956bf47052807d1491b96db68fab0c2f Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Oct 2018 21:05:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=83=A8=E5=88=86265=20rtp?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Factory.cpp | 17 +++++++++- src/Extension/H265.h | 57 +++++++++++++++++++++++++++++++--- src/RtspMuxer/H265RtpCodec.cpp | 43 ++++++++++++------------- src/RtspMuxer/H265RtpCodec.h | 2 +- 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 45b2ceae..5c3f2f17 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -48,6 +48,19 @@ Sdp::Ptr Factory::getSdpByTrack(const Track::Ptr &track) { return std::make_shared(h264Track->getSps(),h264Track->getPps()); } + case CodecH265:{ + H265Track::Ptr h265Track = dynamic_pointer_cast(track); + if(!h265Track){ + WarnL << "该Track不是H265Track类型"; + return nullptr; + } + if(!h265Track->ready()){ + WarnL << "该Track未准备好"; + return nullptr; + } + return std::make_shared(h265Track->getSps(),h265Track->getPps()); + } + case CodecAAC:{ AACTrack::Ptr aacTrack = dynamic_pointer_cast(track); if(!aacTrack){ @@ -115,7 +128,9 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) { if (3 != sscanf(track->_fmtp.c_str(), "%d sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt, sprop_sps, sprop_pps)) { return std::make_shared(); } - return std::make_shared("",sprop_sps,sprop_pps,0,0,0); + auto sps = decodeBase64(sprop_sps); + auto pps = decodeBase64(sprop_pps); + return std::make_shared("",sps,pps,0,0,0); } diff --git a/src/Extension/H265.h b/src/Extension/H265.h index af2f754b..186b24a1 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -29,6 +29,7 @@ #include "Frame.h" #include "Track.h" +#include "RtspMuxer/RtspSdp.h" namespace mediakit { @@ -228,7 +229,7 @@ public: } bool ready() override { - return !_sps.empty() && !_pps.empty() && !_vps.empty(); + return !_sps.empty() && !_pps.empty(); } @@ -251,7 +252,7 @@ public: _vpsFrame = insertFrame; } _vpsFrame->timeStamp = frame->stamp(); - VideoTrack::inputFrame(_vpsFrame); + // VideoTrack::inputFrame(_vpsFrame); } if (!_sps.empty()) { if (!_spsFrame) { @@ -264,7 +265,7 @@ public: _spsFrame = insertFrame; } _spsFrame->timeStamp = frame->stamp(); - VideoTrack::inputFrame(_spsFrame); + // VideoTrack::inputFrame(_spsFrame); } if (!_pps.empty()) { @@ -278,7 +279,7 @@ public: _ppsFrame = insertFrame; } _ppsFrame->timeStamp = frame->stamp(); - VideoTrack::inputFrame(_ppsFrame); + //VideoTrack::inputFrame(_ppsFrame); } VideoTrack::inputFrame(frame); return; @@ -289,17 +290,20 @@ public: case H265Frame::NAL_VPS: { //vps _vps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + VideoTrack::inputFrame(frame); } break; case H265Frame::NAL_SPS: { //sps _sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + VideoTrack::inputFrame(frame); } break; case H265Frame::NAL_PPS: { //pps _pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + VideoTrack::inputFrame(frame); } break; @@ -341,6 +345,51 @@ private: }; +/** +* h265类型sdp +*/ +class H265Sdp : public Sdp { +public: + + /** + * + * @param sps 265 sps,不带0x00000001头 + * @param pps 265 pps,不带0x00000001头 + * @param playload_type rtp playload type 默认96 + * @param bitrate 比特率 + */ + H265Sdp(const string &strSPS, + const string &strPPS, + int playload_type = 96, + int bitrate = 4000) : Sdp(90000,playload_type) { + //视频通道 + _printer << "m=video 0 RTP/AVP " << playload_type << "\r\n"; + _printer << "b=AS:" << bitrate << "\r\n"; + _printer << "a=rtpmap:" << playload_type << " H265/" << 90000 << "\r\n"; + _printer << "a=fmtp:" << playload_type << " sprop-sps="; + _printer << encodeBase64(strSPS) << "; "; + _printer << "sprop-pps="; + _printer << encodeBase64(strPPS) << "\r\n"; + _printer << "a=control:trackID=" << getTrackType() << "\r\n"; + } + + string getSdp() const override { + return _printer; + } + + TrackType getTrackType() const override { + return TrackVideo; + } + + CodecId getCodecId() const override { + return CodecH265; + } +private: + _StrPrinter _printer; +}; + + + }//namespace mediakit diff --git a/src/RtspMuxer/H265RtpCodec.cpp b/src/RtspMuxer/H265RtpCodec.cpp index 9151c241..775a7048 100644 --- a/src/RtspMuxer/H265RtpCodec.cpp +++ b/src/RtspMuxer/H265RtpCodec.cpp @@ -129,7 +129,7 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { _h265frame->buffer.append((char *) frame + 3, length - 3); return false; } - + default: // 4.4.1. Single NAL Unit Packets (p24) //a full frame _h265frame->buffer.assign("\x0\x0\x0\x1", 4); @@ -146,6 +146,7 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) { //写入环形缓存 auto lastSeq = _h265frame->sequence; + DebugL << (int)frame->type; RtpCodec::inputFrame(frame); _h265frame = obtainFrame(); _h265frame->sequence = lastSeq; @@ -170,49 +171,47 @@ void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) { RtpCodec::inputFrame(frame); GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Rtp::kCycleMS); - auto pcData = frame->data() + frame->prefixSize(); + uint8_t *pcData = (uint8_t*)frame->data() + frame->prefixSize(); auto uiStamp = frame->stamp(); auto iLen = frame->size() - frame->prefixSize(); - + unsigned char naluType = H265_TYPE(pcData[0]); //获取NALU的5bit 帧类型 uiStamp %= cycleMS; - int iSize = _ui32MtuSize - 3; - if (iLen > iSize) { //超过MTU - const unsigned char s_e_Start = 1 << 7; - const unsigned char s_e_Mid = 0x00; - const unsigned char s_e_End = 1 << 6; + + WarnL << (int)naluType; + int maxSize = _ui32MtuSize - 3; + if (iLen > maxSize) { //超过MTU //获取帧头数据,1byte - unsigned char naluType = H265_TYPE(pcData[0]); //获取NALU的5bit 帧类型 - unsigned char s_e_type = naluType; + unsigned char s_e_type; bool bFirst = true; bool mark = false; int nOffset = 2; while (!mark) { - if (iLen < nOffset + iSize) { //是否拆分结束 - iSize = iLen - nOffset; + if (iLen < nOffset + maxSize) { //是否拆分结束 + maxSize = iLen - nOffset; mark = true; - s_e_type = s_e_End + naluType; + s_e_type = 1 << 7 | naluType; } else { if (bFirst == true) { - s_e_type = s_e_Start + naluType; + s_e_type = 1 << 6 | naluType; bFirst = false; } else { - s_e_type = s_e_Mid + naluType; + s_e_type = naluType; } } //FU type _aucSectionBuf[0] = 49 << 1; _aucSectionBuf[1] = 1; _aucSectionBuf[2] = s_e_type; - memcpy(_aucSectionBuf + 3, (unsigned char *) pcData + nOffset, iSize); - nOffset += iSize; - makeH265Rtp(_aucSectionBuf, iSize + 3, mark, uiStamp); + memcpy(_aucSectionBuf + 3, pcData + nOffset, maxSize); + nOffset += maxSize; + makeH265Rtp(naluType,_aucSectionBuf, maxSize + 3, mark, uiStamp); } } else { - makeH265Rtp(pcData, iLen, true, uiStamp); + makeH265Rtp(naluType,pcData, iLen, true, uiStamp); } } -void H265RtpEncoder::makeH265Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) { +void H265RtpEncoder::makeH265Rtp(int nal_type,const void* data, unsigned int len, bool mark, uint32_t uiStamp) { uint16_t ui16RtpLen = len + 12; uint32_t ts = htonl((_ui32SampleRate / 1000) * uiStamp); uint16_t sq = htons(_ui16Sequence); @@ -242,9 +241,7 @@ void H265RtpEncoder::makeH265Rtp(const void* data, unsigned int len, bool mark, rtppkt->ssrc = _ui32Ssrc; rtppkt->type = TrackVideo; rtppkt->offset = 16; - - uint8_t type = H265_TYPE(((uint8_t *) (data))[0]); - RtpCodec::inputRtp(rtppkt,type == H265Frame::isKeyFrame(type)); + RtpCodec::inputRtp(rtppkt,nal_type == H265Frame::NAL_VPS); _ui16Sequence++; _ui32TimeStamp = uiStamp; } diff --git a/src/RtspMuxer/H265RtpCodec.h b/src/RtspMuxer/H265RtpCodec.h index e38fefc6..9c4fb305 100644 --- a/src/RtspMuxer/H265RtpCodec.h +++ b/src/RtspMuxer/H265RtpCodec.h @@ -94,7 +94,7 @@ public: */ void inputFrame(const Frame::Ptr &frame) override; private: - void makeH265Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); + void makeH265Rtp(int nal_type,const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); private: unsigned char _aucSectionBuf[1600]; };