mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-12-09 04:40:38 +08:00
commit
0c9dd568b0
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -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
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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 对象指针
|
||||
|
@ -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);
|
||||
|
@ -122,6 +122,8 @@ rootPath=./www
|
||||
sendBufSize=65536
|
||||
#https服务器监听端口
|
||||
sslport=443
|
||||
#是否显示文件夹菜单,开启后可以浏览文件夹
|
||||
dirMenu=1
|
||||
|
||||
[multicast]
|
||||
#rtp组播截止组播ip地址
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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配置///////////
|
||||
|
@ -138,15 +138,19 @@ 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头!";
|
||||
}
|
||||
}
|
||||
|
||||
if (frame->size() > frame->prefixSize()) {
|
||||
//除adts头外,有实际负载
|
||||
AudioTrack::inputFrame(frame);
|
||||
}
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* 解析2个字节的aac配置
|
||||
|
@ -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<AACFrame>::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;
|
||||
}
|
||||
|
||||
if(len > 0){
|
||||
//追加负载数据
|
||||
frame->_buffer.append(data, len);
|
||||
frame->_dts = stamp;
|
||||
}
|
||||
|
||||
//写入环形缓存
|
||||
if(size > 0 || len > 0){
|
||||
//有adts头或者实际aac负载
|
||||
RtmpCodec::inputFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
|
@ -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() == '/'){
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include "Decoder.h"
|
||||
#include "Common/MediaSink.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -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<SockInfo &>(*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) {
|
||||
|
Loading…
Reference in New Issue
Block a user