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
8f730b8d
Commit
8f730b8d
authored
Jun 28, 2021
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
整理代码
parent
430229fe
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
173 行增加
和
180 行删除
+173
-180
src/Extension/Frame.cpp
+52
-46
src/Extension/H264Rtmp.cpp
+51
-58
src/Extension/H264Rtmp.h
+3
-3
src/Extension/H265.cpp
+1
-1
src/Extension/H265Rtmp.cpp
+63
-69
src/Extension/H265Rtmp.h
+3
-3
没有找到文件。
src/Extension/Frame.cpp
查看文件 @
8f730b8d
...
@@ -192,10 +192,11 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
...
@@ -192,10 +192,11 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
switch
(
frame
->
getCodecId
())
{
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:
{
case
CodecH264
:
{
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
if
((
frame
->
data
()[
frame
->
prefixSize
()
+
1
]
&
0x80
)
!=
0
&&
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
// sei aud pps sps 不判断
if
((
frame
->
data
()[
frame
->
prefixSize
()
+
1
]
&
0x80
)
!=
0
&&
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
// sei aud pps sps 不判断
//264 新一帧的开始,刷新输出
//264 新一帧的开始,刷新输出
return
true
;
return
true
;
}
else
{
}
else
{
// 不刷新输出
// 不刷新输出
return
false
;
return
false
;
}
}
...
@@ -203,10 +204,11 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
...
@@ -203,10 +204,11 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
}
}
case
CodecH265
:
{
case
CodecH265
:
{
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
if
((
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
&&
(
(
frame
->
data
()[
frame
->
prefixSize
()
+
2
]
>>
7
&
0x01
)
!=
0
))
{
if
((
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
&&
((
frame
->
data
()[
frame
->
prefixSize
()
+
2
]
>>
7
&
0x01
)
!=
0
))
{
//first_slice_segment_in_pic_flag is frame start
//first_slice_segment_in_pic_flag is frame start
return
true
;
return
true
;
}
else
{
}
else
{
return
false
;
return
false
;
}
}
break
;
break
;
...
@@ -244,64 +246,68 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con
...
@@ -244,64 +246,68 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con
default
:
/*不可达*/
assert
(
0
);
break
;
default
:
/*不可达*/
assert
(
0
);
break
;
}
}
}
}
bool
FrameMerger
::
shouldDrop
(
const
Frame
::
Ptr
&
frame
)
const
{
bool
FrameMerger
::
shouldDrop
(
const
Frame
::
Ptr
&
frame
)
const
{
switch
(
frame
->
getCodecId
())
{
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:{
case
CodecH264
:
{
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
if
(
type
==
H264Frame
::
NAL_SEI
||
type
==
H264Frame
::
NAL_AUD
){
if
(
type
==
H264Frame
::
NAL_SEI
||
type
==
H264Frame
::
NAL_AUD
)
{
// 防止吧AUD或者SEI当成一帧
// 防止吧AUD或者SEI当成一帧
return
true
;
return
true
;
}
}
break
;
break
;
}
}
case
CodecH265
:
{
case
CodecH265
:
{
//如果是新的一帧,前面的缓存需要输出
//如果是新的一帧,前面的缓存需要输出
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
if
(
type
==
H265Frame
::
NAL_AUD
||
type
==
H265Frame
::
NAL_SEI_PREFIX
||
type
==
H265Frame
::
NAL_SEI_SUFFIX
){
if
(
type
==
H265Frame
::
NAL_AUD
||
type
==
H265Frame
::
NAL_SEI_PREFIX
||
type
==
H265Frame
::
NAL_SEI_SUFFIX
)
{
// 防止吧AUD或者SEI当成一帧
// 防止吧AUD或者SEI当成一帧
return
true
;
return
true
;
}
break
;
}
default
:
break
;
}
}
break
;
}
default
:
break
;
}
return
false
;
return
false
;
}
}
bool
FrameMerger
::
frameCacheHasVCL
(
List
<
Frame
::
Ptr
>
&
frameCached
)
const
{
bool
FrameMerger
::
frameCacheHasVCL
(
List
<
Frame
::
Ptr
>
&
frameCached
)
const
{
bool
hasVCL
=
false
;
bool
hasVCL
=
false
;
bool
isH264OrH265
=
false
;
bool
isH264OrH265
=
false
;
frameCached
.
for_each
([
&
hasVCL
,
&
isH264OrH265
](
const
Frame
::
Ptr
&
frame
)
{
frameCached
.
for_each
([
&
hasVCL
,
&
isH264OrH265
](
const
Frame
::
Ptr
&
frame
)
{
switch
(
frame
->
getCodecId
())
{
switch
(
frame
->
getCodecId
())
{
case
CodecH264
:{
case
CodecH264
:
{
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
auto
type
=
H264_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
if
(
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
){
if
(
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
//有编码数据
//有编码数据
hasVCL
=
true
;
hasVCL
=
true
;
}
isH264OrH265
=
true
;
break
;
}
}
case
CodecH265
:
{
isH264OrH265
=
true
;
//如果是新的一帧,前面的缓存需要输出
break
;
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()]);
}
if
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
{
case
CodecH265
:
{
//有编码数据
//如果是新的一帧,前面的缓存需要输出
hasVCL
=
true
;
auto
type
=
H265_TYPE
(
frame
->
data
()[
frame
->
prefixSize
()])
;
}
if
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
{
isH264OrH265
=
true
;
//有编码数据
break
;
hasVCL
=
true
;
}
}
default
:
break
;
isH264OrH265
=
true
;
break
;
}
}
default
:
break
;
}
});
});
if
(
isH264OrH265
)
{
if
(
isH264OrH265
)
{
return
hasVCL
;
return
hasVCL
;
}
}
return
true
;
return
true
;
}
}
void
FrameMerger
::
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
)
{
void
FrameMerger
::
inputFrame
(
const
Frame
::
Ptr
&
frame
,
const
onOutput
&
cb
)
{
if
(
shouldDrop
(
frame
))
{
if
(
shouldDrop
(
frame
))
{
return
;
return
;
}
}
if
(
willFlush
(
frame
)
&&
frameCacheHasVCL
(
_frameCached
))
{
if
(
willFlush
(
frame
)
&&
frameCacheHasVCL
(
_frameCached
))
{
...
...
src/Extension/H264Rtmp.cpp
查看文件 @
8f730b8d
...
@@ -95,22 +95,21 @@ void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
...
@@ -95,22 +95,21 @@ void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
}
}
if
(
pkt
->
buffer
.
size
()
>
9
)
{
if
(
pkt
->
buffer
.
size
()
>
9
)
{
auto
iTotalL
en
=
pkt
->
buffer
.
size
();
auto
total_l
en
=
pkt
->
buffer
.
size
();
size_t
iO
ffset
=
5
;
size_t
o
ffset
=
5
;
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
auto
pts
=
pkt
->
time_stamp
+
cts
;
auto
pts
=
pkt
->
time_stamp
+
cts
;
while
(
offset
+
4
<
total_len
)
{
while
(
iOffset
+
4
<
iTotalLen
){
uint32_t
frame_len
;
uint32_t
iFrameLen
;
memcpy
(
&
frame_len
,
pkt
->
buffer
.
data
()
+
offset
,
4
);
memcpy
(
&
iFrameLen
,
pkt
->
buffer
.
data
()
+
iOffset
,
4
);
frame_len
=
ntohl
(
frame_len
);
iFrameLen
=
ntohl
(
iFrameLen
);
offset
+=
4
;
iOffset
+=
4
;
if
(
frame_len
+
offset
>
total_len
)
{
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
break
;
break
;
}
}
onGetH264
(
pkt
->
buffer
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
time_stamp
,
pts
);
onGetH264
(
pkt
->
buffer
.
data
()
+
offset
,
frame_len
,
pkt
->
time_stamp
,
pts
);
iOffset
+=
iFrameL
en
;
offset
+=
frame_l
en
;
}
}
}
}
}
}
...
@@ -151,79 +150,73 @@ void H264RtmpEncoder::makeConfigPacket(){
...
@@ -151,79 +150,73 @@ void H264RtmpEncoder::makeConfigPacket(){
if
(
!
_sps
.
empty
()
&&
!
_pps
.
empty
())
{
if
(
!
_sps
.
empty
()
&&
!
_pps
.
empty
())
{
//获取到sps/pps
//获取到sps/pps
makeVideoConfigPkt
();
makeVideoConfigPkt
();
_got
SpsPps
=
true
;
_got
_config_frame
=
true
;
}
}
}
}
void
H264RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
void
H264RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
auto
pcData
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
data
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
len
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
type
=
H264_TYPE
(((
uint8_t
*
)
pcData
)[
0
]);
auto
type
=
H264_TYPE
(((
uint8_t
*
)
data
)[
0
]);
if
(
type
==
H264Frame
::
NAL_SEI
||
type
==
H264Frame
::
NAL_AUD
){
switch
(
type
)
{
return
;
case
H264Frame
:
:
NAL_SEI
:
}
case
H264Frame
:
:
NAL_AUD
:
return
;
case
H264Frame
:
:
NAL_SPS
:
{
if
(
!
_gotSpsPps
)
{
if
(
!
_got_config_frame
)
{
//尝试从frame中获取sps pps
_sps
=
string
(
data
,
len
);
switch
(
type
)
{
case
H264Frame
:
:
NAL_SPS
:
{
//sps
_sps
=
string
(
pcData
,
iLen
);
makeConfigPacket
();
makeConfigPacket
();
break
;
}
}
case
H264Frame
:
:
NAL_PPS
:
{
break
;
//pps
}
_pps
=
string
(
pcData
,
iLen
);
case
H264Frame
:
:
NAL_PPS
:
{
if
(
!
_got_config_frame
)
{
_pps
=
string
(
data
,
len
);
makeConfigPacket
();
makeConfigPacket
();
break
;
}
}
default
:
break
;
break
;
}
}
default
:
break
;
}
}
if
(
frame
->
configFrame
()
&&
_lastPacket
&&
_lastPacketHasVCL
){
if
(
frame
->
configFrame
()
&&
_rtmp_packet
&&
_has_vcl
)
{
//sps pps flush frame
//sps pps flush frame
RtmpCodec
::
inputRtmp
(
_
lastP
acket
);
RtmpCodec
::
inputRtmp
(
_
rtmp_p
acket
);
_
lastPacket
=
nullptr
;
_
has_vcl
=
false
;
_
lastPacketHasVCL
=
false
;
_
rtmp_packet
=
nullptr
;
}
}
if
(
_lastPacket
&&
(
_lastPacket
->
time_stamp
!=
frame
->
dts
()
||
((
pcData
[
1
]
&
0x80
)
!=
0
&&
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
&&
_lastPacketHasVCL
)))
{
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
(
_
lastP
acket
);
RtmpCodec
::
inputRtmp
(
_
rtmp_p
acket
);
_
lastPacket
=
nullptr
;
_
has_vcl
=
false
;
_
lastPacketHasVCL
=
false
;
_
rtmp_packet
=
nullptr
;
}
}
if
(
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
if
(
type
>=
H264Frame
::
NAL_B_P
&&
type
<=
H264Frame
::
NAL_IDR
)
{
_
lastPacketHasVCL
=
true
;
_
has_vcl
=
true
;
}
}
if
(
!
_rtmp_packet
)
{
if
(
!
_lastPacket
)
{
//I or P or B frame
//I or P or B frame
int8_t
flags
=
FLV_CODEC_H264
;
int8_t
flags
=
FLV_CODEC_H264
;
bool
is_config
=
false
;
bool
is_config
=
false
;
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
_
lastP
acket
=
RtmpPacket
::
create
();
_
rtmp_p
acket
=
RtmpPacket
::
create
();
_
lastP
acket
->
buffer
.
push_back
(
flags
);
_
rtmp_p
acket
->
buffer
.
push_back
(
flags
);
_
lastP
acket
->
buffer
.
push_back
(
!
is_config
);
_
rtmp_p
acket
->
buffer
.
push_back
(
!
is_config
);
int32_t
cts
=
frame
->
pts
()
-
frame
->
dts
();
int32_t
cts
=
frame
->
pts
()
-
frame
->
dts
();
if
(
cts
<
0
)
{
if
(
cts
<
0
)
{
cts
=
0
;
cts
=
0
;
}
}
cts
=
htonl
(
cts
);
cts
=
htonl
(
cts
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_rtmp_packet
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_rtmp_packet
->
chunk_id
=
CHUNK_VIDEO
;
_lastPacket
->
chunk_id
=
CHUNK_VIDEO
;
_rtmp_packet
->
stream_index
=
STREAM_MEDIA
;
_lastPacket
->
stream_index
=
STREAM_MEDIA
;
_rtmp_packet
->
time_stamp
=
frame
->
dts
();
_lastPacket
->
time_stamp
=
frame
->
dts
();
_rtmp_packet
->
type_id
=
MSG_VIDEO
;
_lastPacket
->
type_id
=
MSG_VIDEO
;
}
}
uint32_t
size
=
htonl
((
uint32_t
)
iL
en
);
uint32_t
size
=
htonl
((
uint32_t
)
l
en
);
_
lastP
acket
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_
rtmp_p
acket
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_
lastPacket
->
buffer
.
append
(
pcData
,
iL
en
);
_
rtmp_packet
->
buffer
.
append
(
data
,
l
en
);
_
lastPacket
->
body_size
=
_lastP
acket
->
buffer
.
size
();
_
rtmp_packet
->
body_size
=
_rtmp_p
acket
->
buffer
.
size
();
}
}
void
H264RtmpEncoder
::
makeVideoConfigPkt
()
{
void
H264RtmpEncoder
::
makeVideoConfigPkt
()
{
...
...
src/Extension/H264Rtmp.h
查看文件 @
8f730b8d
...
@@ -78,10 +78,10 @@ public:
...
@@ -78,10 +78,10 @@ public:
private
:
private
:
void
makeVideoConfigPkt
();
void
makeVideoConfigPkt
();
private
:
private
:
bool
_has_vcl
=
false
;
bool
_got_config_frame
=
false
;
H264Track
::
Ptr
_track
;
H264Track
::
Ptr
_track
;
bool
_gotSpsPps
=
false
;
RtmpPacket
::
Ptr
_rtmp_packet
;
bool
_lastPacketHasVCL
=
false
;
RtmpPacket
::
Ptr
_lastPacket
;
};
};
}
//namespace mediakit
}
//namespace mediakit
...
...
src/Extension/H265.cpp
查看文件 @
8f730b8d
...
@@ -64,7 +64,7 @@ bool H265Frame::configFrame() const {
...
@@ -64,7 +64,7 @@ bool H265Frame::configFrame() const {
}
}
bool
H265Frame
::
isKeyFrame
(
int
type
,
const
char
*
ptr
)
{
bool
H265Frame
::
isKeyFrame
(
int
type
,
const
char
*
ptr
)
{
if
(
ptr
)
{
if
(
ptr
)
{
return
(((
*
((
uint8_t
*
)
ptr
+
2
))
>>
7
)
&
0x01
)
==
1
&&
(
type
==
NAL_IDR_N_LP
||
type
==
NAL_IDR_W_RADL
);
return
(((
*
((
uint8_t
*
)
ptr
+
2
))
>>
7
)
&
0x01
)
==
1
&&
(
type
==
NAL_IDR_N_LP
||
type
==
NAL_IDR_W_RADL
);
}
}
return
false
;
return
false
;
...
...
src/Extension/H265Rtmp.cpp
查看文件 @
8f730b8d
...
@@ -73,22 +73,21 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
...
@@ -73,22 +73,21 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
}
}
if
(
pkt
->
buffer
.
size
()
>
9
)
{
if
(
pkt
->
buffer
.
size
()
>
9
)
{
auto
iTotalL
en
=
pkt
->
buffer
.
size
();
auto
total_l
en
=
pkt
->
buffer
.
size
();
size_t
iO
ffset
=
5
;
size_t
o
ffset
=
5
;
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
auto
pts
=
pkt
->
time_stamp
+
cts
;
auto
pts
=
pkt
->
time_stamp
+
cts
;
while
(
offset
+
4
<
total_len
)
{
while
(
iOffset
+
4
<
iTotalLen
){
uint32_t
frame_len
;
uint32_t
iFrameLen
;
memcpy
(
&
frame_len
,
pkt
->
buffer
.
data
()
+
offset
,
4
);
memcpy
(
&
iFrameLen
,
pkt
->
buffer
.
data
()
+
iOffset
,
4
);
frame_len
=
ntohl
(
frame_len
);
iFrameLen
=
ntohl
(
iFrameLen
);
offset
+=
4
;
iOffset
+=
4
;
if
(
frame_len
+
offset
>
total_len
)
{
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
break
;
break
;
}
}
onGetH265
(
pkt
->
buffer
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
time_stamp
,
pts
);
onGetH265
(
pkt
->
buffer
.
data
()
+
offset
,
frame_len
,
pkt
->
time_stamp
,
pts
);
iOffset
+=
iFrameL
en
;
offset
+=
frame_l
en
;
}
}
}
}
}
}
...
@@ -130,87 +129,85 @@ void H265RtmpEncoder::makeConfigPacket(){
...
@@ -130,87 +129,85 @@ void H265RtmpEncoder::makeConfigPacket(){
if
(
!
_sps
.
empty
()
&&
!
_pps
.
empty
()
&&
!
_vps
.
empty
())
{
if
(
!
_sps
.
empty
()
&&
!
_pps
.
empty
()
&&
!
_vps
.
empty
())
{
//获取到sps/pps
//获取到sps/pps
makeVideoConfigPkt
();
makeVideoConfigPkt
();
_got
SpsPps
=
true
;
_got
_config_frame
=
true
;
}
}
}
}
void
H265RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
void
H265RtmpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
auto
pcData
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
data
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
len
=
frame
->
size
()
-
frame
->
prefixSize
();
auto
type
=
H265_TYPE
(((
uint8_t
*
)
pcData
)[
0
]);
auto
type
=
H265_TYPE
(((
uint8_t
*
)
data
)[
0
]);
if
(
!
_gotSpsPps
)
{
switch
(
type
)
{
//尝试从frame中获取sps pps
case
H265Frame
:
:
NAL_SPS
:
{
switch
(
type
)
{
if
(
!
_got_config_frame
)
{
case
H265Frame
:
:
NAL_SPS
:
{
_sps
=
string
(
data
,
len
);
//sps
_sps
=
string
(
pcData
,
iLen
);
makeConfigPacket
();
makeConfigPacket
();
break
;
}
}
case
H265Frame
:
:
NAL_PPS
:
{
break
;
//pps
}
_pps
=
string
(
pcData
,
iLen
);
case
H265Frame
:
:
NAL_PPS
:
{
if
(
!
_got_config_frame
)
{
_pps
=
string
(
data
,
len
);
makeConfigPacket
();
makeConfigPacket
();
break
;
}
}
case
H265Frame
:
:
NAL_VPS
:
{
break
;
//vps
}
_vps
=
string
(
pcData
,
iLen
);
case
H265Frame
:
:
NAL_VPS
:
{
if
(
!
_got_config_frame
)
{
_vps
=
string
(
data
,
len
);
makeConfigPacket
();
makeConfigPacket
();
break
;
break
;
}
}
default
:
break
;
}
}
case
H265Frame
:
:
NAL_AUD
:
case
H265Frame
:
:
NAL_SEI_PREFIX
:
case
H265Frame
:
:
NAL_SEI_SUFFIX
:
return
;
default
:
break
;
}
}
if
(
type
==
H265Frame
::
NAL_SEI_PREFIX
||
type
==
H265Frame
::
NAL_SEI_SUFFIX
||
type
==
H265Frame
::
NAL_AUD
){
if
(
frame
->
configFrame
()
&&
_rtmp_packet
&&
_has_vcl
){
return
;
// 防止sei aud 作为一帧
}
if
(
frame
->
configFrame
()
&&
_lastPacket
&&
_lastPacketHasVCL
){
// sps pps flush frame
// sps pps flush frame
RtmpCodec
::
inputRtmp
(
_
lastP
acket
);
RtmpCodec
::
inputRtmp
(
_
rtmp_p
acket
);
_
lastP
acket
=
nullptr
;
_
rtmp_p
acket
=
nullptr
;
_
lastPacketHasVCL
=
false
;
_
has_vcl
=
false
;
}
}
if
(
_
lastPacket
&&
(
_lastPacket
->
time_stamp
!=
frame
->
dts
()
||
(
_lastPacketHasVCL
&&
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
&&
(
pcData
[
2
]
>>
7
&
0x01
)
!=
0
)))
{
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
(
_
lastP
acket
);
RtmpCodec
::
inputRtmp
(
_
rtmp_p
acket
);
_
lastPacket
=
nullptr
;
_
has_vcl
=
false
;
_
lastPacketHasVCL
=
false
;
_
rtmp_packet
=
nullptr
;
}
}
if
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
{
if
(
type
>=
H265Frame
::
NAL_TRAIL_R
&&
type
<=
H265Frame
::
NAL_RSV_IRAP_VCL23
)
{
_
lastPacketHasVCL
=
true
;
_
has_vcl
=
true
;
}
}
if
(
!
_lastP
acket
)
{
if
(
!
_rtmp_p
acket
)
{
//I or P or B frame
//I or P or B frame
int8_t
flags
=
FLV_CODEC_H265
;
int8_t
flags
=
FLV_CODEC_H265
;
bool
is_config
=
false
;
bool
is_config
=
false
;
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
// to do
// todo 必须是IDR帧才能是关键帧,否则有可能开始帧会花屏 SPS PPS VPS 打头的是一般I帧,但不一定是IDR帧
// 必须是IDR帧才能是关键帧,否则有可能开始帧会花屏 SPS PPS VPS 打头的是一般I帧,但不一定是IDR帧
// RtmpCodec::inputRtmp 时需要判断 是否是IDR帧,做出相应的修改
// RtmpCodec::inputRtmp 时需要判断 是否是IDR帧,做出相应的修改
_rtmp_packet
=
RtmpPacket
::
create
();
_lastPacket
=
RtmpPacket
::
create
();
_rtmp_packet
->
buffer
.
push_back
(
flags
);
_lastPacket
->
buffer
.
push_back
(
flags
);
_rtmp_packet
->
buffer
.
push_back
(
!
is_config
);
_lastPacket
->
buffer
.
push_back
(
!
is_config
);
int32_t
cts
=
frame
->
pts
()
-
frame
->
dts
();
auto
cts
=
frame
->
pts
()
-
frame
->
dts
();
if
(
cts
<
0
)
{
cts
=
0
;
}
cts
=
htonl
(
cts
);
cts
=
htonl
(
cts
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_rtmp_packet
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_rtmp_packet
->
chunk_id
=
CHUNK_VIDEO
;
_lastPacket
->
chunk_id
=
CHUNK_VIDEO
;
_rtmp_packet
->
stream_index
=
STREAM_MEDIA
;
_lastPacket
->
stream_index
=
STREAM_MEDIA
;
_rtmp_packet
->
time_stamp
=
frame
->
dts
();
_lastPacket
->
time_stamp
=
frame
->
dts
();
_rtmp_packet
->
type_id
=
MSG_VIDEO
;
_lastPacket
->
type_id
=
MSG_VIDEO
;
}
uint32_t
size
=
htonl
((
uint32_t
)
len
);
}
_rtmp_packet
->
buffer
.
append
((
char
*
)
&
size
,
4
);
uint32_t
size
=
htonl
((
uint32_t
)
iLen
);
_rtmp_packet
->
buffer
.
append
(
data
,
len
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_rtmp_packet
->
body_size
=
_rtmp_packet
->
buffer
.
size
();
_lastPacket
->
buffer
.
append
(
pcData
,
iLen
);
_lastPacket
->
body_size
=
_lastPacket
->
buffer
.
size
();
}
}
void
H265RtmpEncoder
::
makeVideoConfigPkt
()
{
void
H265RtmpEncoder
::
makeVideoConfigPkt
()
{
...
@@ -218,7 +215,6 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
...
@@ -218,7 +215,6 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
int8_t
flags
=
FLV_CODEC_H265
;
int8_t
flags
=
FLV_CODEC_H265
;
flags
|=
(
FLV_KEY_FRAME
<<
4
);
flags
|=
(
FLV_KEY_FRAME
<<
4
);
bool
is_config
=
true
;
bool
is_config
=
true
;
auto
rtmpPkt
=
RtmpPacket
::
create
();
auto
rtmpPkt
=
RtmpPacket
::
create
();
//header
//header
rtmpPkt
->
buffer
.
push_back
(
flags
);
rtmpPkt
->
buffer
.
push_back
(
flags
);
...
@@ -237,10 +233,8 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
...
@@ -237,10 +233,8 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
WarnL
<<
"生成H265 extra_data 失败"
;
WarnL
<<
"生成H265 extra_data 失败"
;
return
;
return
;
}
}
//HEVCDecoderConfigurationRecord
//HEVCDecoderConfigurationRecord
rtmpPkt
->
buffer
.
append
((
char
*
)
extra_data
,
extra_data_size
);
rtmpPkt
->
buffer
.
append
((
char
*
)
extra_data
,
extra_data_size
);
rtmpPkt
->
body_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
body_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
chunk_id
=
CHUNK_VIDEO
;
rtmpPkt
->
chunk_id
=
CHUNK_VIDEO
;
rtmpPkt
->
stream_index
=
STREAM_MEDIA
;
rtmpPkt
->
stream_index
=
STREAM_MEDIA
;
...
...
src/Extension/H265Rtmp.h
查看文件 @
8f730b8d
...
@@ -78,13 +78,13 @@ private:
...
@@ -78,13 +78,13 @@ private:
void
makeVideoConfigPkt
();
void
makeVideoConfigPkt
();
private
:
private
:
bool
_gotSpsPps
=
false
;
bool
_has_vcl
=
false
;
bool
_got_config_frame
=
false
;
string
_vps
;
string
_vps
;
string
_sps
;
string
_sps
;
string
_pps
;
string
_pps
;
H265Track
::
Ptr
_track
;
H265Track
::
Ptr
_track
;
RtmpPacket
::
Ptr
_lastPacket
;
RtmpPacket
::
Ptr
_rtmp_packet
;
bool
_lastPacketHasVCL
=
false
;
};
};
}
//namespace mediakit
}
//namespace mediakit
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论