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
dad01750
Commit
dad01750
authored
Jan 14, 2020
by
Luke
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into research
parents
2d9537ec
491ed6f8
隐藏空白字符变更
内嵌
并排
正在显示
31 个修改的文件
包含
331 行增加
和
173 行删除
+331
-173
README.md
+19
-0
api/include/mk_media.h
+2
-2
conf/config.ini
+0
-2
server/WebHook.cpp
+1
-1
src/Common/Device.cpp
+16
-2
src/Common/MediaSink.cpp
+50
-30
src/Common/MediaSink.h
+2
-1
src/Common/Stamp.cpp
+62
-3
src/Common/Stamp.h
+23
-1
src/Common/config.cpp
+0
-2
src/Common/config.h
+0
-2
src/Extension/AAC.h
+0
-1
src/Extension/AACRtmp.cpp
+1
-1
src/Extension/AACRtp.cpp
+1
-2
src/Extension/Frame.h
+0
-7
src/Extension/H264.h
+20
-19
src/Extension/H264Rtmp.cpp
+13
-9
src/Extension/H264Rtp.cpp
+23
-19
src/Extension/H264Rtp.h
+2
-0
src/Extension/H265.h
+23
-23
src/Extension/H265Rtp.cpp
+21
-17
src/Extension/H265Rtp.h
+2
-0
src/Http/WebSocketClient.h
+1
-1
src/Player/PlayerProxy.cpp
+14
-4
src/Record/MP4Reader.cpp
+7
-5
src/Rtmp/RtmpMediaSource.h
+6
-5
src/Rtmp/RtmpPlayerImp.h
+6
-0
src/Rtmp/RtmpProtocol.cpp
+5
-5
src/Rtmp/RtmpSession.cpp
+10
-3
src/Rtmp/RtmpSession.h
+1
-0
src/Rtsp/RtspSession.cpp
+0
-6
没有找到文件。
README.md
查看文件 @
dad01750
...
...
@@ -376,6 +376,25 @@ git submodule update --init
-
2、如果您的问题还没解决,可以提issue.
-
3、有些问题,如果不具备参考性的,无需在issue提的,可以在qq群提.
-
4、QQ私聊一般不接受无偿技术咨询和支持(谈谈人生理想还是可以的😂),毕竟精力有限,谢谢理解.
## 致谢
感谢以下各位对本项目包括但不限于代码贡献、问题反馈、资金捐赠等各种方式的支持!以下排名不分先后:
[
老陈
](
https://github.com/ireader
)
[
Gemfield
](
https://github.com/gemfield
)
[
南冠彤
](
https://github.com/nanguantong2
)
[
凹凸慢
](
https://github.com/tsingeye
)
[
chenxiaolei
](
https://github.com/chenxiaolei
)
[
史前小虫
](
https://github.com/zqsong
)
[
清涩绿茶
](
https://github.com/baiyfcu
)
[
3503207480
](
https://github.com/3503207480
)
[
DroidChow
](
https://github.com/DroidChow
)
[
阿塞
](
https://github.com/HuoQiShuai
)
[
火宣
](
https://github.com/ChinaCCF
)
[
γ瑞γミ
](
https://github.com/JerryLinGd
)
[
linkingvision
](
https://www.linkingvision.com/
)
[
茄子
](
https://github.com/taotaobujue2008
)
[
好心情
](
<
409257224@qq.com
>
)
## 捐赠
欢迎捐赠以便更好的推动项目的发展,谢谢您的支持!
...
...
api/include/mk_media.h
查看文件 @
dad01750
...
...
@@ -87,7 +87,7 @@ API_EXPORT void API_CALL mk_media_init_aac(mk_media ctx, int channel, int sample
* @param data 单帧H264数据
* @param len 单帧H264数据字节数
* @param dts 解码时间戳,单位毫秒
* @param
d
ts 播放时间戳,单位毫秒
* @param
p
ts 播放时间戳,单位毫秒
*/
API_EXPORT
void
API_CALL
mk_media_input_h264
(
mk_media
ctx
,
void
*
data
,
int
len
,
uint32_t
dts
,
uint32_t
pts
);
...
...
@@ -97,7 +97,7 @@ API_EXPORT void API_CALL mk_media_input_h264(mk_media ctx, void *data, int len,
* @param data 单帧H265数据
* @param len 单帧H265数据字节数
* @param dts 解码时间戳,单位毫秒
* @param
d
ts 播放时间戳,单位毫秒
* @param
p
ts 播放时间戳,单位毫秒
*/
API_EXPORT
void
API_CALL
mk_media_input_h265
(
mk_media
ctx
,
void
*
data
,
int
len
,
uint32_t
dts
,
uint32_t
pts
);
...
...
conf/config.ini
查看文件 @
dad01750
...
...
@@ -191,8 +191,6 @@ keepAliveSecond=15
port
=
554
#rtsps服务器监听地址
sslport
=
322
#在接收rtsp推流时,是否重新生成时间戳(很多推流器的时间戳着实很烂)
modifyStamp
=
0
[shell]
#调试telnet服务器接受最大bufffer大小
...
...
server/WebHook.cpp
查看文件 @
dad01750
...
...
@@ -438,7 +438,7 @@ void installWebHook(){
//如果没有url参数,客户端又不支持cookie,那么会根据ip和端口追踪用户
//追踪用户的目的是为了缓存上次鉴权结果,减少鉴权次数,提高性能
NoticeCenter
::
Instance
().
addListener
(
nullptr
,
Broadcast
::
kBroadcastHttpAccess
,[](
BroadcastHttpAccessArgs
){
if
(
sender
.
get_peer_ip
()
==
"127.0.0.1"
&&
parser
.
Params
()
==
hook_adminparams
){
if
(
sender
.
get_peer_ip
()
==
"127.0.0.1"
||
parser
.
Params
()
==
hook_adminparams
){
//如果是本机或超级管理员访问,那么不做访问鉴权;权限有效期1个小时
invoker
(
""
,
""
,
60
*
60
);
return
;
...
...
src/Common/Device.cpp
查看文件 @
dad01750
...
...
@@ -104,7 +104,14 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32
}
else
{
prefixeSize
=
0
;
}
inputFrame
(
std
::
make_shared
<
H264FrameNoCacheAble
>
((
char
*
)
pcData
,
iDataLen
,
dts
,
pts
,
prefixeSize
));
H264Frame
::
Ptr
frame
=
std
::
make_shared
<
H264Frame
>
();
frame
->
_dts
=
dts
;
frame
->
_pts
=
pts
;
frame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
frame
->
_buffer
.
append
(
pcData
+
prefixeSize
,
iDataLen
-
prefixeSize
);
frame
->
_prefix_size
=
4
;
inputFrame
(
frame
);
}
void
DevChannel
::
inputH265
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
dts
,
uint32_t
pts
)
{
...
...
@@ -122,7 +129,14 @@ void DevChannel::inputH265(const char* pcData, int iDataLen, uint32_t dts,uint32
}
else
{
prefixeSize
=
0
;
}
inputFrame
(
std
::
make_shared
<
H265FrameNoCacheAble
>
((
char
*
)
pcData
,
iDataLen
,
dts
,
pts
,
prefixeSize
));
H265Frame
::
Ptr
frame
=
std
::
make_shared
<
H265Frame
>
();
frame
->
_dts
=
dts
;
frame
->
_pts
=
pts
;
frame
->
_buffer
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
frame
->
_buffer
.
append
(
pcData
+
prefixeSize
,
iDataLen
-
prefixeSize
);
frame
->
_prefix_size
=
4
;
inputFrame
(
frame
);
}
void
DevChannel
::
inputAAC
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
,
bool
withAdtsHeader
)
{
...
...
src/Common/MediaSink.cpp
查看文件 @
dad01750
...
...
@@ -26,7 +26,11 @@
#include "MediaSink.h"
//最多等待未初始化的Track 10秒,超时之后会忽略未初始化的Track
#define MAX_WAIT_MS 10000
#define MAX_WAIT_MS_READY 10000
//如果添加Track,最多等待3秒
#define MAX_WAIT_MS_ADD_TRACK 3000
namespace
mediakit
{
...
...
@@ -34,23 +38,16 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
//克隆Track,只拷贝其数据,不拷贝其数据转发关系
auto
track
=
track_in
->
clone
();
auto
codec_id
=
track
->
getCodecId
();
_track_map
[
codec_id
]
=
track
;
auto
lam
=
[
this
,
track
](){
_allTrackReady
=
false
;
_trackReadyCallback
[
codec_id
]
=
[
this
,
track
]()
{
onTrackReady
(
track
);
};
if
(
track
->
ready
()){
lam
();
}
else
{
_anyTrackUnReady
=
true
;
_allTrackReady
=
false
;
_trackReadyCallback
[
codec_id
]
=
lam
;
_ticker
.
resetTime
();
}
_ticker
.
resetTime
();
track
->
addDelegate
(
std
::
make_shared
<
FrameWriterInterfaceHelper
>
([
this
](
const
Frame
::
Ptr
&
frame
){
if
(
!
_anyTrackUnReady
)
{
track
->
addDelegate
(
std
::
make_shared
<
FrameWriterInterfaceHelper
>
([
this
](
const
Frame
::
Ptr
&
frame
)
{
if
(
_allTrackReady
)
{
onTrackFrame
(
frame
);
}
}));
...
...
@@ -58,7 +55,6 @@ void MediaSink::addTrack(const Track::Ptr &track_in) {
void
MediaSink
::
resetTracks
()
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
_anyTrackUnReady
=
false
;
_allTrackReady
=
false
;
_track_map
.
clear
();
_trackReadyCallback
.
clear
();
...
...
@@ -83,26 +79,50 @@ void MediaSink::inputFrame(const Frame::Ptr &frame) {
}
}
if
(
!
_allTrackReady
&&
(
_trackReadyCallback
.
empty
()
||
_ticker
.
elapsedTime
()
>
MAX_WAIT_MS
)){
_allTrackReady
=
true
;
_anyTrackUnReady
=
false
;
if
(
!
_allTrackReady
){
if
(
_ticker
.
elapsedTime
()
>
MAX_WAIT_MS_READY
){
//如果超过规定时间,那么不再等待并忽略未准备好的Track
emitAllTrackReady
();
return
;
}
if
(
!
_trackReadyCallback
.
empty
()){
//这是超时强制忽略未准备好的Track
_trackReadyCallback
.
clear
();
//移除未准备好的Track
for
(
auto
it
=
_track_map
.
begin
()
;
it
!=
_track_map
.
end
()
;
){
if
(
!
it
->
second
->
ready
()){
it
=
_track_map
.
erase
(
it
);
continue
;
}
++
it
;
}
//在超时时间内,如果存在未准备好的Track,那么继续等待
return
;
}
if
(
!
_track_map
.
empty
()){
//最少有一个有效的Track
onAllTrackReady
();
if
(
_track_map
.
size
()
==
2
){
//如果已经添加了音视频Track,并且不存在未准备好的Track,那么说明所有Track都准备好了
emitAllTrackReady
();
return
;
}
if
(
_track_map
.
size
()
==
1
&&
_ticker
.
elapsedTime
()
>
MAX_WAIT_MS_ADD_TRACK
){
//如果只有一个Track,那么在该Track添加后,我们最多还等待若干时间(可能后面还会添加Track)
emitAllTrackReady
();
return
;
}
}
}
void
MediaSink
::
emitAllTrackReady
()
{
_allTrackReady
=
true
;
if
(
!
_trackReadyCallback
.
empty
()){
//这是超时强制忽略未准备好的Track
_trackReadyCallback
.
clear
();
//移除未准备好的Track
for
(
auto
it
=
_track_map
.
begin
()
;
it
!=
_track_map
.
end
()
;
){
if
(
!
it
->
second
->
ready
()){
it
=
_track_map
.
erase
(
it
);
continue
;
}
++
it
;
}
}
if
(
!
_track_map
.
empty
()){
//最少有一个有效的Track
onAllTrackReady
();
}
}
...
...
src/Common/MediaSink.h
查看文件 @
dad01750
...
...
@@ -110,11 +110,12 @@ protected:
*/
virtual
void
onTrackFrame
(
const
Frame
::
Ptr
&
frame
)
{};
private
:
void
emitAllTrackReady
();
private
:
mutable
recursive_mutex
_mtx
;
map
<
int
,
Track
::
Ptr
>
_track_map
;
map
<
int
,
function
<
void
()
>
>
_trackReadyCallback
;
bool
_allTrackReady
=
false
;
bool
_anyTrackUnReady
=
false
;
Ticker
_ticker
;
};
...
...
src/Common/Stamp.cpp
查看文件 @
dad01750
...
...
@@ -26,14 +26,18 @@
#include "Stamp.h"
#define MAX_DELTA_STAMP 300
#define MAX_DELTA_STAMP 1000
#define MAX_CTS 500
#define ABS(x) ((x) > 0 ? (x) : (-x))
namespace
mediakit
{
int64_t
DeltaStamp
::
deltaStamp
(
int64_t
stamp
)
{
if
(
!
_last_stamp
){
//第一次计算时间戳增量,时间戳增量为0
_last_stamp
=
stamp
;
if
(
stamp
){
_last_stamp
=
stamp
;
}
return
0
;
}
...
...
@@ -75,7 +79,7 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,
dts_out
=
_relativeStamp
;
//////////////以下是播放时间戳的计算//////////////////
if
(
pts_dts_diff
>
MAX_DELTA_STAMP
||
pts_dts_diff
<
-
MAX_DELTA_STAMP
){
if
(
ABS
(
pts_dts_diff
)
>
MAX_CTS
){
//如果差值太大,则认为由于回环导致时间戳错乱了
pts_dts_diff
=
0
;
}
...
...
@@ -96,4 +100,58 @@ int64_t Stamp::getRelativeStamp() const {
}
bool
DtsGenerator
::
getDts
(
uint32_t
pts
,
uint32_t
&
dts
){
bool
ret
=
false
;
if
(
pts
==
_last_pts
){
//pts未变,返回上次结果
if
(
_last_dts
){
dts
=
_last_dts
;
ret
=
true
;
}
return
ret
;
}
ret
=
getDts_l
(
pts
,
dts
);
if
(
ret
){
//保存本次结果
_last_dts
=
dts
;
}
//记录上次pts
_last_pts
=
pts
;
return
ret
;
}
bool
DtsGenerator
::
getDts_l
(
uint32_t
pts
,
uint32_t
&
dts
){
if
(
_sorter_max_size
==
1
){
//没有B帧
dts
=
pts
;
return
true
;
}
if
(
!
_sorter_max_size
){
if
(
pts
>
_last_max_pts
){
if
(
_frames_since_last_max_pts
&&
_count_sorter_max_size
++
>
0
){
_sorter_max_size
=
_frames_since_last_max_pts
;
_dts_pts_offset
=
(
pts
-
_last_max_pts
)
/
2
;
}
_frames_since_last_max_pts
=
0
;
_last_max_pts
=
pts
;
}
++
_frames_since_last_max_pts
;
}
_pts_sorter
.
emplace
(
pts
);
if
(
_sorter_max_size
&&
_pts_sorter
.
size
()
>
_sorter_max_size
){
auto
it
=
_pts_sorter
.
begin
();
dts
=
*
it
+
_dts_pts_offset
;
if
(
dts
>
pts
){
//dts不能大于pts(基本不可能到达这个逻辑)
dts
=
pts
;
}
_pts_sorter
.
erase
(
it
);
return
true
;
}
return
false
;
}
}
//
namespace
mediakit
\ No newline at end of file
src/Common/Stamp.h
查看文件 @
dad01750
...
...
@@ -27,8 +27,9 @@
#ifndef ZLMEDIAKIT_STAMP_H
#define ZLMEDIAKIT_STAMP_H
#include
"Util/TimeTicker.h"
#include
<set>
#include <cstdint>
#include "Util/TimeTicker.h"
using
namespace
toolkit
;
namespace
mediakit
{
...
...
@@ -88,6 +89,27 @@ private:
SmoothTicker
_ticker
;
};
class
DtsGenerator
{
public
:
DtsGenerator
()
=
default
;
~
DtsGenerator
()
=
default
;
bool
getDts
(
uint32_t
pts
,
uint32_t
&
dts
);
private
:
bool
getDts_l
(
uint32_t
pts
,
uint32_t
&
dts
);
private
:
uint32_t
_dts_pts_offset
=
0
;
uint32_t
_last_dts
=
0
;
uint32_t
_last_pts
=
0
;
uint32_t
_last_max_pts
=
0
;
int
_frames_since_last_max_pts
=
0
;
int
_sorter_max_size
=
0
;
int
_count_sorter_max_size
=
0
;
set
<
uint32_t
>
_pts_sorter
;
};
}
//namespace mediakit
#endif //ZLMEDIAKIT_STAMP_H
src/Common/config.cpp
查看文件 @
dad01750
...
...
@@ -158,7 +158,6 @@ const string kAuthBasic = RTSP_FIELD"authBasic";
const
string
kHandshakeSecond
=
RTSP_FIELD
"handshakeSecond"
;
const
string
kKeepAliveSecond
=
RTSP_FIELD
"keepAliveSecond"
;
const
string
kDirectProxy
=
RTSP_FIELD
"directProxy"
;
const
string
kModifyStamp
=
RTSP_FIELD
"modifyStamp"
;
onceToken
token
([](){
//默认Md5方式认证
...
...
@@ -166,7 +165,6 @@ onceToken token([](){
mINI
::
Instance
()[
kHandshakeSecond
]
=
15
;
mINI
::
Instance
()[
kKeepAliveSecond
]
=
15
;
mINI
::
Instance
()[
kDirectProxy
]
=
1
;
mINI
::
Instance
()[
kModifyStamp
]
=
false
;
},
nullptr
);
}
//namespace Rtsp
...
...
src/Common/config.h
查看文件 @
dad01750
...
...
@@ -232,8 +232,6 @@ extern const string kKeepAliveSecond;
//假定您的拉流源地址不是264或265或AAC,那么你可以使用直接代理的方式来支持rtsp代理
//默认开启rtsp直接代理,rtmp由于没有这些问题,是强制开启直接代理的
extern
const
string
kDirectProxy
;
//rtsp推流是否修改时间戳
extern
const
string
kModifyStamp
;
}
//namespace Rtsp
////////////RTMP服务器配置///////////
...
...
src/Extension/AAC.h
查看文件 @
dad01750
...
...
@@ -104,7 +104,6 @@ public:
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
unsigned
int
no_raw_data_blocks_in_frame
;
//2 uimsfb
unsigned
char
buffer
[
2
*
1024
+
7
];
uint16_t
sequence
;
uint32_t
timeStamp
;
uint32_t
iPrefixSize
=
7
;
}
;
...
...
src/Extension/AACRtmp.cpp
查看文件 @
dad01750
...
...
@@ -102,7 +102,7 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
rtmpPkt
->
bodySize
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
chunkId
=
CHUNK_AUDIO
;
rtmpPkt
->
streamId
=
STREAM_MEDIA
;
rtmpPkt
->
timeStamp
=
frame
->
stamp
();
rtmpPkt
->
timeStamp
=
frame
->
dts
();
rtmpPkt
->
typeId
=
MSG_AUDIO
;
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
}
...
...
src/Extension/AACRtp.cpp
查看文件 @
dad01750
...
...
@@ -41,7 +41,7 @@ AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc,
void
AACRtpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
GET_CONFIG
(
uint32_t
,
cycleMS
,
Rtp
::
kCycleMS
);
auto
uiStamp
=
frame
->
stamp
();
auto
uiStamp
=
frame
->
dts
();
auto
pcData
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
...
...
@@ -149,7 +149,6 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
memcpy
(
_adts
->
buffer
+
_adts
->
aac_frame_length
,
rtp_packet_payload
+
next_aac_payload_offset
,
cur_aac_payload_len
);
_adts
->
aac_frame_length
+=
(
cur_aac_payload_len
);
if
(
rtppack
->
mark
==
true
)
{
_adts
->
sequence
=
rtppack
->
sequence
;
_adts
->
timeStamp
=
rtppack
->
timeStamp
;
writeAdtsHeader
(
*
_adts
,
_adts
->
buffer
);
onGetAAC
(
_adts
);
...
...
src/Extension/Frame.h
查看文件 @
dad01750
...
...
@@ -81,13 +81,6 @@ class Frame : public Buffer, public CodecInfo {
public
:
typedef
std
::
shared_ptr
<
Frame
>
Ptr
;
virtual
~
Frame
(){}
/**
* 时间戳,已经废弃,请使用dts() 、pts()接口
*/
inline
uint32_t
stamp
()
const
{
return
dts
();
};
/**
* 返回解码时间戳,单位毫秒
...
...
src/Extension/H264.h
查看文件 @
dad01750
...
...
@@ -49,24 +49,25 @@ public:
NAL_SPS
=
7
,
NAL_PPS
=
8
,
NAL_IDR
=
5
,
NAL_SEI
=
6
,
}
NalType
;
char
*
data
()
const
override
{
return
(
char
*
)
buffer
.
data
();
return
(
char
*
)
_
buffer
.
data
();
}
uint32_t
size
()
const
override
{
return
buffer
.
size
();
return
_
buffer
.
size
();
}
uint32_t
dts
()
const
override
{
return
timeStamp
;
return
_dts
;
}
uint32_t
pts
()
const
override
{
return
ptsStamp
?
ptsStamp
:
timeStamp
;
return
_pts
?
_pts
:
_dts
;
}
uint32_t
prefixSize
()
const
override
{
return
iPrefixS
ize
;
return
_prefix_s
ize
;
}
TrackType
getTrackType
()
const
override
{
...
...
@@ -78,11 +79,11 @@ public:
}
bool
keyFrame
()
const
override
{
return
H264_TYPE
(
buffer
[
iPrefixS
ize
])
==
H264Frame
::
NAL_IDR
;
return
H264_TYPE
(
_buffer
[
_prefix_s
ize
])
==
H264Frame
::
NAL_IDR
;
}
bool
configFrame
()
const
override
{
switch
(
H264_TYPE
(
buffer
[
iPrefixS
ize
])
){
switch
(
H264_TYPE
(
_buffer
[
_prefix_s
ize
])
){
case
H264Frame
:
:
NAL_SPS
:
case
H264Frame
:
:
NAL_PPS
:
return
true
;
...
...
@@ -91,10 +92,10 @@ public:
}
}
public
:
uint32_t
timeStamp
;
uint32_t
ptsStamp
=
0
;
string
buffer
;
uint32_t
iPrefixSize
=
4
;
uint32_t
_dts
=
0
;
uint32_t
_pts
=
0
;
uint32_t
_prefix_size
=
4
;
string
_buffer
;
};
...
...
@@ -339,19 +340,19 @@ private:
if
(
!
_sps
.
empty
()){
auto
spsFrame
=
std
::
make_shared
<
H264Frame
>
();
spsFrame
->
iPrefixS
ize
=
4
;
spsFrame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
spsFrame
->
buffer
.
append
(
_sps
);
spsFrame
->
timeStamp
=
frame
->
stamp
();
spsFrame
->
_prefix_s
ize
=
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
->
iPrefixS
ize
=
4
;
ppsFrame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
buffer
.
append
(
_pps
);
ppsFrame
->
timeStamp
=
frame
->
stamp
();
ppsFrame
->
_prefix_s
ize
=
4
;
ppsFrame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
_
buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
...
...
src/Extension/H264Rtmp.cpp
查看文件 @
dad01750
...
...
@@ -35,8 +35,8 @@ H264RtmpDecoder::H264RtmpDecoder() {
H264Frame
::
Ptr
H264RtmpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
obtainObj
();
frame
->
buffer
.
clear
();
frame
->
iPrefixS
ize
=
4
;
frame
->
_
buffer
.
clear
();
frame
->
_prefix_s
ize
=
4
;
return
frame
;
}
...
...
@@ -78,10 +78,10 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
inline
void
H264RtmpDecoder
::
onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
dts
,
uint32_t
pts
)
{
#if 1
_h264frame
->
timeStamp
=
dts
;
_h264frame
->
ptsStamp
=
pts
;
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
_h264frame
->
buffer
.
append
(
pcData
,
iLen
);
_h264frame
->
_dts
=
dts
;
_h264frame
->
_pts
=
pts
;
_h264frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
_h264frame
->
_
buffer
.
append
(
pcData
,
iLen
);
//写入环形缓存
RtmpCodec
::
inputFrame
(
_h264frame
);
...
...
@@ -140,7 +140,11 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
}
}
if
(
_lastPacket
&&
_lastPacket
->
timeStamp
!=
frame
->
stamp
())
{
if
(
type
==
H264Frame
::
NAL_SEI
){
return
;
}
if
(
_lastPacket
&&
_lastPacket
->
timeStamp
!=
frame
->
dts
())
{
RtmpCodec
::
inputRtmp
(
_lastPacket
,
_lastPacket
->
isVideoKeyFrame
());
_lastPacket
=
nullptr
;
}
...
...
@@ -149,7 +153,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
//I or P or B frame
int8_t
flags
=
7
;
//h.264
bool
is_config
=
false
;
flags
|=
((
frame
->
keyFrame
(
)
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
flags
|=
((
(
frame
->
configFrame
()
||
frame
->
keyFrame
()
)
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
_lastPacket
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
_lastPacket
->
strBuf
.
clear
();
...
...
@@ -161,7 +165,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
_lastPacket
->
chunkId
=
CHUNK_VIDEO
;
_lastPacket
->
streamId
=
STREAM_MEDIA
;
_lastPacket
->
timeStamp
=
frame
->
stamp
();
_lastPacket
->
timeStamp
=
frame
->
dts
();
_lastPacket
->
typeId
=
MSG_VIDEO
;
}
...
...
src/Extension/H264Rtp.cpp
查看文件 @
dad01750
...
...
@@ -70,8 +70,8 @@ H264RtpDecoder::H264RtpDecoder() {
H264Frame
::
Ptr
H264RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H264Frame
>::
obtainObj
();
frame
->
buffer
.
clear
();
frame
->
iPrefixS
ize
=
4
;
frame
->
_
buffer
.
clear
();
frame
->
_prefix_s
ize
=
4
;
return
frame
;
}
...
...
@@ -113,9 +113,9 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
nal
.
type
>=
0
&&
nal
.
type
<
24
)
{
//a full frame
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
,
length
);
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h264frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
_
buffer
.
append
((
char
*
)
frame
,
length
);
_h264frame
->
_pts
=
rtppack
->
timeStamp
;
auto
key
=
_h264frame
->
keyFrame
();
onGetH264
(
_h264frame
);
return
(
key
);
//i frame
...
...
@@ -142,9 +142,9 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
//过小的帧丢弃
NALU
nal
;
MakeNalu
(
ptr
[
0
],
nal
);
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
buffer
.
append
((
char
*
)
ptr
,
len
);
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h264frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
_
buffer
.
append
((
char
*
)
ptr
,
len
);
_h264frame
->
_pts
=
rtppack
->
timeStamp
;
if
(
nal
.
type
==
H264Frame
::
NAL_IDR
){
haveIDR
=
true
;
}
...
...
@@ -162,10 +162,10 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
fu
.
S
)
{
//该帧的第一个rtp包 FU-A start
char
tmp
=
(
nal
.
forbidden_zero_bit
<<
7
|
nal
.
nal_ref_idc
<<
5
|
fu
.
type
);
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
buffer
.
push_back
(
tmp
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h264frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
_
buffer
.
push_back
(
tmp
);
_h264frame
->
_
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
_pts
=
rtppack
->
timeStamp
;
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
_lastSeq
=
rtppack
->
sequence
;
return
_h264frame
->
keyFrame
();
...
...
@@ -173,22 +173,22 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
rtppack
->
sequence
!=
_lastSeq
+
1
&&
rtppack
->
sequence
!=
0
)
{
//中间的或末尾的rtp包,其seq必须连续(如果回环了则判定为连续),否则说明rtp丢包,那么该帧不完整,必须得丢弃
_h264frame
->
buffer
.
clear
();
_h264frame
->
_
buffer
.
clear
();
WarnL
<<
"rtp sequence不连续: "
<<
rtppack
->
sequence
<<
" != "
<<
_lastSeq
<<
" + 1,该帧被废弃"
;
return
false
;
}
if
(
!
fu
.
E
)
{
//该帧的中间rtp包 FU-A mid
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
_
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
_lastSeq
=
rtppack
->
sequence
;
return
false
;
}
//该帧最后一个rtp包 FU-A end
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h264frame
->
_
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
_pts
=
rtppack
->
timeStamp
;
auto
key
=
_h264frame
->
keyFrame
();
onGetH264
(
_h264frame
);
return
key
;
...
...
@@ -209,8 +209,12 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
}
void
H264RtpDecoder
::
onGetH264
(
const
H264Frame
::
Ptr
&
frame
)
{
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
//根据pts计算dts
auto
flag
=
_dts_generator
.
getDts
(
frame
->
_pts
,
frame
->
_dts
);
if
(
flag
){
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
}
_h264frame
=
obtainFrame
();
}
...
...
@@ -232,7 +236,7 @@ H264RtpEncoder::H264RtpEncoder(uint32_t ui32Ssrc,
void
H264RtpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
GET_CONFIG
(
uint32_t
,
cycleMS
,
Rtp
::
kCycleMS
);
auto
pcData
=
frame
->
data
()
+
frame
->
prefixSize
();
auto
uiStamp
=
frame
->
stamp
();
auto
uiStamp
=
frame
->
pts
();
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
//获取NALU的5bit 帧类型
unsigned
char
naluType
=
H264_TYPE
(
pcData
[
0
]);
...
...
src/Extension/H264Rtp.h
查看文件 @
dad01750
...
...
@@ -30,6 +30,7 @@
#include "Rtsp/RtpCodec.h"
#include "Util/ResourcePool.h"
#include "Extension/H264.h"
#include "Common/Stamp.h"
using
namespace
toolkit
;
namespace
mediakit
{
...
...
@@ -66,6 +67,7 @@ private:
H264Frame
::
Ptr
obtainFrame
();
private
:
H264Frame
::
Ptr
_h264frame
;
DtsGenerator
_dts_generator
;
int
_lastSeq
=
0
;
};
...
...
src/Extension/H265.h
查看文件 @
dad01750
...
...
@@ -74,23 +74,23 @@ public:
}
NaleType
;
char
*
data
()
const
override
{
return
(
char
*
)
buffer
.
data
();
return
(
char
*
)
_
buffer
.
data
();
}
uint32_t
size
()
const
override
{
return
buffer
.
size
();
return
_
buffer
.
size
();
}
uint32_t
dts
()
const
override
{
return
timeStamp
;
return
_dts
;
}
uint32_t
pts
()
const
override
{
return
ptsStamp
?
ptsStamp
:
timeStamp
;
return
_pts
?
_pts
:
_dts
;
}
uint32_t
prefixSize
()
const
override
{
return
iPrefixS
ize
;
return
_prefix_s
ize
;
}
TrackType
getTrackType
()
const
override
{
...
...
@@ -102,11 +102,11 @@ public:
}
bool
keyFrame
()
const
override
{
return
isKeyFrame
(
H265_TYPE
(
buffer
[
iPrefixS
ize
]));
return
isKeyFrame
(
H265_TYPE
(
_buffer
[
_prefix_s
ize
]));
}
bool
configFrame
()
const
override
{
switch
(
H265_TYPE
(
buffer
[
iPrefixS
ize
])){
switch
(
H265_TYPE
(
_buffer
[
_prefix_s
ize
])){
case
H265Frame
:
:
NAL_VPS
:
case
H265Frame
:
:
NAL_SPS
:
case
H265Frame
:
:
NAL_PPS
:
...
...
@@ -131,10 +131,10 @@ public:
}
public
:
uint32_t
timeStamp
;
uint32_t
ptsStamp
=
0
;
string
buffer
;
uint32_t
iPrefixSize
=
4
;
uint32_t
_dts
=
0
;
uint32_t
_pts
=
0
;
uint32_t
_prefix_size
=
4
;
string
_buffer
;
};
...
...
@@ -356,27 +356,27 @@ private:
}
if
(
!
_vps
.
empty
()){
auto
vpsFrame
=
std
::
make_shared
<
H265Frame
>
();
vpsFrame
->
iPrefixS
ize
=
4
;
vpsFrame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
vpsFrame
->
buffer
.
append
(
_vps
);
vpsFrame
->
timeStamp
=
frame
->
stamp
();
vpsFrame
->
_prefix_s
ize
=
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
->
iPrefixS
ize
=
4
;
spsFrame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
spsFrame
->
buffer
.
append
(
_sps
);
spsFrame
->
timeStamp
=
frame
->
stamp
();
spsFrame
->
_prefix_s
ize
=
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
<
H265Frame
>
();
ppsFrame
->
iPrefixS
ize
=
4
;
ppsFrame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
buffer
.
append
(
_pps
);
ppsFrame
->
timeStamp
=
frame
->
stamp
();
ppsFrame
->
_prefix_s
ize
=
4
;
ppsFrame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
ppsFrame
->
_
buffer
.
append
(
_pps
);
ppsFrame
->
_dts
=
frame
->
dts
();
VideoTrack
::
inputFrame
(
ppsFrame
);
}
}
...
...
src/Extension/H265Rtp.cpp
查看文件 @
dad01750
...
...
@@ -70,8 +70,8 @@ H265RtpDecoder::H265RtpDecoder() {
H265Frame
::
Ptr
H265RtpDecoder
::
obtainFrame
()
{
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto
frame
=
ResourcePoolHelper
<
H265Frame
>::
obtainObj
();
frame
->
buffer
.
clear
();
frame
->
iPrefixS
ize
=
4
;
frame
->
_
buffer
.
clear
();
frame
->
_prefix_s
ize
=
4
;
return
frame
;
}
...
...
@@ -99,11 +99,11 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
MakeFU
(
frame
[
2
],
fu
);
if
(
fu
.
S
)
{
//该帧的第一个rtp包
_h265frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h265frame
->
buffer
.
push_back
(
fu
.
type
<<
1
);
_h265frame
->
buffer
.
push_back
(
0x01
);
_h265frame
->
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
_h265frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h265frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h265frame
->
_
buffer
.
push_back
(
fu
.
type
<<
1
);
_h265frame
->
_
buffer
.
push_back
(
0x01
);
_h265frame
->
_
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
_h265frame
->
_pts
=
rtppack
->
timeStamp
;
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
_lastSeq
=
rtppack
->
sequence
;
return
(
_h265frame
->
keyFrame
());
//i frame
...
...
@@ -111,22 +111,22 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
rtppack
->
sequence
!=
_lastSeq
+
1
&&
rtppack
->
sequence
!=
0
)
{
//中间的或末尾的rtp包,其seq必须连续(如果回环了则判定为连续),否则说明rtp丢包,那么该帧不完整,必须得丢弃
_h265frame
->
buffer
.
clear
();
_h265frame
->
_
buffer
.
clear
();
WarnL
<<
"rtp sequence不连续: "
<<
rtppack
->
sequence
<<
" != "
<<
_lastSeq
<<
" + 1,该帧被废弃"
;
return
false
;
}
if
(
!
fu
.
E
)
{
//该帧的中间rtp包
_h265frame
->
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
_h265frame
->
_
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
//该函数return时,保存下当前sequence,以便下次对比seq是否连续
_lastSeq
=
rtppack
->
sequence
;
return
false
;
}
//该帧最后一个rtp包
_h265frame
->
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
_h265frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h265frame
->
_
buffer
.
append
((
char
*
)
frame
+
3
,
length
-
3
);
_h265frame
->
_pts
=
rtppack
->
timeStamp
;
auto
key
=
_h265frame
->
keyFrame
();
onGetH265
(
_h265frame
);
return
key
;
...
...
@@ -134,9 +134,9 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
default
:
// 4.4.1. Single NAL Unit Packets (p24)
//a full frame
_h265frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h265frame
->
buffer
.
append
((
char
*
)
frame
,
length
);
_h265frame
->
timeStamp
=
rtppack
->
timeStamp
;
_h265frame
->
_
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h265frame
->
_
buffer
.
append
((
char
*
)
frame
,
length
);
_h265frame
->
_pts
=
rtppack
->
timeStamp
;
auto
key
=
_h265frame
->
keyFrame
();
onGetH265
(
_h265frame
);
return
key
;
...
...
@@ -144,8 +144,12 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
}
void
H265RtpDecoder
::
onGetH265
(
const
H265Frame
::
Ptr
&
frame
)
{
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
//计算dts
auto
flag
=
_dts_generator
.
getDts
(
frame
->
_pts
,
frame
->
_dts
);
if
(
flag
){
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
}
_h265frame
=
obtainFrame
();
}
...
...
@@ -167,7 +171,7 @@ H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc,
void
H265RtpEncoder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
GET_CONFIG
(
uint32_t
,
cycleMS
,
Rtp
::
kCycleMS
);
uint8_t
*
pcData
=
(
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
();
auto
uiStamp
=
frame
->
stamp
();
auto
uiStamp
=
frame
->
pts
();
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
unsigned
char
naluType
=
H265_TYPE
(
pcData
[
0
]);
//获取NALU的5bit 帧类型
uiStamp
%=
cycleMS
;
...
...
src/Extension/H265Rtp.h
查看文件 @
dad01750
...
...
@@ -30,6 +30,7 @@
#include "Rtsp/RtpCodec.h"
#include "Util/ResourcePool.h"
#include "Extension/H265.h"
#include "Common/Stamp.h"
using
namespace
toolkit
;
...
...
@@ -67,6 +68,7 @@ private:
H265Frame
::
Ptr
obtainFrame
();
private
:
H265Frame
::
Ptr
_h265frame
;
DtsGenerator
_dts_generator
;
int
_lastSeq
=
0
;
};
...
...
src/Http/WebSocketClient.h
查看文件 @
dad01750
...
...
@@ -303,7 +303,7 @@ private:
//拦截websocket数据接收
_onRecv
=
[
this
](
const
Buffer
::
Ptr
&
pBuf
){
//解析websocket数据包
WebSocketSplitter
::
decode
((
uint8_t
*
)
pBuf
->
data
(),
pBuf
->
size
());
this
->
WebSocketSplitter
::
decode
((
uint8_t
*
)
pBuf
->
data
(),
pBuf
->
size
());
};
return
;
}
...
...
src/Player/PlayerProxy.cpp
查看文件 @
dad01750
...
...
@@ -219,16 +219,26 @@ public:
virtual
~
MuteAudioMaker
(){}
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
{
if
(
frame
->
getTrackType
()
==
TrackVideo
){
auto
iAudioIndex
=
frame
->
stamp
()
/
MUTE_ADTS_DATA_MS
;
auto
iAudioIndex
=
frame
->
dts
()
/
MUTE_ADTS_DATA_MS
;
if
(
_iAudioIndex
!=
iAudioIndex
){
_iAudioIndex
=
iAudioIndex
;
auto
aacFrame
=
std
::
make_shared
<
AACFrameNoCacheAble
>
((
char
*
)
MUTE_ADTS_DATA
,
MUTE_ADTS_DATA_LEN
,
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
auto
aacFrame
=
std
::
make_shared
<
AACFrameCacheAble
>
((
char
*
)
MUTE_ADTS_DATA
,
MUTE_ADTS_DATA_LEN
,
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
FrameDispatcher
::
inputFrame
(
aacFrame
);
}
}
}
private
:
class
AACFrameCacheAble
:
public
AACFrameNoCacheAble
{
public
:
template
<
typename
...
ARGS
>
AACFrameCacheAble
(
ARGS
&&
...
args
)
:
AACFrameNoCacheAble
(
std
::
forward
<
ARGS
>
(
args
)...){};
virtual
~
AACFrameCacheAble
()
=
default
;
bool
cacheAble
()
const
override
{
return
true
;
}
};
private
:
int
_iAudioIndex
=
0
;
};
...
...
src/Record/MP4Reader.cpp
查看文件 @
dad01750
...
...
@@ -225,8 +225,10 @@ inline bool MP4Reader::readVideoSample(int iTimeInc,bool justSeekSyncFrame) {
uint32_t
numBytes
=
_video_sample_max_size
;
MP4Duration
pRenderingOffset
;
if
(
MP4ReadSample
(
_hMP4File
,
_video_trId
,
iIdx
+
1
,
&
pBytes
,
&
numBytes
,
NULL
,
NULL
,
&
pRenderingOffset
,
&
_bSyncSample
)){
if
(
!
justSeekSyncFrame
)
{
uint32_t
iOffset
=
0
;
if
(
!
justSeekSyncFrame
)
{
uint32_t
dts
=
(
double
)
_video_ms
*
iIdx
/
_video_num_samples
;
uint32_t
pts
=
dts
+
pRenderingOffset
/
90
;
uint32_t
iOffset
=
0
;
while
(
iOffset
<
numBytes
)
{
uint32_t
iFrameLen
;
memcpy
(
&
iFrameLen
,
pBytes
+
iOffset
,
4
);
...
...
@@ -235,8 +237,7 @@ inline bool MP4Reader::readVideoSample(int iTimeInc,bool justSeekSyncFrame) {
break
;
}
memcpy
(
pBytes
+
iOffset
,
"\x0\x0\x0\x1"
,
4
);
uint32_t
dts
=
(
double
)
_video_ms
*
iIdx
/
_video_num_samples
;
writeH264
(
pBytes
+
iOffset
,
iFrameLen
+
4
,
dts
,
dts
+
pRenderingOffset
/
90
);
writeH264
(
pBytes
+
iOffset
,
iFrameLen
+
4
,
dts
,
pts
);
iOffset
+=
(
iFrameLen
+
4
);
}
}
else
if
(
_bSyncSample
){
...
...
@@ -260,9 +261,10 @@ inline bool MP4Reader::readAudioSample(int iTimeInc,bool justSeekSyncFrame) {
uint8_t
*
pBytes
=
_adts
.
buffer
+
7
;
if
(
MP4ReadSample
(
_hMP4File
,
_audio_trId
,
i
+
1
,
&
pBytes
,
&
numBytes
)){
if
(
!
justSeekSyncFrame
)
{
uint32_t
dts
=
(
double
)
_audio_ms
*
i
/
_audio_num_samples
;
_adts
.
aac_frame_length
=
7
+
numBytes
;
writeAdtsHeader
(
_adts
,
_adts
.
buffer
);
writeAAC
(
_adts
.
buffer
,
_adts
.
aac_frame_length
,
(
double
)
_audio_ms
*
i
/
_audio_num_sample
s
);
writeAAC
(
_adts
.
buffer
,
_adts
.
aac_frame_length
,
dt
s
);
}
}
else
{
ErrorL
<<
"读取音频失败:"
<<
i
+
1
;
...
...
src/Rtmp/RtmpMediaSource.h
查看文件 @
dad01750
...
...
@@ -72,7 +72,6 @@ public:
const
string
&
stream_id
,
int
ring_size
=
0
)
:
MediaSource
(
RTMP_SCHEMA
,
vhost
,
app
,
stream_id
),
_ring_size
(
ring_size
)
{
_metadata
=
TitleMeta
().
getMetadata
();
}
virtual
~
RtmpMediaSource
()
{}
...
...
@@ -117,6 +116,9 @@ public:
virtual
void
setMetaData
(
const
AMFValue
&
metadata
)
{
lock_guard
<
recursive_mutex
>
lock
(
_mtx
);
_metadata
=
metadata
;
if
(
_ring
){
regist
();
}
}
/**
...
...
@@ -143,10 +145,9 @@ public:
_ring
=
std
::
make_shared
<
RingType
>
(
_ring_size
,
std
::
move
(
lam
));
onReaderChanged
(
0
);
//如果输入了非config帧,
//那么说明不再可能获取config帧以及metadata,
//所以我们强制其为已注册
regist
();
if
(
_metadata
){
regist
();
}
}
_track_stamps_map
[
pkt
->
typeId
]
=
pkt
->
timeStamp
;
_ring
->
write
(
pkt
,
pkt
->
isVideoKeyFrame
());
...
...
src/Rtmp/RtmpPlayerImp.h
查看文件 @
dad01750
...
...
@@ -66,6 +66,7 @@ private:
_pRtmpMediaSrc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
);
if
(
_pRtmpMediaSrc
){
_pRtmpMediaSrc
->
setMetaData
(
val
);
_set_meta_data
=
true
;
}
_delegate
.
reset
(
new
RtmpDemuxer
);
_delegate
->
loadMetaData
(
val
);
...
...
@@ -73,6 +74,10 @@ private:
}
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
override
{
if
(
_pRtmpMediaSrc
){
if
(
!
_set_meta_data
&&
!
chunkData
->
isCfgFrame
()){
_set_meta_data
=
true
;
_pRtmpMediaSrc
->
setMetaData
(
TitleMeta
().
getMetadata
());
}
_pRtmpMediaSrc
->
onWrite
(
chunkData
);
}
if
(
!
_delegate
){
...
...
@@ -83,6 +88,7 @@ private:
}
private
:
RtmpMediaSource
::
Ptr
_pRtmpMediaSrc
;
bool
_set_meta_data
=
false
;
};
...
...
src/Rtmp/RtmpProtocol.cpp
查看文件 @
dad01750
...
...
@@ -332,7 +332,7 @@ void RtmpProtocol::handle_C0C1() {
//complex handsharke
handle_C1_complex
();
#else
WarnL
<<
"未打开ENABLE_OPENSSL宏,复杂握手采用简单方式处理!"
;
WarnL
<<
"未打开ENABLE_OPENSSL宏,复杂握手采用简单方式处理
,flash播放器可能无法播放
!"
;
handle_C1_simple
();
#endif//ENABLE_OPENSSL
}
...
...
@@ -372,10 +372,10 @@ void RtmpProtocol::handle_C1_complex(){
check_C1_Digest
(
digest
,
c1_joined
);
send_complex_S0S1S2
(
0
,
digest
);
InfoL
<<
"schema0"
;
//
InfoL << "schema0";
}
catch
(
std
::
exception
&
ex
){
//貌似flash从来都不用schema1
WarnL
<<
"try rtmp complex schema0 failed:"
<<
ex
.
what
();
//
WarnL << "try rtmp complex schema0 failed:" << ex.what();
try
{
/* c1s1 schema1
time: 4bytes
...
...
@@ -389,9 +389,9 @@ void RtmpProtocol::handle_C1_complex(){
check_C1_Digest
(
digest
,
c1_joined
);
send_complex_S0S1S2
(
1
,
digest
);
InfoL
<<
"schema1"
;
//
InfoL << "schema1";
}
catch
(
std
::
exception
&
ex
){
WarnL
<<
"try rtmp complex schema1 failed:"
<<
ex
.
what
();
//
WarnL << "try rtmp complex schema1 failed:" << ex.what();
handle_C1_simple
();
}
}
...
...
src/Rtmp/RtmpSession.cpp
查看文件 @
dad01750
...
...
@@ -434,6 +434,7 @@ void RtmpSession::setMetaData(AMFDecoder &dec) {
auto
metadata
=
dec
.
load
<
AMFValue
>
();
// dumpMetadata(metadata);
_pPublisherSrc
->
setMetaData
(
metadata
);
_set_meta_data
=
true
;
}
void
RtmpSession
::
onProcessCmd
(
AMFDecoder
&
dec
)
{
...
...
@@ -452,7 +453,7 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
std
::
string
method
=
dec
.
load
<
std
::
string
>
();
auto
it
=
s_cmd_functions
.
find
(
method
);
if
(
it
==
s_cmd_functions
.
end
())
{
TraceP
(
this
)
<<
"can not support cmd:"
<<
method
;
//
TraceP(this) << "can not support cmd:" << method;
return
;
}
_dNowReqID
=
dec
.
load
<
double
>
();
...
...
@@ -473,10 +474,11 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
case
MSG_DATA3
:
{
AMFDecoder
dec
(
chunkData
.
strBuf
,
chunkData
.
typeId
==
MSG_CMD3
?
1
:
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
TraceP
(
this
)
<<
"notify:"
<<
type
;
if
(
type
==
"@setDataFrame"
)
{
setMetaData
(
dec
);
}
}
else
{
TraceP
(
this
)
<<
"unknown notify:"
<<
type
;
}
}
break
;
case
MSG_AUDIO
:
...
...
@@ -490,6 +492,11 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
_stamp
[
chunkData
.
typeId
%
2
].
revise
(
chunkData
.
timeStamp
,
chunkData
.
timeStamp
,
dts_out
,
dts_out
,
true
);
chunkData
.
timeStamp
=
dts_out
;
}
if
(
!
_set_meta_data
&&
!
chunkData
.
isCfgFrame
()){
_set_meta_data
=
true
;
_pPublisherSrc
->
setMetaData
(
TitleMeta
().
getMetadata
());
}
_pPublisherSrc
->
onWrite
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunkData
)));
}
break
;
...
...
src/Rtmp/RtmpSession.h
查看文件 @
dad01750
...
...
@@ -95,6 +95,7 @@ private:
std
::
string
_strTcUrl
;
MediaInfo
_mediaInfo
;
double
_dNowReqID
=
0
;
bool
_set_meta_data
=
false
;
Ticker
_ticker
;
//数据接收时间
RingBuffer
<
RtmpPacket
::
Ptr
>::
RingReader
::
Ptr
_pRingReader
;
std
::
shared_ptr
<
RtmpMediaSourceImp
>
_pPublisherSrc
;
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
dad01750
...
...
@@ -932,12 +932,6 @@ inline void RtspSession::send_NotAcceptable() {
void
RtspSession
::
onRtpSorted
(
const
RtpPacket
::
Ptr
&
rtppt
,
int
trackidx
)
{
GET_CONFIG
(
bool
,
modify_stamp
,
Rtsp
::
kModifyStamp
);
if
(
modify_stamp
){
int64_t
dts_out
;
_stamp
[
trackidx
].
revise
(
rtppt
->
timeStamp
,
rtppt
->
timeStamp
,
dts_out
,
dts_out
,
true
);
rtppt
->
timeStamp
=
dts_out
;
}
_pushSrc
->
onWrite
(
rtppt
,
false
);
}
inline
void
RtspSession
::
onRcvPeerUdpData
(
int
intervaled
,
const
Buffer
::
Ptr
&
pBuf
,
const
struct
sockaddr
&
addr
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论