Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
d6e60e09
Commit
d6e60e09
authored
Oct 11, 2019
by
Weiwei.Zhou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加断流重连是否接着前一次继续写;修复断流重连成功后hls时间戳错误问题
parent
7d76a3eb
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
109 行增加
和
26 行删除
+109
-26
conf/config.ini
+3
-0
src/Common/MediaSink.cpp
+9
-1
src/Common/MediaSink.h
+8
-5
src/Common/MultiMediaSourceMuxer.h
+13
-0
src/Common/config.cpp
+2
-0
src/Common/config.h
+3
-0
src/MediaFile/HlsMaker.cpp
+18
-2
src/MediaFile/HlsMaker.h
+1
-0
src/MediaFile/HlsRecorder.h
+1
-1
src/MediaFile/MediaRecorder.cpp
+14
-0
src/MediaFile/MediaRecorder.h
+13
-8
src/MediaFile/TsMuxer.cpp
+2
-0
src/MediaFile/TsMuxer.h
+2
-2
src/Player/PlayerProxy.cpp
+20
-7
没有找到文件。
conf/config.ini
查看文件 @
d6e60e09
...
@@ -32,6 +32,9 @@ streamNoneReaderDelayMS=5000
...
@@ -32,6 +32,9 @@ streamNoneReaderDelayMS=5000
ultraLowDelay
=
1
ultraLowDelay
=
1
#拉流代理是否添加静音音频(直接拉流模式本协议无效)
#拉流代理是否添加静音音频(直接拉流模式本协议无效)
addMuteAudio
=
1
addMuteAudio
=
1
#拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
#如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
resetWhenRePlay
=
1
[hls]
[hls]
#hls写文件的buf大小,调整参数可以提高文件io性能
#hls写文件的buf大小,调整参数可以提高文件io性能
...
...
src/Common/MediaSink.cpp
查看文件 @
d6e60e09
...
@@ -32,7 +32,7 @@ namespace mediakit{
...
@@ -32,7 +32,7 @@ namespace mediakit{
void
MediaSink
::
addTrack
(
const
Track
::
Ptr
&
track_in
)
{
void
MediaSink
::
addTrack
(
const
Track
::
Ptr
&
track_in
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
//克隆Track,只拷贝其数据,不拷贝其数据转发关系
//克隆Track,只拷贝其数据,不拷贝其数据转发关系
auto
track
=
track_in
->
clone
();
auto
track
=
track_in
->
clone
();
weak_ptr
<
MediaSink
>
weakSelf
=
shared_from_this
();
weak_ptr
<
MediaSink
>
weakSelf
=
shared_from_this
();
...
@@ -60,6 +60,14 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
...
@@ -60,6 +60,14 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
}
}
}
}
void
MediaSink
::
resetTracks
()
{
_anyTrackUnReady
=
true
;
_allTrackReady
=
false
;
_track_map
.
clear
();
_trackReadyCallback
.
clear
();
_ticker
.
resetTime
();
}
void
MediaSink
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
void
MediaSink
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
auto
codec_id
=
frame
->
getCodecId
();
auto
codec_id
=
frame
->
getCodecId
();
...
...
src/Common/MediaSink.h
查看文件 @
d6e60e09
...
@@ -52,7 +52,7 @@ public:
...
@@ -52,7 +52,7 @@ public:
* 输入frame
* 输入frame
* @param frame
* @param frame
*/
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
/**
/**
* 添加track,内部会调用Track的clone方法
* 添加track,内部会调用Track的clone方法
...
@@ -61,21 +61,24 @@ public:
...
@@ -61,21 +61,24 @@ public:
*/
*/
virtual
void
addTrack
(
const
Track
::
Ptr
&
track
);
virtual
void
addTrack
(
const
Track
::
Ptr
&
track
);
/**
* 重置track
*/
virtual
void
resetTracks
();
/**
/**
* 全部Track是否都准备好了
* 全部Track是否都准备好了
* @return
* @return
*/
*/
bool
isAllTrackReady
()
const
;
bool
isAllTrackReady
()
const
;
/**
/**
* 获取特定类型的Track
* 获取特定类型的Track
* @param type track类型
* @param type track类型
* @param trackReady 是否获取已经准备好的Track
* @param trackReady 是否获取已经准备好的Track
* @return
* @return
*/
*/
Track
::
Ptr
getTrack
(
TrackType
type
,
bool
trackReady
=
true
)
const
;
Track
::
Ptr
getTrack
(
TrackType
type
,
bool
trackReady
=
true
)
const
;
protected
:
protected
:
/**
/**
* 某track已经准备好,其ready()状态返回true,
* 某track已经准备好,其ready()状态返回true,
...
...
src/Common/MultiMediaSourceMuxer.h
查看文件 @
d6e60e09
...
@@ -70,6 +70,19 @@ public:
...
@@ -70,6 +70,19 @@ public:
}
}
/**
/**
* 重置音视频媒体
*/
void
resetTracks
()
{
if
(
_rtmp
){
_rtmp
->
resetTracks
();
}
if
(
_rtsp
){
_rtsp
->
resetTracks
();
}
_record
->
resetTracks
();
}
/**
* 写入帧数据然后打包rtmp
* 写入帧数据然后打包rtmp
* @param frame 帧数据
* @param frame 帧数据
*/
*/
...
...
src/Common/config.cpp
查看文件 @
d6e60e09
...
@@ -78,6 +78,7 @@ const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
...
@@ -78,6 +78,7 @@ 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"
;
const
string
kAddMuteAudio
=
GENERAL_FIELD
"addMuteAudio"
;
const
string
kResetWhenRePlay
=
GENERAL_FIELD
"resetWhenRePlay"
;
onceToken
token
([](){
onceToken
token
([](){
mINI
::
Instance
()[
kFlowThreshold
]
=
1024
;
mINI
::
Instance
()[
kFlowThreshold
]
=
1024
;
...
@@ -86,6 +87,7 @@ onceToken token([](){
...
@@ -86,6 +87,7 @@ onceToken token([](){
mINI
::
Instance
()[
kEnableVhost
]
=
1
;
mINI
::
Instance
()[
kEnableVhost
]
=
1
;
mINI
::
Instance
()[
kUltraLowDelay
]
=
1
;
mINI
::
Instance
()[
kUltraLowDelay
]
=
1
;
mINI
::
Instance
()[
kAddMuteAudio
]
=
1
;
mINI
::
Instance
()[
kAddMuteAudio
]
=
1
;
mINI
::
Instance
()[
kResetWhenRePlay
]
=
1
;
},
nullptr
);
},
nullptr
);
}
//namespace General
}
//namespace General
...
...
src/Common/config.h
查看文件 @
d6e60e09
...
@@ -179,6 +179,9 @@ extern const string kEnableVhost;
...
@@ -179,6 +179,9 @@ extern const string kEnableVhost;
extern
const
string
kUltraLowDelay
;
extern
const
string
kUltraLowDelay
;
//拉流代理时是否添加静音音频
//拉流代理时是否添加静音音频
extern
const
string
kAddMuteAudio
;
extern
const
string
kAddMuteAudio
;
//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
extern
const
string
kResetWhenRePlay
;
}
//namespace General
}
//namespace General
...
...
src/MediaFile/HlsMaker.cpp
查看文件 @
d6e60e09
...
@@ -81,8 +81,18 @@ void HlsMaker::makeIndexFile(bool eof) {
...
@@ -81,8 +81,18 @@ void HlsMaker::makeIndexFile(bool eof) {
void
HlsMaker
::
inputData
(
void
*
data
,
uint32_t
len
,
uint32_t
timestamp
)
{
void
HlsMaker
::
inputData
(
void
*
data
,
uint32_t
len
,
uint32_t
timestamp
)
{
addNewFile
(
timestamp
);
//分片数据中断结束
onWriteFile
((
char
*
)
data
,
len
);
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
();
}
}
}
void
HlsMaker
::
delOldFile
()
{
void
HlsMaker
::
delOldFile
()
{
...
@@ -102,6 +112,12 @@ void HlsMaker::delOldFile() {
...
@@ -102,6 +112,12 @@ void HlsMaker::delOldFile() {
}
}
void
HlsMaker
::
addNewFile
(
uint32_t
)
{
void
HlsMaker
::
addNewFile
(
uint32_t
)
{
//上次分片数据中断结束,重置时间避免中途的等待
if
(
_noData
)
{
_ticker
.
resetTime
();
_last_file_name
=
onOpenFile
(
_file_index
++
);
_noData
=
false
;
}
_stampInc
=
_ticker
.
elapsedTime
();
_stampInc
=
_ticker
.
elapsedTime
();
if
(
_file_index
==
0
||
_stampInc
>=
_seg_duration
*
1000
)
{
if
(
_file_index
==
0
||
_stampInc
>=
_seg_duration
*
1000
)
{
_ticker
.
resetTime
();
_ticker
.
resetTime
();
...
...
src/MediaFile/HlsMaker.h
查看文件 @
d6e60e09
...
@@ -92,6 +92,7 @@ protected:
...
@@ -92,6 +92,7 @@ protected:
protected
:
protected
:
uint32_t
_seg_number
=
0
;
uint32_t
_seg_number
=
0
;
private
:
private
:
bool
_noData
=
false
;
int
_stampInc
=
0
;
int
_stampInc
=
0
;
float
_seg_duration
=
0
;
float
_seg_duration
=
0
;
uint64_t
_file_index
=
0
;
uint64_t
_file_index
=
0
;
...
...
src/MediaFile/HlsRecorder.h
查看文件 @
d6e60e09
...
@@ -32,7 +32,7 @@
...
@@ -32,7 +32,7 @@
namespace
mediakit
{
namespace
mediakit
{
class
HlsRecorder
:
public
HlsMakerImp
,
public
TsMuxer
{
class
HlsRecorder
:
public
HlsMakerImp
,
public
TsMuxer
{
public
:
public
:
template
<
typename
...
ArgsType
>
template
<
typename
...
ArgsType
>
HlsRecorder
(
ArgsType
&&
...
args
)
:
HlsMakerImp
(
std
::
forward
<
ArgsType
>
(
args
)...){}
HlsRecorder
(
ArgsType
&&
...
args
)
:
HlsMakerImp
(
std
::
forward
<
ArgsType
>
(
args
)...){}
...
...
src/MediaFile/MediaRecorder.cpp
查看文件 @
d6e60e09
...
@@ -113,4 +113,18 @@ void MediaRecorder::addTrack(const Track::Ptr &track) {
...
@@ -113,4 +113,18 @@ void MediaRecorder::addTrack(const Track::Ptr &track) {
#endif //defined(ENABLE_MP4RECORD)
#endif //defined(ENABLE_MP4RECORD)
}
}
void
MediaRecorder
::
resetTracks
()
{
#if defined(ENABLE_HLS)
if
(
_hlsRecorder
)
{
_hlsRecorder
->
resetTracks
();
}
#endif //defined(ENABLE_HLS)
#if defined(ENABLE_MP4RECORD)
if
(
_mp4Recorder
)
{
_mp4Recorder
->
resetTracks
();
}
#endif //defined(ENABLE_MP4RECORD)
}
}
/* namespace mediakit */
}
/* namespace mediakit */
src/MediaFile/MediaRecorder.h
查看文件 @
d6e60e09
...
@@ -48,17 +48,22 @@ public:
...
@@ -48,17 +48,22 @@ public:
virtual
~
MediaRecorder
();
virtual
~
MediaRecorder
();
/**
/**
* 输入frame
* 输入frame
* @param frame
* @param frame
*/
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
/**
/**
* 添加track,内部会调用Track的clone方法
* 添加track,内部会调用Track的clone方法
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
* @param track
* @param track
*/
*/
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
/**
* 重置track
*/
void
resetTracks
()
override
;
private
:
private
:
#if defined(ENABLE_HLS)
#if defined(ENABLE_HLS)
std
::
shared_ptr
<
HlsRecorder
>
_hlsRecorder
;
std
::
shared_ptr
<
HlsRecorder
>
_hlsRecorder
;
...
...
src/MediaFile/TsMuxer.cpp
查看文件 @
d6e60e09
...
@@ -101,6 +101,8 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) {
...
@@ -101,6 +101,8 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) {
}
}
void
TsMuxer
::
resetTracks
()
{
void
TsMuxer
::
resetTracks
()
{
//通知片段中断
onTs
(
nullptr
,
0
,
0
,
0
);
uninit
();
uninit
();
init
();
init
();
}
}
...
...
src/MediaFile/TsMuxer.h
查看文件 @
d6e60e09
...
@@ -43,10 +43,10 @@ public:
...
@@ -43,10 +43,10 @@ public:
TsMuxer
();
TsMuxer
();
virtual
~
TsMuxer
();
virtual
~
TsMuxer
();
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
void
resetTracks
()
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
protected
:
protected
:
virtual
void
onTs
(
const
void
*
packet
,
int
bytes
,
uint32_t
timestamp
,
int
flags
)
=
0
;
virtual
void
onTs
(
const
void
*
packet
,
int
bytes
,
uint32_t
timestamp
,
int
flags
)
=
0
;
void
resetTracks
();
private
:
private
:
void
init
();
void
init
();
void
uninit
();
void
uninit
();
...
...
src/Player/PlayerProxy.cpp
查看文件 @
d6e60e09
...
@@ -122,7 +122,13 @@ void PlayerProxy::play(const string &strUrlTmp) {
...
@@ -122,7 +122,13 @@ void PlayerProxy::play(const string &strUrlTmp) {
for
(
auto
&
track
:
tracks
){
for
(
auto
&
track
:
tracks
){
track
->
delDelegate
(
strongSelf
->
_mediaMuxer
.
get
());
track
->
delDelegate
(
strongSelf
->
_mediaMuxer
.
get
());
}
}
strongSelf
->
_mediaMuxer
.
reset
();
GET_CONFIG
(
bool
,
resetWhenRePlay
,
General
::
kResetWhenRePlay
);
if
(
resetWhenRePlay
)
{
strongSelf
->
_mediaMuxer
.
reset
();
}
else
{
strongSelf
->
_mediaMuxer
->
resetTracks
();
}
}
}
//播放异常中断,延时重试播放
//播放异常中断,延时重试播放
if
(
*
piFailedCnt
<
strongSelf
->
_iRetryCount
||
strongSelf
->
_iRetryCount
<
0
)
{
if
(
*
piFailedCnt
<
strongSelf
->
_iRetryCount
||
strongSelf
->
_iRetryCount
<
0
)
{
...
@@ -138,7 +144,7 @@ void PlayerProxy::play(const string &strUrlTmp) {
...
@@ -138,7 +144,7 @@ void PlayerProxy::play(const string &strUrlTmp) {
if
(
directProxy
&&
_bEnableRtsp
){
if
(
directProxy
&&
_bEnableRtsp
){
mediaSource
=
std
::
make_shared
<
RtspMediaSource
>
(
_strVhost
,
_strApp
,
_strSrc
);
mediaSource
=
std
::
make_shared
<
RtspMediaSource
>
(
_strVhost
,
_strApp
,
_strSrc
);
}
}
}
else
if
(
dynamic_pointer_cast
<
RtmpPlayer
>
(
_parser
)){
}
else
if
(
dynamic_pointer_cast
<
RtmpPlayer
>
(
_parser
)){
//rtmp拉流
//rtmp拉流
if
(
_bEnableRtmp
){
if
(
_bEnableRtmp
){
mediaSource
=
std
::
make_shared
<
RtmpMediaSource
>
(
_strVhost
,
_strApp
,
_strSrc
);
mediaSource
=
std
::
make_shared
<
RtmpMediaSource
>
(
_strVhost
,
_strApp
,
_strSrc
);
...
@@ -154,7 +160,7 @@ PlayerProxy::~PlayerProxy() {
...
@@ -154,7 +160,7 @@ PlayerProxy::~PlayerProxy() {
_timer
.
reset
();
_timer
.
reset
();
}
}
void
PlayerProxy
::
rePlay
(
const
string
&
strUrl
,
int
iFailedCnt
){
void
PlayerProxy
::
rePlay
(
const
string
&
strUrl
,
int
iFailedCnt
){
auto
iDelay
=
MAX
(
2
*
1000
,
MIN
(
iFailedCnt
*
3000
,
60
*
1000
));
auto
iDelay
=
MAX
(
2
*
1000
,
MIN
(
iFailedCnt
*
3000
,
60
*
1000
));
weak_ptr
<
PlayerProxy
>
weakSelf
=
shared_from_this
();
weak_ptr
<
PlayerProxy
>
weakSelf
=
shared_from_this
();
_timer
=
std
::
make_shared
<
Timer
>
(
iDelay
/
1000.0
f
,[
weakSelf
,
strUrl
,
iFailedCnt
]()
{
_timer
=
std
::
make_shared
<
Timer
>
(
iDelay
/
1000.0
f
,[
weakSelf
,
strUrl
,
iFailedCnt
]()
{
//播放失败次数越多,则延时越长
//播放失败次数越多,则延时越长
...
@@ -213,7 +219,7 @@ public:
...
@@ -213,7 +219,7 @@ public:
if
(
_iAudioIndex
!=
iAudioIndex
){
if
(
_iAudioIndex
!=
iAudioIndex
){
_iAudioIndex
=
iAudioIndex
;
_iAudioIndex
=
iAudioIndex
;
auto
aacFrame
=
std
::
make_shared
<
AACFrameNoCacheAble
>
((
char
*
)
MUTE_ADTS_DATA
,
auto
aacFrame
=
std
::
make_shared
<
AACFrameNoCacheAble
>
((
char
*
)
MUTE_ADTS_DATA
,
MUTE_ADTS_DATA_LEN
,
MUTE_ADTS_DATA_LEN
,
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
FrameRingInterfaceDelegate
::
inputFrame
(
aacFrame
);
FrameRingInterfaceDelegate
::
inputFrame
(
aacFrame
);
}
}
...
@@ -224,15 +230,22 @@ private:
...
@@ -224,15 +230,22 @@ private:
};
};
void
PlayerProxy
::
onPlaySuccess
()
{
void
PlayerProxy
::
onPlaySuccess
()
{
GET_CONFIG
(
bool
,
resetWhenRePlay
,
General
::
kResetWhenRePlay
);
if
(
dynamic_pointer_cast
<
RtspMediaSource
>
(
_pMediaSrc
))
{
if
(
dynamic_pointer_cast
<
RtspMediaSource
>
(
_pMediaSrc
))
{
//rtsp拉流代理
//rtsp拉流代理
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
false
,
_bEnableRtmp
,
_bEnableHls
,
_bEnableMp4
));
if
(
resetWhenRePlay
||
!
_mediaMuxer
)
{
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
false
,
_bEnableRtmp
,
_bEnableHls
,
_bEnableMp4
));
}
}
else
if
(
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
))
{
}
else
if
(
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
))
{
//rtmp拉流代理
//rtmp拉流代理
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
_bEnableRtsp
,
false
,
_bEnableHls
,
_bEnableMp4
));
if
(
resetWhenRePlay
||
!
_mediaMuxer
)
{
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
_bEnableRtsp
,
false
,
_bEnableHls
,
_bEnableMp4
));
}
}
else
{
}
else
{
//其他拉流代理
//其他拉流代理
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
_bEnableRtsp
,
_bEnableRtmp
,
_bEnableHls
,
_bEnableMp4
));
if
(
resetWhenRePlay
||
!
_mediaMuxer
)
{
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
_bEnableRtsp
,
_bEnableRtmp
,
_bEnableHls
,
_bEnableMp4
));
}
}
}
_mediaMuxer
->
setListener
(
shared_from_this
());
_mediaMuxer
->
setListener
(
shared_from_this
());
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论