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-17 17:35:21 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
2d1c28cff9f9b89d47c2bf6d0c811b393e40fd5e
2d1c28cf
1 parent
6f19a831
update dvr, support segment plan
隐藏空白字符变更
内嵌
并排对比
正在显示
7 个修改的文件
包含
230 行增加
和
23 行删除
trunk/conf/full.conf
trunk/src/app/srs_app_config.cpp
trunk/src/app/srs_app_config.hpp
trunk/src/app/srs_app_dvr.cpp
trunk/src/app/srs_app_dvr.hpp
trunk/src/app/srs_app_source.cpp
trunk/src/kernel/srs_kernel_utility.cpp
trunk/conf/full.conf
查看文件 @
2d1c28c
...
...
@@ -108,10 +108,19 @@ vhost dvr.srs.com {
# http://127.0.0.1/live/livestream.m3u8
# where dvr_path is /dvr, srs will create the following files:
# /dvr/live the app dir for all streams.
# /dvr/live/livestream.flv the dvr flv file.
# /dvr/live/livestream.{time}.flv the dvr flv file.
# @remark, the time use system timestamp in ms, user can use http callback to rename it.
# in a word, the dvr_path is for vhost.
# default: ./objs/nginx/html
dvr_path
./
objs
/
nginx
/
html
;
# the dvr plan. canbe:
# session reap flv when session end(unpublish).
# segment reap flv when flv duration exceed the specified duration.
# default: session
dvr_plan
session
;
# the param for plan(segment), in seconds.
# default: 30
dvr_duration
30
;
}
}
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
2d1c28c
...
...
@@ -2354,6 +2354,40 @@ string SrsConfig::get_dvr_path(string vhost)
return
conf
->
arg0
();
}
string
SrsConfig
::
get_dvr_plan
(
string
vhost
)
{
SrsConfDirective
*
dvr
=
get_dvr
(
vhost
);
if
(
!
dvr
)
{
return
SRS_CONF_DEFAULT_DVR_PLAN
;
}
SrsConfDirective
*
conf
=
dvr
->
get
(
"dvr_plan"
);
if
(
!
conf
)
{
return
SRS_CONF_DEFAULT_DVR_PLAN
;
}
return
conf
->
arg0
();
}
int
SrsConfig
::
get_dvr_duration
(
string
vhost
)
{
SrsConfDirective
*
dvr
=
get_dvr
(
vhost
);
if
(
!
dvr
)
{
return
SRS_CONF_DEFAULT_DVR_DURATION
;
}
SrsConfDirective
*
conf
=
dvr
->
get
(
"dvr_duration"
);
if
(
!
conf
)
{
return
SRS_CONF_DEFAULT_DVR_DURATION
;
}
return
::
atoi
(
conf
->
arg0
().
c_str
());
}
SrsConfDirective
*
SrsConfig
::
get_http_api
()
{
return
root
->
get
(
"http_api"
);
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
2d1c28c
...
...
@@ -45,6 +45,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
#define SRS_CONF_DEFAULT_HLS_WINDOW 60
#define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html"
#define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session"
#define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment"
#define SRS_CONF_DEFAULT_DVR_PLAN SRS_CONF_DEFAULT_DVR_PLAN_SESSION
#define SRS_CONF_DEFAULT_DVR_DURATION 30
// in ms, for HLS aac sync time.
#define SRS_CONF_DEFAULT_AAC_SYNC 100
// in ms, for HLS aac flush the audio
...
...
@@ -229,6 +233,8 @@ private:
public
:
virtual
bool
get_dvr_enabled
(
std
::
string
vhost
);
virtual
std
::
string
get_dvr_path
(
std
::
string
vhost
);
virtual
std
::
string
get_dvr_plan
(
std
::
string
vhost
);
virtual
int
get_dvr_duration
(
std
::
string
vhost
);
// http api section
private:
virtual
SrsConfDirective
*
get_http_api
();
...
...
trunk/src/app/srs_app_dvr.cpp
查看文件 @
2d1c28c
...
...
@@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_AUTO_DVR
#include <fcntl.h>
#include <sstream>
using
namespace
std
;
#include <srs_app_config.hpp>
...
...
@@ -35,6 +36,7 @@ using namespace std;
#include <srs_app_source.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_stream.hpp>
#include <srs_kernel_utility.hpp>
SrsFileStream
::
SrsFileStream
()
{
...
...
@@ -302,7 +304,7 @@ SrsDvrPlan::~SrsDvrPlan()
srs_freep
(
enc
);
}
int
SrsDvrPlan
::
initialize
(
SrsSource
*
source
)
int
SrsDvrPlan
::
initialize
(
SrsSource
*
source
,
SrsRequest
*
/*req*/
)
{
int
ret
=
ERROR_SUCCESS
;
...
...
@@ -401,9 +403,16 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video)
return
ret
;
}
SrsDvrPlan
*
SrsDvrPlan
::
create_plan
()
SrsDvrPlan
*
SrsDvrPlan
::
create_plan
(
string
vhost
)
{
return
new
SrsDvrSessionPlan
();
std
::
string
plan
=
_srs_config
->
get_dvr_plan
(
vhost
);
if
(
plan
==
SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT
)
{
return
new
SrsDvrSegmentPlan
();
}
else
if
(
plan
==
SRS_CONF_DEFAULT_DVR_PLAN_SESSION
)
{
return
new
SrsDvrSessionPlan
();
}
else
{
return
new
SrsDvrSessionPlan
();
}
}
SrsDvrSessionPlan
::
SrsDvrSessionPlan
()
...
...
@@ -427,14 +436,13 @@ int SrsDvrSessionPlan::on_publish(SrsRequest* req)
return
ret
;
}
std
::
string
path
=
_srs_config
->
get_dvr_path
(
req
->
vhost
);
path
+=
"/"
;
path
+=
req
->
app
;
path
+=
"/"
;
path
+=
req
->
stream
;
path
+=
".flv"
;
std
::
stringstream
path
;
path
<<
_srs_config
->
get_dvr_path
(
req
->
vhost
)
<<
"/"
<<
req
->
app
<<
"/"
<<
req
->
stream
<<
"."
<<
srs_get_system_time_ms
()
<<
".flv"
;
if
((
ret
=
flv_open
(
req
->
get_stream_url
(),
path
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
flv_open
(
req
->
get_stream_url
(),
path
.
str
()
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
dvr_enabled
=
true
;
...
...
@@ -458,6 +466,132 @@ void SrsDvrSessionPlan::on_unpublish()
dvr_enabled
=
false
;
}
SrsDvrSegmentPlan
::
SrsDvrSegmentPlan
()
{
starttime
=
-
1
;
duration
=
0
;
segment_duration
=
-
1
;
}
SrsDvrSegmentPlan
::~
SrsDvrSegmentPlan
()
{
}
int
SrsDvrSegmentPlan
::
initialize
(
SrsSource
*
source
,
SrsRequest
*
req
)
{
int
ret
=
ERROR_SUCCESS
;
if
((
ret
=
SrsDvrPlan
::
initialize
(
source
,
req
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
segment_duration
=
_srs_config
->
get_dvr_duration
(
req
->
vhost
);
// to ms
segment_duration
*=
1000
;
return
ret
;
}
int
SrsDvrSegmentPlan
::
on_publish
(
SrsRequest
*
req
)
{
int
ret
=
ERROR_SUCCESS
;
// support multiple publish.
if
(
dvr_enabled
)
{
return
ret
;
}
if
(
!
_srs_config
->
get_dvr_enabled
(
req
->
vhost
))
{
return
ret
;
}
std
::
stringstream
path
;
path
<<
_srs_config
->
get_dvr_path
(
req
->
vhost
)
<<
"/"
<<
req
->
app
<<
"/"
<<
req
->
stream
<<
"."
<<
srs_get_system_time_ms
()
<<
".flv"
;
if
((
ret
=
flv_open
(
req
->
get_stream_url
(),
path
.
str
()))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
dvr_enabled
=
true
;
return
ret
;
}
void
SrsDvrSegmentPlan
::
on_unpublish
()
{
// support multiple publish.
if
(
!
dvr_enabled
)
{
return
;
}
// ignore error.
int
ret
=
flv_close
();
if
(
ret
!=
ERROR_SUCCESS
)
{
srs_warn
(
"ignore flv close error. ret=%d"
,
ret
);
}
dvr_enabled
=
false
;
}
int
SrsDvrSegmentPlan
::
on_audio
(
SrsSharedPtrMessage
*
audio
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
!
dvr_enabled
)
{
return
ret
;
}
if
((
ret
=
update_duration
(
audio
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
if
((
ret
=
SrsDvrPlan
::
on_audio
(
audio
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
int
SrsDvrSegmentPlan
::
on_video
(
SrsSharedPtrMessage
*
video
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
!
dvr_enabled
)
{
return
ret
;
}
if
((
ret
=
update_duration
(
video
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
if
((
ret
=
SrsDvrPlan
::
on_video
(
video
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
int
SrsDvrSegmentPlan
::
update_duration
(
SrsSharedPtrMessage
*
msg
)
{
int
ret
=
ERROR_SUCCESS
;
// foreach msg, collect the duration.
if
(
starttime
<
0
||
starttime
>
msg
->
header
.
timestamp
)
{
starttime
=
msg
->
header
.
timestamp
;
}
duration
+=
msg
->
header
.
timestamp
-
starttime
;
starttime
=
msg
->
header
.
timestamp
;
// reap if exceed duration.
if
(
duration
>
0
&&
segment_duration
>
0
&&
duration
>
segment_duration
)
{
on_unpublish
();
}
return
ret
;
}
SrsDvr
::
SrsDvr
(
SrsSource
*
source
)
{
_source
=
source
;
...
...
@@ -469,14 +603,14 @@ SrsDvr::~SrsDvr()
srs_freep
(
plan
);
}
int
SrsDvr
::
initialize
()
int
SrsDvr
::
initialize
(
SrsRequest
*
req
)
{
int
ret
=
ERROR_SUCCESS
;
srs_freep
(
plan
);
plan
=
SrsDvrPlan
::
create_plan
();
plan
=
SrsDvrPlan
::
create_plan
(
req
->
vhost
);
if
((
ret
=
plan
->
initialize
(
_source
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
plan
->
initialize
(
_source
,
req
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
...
...
trunk/src/app/srs_app_dvr.hpp
查看文件 @
2d1c28c
...
...
@@ -127,7 +127,7 @@ public:
SrsDvrPlan
();
virtual
~
SrsDvrPlan
();
public
:
virtual
int
initialize
(
SrsSource
*
source
);
virtual
int
initialize
(
SrsSource
*
source
,
SrsRequest
*
req
);
virtual
int
on_publish
(
SrsRequest
*
req
)
=
0
;
virtual
void
on_unpublish
()
=
0
;
virtual
int
on_meta_data
(
SrsOnMetaDataPacket
*
metadata
);
...
...
@@ -137,14 +137,11 @@ protected:
virtual
int
flv_open
(
std
::
string
stream
,
std
::
string
path
);
virtual
int
flv_close
();
public
:
static
SrsDvrPlan
*
create_plan
();
static
SrsDvrPlan
*
create_plan
(
std
::
string
vhost
);
};
/**
* default session plan:
* 1. start dvr when session start(publish).
* 2. stop dvr when session stop(unpublish).
* 3. always dvr to file: dvr_path/app/stream.flv
* session plan: reap flv when session complete(unpublish)
*/
class
SrsDvrSessionPlan
:
public
SrsDvrPlan
{
...
...
@@ -157,6 +154,29 @@ public:
};
/**
* segment plan: reap flv when duration exceed.
*/
class
SrsDvrSegmentPlan
:
public
SrsDvrPlan
{
private
:
int64_t
duration
;
int64_t
starttime
;
// in config, in ms
int
segment_duration
;
public
:
SrsDvrSegmentPlan
();
virtual
~
SrsDvrSegmentPlan
();
public
:
virtual
int
initialize
(
SrsSource
*
source
,
SrsRequest
*
req
);
virtual
int
on_publish
(
SrsRequest
*
req
);
virtual
void
on_unpublish
();
virtual
int
on_audio
(
SrsSharedPtrMessage
*
audio
);
virtual
int
on_video
(
SrsSharedPtrMessage
*
video
);
private
:
virtual
int
update_duration
(
SrsSharedPtrMessage
*
msg
);
};
/**
* dvr(digital video recorder) to record RTMP stream to flv file.
* TODO: FIXME: add utest for it.
*/
...
...
@@ -175,7 +195,7 @@ public:
* when system initialize(encoder publish at first time, or reload),
* initialize the dvr will reinitialize the plan, the whole dvr framework.
*/
virtual
int
initialize
();
virtual
int
initialize
(
SrsRequest
*
req
);
/**
* publish stream event,
* when encoder start to publish RTMP stream.
...
...
trunk/src/app/srs_app_source.cpp
查看文件 @
2d1c28c
...
...
@@ -507,7 +507,7 @@ int SrsSource::initialize()
int
ret
=
ERROR_SUCCESS
;
#ifdef SRS_AUTO_DVR
if
((
ret
=
dvr
->
initialize
())
!=
ERROR_SUCCESS
)
{
if
((
ret
=
dvr
->
initialize
(
req
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
#endif
...
...
@@ -641,7 +641,7 @@ int SrsSource::on_reload_vhost_dvr(string vhost)
dvr
->
on_unpublish
();
// reinitialize the dvr, update plan.
if
((
ret
=
dvr
->
initialize
())
!=
ERROR_SUCCESS
)
{
if
((
ret
=
dvr
->
initialize
(
req
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
...
...
trunk/src/kernel/srs_kernel_utility.cpp
查看文件 @
2d1c28c
...
...
@@ -31,6 +31,10 @@ static int64_t _srs_system_time_us_cache = 0;
int64_t
srs_get_system_time_ms
()
{
if
(
_srs_system_time_us_cache
<=
0
)
{
srs_update_system_time_ms
();
}
return
_srs_system_time_us_cache
/
1000
;
}
...
...
请
注册
或
登录
后发表评论