Merge pull request #1 from zlmediakit/master

merge
This commit is contained in:
nanguantong 2019-09-29 22:00:18 +08:00 committed by GitHub
commit 5704d8171c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 53 additions and 24 deletions

@ -1 +1 @@
Subproject commit 91246bb01475c7336040a4b7ec35d0584887f365 Subproject commit b7485c4b48b277bfaba2ad930cf1f30e2806299c

View File

@ -39,6 +39,7 @@ filePath=/Users/xzl/git/ZLMediaKit/release/mac/Release/httpRoot
#hls最大切片时间 #hls最大切片时间
segDur=3 segDur=3
#m3u8索引中,hls保留切片个数(实际保留切片个数大2~3个) #m3u8索引中,hls保留切片个数(实际保留切片个数大2~3个)
#如果设置为0则不删除切片而是保存为点播
segNum=3 segNum=3
[hook] [hook]

View File

@ -25,6 +25,7 @@
*/ */
#include <limits.h> #include <limits.h>
#include <sys/stat.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <unistd.h> #include <unistd.h>
#include <stdexcept> #include <stdexcept>

View File

@ -27,7 +27,7 @@
#define IPTV_PROCESS_H #define IPTV_PROCESS_H
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/fcntl.h> #include <fcntl.h>
#include <string> #include <string>
using namespace std; using namespace std;

View File

@ -77,12 +77,15 @@ const string kStreamNoneReaderDelayMS = GENERAL_FIELD"streamNoneReaderDelayMS";
const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS"; const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
const string kEnableVhost = GENERAL_FIELD"enableVhost"; const string kEnableVhost = GENERAL_FIELD"enableVhost";
const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay"; const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay";
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kFlowThreshold] = 1024; mINI::Instance()[kFlowThreshold] = 1024;
mINI::Instance()[kStreamNoneReaderDelayMS] = 5 * 1000; mINI::Instance()[kStreamNoneReaderDelayMS] = 5 * 1000;
mINI::Instance()[kMaxStreamWaitTimeMS] = 5 * 1000; mINI::Instance()[kMaxStreamWaitTimeMS] = 5 * 1000;
mINI::Instance()[kEnableVhost] = 1; mINI::Instance()[kEnableVhost] = 1;
mINI::Instance()[kUltraLowDelay] = 1; mINI::Instance()[kUltraLowDelay] = 1;
mINI::Instance()[kAddMuteAudio] = 1;
},nullptr); },nullptr);
}//namespace General }//namespace General

View File

