Merge pull request #3 from xiongziliang/master

merge
This commit is contained in:
nanguantong 2019-10-14 14:49:28 +08:00 committed by GitHub
commit d40d9a5b5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 130 additions and 99 deletions

@ -1 +1 @@
Subproject commit 2970df35c5c8c48013f91c818845c5c90914ea57
Subproject commit 665f53b6a4385e2312d3bf09aa305d7e3bf079e6

View File

@ -167,6 +167,8 @@ keepAliveSecond=15
port=554
#rtsps服务器监听地址
sslport=322
#在接收rtsp推流时是否重新生成时间戳(很多推流器的时间戳着实很烂)
modifyStamp=1
[shell]
#调试telnet服务器接受最大bufffer大小

View File

@ -35,16 +35,6 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
//克隆Track只拷贝其数据不拷贝其数据转发关系
auto track = track_in->clone();
weak_ptr<MediaSink> weakSelf = shared_from_this();
track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([weakSelf](const Frame::Ptr &frame){
auto strongSelf = weakSelf.lock();
if(!strongSelf){
return;
}
if(!strongSelf->_anyTrackUnReady){
strongSelf->onTrackFrame(frame);
}
}));
auto codec_id = track->getCodecId();
_track_map[codec_id] = track;
auto lam = [this,track](){
@ -58,10 +48,22 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
_trackReadyCallback[codec_id] = lam;
_ticker.resetTime();
}
weak_ptr<MediaSink> weakSelf = shared_from_this();
track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([weakSelf](const Frame::Ptr &frame){
auto strongSelf = weakSelf.lock();
if(!strongSelf){
return;
}
if(!strongSelf->_anyTrackUnReady){
strongSelf->onTrackFrame(frame);
}
}));
}
void MediaSink::resetTracks() {
_anyTrackUnReady = true;
lock_guard<recursive_mutex> lck(_mtx);
_anyTrackUnReady = false;
_allTrackReady = false;
_track_map.clear();
_trackReadyCallback.clear();

View File

@ -177,7 +177,7 @@ onceToken token([](){
mINI::Instance()[kHandshakeSecond] = 15;
mINI::Instance()[kKeepAliveSecond] = 15;
mINI::Instance()[kDirectProxy] = 1;
mINI::Instance()[kModifyStamp] = true;
mINI::Instance()[kModifyStamp] = false;
},nullptr);
} //namespace Rtsp

View File

