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-10 12:01:45 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
e3c6e52547988e81f15d3857a9c8bb5db3d3b379
e3c6e525
1 parent
7dbc95e0
enhanced on_hls_notify, support HTTP GET when reap ts.
隐藏空白字符变更
内嵌
并排对比
正在显示
9 个修改的文件
包含
183 行增加
和
13 行删除
README.md
trunk/conf/full.conf
trunk/research/api-server/server.py
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/app/srs_app_http_hooks.cpp
trunk/src/app/srs_app_http_hooks.hpp
README.md
查看文件 @
e3c6e52
...
...
@@ -562,6 +562,7 @@ Supported operating systems and hardware:
### SRS 2.0 history
*
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.
*
v2.0, 2015-04-04, for
[
#304
](
https://github.com/winlinvip/simple-rtmp-server/issues/304
)
, rewrite annexb mux for ts, refer to apple sample. 2.0.157.
...
...
trunk/conf/full.conf
查看文件 @
e3c6e52
...
...
@@ -618,6 +618,15 @@ vhost with-hls.srs.com {
# for the hls http callback, @see http_hooks.on_hls of vhost hooks.callback.srs.com
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DeliveryHLS#http-callback
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DeliveryHLS#http-callback
# on_hls_notify, never config in here, should config in http_hooks.
# we support the variables to generate the notify url:
# [app], replace with the app.
# [stream], replace with the stream.
# [ts_url], replace with the ts url.
# for the hls http callback, @see http_hooks.on_hls_notify of vhost hooks.callback.srs.com
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DeliveryHLS#on-hls-notify
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DeliveryHLS#on-hls-notify
}
}
# the vhost with hls disabled.
...
...
@@ -768,6 +777,14 @@ vhost hooks.callback.srs.com {
# an int value specifies the error code(0 corresponding to success):
# 0
on_hls
http
://
127
.
0
.
0
.
1
:
8085
/
api
/
v1
/
hls
http
://
localhost
:
8085
/
api
/
v1
/
hls
;
# when srs reap a ts file of hls, call this hook,
# used to push file to cdn network, by get the ts file from cdn network.
# so we use HTTP GET and use the variable following:
# [app], replace with the app.
# [stream], replace with the stream.
# [ts_url], replace with the ts url.
# ignore any return data of server.
on_hls_notify
http
://
127
.
0
.
0
.
1
:
8085
/
api
/
v1
/
hls
/[
app
]/[
stream
][
ts_url
];
}
}
...
...
trunk/research/api-server/server.py
查看文件 @
e3c6e52
...
...
@@ -314,10 +314,24 @@ handle the hls requests: hls stream.
class
RESTHls
(
object
):
exposed
=
True
def
GET
(
self
):
'''
for SRS hook: on_hls_notify
on_hls_notify:
when srs reap a ts file of hls, call this hook,
used to push file to cdn network, by get the ts file from cdn network.
so we use HTTP GET and use the variable following:
[app], replace with the app.
[stream], replace with the stream.
[ts_url], replace with the ts url.
ignore any return data of server.
'''
def
GET
(
self
,
*
args
,
**
kwargs
):
enable_crossdomain
()
hls
=
{}
hls
=
{
"args"
:
args
,
"kwargs"
:
kwargs
}
return
json
.
dumps
(
hls
)
'''
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
e3c6e52
...
...
@@ -1499,7 +1499,7 @@ int SrsConfig::check_config()
string
m
=
conf
->
at
(
j
)
->
name
.
c_str
();
if
(
m
!=
"enabled"
&&
m
!=
"on_connect"
&&
m
!=
"on_close"
&&
m
!=
"on_publish"
&&
m
!=
"on_unpublish"
&&
m
!=
"on_play"
&&
m
!=
"on_stop"
&&
m
!=
"on_dvr"
&&
m
!=
"on_hls"
&&
m
!=
"on_dvr"
&&
m
!=
"on_hls"
&&
m
!=
"on_hls_notify"
)
{
ret
=
ERROR_SYSTEM_CONFIG_INVALID
;
srs_error
(
"unsupported vhost http_hooks directive %s, ret=%d"
,
m
.
c_str
(),
ret
);
...
...
@@ -2429,6 +2429,17 @@ SrsConfDirective* SrsConfig::get_vhost_on_hls(string vhost)
return
conf
->
get
(
"on_hls"
);
}
SrsConfDirective
*
SrsConfig
::
get_vhost_on_hls_notify
(
string
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost_http_hooks
(
vhost
);
if
(
!
conf
)
{
return
NULL
;
}
return
conf
->
get
(
"on_hls_notify"
);
}
bool
SrsConfig
::
get_bw_check_enabled
(
string
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost
(
vhost
);
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
e3c6e52
...
...
@@ -646,6 +646,11 @@ public:
* @return the on_hls callback directive, the args is the url to callback.
*/
virtual
SrsConfDirective
*
get_vhost_on_hls
(
std
::
string
vhost
);
/**
* get the on_hls_notify callbacks of vhost.
* @return the on_hls_notify callback directive, the args is the url to callback.
*/
virtual
SrsConfDirective
*
get_vhost_on_hls_notify
(
std
::
string
vhost
);
// bwct(bandwidth check tool) section
public:
/**
...
...
trunk/src/app/srs_app_hls.cpp
查看文件 @
e3c6e52
...
...
@@ -213,9 +213,49 @@ int SrsDvrAsyncCallOnHls::call()
string
SrsDvrAsyncCallOnHls
::
to_string
()
{
std
::
stringstream
ss
;
ss
<<
"vhost="
<<
req
->
vhost
<<
", file="
<<
path
;
return
ss
.
str
();
return
"on_hls: "
+
path
;
}
SrsDvrAsyncCallOnHlsNotify
::
SrsDvrAsyncCallOnHlsNotify
(
SrsRequest
*
r
,
string
u
)
{
req
=
r
;
ts_url
=
u
;
}
SrsDvrAsyncCallOnHlsNotify
::~
SrsDvrAsyncCallOnHlsNotify
()
{
}
int
SrsDvrAsyncCallOnHlsNotify
::
call
()
{
int
ret
=
ERROR_SUCCESS
;
#ifdef SRS_AUTO_HTTP_CALLBACK
// http callback for on_hls_notify in config.
if
(
_srs_config
->
get_vhost_http_hooks_enabled
(
req
->
vhost
))
{
// HTTP: on_hls
SrsConfDirective
*
on_hls
=
_srs_config
->
get_vhost_on_hls_notify
(
req
->
vhost
);
if
(
!
on_hls
)
{
srs_info
(
"ignore the empty http callback: on_hls_notify"
);
return
ret
;
}
for
(
int
i
=
0
;
i
<
(
int
)
on_hls
->
args
.
size
();
i
++
)
{
std
::
string
url
=
on_hls
->
args
.
at
(
i
);
if
((
ret
=
SrsHttpHooks
::
on_hls_notify
(
url
,
req
,
ts_url
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"hook client on_hls_notify failed. url=%s, ret=%d"
,
url
.
c_str
(),
ret
);
return
ret
;
}
}
}
#endif
return
ret
;
}
string
SrsDvrAsyncCallOnHlsNotify
::
to_string
()
{
return
"on_hls_notify: "
+
ts_url
;
}
SrsHlsMuxer
::
SrsHlsMuxer
()
...
...
@@ -414,19 +454,23 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
// when reap ts, adjust the deviation.
deviation_ts
=
(
int
)(
accept_floor_ts
-
current_floor_ts
);
// we always ensure the piece is increase one by one.
std
::
stringstream
ts_floor
;
ts_floor
<<
accept_floor_ts
;
ts_file
=
srs_string_replace
(
ts_file
,
"[timestamp]"
,
ts_floor
.
str
());
// dup/jmp detect for ts in floor mode.
if
(
previous_floor_ts
&&
previous_floor_ts
!=
current_floor_ts
-
1
)
{
srs_warn
(
"hls: dup or jmp for floor ts, previous=%"
PRId64
", current=%"
PRId64
", accept=%"
PRId64
", deviation=%d"
,
previous_floor_ts
,
current_floor_ts
,
accept_floor_ts
,
deviation_ts
);
}
previous_floor_ts
=
current_floor_ts
;
// we always ensure the piece is increase one by one.
std
::
stringstream
ts_floor
;
ts_floor
<<
accept_floor_ts
;
ts_file
=
srs_string_replace
(
ts_file
,
"[timestamp]"
,
ts_floor
.
str
());
// TODO: FIMXE: we must use the accept ts floor time to generate the hour variable.
ts_file
=
srs_path_build_timestamp
(
ts_file
);
}
else
{
ts_file
=
srs_path_build_timestamp
(
ts_file
);
}
ts_file
=
srs_path_build_timestamp
(
ts_file
);
if
(
true
)
{
std
::
stringstream
ss
;
ss
<<
current
->
sequence_no
;
...
...
@@ -593,6 +637,11 @@ int SrsHlsMuxer::segment_close(string log_desc)
if
((
ret
=
async
->
call
(
new
SrsDvrAsyncCallOnHls
(
req
,
current
->
full_path
,
current
->
sequence_no
,
current
->
duration
)))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
// use async to call the http hooks, for it will cause thread switch.
if
((
ret
=
async
->
call
(
new
SrsDvrAsyncCallOnHlsNotify
(
req
,
current
->
uri
)))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
srs_info
(
"%s reap ts segment, sequence_no=%d, uri=%s, duration=%.2f, start=%"
PRId64
,
log_desc
.
c_str
(),
current
->
sequence_no
,
current
->
uri
.
c_str
(),
current
->
duration
,
...
...
trunk/src/app/srs_app_hls.hpp
查看文件 @
e3c6e52
...
...
@@ -157,7 +157,7 @@ public:
};
/**
* the
dvr async call.
* the
hls async call: on_hls
*/
class
SrsDvrAsyncCallOnHls
:
public
ISrsDvrAsyncCall
{
...
...
@@ -175,6 +175,22 @@ public:
};
/**
* the hls async call: on_hls_notify
*/
class
SrsDvrAsyncCallOnHlsNotify
:
public
ISrsDvrAsyncCall
{
private
:
std
::
string
ts_url
;
SrsRequest
*
req
;
public
:
SrsDvrAsyncCallOnHlsNotify
(
SrsRequest
*
r
,
std
::
string
u
);
virtual
~
SrsDvrAsyncCallOnHlsNotify
();
public
:
virtual
int
call
();
virtual
std
::
string
to_string
();
};
/**
* muxer the HLS stream(m3u8 and ts files).
* generally, the m3u8 muxer only provides methods to open/close segments,
* to flush video/audio, without any mechenisms.
...
...
trunk/src/app/srs_app_http_hooks.cpp
查看文件 @
e3c6e52
...
...
@@ -37,6 +37,7 @@ using namespace std;
#include <srs_app_http_client.hpp>
#include <srs_core_autofree.hpp>
#include <srs_app_config.hpp>
#include <srs_kernel_utility.hpp>
#define SRS_HTTP_RESPONSE_OK SRS_XSTR(ERROR_SUCCESS)
...
...
@@ -325,6 +326,55 @@ int SrsHttpHooks::on_hls(string url, SrsRequest* req, string file, int sn, doubl
return
ret
;
}
int
SrsHttpHooks
::
on_hls_notify
(
std
::
string
url
,
SrsRequest
*
req
,
std
::
string
ts_url
)
{
int
ret
=
ERROR_SUCCESS
;
int
client_id
=
_srs_context
->
get_id
();
std
::
string
cwd
=
_srs_config
->
cwd
();
if
(
srs_string_starts_with
(
ts_url
,
"http://"
)
||
srs_string_starts_with
(
ts_url
,
"https://"
))
{
url
=
ts_url
;
}
url
=
srs_string_replace
(
url
,
"[app]"
,
req
->
app
);
url
=
srs_string_replace
(
url
,
"[stream]"
,
req
->
stream
);
url
=
srs_string_replace
(
url
,
"[ts_url]"
,
ts_url
);
SrsHttpUri
uri
;
if
((
ret
=
uri
.
initialize
(
url
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"http: post failed. url=%s, ret=%d"
,
url
.
c_str
(),
ret
);
return
ret
;
}
SrsHttpClient
http
;
if
((
ret
=
http
.
initialize
(
uri
.
get_host
(),
uri
.
get_port
()))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
SrsHttpMessage
*
msg
=
NULL
;
if
((
ret
=
http
.
get
(
uri
.
get_path
(),
""
,
&
msg
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
SrsAutoFree
(
SrsHttpMessage
,
msg
);
ISrsHttpResponseReader
*
br
=
msg
->
body_reader
();
while
(
!
br
->
eof
())
{
std
::
string
data
;
if
((
ret
=
br
->
read
(
data
))
!=
ERROR_SUCCESS
)
{
break
;
}
}
srs_trace
(
"http hook on_hls_notify success. client_id=%d, url=%s, code=%d, ret=%d"
,
client_id
,
url
.
c_str
(),
msg
->
status_code
(),
ret
);
// ignore any error for on_hls_notify.
ret
=
ERROR_SUCCESS
;
return
ret
;
}
int
SrsHttpHooks
::
do_post
(
std
::
string
url
,
std
::
string
req
,
int
&
code
,
string
&
res
)
{
int
ret
=
ERROR_SUCCESS
;
...
...
trunk/src/app/srs_app_http_hooks.hpp
查看文件 @
e3c6e52
...
...
@@ -105,6 +105,13 @@ public:
* @param duration the segment duration in seconds.
*/
static
int
on_hls
(
std
::
string
url
,
SrsRequest
*
req
,
std
::
string
file
,
int
sn
,
double
duration
);
/**
* when hls reap segment, callback.
* @param url the api server url, to process the event.
* ignore if empty.
* @param ts_url the ts uri, used to replace the variable [ts_url] in url.
*/
static
int
on_hls_notify
(
std
::
string
url
,
SrsRequest
*
req
,
std
::
string
ts_url
);
private
:
static
int
do_post
(
std
::
string
url
,
std
::
string
req
,
int
&
code
,
std
::
string
&
res
);
};
...
...
请
注册
或
登录
后发表评论