diff --git a/src/Extension/H264.cpp b/src/Extension/H264.cpp index b1874e30..5c8c6d8a 100644 --- a/src/Extension/H264.cpp +++ b/src/Extension/H264.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). @@ -14,24 +14,24 @@ using namespace toolkit; using namespace std; -namespace mediakit{ +namespace mediakit { -static bool getAVCInfo(const char *sps, size_t sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){ +static bool getAVCInfo(const char *sps, size_t sps_len, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) { if (sps_len < 4) { return false; } T_GetBitContext tGetBitBuf; T_SPS tH264SpsInfo; - memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); - memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo)); - tGetBitBuf.pu8Buf = (uint8_t*)sps + 1; + memset(&tGetBitBuf, 0, sizeof(tGetBitBuf)); + memset(&tH264SpsInfo, 0, sizeof(tH264SpsInfo)); + tGetBitBuf.pu8Buf = (uint8_t *)sps + 1; tGetBitBuf.iBufSize = (int)(sps_len - 1); - if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){ + if (0 != h264DecSeqParameterSet((void *)&tGetBitBuf, &tH264SpsInfo)) { return false; } h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight); h264GeFramerate(&tH264SpsInfo, &iVideoFps); - //ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; + // ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; return true; } @@ -48,7 +48,8 @@ static const char *memfind(const char *buf, ssize_t len, const char *subbuf, ssi return NULL; } -void splitH264(const char *ptr, size_t len, size_t prefix, const std::function &cb) { +void splitH264( + const char *ptr, size_t len, size_t prefix, const std::function &cb) { auto start = ptr + prefix; auto end = ptr + len; size_t next_prefix; @@ -78,7 +79,7 @@ void splitH264(const char *ptr, size_t len, size_t prefix, const std::functiongetCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){ +H264Track::H264Track(const Frame::Ptr &sps, const Frame::Ptr &pps) { + if (sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264) { throw std::invalid_argument("必须输入H264类型的帧"); } - _sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize()); - _pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize()); + _sps = string(sps->data() + sps->prefixSize(), sps->size() - sps->prefixSize()); + _pps = string(pps->data() + pps->prefixSize(), pps->size() - pps->prefixSize()); onReady(); } -const string &H264Track::getSps() const{ +const string &H264Track::getSps() const { return _sps; } -const string &H264Track::getPps() const{ +const string &H264Track::getPps() const { return _pps; } @@ -155,7 +156,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) { //非I/B/P帧情况下,split一下,防止多个帧粘合在一起 bool ret = false; splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, size_t len, size_t prefix) { - H264FrameInternal::Ptr sub_frame = std::make_shared(frame, (char *) ptr, len, prefix); + H264FrameInternal::Ptr sub_frame = std::make_shared(frame, (char *)ptr, len, prefix); if (inputFrame_l(sub_frame)) { ret = true; } @@ -163,7 +164,7 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) { return ret; } -void H264Track::onReady(){ +void H264Track::onReady() { if (!getAVCInfo(_sps, _width, _height, _fps)) { _sps.clear(); _pps.clear(); @@ -171,33 +172,39 @@ void H264Track::onReady(){ } Track::Ptr H264Track::clone() { - return std::make_shared::type >(*this); + return std::make_shared::type>(*this); } -bool H264Track::inputFrame_l(const Frame::Ptr &frame){ - int type = H264_TYPE( frame->data()[frame->prefixSize()]); +bool H264Track::inputFrame_l(const Frame::Ptr &frame) { + int type = H264_TYPE(frame->data()[frame->prefixSize()]); bool ret = true; switch (type) { - case H264Frame::NAL_SPS: { - _sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); - break; - } - case H264Frame::NAL_PPS: { - _pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); - _insert_config_frame = true; - break; - } - - default: - if (_insert_config_frame && !frame->dropAble()) { - if (!frame->keyFrame()) { - const_cast(frame) = std::make_shared(frame, true); - } - insertConfigFrame(frame); - _insert_config_frame = false; + case H264Frame::NAL_SPS: { + _sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + _latest_is_config_frame = true; + ret = VideoTrack::inputFrame(frame); + break; + } + case H264Frame::NAL_PPS: { + _pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); + _latest_is_config_frame = true; + ret = VideoTrack::inputFrame(frame); + break; + } + default: + // 避免识别不出关键帧 + if (_latest_is_config_frame && !frame->dropAble()) { + if (!frame->keyFrame()) { + const_cast(frame) = std::make_shared(frame, true); } - ret = VideoTrack::inputFrame(frame); - break; + } + // 判断是否是I帧, 并且如果是,那判断前面是否插入过config帧, 如果插入过就不插入了 + if (frame->keyFrame() && !_latest_is_config_frame) { + insertConfigFrame(frame); + } + _latest_is_config_frame = false; + ret = VideoTrack::inputFrame(frame); + break; } if (_width == 0 && ready()) { @@ -206,20 +213,20 @@ bool H264Track::inputFrame_l(const Frame::Ptr &frame){ return ret; } -void H264Track::insertConfigFrame(const Frame::Ptr &frame){ - if(!_sps.empty()){ +void H264Track::insertConfigFrame(const Frame::Ptr &frame) { + if (!_sps.empty()) { auto spsFrame = FrameImp::create(); spsFrame->_prefix_size = 4; - spsFrame->_buffer.assign("\x00\x00\x00\x01",4); + spsFrame->_buffer.assign("\x00\x00\x00\x01", 4); spsFrame->_buffer.append(_sps); spsFrame->_dts = frame->dts(); VideoTrack::inputFrame(spsFrame); } - if(!_pps.empty()){ + if (!_pps.empty()) { auto ppsFrame = FrameImp::create(); ppsFrame->_prefix_size = 4; - ppsFrame->_buffer.assign("\x00\x00\x00\x01",4); + ppsFrame->_buffer.assign("\x00\x00\x00\x01", 4); ppsFrame->_buffer.append(_pps); ppsFrame->_dts = frame->dts(); VideoTrack::inputFrame(ppsFrame); @@ -250,34 +257,28 @@ public: _printer << strTemp; _printer << "; sprop-parameter-sets="; memset(strTemp, 0, sizeof(strTemp)); - av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *) strSPS.data(), (int) strSPS.size()); + av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *)strSPS.data(), (int)strSPS.size()); _printer << strTemp << ","; memset(strTemp, 0, sizeof(strTemp)); - av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *) strPPS.data(), (int) strPPS.size()); + av_base64_encode(strTemp, sizeof(strTemp), (uint8_t *)strPPS.data(), (int)strPPS.size()); _printer << strTemp << "\r\n"; - _printer << "a=control:trackID=" << (int) TrackVideo << "\r\n"; + _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } - string getSdp() const { - return _printer; - } + string getSdp() const { return _printer; } - CodecId getCodecId() const { - return CodecH264; - } + CodecId getCodecId() const { return CodecH264; } private: _StrPrinter _printer; }; Sdp::Ptr H264Track::getSdp() { - if(!ready()){ + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } return std::make_shared(getSps(), getPps(), getBitRate() / 1024); } -}//namespace mediakit - - +} // namespace mediakit