Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
胡斌
/
srs
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
winlin
2015-04-13 10:32:32 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
dcac9c69d5d9d606f2128e552c0447dcefecca5a
dcac9c69
1 parent
d2c63d81
fix #381, support reap hls/ts by gop or not. 2.0.160.
隐藏空白字符变更
内嵌
并排对比
正在显示
7 个修改的文件
包含
65 行增加
和
16 行删除
README.md
trunk/conf/full.conf
trunk/src/app/srs_app_config.cpp
trunk/src/app/srs_app_config.hpp
trunk/src/app/srs_app_hls.cpp
trunk/src/app/srs_app_hls.hpp
trunk/src/core/srs_core.hpp
README.md
查看文件 @
dcac9c6
...
...
@@ -562,6 +562,7 @@ Supported operating systems and hardware:
### SRS 2.0 history
*
v2.0, 2015-04-13, for
[
#381
](
https://github.com/winlinvip/simple-rtmp-server/issues/381
)
, support reap hls/ts by gop or not. 2.0.160.
*
v2.0, 2015-04-10, enhanced on_hls_notify, support HTTP GET when reap ts.
*
v2.0, 2015-04-10, refine the hls deviation for floor algorithm.
*
v2.0, 2015-04-08, for
[
#375
](
https://github.com/winlinvip/simple-rtmp-server/issues/375
)
, fix hls bug, keep cc continous between ts files. 2.0.159.
...
...
trunk/conf/full.conf
查看文件 @
dcac9c6
...
...
@@ -618,6 +618,11 @@ vhost with-hls.srs.com {
# @remark only used when on_hls_notify is config.
# default: 64
hls_nb_notify
64
;
# whether wait keyframe to reap segment,
# if off, reap segment when duration exceed the fragment,
# if on, reap segment when duration exceed and got keyframe.
# default: on
hls_wait_keyframe
on
;
# on_hls, never config in here, should config in http_hooks.
# for the hls http callback, @see http_hooks.on_hls of vhost hooks.callback.srs.com
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
dcac9c6
...
...
@@ -1487,7 +1487,7 @@ int SrsConfig::check_config()
string
m
=
conf
->
at
(
j
)
->
name
.
c_str
();
if
(
m
!=
"enabled"
&&
m
!=
"hls_entry_prefix"
&&
m
!=
"hls_path"
&&
m
!=
"hls_fragment"
&&
m
!=
"hls_window"
&&
m
!=
"hls_on_error"
&&
m
!=
"hls_storage"
&&
m
!=
"hls_mount"
&&
m
!=
"hls_td_ratio"
&&
m
!=
"hls_aof_ratio"
&&
m
!=
"hls_acodec"
&&
m
!=
"hls_vcodec"
&&
m
!=
"hls_m3u8_file"
&&
m
!=
"hls_ts_file"
&&
m
!=
"hls_ts_floor"
&&
m
!=
"hls_cleanup"
&&
m
!=
"hls_nb_notify"
&&
m
!=
"hls_m3u8_file"
&&
m
!=
"hls_ts_file"
&&
m
!=
"hls_ts_floor"
&&
m
!=
"hls_cleanup"
&&
m
!=
"hls_nb_notify"
&&
m
!=
"hls_wait_keyframe"
)
{
ret
=
ERROR_SYSTEM_CONFIG_INVALID
;
srs_error
(
"unsupported vhost hls directive %s, ret=%d"
,
m
.
c_str
(),
ret
);
...
...
@@ -3451,6 +3451,23 @@ bool SrsConfig::get_hls_cleanup(string vhost)
return
SRS_CONF_PERFER_TRUE
(
conf
->
arg0
());
}
bool
SrsConfig
::
get_hls_wait_keyframe
(
string
vhost
)
{
SrsConfDirective
*
hls
=
get_hls
(
vhost
);
if
(
!
hls
)
{
return
SRS_CONF_DEFAULT_HLS_WAIT_KEYFRAME
;
}
SrsConfDirective
*
conf
=
hls
->
get
(
"hls_wait_keyframe"
);
if
(
!
conf
||
conf
->
arg0
().
empty
())
{
return
SRS_CONF_DEFAULT_HLS_WAIT_KEYFRAME
;
}
return
SRS_CONF_PERFER_TRUE
(
conf
->
arg0
());
}
SrsConfDirective
*
SrsConfig
::
get_hds
(
const
string
&
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost
(
vhost
);
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
dcac9c6
...
...
@@ -63,6 +63,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONF_DEFAULT_HLS_ACODEC "aac"
#define SRS_CONF_DEFAULT_HLS_VCODEC "h264"
#define SRS_CONF_DEFAULT_HLS_CLEANUP true
#define SRS_CONF_DEFAULT_HLS_WAIT_KEYFRAME true
#define SRS_CONF_DEFAULT_HLS_NB_NOTIFY 64
#define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html/[app]/[stream].[timestamp].flv"
#define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session"
...
...
@@ -961,6 +962,10 @@ public:
*/
virtual
bool
get_hls_cleanup
(
std
::
string
vhost
);
/**
* whether reap the ts when got keyframe.
*/
virtual
bool
get_hls_wait_keyframe
(
std
::
string
vhost
);
/**
* get the size of bytes to read from cdn network, for the on_hls_notify callback,
* that is, to read max bytes of the bytes from the callback, or timeout or error.
*/
...
...
trunk/src/app/srs_app_hls.cpp
查看文件 @
dcac9c6
...
...
@@ -267,6 +267,7 @@ SrsHlsMuxer::SrsHlsMuxer()
hls_aof_ratio
=
1.0
;
deviation_ts
=
0
;
hls_cleanup
=
true
;
hls_wait_keyframe
=
true
;
previous_floor_ts
=
0
;
accept_floor_ts
=
0
;
hls_ts_floor
=
false
;
...
...
@@ -335,7 +336,7 @@ int SrsHlsMuxer::initialize(ISrsHlsHandler* h)
int
SrsHlsMuxer
::
update_config
(
SrsRequest
*
r
,
string
entry_prefix
,
string
path
,
string
m3u8_file
,
string
ts_file
,
double
fragment
,
double
window
,
bool
ts_floor
,
double
aof_ratio
,
bool
cleanup
bool
ts_floor
,
double
aof_ratio
,
bool
cleanup
,
bool
wait_keyframe
)
{
int
ret
=
ERROR_SUCCESS
;
...
...
@@ -349,6 +350,7 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
hls_aof_ratio
=
aof_ratio
;
hls_ts_floor
=
ts_floor
;
hls_cleanup
=
cleanup
;
hls_wait_keyframe
=
wait_keyframe
;
previous_floor_ts
=
0
;
accept_floor_ts
=
0
;
hls_window
=
window
;
...
...
@@ -542,6 +544,11 @@ bool SrsHlsMuxer::is_segment_overflow()
return
current
->
duration
>=
hls_fragment
+
deviation
;
}
bool
SrsHlsMuxer
::
wait_keyframe
()
{
return
hls_wait_keyframe
;
}
bool
SrsHlsMuxer
::
is_segment_absolutely_overflow
()
{
// @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-83553950
...
...
@@ -862,6 +869,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
std
::
string
m3u8_file
=
_srs_config
->
get_hls_m3u8_file
(
vhost
);
std
::
string
ts_file
=
_srs_config
->
get_hls_ts_file
(
vhost
);
bool
cleanup
=
_srs_config
->
get_hls_cleanup
(
vhost
);
bool
wait_keyframe
=
_srs_config
->
get_hls_wait_keyframe
(
vhost
);
// the audio overflow, for pure audio to reap segment.
double
hls_aof_ratio
=
_srs_config
->
get_hls_aof_ratio
(
vhost
);
// whether use floor(timestamp/hls_fragment) for variable timestamp
...
...
@@ -873,7 +881,7 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
// open muxer
if
((
ret
=
muxer
->
update_config
(
req
,
entry_prefix
,
path
,
m3u8_file
,
ts_file
,
hls_fragment
,
hls_window
,
ts_floor
,
hls_aof_ratio
,
cleanup
))
!=
ERROR_SUCCESS
cleanup
,
wait_keyframe
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"m3u8 muxer update config failed. ret=%d"
,
ret
);
return
ret
;
...
...
@@ -883,9 +891,9 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
srs_error
(
"m3u8 muxer open segment failed. ret=%d"
,
ret
);
return
ret
;
}
srs_trace
(
"hls: win=%.2f, frag=%.2f, prefix=%s, path=%s, m3u8=%s, ts=%s, aof=%.2f, floor=%d"
,
srs_trace
(
"hls: win=%.2f, frag=%.2f, prefix=%s, path=%s, m3u8=%s, ts=%s, aof=%.2f, floor=%d
, clean=%d, waitk=%d
"
,
hls_window
,
hls_fragment
,
entry_prefix
.
c_str
(),
path
.
c_str
(),
m3u8_file
.
c_str
(),
ts_file
.
c_str
(),
hls_aof_ratio
,
ts_floor
);
ts_file
.
c_str
(),
hls_aof_ratio
,
ts_floor
,
cleanup
,
wait_keyframe
);
return
ret
;
}
...
...
@@ -972,17 +980,25 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
return
ret
;
}
// new segment when:
// 1. base on gop(IDR).
// 2. some gops duration overflow.
if
(
sample
->
frame_type
==
SrsCodecVideoAVCFrameKeyFrame
&&
muxer
->
is_segment_overflow
())
{
if
(
!
sample
->
has_idr
)
{
srs_warn
(
"hls: ts starts without IDR, first nalu=%d, idr=%d"
,
sample
->
first_nalu_type
,
sample
->
has_idr
);
}
if
((
ret
=
reap_segment
(
"video"
,
muxer
,
cache
->
video
->
dts
))
!=
ERROR_SUCCESS
)
{
// when segment overflow, reap if possible.
if
(
muxer
->
is_segment_overflow
())
{
// do reap ts if any of:
// a. wait keyframe and got keyframe.
// b. always reap when not wait keyframe.
if
(
!
muxer
->
wait_keyframe
()
||
sample
->
frame_type
==
SrsCodecVideoAVCFrameKeyFrame
)
{
// when wait keyframe, there must exists idr frame in sample.
if
(
!
sample
->
has_idr
&&
muxer
->
wait_keyframe
())
{
srs_warn
(
"hls: ts starts without IDR, first nalu=%d, idr=%d"
,
sample
->
first_nalu_type
,
sample
->
has_idr
);
}
// reap the segment, which will also flush the video.
if
((
ret
=
reap_segment
(
"video"
,
muxer
,
cache
->
video
->
dts
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
// the video must be flushed, just return.
return
ret
;
}
return
ret
;
}
// flush video when got one
...
...
trunk/src/app/srs_app_hls.hpp
查看文件 @
dcac9c6
...
...
@@ -207,6 +207,7 @@ private:
std
::
string
hls_path
;
std
::
string
hls_ts_file
;
bool
hls_cleanup
;
bool
hls_wait_keyframe
;
std
::
string
m3u8_dir
;
double
hls_aof_ratio
;
double
hls_fragment
;
...
...
@@ -270,7 +271,7 @@ public:
virtual
int
update_config
(
SrsRequest
*
r
,
std
::
string
entry_prefix
,
std
::
string
path
,
std
::
string
m3u8_file
,
std
::
string
ts_file
,
double
fragment
,
double
window
,
bool
ts_floor
,
double
aof_ratio
,
bool
cleanup
);
bool
cleanup
,
bool
wait_keyframe
);
/**
* open a new segment(a new ts file),
* @param segment_start_dts use to calc the segment duration,
...
...
@@ -284,6 +285,10 @@ public:
*/
virtual
bool
is_segment_overflow
();
/**
* whether wait keyframe to reap the ts.
*/
virtual
bool
wait_keyframe
();
/**
* whether segment absolutely overflow, for pure audio to reap segment,
* that is whether the current segment duration>=2*(the segment in config)
* @see https://github.com/winlinvip/simple-rtmp-server/issues/151#issuecomment-71155184
...
...
trunk/src/core/srs_core.hpp
查看文件 @
dcac9c6
...
...
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_REVISION 1
59
#define VERSION_REVISION 1
60
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
...
...
请
注册
或
登录
后发表评论