@ -177,6 +177,8 @@ extern const string kMaxStreamWaitTimeMS;
extern const string kEnableVhost; extern const string kEnableVhost;
//超低延时模式,默认打开,打开后会降低延时但是转发性能会稍差 //超低延时模式,默认打开,打开后会降低延时但是转发性能会稍差
extern const string kUltraLowDelay; extern const string kUltraLowDelay;
//拉流代理时是否添加静音音频
extern const string kAddMuteAudio;
}//namespace General }//namespace General
@ -276,7 +278,7 @@ extern const string kFileRepeat;
namespace Hls { namespace Hls {
//HLS切片时长,单位秒 //HLS切片时长,单位秒
extern const string kSegmentDuration; extern const string kSegmentDuration;
//HLS切片个数 //HLS切片个数如果设置为0则不删除切片而是保存为点播
extern const string kSegmentNum; extern const string kSegmentNum;
//HLS文件写缓存大小 //HLS文件写缓存大小
extern const string kFileBufSize; extern const string kFileBufSize;

View File

@ -60,16 +60,16 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
} }
if (strcasecmp(track->_codec.data(), "h264") == 0) { if (strcasecmp(track->_codec.data(), "h264") == 0) {
string sps_pps = FindField(track->_fmtp.data(), "sprop-parameter-sets=", nullptr); auto map = Parser::parseArgs(track->_fmtp," ","=");
for(auto &pr : map){
trim(pr.second," ;");
}
auto sps_pps = map["sprop-parameter-sets"];
if(sps_pps.empty()){ if(sps_pps.empty()){
return std::make_shared<H264Track>(); return std::make_shared<H264Track>();
} }
string base64_SPS = FindField(sps_pps.data(), NULL, ","); string base64_SPS = FindField(sps_pps.data(), NULL, ",");
string base64_PPS = FindField(sps_pps.data(), ",", NULL); string base64_PPS = FindField(sps_pps.data(), ",", NULL);
if(base64_PPS.back() == ';'){
base64_PPS.pop_back();
}
auto sps = decodeBase64(base64_SPS); auto sps = decodeBase64(base64_SPS);
auto pps = decodeBase64(base64_PPS); auto pps = decodeBase64(base64_PPS);
return std::make_shared<H264Track>(sps,pps,0,0); return std::make_shared<H264Track>(sps,pps,0,0);

View File

@ -28,7 +28,8 @@
namespace mediakit { namespace mediakit {
HlsMaker::HlsMaker(float seg_duration, uint32_t seg_number) { HlsMaker::HlsMaker(float seg_duration, uint32_t seg_number) {
seg_number = MAX(1,seg_number); //最小允许设置为00个切片代表点播
seg_number = MAX(0,seg_number);
seg_duration = MAX(1,seg_duration); seg_duration = MAX(1,seg_duration);
_seg_number = seg_number; _seg_number = seg_number;
_seg_duration = seg_duration; _seg_duration = seg_duration;
@ -37,12 +38,9 @@ HlsMaker::HlsMaker(float seg_duration, uint32_t seg_number) {
HlsMaker::~HlsMaker() { HlsMaker::~HlsMaker() {
} }
#define PRINT(...) file_size += snprintf(file_content + file_size,sizeof(file_content) - file_size, ##__VA_ARGS__)
void HlsMaker::makeIndexFile(bool eof) { void HlsMaker::makeIndexFile(bool eof) {
char file_content[4 * 1024]; char file_content[1024];
int file_size = 0;
int maxSegmentDuration = 0; int maxSegmentDuration = 0;
for (auto &tp : _seg_dur_list) { for (auto &tp : _seg_dur_list) {
int dur = std::get<0>(tp); int dur = std::get<0>(tp);
@ -50,7 +48,10 @@ void HlsMaker::makeIndexFile(bool eof) {
maxSegmentDuration = dur; maxSegmentDuration = dur;
} }
} }
PRINT("#EXTM3U\n"
string m3u8;
snprintf(file_content,sizeof(file_content),
"#EXTM3U\n"
"#EXT-X-VERSION:3\n" "#EXT-X-VERSION:3\n"
"#EXT-X-ALLOW-CACHE:NO\n" "#EXT-X-ALLOW-CACHE:NO\n"
"#EXT-X-TARGETDURATION:%u\n" "#EXT-X-TARGETDURATION:%u\n"
@ -58,14 +59,18 @@ void HlsMaker::makeIndexFile(bool eof) {
(maxSegmentDuration + 999) / 1000, (maxSegmentDuration + 999) / 1000,
_file_index); _file_index);
m3u8.assign(file_content);
for (auto &tp : _seg_dur_list) { for (auto &tp : _seg_dur_list) {
PRINT("#EXTINF:%.3f,\n%s\n", std::get<0>(tp) / 1000.0, std::get<1>(tp).data()); snprintf(file_content,sizeof(file_content), "#EXTINF:%.3f,\n%s\n", std::get<0>(tp) / 1000.0, std::get<1>(tp).data());
m3u8.append(file_content);
} }
if (eof) { if (eof) {
PRINT("#EXT-X-ENDLIST\n"); snprintf(file_content,sizeof(file_content),"#EXT-X-ENDLIST\n");
m3u8.append(file_content);
} }
onWriteHls(file_content, file_size); onWriteHls(m3u8.data(), m3u8.size());
} }
@ -75,6 +80,10 @@ void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) {
} }
void HlsMaker::delOldFile() { void HlsMaker::delOldFile() {
if(_seg_number == 0){
//如果设置为保留0个切片则认为是保存为点播
return;
}
//在hls m3u8索引文件中,我们保存的切片个数跟_seg_number相关设置一致 //在hls m3u8索引文件中,我们保存的切片个数跟_seg_number相关设置一致
if (_file_index >= _seg_number + 2) { if (_file_index >= _seg_number + 2) {
_seg_dur_list.pop_front(); _seg_dur_list.pop_front();

View File

@ -81,13 +81,18 @@ protected:
* @param len * @param len
*/ */
virtual void onWriteHls(const char *data, int len) = 0; virtual void onWriteHls(const char *data, int len) = 0;
private:
/**
* m3u8文件
* @param eof true代表点播
*/
void makeIndexFile(bool eof = false);
void delOldFile(); void delOldFile();
void addNewFile(uint32_t timestamp); void addNewFile(uint32_t timestamp);
void makeIndexFile(bool eof = false); protected:
uint32_t _seg_number = 0;
private: private:
float _seg_duration = 0; float _seg_duration = 0;
uint32_t _seg_number = 0;
uint64_t _file_index = 0; uint64_t _file_index = 0;
Ticker _ticker; Ticker _ticker;
string _last_file_name; string _last_file_name;

View File

@ -46,9 +46,13 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
} }
HlsMakerImp::~HlsMakerImp() { HlsMakerImp::~HlsMakerImp() {
_file.reset(); //录制完了
makeIndexFile(true);
if(_seg_number){
//hls直播才删除文件
File::delete_file(_path_prefix.data()); File::delete_file(_path_prefix.data());
} }
}
string HlsMakerImp::onOpenFile(int index) { string HlsMakerImp::onOpenFile(int index) {
auto full_path = fullPath(index); auto full_path = fullPath(index);

View File

@ -30,6 +30,7 @@
#include "Http/HttpSession.h" #include "Http/HttpSession.h"
#include "Extension/AAC.h" #include "Extension/AAC.h"
#include "Extension/H264.h" #include "Extension/H264.h"
#include "Thread/WorkThreadPool.h"
using namespace toolkit; using namespace toolkit;
@ -37,7 +38,7 @@ namespace mediakit {
#ifdef ENABLE_MP4V2 #ifdef ENABLE_MP4V2
MediaReader::MediaReader(const string &strVhost,const string &strApp, const string &strId,const string &filePath ) { MediaReader::MediaReader(const string &strVhost,const string &strApp, const string &strId,const string &filePath ) {
_poller = EventPollerPool::Instance().getPoller(); _poller = WorkThreadPool::Instance().getPoller();
auto strFileName = filePath; auto strFileName = filePath;
if(strFileName.empty()){ if(strFileName.empty()){
GET_CONFIG(string,recordPath,Record::kFilePath); GET_CONFIG(string,recordPath,Record::kFilePath);

View File

@ -244,13 +244,16 @@ void PlayerProxy::onPlaySuccess() {
videoTrack->addDelegate(_mediaMuxer); videoTrack->addDelegate(_mediaMuxer);
} }
//是否添加静音音频
GET_CONFIG(bool,addMuteAudio,General::kAddMuteAudio);
auto audioTrack = getTrack(TrackAudio, false); auto audioTrack = getTrack(TrackAudio, false);
if(audioTrack){ if(audioTrack){
//添加音频 //添加音频
_mediaMuxer->addTrack(audioTrack); _mediaMuxer->addTrack(audioTrack);
//音频数据写入_mediaMuxer //音频数据写入_mediaMuxer
audioTrack->addDelegate(_mediaMuxer); audioTrack->addDelegate(_mediaMuxer);
}else if(videoTrack){ }else if(addMuteAudio && videoTrack){
//没有音频信息,产生一个静音音频 //没有音频信息,产生一个静音音频
MuteAudioMaker::Ptr audioMaker = std::make_shared<MuteAudioMaker>(); MuteAudioMaker::Ptr audioMaker = std::make_shared<MuteAudioMaker>();
//videoTrack把数据写入MuteAudioMaker //videoTrack把数据写入MuteAudioMaker