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
2013-12-01 10:54:41 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9a0d8855d852a108701cbeed552e81c846832b7c
9a0d8855
1 parent
f85b7096
support ffmpeg filter
隐藏空白字符变更
内嵌
并排对比
正在显示
8 个修改的文件
包含
281 行增加
和
86 行删除
README.md
trunk/auto/build_ffmpeg.sh
trunk/conf/srs.conf
trunk/doc/ffmpeg-logo.png
trunk/src/core/srs_core_config.cpp
trunk/src/core/srs_core_config.hpp
trunk/src/core/srs_core_encoder.cpp
trunk/src/core/srs_core_encoder.hpp
README.md
查看文件 @
9a0d885
...
...
@@ -69,15 +69,16 @@ Supported operating systems and hardware:
14.
support forward publish stream to build active-standby cluster.
<br/>
15.
support broadcast by forward the stream to other servers(origin/edge).
<br/>
16.
support live stream transcoding by ffmpeg.
<br/>
17.
[
plan
]
support full http callback api.
<br/>
18.
[
plan
]
support network based cli and json result.
<br/>
19.
[
plan
]
support bandwidth test api and flash client.
<br/>
20.
[
plan
]
support adobe flash refer/token/swf verification.
<br/>
21.
[
plan
]
support adobe amf3 codec.
<br/>
22.
[
plan
]
support dvr(record live to vod file)
<br/>
23.
[
plan
]
support FMS edge protocol
<br/>
24.
[
plan
]
support encryption: RTMPE/RTMPS, HLS DRM
<br/>
25.
[
plan
]
support RTMPT, http to tranverse firewalls
<br/>
17.
support live stream transcoding by ffmpeg.
<br/>
18.
support ffmpeg filters(logo/overlay/crop), x264 params.
<br/>
19.
[
plan
]
support network based cli and json result.
<br/>
20.
[
plan
]
support bandwidth test api and flash client.
<br/>
21.
[
plan
]
support adobe flash refer/token/swf verification.
<br/>
22.
[
plan
]
support adobe amf3 codec.
<br/>
23.
[
plan
]
support dvr(record live to vod file)
<br/>
24.
[
plan
]
support FMS edge protocol
<br/>
25.
[
plan
]
support encryption: RTMPE/RTMPS, HLS DRM
<br/>
26.
[
plan
]
support RTMPT, http to tranverse firewalls
<br/>
### Performance
1.
300 connections, 150Mbps, 500kbps, CPU 18.8%, 5956KB.
...
...
trunk/auto/build_ffmpeg.sh
查看文件 @
9a0d885
...
...
@@ -84,6 +84,7 @@ else
--extra-ldflags
=
'-L${ffmpeg_exported_release_dir}/lib -lm -ldl'
\
--disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc
\
--enable-postproc --enable-bzlib --enable-zlib --enable-parsers
\
--enable-libfreetype
\
--enable-libx264 --enable-libmp3lame --enable-libaacplus
\
--enable-pthreads --extra-libs
=
-lpthread --enable-encoders --enable-decoders --enable-avfilter --enable-muxers --enable-demuxers
&&
make
&&
make install
...
...
trunk/conf/srs.conf
查看文件 @
9a0d885
...
...
@@ -15,13 +15,19 @@ vhost __defaultVhost__ {
hls_path
./
objs
/
nginx
/
html
;
hls_fragment
5
;
hls_window
30
;
#
forward 127.0.0.1:1936;
forward
127
.
0
.
0
.
1
:
1936
;
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
#ffmpeg ./research/ffempty/ffempty;
engine
fast
{
enabled
on
;
vfilter
{
vf
'drawtext=text=SRS'
;
#vf 'crop=in_w-20:in_h-160:10:80';
#i ./doc/ffmpeg-logo.png;
#filter_complex 'overlay=10:10';
}
vcodec
libx264
;
vbitrate
300
;
vfps
20
;
...
...
@@ -37,11 +43,15 @@ vhost __defaultVhost__ {
asample_rate
44100
;
achannels
2
;
aparams
{
profile
:
a
aac_low
;
}
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
fast
;
}
engine
sd
{
enabled
on
;
enabled
off
;
vfilter
{
vf
'split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2'
;
}
vcodec
libx264
;
vbitrate
500
;
vfps
20
;
...
...
@@ -79,6 +89,14 @@ vhost all.transcode.vhost.com {
# whether the engine is enabled
# default: off.
enabled
on
;
# ffmpeg filters, follows the main input.
vfilter
{
# the logo input file.
i
./
doc
/
ffmpeg
-
logo
.
png
;
# the ffmpeg complex filter.
# for filters, @see: http://ffmpeg.org/ffmpeg-filters.html
filter_complex
'overlay=10:10'
;
}
# video encoder name
vcodec
libx264
;
# video bitrate, in kbps
...
...
@@ -100,6 +118,13 @@ vhost all.transcode.vhost.com {
vpreset
medium
;
# other x264 or ffmpeg video params
vparams
{
# ffmpeg options, @see: http://ffmpeg.org/ffmpeg.html
t
100
;
# 264 params, @see: http://ffmpeg.org/ffmpeg-codecs.html#libx264
coder
1
;
b_strategy
2
;
bf
3
;
refs
10
;
}
# audio encoder name
acodec
libaacplus
;
...
...
@@ -182,12 +207,102 @@ vhost all.transcode.vhost.com {
}
}
}
# the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction
vhost
mirror
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
mirror
{
enabled
on
;
vfilter
{
vf
'split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2'
;
}
vcodec
libx264
;
vbitrate
300
;
vfps
20
;
vwidth
480
;
vheight
320
;
vthreads
2
;
vprofile
baseline
;
vpreset
superfast
;
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
mirror
;
}
}
}
# the logo filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#crop
vhost
crop
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
crop
{
enabled
on
;
vfilter
{
vf
'crop=in_w-20:in_h-160:10:80'
;
}
vcodec
libx264
;
vbitrate
300
;
vfps
20
;
vwidth
480
;
vheight
320
;
vthreads
2
;
vprofile
baseline
;
vpreset
superfast
;
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
crop
;
}
}
}
# the crop filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#crop
vhost
logo
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
logo
{
enabled
on
;
vfilter
{
vf
'crop=200:100:10:10'
;
}
vcodec
libx264
;
vbitrate
300
;
vfps
20
;
vwidth
480
;
vheight
320
;
vthreads
2
;
vprofile
baseline
;
vpreset
superfast
;
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
logo
;
}
}
}
# transcode all stream using the empty ffmpeg demo, donothing.
vhost
ffempty
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
research
/
ffempty
/
ffempty
;
engine
fd
{
engine
empty
{
enabled
on
;
vcodec
libx264
;
vbitrate
300
;
...
...
@@ -205,7 +320,7 @@ vhost ffempty.transcode.vhost.com {
achannels
2
;
aparams
{
}
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
fast
;
output
rtmp
://[
vhost
]:[
port
]/[
app
]/[
stream
]
_
empty
;
}
}
}
...
...
trunk/doc/ffmpeg-logo.png
0 → 100644
查看文件 @
9a0d885
8.5 KB
trunk/src/core/srs_core_config.cpp
查看文件 @
9a0d885
...
...
@@ -768,30 +768,48 @@ std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine)
return
conf
->
arg0
();
}
std
::
string
SrsConfig
::
get_engine_vparams
(
SrsConfDirective
*
engine
)
void
SrsConfig
::
get_engine_vparams
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
vparams
)
{
if
(
!
engine
)
{
return
""
;
return
;
}
SrsConfDirective
*
conf
=
engine
->
get
(
"vparams"
);
if
(
!
conf
)
{
return
""
;
return
;
}
std
::
string
avparams
;
for
(
int
i
=
0
;
i
<
(
int
)
conf
->
directives
.
size
();
i
++
)
{
SrsConfDirective
*
p
=
conf
->
directives
[
i
];
if
(
!
p
)
{
continue
;
}
avparams
+=
p
->
name
;
avparams
+=
" "
;
avparams
+=
p
->
arg0
();
vparams
.
push_back
(
"-"
+
p
->
name
);
vparams
.
push_back
(
p
->
arg0
());
}
}
void
SrsConfig
::
get_engine_vfilter
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
vfilter
)
{
if
(
!
engine
)
{
return
;
}
SrsConfDirective
*
conf
=
engine
->
get
(
"vfilter"
);
if
(
!
conf
)
{
return
;
}
return
avparams
;
for
(
int
i
=
0
;
i
<
(
int
)
conf
->
directives
.
size
();
i
++
)
{
SrsConfDirective
*
p
=
conf
->
directives
[
i
];
if
(
!
p
)
{
continue
;
}
vfilter
.
push_back
(
"-"
+
p
->
name
);
vfilter
.
push_back
(
p
->
arg0
());
}
}
std
::
string
SrsConfig
::
get_engine_acodec
(
SrsConfDirective
*
engine
)
...
...
@@ -850,30 +868,26 @@ int SrsConfig::get_engine_achannels(SrsConfDirective* engine)
return
::
atoi
(
conf
->
arg0
().
c_str
());
}
std
::
string
SrsConfig
::
get_engine_aparams
(
SrsConfDirective
*
engine
)
void
SrsConfig
::
get_engine_aparams
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
aparams
)
{
if
(
!
engine
)
{
return
""
;
return
;
}
SrsConfDirective
*
conf
=
engine
->
get
(
"aparams"
);
if
(
!
conf
)
{
return
""
;
return
;
}
std
::
string
avparams
;
for
(
int
i
=
0
;
i
<
(
int
)
conf
->
directives
.
size
();
i
++
)
{
SrsConfDirective
*
p
=
conf
->
directives
[
i
];
if
(
!
p
)
{
continue
;
}
avparams
+=
p
->
name
;
avparams
+=
" "
;
avparams
+=
p
->
arg0
();
aparams
.
push_back
(
"-"
+
p
->
name
);
aparams
.
push_back
(
p
->
arg0
());
}
return
avparams
;
}
std
::
string
SrsConfig
::
get_engine_output
(
SrsConfDirective
*
engine
)
...
...
trunk/src/core/srs_core_config.hpp
查看文件 @
9a0d885
...
...
@@ -128,12 +128,13 @@ public:
virtual
int
get_engine_vthreads
(
SrsConfDirective
*
engine
);
virtual
std
::
string
get_engine_vprofile
(
SrsConfDirective
*
engine
);
virtual
std
::
string
get_engine_vpreset
(
SrsConfDirective
*
engine
);
virtual
std
::
string
get_engine_vparams
(
SrsConfDirective
*
engine
);
virtual
void
get_engine_vparams
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
vparams
);
virtual
void
get_engine_vfilter
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
vfilter
);
virtual
std
::
string
get_engine_acodec
(
SrsConfDirective
*
engine
);
virtual
int
get_engine_abitrate
(
SrsConfDirective
*
engine
);
virtual
int
get_engine_asample_rate
(
SrsConfDirective
*
engine
);
virtual
int
get_engine_achannels
(
SrsConfDirective
*
engine
);
virtual
std
::
string
get_engine_aparams
(
SrsConfDirective
*
engine
);
virtual
void
get_engine_aparams
(
SrsConfDirective
*
engine
,
std
::
vector
<
std
::
string
>&
aparams
);
virtual
std
::
string
get_engine_output
(
SrsConfDirective
*
engine
);
virtual
SrsConfDirective
*
get_gop_cache
(
std
::
string
vhost
);
virtual
SrsConfDirective
*
get_forward
(
std
::
string
vhost
);
...
...
trunk/src/core/srs_core_encoder.cpp
查看文件 @
9a0d885
...
...
@@ -60,6 +60,7 @@ int SrsFFMPEG::initialize(std::string vhost, std::string port, std::string app,
{
int
ret
=
ERROR_SUCCESS
;
config
->
get_engine_vfilter
(
engine
,
vfilter
);
vcodec
=
config
->
get_engine_vcodec
(
engine
);
vbitrate
=
config
->
get_engine_vbitrate
(
engine
);
vfps
=
config
->
get_engine_vfps
(
engine
);
...
...
@@ -68,12 +69,12 @@ int SrsFFMPEG::initialize(std::string vhost, std::string port, std::string app,
vthreads
=
config
->
get_engine_vthreads
(
engine
);
vprofile
=
config
->
get_engine_vprofile
(
engine
);
vpreset
=
config
->
get_engine_vpreset
(
engine
);
vparams
=
config
->
get_engine_vparams
(
engine
);
config
->
get_engine_vparams
(
engine
,
vparams
);
acodec
=
config
->
get_engine_acodec
(
engine
);
abitrate
=
config
->
get_engine_abitrate
(
engine
);
asample_rate
=
config
->
get_engine_asample_rate
(
engine
);
achannels
=
config
->
get_engine_achannels
(
engine
);
aparams
=
config
->
get_engine_aparams
(
engine
);
config
->
get_engine_aparams
(
engine
,
aparams
);
output
=
config
->
get_engine_output
(
engine
);
// ensure the size is even.
...
...
@@ -198,37 +199,109 @@ int SrsFFMPEG::start()
return
ret
;
}
// prepare execl params
char
vsize
[
22
];
snprintf
(
vsize
,
sizeof
(
vsize
),
"%dx%d"
,
vwidth
,
vheight
);
char
vaspect
[
22
];
snprintf
(
vaspect
,
sizeof
(
vaspect
),
"%d:%d"
,
vwidth
,
vheight
);
char
s_vbitrate
[
10
];
snprintf
(
s_vbitrate
,
sizeof
(
s_vbitrate
),
"%d"
,
vbitrate
*
1000
);
char
s_vfps
[
10
];
snprintf
(
s_vfps
,
sizeof
(
s_vfps
),
"%.2f"
,
vfps
);
char
s_vthreads
[
10
];
snprintf
(
s_vthreads
,
sizeof
(
s_vthreads
),
"%d"
,
vthreads
);
char
s_abitrate
[
10
];
snprintf
(
s_abitrate
,
sizeof
(
s_abitrate
),
"%d"
,
abitrate
*
1000
);
char
s_asample_rate
[
10
];
snprintf
(
s_asample_rate
,
sizeof
(
s_asample_rate
),
"%d"
,
asample_rate
);
char
s_achannels
[
10
];
snprintf
(
s_achannels
,
sizeof
(
s_achannels
),
"%d"
,
achannels
);
// TODO: execl donot support the params.
// video params
std
::
string
s_vpreset
=
vpreset
;
// prepare exec params
char
tmp
[
256
];
std
::
vector
<
std
::
string
>
params
;
// argv[0], set to ffmpeg bin.
// The execv() and execvp() functions ....
// The first argument, by convention, should point to
// the filename associated with the file being executed.
params
.
push_back
(
ffmpeg
);
// input.
params
.
push_back
(
"-f"
);
params
.
push_back
(
"flv"
);
params
.
push_back
(
"-i"
);
params
.
push_back
(
input
);
// build the filter
if
(
!
vfilter
.
empty
())
{
std
::
vector
<
std
::
string
>::
iterator
it
;
for
(
it
=
vfilter
.
begin
();
it
!=
vfilter
.
end
();
++
it
)
{
std
::
string
p
=
*
it
;
if
(
!
p
.
empty
())
{
params
.
push_back
(
p
);
}
}
}
// video specified.
params
.
push_back
(
"-vcodec"
);
params
.
push_back
(
vcodec
);
params
.
push_back
(
"-b:v"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
vbitrate
*
1000
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-r"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%.2f"
,
vfps
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-s"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%dx%d"
,
vwidth
,
vheight
);
params
.
push_back
(
tmp
);
// TODO: add aspect if needed.
params
.
push_back
(
"-aspect"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d:%d"
,
vwidth
,
vheight
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-threads"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
vthreads
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-profile:v"
);
params
.
push_back
(
vprofile
);
params
.
push_back
(
"-preset"
);
params
.
push_back
(
vpreset
);
// vparams
if
(
!
vparams
.
empty
())
{
s_vpreset
+=
" "
;
s_vpreset
+=
vparams
;
std
::
vector
<
std
::
string
>::
iterator
it
;
for
(
it
=
vparams
.
begin
();
it
!=
vparams
.
end
();
++
it
)
{
std
::
string
p
=
*
it
;
if
(
!
p
.
empty
())
{
params
.
push_back
(
p
);
}
}
}
// audio params
std
::
string
s_aparams
=
s_achannels
;
// audio specified.
params
.
push_back
(
"-acodec"
);
params
.
push_back
(
acodec
);
params
.
push_back
(
"-b:a"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
abitrate
*
1000
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-ar"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
asample_rate
);
params
.
push_back
(
tmp
);
params
.
push_back
(
"-ac"
);
snprintf
(
tmp
,
sizeof
(
tmp
),
"%d"
,
achannels
);
params
.
push_back
(
tmp
);
// aparams
if
(
!
aparams
.
empty
())
{
s_aparams
+=
" "
;
s_aparams
+=
aparams
;
std
::
vector
<
std
::
string
>::
iterator
it
;
for
(
it
=
aparams
.
begin
();
it
!=
aparams
.
end
();
++
it
)
{
std
::
string
p
=
*
it
;
if
(
!
p
.
empty
())
{
params
.
push_back
(
p
);
}
}
}
// output
params
.
push_back
(
"-f"
);
params
.
push_back
(
"flv"
);
params
.
push_back
(
"-y"
);
params
.
push_back
(
output
);
// TODO: fork or vfork?
if
((
pid
=
fork
())
<
0
)
{
...
...
@@ -239,28 +312,17 @@ int SrsFFMPEG::start()
// child process: ffmpeg encoder engine.
if
(
pid
==
0
)
{
// TODO: execl or execlp
ret
=
execl
(
ffmpeg
.
c_str
(),
"-f"
,
"flv"
,
"-i"
,
input
.
c_str
(),
// video specified.
"-vcodec"
,
vcodec
.
c_str
(),
"-b:v"
,
s_vbitrate
,
"-r"
,
s_vfps
,
"-s"
,
vsize
,
"-aspect"
,
vaspect
,
// TODO: add aspect if needed.
"-threads"
,
s_vthreads
,
"-profile:v"
,
vprofile
.
c_str
(),
"-preset"
,
s_vpreset
.
c_str
(),
// audio specified.
"-acodec"
,
acodec
.
c_str
(),
"-b:a"
,
s_abitrate
,
"-ar"
,
s_asample_rate
,
"-ac"
,
s_aparams
.
c_str
(),
"-f"
,
"flv"
,
"-y"
,
output
.
c_str
(),
NULL
);
// memory leak in child process, it's ok.
char
**
charpv_params
=
new
char
*
[
params
.
size
()
+
1
];
for
(
int
i
=
0
;
i
<
(
int
)
params
.
size
();
i
++
)
{
std
::
string
p
=
params
[
i
];
charpv_params
[
i
]
=
(
char
*
)
p
.
c_str
();
}
// EOF: NULL
charpv_params
[
params
.
size
()]
=
NULL
;
// TODO: execv or execvp
ret
=
execv
(
ffmpeg
.
c_str
(),
charpv_params
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"fork ffmpeg failed, errno=%d(%s)"
,
errno
,
strerror
(
errno
));
...
...
@@ -347,7 +409,7 @@ int SrsEncoder::on_publish(std::string _vhost, std::string _port, std::string _a
ret
=
parse_scope_engines
();
// ignore the loop encoder
if
(
ret
=
ERROR_ENCODER_LOOP
)
{
if
(
ret
=
=
ERROR_ENCODER_LOOP
)
{
ret
=
ERROR_SUCCESS
;
}
...
...
trunk/src/core/srs_core_encoder.hpp
查看文件 @
9a0d885
...
...
@@ -47,6 +47,7 @@ private:
pid_t
pid
;
private
:
std
::
string
ffmpeg
;
std
::
vector
<
std
::
string
>
vfilter
;
std
::
string
vcodec
;
int
vbitrate
;
double
vfps
;
...
...
@@ -55,12 +56,12 @@ private:
int
vthreads
;
std
::
string
vprofile
;
std
::
string
vpreset
;
std
::
string
vparams
;
std
::
vector
<
std
::
string
>
vparams
;
std
::
string
acodec
;
int
abitrate
;
int
asample_rate
;
int
achannels
;
std
::
string
aparams
;
std
::
vector
<
std
::
string
>
aparams
;
std
::
string
output
;
std
::
string
input
;
public
:
...
...
请
注册
或
登录
后发表评论