From a28aeb214833b83126bd0016c60ab111df875e76 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 19 Jun 2021 01:27:13 +0800 Subject: [PATCH] for frame merge must has vlc(video codec layer) data and flush rtmp a frame must has vcl --- src/Extension/Frame.cpp | 35 ++++++++++++++++++++++++++++++++++- src/Extension/Frame.h | 1 + src/Extension/H264Rtmp.cpp | 16 +++++++++++++--- src/Extension/H264Rtmp.h | 1 + 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/Extension/Frame.cpp b/src/Extension/Frame.cpp index 62753f59..62965553 100644 --- a/src/Extension/Frame.cpp +++ b/src/Extension/Frame.cpp @@ -267,11 +267,44 @@ bool FrameMerger::shouldDrop(const Frame::Ptr &frame) const{ } return false; } +bool FrameMerger::frameCacheHasVCL(List &frameCached) const{ + bool hasVCL = false; + bool isH264OrH265 = false; + frameCached.for_each([&hasVCL,&isH264OrH265](const Frame::Ptr &frame){ + switch (frame->getCodecId()) { + case CodecH264:{ + auto type = H264_TYPE(frame->data()[frame->prefixSize()]); + if(type >=H264Frame::NAL_B_P && type <= H264Frame::NAL_IDR){ + //有编码数据 + hasVCL=true; + } + isH264OrH265 = true; + break; + } + case CodecH265: { + //如果是新的一帧,前面的缓存需要输出 + auto type = H265_TYPE(frame->data()[frame->prefixSize()]); + if(type>=H265Frame::NAL_TRAIL_R &&type<= H265Frame::NAL_RSV_IRAP_VCL23){ + //有编码数据 + hasVCL=true; + } + isH264OrH265 = true; + break; + } + default: break; + } + }); + if(isH264OrH265){ + return hasVCL; + } + return true; + +} void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) { if(shouldDrop(frame)){ return; } - if (willFlush(frame)) { + if (willFlush(frame) && frameCacheHasVCL(_frameCached)) { Frame::Ptr back = _frameCached.back(); Buffer::Ptr merged_frame = back; bool have_idr = back->keyFrame(); diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index 95a5ec6d..973b6359 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -476,6 +476,7 @@ private: bool willFlush(const Frame::Ptr &frame) const; void doMerge(BufferLikeString &buffer, const Frame::Ptr &frame) const; bool shouldDrop(const Frame::Ptr &frame) const; + bool frameCacheHasVCL(List &frameCached) const; private: int _type; diff --git a/src/Extension/H264Rtmp.cpp b/src/Extension/H264Rtmp.cpp index b3426fe8..6765b476 100644 --- a/src/Extension/H264Rtmp.cpp +++ b/src/Extension/H264Rtmp.cpp @@ -159,7 +159,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { auto pcData = frame->data() + frame->prefixSize(); auto iLen = frame->size() - frame->prefixSize(); auto type = H264_TYPE(((uint8_t*)pcData)[0]); - if(type == H264Frame::NAL_SEI){ + if(type == H264Frame::NAL_SEI || type == H264Frame::NAL_AUD){ return; } @@ -182,10 +182,20 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { break; } } - - if(_lastPacket && (_lastPacket->time_stamp != frame->dts() || ((pcData[1]&0x80) != 0 && type>=H264Frame::NAL_B_P && type<=H264Frame::NAL_IDR))) { + if((frame->configFrame() || frame->keyFrame()) && _lastPacket){ + // key frame or sps pps flush frame RtmpCodec::inputRtmp(_lastPacket); _lastPacket = nullptr; + _lastPacketHasVCL = false; + } + + if(_lastPacket && (_lastPacket->time_stamp != frame->dts() || ((pcData[1]&0x80) != 0 && type>=H264Frame::NAL_B_P && type<=H264Frame::NAL_IDR && _lastPacketHasVCL))) { + RtmpCodec::inputRtmp(_lastPacket); + _lastPacket = nullptr; + _lastPacketHasVCL = false; + } + if(type>=H264Frame::NAL_B_P && type<=H264Frame::NAL_IDR){ + _lastPacketHasVCL = true; } if(!_lastPacket) { diff --git a/src/Extension/H264Rtmp.h b/src/Extension/H264Rtmp.h index a7c243ca..c45da3a6 100644 --- a/src/Extension/H264Rtmp.h +++ b/src/Extension/H264Rtmp.h @@ -80,6 +80,7 @@ private: private: H264Track::Ptr _track; bool _gotSpsPps = false; + bool _lastPacketHasVCL = false; RtmpPacket::Ptr _lastPacket; };