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-06 14:35:03 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
3b09f9bea9dad201b28be9be9bc5af775cbed202
3b09f9be
1 parent
2d592d17
support audio transcode only, speex/mp3 to aac
隐藏空白字符变更
内嵌
并排对比
正在显示
3 个修改的文件
包含
224 行增加
和
130 行删除
README.md
trunk/conf/srs.conf
trunk/src/core/srs_core_encoder.cpp
README.md
查看文件 @
3b09f9b
...
...
@@ -126,7 +126,7 @@ Supported operating systems and hardware:
16.
support live stream transcoding by ffmpeg.
<br/>
17.
support live stream transcoding by ffmpeg.
<br/>
18.
support ffmpeg filters(logo/overlay/crop), x264 params.
<br/>
19.
[
dev
]
support audio transcode only, speex/mp3 to aac
<br/>
19.
support audio transcode only, speex/mp3 to aac
<br/>
20.
[
plan
]
support network based cli and json result.
<br/>
21.
[
plan
]
support http callback api hooks(for authentication).
<br/>
22.
[
plan
]
support bandwidth test api and flash client.
<br/>
...
...
trunk/conf/srs.conf
查看文件 @
3b09f9b
...
...
@@ -15,6 +15,7 @@ log_dir ./objs/logs;
# default: 2000
max_connections
2000
;
# vhost list, the __defaultVhost__ is the default vhost
# for example, user use ip to access the stream: rtmp://192.168.1.2/live/livestream.
# for which cannot identify the required vhost.
# for default demo.
vhost
__
defaultVhost__
{
...
...
@@ -44,7 +45,7 @@ vhost __defaultVhost__ {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -90,7 +91,7 @@ vhost dev {
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
dev
{
enabled
o
n
;
enabled
o
ff
;
vfilter
{
}
vcodec
libx264
;
...
...
@@ -104,7 +105,18 @@ vhost dev {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
engine
dev_acodec
{
enabled
on
;
vcodec
copy
;
acodec
libaacplus
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -134,7 +146,7 @@ vhost mirror.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -164,7 +176,7 @@ vhost drawtext.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -194,7 +206,7 @@ vhost crop.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -224,7 +236,7 @@ vhost logo.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
@@ -233,6 +245,40 @@ vhost logo.transcode.vhost.com {
}
}
}
# audio transcode only.
# for example, FMLE publish audio codec in mp3, and donot support HLS output,
# we can transcode the audio to aac and copy video to the new stream with HLS.
vhost
audio
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
acodec
{
enabled
on
;
vcodec
copy
;
acodec
libaacplus
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
}
}
# ffmpeg-copy(forward implements by ffmpeg).
# copy the video and audio to a new stream.
vhost
copy
.
transcode
.
vhost
.
com
{
transcode
{
enabled
on
;
ffmpeg
./
objs
/
ffmpeg
/
bin
/
ffmpeg
;
engine
copy
{
enabled
on
;
vcodec
copy
;
acodec
copy
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
}
}
# transcode all app and stream of vhost
vhost
all
.
transcode
.
vhost
.
com
{
# the streaming transcode configs.
...
...
@@ -258,7 +304,9 @@ vhost all.transcode.vhost.com {
# for filters, @see: http://ffmpeg.org/ffmpeg-filters.html
filter_complex
'overlay=10:10'
;
}
# video encoder name
# video encoder name. can be:
# libx264: use h.264(libx264) video encoder.
# copy: donot encoder the video stream, copy it.
vcodec
libx264
;
# video bitrate, in kbps
vbitrate
1500
;
...
...
@@ -287,7 +335,9 @@ vhost all.transcode.vhost.com {
bf
3
;
refs
10
;
}
# audio encoder name
# audio encoder name. can be:
# libaacplus: use aac(libaacplus) audio encoder.
# copy: donot encoder the audio stream, copy it.
acodec
libaacplus
;
# audio bitrate, in kbps. [16, 72] for libaacplus.
abitrate
70
;
...
...
@@ -362,13 +412,45 @@ vhost all.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
engine
vcopy
{
enabled
on
;
vcodec
copy
;
acodec
libaacplus
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
}
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
engine
acopy
{
enabled
on
;
vcodec
libx264
;
vbitrate
300
;
vfps
20
;
vwidth
768
;
vheight
320
;
vthreads
2
;
vprofile
baseline
;
vpreset
superfast
;
vparams
{
}
acodec
copy
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
engine
copy
{
enabled
on
;
vcodec
copy
;
acodec
copy
;
output
rtmp
://
127
.
0
.
0
.
1
:[
port
]/[
app
]?
vhost
=[
vhost
]/[
stream
]
_
[
engine
];
}
}
}
# transcode all stream using the empty ffmpeg demo, donothing.
...
...
@@ -389,7 +471,7 @@ vhost ffempty.transcode.vhost.com {
vparams
{
}
acodec
libaacplus
;
abitrate
30
;
abitrate
45
;
asample_rate
44100
;
achannels
2
;
aparams
{
...
...
trunk/src/core/srs_core_encoder.cpp
查看文件 @
3b09f9b
...
...
@@ -42,8 +42,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SRS_ENCODER_SLEEP_MS 2000
#define SRS_ENCODER_VCODEC "libx264"
#define SRS_ENCODER_ACODEC "libaacplus"
#define SRS_ENCODER_COPY "copy"
#define SRS_ENCODER_VCODEC "libx264"
#define SRS_ENCODER_ACODEC "libaacplus"
// for encoder to detect the dead loop
static
std
::
vector
<
std
::
string
>
_transcoded_url
;
...
...
@@ -138,70 +139,75 @@ int SrsFFMPEG::initialize(SrsRequest* req, SrsConfDirective* engine)
}
_transcoded_url
.
push_back
(
output
);
if
(
vcodec
!=
SRS_ENCODER_VCODEC
)
{
ret
=
ERROR_ENCODER_VCODEC
;
srs_error
(
"invalid vcodec, must be %s, actual %s, ret=%d"
,
SRS_ENCODER_VCODEC
,
vcodec
.
c_str
(),
ret
);
return
ret
;
}
if
(
vbitrate
<=
0
)
{
ret
=
ERROR_ENCODER_VBITRATE
;
srs_error
(
"invalid vbitrate: %d, ret=%d"
,
vbitrate
,
ret
);
return
ret
;
}
if
(
vfps
<=
0
)
{
ret
=
ERROR_ENCODER_VFPS
;
srs_error
(
"invalid vfps: %.2f, ret=%d"
,
vfps
,
ret
);
return
ret
;
}
if
(
vwidth
<=
0
)
{
ret
=
ERROR_ENCODER_VWIDTH
;
srs_error
(
"invalid vwidth: %d, ret=%d"
,
vwidth
,
ret
);
return
ret
;
}
if
(
vheight
<=
0
)
{
ret
=
ERROR_ENCODER_VHEIGHT
;
srs_error
(
"invalid vheight: %d, ret=%d"
,
vheight
,
ret
);
return
ret
;
}
if
(
vthreads
<
0
)
{
ret
=
ERROR_ENCODER_VTHREADS
;
srs_error
(
"invalid vthreads: %d, ret=%d"
,
vthreads
,
ret
);
return
ret
;
}
if
(
vprofile
.
empty
())
{
ret
=
ERROR_ENCODER_VPROFILE
;
srs_error
(
"invalid vprofile: %s, ret=%d"
,
vprofile
.
c_str
(),
ret
);
return
ret
;
}
if
(
vpreset
.
empty
())
{
ret
=
ERROR_ENCODER_VPRESET
;
srs_error
(
"invalid vpreset: %s, ret=%d"
,
vpreset
.
c_str
(),
ret
);
return
ret
;
}
if
(
acodec
!=
SRS_ENCODER_ACODEC
)
{
ret
=
ERROR_ENCODER_ACODEC
;
srs_error
(
"invalid acodec, must be %s, actual %s, ret=%d"
,
SRS_ENCODER_ACODEC
,
acodec
.
c_str
(),
ret
);
return
ret
;
}
if
(
abitrate
<=
0
)
{
ret
=
ERROR_ENCODER_ABITRATE
;
srs_error
(
"invalid abitrate: %d, ret=%d"
,
abitrate
,
ret
);
return
ret
;
}
if
(
asample_rate
<=
0
)
{
ret
=
ERROR_ENCODER_ASAMPLE_RATE
;
srs_error
(
"invalid sample rate: %d, ret=%d"
,
asample_rate
,
ret
);
return
ret
;
if
(
vcodec
!=
SRS_ENCODER_COPY
)
{
if
(
vcodec
!=
SRS_ENCODER_VCODEC
)
{
ret
=
ERROR_ENCODER_VCODEC
;
srs_error
(
"invalid vcodec, must be %s, actual %s, ret=%d"
,
SRS_ENCODER_VCODEC
,
vcodec
.
c_str
(),
ret
);
return
ret
;
}
if
(
vbitrate
<=
0
)
{
ret
=
ERROR_ENCODER_VBITRATE
;
srs_error
(
"invalid vbitrate: %d, ret=%d"
,
vbitrate
,
ret
);
return
ret
;
}
if
(
vfps
<=
0
)
{
ret
=
ERROR_ENCODER_VFPS
;
srs_error
(
"invalid vfps: %.2f, ret=%d"
,
vfps
,
ret
);
return
ret
;
}
if
(
vwidth
<=
0
)
{
ret
=
ERROR_ENCODER_VWIDTH
;
srs_error
(
"invalid vwidth: %d, ret=%d"
,
vwidth
,
ret
);
return
ret
;
}
if
(
vheight
<=
0
)
{
ret
=
ERROR_ENCODER_VHEIGHT
;
srs_error
(
"invalid vheight: %d, ret=%d"
,
vheight
,
ret
);
return
ret
;
}
if
(
vthreads
<
0
)
{
ret
=
ERROR_ENCODER_VTHREADS
;
srs_error
(
"invalid vthreads: %d, ret=%d"
,
vthreads
,
ret
);
return
ret
;
}
if
(
vprofile
.
empty
())
{
ret
=
ERROR_ENCODER_VPROFILE
;
srs_error
(
"invalid vprofile: %s, ret=%d"
,
vprofile
.
c_str
(),
ret
);
return
ret
;
}
if
(
vpreset
.
empty
())
{
ret
=
ERROR_ENCODER_VPRESET
;
srs_error
(
"invalid vpreset: %s, ret=%d"
,
vpreset
.
c_str
(),
ret
);
return
ret
;
}
}
if
(
achannels
!=
1
&&
achannels
!=
2
)
{
ret
=
ERROR_ENCODER_ACHANNELS
;
srs_error
(
"invalid achannels, must be 1 or 2, actual %d, ret=%d"
,
achannels
,
ret
);
return
ret
;
if
(
acodec
!=
SRS_ENCODER_COPY
)
{
if
(
acodec
!=
SRS_ENCODER_ACODEC
)
{
ret
=
ERROR_ENCODER_ACODEC
;
srs_error
(
"invalid acodec, must be %s, actual %s, ret=%d"
,
SRS_ENCODER_ACODEC
,
acodec
.
c_str
(),
ret
);
return
ret
;
}
if
(
abitrate
<=
0
)
{
ret
=
ERROR_ENCODER_ABITRATE
;
srs_error
(
"invalid abitrate: %d, ret=%d"
,
abitrate
,
ret
);
return
ret
;
}
if
(
asample_rate
<=
0
)
{
ret
=
ERROR_ENCODER_ASAMPLE_RATE
;
srs_error
(
"invalid sample rate: %d, ret=%d"
,
asample_rate
,
ret
);
return
ret
;
}
if
(
achannels
!=
1
&&
achannels
!=
2
)
{
ret
=
ERROR_ENCODER_ACHANNELS
;
srs_error
(
"invalid achannels, must be 1 or 2, actual %d, ret=%d"
,
achannels
,
ret
);
return
ret
;
}
}
if
(
output
.
empty
())
{
ret
=
ERROR_ENCODER_OUTPUT
;
...
...
@@ -252,40 +258,43 @@ int SrsFFMPEG::start()
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
())
{
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
);
// the codec params is disabled when copy
if
(
vcodec
!=
SRS_ENCODER_COPY
)
{
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
())
{
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
);
}
}
}
}
...
...
@@ -294,25 +303,28 @@ int SrsFFMPEG::start()
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
())
{
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
);
// the codec params is disabled when copy
if
(
acodec
!=
SRS_ENCODER_COPY
)
{
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
())
{
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
);
}
}
}
}
...
...
请
注册
或
登录
后发表评论