Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
41509800
Commit
41509800
authored
May 28, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完善对无metadata的rtmp流的兼容性
parent
e7f263b0
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
89 行增加
和
87 行删除
+89
-87
src/Extension/Factory.cpp
+16
-2
src/Extension/Factory.h
+2
-1
src/Rtmp/Rtmp.cpp
+20
-0
src/Rtmp/Rtmp.h
+2
-1
src/Rtmp/RtmpDemuxer.cpp
+15
-19
src/Rtmp/RtmpDemuxer.h
+1
-1
src/Rtmp/RtmpMediaSourceImp.h
+20
-2
src/Rtmp/RtmpMuxer.cpp
+3
-43
src/Rtmp/amf.cpp
+8
-14
src/Rtmp/amf.h
+2
-4
没有找到文件。
src/Extension/Factory.cpp
查看文件 @
41509800
...
...
@@ -221,13 +221,27 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int
return
getTrackByCodecId
(
codecId
,
sample_rate
,
channels
,
sample_bit
);
}
RtmpCodec
::
Ptr
Factory
::
getRtmpCodecByTrack
(
const
Track
::
Ptr
&
track
)
{
RtmpCodec
::
Ptr
Factory
::
getRtmpCodecByTrack
(
const
Track
::
Ptr
&
track
,
bool
is_encode
)
{
switch
(
track
->
getCodecId
()){
case
CodecH264
:
return
std
::
make_shared
<
H264RtmpEncoder
>
(
track
);
case
CodecAAC
:
return
std
::
make_shared
<
AACRtmpEncoder
>
(
track
);
case
CodecH265
:
return
std
::
make_shared
<
H265RtmpEncoder
>
(
track
);
case
CodecG711A
:
case
CodecG711U
:
return
std
::
make_shared
<
G711RtmpEncoder
>
(
track
);
case
CodecG711U
:
{
auto
audio_track
=
dynamic_pointer_cast
<
AudioTrack
>
(
track
);
if
(
is_encode
&&
(
audio_track
->
getAudioSampleRate
()
!=
8000
||
audio_track
->
getAudioChannel
()
!=
1
||
audio_track
->
getAudioSampleBit
()
!=
16
))
{
//rtmp对g711只支持8000/1/16规格,但是ZLMediaKit可以解析其他规格的G711
WarnL
<<
"RTMP只支持8000/1/16规格的G711,目前规格是:"
<<
audio_track
->
getAudioSampleRate
()
<<
"/"
<<
audio_track
->
getAudioChannel
()
<<
"/"
<<
audio_track
->
getAudioSampleBit
()
<<
",该音频已被忽略"
;
return
nullptr
;
}
return
std
::
make_shared
<
G711RtmpEncoder
>
(
track
);
}
default
:
WarnL
<<
"暂不支持该CodecId:"
<<
track
->
getCodecName
();
return
nullptr
;
}
}
...
...
src/Extension/Factory.h
查看文件 @
41509800
...
...
@@ -59,8 +59,9 @@ public:
/**
* 根据Track获取Rtmp的编解码器
* @param track 媒体描述对象
* @param is_encode 是否为编码器还是解码器
*/
static
RtmpCodec
::
Ptr
getRtmpCodecByTrack
(
const
Track
::
Ptr
&
track
);
static
RtmpCodec
::
Ptr
getRtmpCodecByTrack
(
const
Track
::
Ptr
&
track
,
bool
is_encode
);
/**
* 根据codecId获取rtmp的codec描述
...
...
src/Rtmp/Rtmp.cpp
查看文件 @
41509800
...
...
@@ -100,4 +100,23 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track){
}
void
Metadata
::
addTrack
(
AMFValue
&
metadata
,
const
Track
::
Ptr
&
track
)
{
Metadata
::
Ptr
new_metadata
;
switch
(
track
->
getTrackType
())
{
case
TrackVideo
:
{
new_metadata
=
std
::
make_shared
<
VideoMeta
>
(
dynamic_pointer_cast
<
VideoTrack
>
(
track
));
}
break
;
case
TrackAudio
:
{
new_metadata
=
std
::
make_shared
<
AudioMeta
>
(
dynamic_pointer_cast
<
AudioTrack
>
(
track
));
}
break
;
default
:
return
;
}
new_metadata
->
getMetadata
().
object_for_each
([
&
](
const
std
::
string
&
key
,
const
AMFValue
&
value
)
{
metadata
.
set
(
key
,
value
);
});
}
}
//
namespace
mediakit
\ No newline at end of file
src/Rtmp/Rtmp.h
查看文件 @
41509800
...
...
@@ -220,6 +220,8 @@ public:
const
AMFValue
&
getMetadata
()
const
{
return
_metadata
;
}
static
void
addTrack
(
AMFValue
&
metadata
,
const
Track
::
Ptr
&
track
);
protected
:
AMFValue
_metadata
;
};
...
...
@@ -261,7 +263,6 @@ private:
CodecId
_codecId
;
};
class
AudioMeta
:
public
Metadata
{
public
:
typedef
std
::
shared_ptr
<
AudioMeta
>
Ptr
;
...
...
src/Rtmp/RtmpDemuxer.cpp
查看文件 @
41509800
...
...
@@ -13,60 +13,56 @@
namespace
mediakit
{
void
RtmpDemuxer
::
loadMetaData
(
const
AMFValue
&
val
){
bool
RtmpDemuxer
::
loadMetaData
(
const
AMFValue
&
val
){
bool
ret
=
false
;
try
{
int
audiosamplerate
=
0
;
int
audiochannels
=
0
;
int
audiosamplesize
=
0
;
const
AMFValue
*
audiocodecid
=
nullptr
;
const
AMFValue
*
videocodecid
=
nullptr
;
val
.
object_for_each
([
&
](
const
string
&
key
,
const
AMFValue
&
val
)
{
if
(
key
==
"duration"
)
{
_fDuration
=
val
.
as_number
();
return
;
}
if
(
key
==
"audiosamplerate"
){
if
(
key
==
"audiosamplerate"
)
{
audiosamplerate
=
val
.
as_integer
();
return
;
}
if
(
key
==
"audiosamplesize"
){
if
(
key
==
"audiosamplesize"
)
{
audiosamplesize
=
val
.
as_integer
();
return
;
}
if
(
key
==
"stereo"
){
if
(
key
==
"stereo"
)
{
audiochannels
=
val
.
as_boolean
()
?
2
:
1
;
return
;
}
if
(
key
==
"videocodecid"
){
if
(
key
==
"videocodecid"
)
{
//找到视频
videocodecid
=
&
val
;
return
;
}
if
(
key
==
"audiocodecid"
){
if
(
key
==
"audiocodecid"
)
{
//找到音频
audiocodecid
=
&
val
;
return
;
}
});
if
(
videocodecid
){
if
(
videocodecid
)
{
//有视频
ret
=
true
;
makeVideoTrack
(
*
videocodecid
);
}
if
(
audiocodecid
){
if
(
audiocodecid
)
{
//有音频
ret
=
true
;
makeAudioTrack
(
*
audiocodecid
,
audiosamplerate
,
audiochannels
,
audiosamplesize
);
}
}
catch
(
std
::
exception
&
ex
)
{
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
}
return
ret
;
}
bool
RtmpDemuxer
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
...
...
@@ -105,7 +101,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
_videoTrack
=
dynamic_pointer_cast
<
VideoTrack
>
(
Factory
::
getVideoTrackByAmf
(
videoCodec
));
if
(
_videoTrack
)
{
//生成rtmpCodec对象以便解码rtmp
_videoRtmpDecoder
=
Factory
::
getRtmpCodecByTrack
(
_videoTrack
);
_videoRtmpDecoder
=
Factory
::
getRtmpCodecByTrack
(
_videoTrack
,
false
);
if
(
_videoRtmpDecoder
)
{
//设置rtmp解码器代理,生成的frame写入该Track
_videoRtmpDecoder
->
addDelegate
(
_videoTrack
);
...
...
@@ -123,7 +119,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int
_audioTrack
=
dynamic_pointer_cast
<
AudioTrack
>
(
Factory
::
getAudioTrackByAmf
(
audioCodec
,
sample_rate
,
channels
,
sample_bit
));
if
(
_audioTrack
)
{
//生成rtmpCodec对象以便解码rtmp
_audioRtmpDecoder
=
Factory
::
getRtmpCodecByTrack
(
_audioTrack
);
_audioRtmpDecoder
=
Factory
::
getRtmpCodecByTrack
(
_audioTrack
,
false
);
if
(
_audioRtmpDecoder
)
{
//设置rtmp解码器代理,生成的frame写入该Track
_audioRtmpDecoder
->
addDelegate
(
_audioTrack
);
...
...
src/Rtmp/RtmpDemuxer.h
查看文件 @
41509800
...
...
@@ -30,7 +30,7 @@ public:
RtmpDemuxer
()
=
default
;
virtual
~
RtmpDemuxer
()
=
default
;
void
loadMetaData
(
const
AMFValue
&
metadata
);
bool
loadMetaData
(
const
AMFValue
&
metadata
);
/**
* 开始解复用
...
...
src/Rtmp/RtmpMediaSourceImp.h
查看文件 @
41509800
...
...
@@ -49,8 +49,13 @@ public:
* 设置metadata
*/
void
setMetaData
(
const
AMFValue
&
metadata
)
override
{
_demuxer
->
loadMetaData
(
metadata
);
RtmpMediaSource
::
setMetaData
(
metadata
);
if
(
!
_demuxer
->
loadMetaData
(
metadata
)){
//该metadata无效,需要重新生成
_metadata
=
metadata
;
_recreate_metadata
=
true
;
}
else
{
RtmpMediaSource
::
setMetaData
(
metadata
);
}
}
/**
...
...
@@ -138,6 +143,11 @@ public:
_muxer
->
addTrack
(
track
);
track
->
addDelegate
(
_muxer
);
}
if
(
_recreate_metadata
){
//需要重新生成metadata
Metadata
::
addTrack
(
_metadata
,
track
);
}
}
/**
...
...
@@ -146,11 +156,19 @@ public:
void
onAllTrackReady
()
override
{
setTrackSource
(
_muxer
);
_all_track_ready
=
true
;
if
(
_recreate_metadata
){
//需要重新生成metadata
RtmpMediaSource
::
setMetaData
(
_metadata
);
}
}
private
:
RtmpDemuxer
::
Ptr
_demuxer
;
MultiMediaSourceMuxer
::
Ptr
_muxer
;
AMFValue
_metadata
;
bool
_all_track_ready
=
false
;
bool
_recreate_metadata
=
false
;
};
}
/* namespace mediakit */
...
...
src/Rtmp/RtmpMuxer.cpp
查看文件 @
41509800
...
...
@@ -23,47 +23,9 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
}
void
RtmpMuxer
::
addTrack
(
const
Track
::
Ptr
&
track
)
{
//根据track生产metadata
Metadata
::
Ptr
metadata
;
switch
(
track
->
getTrackType
()){
case
TrackVideo
:{
metadata
=
std
::
make_shared
<
VideoMeta
>
(
dynamic_pointer_cast
<
VideoTrack
>
(
track
));
}
break
;
case
TrackAudio
:{
metadata
=
std
::
make_shared
<
AudioMeta
>
(
dynamic_pointer_cast
<
AudioTrack
>
(
track
));
}
break
;
default
:
return
;
}
switch
(
track
->
getCodecId
()){
case
CodecG711A
:
case
CodecG711U
:{
auto
audio_track
=
dynamic_pointer_cast
<
AudioTrack
>
(
track
);
if
(
!
audio_track
){
return
;
}
if
(
audio_track
->
getAudioSampleRate
()
!=
8000
||
audio_track
->
getAudioChannel
()
!=
1
||
audio_track
->
getAudioSampleBit
()
!=
16
)
{
WarnL
<<
"RTMP只支持8000/1/16规格的G711,目前规格是:"
<<
audio_track
->
getAudioSampleRate
()
<<
"/"
<<
audio_track
->
getAudioChannel
()
<<
"/"
<<
audio_track
->
getAudioSampleBit
()
<<
",该音频已被忽略"
;
return
;
}
break
;
}
default
:
break
;
}
auto
&
encoder
=
_encoder
[
track
->
getTrackType
()];
//生成rtmp编码器,克隆该Track,防止循环引用
encoder
=
Factory
::
getRtmpCodecByTrack
(
track
->
clone
());
encoder
=
Factory
::
getRtmpCodecByTrack
(
track
->
clone
()
,
true
);
if
(
!
encoder
)
{
return
;
}
...
...
@@ -71,10 +33,8 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) {
//设置rtmp输出环形缓存
encoder
->
setRtmpRing
(
_rtmpRing
);
//添加其metadata
metadata
->
getMetadata
().
object_for_each
([
&
](
const
std
::
string
&
key
,
const
AMFValue
&
value
){
_metadata
.
set
(
key
,
value
);
});
//添加metadata
Metadata
::
addTrack
(
_metadata
,
track
);
}
void
RtmpMuxer
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
...
...
src/Rtmp/amf.cpp
查看文件 @
41509800
...
...
@@ -44,6 +44,7 @@ inline void AMFValue::destroy() {
break
;
}
}
inline
void
AMFValue
::
init
()
{
switch
(
_type
)
{
case
AMF_OBJECT
:
...
...
@@ -60,14 +61,13 @@ inline void AMFValue::init() {
default
:
break
;
}
}
AMFValue
::
AMFValue
(
AMFType
type
)
:
_type
(
type
)
{
init
();
}
AMFValue
::~
AMFValue
()
{
destroy
();
}
...
...
@@ -78,7 +78,6 @@ AMFValue::AMFValue(const char *s) :
*
_value
.
string
=
s
;
}
AMFValue
::
AMFValue
(
const
std
::
string
&
s
)
:
_type
(
AMF_STRING
)
{
init
();
...
...
@@ -108,15 +107,7 @@ AMFValue::AMFValue(const AMFValue &from) :
*
this
=
from
;
}
AMFValue
::
AMFValue
(
AMFValue
&&
from
)
{
*
this
=
std
::
forward
<
AMFValue
>
(
from
);
}
AMFValue
&
AMFValue
::
operator
=
(
const
AMFValue
&
from
)
{
return
*
this
=
const_cast
<
AMFValue
&&>
(
from
);
}
AMFValue
&
AMFValue
::
operator
=
(
AMFValue
&&
from
)
{
AMFValue
&
AMFValue
::
operator
=
(
const
AMFValue
&
from
)
{
destroy
();
_type
=
from
.
_type
;
init
();
...
...
@@ -144,7 +135,6 @@ AMFValue& AMFValue::operator =(AMFValue &&from) {
break
;
}
return
*
this
;
}
void
AMFValue
::
clear
()
{
...
...
@@ -236,7 +226,6 @@ string AMFValue::to_string() const{
}
}
const
AMFValue
&
AMFValue
::
operator
[](
const
char
*
str
)
const
{
if
(
_type
!=
AMF_OBJECT
&&
_type
!=
AMF_ECMA_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a object"
);
...
...
@@ -338,6 +327,7 @@ AMFEncoder & AMFEncoder::operator <<(const char *s) {
}
return
*
this
;
}
AMFEncoder
&
AMFEncoder
::
operator
<<
(
const
std
::
string
&
s
)
{
if
(
!
s
.
empty
())
{
buf
+=
char
(
AMF0_STRING
);
...
...
@@ -349,18 +339,22 @@ AMFEncoder & AMFEncoder::operator <<(const std::string &s) {
}
return
*
this
;
}
AMFEncoder
&
AMFEncoder
::
operator
<<
(
std
::
nullptr_t
)
{
buf
+=
char
(
AMF0_NULL
);
return
*
this
;
}
AMFEncoder
&
AMFEncoder
::
write_undefined
()
{
buf
+=
char
(
AMF0_UNDEFINED
);
return
*
this
;
}
AMFEncoder
&
AMFEncoder
::
operator
<<
(
const
int
n
){
return
(
*
this
)
<<
(
double
)
n
;
}
AMFEncoder
&
AMFEncoder
::
operator
<<
(
const
double
n
)
{
buf
+=
char
(
AMF0_NUMBER
);
uint64_t
encoded
=
0
;
...
...
src/Rtmp/amf.h
查看文件 @
41509800
...
...
@@ -40,6 +40,7 @@ public:
typedef
std
::
map
<
std
::
string
,
AMFValue
>
mapType
;
typedef
std
::
vector
<
AMFValue
>
arrayType
;
~
AMFValue
();
AMFValue
(
AMFType
type
=
AMF_NULL
);
AMFValue
(
const
char
*
s
);
AMFValue
(
const
std
::
string
&
s
);
...
...
@@ -47,10 +48,7 @@ public:
AMFValue
(
int
i
);
AMFValue
(
bool
b
);
AMFValue
(
const
AMFValue
&
from
);
AMFValue
(
AMFValue
&&
from
);
AMFValue
&
operator
=
(
const
AMFValue
&
from
);
AMFValue
&
operator
=
(
AMFValue
&&
from
);
~
AMFValue
();
AMFValue
&
operator
=
(
const
AMFValue
&
from
);
void
clear
();
AMFType
type
()
const
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论