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
35d9321b
Commit
35d9321b
authored
Jul 09, 2021
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
整理H264/H265 Frame对象及相关代码
parent
4fb44716
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
203 行增加
和
300 行删除
+203
-300
src/Extension/Frame.cpp
+49
-96
src/Extension/Frame.h
+26
-7
src/Extension/H264.cpp
+0
-42
src/Extension/H264.h
+47
-21
src/Extension/H264Rtmp.cpp
+9
-22
src/Extension/H264Rtmp.h
+3
-1
src/Extension/H265.cpp
+3
-54
src/Extension/H265.h
+54
-20
src/Extension/H265Rtmp.cpp
+9
-28
src/Extension/H265Rtmp.h
+1
-1
src/Extension/H265Rtp.cpp
+2
-6
src/Extension/H265Rtp.h
+0
-2
没有找到文件。
src/Extension/Frame.cpp
查看文件 @
35d9321b
...
...
@@ -58,12 +58,12 @@ public:
typedef
std
::
shared_ptr
<
FrameCacheAble
>
Ptr
;
FrameCacheAble
(
const
Frame
::
Ptr
&
frame
){
if
(
frame
->
cacheAble
())
{
if
(
frame
->
cacheAble
())
{
_frame
=
frame
;
_ptr
=
frame
->
data
();
}
else
{
}
else
{
_buffer
=
FrameImp
::
create
();
_buffer
->
_buffer
.
assign
(
frame
->
data
(),
frame
->
size
());
_buffer
->
_buffer
.
assign
(
frame
->
data
(),
frame
->
size
());
_ptr
=
_buffer
->
data
();
}
_size
=
frame
->
size
();
...
...
@@ -73,6 +73,8 @@ public:
_codec_id
=
frame
->
getCodecId
();
_key
=
frame
->
keyFrame
();
_config
=
frame
->
configFrame
();
_drop_able
=
frame
->
dropAble
();
_decode_able
=
frame
->
decodeAble
();
}
~
FrameCacheAble
()
override
=
default
;
...
...
@@ -92,9 +94,19 @@ public:
return
_config
;
}
bool
dropAble
()
const
override
{
return
_drop_able
;
}
bool
decodeAble
()
const
override
{
return
_decode_able
;
}
private
:
bool
_key
;
bool
_config
;
bool
_drop_able
;
bool
_decode_able
;
Frame
::
Ptr
_frame
;
FrameImp
::
Ptr
_buffer
;
};
...
...
@@ -153,18 +165,18 @@ const char* getTrackString(TrackType type){
}
}
const
char
*
CodecInfo
::
getCodecName
()
{
const
char
*
CodecInfo
::
getCodecName
()
const
{
return
mediakit
::
getCodecName
(
getCodecId
());
}
TrackType
CodecInfo
::
getTrackType
()
{
TrackType
CodecInfo
::
getTrackType
()
const
{
return
mediakit
::
getTrackType
(
getCodecId
());
}
static
size_t
constexpr
kMaxFrameCacheSize
=
100
;
bool
FrameMerger
::
willFlush
(
const
Frame
::
Ptr
&
frame
)
const
{
if
(
_frame
Cached
.
empty
())
{
if
(
_frame
_cache
.
empty
())
{
//缓存为空
return
false
;
}
...
...
@@ -182,36 +194,20 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
default
:
break
;
}
//遇到新帧、或时间戳变化或缓存太多,防止内存溢出,则flush输出
return
new_frame
||
_frame
Cached
.
back
()
->
dts
()
!=
frame
->
dts
()
||
_frameCached
.
size
()
>
kMaxFrameCacheSize
;
return
new_frame
||
_frame
_cache
.
back
()
->
dts
()
!=
frame
->
dts
()
||
_frame_cache
.
size
()
>
kMaxFrameCacheSize
;
}
case
mp4_nal_size
:
case
h264_prefix
:
{
if
(
!
frameCacheHasVCL
()
)
{
if
(
!
_have_decode_able_frame
)
{
//缓存中没有有效的能解码的帧,所以这次不flush
return
fals
e
;
return
_frame_cache
.
size
()
>
kMaxFrameCacheSiz
e
;
}
if
(
_frame
Cached
.
back
()
->
dts
()
!=
frame
->
dts
())
{
//时间戳变化了,立即flush
if
(
_frame
_cache
.
back
()
->
dts
()
!=
frame
->
dts
()
||
frame
->
decodeAble
())
{
//时间戳变化了,
或新的一帧,
立即flush
return
true
;
}
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:
{
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
// sei aud pps sps 不判断;264 新一帧的开始,刷新输出
return
(
frame
->
data
()[
frame
->
prefixSize
()
+
1
]
&
0x80
)
!=
0
&&
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
;
}
case
CodecH265
:
{
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
//first_slice_segment_in_pic_flag is frame start
return
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
&&
((
frame
->
data
()[
frame
->
prefixSize
()
+
2
]
>>
7
&
0x01
)
!=
0
);
}
default
:
//缓存太多,防止内存溢出
return
_frameCached
.
size
()
>
kMaxFrameCacheSize
;
}
return
_frame_cache
.
size
()
>
kMaxFrameCacheSize
;
}
default
:
/*不可达*/
assert
(
0
);
return
true
;
}
...
...
@@ -245,86 +241,39 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con
}
}
bool
FrameMerger
::
shouldDrop
(
const
Frame
::
Ptr
&
frame
)
const
{
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:
{
switch
(
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]))
{
// 防止把AUD或者SEI当成一帧
case
H264Frame
:
:
NAL_SEI
:
case
H264Frame
:
:
NAL_AUD
:
return
true
;
default
:
return
false
;
}
}
case
CodecH265
:
{
switch
(
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]))
{
// 防止把AUD或者SEI当成一帧
case
H265Frame
:
:
NAL_AUD
:
case
H265Frame
:
:
NAL_SEI_SUFFIX
:
case
H265Frame
:
:
NAL_SEI_PREFIX
:
return
true
;
default
:
return
false
;
}
}
default
:
return
false
;
}
}
bool
FrameMerger
::
frameCacheHasVCL
()
const
{
bool
has_vcl
=
false
;
bool
is_h264_or_h265
=
false
;
_frameCached
.
for_each
([
&
](
const
Frame
::
Ptr
&
frame
)
{
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:
{
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
//有编码数据
has_vcl
=
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
;
is_h264_or_h265
=
true
;
break
;
}
case
CodecH265
:
{
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
//有编码数据
has_vcl
=
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
;
is_h264_or_h265
=
true
;
break
;
}
default
:
break
;
}
});
if
(
is_h264_or_h265
)
{
return
has_vcl
;
}
return
true
;
}
void
FrameMerger
::
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
)
{
void
FrameMerger
::
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
,
BufferLikeString
*
buffer
)
{
if
(
willFlush
(
frame
))
{
Frame
::
Ptr
back
=
_frame
Cached
.
back
();
Frame
::
Ptr
back
=
_frame
_cache
.
back
();
Buffer
::
Ptr
merged_frame
=
back
;
bool
have_
idr
=
back
->
keyFrame
();
bool
have_
key_frame
=
back
->
keyFrame
();
if
(
_frame
Cached
.
size
()
!=
1
||
_type
==
mp4_nal_size
)
{
if
(
_frame
_cache
.
size
()
!=
1
||
_type
==
mp4_nal_size
||
buffer
)
{
//在MP4模式下,一帧数据也需要在前添加nalu_size
BufferLikeString
merged
;
merged
.
reserve
(
back
->
size
()
+
1024
);
_frameCached
.
for_each
([
&
](
const
Frame
::
Ptr
&
frame
)
{
BufferLikeString
tmp
;
BufferLikeString
&
merged
=
buffer
?
*
buffer
:
tmp
;
if
(
!
buffer
)
{
tmp
.
reserve
(
back
->
size
()
+
1024
);
}
_frame_cache
.
for_each
([
&
](
const
Frame
::
Ptr
&
frame
)
{
doMerge
(
merged
,
frame
);
if
(
frame
->
keyFrame
())
{
have_
idr
=
true
;
have_
key_frame
=
true
;
}
});
merged_frame
=
std
::
make_shared
<
BufferOffset
<
BufferLikeString
>
>
(
std
::
move
(
merged
));
merged_frame
=
std
::
make_shared
<
BufferOffset
<
BufferLikeString
>
>
(
buffer
?
merged
:
std
::
move
(
merged
));
}
cb
(
back
->
dts
(),
back
->
pts
(),
merged_frame
,
have_idr
);
_frameCached
.
clear
();
cb
(
back
->
dts
(),
back
->
pts
(),
merged_frame
,
have_key_frame
);
_frame_cache
.
clear
();
_have_decode_able_frame
=
false
;
}
switch
(
_type
)
{
case
h264_prefix
:
case
mp4_nal_size
:
{
//h264头和mp4头模式过滤无效的帧
if
(
shouldDrop
(
frame
))
{
if
(
frame
->
dropAble
())
{
//h264头和mp4头模式过滤无效的帧
return
;
}
break
;
...
...
@@ -332,7 +281,10 @@ void FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb) {
default
:
break
;
}
_frameCached
.
emplace_back
(
Frame
::
getCacheAbleFrame
(
frame
));
if
(
frame
->
decodeAble
())
{
_have_decode_able_frame
=
true
;
}
_frame_cache
.
emplace_back
(
Frame
::
getCacheAbleFrame
(
frame
));
}
FrameMerger
::
FrameMerger
(
int
type
)
{
...
...
@@ -340,7 +292,8 @@ FrameMerger::FrameMerger(int type) {
}
void
FrameMerger
::
clear
()
{
_frameCached
.
clear
();
_frame_cache
.
clear
();
_have_decode_able_frame
=
false
;
}
}
//namespace mediakit
src/Extension/Frame.h
查看文件 @
35d9321b
...
...
@@ -95,12 +95,12 @@ public:
/**
* 获取编码器名称
*/
const
char
*
getCodecName
();
const
char
*
getCodecName
()
const
;
/**
* 获取音视频类型
*/
TrackType
getTrackType
();
TrackType
getTrackType
()
const
;
};
/**
...
...
@@ -145,6 +145,26 @@ public:
virtual
bool
cacheAble
()
const
{
return
true
;
}
/**
* 该帧是否可以丢弃
* SEI/AUD帧可以丢弃
* 默认都不能丢帧
*/
virtual
bool
dropAble
()
const
{
return
false
;
}
/**
* 是否为可解码帧
* sps pps等帧不能解码
*/
virtual
bool
decodeAble
()
const
{
if
(
getTrackType
()
!=
TrackVideo
)
{
//非视频帧都可以解码
return
true
;
}
//默认非sps pps帧都可以解码
return
!
configFrame
();
}
/**
* 返回可缓存的frame
*/
static
Ptr
getCacheAbleFrame
(
const
Ptr
&
frame
);
...
...
@@ -459,7 +479,7 @@ private:
*/
class
FrameMerger
{
public
:
using
onOutput
=
function
<
void
(
uint32_t
dts
,
uint32_t
pts
,
const
Buffer
::
Ptr
&
buffer
,
bool
have_
idr
)
>
;
using
onOutput
=
function
<
void
(
uint32_t
dts
,
uint32_t
pts
,
const
Buffer
::
Ptr
&
buffer
,
bool
have_
key_frame
)
>
;
using
Ptr
=
std
::
shared_ptr
<
FrameMerger
>
;
enum
{
none
=
0
,
...
...
@@ -471,17 +491,16 @@ public:
~
FrameMerger
()
=
default
;
void
clear
();
void
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
);
void
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
,
BufferLikeString
*
buffer
=
nullptr
);
private
:
bool
willFlush
(
const
Frame
::
Ptr
&
frame
)
const
;
void
doMerge
(
BufferLikeString
&
buffer
,
const
Frame
::
Ptr
&
frame
)
const
;
bool
shouldDrop
(
const
Frame
::
Ptr
&
frame
)
const
;
bool
frameCacheHasVCL
()
const
;
private
:
int
_type
;
List
<
Frame
::
Ptr
>
_frameCached
;
bool
_have_decode_able_frame
=
false
;
List
<
Frame
::
Ptr
>
_frame_cache
;
};
}
//namespace mediakit
...
...
src/Extension/H264.cpp
查看文件 @
35d9321b
...
...
@@ -276,48 +276,6 @@ Sdp::Ptr H264Track::getSdp() {
return
std
::
make_shared
<
H264Sdp
>
(
getSps
(),
getPps
(),
getBitRate
()
/
1024
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool
H264Frame
::
keyFrame
()
const
{
//多slice 一帧的情况下检查 first_mb_in_slice 是否为0 表示其为一帧的开始
return
H264_TYPE
(
_buffer
[
_prefix_size
])
==
H264Frame
::
NAL_IDR
&&
(
_buffer
[
_prefix_size
+
1
]
&
0x80
);
}
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
查看文件 @
35d9321b
...
...
@@ -23,12 +23,12 @@ bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float
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
{
template
<
typename
Parent
>
class
H264FrameHelper
:
public
Parent
{
public
:
using
Ptr
=
std
::
shared_ptr
<
H264Frame
>
;
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H264FrameHelper
>
;
using
Ptr
=
std
::
shared_ptr
<
H264FrameHelper
>
;
enum
{
NAL_IDR
=
5
,
...
...
@@ -39,28 +39,54 @@ public:
NAL_B_P
=
1
,
};
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
protected
:
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H264Frame
>
;
H264Frame
();
template
<
typename
...
ARGS
>
H264FrameHelper
(
ARGS
&&
...
args
)
:
Parent
(
std
::
forward
<
ARGS
>
(
args
)...)
{
this
->
_codec_id
=
CodecH264
;
}
~
H264FrameHelper
()
override
=
default
;
bool
keyFrame
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
return
H264_TYPE
(
*
nal_ptr
)
==
NAL_IDR
&&
decodeAble
();
}
bool
configFrame
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
switch
(
H264_TYPE
(
*
nal_ptr
))
{
case
NAL_SPS
:
case
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
bool
dropAble
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
switch
(
H264_TYPE
(
*
nal_ptr
))
{
case
NAL_SEI
:
case
NAL_AUD
:
return
true
;
default
:
return
false
;
}
}
bool
decodeAble
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
auto
type
=
H264_TYPE
(
*
nal_ptr
);
//多slice情况下, first_mb_in_slice 表示其为一帧的开始
return
type
>=
NAL_B_P
&&
type
<=
NAL_IDR
&&
(
nal_ptr
[
1
]
&
0x80
);
}
};
/**
* 264帧类
*/
using
H264Frame
=
H264FrameHelper
<
FrameImp
>
;
/**
* 防止内存拷贝的H264类
* 用户可以通过该类型快速把一个指针无拷贝的包装成Frame类
* 该类型在DevChannel中有使用
*/
class
H264FrameNoCacheAble
:
public
FrameFromPtr
{
public
:
using
Ptr
=
std
::
shared_ptr
<
H264FrameNoCacheAble
>
;
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
;
};
using
H264FrameNoCacheAble
=
H264FrameHelper
<
FrameFromPtr
>
;
/**
* 264视频通道
...
...
src/Extension/H264Rtmp.cpp
查看文件 @
35d9321b
...
...
@@ -157,10 +157,8 @@ void H264RtmpEncoder::makeConfigPacket(){
void
H264RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
auto
data
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
len
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
type
=
H264_TYPE
(
((
uint8_t
*
)
data
)
[
0
]);
auto
type
=
H264_TYPE
(
data
[
0
]);
switch
(
type
)
{
case
H264Frame
:
:
NAL_SEI
:
case
H264Frame
:
:
NAL_AUD
:
return
;
case
H264Frame
:
:
NAL_SPS
:
{
if
(
!
_got_config_frame
)
{
_sps
=
string
(
data
,
len
);
...
...
@@ -178,21 +176,6 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
default
:
break
;
}
if
(
frame
->
configFrame
()
&&
_rtmp_packet
&&
_has_vcl
)
{
//sps pps flush frame
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_has_vcl
=
false
;
_rtmp_packet
=
nullptr
;
}
if
(
_rtmp_packet
&&
(
_rtmp_packet
->
time_stamp
!=
frame
->
dts
()
||
((
data
[
1
]
&
0x80
)
!=
0
&&
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
&&
_has_vcl
)))
{
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_has_vcl
=
false
;
_rtmp_packet
=
nullptr
;
}
if
(
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
_has_vcl
=
true
;
}
if
(
!
_rtmp_packet
)
{
//I or P or B frame
int8_t
flags
=
FLV_CODEC_H264
;
...
...
@@ -200,6 +183,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
_rtmp_packet
=
RtmpPacket
::
create
();
_rtmp_packet
->
buffer
.
clear
();
_rtmp_packet
->
buffer
.
push_back
(
flags
);
_rtmp_packet
->
buffer
.
push_back
(
!
is_config
);
int32_t
cts
=
frame
->
pts
()
-
frame
->
dts
();
...
...
@@ -213,10 +197,13 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
_rtmp_packet
->
time_stamp
=
frame
->
dts
();
_rtmp_packet
->
type_id
=
MSG_VIDEO
;
}
uint32_t
size
=
htonl
((
uint32_t
)
len
);
_rtmp_packet
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_rtmp_packet
->
buffer
.
append
(
data
,
len
);
_rtmp_packet
->
body_size
=
_rtmp_packet
->
buffer
.
size
();
_merger
.
inputFrame
(
frame
,
[
&
](
uint32_t
,
uint32_t
,
const
Buffer
::
Ptr
&
,
bool
)
{
//输出rtmp packet
_rtmp_packet
->
body_size
=
_rtmp_packet
->
buffer
.
size
();
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_rtmp_packet
=
nullptr
;
},
&
_rtmp_packet
->
buffer
);
}
void
H264RtmpEncoder
::
makeVideoConfigPkt
()
{
...
...
src/Extension/H264Rtmp.h
查看文件 @
35d9321b
...
...
@@ -75,13 +75,15 @@ public:
* 生成config包
*/
void
makeConfigPacket
()
override
;
private
:
void
makeVideoConfigPkt
();
private
:
bool
_has_vcl
=
false
;
bool
_got_config_frame
=
false
;
H264Track
::
Ptr
_track
;
RtmpPacket
::
Ptr
_rtmp_packet
;
FrameMerger
_merger
{
FrameMerger
::
mp4_nal_size
};
};
}
//namespace mediakit
...
...
src/Extension/H265.cpp
查看文件 @
35d9321b
...
...
@@ -50,56 +50,6 @@ bool getHEVCInfo(const string &strVps, const string &strSps, int &iVideoWidth, i
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool
H265Frame
::
keyFrame
()
const
{
return
isKeyFrame
(
H265_TYPE
(
_buffer
[
_prefix_size
]),
_buffer
.
data
()
+
_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
,
const
char
*
ptr
)
{
if
(
ptr
)
{
return
(((
*
((
uint8_t
*
)
ptr
+
2
))
>>
7
)
&
0x01
)
==
1
&&
(
type
==
NAL_IDR_N_LP
||
type
==
NAL_IDR_W_RADL
);
}
return
false
;
}
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
]),
_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
);
...
...
@@ -154,17 +104,16 @@ void H265Track::inputFrame(const Frame::Ptr &frame) {
}
void
H265Track
::
inputFrame_l
(
const
Frame
::
Ptr
&
frame
)
{
int
type
=
H265_TYPE
(((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
())[
0
]);
if
(
H265Frame
::
isKeyFrame
(
type
,
frame
->
data
()
+
frame
->
prefixSize
()))
{
if
(
frame
->
keyFrame
())
{
insertConfigFrame
(
frame
);
VideoTrack
::
inputFrame
(
frame
);
_is_idr
=
true
;
return
;
}
_is_idr
=
false
;
_is_idr
=
false
;
//非idr帧
switch
(
type
)
{
switch
(
H265_TYPE
(((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
())[
0
])
)
{
case
H265Frame
:
:
NAL_VPS
:
{
_vps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
break
;
...
...
src/Extension/H265.h
查看文件 @
35d9321b
...
...
@@ -22,12 +22,13 @@ namespace mediakit {
bool
getHEVCInfo
(
const
string
&
strVps
,
const
string
&
strSps
,
int
&
iVideoWidth
,
int
&
iVideoHeight
,
float
&
iVideoFps
);
/**
* 265帧类
*/
class
H265Frame
:
public
FrameImp
{
template
<
typename
Parent
>
class
H265FrameHelper
:
public
Parent
{
public
:
using
Ptr
=
std
::
shared_ptr
<
H265Frame
>
;
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H265FrameHelper
>
;
using
Ptr
=
std
::
shared_ptr
<
H265FrameHelper
>
;
enum
{
NAL_TRAIL_N
=
0
,
NAL_TRAIL_R
=
1
,
...
...
@@ -59,24 +60,57 @@ public:
NAL_SEI_SUFFIX
=
40
,
};
bool
keyFrame
()
const
override
;
bool
configFrame
()
const
override
;
static
bool
isKeyFrame
(
int
type
,
const
char
*
ptr
);
protected
:
friend
class
FrameImp
;
friend
class
ResourcePool_l
<
H265Frame
>
;
H265Frame
();
template
<
typename
...
ARGS
>
H265FrameHelper
(
ARGS
&&
...
args
)
:
Parent
(
std
::
forward
<
ARGS
>
(
args
)...)
{
this
->
_codec_id
=
CodecH265
;
}
~
H265FrameHelper
()
override
=
default
;
bool
keyFrame
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
auto
type
=
H265_TYPE
(
*
nal_ptr
);
return
(
type
==
NAL_IDR_N_LP
||
type
==
NAL_IDR_W_RADL
)
&&
decodeAble
();
}
bool
configFrame
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
switch
(
H265_TYPE
(
*
nal_ptr
))
{
case
NAL_VPS
:
case
NAL_SPS
:
case
NAL_PPS
:
return
true
;
default
:
return
false
;
}
}
bool
dropAble
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
switch
(
H264_TYPE
(
*
nal_ptr
))
{
case
NAL_AUD
:
case
NAL_SEI_SUFFIX
:
case
NAL_SEI_PREFIX
:
return
true
;
default
:
return
false
;
}
}
bool
decodeAble
()
const
override
{
auto
nal_ptr
=
(
uint8_t
*
)
this
->
data
()
+
this
->
prefixSize
();
auto
type
=
H265_TYPE
(
*
nal_ptr
);
//多slice情况下, first_slice_segment_in_pic_flag 表示其为一帧的开始
return
type
>=
NAL_TRAIL_R
&&
type
<=
NAL_RSV_IRAP_VCL23
&&
(
nal_ptr
[
2
]
&
0x80
);
}
};
class
H265FrameNoCacheAble
:
public
FrameFromPtr
{
public
:
using
Ptr
=
std
::
shared_ptr
<
H265FrameNoCacheAble
>
;
/**
* 265帧类
*/
using
H265Frame
=
H265FrameHelper
<
FrameImp
>
;
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
;
};
/**
* 防止内存拷贝的H265类
* 用户可以通过该类型快速把一个指针无拷贝的包装成Frame类
*/
using
H265FrameNoCacheAble
=
H265FrameHelper
<
FrameFromPtr
>
;
/**
* 265视频通道
...
...
src/Extension/H265Rtmp.cpp
查看文件 @
35d9321b
...
...
@@ -136,8 +136,7 @@ void H265RtmpEncoder::makeConfigPacket(){
void
H265RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
auto
data
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
len
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
type
=
H265_TYPE
(((
uint8_t
*
)
data
)[
0
]);
auto
type
=
H265_TYPE
(
data
[
0
]);
switch
(
type
)
{
case
H265Frame
:
:
NAL_SPS
:
{
if
(
!
_got_config_frame
)
{
...
...
@@ -160,37 +159,16 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
}
break
;
}
case
H265Frame
:
:
NAL_AUD
:
case
H265Frame
:
:
NAL_SEI_PREFIX
:
case
H265Frame
:
:
NAL_SEI_SUFFIX
:
return
;
default
:
break
;
}
if
(
frame
->
configFrame
()
&&
_rtmp_packet
&&
_has_vcl
){
// sps pps flush frame
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_rtmp_packet
=
nullptr
;
_has_vcl
=
false
;
}
if
(
_rtmp_packet
&&
(
_rtmp_packet
->
time_stamp
!=
frame
->
dts
()
||
(
_has_vcl
&&
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
&&
(
data
[
2
]
>>
7
&
0x01
)
!=
0
)))
{
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_has_vcl
=
false
;
_rtmp_packet
=
nullptr
;
}
if
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
{
_has_vcl
=
true
;
}
if
(
!
_rtmp_packet
)
{
//I or P or B frame
int8_t
flags
=
FLV_CODEC_H265
;
bool
is_config
=
false
;
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
// todo 必须是IDR帧才能是关键帧,否则有可能开始帧会花屏 SPS PPS VPS 打头的是一般I帧,但不一定是IDR帧
// RtmpCodec::inputRtmp 时需要判断 是否是IDR帧,做出相应的修改
_rtmp_packet
=
RtmpPacket
::
create
();
_rtmp_packet
->
buffer
.
clear
();
_rtmp_packet
->
buffer
.
push_back
(
flags
);
_rtmp_packet
->
buffer
.
push_back
(
!
is_config
);
int32_t
cts
=
frame
->
pts
()
-
frame
->
dts
();
...
...
@@ -204,10 +182,13 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
_rtmp_packet
->
time_stamp
=
frame
->
dts
();
_rtmp_packet
->
type_id
=
MSG_VIDEO
;
}
uint32_t
size
=
htonl
((
uint32_t
)
len
);
_rtmp_packet
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_rtmp_packet
->
buffer
.
append
(
data
,
len
);
_rtmp_packet
->
body_size
=
_rtmp_packet
->
buffer
.
size
();
_merger
.
inputFrame
(
frame
,
[
&
](
uint32_t
,
uint32_t
,
const
Buffer
::
Ptr
&
,
bool
)
{
//输出rtmp packet
_rtmp_packet
->
body_size
=
_rtmp_packet
->
buffer
.
size
();
RtmpCodec
::
inputRtmp
(
_rtmp_packet
);
_rtmp_packet
=
nullptr
;
},
&
_rtmp_packet
->
buffer
);
}
void
H265RtmpEncoder
::
makeVideoConfigPkt
()
{
...
...
src/Extension/H265Rtmp.h
查看文件 @
35d9321b
...
...
@@ -78,13 +78,13 @@ private:
void
makeVideoConfigPkt
();
private
:
bool
_has_vcl
=
false
;
bool
_got_config_frame
=
false
;
string
_vps
;
string
_sps
;
string
_pps
;
H265Track
::
Ptr
_track
;
RtmpPacket
::
Ptr
_rtmp_packet
;
FrameMerger
_merger
{
FrameMerger
::
mp4_nal_size
};
};
}
//namespace mediakit
...
...
src/Extension/H265Rtp.cpp
查看文件 @
35d9321b
...
...
@@ -269,19 +269,15 @@ void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) {
//H265 数据
memcpy
(
payload
+
3
,
ptr
+
offset
,
max_size
);
//输入到rtp环形缓存
RtpCodec
::
inputRtp
(
rtp
,
fu_start
&&
H265Frame
::
isKeyFrame
(
nal_type
,
frame
->
data
()
+
frame
->
prefixSize
()
));
RtpCodec
::
inputRtp
(
rtp
,
fu_start
&&
frame
->
keyFrame
(
));
}
offset
+=
max_size
;
fu_start
=
false
;
}
}
else
{
makeH265Rtp
(
nal_type
,
ptr
,
len
,
false
,
true
,
pts
);
RtpCodec
::
inputRtp
(
makeRtp
(
getTrackType
(),
ptr
,
len
,
false
,
pts
),
frame
->
keyFrame
()
);
}
}
void
H265RtpEncoder
::
makeH265Rtp
(
int
nal_type
,
const
void
*
data
,
size_t
len
,
bool
mark
,
bool
first_packet
,
uint32_t
uiStamp
)
{
RtpCodec
::
inputRtp
(
makeRtp
(
getTrackType
(),
data
,
len
,
mark
,
uiStamp
),
first_packet
&&
H265Frame
::
isKeyFrame
(
nal_type
,
(
const
char
*
)
data
+
prefixSize
((
const
char
*
)
data
,
len
)));
}
}
//namespace mediakit
src/Extension/H265Rtp.h
查看文件 @
35d9321b
...
...
@@ -84,8 +84,6 @@ public:
* @param frame 帧数据,必须
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
private
:
void
makeH265Rtp
(
int
nal_type
,
const
void
*
pData
,
size_t
uiLen
,
bool
bMark
,
bool
first_packet
,
uint32_t
uiStamp
);
};
}
//namespace mediakit{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论