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 个修改的文件
包含
843 行增加
和
851 行删除
+843
-851
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
+37
-250
src/Extension/H264Rtmp.cpp
+2
-4
src/Extension/H264Rtmp.h
+1
-1
src/Extension/H264Rtp.cpp
+4
-6
src/Extension/H264Rtp.h
+1
-1
src/Extension/H265.cpp
+223
-2
src/Extension/H265.h
+37
-254
src/Extension/H265Rtmp.cpp
+2
-4
src/Extension/H265Rtmp.h
+1
-1
src/Extension/H265Rtp.cpp
+1
-3
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
...
...
@@ -14,45 +14,38 @@
#include "Frame.h"
#include "Track.h"
#include "Util/base64.h"
using
namespace
toolkit
;
#define H264_TYPE(v) ((uint8_t)(v) & 0x1F)
using
namespace
toolkit
;
namespace
mediakit
{
bool
getAVCInfo
(
const
string
&
strSps
,
int
&
iVideoWidth
,
int
&
iVideoHeight
,
float
&
iVideoFps
);
void
splitH264
(
const
char
*
ptr
,
size_t
len
,
size_t
prefix
,
const
std
::
function
<
void
(
const
char
*
,
size_t
,
size_t
)
>
&
cb
);
size_t
prefixSize
(
const
char
*
ptr
,
size_t
len
);
/**
* 264帧类
*/
class
H264Frame
:
public
FrameImp
{
public
:
typedef
std
::
shared_ptr
<
H264Frame
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
H264Frame
>
;
typedef
enum
{
enum
{
NAL_IDR
=
5
,
NAL_SEI
=
6
,
NAL_SPS
=
7
,
NAL_PPS
=
8
,
NAL_AUD
=
9
,
NAL_B_P
=
1
,
}
NalType
;
H264Frame
(){
_codec_id
=
CodecH264
;
}
};
bool
keyFrame
()
const
override
{
return
H264_TYPE
(
_buffer
[
_prefix_size
])
==
H264Frame
::
NAL_IDR
;
}
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
bool
configFrame
()
const
override
{
switch
(
H264_TYPE
(
_buffer
[
_prefix_size
])
){
case
H264Frame
:
:
NAL_SPS
:
case
H264Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
protected
:
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H264Frame
>
;
H264Frame
();
};
/**
...
...
@@ -62,44 +55,26 @@ public:
*/
class
H264FrameNoCacheAble
:
public
FrameFromPtr
{
public
:
typedef
std
::
shared_ptr
<
H264FrameNoCacheAble
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
H264FrameNoCacheAble
>
;
H264FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
=
4
){
_ptr
=
ptr
;
_size
=
size
;
_dts
=
dts
;
_pts
=
pts
;
_prefix_size
=
prefix_size
;
_codec_id
=
CodecH264
;
}
bool
keyFrame
()
const
override
{
return
H264_TYPE
(
_ptr
[
_prefix_size
])
==
H264Frame
::
NAL_IDR
;
}
bool
configFrame
()
const
override
{
switch
(
H264_TYPE
(
_ptr
[
_prefix_size
])){
case
H264Frame
:
:
NAL_SPS
:
case
H264Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
H264FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
=
4
);
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
};
typedef
FrameInternal
<
H264FrameNoCacheAble
>
H264FrameInternal
;
/**
* 264视频通道
*/
class
H264Track
:
public
VideoTrack
{
public
:
typedef
std
::
shared_ptr
<
H264Track
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
H264Track
>
;
/**
* 不指定sps pps构造h264类型的媒体
* 在随后的inputFrame中获取sps pps
*/
H264Track
(){}
H264Track
()
=
default
;
/**
* 构造h264类型的媒体
* @param sps sps帧数据
...
...
@@ -107,230 +82,42 @@ public:
* @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
* @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
*/
H264Track
(
const
string
&
sps
,
const
string
&
pps
,
int
sps_prefix_len
=
4
,
int
pps_prefix_len
=
4
){
_sps
=
sps
.
substr
(
sps_prefix_len
);
_pps
=
pps
.
substr
(
pps_prefix_len
);
onReady
();
}
H264Track
(
const
string
&
sps
,
const
string
&
pps
,
int
sps_prefix_len
=
4
,
int
pps_prefix_len
=
4
);
/**
* 构造h264类型的媒体
* @param sps sps帧
* @param pps pps帧
*/
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
();
}
/**
* 返回不带0x00 00 00 01头的sps
* @return
*/
const
string
&
getSps
()
const
{
return
_sps
;
}
H264Track
(
const
Frame
::
Ptr
&
sps
,
const
Frame
::
Ptr
&
pps
);
/**
* 返回不带0x00 00 00 01头的pps
* @return
* 返回不带0x00 00 00 01头的sps/pps
*/
const
string
&
getPps
()
const
{
return
_pps
;
}
const
string
&
getSps
()
const
;
const
string
&
getPps
()
const
;
CodecId
getCodecId
()
const
override
{
return
CodecH264
;
}
bool
ready
()
override
;
CodecId
getCodecId
()
const
override
;
int
getVideoHeight
()
const
override
;
int
getVideoWidth
()
const
override
;
float
getVideoFps
()
const
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
/**
* 返回视频高度
* @return
*/
int
getVideoHeight
()
const
override
{
return
_height
;
}
/**
* 返回视频宽度
* @return
*/
int
getVideoWidth
()
const
override
{
return
_width
;
}
/**
* 返回视频fps
* @return
*/
float
getVideoFps
()
const
override
{
return
_fps
;
}
bool
ready
()
override
{
return
!
_sps
.
empty
()
&&
!
_pps
.
empty
();
}
/**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
{
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
);
}
}
private
:
/**
* 解析sps获取宽高fps
*/
void
onReady
(){
getAVCInfo
(
_sps
,
_width
,
_height
,
_fps
);
}
Track
::
Ptr
clone
()
override
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
void
onReady
();
Sdp
::
Ptr
getSdp
()
override
;
Track
::
Ptr
clone
()
override
;
void
inputFrame_l
(
const
Frame
::
Ptr
&
frame
);
void
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
);
/**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
*/
void
inputFrame_l
(
const
Frame
::
Ptr
&
frame
){
int
type
=
H264_TYPE
(
*
((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
()));
switch
(
type
){
case
H264Frame
:
:
NAL_SPS
:
{
//sps
_sps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
case
H264Frame
:
:
NAL_PPS
:
{
//pps
_pps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
case
H264Frame
:
:
NAL_IDR
:
{
//I
insertConfigFrame
(
frame
);
VideoTrack
::
inputFrame
(
frame
);
}
break
;
case
H264Frame
:
:
NAL_AUD
:
{
//忽略AUD帧;
}
break
;
default
:
VideoTrack
::
inputFrame
(
frame
);
break
;
}
_last_frame_is_idr
=
type
==
H264Frame
::
NAL_IDR
;
if
(
_width
==
0
&&
ready
()){
onReady
();
}
}
//生成sdp
Sdp
::
Ptr
getSdp
()
override
;
private
:
//在idr帧前插入sps pps帧
void
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
){
if
(
_last_frame_is_idr
){
return
;
}
if
(
!
_sps
.
empty
()){
auto
spsFrame
=
std
::
make_shared
<
H264Frame
>
();
spsFrame
->
_prefix_size
=
4
;
spsFrame
->
_buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
spsFrame
->
_buffer
.
append
(
_sps
);
spsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
spsFrame
);
}
if
(
!
_pps
.
empty
()){
auto
ppsFrame
=
std
::
make_shared
<
H264Frame
>
();
ppsFrame
->
_prefix_size
=
4
;
ppsFrame
->
_buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
_buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
private
:
string
_sps
;
string
_pps
;
bool
_is_idr
=
false
;
int
_width
=
0
;
int
_height
=
0
;
float
_fps
=
0
;
bool
_last_frame_is_idr
=
false
;
};
/**
* h264类型sdp
*/
class
H264Sdp
:
public
Sdp
{
public
:
/**
*
* @param sps 264 sps,不带0x00000001头
* @param pps 264 pps,不带0x00000001头
* @param payload_type rtp payload type 默认96
* @param bitrate 比特率
*/
H264Sdp
(
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
<<
" 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
override
{
return
_printer
;
}
CodecId
getCodecId
()
const
override
{
return
CodecH264
;
}
private
:
_StrPrinter
_printer
;
string
_sps
;
string
_pps
;
};
}
//namespace mediakit
...
...
src/Extension/H264Rtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -16,9 +16,7 @@ H264RtmpDecoder::H264RtmpDecoder() {
}
H264Frame
::
Ptr
H264RtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
obtainObj
();
frame
->
_buffer
.
clear
();
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
...
...
@@ -35,9 +35,7 @@ H264RtpDecoder::H264RtpDecoder() {
}
H264Frame
::
Ptr
H264RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H264Frame
>::
obtainObj
();
frame
->
_buffer
.
clear
();
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
...
...
@@ -15,8 +15,8 @@
#include "Track.h"
#include "Util/base64.h"
#include "H264.h"
using
namespace
toolkit
;
#define H265_TYPE(v) (((uint8_t)(v) >> 1) & 0x3f)
using
namespace
toolkit
;
namespace
mediakit
{
...
...
@@ -27,9 +27,8 @@ bool getHEVCInfo(const string &strVps, const string &strSps, int &iVideoWidth, i
*/
class
H265Frame
:
public
FrameImp
{
public
:
typedef
std
::
shared_ptr
<
H265Frame
>
Ptr
;
typedef
enum
{
using
Ptr
=
std
::
shared_ptr
<
H265Frame
>
;
enum
{
NAL_TRAIL_N
=
0
,
NAL_TRAIL_R
=
1
,
NAL_TSA_N
=
2
,
...
...
@@ -58,71 +57,39 @@ public:
NAL_FD_NUT
=
38
,
NAL_SEI_PREFIX
=
39
,
NAL_SEI_SUFFIX
=
40
,
}
NaleType
;
H265Frame
(){
_codec_id
=
CodecH265
;
}
};
bool
keyFrame
()
const
override
{
return
isKeyFrame
(
H265_TYPE
(
_buffer
[
_prefix_size
]))
;
}
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
static
bool
isKeyFrame
(
int
type
);
bool
configFrame
()
const
override
{
switch
(
H265_TYPE
(
_buffer
[
_prefix_size
])){
case
H265Frame
:
:
NAL_VPS
:
case
H265Frame
:
:
NAL_SPS
:
case
H265Frame
:
:
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
static
bool
isKeyFrame
(
int
type
)
{
return
type
>=
NAL_BLA_W_LP
&&
type
<=
NAL_RSV_IRAP_VCL23
;
}
protected
:
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H265Frame
>
;
H265Frame
();
};
class
H265FrameNoCacheAble
:
public
FrameFromPtr
{
public
:
typedef
std
::
shared_ptr
<
H265FrameNoCacheAble
>
Ptr
;
H265FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
=
4
)
{
_ptr
=
ptr
;
_size
=
size
;
_dts
=
dts
;
_pts
=
pts
;
_prefix_size
=
prefix_size
;
_codec_id
=
CodecH265
;
}
bool
keyFrame
()
const
override
{
return
H265Frame
::
isKeyFrame
(
H265_TYPE
(((
uint8_t
*
)
_ptr
)[
_prefix_size
]));
}
using
Ptr
=
std
::
shared_ptr
<
H265FrameNoCacheAble
>
;
bool
configFrame
()
const
override
{
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
;
}
}
H265FrameNoCacheAble
(
char
*
ptr
,
size_t
size
,
uint32_t
dts
,
uint32_t
pts
,
size_t
prefix_size
=
4
);
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
};
typedef
FrameInternal
<
H265FrameNoCacheAble
>
H265FrameInternal
;
/**
* 265视频通道
*/
class
H265Track
:
public
VideoTrack
{
public
:
typedef
std
::
shared_ptr
<
H265Track
>
Ptr
;
using
Ptr
=
std
::
shared_ptr
<
H265Track
>
;
/**
* 不指定sps pps构造h265类型的媒体
* 在随后的inputFrame中获取sps pps
*/
H265Track
()
{}
H265Track
()
=
default
;
/**
* 构造h265类型的媒体
...
...
@@ -133,221 +100,37 @@ public:
* @param sps_prefix_len 265头长度,可以为3个或4个字节,一般为0x00 00 00 01
* @param pps_prefix_len 265头长度,可以为3个或4个字节,一般为0x00 00 00 01
*/
H265Track
(
const
string
&
vps
,
const
string
&
sps
,
const
string
&
pps
,
int
vps_prefix_len
=
4
,
int
sps_prefix_len
=
4
,
int
pps_prefix_len
=
4
)
{
_vps
=
vps
.
substr
(
vps_prefix_len
);
_sps
=
sps
.
substr
(
sps_prefix_len
);
_pps
=
pps
.
substr
(
pps_prefix_len
);
onReady
();
}
/**
* 返回不带0x00 00 00 01头的vps
*/
const
string
&
getVps
()
const
{
return
_vps
;
}
/**
* 返回不带0x00 00 00 01头的sps
*/
const
string
&
getSps
()
const
{
return
_sps
;
}
H265Track
(
const
string
&
vps
,
const
string
&
sps
,
const
string
&
pps
,
int
vps_prefix_len
=
4
,
int
sps_prefix_len
=
4
,
int
pps_prefix_len
=
4
);
/**
* 返回不带0x00 00 00 01头的pps
* 返回不带0x00 00 00 01头的
vps/sps/
pps
*/
const
string
&
get
Pps
()
const
{
return
_pps
;
}
const
string
&
get
Vps
()
const
;
const
string
&
getSps
()
const
;
const
string
&
getPps
()
const
;
CodecId
getCodecId
()
const
override
{
return
CodecH265
;
}
/**
* 返回视频高度
*/
int
getVideoHeight
()
const
override
{
return
_height
;
}
/**
* 返回视频宽度
*/
int
getVideoWidth
()
const
override
{
return
_width
;
}
/**
* 返回视频fps
*/
float
getVideoFps
()
const
override
{
return
_fps
;
}
bool
ready
()
override
{
return
!
_vps
.
empty
()
&&
!
_sps
.
empty
()
&&
!
_pps
.
empty
();
}
/**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
{
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
);
}
}
bool
ready
()
override
;
CodecId
getCodecId
()
const
override
;
int
getVideoWidth
()
const
override
;
int
getVideoHeight
()
const
override
;
float
getVideoFps
()
const
override
;
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
private
:
/**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
*/
void
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
);
_last_frame_is_idr
=
true
;
return
;
}
_last_frame_is_idr
=
false
;
//非idr帧
switch
(
type
)
{
case
H265Frame
:
:
NAL_VPS
:
{
//vps
_vps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
case
H265Frame
:
:
NAL_SPS
:
{
//sps
_sps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
case
H265Frame
:
:
NAL_PPS
:
{
//pps
_pps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
default
:
{
//other frames
VideoTrack
::
inputFrame
(
frame
);
}
break
;
}
if
(
_width
==
0
&&
ready
())
{
onReady
();
}
}
/**
* 解析sps获取宽高fps
*/
void
onReady
(){
getHEVCInfo
(
_vps
,
_sps
,
_width
,
_height
,
_fps
);
}
Track
::
Ptr
clone
()
override
{
return
std
::
make_shared
<
std
::
remove_reference
<
decltype
(
*
this
)
>::
type
>
(
*
this
);
}
//生成sdp
Sdp
::
Ptr
getSdp
()
override
;
//在idr帧前插入vps sps pps帧
void
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
){
if
(
_last_frame_is_idr
){
return
;
}
if
(
!
_vps
.
empty
()){
auto
vpsFrame
=
std
::
make_shared
<
H265Frame
>
();
vpsFrame
->
_prefix_size
=
4
;
vpsFrame
->
_buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
vpsFrame
->
_buffer
.
append
(
_vps
);
vpsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
vpsFrame
);
}
if
(
!
_sps
.
empty
())
{
auto
spsFrame
=
std
::
make_shared
<
H265Frame
>
();
spsFrame
->
_prefix_size
=
4
;
spsFrame
->
_buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
spsFrame
->
_buffer
.
append
(
_sps
);
spsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
spsFrame
);
}
void
onReady
();
Sdp
::
Ptr
getSdp
()
override
;
Track
::
Ptr
clone
()
override
;
void
inputFrame_l
(
const
Frame
::
Ptr
&
frame
);
void
insertConfigFrame
(
const
Frame
::
Ptr
&
frame
);
if
(
!
_pps
.
empty
())
{
auto
ppsFrame
=
std
::
make_shared
<
H265Frame
>
();
ppsFrame
->
_prefix_size
=
4
;
ppsFrame
->
_buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
_buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
private
:
string
_vps
;
string
_sps
;
string
_pps
;
bool
_is_idr
=
false
;
int
_width
=
0
;
int
_height
=
0
;
float
_fps
=
0
;
bool
_last_frame_is_idr
=
false
;
};
/**
* 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
;
string
_vps
;
string
_sps
;
string
_pps
;
};
}
//namespace mediakit
...
...
src/Extension/H265Rtmp.cpp
查看文件 @
62ba87dd
...
...
@@ -20,9 +20,7 @@ H265RtmpDecoder::H265RtmpDecoder() {
}
H265Frame
::
Ptr
H265RtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
obtainObj
();
frame
->
_buffer
.
clear
();
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
...
...
@@ -30,9 +30,7 @@ H265RtpDecoder::H265RtpDecoder() {
}
H265Frame
::
Ptr
H265RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H265Frame
>::
obtainObj
();
frame
->
_buffer
.
clear
();
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论