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
2014-04-23 17:53:14 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
e271cb607f1ef9e5abf50e38c9538f5a332f7297
e271cb60
1 parent
0c0010d5
refine plan, add stream start time for atc
隐藏空白字符变更
内嵌
并排对比
正在显示
5 个修改的文件
包含
101 行增加
和
72 行删除
trunk/research/api-server/server.py
trunk/src/app/srs_app_dvr.cpp
trunk/src/app/srs_app_dvr.hpp
trunk/src/app/srs_app_http_hooks.cpp
trunk/src/app/srs_app_http_hooks.hpp
trunk/research/api-server/server.py
查看文件 @
e271cb6
...
...
@@ -325,6 +325,56 @@ class RESTSessions(object):
# TODO: process the on_stop event
return
code
# the rest dvrs, when dvr got keyframe, call this api.
class
RESTDvrs
(
object
):
exposed
=
True
def
__init__
(
self
):
pass
# the dvrs POST api specified in following.
#
# when dvr got an keyframe, call the hook,
# the request in the POST data string is a object encode by json:
# {
# "action": "on_dvr_keyframe",
# "vhost": "video.test.com", "app": "live",
# "stream": "livestream"
# }
#
# if valid, the hook must return HTTP code 200(Stauts OK) and response
# an int value specifies the error code(0 corresponding to success):
# 0
def
POST
(
self
):
enable_crossdomain
()
req
=
cherrypy
.
request
.
body
.
read
()
trace
(
"post to sessions, req=
%
s"
%
(
req
))
try
:
json_req
=
json
.
loads
(
req
)
except
Exception
,
ex
:
code
=
Error
.
system_parse_json
trace
(
"parse the request to json failed, req=
%
s, ex=
%
s, code=
%
s"
%
(
req
,
ex
,
code
))
return
str
(
code
)
action
=
json_req
[
"action"
]
if
action
==
"on_dvr_keyframe"
:
code
=
self
.
__on_dvr_keyframe
(
json_req
)
else
:
code
=
Errors
.
request_invalid_action
trace
(
"invalid request action:
%
s, code=
%
s"
%
(
json_req
[
"action"
],
code
))
return
str
(
code
)
def
__on_dvr_keyframe
(
self
,
req
):
code
=
Error
.
success
trace
(
"srs
%
s: vhost=
%
s, app=
%
s, stream=
%
s"
%
(
req
[
"action"
],
req
[
"vhost"
],
req
[
"app"
],
req
[
"stream"
]
))
# TODO: process the on_dvr_keyframe event
return
code
global_arm_server_id
=
os
.
getpid
();
class
ArmServer
:
...
...
@@ -930,6 +980,7 @@ class V1(object):
self
.
clients
=
RESTClients
()
self
.
streams
=
RESTStreams
()
self
.
sessions
=
RESTSessions
()
self
.
dvrs
=
RESTDvrs
()
self
.
chats
=
RESTChats
()
self
.
servers
=
RESTServers
()
self
.
nodes
=
RESTNodes
()
...
...
trunk/src/app/srs_app_dvr.cpp
查看文件 @
e271cb6
...
...
@@ -303,10 +303,12 @@ SrsFlvSegment::SrsFlvSegment()
segment_has_keyframe
=
false
;
duration
=
0
;
starttime
=
-
1
;
stream_starttime
=
0
;
}
void
SrsFlvSegment
::
reset
()
{
segment_has_keyframe
=
false
;
duration
=
0
;
starttime
=
-
1
;
}
...
...
@@ -319,7 +321,7 @@ SrsDvrPlan::SrsDvrPlan()
dvr_enabled
=
false
;
fs
=
new
SrsFileStream
();
enc
=
new
SrsFlvEncoder
();
segment
=
NULL
;
segment
=
new
SrsFlvSegment
()
;
}
SrsDvrPlan
::~
SrsDvrPlan
()
...
...
@@ -362,6 +364,22 @@ int SrsDvrPlan::on_publish()
// always update time cache.
srs_update_system_time_ms
();
// when republish, stream starting.
segment
->
stream_starttime
=
srs_get_system_time_ms
();
if
((
ret
=
open_new_segment
())
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
int
SrsDvrPlan
::
open_new_segment
()
{
int
ret
=
ERROR_SUCCESS
;
SrsRequest
*
req
=
_req
;
// new flv file
std
::
stringstream
path
;
...
...
@@ -468,8 +486,7 @@ int SrsDvrPlan::flv_open(string stream, string path)
{
int
ret
=
ERROR_SUCCESS
;
srs_freep
(
segment
);
segment
=
new
SrsFlvSegment
();
segment
->
reset
();
std
::
string
tmp_file
=
path
+
".tmp"
;
if
((
ret
=
fs
->
open
(
tmp_file
))
!=
ERROR_SUCCESS
)
{
...
...
@@ -548,7 +565,7 @@ int SrsDvrPlan::on_dvr_keyframe()
for
(
int
i
=
0
;
i
<
(
int
)
on_dvr_keyframe
->
args
.
size
();
i
++
)
{
std
::
string
url
=
on_dvr_keyframe
->
args
.
at
(
i
);
SrsHttpHooks
::
on_dvr_keyframe
(
url
,
_req
);
SrsHttpHooks
::
on_dvr_keyframe
(
url
,
_req
,
segment
);
}
#endif
...
...
@@ -620,6 +637,9 @@ int SrsDvrSegmentPlan::on_publish()
int
ret
=
ERROR_SUCCESS
;
// if already opened, continue to dvr.
// the segment plan maybe keep running longer than the encoder.
// for example, segment running, encoder restart,
// the segment plan will just continue going and donot open new segment.
if
(
fs
->
is_open
())
{
dvr_enabled
=
true
;
return
ret
;
...
...
@@ -648,15 +668,14 @@ int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
srs_assert
(
segment
);
// reap if exceed duration.
if
(
segment
->
duration
>
0
&&
segment_duration
>
0
&&
segment
->
duration
>
segment_duration
)
{
segment
->
reset
();
if
(
segment_duration
>
0
&&
segment
->
duration
>
segment_duration
)
{
if
((
ret
=
flv_close
())
!=
ERROR_SUCCESS
)
{
segment
->
reset
();
return
ret
;
}
on_unpublish
();
if
((
ret
=
o
n_publish
())
!=
ERROR_SUCCESS
)
{
if
((
ret
=
o
pen_new_segment
())
!=
ERROR_SUCCESS
)
{
return
ret
;
}
}
...
...
trunk/src/app/srs_app_dvr.hpp
查看文件 @
e271cb6
...
...
@@ -121,11 +121,15 @@ public:
* whether current segment has keyframe.
*/
bool
segment_has_keyframe
;
/**
* current segment duration and starttime.
*/
/**
* current segment duration and starttime.
*/
int64_t
duration
;
int64_t
starttime
;
/**
* stream start time, to generate atc pts.
*/
int64_t
stream_starttime
;
public
:
SrsFlvSegment
();
virtual
void
reset
();
...
...
@@ -137,6 +141,7 @@ public:
* 1. filename: the filename for record file.
* 2. reap flv: when to reap the flv and start new piece.
*/
// TODO: FIXME: the plan is too fat, refine me.
class
SrsDvrPlan
{
protected
:
...
...
@@ -165,12 +170,13 @@ public:
protected
:
virtual
int
flv_open
(
std
::
string
stream
,
std
::
string
path
);
virtual
int
flv_close
();
virtual
int
open_new_segment
();
virtual
int
update_duration
(
SrsSharedPtrMessage
*
msg
);
private
:
/**
* when srs reap the flv(close the segment),
* if has keyframe, notice the api.
*/
/**
* when srs reap the flv(close the segment),
* if has keyframe, notice the api.
*/
virtual
int
on_dvr_keyframe
();
public
:
static
SrsDvrPlan
*
create_plan
(
std
::
string
vhost
);
...
...
trunk/src/app/srs_app_http_hooks.cpp
查看文件 @
e271cb6
...
...
@@ -36,6 +36,7 @@ using namespace std;
#include <srs_app_socket.hpp>
#include <srs_app_http.hpp>
#include <srs_app_json.hpp>
#include <srs_app_dvr.hpp>
#define SRS_HTTP_RESPONSE_OK "0"
...
...
@@ -194,14 +195,6 @@ int SrsHttpHooks::on_connect(string url, int client_id, string ip, SrsRequest* r
return
ret
;
}
/**
{
"action": "on_connect",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"pageUrl": "http://www.test.com/live.html"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_connect"
)
<<
JFIELD_CONT
...
...
@@ -247,14 +240,6 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re
return
;
}
/**
{
"action": "on_close",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_close"
)
<<
JFIELD_CONT
...
...
@@ -300,14 +285,6 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r
return
ret
;
}
/**
{
"action": "on_publish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_publish"
)
<<
JFIELD_CONT
...
...
@@ -354,14 +331,6 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest
return
;
}
/**
{
"action": "on_unpublish",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_unpublish"
)
<<
JFIELD_CONT
...
...
@@ -408,14 +377,6 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req)
return
ret
;
}
/**
{
"action": "on_play",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_play"
)
<<
JFIELD_CONT
...
...
@@ -462,14 +423,6 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
return
;
}
/**
{
"action": "on_stop",
"client_id": 1985,
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_stop"
)
<<
JFIELD_CONT
...
...
@@ -505,10 +458,15 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
return
;
}
void
SrsHttpHooks
::
on_dvr_keyframe
(
string
url
,
SrsRequest
*
req
)
void
SrsHttpHooks
::
on_dvr_keyframe
(
string
url
,
SrsRequest
*
req
,
SrsFlvSegment
*
segment
)
{
int
ret
=
ERROR_SUCCESS
;
srs_trace
(
"flv segment %s, atc_start=%"
PRId64
", "
"has_key=%d, starttime=%"
PRId64
", duration=%d"
,
segment
->
current_flv_path
.
c_str
(),
segment
->
stream_starttime
,
segment
->
segment_has_keyframe
,
segment
->
starttime
,
(
int
)
segment
->
duration
);
SrsHttpUri
uri
;
if
((
ret
=
uri
.
initialize
(
url
))
!=
ERROR_SUCCESS
)
{
srs_warn
(
"http uri parse on_dvr_keyframe url failed, ignored. "
...
...
@@ -516,13 +474,6 @@ void SrsHttpHooks::on_dvr_keyframe(string url, SrsRequest* req)
return
;
}
/**
{
"action": "on_dvr_keyframe",
"vhost": "video.test.com", "app": "live",
"stream": "livestream"
}
*/
std
::
stringstream
ss
;
ss
<<
JOBJECT_START
<<
JFIELD_STR
(
"action"
,
"on_dvr_keyframe"
)
<<
JFIELD_CONT
...
...
trunk/src/app/srs_app_http_hooks.hpp
查看文件 @
e271cb6
...
...
@@ -37,6 +37,7 @@ class SrsHttpUri;
class
SrsSocket
;
class
SrsRequest
;
class
SrsHttpParser
;
class
SrsFlvSegment
;
#include <srs_app_st.hpp>
...
...
@@ -126,8 +127,9 @@ public:
* on_dvr_keyframe hook, when dvr get keyframe.
* @param url the api server url, to process the event.
* ignore if empty.
* @param segment the current flv segment.
*/
static
void
on_dvr_keyframe
(
std
::
string
url
,
SrsRequest
*
req
);
static
void
on_dvr_keyframe
(
std
::
string
url
,
SrsRequest
*
req
,
SrsFlvSegment
*
segment
);
};
#endif
...
...
请
注册
或
登录
后发表评论