From 66c5a7169a1377282edff0b8e0f7a33393ce8797 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 24 Jun 2020 11:02:35 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmetadata=E4=B8=AD?= =?UTF-8?q?=E6=B2=A1duration=E5=AF=BC=E8=87=B4=E6=92=AD=E6=94=BE=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84bug:#362?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtmp/RtmpSession.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index 95076682..d52b0943 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -257,8 +257,8 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr invoke.clear(); invoke << "onMetaData" << metadata; sendResponse(MSG_DATA, invoke.data()); - auto duration = metadata["duration"].as_number(); - if(duration > 0){ + auto duration = metadata["duration"]; + if(duration && duration.as_number() > 0){ //这是点播,使用绝对时间戳 _stamp[0].setPlayBack(); _stamp[1].setPlayBack(); From e89caa23851dd7fc763115347deb59562cf97375 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 24 Jun 2020 11:18:04 +0800 Subject: [PATCH 02/14] =?UTF-8?q?c=20sdk=E6=94=AF=E6=8C=81pcm=E8=BE=93?= =?UTF-8?q?=E5=85=A5:#363?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/include/mk_media.h | 7 +++---- api/source/mk_media.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/include/mk_media.h b/api/include/mk_media.h index ff85cf47..3337b59f 100755 --- a/api/include/mk_media.h +++ b/api/include/mk_media.h @@ -98,16 +98,15 @@ API_EXPORT void API_CALL mk_media_input_h265(mk_media ctx, void *data, int len, */ API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, uint32_t dts, void *adts); -#ifdef ENABLE_FAAC /** - * 输入单帧PCM音频 + * 输入单帧PCM音频,启用ENABLE_FAAC编译时,该函数才有效 * @param ctx 对象指针 * @param data 单帧PCM数据 * @param len 单帧PCM数据字节数 * @param dts 时间戳,毫秒 */ -API_EXPORT void API_CALL mk_media_input_PCM(mk_media ctx, void *Data, int len, uint32_t pts); -#endif //ENABLE_FAAC +API_EXPORT void API_CALL mk_media_input_pcm(mk_media ctx, void *data, int len, uint32_t pts); + /** * 输入单帧G711音频 * @param ctx 对象指针 diff --git a/api/source/mk_media.cpp b/api/source/mk_media.cpp index c6bdaf19..91761829 100755 --- a/api/source/mk_media.cpp +++ b/api/source/mk_media.cpp @@ -157,14 +157,15 @@ API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, u (*obj)->getChannel()->inputAAC((char *) data, len, dts, (char *) adts); } +API_EXPORT void API_CALL mk_media_input_pcm(mk_media ctx, void *data , int len, uint32_t pts){ #ifdef ENABLE_FAAC -API_EXPORT void API_CALL mk_media_input_PCM(mk_media ctx, void *data , int len, uint32_t pts) -{ assert(ctx && data && len > 0); MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx; (*obj)->getChannel()->inputPCM((char*)data, len, pts); -} +#else + WarnL << "aac编码未启用,该方法无效,编译时请打开ENABLE_FAAC选项"; #endif //ENABLE_FAAC +} API_EXPORT void API_CALL mk_media_input_g711(mk_media ctx, void* data, int len, uint32_t dts){ assert(ctx && data && len > 0); From f67e9fce9aa83f1ae9425f8f60252eef62a67ceb Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 28 Jun 2020 15:21:41 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=82=AC=E5=9E=82=E6=8C=87=E9=92=88=E7=9A=84=E5=8F=AF=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtp/RtpProcess.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Rtp/RtpProcess.cpp b/src/Rtp/RtpProcess.cpp index 7deb0e0a..08923216 100644 --- a/src/Rtp/RtpProcess.cpp +++ b/src/Rtp/RtpProcess.cpp @@ -73,11 +73,6 @@ RtpProcess::RtpProcess(uint32_t ssrc) { } RtpProcess::~RtpProcess() { - DebugP(this); - if (_addr) { - delete _addr; - } - uint64_t duration = (_last_rtp_time.createdTime() - _last_rtp_time.elapsedTime()) / 1000; WarnP(this) << "RTP推流器(" << _media_info._vhost << "/" @@ -90,6 +85,11 @@ RtpProcess::~RtpProcess() { if (_total_bytes > iFlowThreshold * 1024) { NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport, _media_info, _total_bytes, duration, false, static_cast(*this)); } + + if (_addr) { + delete _addr; + _addr = nullptr; + } } bool RtpProcess::inputRtp(const Socket::Ptr &sock, const char *data, int data_len,const struct sockaddr *addr,uint32_t *dts_out) { From fd7739829110308f96c28842e0b04f4bc1498c58 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 28 Jun 2020 15:24:08 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddts=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E5=AF=BC=E8=87=B4=E4=B8=8D=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9A#369?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Stamp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index e5fd631c..d9ab1823 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -176,6 +176,8 @@ bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){ _sorter_max_size = _frames_since_last_max_pts; //我们记录P帧间时间间隔(也就是多个B帧时间戳增量累计) _dts_pts_offset = (pts - _last_max_pts); + //除以2,防止dts大于pts + _dts_pts_offset /= 2; } //遇到P帧或关键帧,连续B帧计数清零 _frames_since_last_max_pts = 0; From 038979b71626f157ad98bba18de6920e6e706a37 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 28 Jun 2020 21:49:08 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9rtmp=20metadata=20codec?= =?UTF-8?q?=E7=94=B1=E5=AD=97=E7=AC=A6=E4=B8=BA=E6=95=B4=E5=BD=A2,?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=AF=94=E8=BE=83=E8=80=81=E7=9A=84rtmp?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Factory.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 3a8fce31..1e7a6284 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -243,9 +243,8 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_enc AMFValue Factory::getAmfByCodecId(CodecId codecId) { switch (codecId){ - //此处用string标明rtmp编码类型目的是为了兼容某些android系统 - case CodecAAC: return AMFValue("mp4a"); - case CodecH264: return AMFValue("avc1"); + case CodecAAC: return AMFValue(FLV_CODEC_AAC); + case CodecH264: return AMFValue(FLV_CODEC_H264); case CodecH265: return AMFValue(FLV_CODEC_H265); case CodecG711A: return AMFValue(FLV_CODEC_G711A); case CodecG711U: return AMFValue(FLV_CODEC_G711U); From bbcb4d41f7e55ca971b57d3dbbe555b3ba34d392 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 29 Jun 2020 11:55:13 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dps=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E8=AF=AF=E5=88=A4=E4=B8=BAaac=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtp/Decoder.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Rtp/Decoder.cpp b/src/Rtp/Decoder.cpp index cd8e566d..92402a95 100644 --- a/src/Rtp/Decoder.cpp +++ b/src/Rtp/Decoder.cpp @@ -158,6 +158,11 @@ void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t d } case PSI_STREAM_AAC: { + uint8_t *ptr = (uint8_t *)data; + if(!(bytes > 7 && ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0)){ + //这不是aac + break; + } if (!_codecid_audio) { //获取到音频 _codecid_audio = codecid; From 41c75fb66a235ddf1f282b7c067376a99347c9a6 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Jun 2020 09:16:02 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E6=B5=8F=E8=A7=88http=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=9A=84=E9=85=8D=E7=BD=AE=E9=80=89=E9=A1=B9:#367?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 2 ++ src/Common/config.cpp | 4 ++++ src/Common/config.h | 2 ++ src/Http/HttpFileManager.cpp | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/conf/config.ini b/conf/config.ini index 8f5fe93f..5964342f 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -122,6 +122,8 @@ rootPath=./www sendBufSize=65536 #https服务器监听端口 sslport=443 +#是否显示文件夹菜单,开启后可以浏览文件夹 +dirMenu=1 [multicast] #rtp组播截止组播ip地址 diff --git a/src/Common/config.cpp b/src/Common/config.cpp index b2e00ba5..90e171ab 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -100,11 +100,15 @@ const string kCharSet = HTTP_FIELD"charSet"; const string kRootPath = HTTP_FIELD"rootPath"; //http 404错误提示内容 const string kNotFound = HTTP_FIELD"notFound"; +//是否显示文件夹菜单 +const string kDirMenu = HTTP_FIELD"dirMenu"; onceToken token([](){ mINI::Instance()[kSendBufSize] = 64 * 1024; mINI::Instance()[kMaxReqSize] = 4*1024; mINI::Instance()[kKeepAliveSecond] = 15; + mINI::Instance()[kDirMenu] = true; + #if defined(_WIN32) mINI::Instance()[kCharSet] = "gb2312"; #else diff --git a/src/Common/config.h b/src/Common/config.h index 27b4cefa..5d210ce5 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -193,6 +193,8 @@ extern const string kCharSet; extern const string kRootPath; //http 404错误提示内容 extern const string kNotFound; +//是否显示文件夹菜单 +extern const string kDirMenu; }//namespace Http ////////////SHELL配置/////////// diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index 584b6f25..5d6464db 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -195,6 +195,11 @@ static string searchIndexFile(const string &dir){ } static bool makeFolderMenu(const string &httpPath, const string &strFullPath, string &strRet) { + GET_CONFIG(bool, dirMenu, Http::kDirMenu); + if(!dirMenu){ + //不允许浏览文件夹 + return false; + } string strPathPrefix(strFullPath); string last_dir_name; if(strPathPrefix.back() == '/'){ From 2b276efaddc36f8211d779d502132ac24674f43d Mon Sep 17 00:00:00 2001 From: Xiaofeng Wang <1237906+wasphin@users.noreply.github.com> Date: Tue, 30 Jun 2020 20:15:22 +0800 Subject: [PATCH 08/14] Remove self-included header --- src/Rtp/Decoder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rtp/Decoder.h b/src/Rtp/Decoder.h index a74ee9f2..5552500f 100644 --- a/src/Rtp/Decoder.h +++ b/src/Rtp/Decoder.h @@ -14,7 +14,6 @@ #include #include #include -#include "Decoder.h" #include "Common/MediaSink.h" using namespace std; From 29077dcef4d9dba2a1b63c84825dc20a9717bd43 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Jun 2020 21:00:45 +0800 Subject: [PATCH 09/14] =?UTF-8?q?rtmp=E6=92=AD=E6=94=BE=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E6=97=B6=E7=A1=AE=E4=BF=9Daac=20track=E5=A4=84=E4=BA=8Eready?= =?UTF-8?q?=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/AAC.h | 8 ++++++-- src/Extension/AACRtmp.cpp | 16 +++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h index e024bb90..aa9dbb1e 100644 --- a/src/Extension/AAC.h +++ b/src/Extension/AAC.h @@ -138,14 +138,18 @@ public: if (_cfg.empty()) { //未获取到aac_cfg信息 if (frame->prefixSize()) { - //7个字节的adts头 + //根据7个字节的adts头生成aac config _cfg = makeAacConfig((uint8_t *) (frame->data()), frame->prefixSize()); onReady(); } else { WarnL << "无法获取adts头!"; } } - AudioTrack::inputFrame(frame); + + if (frame->size() > frame->prefixSize()) { + //除adts头外,有实际负载 + AudioTrack::inputFrame(frame); + } } private: /** diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index 48102a2d..d58cdfb4 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -32,7 +32,6 @@ static string getAacCfg(const RtmpPacket &thiz) { bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) { if (pkt->isCfgFrame()) { _aac_cfg = getAacCfg(*pkt); - return false; } if (!_aac_cfg.empty()) { onGetAAC(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp); @@ -42,7 +41,6 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) { void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) { auto frame = ResourcePoolHelper::obtainObj(); - //生成adts头 char adts_header[32] = {0}; auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header)); @@ -54,12 +52,16 @@ void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) { frame->_prefix_size = 0; } - //追加负载数据 - frame->_buffer.append(data, len); - frame->_dts = stamp; + if(len){ + //追加负载数据 + frame->_buffer.append(data, len); + frame->_dts = stamp; + } - //写入环形缓存 - RtmpCodec::inputFrame(frame); + if(size || len){ + //有adts头或者实际aac负载 + RtmpCodec::inputFrame(frame); + } } ///////////////////////////////////////////////////////////////////////////////////// From 9e42772b482a9a42e01728d17e4037acc7eadc11 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Jun 2020 21:08:52 +0800 Subject: [PATCH 10/14] =?UTF-8?q?rtmp=20aac=20config=E5=8C=85=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=B4=9F=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/AACRtmp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index d58cdfb4..5355146b 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -32,7 +32,10 @@ static string getAacCfg(const RtmpPacket &thiz) { bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) { if (pkt->isCfgFrame()) { _aac_cfg = getAacCfg(*pkt); + onGetAAC(nullptr, 0, 0); + return false; } + if (!_aac_cfg.empty()) { onGetAAC(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp); } From d2c052a67353a33dcd53130a9a841682d3a8de2b Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Jun 2020 21:11:59 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/AACRtmp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index 5355146b..c2e5de6c 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -55,13 +55,13 @@ void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) { frame->_prefix_size = 0; } - if(len){ + if(len > 0){ //追加负载数据 frame->_buffer.append(data, len); frame->_dts = stamp; } - if(size || len){ + if(size > 0 || len > 0){ //有adts头或者实际aac负载 RtmpCodec::inputFrame(frame); } From bc606cf76793c3c8fba94d51d7e9a1e565320ff3 Mon Sep 17 00:00:00 2001 From: Xiaofeng Wang <1237906+wasphin@users.noreply.github.com> Date: Tue, 30 Jun 2020 21:13:52 +0800 Subject: [PATCH 12/14] =?UTF-8?q?=E5=AD=90=E6=A8=A1=E5=9D=97=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E4=BD=BF=E7=94=A8=E7=9B=B8=E5=AF=B9=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 子模块地址使用相对路径。 * 统一服务器,即主库通过 github 下载则子库也通过 github 下载; * 也方便做 git 镜像,在自建 git 服务器上镜像后访问也更方便; --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 54226a7f..442daee9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "ZLToolKit"] path = 3rdpart/ZLToolKit - url = https://gitee.com/xiahcu/ZLToolKit + url = ../ZLToolKit [submodule "3rdpart/media-server"] path = 3rdpart/media-server - url = https://gitee.com/xiahcu/media-server + url = ../media-server From e679e746958452980ea0f7ebf26a8ea40a6c1140 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 30 Jun 2020 21:14:51 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=9A=E4=BD=99#incl?= =?UTF-8?q?ude?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtp/Decoder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rtp/Decoder.h b/src/Rtp/Decoder.h index a74ee9f2..5552500f 100644 --- a/src/Rtp/Decoder.h +++ b/src/Rtp/Decoder.h @@ -14,7 +14,6 @@ #include #include #include -#include "Decoder.h" #include "Common/MediaSink.h" using namespace std; From e24adfe995c353cf8b7304536f9a44014cceb31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E6=A5=9A?= <771730766@qq.com> Date: Thu, 2 Jul 2020 15:26:40 +0800 Subject: [PATCH 14/14] Update README_en.md --- README_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_en.md b/README_en.md index 485bd5ce..6eae5565 100644 --- a/README_en.md +++ b/README_en.md @@ -128,7 +128,7 @@ It is recommended to compile on Ubuntu or MacOS,compiling on windows is cumber ### Before build - **You must use git to clone the complete code. Do not download the source code by downloading zip package. Otherwise, the sub-module code will not be downloaded by default.You can do it like this:** ``` -git clone https://github.com/zlmediakit/ZLMediaKit.git +git clone https://github.com/xiongziliang/ZLMediaKit.git cd ZLMediaKit git submodule update --init ```