@ -43,11 +43,6 @@ void HlsMaker::makeIndexFile(bool eof) {
char file_content[1024];
int maxSegmentDuration = 0;
//停止写之后将最后的片段也写进m3u8文件中
if (eof && _stampInc > 0) {
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
}
for (auto &tp : _seg_dur_list) {
int dur = std::get<0>(tp);
if (dur > maxSegmentDuration) {
@ -83,19 +78,16 @@ void HlsMaker::makeIndexFile(bool eof) {
void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) {
//分片数据中断结束
if (data && len) {
addNewFile(timestamp);
onWriteFile((char *) data, len);
}
else {
_noData = true;
_stampInc = _ticker.elapsedTime();
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
delOldFile();
makeIndexFile();
addNewSegment(timestamp);
onWriteSegment((char *) data, len);
//记录上次写入数据时间
_ticker_last_data.resetTime();
} else {
flushLastSegment(true);
}
}
void HlsMaker::delOldFile() {
void HlsMaker::delOldSegment() {
if(_seg_number == 0){
//如果设置为保留0个切片则认为是保存为点播
return;
@ -107,28 +99,38 @@ void HlsMaker::delOldFile() {
//但是实际保存的切片个数比m3u8所述多两个,这样做的目的是防止播放器在切片删除前能下载完毕
if (_file_index >= _seg_number + 4) {
onDelFile(_file_index - _seg_number - 4);
onDelSegment(_file_index - _seg_number - 4);
}
}
void HlsMaker::addNewFile(uint32_t) {
//上次分片数据中断结束,重置时间避免中途的等待
if (_noData) {
void HlsMaker::addNewSegment(uint32_t) {
if(!_last_file_name.empty() && _ticker.elapsedTime() < _seg_duration * 1000){
//存在上个切片,并且未到分片时间
return;
}
//关闭并保存上一个切片
flushLastSegment();
//新增切片
_last_file_name = onOpenSegment(_file_index++);
//重置切片计时器
_ticker.resetTime();
_last_file_name = onOpenFile(_file_index++);
_noData = false;
}
void HlsMaker::flushLastSegment(bool eof){
if(_last_file_name.empty()){
//不存在上个切片
return;
}
_stampInc = _ticker.elapsedTime();
if (_file_index == 0 || _stampInc >= _seg_duration * 1000) {
_ticker.resetTime();
auto file_name = onOpenFile(_file_index);
if (_file_index++ > 0) {
_seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name));
delOldFile();
makeIndexFile();
}
_last_file_name = file_name;
//文件创建到最后一次数据写入的时间即为切片长度
auto seg_dur = _ticker.elapsedTime() - _ticker_last_data.elapsedTime();
if(seg_dur <= 0){
seg_dur = 100;
}
_seg_dur_list.push_back(std::make_tuple(seg_dur, _last_file_name));
delOldSegment();
makeIndexFile(eof);
_last_file_name.clear();
}
}//namespace mediakit

View File

@ -60,20 +60,20 @@ protected:
* @param index
* @return
*/
virtual string onOpenFile(int index) = 0;
virtual string onOpenSegment(int index) = 0;
/**
* ts切片文件回调
* @param index
*/
virtual void onDelFile(int index) = 0;
virtual void onDelSegment(int index) = 0;
/**
* ts切片文件回调
* @param data
* @param len
*/
virtual void onWriteFile(const char *data, int len) = 0;
virtual void onWriteSegment(const char *data, int len) = 0;
/**
* m3u8文件回调
@ -82,21 +82,34 @@ protected:
*/
virtual void onWriteHls(const char *data, int len) = 0;
/**
* ts切片并且写入m3u8索引
* @param eof
*/
void flushLastSegment(bool eof = false);
private:
/**
* m3u8文件
* @param eof true代表点播
*/
void makeIndexFile(bool eof = false);
void delOldFile();
void addNewFile(uint32_t timestamp);
protected:
uint32_t _seg_number = 0;
/**
* ts切片
*/
void delOldSegment();
/**
* ts切片
* @param timestamp
*/
void addNewSegment(uint32_t timestamp);
private:
bool _noData = false;
int _stampInc = 0;
uint32_t _seg_number = 0;
float _seg_duration = 0;
uint64_t _file_index = 0;
Ticker _ticker;
Ticker _ticker_last_data;
string _last_file_name;
std::deque<tuple<int,string> > _seg_dur_list;
};

View File

@ -40,6 +40,7 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
_path_hls = m3u8_file;
_params = params;
_buf_size = bufSize;
_is_vod = seg_number == 0;
_file_buf.reset(new char[bufSize],[](char *ptr){
delete[] ptr;
});
@ -47,14 +48,14 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
HlsMakerImp::~HlsMakerImp() {
//录制完了
makeIndexFile(true);
if(_seg_number){
flushLastSegment(true);
if(!_is_vod){
//hls直播才删除文件
File::delete_file(_path_prefix.data());
}
}
string HlsMakerImp::onOpenFile(int index) {
string HlsMakerImp::onOpenSegment(int index) {
auto full_path = fullPath(index);
_file = makeFile(full_path, true);
if(!_file){
@ -67,12 +68,12 @@ string HlsMakerImp::onOpenFile(int index) {
return StrPrinter << index << ".ts" << "?" << _params;
}
void HlsMakerImp::onDelFile(int index) {
void HlsMakerImp::onDelSegment(int index) {
//WarnL << index;
File::delete_file(fullPath(index).data());
}
void HlsMakerImp::onWriteFile(const char *data, int len) {
void HlsMakerImp::onWriteSegment(const char *data, int len) {
if (_file) {
fwrite(data, len, 1, _file.get());
}

View File

@ -44,9 +44,9 @@ public:
uint32_t seg_number = 3);
virtual ~HlsMakerImp();
protected:
string onOpenFile(int index) override ;
void onDelFile(int index) override;
void onWriteFile(const char *data, int len) override;
string onOpenSegment(int index) override ;
void onDelSegment(int index) override;
void onWriteSegment(const char *data, int len) override;
void onWriteHls(const char *data, int len) override;
private:
string fullPath(int index);
@ -58,6 +58,8 @@ private:
string _path_hls;
string _params;
int _buf_size;
//是否为点播
bool _is_vod;
};
}//namespace mediakit

View File

@ -58,7 +58,7 @@ public:
* sps pps这些信息 Delegate相关关系
* @param track
*/
void addTrack(const Track::Ptr & track) override;
void addTrack(const Track::Ptr &track) override;
/**
* track

View File

@ -51,12 +51,9 @@ void DeltaStamp::setPlayBack(bool playback) {
_playback = playback;
}
void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out) {
if(!dts && !pts){
//没有时间戳,我们生成时间戳
pts = dts = _ticker.elapsedTime();
}else if(!pts){
//只是没有播放时间戳,使其赋值为解码时间戳
void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
if(!pts){
//没有播放时间戳,使其赋值为解码时间戳
pts = dts;
}
@ -64,7 +61,7 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out)
int pts_dts_diff = pts - dts;
//相对时间戳
_relativeStamp += deltaStamp(dts);
_relativeStamp += deltaStamp(modifyStamp ? _ticker.elapsedTime() : dts);
dts_out = _relativeStamp;
//////////////以下是播放时间戳的计算//////////////////

View File

@ -67,8 +67,9 @@ public:
* @param pts pts0dts
* @param dts_out dts
* @param pts_out pts
* @param modifyStamp
*/
void revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out);
void revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false);
/**
* seek用

View File

@ -486,7 +486,7 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
GET_CONFIG(bool,rtmp_modify_stamp,Rtmp::kModifyStamp);
if(rtmp_modify_stamp){
int64_t dts_out;
_stamp[chunkData.typeId % 2].revise(0, 0, dts_out, dts_out);
_stamp[chunkData.typeId % 2].revise(0, 0, dts_out, dts_out, true);
chunkData.timeStamp = dts_out;
}
if(!_metadata_got && !chunkData.isCfgFrame()){

View File

@ -76,24 +76,35 @@ void RtspPlayer::teardown(){
}
void RtspPlayer::play(const string &strUrl){
auto userAndPwd = FindField(strUrl.data(),"://","@");
Rtsp::eRtpType eType = (Rtsp::eRtpType)(int)(*this)[kRtpType];
if(userAndPwd.empty()){
play(strUrl,"","",eType);
auto schema = FindField(strUrl.data(), nullptr,"://");
bool isSSL = strcasecmp(schema.data(),"rtsps") == 0;
//查找"://"与"/"之间的字符串,用于提取用户名密码
auto middle_url = FindField(strUrl.data(),"://","/");
if(middle_url.empty()){
middle_url = FindField(strUrl.data(),"://", nullptr);
}
auto pos = middle_url.rfind('@');
if(pos == string::npos){
//并没有用户名密码
play(isSSL,strUrl,"","",eType);
return;
}
auto suffix = FindField(strUrl.data(),"@",nullptr);
//包含用户名密码
auto user_pwd = middle_url.substr(0,pos);
auto suffix = strUrl.substr(schema.size() + 3 + pos + 1);
auto url = StrPrinter << "rtsp://" << suffix << endl;
if(userAndPwd.find(":") == string::npos){
play(url,userAndPwd,"",eType);
if(user_pwd.find(":") == string::npos){
play(isSSL,url,user_pwd,"",eType);
return;
}
auto user = FindField(userAndPwd.data(),nullptr,":");
auto pwd = FindField(userAndPwd.data(),":",nullptr);
play(url,user,pwd,eType);
auto user = FindField(user_pwd.data(),nullptr,":");
auto pwd = FindField(user_pwd.data(),":",nullptr);
play(isSSL,url,user,pwd,eType);
}
//播放指定是否走rtp over tcp
void RtspPlayer::play(const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType ) {
void RtspPlayer::play(bool isSSL,const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType ) {
DebugL << strUrl << " "
<< (strUser.size() ? strUser : "null") << " "
<< (strPwd.size() ? strPwd:"null") << " "
@ -112,12 +123,12 @@ void RtspPlayer::play(const string &strUrl, const string &strUser, const string
auto ip = FindField(strUrl.data(), "://", "/");
if (!ip.size()) {
ip = FindField(strUrl.data(), "://", NULL);
ip = split(FindField(strUrl.data(), "://", NULL),"?")[0];
}
auto port = atoi(FindField(ip.data(), ":", NULL).data());
if (port <= 0) {
//rtsp 默认端口554
port = 554;
port = isSSL ? 322 : 554;
} else {
//服务器域名
ip = FindField(ip.data(), NULL, ":");

View File

@ -107,7 +107,7 @@ private:
int getTrackIndexByInterleaved(int interleaved) const;
int getTrackIndexByTrackType(TrackType trackType) const;
void play(const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType);
void play(bool isSSL,const string &strUrl, const string &strUser, const string &strPwd, Rtsp::eRtpType eType);
void handleResSETUP(const Parser &parser, unsigned int uiTrackIndex);
void handleResDESCRIBE(const Parser &parser);
bool handleAuthenticationFailure(const string &wwwAuthenticateParamsStr);

View File

@ -932,7 +932,7 @@ void RtspSession::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) {
GET_CONFIG(bool,modify_stamp,Rtsp::kModifyStamp);
if(modify_stamp){
int64_t dts_out;
_stamp[trackidx].revise(0, 0, dts_out, dts_out);
_stamp[trackidx].revise(0, 0, dts_out, dts_out, true);
rtppt->timeStamp = dts_out;
}
_pushSrc->onWrite(rtppt, false);