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 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 ``` 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); 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/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; 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/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..c2e5de6c 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -32,8 +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); } @@ -42,7 +44,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 +55,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 > 0){ + //追加负载数据 + frame->_buffer.append(data, len); + frame->_dts = stamp; + } - //写入环形缓存 - RtmpCodec::inputFrame(frame); + if(size > 0 || len > 0){ + //有adts头或者实际aac负载 + RtmpCodec::inputFrame(frame); + } } ///////////////////////////////////////////////////////////////////////////////////// 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); 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() == '/'){ 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(); 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; 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; 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) {