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-07-14 11:32:40 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
5f91fbc970ab09907403d5b2ebd72c869224633e
5f91fbc9
2 parents
677567d9
d995726f
merge from 2.0release
隐藏空白字符变更
内嵌
并排对比
正在显示
10 个修改的文件
包含
97 行增加
和
34 行删除
README.md
trunk/research/librtmp/srs_ingest_flv.c
trunk/src/app/srs_app_config.cpp
trunk/src/app/srs_app_config.hpp
trunk/src/app/srs_app_forward.cpp
trunk/src/app/srs_app_hls.cpp
trunk/src/app/srs_app_hls.hpp
trunk/src/app/srs_app_http_stream.cpp
trunk/src/app/srs_app_server.cpp
trunk/src/app/srs_app_source.cpp
README.md
查看文件 @
5f91fbc
#Simple-RTMP-Server
SRS/3.0
,开发代号:
[
OuXuli
](
https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#release30
)
SRS/3.0
,
[
OuXuli
](
https://github.com/simple-rtmp-server/srs/wiki/v1_CN_Product#release30
)
SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码。
<br/>
SRS is industrial-strength live streaming cluster, for the best conceptual integrity and the simplest implementation.
Download from github.io:
[
Centos6-x86_64
][
centos0
]
,
[
more...
][
more0
]
<br/>
Download from ossrs.net:
[
Centos6-x86_64
][
centos1
]
,
[
more...
][
more1
]
<br/>
Contact by QQ or Skype, read
[
Contact
][
contact
]
Website for SRS/2.0, read SRS 2.0
[
Chinese
][
srs2_CN
]
or
[
English
][
srs2_EN
]
.
## Why SRS?
...
...
@@ -1025,5 +1025,6 @@ Winlin
[
centos0
]:
http://winlinvip.github.io/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip
[
centos1
]:
http://www.ossrs.net/srs.release/releases/files/SRS-CentOS6-x86_64-1.0.32.zip
[
srs2_CN
]:
https://github.com/simple-rtmp-server/srs/wiki/v2_CN_Home
[
srs2_EN
]:
https://github.com/simple-rtmp-server/srs/wiki/v2_EN_Home
...
...
trunk/research/librtmp/srs_ingest_flv.c
查看文件 @
5f91fbc
...
...
@@ -38,6 +38,7 @@ int proxy(srs_flv_t flv, srs_rtmp_t ortmp);
int
connect_oc
(
srs_rtmp_t
ortmp
);
#define RE_PULSE_MS 300
#define RE_PULSE_JITTER_MS 3000
int64_t
re_create
();
void
re_update
(
int64_t
re
,
int32_t
starttime
,
u_int32_t
time
);
void
re_cleanup
(
int64_t
re
,
int32_t
starttime
,
u_int32_t
time
);
...
...
@@ -256,7 +257,7 @@ void re_update(int64_t re, int32_t starttime, u_int32_t time)
// send by pulse algorithm.
int64_t
now
=
srs_utils_time_ms
();
int64_t
diff
=
time
-
starttime
-
(
now
-
re
);
if
(
diff
>
RE_PULSE_MS
)
{
if
(
diff
>
RE_PULSE_MS
&&
diff
<
RE_PULSE_JITTER_MS
)
{
usleep
((
useconds_t
)(
diff
*
1000
));
}
}
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
5f91fbc
...
...
@@ -853,6 +853,7 @@ int SrsConfig::reload_vhost(SrsConfDirective* old_root)
}
}
// TODO: reload new http_remux in on_vhost_add
// http_remux, only one per vhost.
if
(
get_vhost_http_remux_enabled
(
vhost
))
{
for
(
it
=
subscribes
.
begin
();
it
!=
subscribes
.
end
();
++
it
)
{
...
...
@@ -4417,3 +4418,18 @@ bool srs_config_dvr_is_plan_append(string plan)
{
return
plan
==
SRS_CONF_DEFAULT_DVR_PLAN_APPEND
;
}
bool
srs_stream_caster_is_udp
(
string
caster
)
{
return
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP
;
}
bool
srs_stream_caster_is_rtsp
(
string
caster
)
{
return
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_RTSP
;
}
bool
srs_stream_caster_is_flv
(
string
caster
)
{
return
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_FLV
;
}
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
5f91fbc
...
...
@@ -1143,6 +1143,9 @@ extern bool srs_config_ingest_is_stream(std::string type);
extern
bool
srs_config_dvr_is_plan_segment
(
std
::
string
plan
);
extern
bool
srs_config_dvr_is_plan_session
(
std
::
string
plan
);
extern
bool
srs_config_dvr_is_plan_append
(
std
::
string
plan
);
extern
bool
srs_stream_caster_is_udp
(
std
::
string
caster
);
extern
bool
srs_stream_caster_is_rtsp
(
std
::
string
caster
);
extern
bool
srs_stream_caster_is_flv
(
std
::
string
caster
);
// global config
extern
SrsConfig
*
_srs_config
;
...
...
trunk/src/app/srs_app_forward.cpp
查看文件 @
5f91fbc
...
...
@@ -164,7 +164,7 @@ int SrsForwarder::on_meta_data(SrsSharedPtrMessage* shared_metadata)
SrsSharedPtrMessage
*
metadata
=
shared_metadata
->
copy
();
// TODO: FIXME: config the jitter of Forwarder.
if
((
ret
=
jitter
->
correct
(
metadata
,
SrsRtmpJitterAlgorithm
FULL
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
jitter
->
correct
(
metadata
,
SrsRtmpJitterAlgorithm
OFF
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
metadata
);
return
ret
;
}
...
...
@@ -183,7 +183,7 @@ int SrsForwarder::on_audio(SrsSharedPtrMessage* shared_audio)
SrsSharedPtrMessage
*
msg
=
shared_audio
->
copy
();
// TODO: FIXME: config the jitter of Forwarder.
if
((
ret
=
jitter
->
correct
(
msg
,
SrsRtmpJitterAlgorithm
FULL
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
jitter
->
correct
(
msg
,
SrsRtmpJitterAlgorithm
OFF
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
msg
);
return
ret
;
}
...
...
@@ -207,7 +207,7 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* shared_video)
SrsSharedPtrMessage
*
msg
=
shared_video
->
copy
();
// TODO: FIXME: config the jitter of Forwarder.
if
((
ret
=
jitter
->
correct
(
msg
,
SrsRtmpJitterAlgorithm
FULL
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
jitter
->
correct
(
msg
,
SrsRtmpJitterAlgorithm
OFF
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
msg
);
return
ret
;
}
...
...
trunk/src/app/srs_app_hls.cpp
查看文件 @
5f91fbc
...
...
@@ -53,6 +53,8 @@ using namespace std;
// drop the segment when duration of ts too small.
#define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
// when hls timestamp jump, reset it.
#define SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS 300
// fragment plus the deviation percent.
#define SRS_HLS_FLOOR_REAP_PERCENT 0.3
...
...
@@ -161,6 +163,11 @@ void SrsHlsSegment::update_duration(int64_t current_frame_dts)
// update the segment duration, which is nagetive,
// just ignore it.
if
(
current_frame_dts
<
segment_start_dts
)
{
// for atc and timestamp jump, reset the start dts.
if
(
current_frame_dts
<
segment_start_dts
-
SRS_AUTO_HLS_SEGMENT_TIMESTAMP_JUMP_MS
*
90
)
{
srs_warn
(
"hls timestamp jump %"
PRId64
"=>%"
PRId64
,
segment_start_dts
,
current_frame_dts
);
segment_start_dts
=
current_frame_dts
;
}
return
;
}
...
...
@@ -280,7 +287,7 @@ SrsHlsMuxer::SrsHlsMuxer()
previous_floor_ts
=
0
;
accept_floor_ts
=
0
;
hls_ts_floor
=
false
;
target_duration
=
0
;
max_td
=
0
;
_sequence_no
=
0
;
current
=
NULL
;
acodec
=
SrsCodecAudioReserved1
;
...
...
@@ -400,10 +407,8 @@ int SrsHlsMuxer::update_config(SrsRequest* r, string entry_prefix,
m3u8_url
=
srs_path_build_stream
(
m3u8_file
,
req
->
vhost
,
req
->
app
,
req
->
stream
);
m3u8
=
path
+
"/"
+
m3u8_url
;
// we always keep the target duration increasing.
int
max_td
=
srs_max
(
target_duration
,
(
int
)(
fragment
*
_srs_config
->
get_hls_td_ratio
(
r
->
vhost
)));
srs_info
(
"hls update target duration %d=>%d, aof=%.2f"
,
target_duration
,
max_td
,
aof_ratio
);
target_duration
=
max_td
;
// when update config, reset the history target duration.
max_td
=
(
int
)(
fragment
*
_srs_config
->
get_hls_td_ratio
(
r
->
vhost
));
std
::
string
storage
=
_srs_config
->
get_hls_storage
(
r
->
vhost
);
if
(
storage
==
"ram"
)
{
...
...
@@ -699,7 +704,9 @@ int SrsHlsMuxer::segment_close(string log_desc)
srs_assert
(
it
==
segments
.
end
());
// valid, add to segments if segment duration is ok
if
(
current
->
duration
*
1000
>=
SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS
)
{
// when too small, it maybe not enough data to play.
// when too large, it maybe timestamp corrupt.
if
(
current
->
duration
*
1000
>=
SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS
&&
(
int
)
current
->
duration
<=
max_td
)
{
segments
.
push_back
(
current
);
// use async to call the http hooks, for it will cause thread switch.
...
...
@@ -750,7 +757,6 @@ int SrsHlsMuxer::segment_close(string log_desc)
// rename from tmp to real path
std
::
string
tmp_file
=
current
->
full_path
+
".tmp"
;
if
(
should_write_file
)
{
unlink
(
tmp_file
.
c_str
());
if
(
unlink
(
tmp_file
.
c_str
())
<
0
)
{
srs_warn
(
"ignore unlink path failed, file=%s."
,
tmp_file
.
c_str
());
}
...
...
@@ -817,6 +823,11 @@ int SrsHlsMuxer::refresh_m3u8()
{
int
ret
=
ERROR_SUCCESS
;
// no segments, also no m3u8, return.
if
(
segments
.
size
()
==
0
)
{
return
ret
;
}
std
::
string
temp_m3u8
=
m3u8
+
".temp"
;
if
((
ret
=
_refresh_m3u8
(
temp_m3u8
))
==
ERROR_SUCCESS
)
{
if
(
should_write_file
&&
rename
(
temp_m3u8
.
c_str
(),
m3u8
.
c_str
())
<
0
)
{
...
...
@@ -826,7 +837,11 @@ int SrsHlsMuxer::refresh_m3u8()
}
// remove the temp file.
unlink
(
temp_m3u8
.
c_str
());
if
(
srs_path_exists
(
temp_m3u8
))
{
if
(
unlink
(
temp_m3u8
.
c_str
())
<
0
)
{
srs_warn
(
"ignore remove m3u8 failed, %s"
,
temp_m3u8
.
c_str
());
}
}
return
ret
;
}
...
...
@@ -861,6 +876,9 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
ss
<<
"#EXT-X-MEDIA-SEQUENCE:"
<<
first
->
sequence_no
<<
SRS_CONSTS_LF
;
srs_verbose
(
"write m3u8 sequence success."
);
// iterator shared for td generation and segemnts wrote.
std
::
vector
<
SrsHlsSegment
*>::
iterator
it
;
// #EXT-X-TARGETDURATION:4294967295\n
/**
* @see hls-m3u8-draft-pantos-http-live-streaming-12.pdf, page 25
...
...
@@ -871,11 +889,13 @@ int SrsHlsMuxer::_refresh_m3u8(string m3u8_file)
* typical target duration is 10 seconds.
*/
// @see https://github.com/simple-rtmp-server/srs/issues/304#issuecomment-74000081
std
::
vector
<
SrsHlsSegment
*>::
iterator
it
;
int
target_duration
=
0
;
for
(
it
=
segments
.
begin
();
it
!=
segments
.
end
();
++
it
)
{
SrsHlsSegment
*
segment
=
*
it
;
target_duration
=
srs_max
(
target_duration
,
(
int
)
ceil
(
segment
->
duration
));
}
target_duration
=
srs_max
(
target_duration
,
max_td
);
ss
<<
"#EXT-X-TARGETDURATION:"
<<
target_duration
<<
SRS_CONSTS_LF
;
srs_verbose
(
"write m3u8 duration success."
);
...
...
@@ -1335,7 +1355,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* shared_audio)
}
// TODO: FIXME: config the jitter of HLS.
if
((
ret
=
jitter
->
correct
(
audio
,
SrsRtmpJitterAlgorithm
FULL
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
jitter
->
correct
(
audio
,
SrsRtmpJitterAlgorithm
OFF
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"rtmp jitter correct audio failed. ret=%d"
,
ret
);
return
ret
;
}
...
...
@@ -1393,7 +1413,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* shared_video)
}
// TODO: FIXME: config the jitter of HLS.
if
((
ret
=
jitter
->
correct
(
video
,
SrsRtmpJitterAlgorithm
FULL
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
jitter
->
correct
(
video
,
SrsRtmpJitterAlgorithm
OFF
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"rtmp jitter correct video failed. ret=%d"
,
ret
);
return
ret
;
}
...
...
trunk/src/app/srs_app_hls.hpp
查看文件 @
5f91fbc
...
...
@@ -233,7 +233,7 @@ private:
int64_t
previous_floor_ts
;
private
:
int
_sequence_no
;
int
target_duration
;
int
max_td
;
std
::
string
m3u8
;
std
::
string
m3u8_url
;
private
:
...
...
trunk/src/app/srs_app_http_stream.cpp
查看文件 @
5f91fbc
...
...
@@ -805,7 +805,14 @@ int SrsHttpStreamServer::http_mount(SrsSource* s, SrsRequest* r)
entry
->
cache
=
new
SrsStreamCache
(
s
,
r
);
entry
->
stream
=
new
SrsLiveStream
(
s
,
r
,
entry
->
cache
);
srs_assert
(
!
tmpl
->
req
);
// TODO: FIXME: maybe refine the logic of http remux service.
// if user push streams followed:
// rtmp://test.com/live/stream1
// rtmp://test.com/live/stream2
// and they will using the same template, such as: [vhost]/[app]/[stream].flv
// so, need to free last request object, otherwise, it will cause memory leak.
srs_freep
(
tmpl
->
req
);
tmpl
->
source
=
s
;
tmpl
->
req
=
r
->
copy
();
...
...
@@ -1170,8 +1177,8 @@ int SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph)
std
::
string
sid
=
r
->
get_stream_url
();
// check if the stream is enabled.
if
(
sflvs
.
find
(
sid
)
!=
sflvs
.
end
())
{
SrsLiveEntry
*
entry
=
sflvs
[
sid
];
if
(
!
entry
->
stream
->
entry
->
enabled
)
{
SrsLiveEntry
*
s_entry
=
sflvs
[
sid
];
if
(
!
s_entry
->
stream
->
entry
->
enabled
)
{
srs_error
(
"stream is disabled, hijack failed. ret=%d"
,
ret
);
return
ret
;
}
...
...
@@ -1228,7 +1235,9 @@ int SrsHttpStreamServer::initialize_flv_streaming()
continue
;
}
initialize_flv_entry
(
conf
->
arg0
());
if
((
ret
=
initialize_flv_entry
(
conf
->
arg0
()))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
}
return
ret
;
}
...
...
trunk/src/app/srs_app_server.cpp
查看文件 @
5f91fbc
...
...
@@ -1120,11 +1120,11 @@ int SrsServer::listen_stream_caster()
SrsListener
*
listener
=
NULL
;
std
::
string
caster
=
_srs_config
->
get_stream_caster_engine
(
stream_caster
);
if
(
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_MPEGTS_OVER_UDP
)
{
if
(
srs_stream_caster_is_udp
(
caster
)
)
{
listener
=
new
SrsUdpCasterListener
(
this
,
SrsListenerMpegTsOverUdp
,
stream_caster
);
}
else
if
(
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_RTSP
)
{
}
else
if
(
srs_stream_caster_is_rtsp
(
caster
)
)
{
listener
=
new
SrsRtspListener
(
this
,
SrsListenerRtsp
,
stream_caster
);
}
else
if
(
caster
==
SRS_CONF_DEFAULT_STREAM_CASTER_FLV
)
{
}
else
if
(
srs_stream_caster_is_flv
(
caster
)
)
{
listener
=
new
SrsHttpFlvListener
(
this
,
SrsListenerFlv
,
stream_caster
);
}
else
{
ret
=
ERROR_STREAM_CASTER_ENGINE
;
...
...
trunk/src/app/srs_app_source.cpp
查看文件 @
5f91fbc
...
...
@@ -55,8 +55,8 @@ using namespace std;
// 115 packets is 3s.
#define SRS_PURE_AUDIO_GUESS_COUNT 115
// when got these videos or audios, mix ok.
#define SRS_MIX_CORRECT_MIX_AV 10
// when got these videos or audios, pure audio or video, mix ok.
#define SRS_MIX_CORRECT_PURE_AV 10
int
_srs_time_jitter_string2int
(
std
::
string
time_jitter
)
{
...
...
@@ -849,12 +849,25 @@ void SrsMixQueue::push(SrsSharedPtrMessage* msg)
SrsSharedPtrMessage
*
SrsMixQueue
::
pop
()
{
// when got 10+ videos or audios, mix ok.
// when got 1 video and 1 audio, mix ok.
if
(
nb_videos
<
SRS_MIX_CORRECT_MIX_AV
&&
nb_audios
<
SRS_MIX_CORRECT_MIX_AV
)
{
if
(
nb_videos
<
1
||
nb_audios
<
1
)
{
return
NULL
;
}
bool
mix_ok
=
false
;
// pure video
if
(
nb_videos
>=
SRS_MIX_CORRECT_PURE_AV
&&
nb_audios
==
0
)
{
mix_ok
=
true
;
}
// pure audio
if
(
nb_audios
>=
SRS_MIX_CORRECT_PURE_AV
&&
nb_videos
==
0
)
{
mix_ok
=
true
;
}
// got 1 video and 1 audio, mix ok.
if
(
nb_videos
>=
1
&&
nb_audios
>=
1
)
{
mix_ok
=
true
;
}
if
(
!
mix_ok
)
{
return
NULL
;
}
// pop the first msg.
...
...
请
注册
或
登录
后发表评论