From cc7556b5a8027f6c4916b4b34aca3198190972e4 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 30 Jan 2019 11:44:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=8A=8ASPS=20PPS=20IDR?= =?UTF-8?q?=E6=89=93=E5=8C=85=E5=9C=A8=E4=B8=80=E8=B5=B7=E7=9A=84=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZLToolKit | 2 +- src/Extension/H264.cpp | 26 ++++++++++++++++ src/Extension/H264.h | 70 +++++++++++++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/ZLToolKit b/ZLToolKit index 5573789f..8c1a0f88 160000 --- a/ZLToolKit +++ b/ZLToolKit @@ -1 +1 @@ -Subproject commit 5573789f4ec0546f8788bc7be3d564de6e1365d6 +Subproject commit 8c1a0f88a0b8e332c3eaf04dbb9a8f2402b267ba diff --git a/src/Extension/H264.cpp b/src/Extension/H264.cpp index c62aa09a..06e20975 100644 --- a/src/Extension/H264.cpp +++ b/src/Extension/H264.cpp @@ -51,6 +51,32 @@ bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight return true; } + +const char *memfind(const char *buf, int len, const char *subbuf, int sublen) { + for (auto i = 0; i < len - sublen; ++i) { + if (memcmp(buf + i, subbuf, sublen) == 0) { + return buf + i; + } + } + return NULL; +} + +void splitH264(const char *ptr, int len, const std::function &cb) { + auto nal = ptr; + auto end = ptr + len; + while(true) { + auto next_nal = memfind(nal + 3,end - nal - 3,"\x0\x0\x1",3); + if(next_nal){ + cb(nal,next_nal - nal); + nal = next_nal; + continue; + } + cb(nal,end - nal); + break; + } +} + + }//namespace mediakit diff --git a/src/Extension/H264.h b/src/Extension/H264.h index 37999d5a..82cbb149 100644 --- a/src/Extension/H264.h +++ b/src/Extension/H264.h @@ -38,6 +38,7 @@ namespace mediakit{ bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); +void splitH264(const char *ptr, int len, const std::function &cb); /** * 264帧类 @@ -116,6 +117,20 @@ public: } }; +class H264FrameSubFrame : public H264FrameNoCopyAble{ +public: + typedef std::shared_ptr Ptr; + + H264FrameSubFrame(const Frame::Ptr &strongRef, + char *ptr, + uint32_t size, + uint32_t stamp, + int prefixeSize) : H264FrameNoCopyAble(ptr,size,stamp,prefixeSize){ + _strongRef = strongRef; + } +private: + Frame::Ptr _strongRef; +}; /** * 264视频通道 @@ -204,12 +219,55 @@ public: return !_sps.empty() && !_pps.empty(); } + /** + * 输入数据帧,并获取sps pps + * @param frame 数据帧 + */ + void inputFrame(const Frame::Ptr &frame) override{ + int type = H264_TYPE(*((uint8_t *)frame->data() + frame->prefixSize())); + if(type == H264Frame::NAL_SPS){ + //有些设备会把SPS PPS IDR帧当做一个帧打包,所以我们要split一下 + bool first_frame = true; + splitH264(frame->data() + frame->prefixSize(), + frame->size() - frame->prefixSize(), + [&](const char *ptr, int len){ + if(first_frame){ + H264FrameSubFrame::Ptr sub_frame = std::make_shared(frame, + frame->data(), + len + frame->prefixSize(), + frame->stamp(), + frame->prefixSize()); + inputFrame_l(sub_frame); + first_frame = false; + }else{ + H264FrameSubFrame::Ptr sub_frame = std::make_shared(frame, + (char *)ptr, + len , + frame->stamp(), + 3); + inputFrame_l(sub_frame); + } + }); + } else{ + inputFrame_l(frame); + } + } +private: + /** + * 解析sps获取宽高fps + */ + void onReady(){ + getAVCInfo(_sps,_width,_height,_fps); + } + Track::Ptr clone() override { + return std::make_shared::type >(*this); + } /** * 输入数据帧,并获取sps pps * @param frame 数据帧 */ - void inputFrame(const Frame::Ptr &frame) override{ + void inputFrame_l(const Frame::Ptr &frame){ int type = H264_TYPE(*((uint8_t *)frame->data() + frame->prefixSize())); switch (type){ case H264Frame::NAL_SPS:{ @@ -271,16 +329,6 @@ public: onReady(); } } -private: - /** - * 解析sps获取宽高fps - */ - void onReady(){ - getAVCInfo(_sps,_width,_height,_fps); - } - Track::Ptr clone() override { - return std::make_shared::type >(*this); - } private: string _sps; string _pps;