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
Feb 05, 2021
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
);
...
...
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未准备好"
;
...
...
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
...
...
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头
...
...
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
;
...
...
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
;
}
...
...
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
;
...
...
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
)
{
...
...
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
;
...
...
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
;
}
...
...
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
;
...
...
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
){
...
...
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
{
...
...
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未准备好"
;
...
...
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
...
...
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
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
);
//写入环形缓存
...
...
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
;
...
...
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
;
...
...
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
;
...
...
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
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
);
//写入环形缓存
...
...
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
;
...
...
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
;
}
...
...
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
;
...
...
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
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
...
...
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未准备好"
;
...
...
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
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
)
{
...
...
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
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论