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
62ba87dd
Commit
62ba87dd
authored
4 years ago
by
xia-chu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化frame性能及整理代码
parent
c5cfbce2
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
33 个修改的文件
包含
810 行增加
和
605 行删除
+810
-605
src/Common/Device.cpp
+2
-2
src/Extension/AAC.cpp
+130
-0
src/Extension/AAC.h
+15
-156
src/Extension/AACRtmp.cpp
+1
-1
src/Extension/AACRtmp.h
+1
-1
src/Extension/AACRtp.cpp
+1
-3
src/Extension/AACRtp.h
+1
-1
src/Extension/CommonRtmp.cpp
+1
-4
src/Extension/CommonRtmp.h
+1
-1
src/Extension/CommonRtp.cpp
+1
-4
src/Extension/CommonRtp.h
+1
-1
src/Extension/Frame.cpp
+33
-3
src/Extension/Frame.h
+11
-21
src/Extension/G711.cpp
+41
-0
src/Extension/G711.h
+3
-44
src/Extension/H264.cpp
+210
-0
src/Extension/H264.h
+0
-0
src/Extension/H264Rtmp.cpp
+3
-5
src/Extension/H264Rtmp.h
+1
-1
src/Extension/H264Rtp.cpp
+5
-7
src/Extension/H264Rtp.h
+1
-1
src/Extension/H265.cpp
+223
-2
src/Extension/H265.h
+37
-254
src/Extension/H265Rtmp.cpp
+3
-5
src/Extension/H265Rtmp.h
+1
-1
src/Extension/H265Rtp.cpp
+2
-4
src/Extension/H265Rtp.h
+1
-1
src/Extension/L16.cpp
+41
-0
src/Extension/L16.h
+3
-44
src/Extension/Opus.cpp
+34
-0
src/Extension/Opus.h
+0
-34
src/Record/MP4Demuxer.cpp
+1
-1
src/Rtmp/Rtmp.cpp
+1
-3
没有找到文件。
src/Common/Device.cpp
查看文件 @
62ba87dd
...
...
@@ -87,7 +87,7 @@ void DevChannel::inputH264(const char *data, int len, uint32_t dts, uint32_t pts
//由于rtmp/hls/mp4需要缓存时间戳相同的帧,
//所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝
//在此处只拷贝一次,性能开销更低
H264Frame
::
Ptr
frame
=
std
::
make_shared
<
H264Frame
>
();
auto
frame
=
FrameImp
::
create
<
H264Frame
>
();
frame
->
_dts
=
dts
;
frame
->
_pts
=
pts
;
frame
->
_buffer
.
assign
(
data
,
len
);
...
...
@@ -106,7 +106,7 @@ void DevChannel::inputH265(const char *data, int len, uint32_t dts, uint32_t pts
//由于rtmp/hls/mp4需要缓存时间戳相同的帧,
//所以使用FrameNoCacheAble类型的帧反而会在转换成FrameCacheAble时多次内存拷贝
//在此处只拷贝一次,性能开销更低
H265Frame
::
Ptr
frame
=
std
::
make_shared
<
H265Frame
>
();
auto
frame
=
FrameImp
::
create
<
H265Frame
>
();
frame
->
_dts
=
dts
;
frame
->
_pts
=
pts
;
frame
->
_buffer
.
assign
(
data
,
len
);
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AAC.cpp
查看文件 @
62ba87dd
...
...
@@ -182,6 +182,136 @@ bool parseAacConfig(const string &config, int &samplerate, int &channels){
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* aac类型SDP
*/
class
AACSdp
:
public
Sdp
{
public
:
/**
* 构造函数
* @param aac_cfg aac两个字节的配置描述
* @param sample_rate 音频采样率
* @param payload_type rtp payload type 默认98
* @param bitrate 比特率
*/
AACSdp
(
const
string
&
aac_cfg
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" MPEG4-GENERIC/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
string
configStr
;
char
buf
[
4
]
=
{
0
};
for
(
auto
&
ch
:
aac_cfg
){
snprintf
(
buf
,
sizeof
(
buf
),
"%02X"
,
(
uint8_t
)
ch
);
configStr
.
append
(
buf
);
}
_printer
<<
"a=fmtp:"
<<
payload_type
<<
" streamtype=5;profile-level-id=1;mode=AAC-hbr;"
<<
"sizelength=13;indexlength=3;indexdeltalength=3;config="
<<
configStr
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecAAC
;
}
private
:
_StrPrinter
_printer
;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
AACTrack
::
AACTrack
(
const
string
&
aac_cfg
)
{
if
(
aac_cfg
.
size
()
<
2
)
{
throw
std
::
invalid_argument
(
"adts配置必须最少2个字节"
);
}
_cfg
=
aac_cfg
;
onReady
();
}
const
string
&
AACTrack
::
getAacCfg
()
const
{
return
_cfg
;
}
CodecId
AACTrack
::
getCodecId
()
const
{
return
CodecAAC
;
}
bool
AACTrack
::
ready
()
{
return
!
_cfg
.
empty
();
}
int
AACTrack
::
getAudioSampleRate
()
const
{
return
_sampleRate
;
}
int
AACTrack
::
getAudioSampleBit
()
const
{
return
_sampleBit
;
}
int
AACTrack
::
getAudioChannel
()
const
{
return
_channel
;
}
void
AACTrack
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
if
(
frame
->
prefixSize
())
{
//有adts头,尝试分帧
auto
ptr
=
frame
->
data
();
auto
end
=
frame
->
data
()
+
frame
->
size
();
while
(
ptr
<
end
)
{
auto
frame_len
=
getAacFrameLength
((
uint8_t
*
)
ptr
,
end
-
ptr
);
if
(
frame_len
<
ADTS_HEADER_LEN
)
{
break
;
}
auto
sub_frame
=
std
::
make_shared
<
FrameInternal
<
FrameFromPtr
>
>
(
frame
,
(
char
*
)
ptr
,
frame_len
,
ADTS_HEADER_LEN
);
ptr
+=
frame_len
;
sub_frame
->
setCodecId
(
CodecAAC
);
inputFrame_l
(
sub_frame
);
}
}
else
{
inputFrame_l
(
frame
);
}
}
void
AACTrack
::
inputFrame_l
(
const
Frame
::
Ptr
&
frame
)
{
if
(
_cfg
.
empty
())
{
//未获取到aac_cfg信息
if
(
frame
->
prefixSize
())
{
//根据7个字节的adts头生成aac config
_cfg
=
makeAacConfig
((
uint8_t
*
)
(
frame
->
data
()),
frame
->
prefixSize
());
onReady
();
}
else
{
WarnL
<<
"无法获取adts头!"
;
}
}
if
(
frame
->
size
()
>
frame
->
prefixSize
())
{
//除adts头外,有实际负载
AudioTrack
::
inputFrame
(
frame
);
}
}
void
AACTrack
::
onReady
()
{
if
(
_cfg
.
size
()
<
2
)
{
return
;
}
parseAacConfig
(
_cfg
,
_sampleRate
,
_channel
);
}
Track
::
Ptr
AACTrack
::
clone
()
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
Sdp
::
Ptr
AACTrack
::
getSdp
()
{
if
(
!
ready
()){
WarnL
<<
getCodecName
()
<<
" Track未准备好"
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AAC.h
查看文件 @
62ba87dd
...
...
@@ -27,184 +27,43 @@ bool parseAacConfig(const string &config, int &samplerate, int &channels);
*/
class
AACTrack
:
public
AudioTrack
{
public
:
typedef
std
::
shared_ptr
<
AACTrack
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
AACTrack
>
;
/**
* 延后获取adts头信息
* 在随后的inputFrame中获取adts头信息
*/
AACTrack
()
{}
AACTrack
()
=
default
;
/**
* 构造aac类型的媒体
* @param aac_cfg aac配置信息
*/
AACTrack
(
const
string
&
aac_cfg
){
setAacCfg
(
aac_cfg
);
}
/**
* 设置aac 配置信息
*/
void
setAacCfg
(
const
string
&
aac_cfg
){
if
(
aac_cfg
.
size
()
<
2
)
{
throw
std
::
invalid_argument
(
"adts配置必须最少2个字节"
);
}
_cfg
=
aac_cfg
;
onReady
();
}
AACTrack
(
const
string
&
aac_cfg
);
/**
* 获取aac 配置信息
*/
const
string
&
getAacCfg
()
const
{
return
_cfg
;
}
/**
* 返回编码类型
*/
CodecId
getCodecId
()
const
override
{
return
CodecAAC
;
}
/**
* 在获取aac_cfg前是无效的Track
*/
bool
ready
()
override
{
return
!
_cfg
.
empty
();
}
/**
* 返回音频采样率
*/
int
getAudioSampleRate
()
const
override
{
return
_sampleRate
;
}
/**
* 返回音频采样位数,一般为16或8
*/
int
getAudioSampleBit
()
const
override
{
return
_sampleBit
;
}
/**
* 返回音频通道数
*/
int
getAudioChannel
()
const
override
{
return
_channel
;
}
/**
* 输入数据帧,并获取aac_cfg
* @param frame 数据帧
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
{
if
(
frame
->
prefixSize
())
{
//有adts头,尝试分帧
auto
ptr
=
frame
->
data
();
auto
end
=
frame
->
data
()
+
frame
->
size
();
while
(
ptr
<
end
)
{
auto
frame_len
=
getAacFrameLength
((
uint8_t
*
)
ptr
,
end
-
ptr
);
if
(
frame_len
<
ADTS_HEADER_LEN
)
{
break
;
}
const
string
&
getAacCfg
()
const
;
auto
sub_frame
=
std
::
make_shared
<
FrameInternal
<
FrameFromPtr
>
>
(
frame
,
(
char
*
)
ptr
,
frame_len
,
ADTS_HEADER_LEN
);
ptr
+=
frame_len
;
sub_frame
->
setCodecId
(
CodecAAC
);
inputFrame_l
(
sub_frame
);
}
}
else
{
inputFrame_l
(
frame
);
}
}
bool
ready
()
override
;
CodecId
getCodecId
()
const
override
;
int
getAudioChannel
()
const
override
;
int
getAudioSampleRate
()
const
override
;
int
getAudioSampleBit
()
const
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
private
:
void
inputFrame_l
(
const
Frame
::
Ptr
&
frame
)
{
if
(
_cfg
.
empty
())
{
//未获取到aac_cfg信息
if
(
frame
->
prefixSize
())
{
//根据7个字节的adts头生成aac config
_cfg
=
makeAacConfig
((
uint8_t
*
)
(
frame
->
data
()),
frame
->
prefixSize
());
onReady
();
}
else
{
WarnL
<<
"无法获取adts头!"
;
}
}
if
(
frame
->
size
()
>
frame
->
prefixSize
())
{
//除adts头外,有实际负载
AudioTrack
::
inputFrame
(
frame
);
}
}
/**
* 解析2个字节的aac配置
*/
void
onReady
(){
if
(
_cfg
.
size
()
<
2
)
{
return
;
}
parseAacConfig
(
_cfg
,
_sampleRate
,
_channel
);
}
void
onReady
();
Sdp
::
Ptr
getSdp
()
override
;
Track
::
Ptr
clone
()
override
;
void
inputFrame_l
(
const
Frame
::
Ptr
&
frame
);
Track
::
Ptr
clone
()
override
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
//生成sdp
Sdp
::
Ptr
getSdp
()
override
;
private
:
string
_cfg
;
int
_channel
=
0
;
int
_sampleRate
=
0
;
int
_sampleBit
=
16
;
int
_channel
=
0
;
};
/**
* aac类型SDP
*/
class
AACSdp
:
public
Sdp
{
public
:
/**
* 构造函数
* @param aac_cfg aac两个字节的配置描述
* @param sample_rate 音频采样率
* @param payload_type rtp payload type 默认98
* @param bitrate 比特率
*/
AACSdp
(
const
string
&
aac_cfg
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" MPEG4-GENERIC/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
string
configStr
;
char
buf
[
4
]
=
{
0
};
for
(
auto
&
ch
:
aac_cfg
){
snprintf
(
buf
,
sizeof
(
buf
),
"%02X"
,
(
uint8_t
)
ch
);
configStr
.
append
(
buf
);
}
_printer
<<
"a=fmtp:"
<<
payload_type
<<
" streamtype=5;profile-level-id=1;mode=AAC-hbr;"
<<
"sizelength=13;indexlength=3;indexdeltalength=3;config="
<<
configStr
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecAAC
;
}
private
:
_StrPrinter
_printer
;
};
}
//namespace mediakit
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AACRtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -42,7 +42,7 @@ void AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
}
void
AACRtmpDecoder
::
onGetAAC
(
const
char
*
data
,
size_t
len
,
uint32_t
stamp
)
{
auto
frame
=
ResourcePoolHelper
<
FrameImp
>::
obtainObj
();
auto
frame
=
FrameImp
::
create
();
frame
->
_codec_id
=
CodecAAC
;
//生成adts头
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AACRtmp.h
查看文件 @
62ba87dd
...
...
@@ -19,7 +19,7 @@ namespace mediakit{
/**
* aac Rtmp转adts类
*/
class
AACRtmpDecoder
:
public
RtmpCodec
,
public
ResourcePoolHelper
<
FrameImp
>
{
class
AACRtmpDecoder
:
public
RtmpCodec
{
public
:
typedef
std
::
shared_ptr
<
AACRtmpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AACRtp.cpp
查看文件 @
62ba87dd
...
...
@@ -74,9 +74,7 @@ AACRtpDecoder::AACRtpDecoder() {
void
AACRtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
_frame
=
ResourcePoolHelper
<
FrameImp
>::
obtainObj
();
_frame
->
_prefix_size
=
0
;
_frame
->
_buffer
.
clear
();
_frame
=
FrameImp
::
create
();
_frame
->
_codec_id
=
CodecAAC
;
}
...
...
This diff is collapsed.
Click to expand it.
src/Extension/AACRtp.h
查看文件 @
62ba87dd
...
...
@@ -17,7 +17,7 @@ namespace mediakit{
/**
* aac rtp转adts类
*/
class
AACRtpDecoder
:
public
RtpCodec
,
public
ResourcePoolHelper
<
FrameImp
>
{
class
AACRtpDecoder
:
public
RtpCodec
{
public
:
typedef
std
::
shared_ptr
<
AACRtpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/CommonRtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -22,11 +22,8 @@ CodecId CommonRtmpDecoder::getCodecId() const {
}
void
CommonRtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
_frame
=
ResourcePoolHelper
<
FrameImp
>::
obtainObj
();
_frame
->
_buffer
.
clear
();
_frame
=
FrameImp
::
create
();
_frame
->
_codec_id
=
_codec
;
_frame
->
_prefix_size
=
0
;
}
void
CommonRtmpDecoder
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
rtmp
)
{
...
...
This diff is collapsed.
Click to expand it.
src/Extension/CommonRtmp.h
查看文件 @
62ba87dd
...
...
@@ -19,7 +19,7 @@ namespace mediakit{
/**
* 通用 rtmp解码类
*/
class
CommonRtmpDecoder
:
public
RtmpCodec
,
public
ResourcePoolHelper
<
FrameImp
>
{
class
CommonRtmpDecoder
:
public
RtmpCodec
{
public
:
typedef
std
::
shared_ptr
<
CommonRtmpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/CommonRtp.cpp
查看文件 @
62ba87dd
...
...
@@ -21,10 +21,7 @@ CodecId CommonRtpDecoder::getCodecId() const {
}
void
CommonRtpDecoder
::
obtainFrame
()
{
_frame
=
ResourcePoolHelper
<
FrameImp
>::
obtainObj
();
_frame
->
_buffer
.
clear
();
_frame
->
_prefix_size
=
0
;
_frame
->
_dts
=
0
;
_frame
=
FrameImp
::
create
();
_frame
->
_codec_id
=
_codec
;
}
...
...
This diff is collapsed.
Click to expand it.
src/Extension/CommonRtp.h
查看文件 @
62ba87dd
...
...
@@ -19,7 +19,7 @@ namespace mediakit{
/**
* 通用 rtp解码类
*/
class
CommonRtpDecoder
:
public
RtpCodec
,
public
ResourcePoolHelper
<
FrameImp
>
{
class
CommonRtpDecoder
:
public
RtpCodec
{
public
:
typedef
std
::
shared_ptr
<
CommonRtpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/Frame.cpp
查看文件 @
62ba87dd
...
...
@@ -9,6 +9,8 @@
*/
#include "Frame.h"
#include "H264.h"
#include "H265.h"
using
namespace
std
;
using
namespace
toolkit
;
...
...
@@ -20,6 +22,34 @@ namespace toolkit {
namespace
mediakit
{
template
<
typename
C
>
std
::
shared_ptr
<
C
>
FrameImp
::
create_l
()
{
#if 0
static ResourcePool<C> packet_pool;
static onceToken token([]() {
packet_pool.setSize(1024);
});
auto ret = packet_pool.obtain();
ret->_buffer.clear();
ret->_prefix_size = 0;
ret->_dts = 0;
ret->_pts = 0;
return ret;
#else
return
std
::
shared_ptr
<
C
>
(
new
C
());
#endif
}
#define CREATE_FRAME_IMP(C) \
template<> \
std::shared_ptr<C> FrameImp::create<C>() { \
return create_l<C>(); \
}
CREATE_FRAME_IMP
(
FrameImp
);
CREATE_FRAME_IMP
(
H264Frame
);
CREATE_FRAME_IMP
(
H265Frame
);
/**
* 该对象的功能是把一个不可缓存的帧转换成可缓存的帧
*/
...
...
@@ -32,8 +62,8 @@ public:
_frame
=
frame
;
_ptr
=
frame
->
data
();
}
else
{
_buffer
=
std
::
make_shared
<
BufferRaw
>
();
_buffer
->
assign
(
frame
->
data
(),
frame
->
size
());
_buffer
=
FrameImp
::
create
();
_buffer
->
_buffer
.
assign
(
frame
->
data
(),
frame
->
size
());
_ptr
=
_buffer
->
data
();
}
_size
=
frame
->
size
();
...
...
@@ -66,7 +96,7 @@ private:
bool
_key
;
bool
_config
;
Frame
::
Ptr
_frame
;
BufferRaw
::
Ptr
_buffer
;
FrameImp
::
Ptr
_buffer
;
};
Frame
::
Ptr
Frame
::
getCacheAbleFrame
(
const
Frame
::
Ptr
&
frame
){
...
...
This diff is collapsed.
Click to expand it.
src/Extension/Frame.h
查看文件 @
62ba87dd
...
...
@@ -130,7 +130,10 @@ private:
class
FrameImp
:
public
Frame
{
public
:
typedef
std
::
shared_ptr
<
FrameImp
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
FrameImp
>
;
template
<
typename
C
=
FrameImp
>
static
std
::
shared_ptr
<
C
>
create
();
char
*
data
()
const
override
{
return
(
char
*
)
_buffer
.
data
();
...
...
@@ -172,6 +175,13 @@ public:
BufferLikeString
_buffer
;
//对象个数统计
ObjectStatistic
<
FrameImp
>
_statistic
;
protected
:
friend
class
ResourcePool_l
<
FrameImp
>
;
FrameImp
()
=
default
;
template
<
typename
C
>
static
std
::
shared_ptr
<
C
>
create_l
();
};
/**
...
...
@@ -196,26 +206,6 @@ private:
};
/**
* 循环池辅助类
*/
template
<
typename
T
>
class
ResourcePoolHelper
{
public
:
ResourcePoolHelper
(
int
size
=
0
){
if
(
size
>
0
)
{
_pool
.
setSize
(
size
);
}
}
virtual
~
ResourcePoolHelper
(){}
std
::
shared_ptr
<
T
>
obtainObj
(){
return
_pool
.
obtain
();
}
private
:
ResourcePool
<
T
>
_pool
;
};
/**
* 写帧接口的抽象接口类
*/
class
FrameWriterInterface
{
...
...
This diff is collapsed.
Click to expand it.
src/Extension/G711.cpp
查看文件 @
62ba87dd
...
...
@@ -12,6 +12,47 @@
namespace
mediakit
{
/**
* G711类型SDP
*/
class
G711Sdp
:
public
Sdp
{
public
:
/**
* G711采样率固定为8000
* @param codecId G711A G711U
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
G711Sdp
(
CodecId
codecId
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
),
_codecId
(
codecId
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
(
codecId
==
CodecG711A
?
" PCMA/"
:
" PCMU/"
)
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
_codecId
;
}
private
:
_StrPrinter
_printer
;
CodecId
_codecId
;
};
Track
::
Ptr
G711Track
::
clone
()
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
Sdp
::
Ptr
G711Track
::
getSdp
()
{
if
(
!
ready
()){
WarnL
<<
getCodecName
()
<<
" Track未准备好"
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/G711.h
查看文件 @
62ba87dd
...
...
@@ -21,53 +21,12 @@ namespace mediakit{
*/
class
G711Track
:
public
AudioTrackImp
{
public
:
typedef
std
::
shared_ptr
<
G711Track
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
G711Track
>
;
G711Track
(
CodecId
codecId
,
int
sample_rate
,
int
channels
,
int
sample_bit
)
:
AudioTrackImp
(
codecId
,
sample_rate
,
channels
,
sample_bit
){}
private
:
//克隆该Track
Track
::
Ptr
clone
()
override
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
//生成sdp
Sdp
::
Ptr
getSdp
()
override
;
};
/**
* G711类型SDP
*/
class
G711Sdp
:
public
Sdp
{
public
:
/**
* G711采样率固定为8000
* @param codecId G711A G711U
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
G711Sdp
(
CodecId
codecId
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
),
_codecId
(
codecId
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
(
codecId
==
CodecG711A
?
" PCMA/"
:
" PCMU/"
)
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
_codecId
;
}
private
:
_StrPrinter
_printer
;
CodecId
_codecId
;
Sdp
::
Ptr
getSdp
()
override
;
Track
::
Ptr
clone
()
override
;
};
}
//namespace mediakit
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H264.cpp
查看文件 @
62ba87dd
...
...
@@ -96,6 +96,174 @@ size_t prefixSize(const char *ptr, size_t len){
return
0
;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
H264Track
::
H264Track
(
const
string
&
sps
,
const
string
&
pps
,
int
sps_prefix_len
,
int
pps_prefix_len
){
_sps
=
sps
.
substr
(
sps_prefix_len
);
_pps
=
pps
.
substr
(
pps_prefix_len
);
onReady
();
}
H264Track
::
H264Track
(
const
Frame
::
Ptr
&
sps
,
const
Frame
::
Ptr
&
pps
){
if
(
sps
->
getCodecId
()
!=
CodecH264
||
pps
->
getCodecId
()
!=
CodecH264
){
throw
std
::
invalid_argument
(
"必须输入H264类型的帧"
);
}
_sps
=
string
(
sps
->
data
()
+
sps
->
prefixSize
(),
sps
->
size
()
-
sps
->
prefixSize
());
_pps
=
string
(
pps
->
data
()
+
pps
->
prefixSize
(),
pps
->
size
()
-
pps
->
prefixSize
());
onReady
();
}
const
string
&
H264Track
::
getSps
()
const
{
return
_sps
;
}
const
string
&
H264Track
::
getPps
()
const
{
return
_pps
;
}
CodecId
H264Track
::
getCodecId
()
const
{
return
CodecH264
;
}
int
H264Track
::
getVideoHeight
()
const
{
return
_height
;
}
int
H264Track
::
getVideoWidth
()
const
{
return
_width
;
}
float
H264Track
::
getVideoFps
()
const
{
return
_fps
;
}
bool
H264Track
::
ready
()
{
return
!
_sps
.
empty
()
&&
!
_pps
.
empty
();
}
void
H264Track
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
using
H264FrameInternal
=
FrameInternal
<
H264FrameNoCacheAble
>
;
int
type
=
H264_TYPE
(
*
((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
()));
if
(
type
!=
H264Frame
::
NAL_B_P
&&
type
!=
H264Frame
::
NAL_IDR
)
{
//非I/B/P帧情况下,split一下,防止多个帧粘合在一起
splitH264
(
frame
->
data
(),
frame
->
size
(),
frame
->
prefixSize
(),
[
&
](
const
char
*
ptr
,
size_t
len
,
size_t
prefix
)
{
H264FrameInternal
::
Ptr
sub_frame
=
std
::
make_shared
<
H264FrameInternal
>
(
frame
,
(
char
*
)
ptr
,
len
,
prefix
);
inputFrame_l
(
sub_frame
);
});
}
else
{
inputFrame_l
(
frame
);
}
}
void
H264Track
::
onReady
(){
getAVCInfo
(
_sps
,
_width
,
_height
,
_fps
);
}
Track
::
Ptr
H264Track
::
clone
()
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
void
H264Track
::
inputFrame_l
(
const
Frame
::
Ptr
&
frame
){
int
type
=
H264_TYPE
(
*
((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
()));
switch
(
type
)
{
case
H264Frame
:
:
NAL_SPS
:
{
_sps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
}
case
H264Frame
:
:
NAL_PPS
:
{
_pps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
}
case
H264Frame
:
:
NAL_IDR
:
{
insertConfigFrame
(
frame
);
VideoTrack
::
inputFrame
(
frame
);
break
;
}
case
H264Frame
:
:
NAL_AUD
:
{
//忽略AUD帧;
break
;
}
default
:
VideoTrack
::
inputFrame
(
frame
);
break
;
}
_is_idr
=
type
==
H264Frame
::
NAL_IDR
;
if
(
_width
==
0
&&
ready
())
{
onReady
();
}
}
void
H264Track
::
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
){
if
(
_is_idr
){
return
;
}
if
(
!
_sps
.
empty
()){
auto
spsFrame
=
FrameImp
::
create
<
H264Frame
>
();
spsFrame
->
_prefix_size
=
4
;
spsFrame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
spsFrame
->
_buffer
.
append
(
_sps
);
spsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
spsFrame
);
}
if
(
!
_pps
.
empty
()){
auto
ppsFrame
=
FrameImp
::
create
<
H264Frame
>
();
ppsFrame
->
_prefix_size
=
4
;
ppsFrame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
ppsFrame
->
_buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
class
H264Sdp
:
public
Sdp
{
public
:
H264Sdp
(
const
string
&
strSPS
,
const
string
&
strPPS
,
int
bitrate
,
int
payload_type
=
96
)
:
Sdp
(
90000
,
payload_type
)
{
//视频通道
_printer
<<
"m=video 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" H264/"
<<
90000
<<
"
\r\n
"
;
_printer
<<
"a=fmtp:"
<<
payload_type
<<
" packetization-mode=1; profile-level-id="
;
char
strTemp
[
100
];
uint32_t
profile_level_id
=
0
;
if
(
strSPS
.
length
()
>=
4
)
{
// sanity check
profile_level_id
=
(
uint8_t
(
strSPS
[
1
])
<<
16
)
|
(
uint8_t
(
strSPS
[
2
])
<<
8
)
|
(
uint8_t
(
strSPS
[
3
]));
// profile_idc|constraint_setN_flag|level_idc
}
memset
(
strTemp
,
0
,
100
);
snprintf
(
strTemp
,
sizeof
(
strTemp
),
"%06X"
,
profile_level_id
);
_printer
<<
strTemp
;
_printer
<<
"; sprop-parameter-sets="
;
memset
(
strTemp
,
0
,
100
);
av_base64_encode
(
strTemp
,
100
,
(
uint8_t
*
)
strSPS
.
data
(),
(
int
)
strSPS
.
size
());
_printer
<<
strTemp
<<
","
;
memset
(
strTemp
,
0
,
100
);
av_base64_encode
(
strTemp
,
100
,
(
uint8_t
*
)
strPPS
.
data
(),
(
int
)
strPPS
.
size
());
_printer
<<
strTemp
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackVideo
<<
"
\r\n
"
;
}
string
getSdp
()
const
{
return
_printer
;
}
CodecId
getCodecId
()
const
{
return
CodecH264
;
}
private
:
_StrPrinter
_printer
;
};
Sdp
::
Ptr
H264Track
::
getSdp
()
{
if
(
!
ready
()){
WarnL
<<
getCodecName
()
<<
" Track未准备好"
;
...
...
@@ -103,6 +271,48 @@ Sdp::Ptr H264Track::getSdp() {
}
return
std
::
make_shared
<
H264Sdp
>
(
getSps
(),
getPps
(),
getBitRate
()
/
1024
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool
H264Frame
::
keyFrame
()
const
{
return
H264_TYPE
(
_buffer
[
_prefix_size
])
==
H264Frame
::
NAL_IDR
;
}
bool
H264Frame
::
configFrame
()
const
{
switch
(
H264_TYPE
(
_buffer
[
_prefix_size
]))
{
case
H264Frame
:
:
NAL_SPS
:
case
H264Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
H264Frame
::
H264Frame
()
{
_codec_id
=
CodecH264
;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
H264FrameNoCacheAble
::
H264FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
){
_ptr
=
ptr
;
_size
=
size
;
_dts
=
dts
;
_pts
=
pts
;
_prefix_size
=
prefix_size
;
_codec_id
=
CodecH264
;
}
bool
H264FrameNoCacheAble
::
keyFrame
()
const
{
return
H264_TYPE
(
_ptr
[
_prefix_size
])
==
H264Frame
::
NAL_IDR
;
}
bool
H264FrameNoCacheAble
::
configFrame
()
const
{
switch
(
H264_TYPE
(
_ptr
[
_prefix_size
]))
{
case
H264Frame
:
:
NAL_SPS
:
case
H264Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
}
//namespace mediakit
This diff is collapsed.
Click to expand it.
src/Extension/H264.h
查看文件 @
62ba87dd
差异被折叠。
点击展开。
src/Extension/H264Rtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -15,10 +15,8 @@ H264RtmpDecoder::H264RtmpDecoder() {
_h264frame
=
obtainFrame
();
}
H264Frame
::
Ptr
H264RtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
obtainObj
();
frame
->
_buffer
.
clear
();
H264Frame
::
Ptr
H264RtmpDecoder
::
obtainFrame
()
{
auto
frame
=
FrameImp
::
create
<
H264Frame
>
();
frame
->
_prefix_size
=
4
;
return
frame
;
}
...
...
@@ -124,7 +122,7 @@ inline void H264RtmpDecoder::onGetH264(const char* pcData, size_t iLen, uint32_t
#if 1
_h264frame
->
_dts
=
dts
;
_h264frame
->
_pts
=
pts
;
_h264frame
->
_buffer
.
assign
(
"\x0
\x0\x0\x
1"
,
4
);
//添加264头
_h264frame
->
_buffer
.
assign
(
"
\x0
0\x00\x00\x0
1
"
,
4
);
//添加264头
_h264frame
->
_buffer
.
append
(
pcData
,
iLen
);
//写入环形缓存
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H264Rtmp.h
查看文件 @
62ba87dd
...
...
@@ -22,7 +22,7 @@ namespace mediakit{
* h264 Rtmp解码类
* 将 h264 over rtmp 解复用出 h264-Frame
*/
class
H264RtmpDecoder
:
public
RtmpCodec
,
public
ResourcePoolHelper
<
H264Frame
>
{
class
H264RtmpDecoder
:
public
RtmpCodec
{
public
:
typedef
std
::
shared_ptr
<
H264RtmpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H264Rtp.cpp
查看文件 @
62ba87dd
...
...
@@ -34,10 +34,8 @@ H264RtpDecoder::H264RtpDecoder() {
_h264frame
=
obtainFrame
();
}
H264Frame
::
Ptr
H264RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H264Frame
>::
obtainObj
();
frame
->
_buffer
.
clear
();
H264Frame
::
Ptr
H264RtpDecoder
::
obtainFrame
()
{
auto
frame
=
FrameImp
::
create
<
H264Frame
>
();
frame
->
_prefix_size
=
4
;
return
frame
;
}
...
...
@@ -81,7 +79,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtp) {
if
(
nal_type
>=
0
&&
nal_type
<
24
)
{
//a full frame
_h264frame
->
_buffer
.
assign
(
"\x0
\x0\x0\x
1"
,
4
);
_h264frame
->
_buffer
.
assign
(
"
\x0
0\x00\x00\x0
1
"
,
4
);
_h264frame
->
_buffer
.
append
((
char
*
)
frame
,
length
);
_h264frame
->
_pts
=
stamp
;
auto
key
=
_h264frame
->
keyFrame
();
...
...
@@ -108,7 +106,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtp) {
}
if
(
len
>
0
)
{
//有有效数据
_h264frame
->
_buffer
.
assign
(
"\x0
\x0\x0\x
1"
,
4
);
_h264frame
->
_buffer
.
assign
(
"
\x0
0\x00\x00\x0
1
"
,
4
);
_h264frame
->
_buffer
.
append
((
char
*
)
ptr
,
len
);
_h264frame
->
_pts
=
stamp
;
if
((
ptr
[
0
]
&
0x1F
)
==
H264Frame
::
NAL_IDR
)
{
...
...
@@ -127,7 +125,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtp) {
MakeFU
(
frame
[
1
],
fu
);
if
(
fu
.
S
)
{
//该帧的第一个rtp包 FU-A start
_h264frame
->
_buffer
.
assign
(
"\x0
\x0\x0\x
1"
,
4
);
_h264frame
->
_buffer
.
assign
(
"
\x0
0\x00\x00\x0
1
"
,
4
);
_h264frame
->
_buffer
.
push_back
(
nal_suffix
|
fu
.
type
);
_h264frame
->
_buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
_pts
=
stamp
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H264Rtp.h
查看文件 @
62ba87dd
...
...
@@ -24,7 +24,7 @@ namespace mediakit{
* 将 h264 over rtsp-rtp 解复用出 h264-Frame
* rfc3984
*/
class
H264RtpDecoder
:
public
RtpCodec
,
public
ResourcePoolHelper
<
H264Frame
>
{
class
H264RtpDecoder
:
public
RtpCodec
{
public
:
typedef
std
::
shared_ptr
<
H264RtpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H265.cpp
查看文件 @
62ba87dd
...
...
@@ -10,7 +10,6 @@
#include "H265.h"
#include "SPSParser.h"
#include "Util/logger.h"
namespace
mediakit
{
...
...
@@ -42,7 +41,6 @@ bool getHEVCInfo(const char * vps, size_t vps_len,const char * sps,size_t sps_le
h265GetWidthHeight
(
&
tH265SpsInfo
,
&
iVideoWidth
,
&
iVideoHeight
);
iVideoFps
=
0
;
h265GeFramerate
(
&
tH265VpsInfo
,
&
tH265SpsInfo
,
&
iVideoFps
);
// ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
return
true
;
}
...
...
@@ -50,6 +48,228 @@ bool getHEVCInfo(const string &strVps, const string &strSps, int &iVideoWidth, i
return
getHEVCInfo
(
strVps
.
data
(),
strVps
.
size
(),
strSps
.
data
(),
strSps
.
size
(),
iVideoWidth
,
iVideoHeight
,
iVideoFps
);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool
H265Frame
::
keyFrame
()
const
{
return
isKeyFrame
(
H265_TYPE
(
_buffer
[
_prefix_size
]));
}
bool
H265Frame
::
configFrame
()
const
{
switch
(
H265_TYPE
(
_buffer
[
_prefix_size
]))
{
case
H265Frame
:
:
NAL_VPS
:
case
H265Frame
:
:
NAL_SPS
:
case
H265Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
bool
H265Frame
::
isKeyFrame
(
int
type
)
{
return
type
>=
NAL_BLA_W_LP
&&
type
<=
NAL_RSV_IRAP_VCL23
;
}
H265Frame
::
H265Frame
(){
_codec_id
=
CodecH265
;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
H265FrameNoCacheAble
::
H265FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
)
{
_ptr
=
ptr
;
_size
=
size
;
_dts
=
dts
;
_pts
=
pts
;
_prefix_size
=
prefix_size
;
_codec_id
=
CodecH265
;
}
bool
H265FrameNoCacheAble
::
keyFrame
()
const
{
return
H265Frame
::
isKeyFrame
(
H265_TYPE
(((
uint8_t
*
)
_ptr
)[
_prefix_size
]));
}
bool
H265FrameNoCacheAble
::
configFrame
()
const
{
switch
(
H265_TYPE
(((
uint8_t
*
)
_ptr
)[
_prefix_size
]))
{
case
H265Frame
:
:
NAL_VPS
:
case
H265Frame
:
:
NAL_SPS
:
case
H265Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
H265Track
::
H265Track
(
const
string
&
vps
,
const
string
&
sps
,
const
string
&
pps
,
int
vps_prefix_len
,
int
sps_prefix_len
,
int
pps_prefix_len
)
{
_vps
=
vps
.
substr
(
vps_prefix_len
);
_sps
=
sps
.
substr
(
sps_prefix_len
);
_pps
=
pps
.
substr
(
pps_prefix_len
);
onReady
();
}
const
string
&
H265Track
::
getVps
()
const
{
return
_vps
;
}
const
string
&
H265Track
::
getSps
()
const
{
return
_sps
;
}
const
string
&
H265Track
::
getPps
()
const
{
return
_pps
;
}
CodecId
H265Track
::
getCodecId
()
const
{
return
CodecH265
;
}
int
H265Track
::
getVideoHeight
()
const
{
return
_height
;
}
int
H265Track
::
getVideoWidth
()
const
{
return
_width
;
}
float
H265Track
::
getVideoFps
()
const
{
return
_fps
;
}
bool
H265Track
::
ready
()
{
return
!
_vps
.
empty
()
&&
!
_sps
.
empty
()
&&
!
_pps
.
empty
();
}
void
H265Track
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
using
H265FrameInternal
=
FrameInternal
<
H265FrameNoCacheAble
>
;
int
type
=
H265_TYPE
(
*
((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
()));
if
(
frame
->
configFrame
()
||
type
==
H265Frame
::
NAL_SEI_PREFIX
)
{
splitH264
(
frame
->
data
(),
frame
->
size
(),
frame
->
prefixSize
(),
[
&
](
const
char
*
ptr
,
size_t
len
,
size_t
prefix
)
{
H265FrameInternal
::
Ptr
sub_frame
=
std
::
make_shared
<
H265FrameInternal
>
(
frame
,
(
char
*
)
ptr
,
len
,
prefix
);
inputFrame_l
(
sub_frame
);
});
}
else
{
inputFrame_l
(
frame
);
}
}
void
H265Track
::
inputFrame_l
(
const
Frame
::
Ptr
&
frame
)
{
int
type
=
H265_TYPE
(((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
())[
0
]);
if
(
H265Frame
::
isKeyFrame
(
type
))
{
insertConfigFrame
(
frame
);
VideoTrack
::
inputFrame
(
frame
);
_is_idr
=
true
;
return
;
}
_is_idr
=
false
;
//非idr帧
switch
(
type
)
{
case
H265Frame
:
:
NAL_VPS
:
{
_vps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
}
case
H265Frame
:
:
NAL_SPS
:
{
_sps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
}
case
H265Frame
:
:
NAL_PPS
:
{
_pps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
}
default
:
{
VideoTrack
::
inputFrame
(
frame
);
break
;
}
}
if
(
_width
==
0
&&
ready
())
{
onReady
();
}
}
void
H265Track
::
onReady
()
{
getHEVCInfo
(
_vps
,
_sps
,
_width
,
_height
,
_fps
);
}
Track
::
Ptr
H265Track
::
clone
()
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
void
H265Track
::
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
)
{
if
(
_is_idr
)
{
return
;
}
if
(
!
_vps
.
empty
())
{
auto
vpsFrame
=
FrameImp
::
create
<
H265Frame
>
();
vpsFrame
->
_prefix_size
=
4
;
vpsFrame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
vpsFrame
->
_buffer
.
append
(
_vps
);
vpsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
vpsFrame
);
}
if
(
!
_sps
.
empty
())
{
auto
spsFrame
=
FrameImp
::
create
<
H265Frame
>
();
spsFrame
->
_prefix_size
=
4
;
spsFrame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
spsFrame
->
_buffer
.
append
(
_sps
);
spsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
spsFrame
);
}
if
(
!
_pps
.
empty
())
{
auto
ppsFrame
=
FrameImp
::
create
<
H265Frame
>
();
ppsFrame
->
_prefix_size
=
4
;
ppsFrame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
ppsFrame
->
_buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* h265类型sdp
*/
class
H265Sdp
:
public
Sdp
{
public
:
/**
* 构造函数
* @param sps 265 sps,不带0x00000001头
* @param pps 265 pps,不带0x00000001头
* @param payload_type rtp payload type 默认96
* @param bitrate 比特率
*/
H265Sdp
(
const
string
&
strVPS
,
const
string
&
strSPS
,
const
string
&
strPPS
,
int
bitrate
=
4000
,
int
payload_type
=
96
)
:
Sdp
(
90000
,
payload_type
)
{
//视频通道
_printer
<<
"m=video 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" H265/"
<<
90000
<<
"
\r\n
"
;
_printer
<<
"a=fmtp:"
<<
payload_type
<<
" "
;
_printer
<<
"sprop-vps="
;
_printer
<<
encodeBase64
(
strVPS
)
<<
"; "
;
_printer
<<
"sprop-sps="
;
_printer
<<
encodeBase64
(
strSPS
)
<<
"; "
;
_printer
<<
"sprop-pps="
;
_printer
<<
encodeBase64
(
strPPS
)
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackVideo
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecH265
;
}
private
:
_StrPrinter
_printer
;
};
Sdp
::
Ptr
H265Track
::
getSdp
()
{
if
(
!
ready
()){
WarnL
<<
getCodecName
()
<<
" Track未准备好"
;
...
...
@@ -57,5 +277,6 @@ Sdp::Ptr H265Track::getSdp() {
}
return
std
::
make_shared
<
H265Sdp
>
(
getVps
(),
getSps
(),
getPps
(),
getBitRate
()
/
1024
);
}
}
//namespace mediakit
This diff is collapsed.
Click to expand it.
src/Extension/H265.h
查看文件 @
62ba87dd
差异被折叠。
点击展开。
src/Extension/H265Rtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -19,10 +19,8 @@ H265RtmpDecoder::H265RtmpDecoder() {
_h265frame
=
obtainFrame
();
}
H265Frame
::
Ptr
H265RtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
obtainObj
();
frame
->
_buffer
.
clear
();
H265Frame
::
Ptr
H265RtmpDecoder
::
obtainFrame
()
{
auto
frame
=
FrameImp
::
create
<
H265Frame
>
();
frame
->
_prefix_size
=
4
;
return
frame
;
}
...
...
@@ -102,7 +100,7 @@ inline void H265RtmpDecoder::onGetH265(const char* pcData, size_t iLen, uint32_t
#if 1
_h265frame
->
_dts
=
dts
;
_h265frame
->
_pts
=
pts
;
_h265frame
->
_buffer
.
assign
(
"\x0
\x0\x0\x
1"
,
4
);
//添加265头
_h265frame
->
_buffer
.
assign
(
"
\x0
0\x00\x00\x0
1
"
,
4
);
//添加265头
_h265frame
->
_buffer
.
append
(
pcData
,
iLen
);
//写入环形缓存
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H265Rtmp.h
查看文件 @
62ba87dd
...
...
@@ -22,7 +22,7 @@ namespace mediakit{
* h265 Rtmp解码类
* 将 h265 over rtmp 解复用出 h265-Frame
*/
class
H265RtmpDecoder
:
public
RtmpCodec
,
public
ResourcePoolHelper
<
H265Frame
>
{
class
H265RtmpDecoder
:
public
RtmpCodec
{
public
:
typedef
std
::
shared_ptr
<
H265RtmpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H265Rtp.cpp
查看文件 @
62ba87dd
...
...
@@ -29,10 +29,8 @@ H265RtpDecoder::H265RtpDecoder() {
_frame
=
obtainFrame
();
}
H265Frame
::
Ptr
H265RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H265Frame
>::
obtainObj
();
frame
->
_buffer
.
clear
();
H265Frame
::
Ptr
H265RtpDecoder
::
obtainFrame
()
{
auto
frame
=
FrameImp
::
create
<
H265Frame
>
();
frame
->
_prefix_size
=
4
;
return
frame
;
}
...
...
This diff is collapsed.
Click to expand it.
src/Extension/H265Rtp.h
查看文件 @
62ba87dd
...
...
@@ -25,7 +25,7 @@ namespace mediakit{
* 将 h265 over rtsp-rtp 解复用出 h265-Frame
* 《草案(H265-over-RTP)draft-ietf-payload-rtp-h265-07.pdf》
*/
class
H265RtpDecoder
:
public
RtpCodec
,
public
ResourcePoolHelper
<
H265Frame
>
{
class
H265RtpDecoder
:
public
RtpCodec
{
public
:
typedef
std
::
shared_ptr
<
H265RtpDecoder
>
Ptr
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/L16.cpp
查看文件 @
62ba87dd
...
...
@@ -12,6 +12,43 @@
namespace
mediakit
{
/**
* L16类型SDP
*/
class
L16Sdp
:
public
Sdp
{
public
:
/**
* L16采样位数固定为16位
* @param codecId CodecL16
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
L16Sdp
(
CodecId
codecId
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
),
_codecId
(
codecId
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" L16/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
_codecId
;
}
private
:
_StrPrinter
_printer
;
CodecId
_codecId
;
};
Sdp
::
Ptr
L16Track
::
getSdp
()
{
WarnL
<<
"Enter L16Track::getSdp function"
;
if
(
!
ready
()){
...
...
@@ -21,6 +58,10 @@ Sdp::Ptr L16Track::getSdp() {
return
std
::
make_shared
<
L16Sdp
>
(
getCodecId
(),
getAudioSampleRate
(),
getAudioChannel
(),
getBitRate
()
/
1024
);
}
Track
::
Ptr
L16Track
::
clone
()
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
}
//namespace mediakit
This diff is collapsed.
Click to expand it.
src/Extension/L16.h
查看文件 @
62ba87dd
...
...
@@ -21,53 +21,12 @@ namespace mediakit{
*/
class
L16Track
:
public
AudioTrackImp
{
public
:
typedef
std
::
shared_ptr
<
L16Track
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
L16Track
>
;
L16Track
(
int
sample_rate
,
int
channels
)
:
AudioTrackImp
(
CodecL16
,
sample_rate
,
channels
,
16
){}
private
:
//克隆该Track
Track
::
Ptr
clone
()
override
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
//生成sdp
Sdp
::
Ptr
getSdp
()
override
;
};
/**
* L16类型SDP
*/
class
L16Sdp
:
public
Sdp
{
public
:
/**
* L16采样位数固定为16位
* @param codecId CodecL16
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
L16Sdp
(
CodecId
codecId
,
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
),
_codecId
(
codecId
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" L16/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
_codecId
;
}
private
:
_StrPrinter
_printer
;
CodecId
_codecId
;
Sdp
::
Ptr
getSdp
()
override
;
Track
::
Ptr
clone
()
override
;
};
}
//namespace mediakit
...
...
This diff is collapsed.
Click to expand it.
src/Extension/Opus.cpp
查看文件 @
62ba87dd
...
...
@@ -12,6 +12,40 @@
namespace
mediakit
{
/**
* Opus类型SDP
*/
class
OpusSdp
:
public
Sdp
{
public
:
/**
* 构造opus sdp
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
OpusSdp
(
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" opus/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecOpus
;
}
private
:
_StrPrinter
_printer
;
};
Sdp
::
Ptr
OpusTrack
::
getSdp
()
{
if
(
!
ready
()){
WarnL
<<
getCodecName
()
<<
" Track未准备好"
;
...
...
This diff is collapsed.
Click to expand it.
src/Extension/Opus.h
查看文件 @
62ba87dd
...
...
@@ -33,39 +33,5 @@ private:
Sdp
::
Ptr
getSdp
()
override
;
};
/**
* Opus类型SDP
*/
class
OpusSdp
:
public
Sdp
{
public
:
/**
* 构造opus sdp
* @param sample_rate 音频采样率
* @param payload_type rtp payload
* @param bitrate 比特率
*/
OpusSdp
(
int
sample_rate
,
int
channels
,
int
bitrate
=
128
,
int
payload_type
=
98
)
:
Sdp
(
sample_rate
,
payload_type
){
_printer
<<
"m=audio 0 RTP/AVP "
<<
payload_type
<<
"
\r\n
"
;
if
(
bitrate
)
{
_printer
<<
"b=AS:"
<<
bitrate
<<
"
\r\n
"
;
}
_printer
<<
"a=rtpmap:"
<<
payload_type
<<
" opus/"
<<
sample_rate
<<
"/"
<<
channels
<<
"
\r\n
"
;
_printer
<<
"a=control:trackID="
<<
(
int
)
TrackAudio
<<
"
\r\n
"
;
}
string
getSdp
()
const
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecOpus
;
}
private
:
_StrPrinter
_printer
;
};
}
//namespace mediakit
#endif //ZLMEDIAKIT_OPUS_H
This diff is collapsed.
Click to expand it.
src/Record/MP4Demuxer.cpp
查看文件 @
62ba87dd
...
...
@@ -221,7 +221,7 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6
if
(
frame_len
+
offset
+
4
>
bytes
)
{
return
nullptr
;
}
memcpy
(
data
+
offset
,
"\x0
\x0\x0\x
1"
,
4
);
memcpy
(
data
+
offset
,
"
\x0
0\x00\x00\x0
1
"
,
4
);
offset
+=
(
frame_len
+
4
);
}
if
(
codec
==
CodecH264
)
{
...
...
This diff is collapsed.
Click to expand it.
src/Rtmp/Rtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -142,9 +142,7 @@ RtmpPacket::Ptr RtmpPacket::create(){
ret->clear();
return ret;
#else
auto
ret
=
Ptr
(
new
RtmpPacket
);
ret
->
clear
();
return
ret
;
return
Ptr
(
new
RtmpPacket
);
#endif
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论