From 946b00f453329f737c38e80e5b48e55df3ba6075 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Oct 2018 17:11:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0265=20rtp?= =?UTF-8?q?=E8=A7=A3=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Factory.cpp | 125 ++++++++++++++++----------- src/Rtsp/RtspPlayer.cpp | 8 +- src/RtspMuxer/H264RtpCodec.cpp | 7 +- src/RtspMuxer/H265RtpCodec.cpp | 152 ++++++++++++++++----------------- 4 files changed, 158 insertions(+), 134 deletions(-) diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index c6ab8f99..45b2ceae 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -29,6 +29,7 @@ #include "RtmpMuxer/AACRtmpCodec.h" #include "RtspMuxer/H264RtpCodec.h" #include "RtspMuxer/AACRtpCodec.h" +#include "RtspMuxer/H265RtpCodec.h" namespace mediakit{ @@ -107,11 +108,83 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) { return std::make_shared(sps,pps,0,0); } + if (strcasestr(track->_codec.data(), "h265") != nullptr) { + //a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA= + int pt; + char sprop_sps[128] = {0},sprop_pps[128] = {0}; + 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); + } + + WarnL << "暂不支持该sdp:" << track->_codec << " " << track->_fmtp; return nullptr; } +Track::Ptr Factory::getTrackByCodecId(CodecId codecId) { + switch (codecId){ + case CodecH264:{ + return std::make_shared(); + } + case CodecH265:{ + return std::make_shared(); + } + case CodecAAC:{ + return std::make_shared(); + } + default: + WarnL << "暂不支持该CodecId:" << codecId; + return nullptr; + } +} + +RtpCodec::Ptr Factory::getRtpEncoderById(CodecId codecId, + uint32_t ui32Ssrc, + uint32_t ui32MtuSize, + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType, + uint8_t ui8Interleaved) { + switch (codecId){ + case CodecH264: + return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); + case CodecH265: + return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); + case CodecAAC: + return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); + default: + WarnL << "暂不支持该CodecId:" << codecId; + return nullptr; + } +} + +RtpCodec::Ptr Factory::getRtpDecoderById(CodecId codecId) { + switch (codecId){ + case CodecH264: + return std::make_shared(); + case CodecH265: + return std::make_shared(); + case CodecAAC: + return std::make_shared(); + default: + WarnL << "暂不支持该CodecId:" << codecId; + return nullptr; + } +} + +/////////////////////////////rtmp相关/////////////////////////////////////////// + +Track::Ptr Factory::getTrackByAmf(const AMFValue &amf) { + CodecId codecId = getCodecIdByAmf(amf); + if(codecId == CodecInvalid){ + return nullptr; + } + return getTrackByCodecId(codecId); +} + + CodecId Factory::getCodecIdByAmf(const AMFValue &val){ if (val.type() == AMF_STRING){ auto str = val.as_string(); @@ -143,58 +216,6 @@ CodecId Factory::getCodecIdByAmf(const AMFValue &val){ return CodecInvalid; } -Track::Ptr Factory::getTrackByCodecId(CodecId codecId) { - switch (codecId){ - case CodecH264:{ - return std::make_shared(); - } - case CodecAAC:{ - return std::make_shared(); - } - default: - WarnL << "暂不支持该CodecId:" << codecId; - return nullptr; - } -} - - -Track::Ptr Factory::getTrackByAmf(const AMFValue &amf) { - CodecId codecId = getCodecIdByAmf(amf); - if(codecId == CodecInvalid){ - return nullptr; - } - return getTrackByCodecId(codecId); -} - - -RtpCodec::Ptr Factory::getRtpEncoderById(CodecId codecId, - uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PlayloadType, - uint8_t ui8Interleaved) { - switch (codecId){ - case CodecH264: - return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); - case CodecAAC: - return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); - default: - WarnL << "暂不支持该CodecId:" << codecId; - return nullptr; - } -} - -RtpCodec::Ptr Factory::getRtpDecoderById(CodecId codecId) { - switch (codecId){ - case CodecH264: - return std::make_shared(); - case CodecAAC: - return std::make_shared(); - default: - WarnL << "暂不支持该CodecId:" << codecId; - return nullptr; - } -} RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) { switch (track->getCodecId()){ diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index e90cf3cb..f3920a5e 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -435,9 +435,11 @@ void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) { auto strControlSuffix = strTrack.substr(1 + strTrack.rfind('/'),strTrack.find(';') - strTrack.rfind('/') - 1); auto strRtpTime = FindField(strTrack.data(), "rtptime=", ";"); auto idx = getTrackIndexByControlSuffix(strControlSuffix); - _aiFistStamp[idx] = atoll(strRtpTime.data()) * 1000 / _aTrackInfo[idx]->_samplerate; - _aiNowStamp[idx] = _aiFistStamp[idx]; - DebugL << "rtptime(ms):" << strControlSuffix <<" " << strRtpTime; + if(idx != -1){ + _aiFistStamp[idx] = atoll(strRtpTime.data()) * 1000 / _aTrackInfo[idx]->_samplerate; + _aiNowStamp[idx] = _aiFistStamp[idx]; + DebugL << "rtptime(ms):" << strControlSuffix <<" " << strRtpTime; + } } } onPlayResult_l(SockException(Err_success, "rtsp play success")); diff --git a/src/RtspMuxer/H264RtpCodec.cpp b/src/RtspMuxer/H264RtpCodec.cpp index e50ed0fd..85128a3a 100644 --- a/src/RtspMuxer/H264RtpCodec.cpp +++ b/src/RtspMuxer/H264RtpCodec.cpp @@ -42,7 +42,7 @@ typedef struct { unsigned type :5; } FU; -bool MakeNalu(uint8_t in, NALU &nal) { +static bool MakeNalu(uint8_t in, NALU &nal) { nal.forbidden_zero_bit = in >> 7; if (nal.forbidden_zero_bit) { return false; @@ -51,7 +51,7 @@ bool MakeNalu(uint8_t in, NALU &nal) { nal.type = in & 0x1f; return true; } -bool MakeFU(uint8_t in, FU &fu) { +static bool MakeFU(uint8_t in, FU &fu) { fu.S = in >> 7; fu.E = (in >> 6) & 0x01; fu.R = (in >> 5) & 0x01; @@ -62,7 +62,6 @@ bool MakeFU(uint8_t in, FU &fu) { return true; } - H264RtpDecoder::H264RtpDecoder() { _h264frame = obtainFrame(); } @@ -157,8 +156,10 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { void H264RtpDecoder::onGetH264(const H264Frame::Ptr &frame) { //写入环形缓存 + auto lastSeq = _h264frame->sequence; RtpCodec::inputFrame(frame); _h264frame = obtainFrame(); + _h264frame->sequence = lastSeq; } diff --git a/src/RtspMuxer/H265RtpCodec.cpp b/src/RtspMuxer/H265RtpCodec.cpp index b469506e..b89cb91a 100644 --- a/src/RtspMuxer/H265RtpCodec.cpp +++ b/src/RtspMuxer/H265RtpCodec.cpp @@ -28,41 +28,41 @@ namespace mediakit{ - -typedef struct { - unsigned forbidden_zero_bit :1; - unsigned nal_ref_idc :2; - unsigned type :5; -} NALU; +//41 +//42 0 1 +//43 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +//44 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +//45 |F| Type | LayerId | TID | +//46 +-------------+-----------------+ +//48 F = 0 +//49 Type = 49 (fragmentation unit (FU)) +//50 LayerId = 0 +//51 TID = 1 +//56 /* +//57 create the FU header +//58 +//59 0 1 2 3 4 5 6 7 +//60 +-+-+-+-+-+-+-+-+ +//61 |S|E| FuType | +//62 +---------------+ +//63 +//64 S = variable +//65 E = variable +//66 FuType = NAL unit type +//67 typedef struct { unsigned S :1; unsigned E :1; - unsigned R :1; - unsigned type :5; + unsigned type :6; } FU; -bool MakeNalu(uint8_t in, NALU &nal) { - nal.forbidden_zero_bit = in >> 7; - if (nal.forbidden_zero_bit) { - return false; - } - nal.nal_ref_idc = (in & 0x60) >> 5; - nal.type = in & 0x1f; - return true; -} -bool MakeFU(uint8_t in, FU &fu) { +static void MakeFU(uint8_t in, FU &fu) { fu.S = in >> 7; fu.E = (in >> 6) & 0x01; - fu.R = (in >> 5) & 0x01; - fu.type = in & 0x1f; - if (fu.R != 0) { - return false; - } - return true; + fu.type = in & 0x3f; } - H265RtpDecoder::H265RtpDecoder() { _h265frame = obtainFrame(); } @@ -93,72 +93,72 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { const uint8_t *frame = (uint8_t *) rtppack->payload + rtppack->offset; int length = rtppack->length - rtppack->offset; - NALU nal; - MakeNalu(*frame, nal); - if (nal.type >= 0 && nal.type < 24) { - //a full frame - _h265frame->buffer.assign("\x0\x0\x0\x1", 4); - _h265frame->buffer.append((char *)frame, length); - _h265frame->type = nal.type; - _h265frame->timeStamp = rtppack->timeStamp; - _h265frame->sequence = rtppack->sequence; - auto isIDR = _h265frame->type == 5; - onGetH265(_h265frame); - return (isIDR); //i frame + int nal = H265_TYPE(frame[0]); + + if (nal > 50){ + WarnL << "不支持该类型的265 RTP包" << nal; + return false; // packet discard, Unsupported (HEVC) NAL type } + switch (nal) { + case 50: + case 48: // aggregated packet (AP) - with two or more NAL units + WarnL << "不支持该类型的265 RTP包" << nal; + return false; + case 49: { + // fragmentation unit (FU) + FU fu; + MakeFU(frame[1], fu); + if (fu.S == 1) { + //FU-A start + _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 + 2, length - 2); + _h265frame->type = fu.type; + _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->sequence = rtppack->sequence; + return (_h265frame->keyFrame()); //i frame + } - if (nal.type == 28) { - //FU-A - FU fu; - MakeFU(frame[1], fu); - if (fu.S == 1) { - //FU-A start - char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type); - _h265frame->buffer.assign("\x0\x0\x0\x1", 4); - _h265frame->buffer.push_back(tmp); - _h265frame->buffer.append((char *)frame + 2, length - 2); - _h265frame->type = fu.type; - _h265frame->timeStamp = rtppack->timeStamp; + if (rtppack->sequence != (uint16_t) (_h265frame->sequence + 1)) { + _h265frame->buffer.clear(); + WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h265frame->sequence; + return false; + } _h265frame->sequence = rtppack->sequence; - return (_h265frame->type == 5); //i frame - } - - if (rtppack->sequence != (uint16_t)(_h265frame->sequence + 1)) { - _h265frame->buffer.clear(); - WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h265frame->sequence; + if (fu.E == 1) { + //FU-A end + _h265frame->buffer.append((char *) frame + 2, length - 2); + _h265frame->timeStamp = rtppack->timeStamp; + auto isIDR = _h265frame->keyFrame(); + onGetH265(_h265frame); + return isIDR; + } + //FU-A mid + _h265frame->buffer.append((char *) frame + 2, length - 2); return false; } - _h265frame->sequence = rtppack->sequence; - if (fu.E == 1) { - //FU-A end - _h265frame->buffer.append((char *)frame + 2, length - 2); + + 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->type = nal; _h265frame->timeStamp = rtppack->timeStamp; - auto isIDR = _h265frame->type == 5; + _h265frame->sequence = rtppack->sequence; + auto isIDR = _h265frame->keyFrame(); onGetH265(_h265frame); - return isIDR; - } - //FU-A mid - _h265frame->buffer.append((char *)frame + 2, length - 2); - return false; + return (isIDR); //i frame } - - WarnL << "不支持的rtp类型:" << nal.type << " " << rtppack->sequence; - return false; - // 29 FU-B 单NAL单元B模式 - // 24 STAP-A 单一时间的组合包 - // 25 STAP-B 单一时间的组合包 - // 26 MTAP16 多个时间的组合包 - // 27 MTAP24 多个时间的组合包 - // 0 udef - // 30 udef - // 31 udef } void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) { //写入环形缓存 + auto lastSeq = _h265frame->sequence; RtpCodec::inputFrame(frame); _h265frame = obtainFrame(); + _h265frame->sequence = lastSeq; }