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 16:06:49 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
73459547e1c8e9c1ad029d9b4fc834de21eaf1a0
73459547
1 parent
996d042a
support dvr. change to 0.9.69
显示空白字符变更
内嵌
并排对比
正在显示
13 个修改的文件
包含
600 行增加
和
21 行删除
trunk/conf/demo.conf
trunk/conf/full.conf
trunk/conf/ingest.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/app/srs_app_source.hpp
trunk/src/core/srs_core.hpp
trunk/src/kernel/srs_kernel_error.hpp
trunk/src/kernel/srs_kernel_stream.cpp
trunk/src/kernel/srs_kernel_stream.hpp
trunk/conf/demo.conf
查看文件 @
7345954
...
...
@@ -113,14 +113,14 @@ vhost demo.srs.com {
}
}
ingest
{
enable
on
;
enable
d
on
;
input
{
type
file
;
url
./
doc
/
source
.
200
kbps
.
768
x320
.
flv
;
}
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
{
enable
off
;
enable
d
off
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/
live
?
vhost
=[
vhost
]/
livestream
;
}
}
...
...
@@ -158,14 +158,14 @@ vhost players {
}
}
ingest
{
enable
on
;
enable
d
on
;
input
{
type
file
;
url
./
doc
/
source
.
200
kbps
.
768
x320
.
flv
;
}
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
{
enable
off
;
enable
d
off
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/
live
?
vhost
=[
vhost
]/
demo
;
}
}
...
...
trunk/conf/full.conf
查看文件 @
7345954
...
...
@@ -91,15 +91,39 @@ http_stream {
vhost
__
defaultVhost__
{
}
# vhost for dvr
vhost
dvr
.
srs
.
com
{
# dvr RTMP stream to file,
# when encoder(FMLE/ffmpeg/flash) start to publish,
# start the dvr and record RTMP to file(flv).
# stop record when encoder stop to publish.
dvr
{
# whether enabled dvr features
# default: off
enabled
on
;
# the dvr output path.
# the app dir is auto created under the dvr_path.
# for example, for rtmp stream:
# rtmp://127.0.0.1/live/livestream
# 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.
# in a word, the dvr_path is for vhost.
# default: ./objs/nginx/html
dvr_path
./
objs
/
nginx
/
html
;
}
}
# vhost for ingest
vhost
ingest
.
srs
.
com
{
# ingest file/stream/device then push to SRS over RTMP.
# the name/id used to identify the ingest, must be unique in global.
# ingest id is used in reload or http api management.
ingest
livestream
{
# whether enable ingest features
# whether enable
d
ingest features
# default: off
enable
on
;
enable
d
on
;
# input file/stream/device
# @remark only support one input.
input
{
...
...
@@ -121,7 +145,7 @@ vhost ingest.srs.com {
# @see enabled of transcode engine.
# if disabled or vcodec/acodec not specified, use copy.
# default: off.
enable
off
;
enable
d
off
;
# output stream. variables:
# [vhost] current vhost which start the ingest.
# [port] system RTMP stream port.
...
...
@@ -134,7 +158,7 @@ vhost ingest.srs.com {
vhost
http
.
srs
.
com
{
# http vhost specified config
http
{
# whether enable the http streaming service for vhost.
# whether enable
d
the http streaming service for vhost.
# default: off
enabled
on
;
# the virtual directory root for this vhost to mount at
...
...
@@ -743,7 +767,7 @@ vhost with-hls.srs.com {
# /hls/live/livestream-1.ts the HLS media/ts file.
# in a word, the hls_path is for vhost.
# default: ./objs/nginx/html
hls_path
/
data
/
nginx
/
html
;
hls_path
./
objs
/
nginx
/
html
;
# the hls fragment in seconds, the duration of a piece of ts.
# default: 10
hls_fragment
10
;
...
...
@@ -766,7 +790,7 @@ vhost no-hls.srs.com {
vhost
min
.
delay
.
com
{
# whether cache the last gop.
# if on, cache the last gop and dispatch to client,
# to enable fast startup for client, client play immediately.
# to enable
d
fast startup for client, client play immediately.
# if off, send the latest media data to client,
# client need to wait for the next Iframe to decode and show the video.
# set to off if requires min delay;
...
...
trunk/conf/ingest.conf
查看文件 @
7345954
...
...
@@ -5,14 +5,14 @@
listen
1935
;
vhost
__
defaultVhost__
{
ingest
livestream
{
enable
on
;
enable
d
on
;
input
{
type
file
;
url
./
doc
/
source
.
200
kbps
.
768
x320
.
flv
;
}
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
{
enable
off
;
enable
d
off
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/
live
?
vhost
=[
vhost
]/
livestream
;
}
}
...
...
trunk/src/app/srs_app_config.cpp
查看文件 @
7345954
...
...
@@ -2109,7 +2109,7 @@ SrsConfDirective* SrsConfig::get_ingest_by_id(std::string vhost, std::string ing
bool
SrsConfig
::
get_ingest_enabled
(
SrsConfDirective
*
ingest
)
{
SrsConfDirective
*
conf
=
ingest
->
get
(
"enable"
);
SrsConfDirective
*
conf
=
ingest
->
get
(
"enable
d
"
);
if
(
!
conf
||
conf
->
arg0
()
!=
"on"
)
{
return
false
;
...
...
@@ -2294,6 +2294,55 @@ double SrsConfig::get_hls_window(string vhost)
return
::
atof
(
conf
->
arg0
().
c_str
());
}
SrsConfDirective
*
SrsConfig
::
get_dvr
(
string
vhost
)
{
SrsConfDirective
*
conf
=
get_vhost
(
vhost
);
if
(
!
conf
)
{
return
NULL
;
}
return
conf
->
get
(
"dvr"
);
}
bool
SrsConfig
::
get_dvr_enabled
(
string
vhost
)
{
SrsConfDirective
*
dvr
=
get_dvr
(
vhost
);
if
(
!
dvr
)
{
return
false
;
}
SrsConfDirective
*
conf
=
dvr
->
get
(
"enabled"
);
if
(
!
conf
)
{
return
false
;
}
if
(
conf
->
arg0
()
==
"on"
)
{
return
true
;
}
return
false
;
}
string
SrsConfig
::
get_dvr_path
(
string
vhost
)
{
SrsConfDirective
*
dvr
=
get_dvr
(
vhost
);
if
(
!
dvr
)
{
return
SRS_CONF_DEFAULT_DVR_PATH
;
}
SrsConfDirective
*
conf
=
dvr
->
get
(
"dvr_path"
);
if
(
!
conf
)
{
return
SRS_CONF_DEFAULT_DVR_PATH
;
}
return
conf
->
arg0
();
}
SrsConfDirective
*
SrsConfig
::
get_http_api
()
{
return
root
->
get
(
"http_api"
);
...
...
trunk/src/app/srs_app_config.hpp
查看文件 @
7345954
...
...
@@ -44,6 +44,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
#define SRS_CONF_DEFAULT_HLS_WINDOW 60
#define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html"
// in ms, for HLS aac sync time.
#define SRS_CONF_DEFAULT_AAC_SYNC 100
// in ms, for HLS aac flush the audio
...
...
@@ -222,6 +223,12 @@ public:
virtual
std
::
string
get_hls_path
(
std
::
string
vhost
);
virtual
double
get_hls_fragment
(
std
::
string
vhost
);
virtual
double
get_hls_window
(
std
::
string
vhost
);
// dvr section
private:
virtual
SrsConfDirective
*
get_dvr
(
std
::
string
vhost
);
public
:
virtual
bool
get_dvr_enabled
(
std
::
string
vhost
);
virtual
std
::
string
get_dvr_path
(
std
::
string
vhost
);
// http api section
private:
virtual
SrsConfDirective
*
get_http_api
();
...
...
trunk/src/app/srs_app_dvr.cpp
查看文件 @
7345954
...
...
@@ -25,45 +25,413 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_AUTO_DVR
#include <fcntl.h>
using
namespace
std
;
#include <srs_app_config.hpp>
#include <srs_kernel_error.hpp>
#include <srs_protocol_rtmp.hpp>
#include <srs_protocol_rtmp_stack.hpp>
#include <srs_app_source.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_stream.hpp>
SrsFileStream
::
SrsFileStream
()
{
fd
=
-
1
;
}
SrsFileStream
::~
SrsFileStream
()
{
close
();
}
int
SrsFileStream
::
open
(
string
file
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
fd
>
0
)
{
ret
=
ERROR_SYSTEM_FILE_ALREADY_OPENED
;
srs_error
(
"file %s already opened. ret=%d"
,
_file
.
c_str
(),
ret
);
return
ret
;
}
int
flags
=
O_CREAT
|
O_WRONLY
|
O_TRUNC
;
mode_t
mode
=
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
;
if
((
fd
=
::
open
(
file
.
c_str
(),
flags
,
mode
))
<
0
)
{
ret
=
ERROR_SYSTEM_FILE_OPENE
;
srs_error
(
"open file %s failed. ret=%d"
,
file
.
c_str
(),
ret
);
return
ret
;
}
_file
=
file
;
return
ret
;
}
int
SrsFileStream
::
close
()
{
int
ret
=
ERROR_SUCCESS
;
if
(
fd
<
0
)
{
return
ret
;
}
if
(
::
close
(
fd
)
<
0
)
{
ret
=
ERROR_SYSTEM_FILE_CLOSE
;
srs_error
(
"close file %s failed. ret=%d"
,
_file
.
c_str
(),
ret
);
return
ret
;
}
fd
=
-
1
;
return
ret
;
}
int
SrsFileStream
::
read
(
void
*
buf
,
size_t
count
,
ssize_t
*
pnread
)
{
int
ret
=
ERROR_SUCCESS
;
ssize_t
nread
;
if
((
nread
=
::
read
(
fd
,
buf
,
count
))
<
0
)
{
ret
=
ERROR_SYSTEM_FILE_READ
;
srs_error
(
"read from file %s failed. ret=%d"
,
_file
.
c_str
(),
ret
);
return
ret
;
}
if
(
nread
==
0
)
{
ret
=
ERROR_SYSTEM_FILE_EOF
;
return
ret
;
}
if
(
pnread
!=
NULL
)
{
*
pnread
=
nread
;
}
return
ret
;
}
int
SrsFileStream
::
write
(
void
*
buf
,
size_t
count
,
ssize_t
*
pnwrite
)
{
int
ret
=
ERROR_SUCCESS
;
ssize_t
nwrite
;
if
((
nwrite
=
::
write
(
fd
,
buf
,
count
))
<
0
)
{
ret
=
ERROR_SYSTEM_FILE_WRITE
;
srs_error
(
"write to file %s failed. ret=%d"
,
_file
.
c_str
(),
ret
);
return
ret
;
}
if
(
pnwrite
!=
NULL
)
{
*
pnwrite
=
nwrite
;
}
return
ret
;
}
int64_t
SrsFileStream
::
size
()
{
::
lseek
(
fd
,
0
,
SEEK_SET
);
return
::
lseek
(
fd
,
0
,
SEEK_END
);
}
off_t
SrsFileStream
::
lseek
(
off_t
offset
)
{
return
::
lseek
(
fd
,
offset
,
SEEK_SET
);
}
SrsFlvEncoder
::
SrsFlvEncoder
()
{
_fs
=
NULL
;
has_audio
=
false
;
has_video
=
false
;
tag_stream
=
new
SrsStream
();
}
SrsFlvEncoder
::~
SrsFlvEncoder
()
{
srs_freep
(
tag_stream
);
}
int
SrsFlvEncoder
::
initialize
(
SrsFileStream
*
fs
)
{
int
ret
=
ERROR_SUCCESS
;
_fs
=
fs
;
has_audio
=
true
;
has_video
=
true
;
return
ret
;
}
int
SrsFlvEncoder
::
write_header
()
{
int
ret
=
ERROR_SUCCESS
;
// seek to header.
_fs
->
lseek
(
0
);
static
char
flv_header
[]
=
{
'F'
,
'L'
,
'V'
,
// Signatures "FLV"
(
char
)
0x01
,
// File version (for example, 0x01 for FLV version 1)
(
char
)
0x00
,
// 4, audio; 1, video; 5 audio+video.
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x09
,
// DataOffset UI32 The length of this header in bytes
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
// PreviousTagSize0 UI32 Always 0
};
// generate audio/video flag.
const
static
int
av_index
=
4
;
flv_header
[
av_index
]
=
0x00
;
if
(
has_audio
)
{
flv_header
[
av_index
]
+=
4
;
}
if
(
has_video
)
{
flv_header
[
av_index
]
+=
1
;
}
// write data.
if
((
ret
=
_fs
->
write
(
flv_header
,
sizeof
(
flv_header
),
NULL
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv header failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
int
SrsFlvEncoder
::
write_metadata
(
char
*
data
,
int
size
)
{
int
ret
=
ERROR_SUCCESS
;
static
char
tag_header
[]
=
{
(
char
)
18
,
// TagType UB [5], 18 = script data
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// DataSize UI24 Length of the message.
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(
char
)
0x00
,
// TimestampExtended UI8
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// StreamID UI24 Always 0.
};
// write data size.
if
((
ret
=
tag_stream
->
initialize
(
tag_header
+
1
,
3
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
tag_stream
->
write_3bytes
(
size
);
if
((
ret
=
write_tag
(
tag_header
,
sizeof
(
tag_header
),
data
,
size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv data tag failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
int
SrsFlvEncoder
::
write_audio
(
int32_t
timestamp
,
char
*
data
,
int
size
)
{
int
ret
=
ERROR_SUCCESS
;
has_audio
=
true
;
static
char
tag_header
[]
=
{
(
char
)
8
,
// TagType UB [5], 8 = audio
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// DataSize UI24 Length of the message.
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(
char
)
0x00
,
// TimestampExtended UI8
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// StreamID UI24 Always 0.
};
// write data size.
if
((
ret
=
tag_stream
->
initialize
(
tag_header
+
1
,
7
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
tag_stream
->
write_3bytes
(
size
);
tag_stream
->
write_3bytes
(
timestamp
);
// default to little-endian
tag_stream
->
write_1bytes
((
timestamp
>>
24
)
&
0xFF
);
if
((
ret
=
write_tag
(
tag_header
,
sizeof
(
tag_header
),
data
,
size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv audio tag failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
int
SrsFlvEncoder
::
write_video
(
int32_t
timestamp
,
char
*
data
,
int
size
)
{
int
ret
=
ERROR_SUCCESS
;
has_video
=
true
;
static
char
tag_header
[]
=
{
(
char
)
9
,
// TagType UB [5], 9 = video
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// DataSize UI24 Length of the message.
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(
char
)
0x00
,
// TimestampExtended UI8
(
char
)
0x00
,
(
char
)
0x00
,
(
char
)
0x00
,
// StreamID UI24 Always 0.
};
// write data size.
if
((
ret
=
tag_stream
->
initialize
(
tag_header
+
1
,
7
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
tag_stream
->
write_3bytes
(
size
);
tag_stream
->
write_3bytes
(
timestamp
);
// default to little-endian
tag_stream
->
write_1bytes
((
timestamp
>>
24
)
&
0xFF
);
if
((
ret
=
write_tag
(
tag_header
,
sizeof
(
tag_header
),
data
,
size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv video tag failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
int
SrsFlvEncoder
::
write_tag
(
char
*
header
,
int
header_size
,
char
*
data
,
int
size
)
{
int
ret
=
ERROR_SUCCESS
;
// write tag header.
if
((
ret
=
_fs
->
write
(
header
,
header_size
,
NULL
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv tag header failed. ret=%d"
,
ret
);
return
ret
;
}
// write tag data.
if
((
ret
=
_fs
->
write
(
data
,
size
,
NULL
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv tag failed. ret=%d"
,
ret
);
return
ret
;
}
// PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.
static
char
pre_size
[
4
];
if
((
ret
=
tag_stream
->
initialize
(
pre_size
,
4
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
tag_stream
->
write_4bytes
(
size
+
header_size
);
if
((
ret
=
_fs
->
write
(
pre_size
,
sizeof
(
pre_size
),
NULL
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv previous tag size failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
SrsDvr
::
SrsDvr
(
SrsSource
*
source
)
{
_source
=
source
;
dvr_enabled
=
false
;
fs
=
new
SrsFileStream
();
enc
=
new
SrsFlvEncoder
();
}
SrsDvr
::~
SrsDvr
()
{
srs_freep
(
fs
);
srs_freep
(
enc
);
}
int
SrsDvr
::
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
::
string
path
=
_srs_config
->
get_dvr_path
(
req
->
vhost
);
path
+=
"/"
;
path
+=
req
->
app
;
path
+=
"/"
;
path
+=
req
->
stream
;
path
+=
".flv"
;
if
((
ret
=
fs
->
open
(
path
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"open file stream for file %s failed. ret=%d"
,
path
.
c_str
(),
ret
);
return
ret
;
}
if
((
ret
=
enc
->
initialize
(
fs
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"initialize enc by fs for file %s failed. ret=%d"
,
path
.
c_str
(),
ret
);
return
ret
;
}
if
((
ret
=
enc
->
write_header
())
!=
ERROR_SUCCESS
)
{
srs_error
(
"write flv header for file %s failed. ret=%d"
,
path
.
c_str
(),
ret
);
return
ret
;
}
if
((
ret
=
_source
->
on_dvr_start
())
!=
ERROR_SUCCESS
)
{
return
ret
;
}
srs_trace
(
"dvr stream %s to file %s"
,
req
->
get_stream_url
().
c_str
(),
path
.
c_str
());
dvr_enabled
=
true
;
return
ret
;
}
void
SrsDvr
::
on_unpublish
()
{
// support multiple publish.
if
(
!
dvr_enabled
)
{
return
;
}
// ignore error.
fs
->
close
();
dvr_enabled
=
false
;
}
int
SrsDvr
::
on_meta_data
(
Srs
Amf0Objec
t
*
metadata
)
int
SrsDvr
::
on_meta_data
(
Srs
OnMetaDataPacke
t
*
metadata
)
{
int
ret
=
ERROR_SUCCESS
;
int
size
=
0
;
char
*
payload
=
NULL
;
if
((
ret
=
metadata
->
encode
(
size
,
payload
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
SrsAutoFree
(
char
,
payload
,
true
);
if
((
ret
=
enc
->
write_metadata
(
payload
,
size
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
int
SrsDvr
::
on_audio
(
SrsSharedPtrMessage
*
audio
)
{
int
ret
=
ERROR_SUCCESS
;
srs_freep
(
audio
);
int32_t
timestamp
=
audio
->
header
.
timestamp
;
char
*
payload
=
(
char
*
)
audio
->
payload
;
int
size
=
(
int
)
audio
->
size
;
if
((
ret
=
enc
->
write_audio
(
timestamp
,
payload
,
size
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
int
SrsDvr
::
on_video
(
SrsSharedPtrMessage
*
video
)
{
int
ret
=
ERROR_SUCCESS
;
srs_freep
(
video
);
int32_t
timestamp
=
video
->
header
.
timestamp
;
char
*
payload
=
(
char
*
)
video
->
payload
;
int
size
=
(
int
)
video
->
size
;
if
((
ret
=
enc
->
write_video
(
timestamp
,
payload
,
size
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
return
ret
;
}
...
...
trunk/src/app/srs_app_dvr.hpp
查看文件 @
7345954
...
...
@@ -33,14 +33,77 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class
SrsSource
;
class
SrsRequest
;
class
SrsAmf0Object
;
class
SrsStream
;
class
SrsOnMetaDataPacket
;
class
SrsSharedPtrMessage
;
/**
* file stream to read/write file.
*/
class
SrsFileStream
{
private
:
std
::
string
_file
;
int
fd
;
public
:
SrsFileStream
();
virtual
~
SrsFileStream
();
public
:
virtual
int
open
(
std
::
string
file
);
virtual
int
close
();
public
:
/**
* @param pnread, return the read size. NULL to ignore.
*/
virtual
int
read
(
void
*
buf
,
size_t
count
,
ssize_t
*
pnread
);
/**
* @param pnwrite, return the write size. NULL to ignore.
*/
virtual
int
write
(
void
*
buf
,
size_t
count
,
ssize_t
*
pnwrite
);
public
:
/**
* get size of file.
*/
virtual
int64_t
size
();
/**
* wrapper for system lseek where whence always use SEEK_SET
*/
virtual
off_t
lseek
(
off_t
offset
);
};
/**
* encode data to flv file.
*/
class
SrsFlvEncoder
{
private
:
SrsFileStream
*
_fs
;
private
:
bool
has_audio
;
bool
has_video
;
SrsStream
*
tag_stream
;
public
:
SrsFlvEncoder
();
virtual
~
SrsFlvEncoder
();
public
:
virtual
int
initialize
(
SrsFileStream
*
fs
);
public
:
/**
* write flv header.
* user can invoke this method multiple times,
* for example, when get audio/video sequence header.
*
* write following:
* 1. E.2 The FLV header
* 2. PreviousTagSize0 UI32 Always 0
* that is, 9+4=13bytes.
*/
virtual
int
write_header
();
virtual
int
write_metadata
(
char
*
data
,
int
size
);
virtual
int
write_audio
(
int32_t
timestamp
,
char
*
data
,
int
size
);
virtual
int
write_video
(
int32_t
timestamp
,
char
*
data
,
int
size
);
private
:
virtual
int
write_tag
(
char
*
header
,
int
header_size
,
char
*
data
,
int
size
);
};
/**
...
...
@@ -51,6 +114,10 @@ class SrsDvr
{
private
:
SrsSource
*
_source
;
private
:
bool
dvr_enabled
;
SrsFileStream
*
fs
;
SrsFlvEncoder
*
enc
;
public
:
SrsDvr
(
SrsSource
*
source
);
virtual
~
SrsDvr
();
...
...
@@ -68,7 +135,7 @@ public:
/**
* get some information from metadata, it's optinal.
*/
virtual
int
on_meta_data
(
Srs
Amf0Objec
t
*
metadata
);
virtual
int
on_meta_data
(
Srs
OnMetaDataPacke
t
*
metadata
);
/**
* mux the audio packets to dvr.
*/
...
...
trunk/src/app/srs_app_source.cpp
查看文件 @
7345954
...
...
@@ -37,6 +37,7 @@ using namespace std;
#include <srs_app_encoder.hpp>
#include <srs_protocol_rtmp.hpp>
#include <srs_app_dvr.hpp>
#include <srs_kernel_stream.hpp>
#define CONST_MAX_JITTER_MS 500
#define DEFAULT_FRAME_TIME_MS 40
...
...
@@ -651,7 +652,6 @@ int SrsSource::on_hls_start()
int
ret
=
ERROR_SUCCESS
;
#ifdef SRS_AUTO_HLS
// feed the hls the metadata/sequence header,
// when reload to start hls, hls will never get the sequence header in stream,
// use the SrsSource.on_hls_start to push the sequence header to HLS.
...
...
@@ -664,7 +664,49 @@ int SrsSource::on_hls_start()
srs_error
(
"hls process audio sequence header message failed. ret=%d"
,
ret
);
return
ret
;
}
#endif
return
ret
;
}
int
SrsSource
::
on_dvr_start
()
{
int
ret
=
ERROR_SUCCESS
;
#ifdef SRS_AUTO_DVR
// feed the dvr the metadata/sequence header,
// when reload to start dvr, dvr will never get the sequence header in stream,
// use the SrsSource.on_dvr_start to push the sequence header to DVR.
if
(
cache_metadata
)
{
char
*
payload
=
(
char
*
)
cache_metadata
->
payload
;
int
size
=
(
int
)
cache_metadata
->
size
;
SrsStream
stream
;
if
((
ret
=
stream
.
initialize
(
payload
,
size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr decode metadata stream failed. ret=%d"
,
ret
);
return
ret
;
}
SrsOnMetaDataPacket
pkt
;
if
((
ret
=
pkt
.
decode
(
&
stream
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr decode metadata packet failed."
);
return
ret
;
}
if
((
ret
=
dvr
->
on_meta_data
(
&
pkt
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr process onMetaData message failed. ret=%d"
,
ret
);
return
ret
;
}
}
if
(
cache_sh_video
&&
(
ret
=
dvr
->
on_video
(
cache_sh_video
->
copy
()))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr process video sequence header message failed. ret=%d"
,
ret
);
return
ret
;
}
if
(
cache_sh_audio
&&
(
ret
=
dvr
->
on_audio
(
cache_sh_audio
->
copy
()))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr process audio sequence header message failed. ret=%d"
,
ret
);
return
ret
;
}
#endif
return
ret
;
...
...
@@ -687,7 +729,7 @@ int SrsSource::on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata
#endif
#ifdef SRS_AUTO_DVR
if
(
metadata
&&
(
ret
=
dvr
->
on_meta_data
(
metadata
->
metadata
))
!=
ERROR_SUCCESS
)
{
if
(
metadata
&&
(
ret
=
dvr
->
on_meta_data
(
metadata
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"dvr process onMetaData message failed. ret=%d"
,
ret
);
return
ret
;
}
...
...
trunk/src/app/srs_app_source.hpp
查看文件 @
7345954
...
...
@@ -284,6 +284,8 @@ public:
virtual
int
on_forwarder_start
(
SrsForwarder
*
forwarder
);
// for the SrsHls to callback to request the sequence headers.
virtual
int
on_hls_start
();
// for the SrsDvr to callback to request the sequence headers.
virtual
int
on_dvr_start
();
public
:
virtual
bool
can_publish
();
virtual
int
on_meta_data
(
SrsCommonMessage
*
msg
,
SrsOnMetaDataPacket
*
metadata
);
...
...
trunk/src/core/srs_core.hpp
查看文件 @
7345954
...
...
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "6
8
"
#define VERSION_REVISION "6
9
"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
...
...
trunk/src/kernel/srs_kernel_error.hpp
查看文件 @
7345954
...
...
@@ -100,6 +100,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_SYSTEM_PID_WRITE_FILE 420
#define ERROR_SYSTEM_PID_GET_FILE_INFO 421
#define ERROR_SYSTEM_PID_SET_FILE_INFO 422
#define ERROR_SYSTEM_FILE_ALREADY_OPENED 423
#define ERROR_SYSTEM_FILE_OPENE 424
#define ERROR_SYSTEM_FILE_CLOSE 425
#define ERROR_SYSTEM_FILE_READ 426
#define ERROR_SYSTEM_FILE_WRITE 427
#define ERROR_SYSTEM_FILE_EOF 428
// see librtmp.
// failed when open ssl create the dh
...
...
trunk/src/kernel/srs_kernel_stream.cpp
查看文件 @
7345954
...
...
@@ -199,6 +199,16 @@ void SrsStream::write_4bytes(int32_t value)
*
p
++
=
pp
[
0
];
}
void
SrsStream
::
write_3bytes
(
int32_t
value
)
{
srs_assert
(
require
(
3
));
pp
=
(
char
*
)
&
value
;
*
p
++
=
pp
[
2
];
*
p
++
=
pp
[
1
];
*
p
++
=
pp
[
0
];
}
void
SrsStream
::
write_8bytes
(
int64_t
value
)
{
srs_assert
(
require
(
8
));
...
...
trunk/src/kernel/srs_kernel_stream.hpp
查看文件 @
7345954
...
...
@@ -118,6 +118,10 @@ public:
*/
virtual
void
write_4bytes
(
int32_t
value
);
/**
* write 3bytes int to stream.
*/
virtual
void
write_3bytes
(
int32_t
value
);
/**
* write 8bytes int to stream.
*/
virtual
void
write_8bytes
(
int64_t
value
);
...
...
请
注册
或
登录
后发表评论