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
49daa1ba
Commit
49daa1ba
authored
Oct 23, 2018
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
开始修改播放器
parent
c5e372c1
隐藏空白字符变更
内嵌
并排
正在显示
21 个修改的文件
包含
394 行增加
和
641 行删除
+394
-641
src/Device/PlayerProxy.cpp
+51
-46
src/MediaFile/Mp4Maker.cpp
+37
-31
src/Player/Frame.h
+1
-2
src/Player/MediaPlayer.cpp
+3
-2
src/Player/PlayerBase.h
+37
-133
src/Player/Track.cpp
+48
-0
src/Player/Track.h
+69
-1
src/RTP/RtpCodec.cpp
+6
-6
src/RTP/RtpCodec.h
+7
-7
src/Rtmp/RtmpMediaSource.h
+1
-1
src/Rtmp/RtmpParser.h
+0
-52
src/Rtmp/RtmpPlayerImp.h
+3
-2
src/Rtmp/RtmpToRtspMediaSource.cpp
+72
-69
src/Rtmp/RtmpToRtspMediaSource.h
+4
-2
src/Rtsp/RtpParser.cpp
+5
-191
src/Rtsp/RtpParser.h
+5
-70
src/Rtsp/RtspEncoder.h
+8
-10
src/Rtsp/RtspPlayer.cpp
+6
-2
src/Rtsp/RtspPlayerImp.h
+4
-3
src/Rtsp/RtspToRtmpMediaSource.cpp
+12
-2
src/Rtsp/RtspToRtmpMediaSource.h
+15
-9
没有找到文件。
src/Device/PlayerProxy.cpp
查看文件 @
49daa1ba
...
...
@@ -83,31 +83,33 @@ PlayerProxy::PlayerProxy(const char *strVhost,
}
void
PlayerProxy
::
play
(
const
char
*
strUrl
)
{
weak_ptr
<
PlayerProxy
>
weakSelf
=
shared_from_this
();
setOnVideoCB
(
[
weakSelf
](
const
H264Frame
&
data
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
return
;
}
if
(
strongSelf
->
m_pChn
){
strongSelf
->
m_pChn
->
inputH264
((
char
*
)
data
.
data
(),
data
.
size
(),
data
.
timeStamp
);
if
(
!
strongSelf
->
m_haveAudio
){
strongSelf
->
makeMuteAudio
(
data
.
timeStamp
);
}
}
else
{
strongSelf
->
initMedia
();
}
});
setOnAudioCB
(
[
weakSelf
](
const
AACFrame
&
data
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
return
;
}
if
(
strongSelf
->
m_pChn
){
strongSelf
->
m_pChn
->
inputAAC
((
char
*
)
data
.
data
(),
data
.
size
(),
data
.
timeStamp
);
}
else
{
strongSelf
->
initMedia
();
}
});
//todo(xzl) 修复此处
// setOnVideoCB( [weakSelf](const H264Frame &data ) {
// auto strongSelf = weakSelf.lock();
// if(!strongSelf){
// return;
// }
// if(strongSelf->m_pChn){
// strongSelf->m_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp);
// if(!strongSelf->m_haveAudio){
// strongSelf->makeMuteAudio(data.timeStamp);
// }
// }else{
// strongSelf->initMedia();
// }
// });
// setOnAudioCB( [weakSelf](const AACFrame &data ) {
// auto strongSelf = weakSelf.lock();
// if(!strongSelf){
// return;
// }
// if(strongSelf->m_pChn){
// strongSelf->m_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp);
// }else{
// strongSelf->initMedia();
// }
// });
std
::
shared_ptr
<
int
>
piFailedCnt
(
new
int
(
0
));
//连续播放失败次数
string
strUrlTmp
(
strUrl
);
...
...
@@ -166,28 +168,31 @@ void PlayerProxy::initMedia() {
}
m_pChn
.
reset
(
new
DevChannel
(
m_strVhost
.
data
(),
m_strApp
.
data
(),
m_strSrc
.
data
(),
getDuration
(),
m_bEnableHls
,
m_bEnableMp4
));
m_pChn
->
setListener
(
shared_from_this
());
if
(
containVideo
())
{
VideoInfo
info
;
info
.
iFrameRate
=
getVideoFps
();
info
.
iWidth
=
getVideoWidth
();
info
.
iHeight
=
getVideoHeight
();
m_pChn
->
initVideo
(
info
);
}
m_haveAudio
=
containAudio
();
if
(
containAudio
())
{
AudioInfo
info
;
info
.
iSampleRate
=
getAudioSampleRate
();
info
.
iChannel
=
getAudioChannel
();
info
.
iSampleBit
=
getAudioSampleBit
();
m_pChn
->
initAudio
(
info
);
}
else
{
AudioInfo
info
;
info
.
iSampleRate
=
MUTE_ADTS_SAMPLE_RATE
;
info
.
iChannel
=
MUTE_ADTS_CHN_CNT
;
info
.
iSampleBit
=
MUTE_ADTS_SAMPLE_BIT
;
m_pChn
->
initAudio
(
info
);
}
//todo(xzl) 修复此处
// if (containVideo()) {
// VideoInfo info;
// info.iFrameRate = getVideoFps();
// info.iWidth = getVideoWidth();
// info.iHeight = getVideoHeight();
// m_pChn->initVideo(info);
// }
//
// m_haveAudio = containAudio();
// if (containAudio()) {
// AudioInfo info;
// info.iSampleRate = getAudioSampleRate();
// info.iChannel = getAudioChannel();
// info.iSampleBit = getAudioSampleBit();
// m_pChn->initAudio(info);
// }else{
// AudioInfo info;
// info.iSampleRate = MUTE_ADTS_SAMPLE_RATE;
// info.iChannel = MUTE_ADTS_CHN_CNT;
// info.iSampleBit = MUTE_ADTS_SAMPLE_BIT;
// m_pChn->initAudio(info);
// }
}
bool
PlayerProxy
::
shutDown
()
{
//通知其停止推流
...
...
src/MediaFile/Mp4Maker.cpp
查看文件 @
49daa1ba
...
...
@@ -131,15 +131,18 @@ void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duratio
void
Mp4Maker
::
_inputAAC
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32Duration
)
{
GET_CONFIG_AND_REGISTER
(
uint32_t
,
recordSec
,
Config
::
Record
::
kFileSecond
);
if
(
!
m_pPlayer
->
containVideo
()
&&
(
m_hMp4
==
MP4_INVALID_FILE_HANDLE
||
m_ticker
.
elapsedTime
()
>
recordSec
*
1000
))
{
//在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件
createFile
();
}
if
(
m_hAudio
!=
MP4_INVALID_TRACK_ID
)
{
auto
duration
=
ui32Duration
*
m_pPlayer
->
getAudioSampleRate
()
/
1000.0
;
MP4WriteSample
(
m_hMp4
,
m_hAudio
,
(
uint8_t
*
)
pData
+
7
,
ui32Length
-
7
,
duration
,
0
,
false
);
}
//todo(xzl) 修复此处
//
// if (!m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordSec * 1000)) {
// //在I帧率处新建MP4文件
// //如果文件未创建或者文件超过10分钟则创建新文件
// createFile();
// }
// if (m_hAudio != MP4_INVALID_TRACK_ID) {
// auto duration = ui32Duration * m_pPlayer->getAudioSampleRate() /1000.0;
// MP4WriteSample(m_hMp4, m_hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
// }
}
void
Mp4Maker
::
createFile
()
{
...
...
@@ -182,28 +185,31 @@ void Mp4Maker::createFile() {
m_strFileTmp
=
strFileTmp
;
m_strFile
=
strFile
;
m_ticker
.
resetTime
();
if
(
m_pPlayer
->
containVideo
()){
auto
&
sps
=
m_pPlayer
->
getSps
();
auto
&
pps
=
m_pPlayer
->
getPps
();
m_hVideo
=
MP4AddH264VideoTrack
(
m_hMp4
,
90000
,
MP4_INVALID_DURATION
,
m_pPlayer
->
getVideoWidth
(),
m_pPlayer
->
getVideoHeight
(),
sps
[
5
],
sps
[
6
],
sps
[
7
],
3
);
if
(
m_hVideo
!=
MP4_INVALID_TRACK_ID
){
MP4AddH264SequenceParameterSet
(
m_hMp4
,
m_hVideo
,
(
uint8_t
*
)
sps
.
data
()
+
4
,
sps
.
size
()
-
4
);
MP4AddH264PictureParameterSet
(
m_hMp4
,
m_hVideo
,
(
uint8_t
*
)
pps
.
data
()
+
4
,
pps
.
size
()
-
4
);
}
else
{
WarnL
<<
"添加视频通道失败:"
<<
strFileTmp
;
}
}
if
(
m_pPlayer
->
containAudio
()){
m_hAudio
=
MP4AddAudioTrack
(
m_hMp4
,
m_pPlayer
->
getAudioSampleRate
(),
MP4_INVALID_DURATION
,
MP4_MPEG4_AUDIO_TYPE
);
if
(
m_hAudio
!=
MP4_INVALID_TRACK_ID
)
{
auto
&
cfg
=
m_pPlayer
->
getAudioCfg
();
MP4SetTrackESConfiguration
(
m_hMp4
,
m_hAudio
,(
uint8_t
*
)
cfg
.
data
(),
cfg
.
size
());
}
else
{
WarnL
<<
"添加音频通道失败:"
<<
strFileTmp
;
}
}
//todo(xzl) 修复此处
// if(m_pPlayer->containVideo()){
// auto &sps = m_pPlayer->getSps();
// auto &pps = m_pPlayer->getPps();
// m_hVideo = MP4AddH264VideoTrack(m_hMp4, 90000, MP4_INVALID_DURATION,
// m_pPlayer->getVideoWidth(), m_pPlayer->getVideoHeight(),
// sps[5], sps[6], sps[7], 3);
// if(m_hVideo !=MP4_INVALID_TRACK_ID){
// MP4AddH264SequenceParameterSet(m_hMp4, m_hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
// MP4AddH264PictureParameterSet(m_hMp4, m_hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
// }else{
// WarnL << "添加视频通道失败:" << strFileTmp;
// }
// }
// if(m_pPlayer->containAudio()){
// m_hAudio = MP4AddAudioTrack(m_hMp4, m_pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
// if (m_hAudio != MP4_INVALID_TRACK_ID) {
// auto &cfg = m_pPlayer->getAudioCfg();
// MP4SetTrackESConfiguration(m_hMp4, m_hAudio,(uint8_t *)cfg.data(), cfg.size());
// }else{
// WarnL << "添加音频通道失败:" << strFileTmp;
// }
// }
}
void
Mp4Maker
::
closeFile
()
{
...
...
src/Player/Frame.h
查看文件 @
49daa1ba
...
...
@@ -93,8 +93,7 @@ public:
typedef
std
::
shared_ptr
<
FrameRing
>
Ptr
;
FrameRing
(){
//禁用缓存
_frameRing
=
std
::
make_shared
<
RingType
>
(
1
);
_frameRing
=
std
::
make_shared
<
RingType
>
();
}
virtual
~
FrameRing
(){}
...
...
src/Player/MediaPlayer.cpp
查看文件 @
49daa1ba
...
...
@@ -48,8 +48,9 @@ void MediaPlayer::play(const char* strUrl) {
m_strPrefix
=
strPrefix
;
m_parser
=
PlayerBase
::
createPlayer
(
strUrl
);
m_parser
->
setOnShutdown
(
m_shutdownCB
);
m_parser
->
setOnVideoCB
(
m_onGetVideoCB
);
m_parser
->
setOnAudioCB
(
m_onGetAudioCB
);
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
}
m_parser
->
setOnPlayResult
(
m_playResultCB
);
m_parser
->
mINI
::
operator
=
(
*
this
);
...
...
src/Player/PlayerBase.h
查看文件 @
49daa1ba
...
...
@@ -47,23 +47,7 @@ using namespace ZL::Network;
namespace
ZL
{
namespace
Player
{
class
MediaFormat
{
public
:
virtual
~
MediaFormat
(){};
virtual
int
getVideoHeight
()
const
{
return
0
;
};
virtual
int
getVideoWidth
()
const
{
return
0
;
};
virtual
float
getVideoFps
()
const
{
return
0
;
};
virtual
int
getAudioSampleRate
()
const
{
return
0
;
};
virtual
int
getAudioSampleBit
()
const
{
return
0
;
};
virtual
int
getAudioChannel
()
const
{
return
0
;
};
virtual
const
string
&
getPps
()
const
{
static
string
null
;
return
null
;
};
virtual
const
string
&
getSps
()
const
{
static
string
null
;
return
null
;
};
virtual
const
string
&
getAudioCfg
()
const
{
static
string
null
;
return
null
;
};
};
class
PlayerBase
:
public
MediaFormat
,
public
mINI
{
class
PlayerBase
:
public
mINI
{
public
:
typedef
std
::
shared_ptr
<
PlayerBase
>
Ptr
;
typedef
enum
{
...
...
@@ -85,34 +69,29 @@ public:
//rtsp认证用用户密码是否为md5
static
const
char
kRtspPwdIsMD5
[];
PlayerBase
(){}
;
virtual
~
PlayerBase
(){}
;
virtual
void
play
(
const
char
*
strUrl
)
{}
;
virtual
void
pause
(
bool
bPause
)
{}
;
virtual
void
teardown
()
{}
;
PlayerBase
(){}
virtual
~
PlayerBase
(){}
virtual
void
play
(
const
char
*
strUrl
)
{}
virtual
void
pause
(
bool
bPause
)
{}
virtual
void
teardown
()
{}
virtual
void
setOnShutdown
(
const
function
<
void
(
const
SockException
&
)
>
&
cb
)
{};
virtual
void
setOnPlayResult
(
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
{};
virtual
void
setOnVideoCB
(
const
function
<
void
(
const
H264Frame
&
frame
)
>
&
cb
)
{};
virtual
void
setOnAudioCB
(
const
function
<
void
(
const
AACFrame
&
frame
)
>
&
cb
)
{};
virtual
float
getProgress
()
const
{
return
0
;};
virtual
void
seekTo
(
float
fProgress
)
{};
virtual
void
setMediaSouce
(
const
MediaSource
::
Ptr
&
src
)
{};
virtual
void
setOnShutdown
(
const
function
<
void
(
const
SockException
&
)
>
&
cb
)
{}
virtual
void
setOnPlayResult
(
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
{}
virtual
bool
isInited
()
const
{
return
true
;
};
//TrackVideo = 0, TrackAudio = 1
virtual
float
getRtpLossRate
(
int
trackType
)
const
{
return
0
;
};
virtual
float
getDuration
()
const
{
return
0
;};
virtual
float
getProgress
()
const
{
return
0
;}
virtual
void
seekTo
(
float
fProgress
)
{}
virtual
void
setMediaSouce
(
const
MediaSource
::
Ptr
&
src
)
{}
virtual
bool
containAudio
()
const
{
return
false
;
};
virtual
bool
containVideo
()
const
{
return
false
;
};
virtual
bool
isInited
()
const
{
return
true
;
}
//TrackVideo = 0, TrackAudio = 1
virtual
float
getRtpLossRate
(
int
trackType
)
const
{
return
0
;
}
virtual
float
getDuration
()
const
{
return
0
;}
virtual
int
getTrackCount
()
const
{
return
0
;}
;
virtual
Track
::
Ptr
getTrack
(
int
index
)
const
{
return
nullptr
;}
;
virtual
int
getTrackCount
()
const
{
return
0
;}
virtual
Track
::
Ptr
getTrack
(
int
index
)
const
{
return
nullptr
;}
protected
:
virtual
void
onShutdown
(
const
SockException
&
ex
)
{}
;
virtual
void
onPlayResult
(
const
SockException
&
ex
)
{}
;
virtual
void
onShutdown
(
const
SockException
&
ex
)
{}
virtual
void
onPlayResult
(
const
SockException
&
ex
)
{}
};
template
<
typename
Parent
,
typename
Parser
>
...
...
@@ -120,8 +99,8 @@ class PlayerImp : public Parent
{
public
:
typedef
std
::
shared_ptr
<
PlayerImp
>
Ptr
;
PlayerImp
(){}
;
virtual
~
PlayerImp
(){}
;
PlayerImp
(){}
virtual
~
PlayerImp
(){}
void
setOnShutdown
(
const
function
<
void
(
const
SockException
&
)
>
&
cb
)
override
{
if
(
m_parser
)
{
m_parser
->
setOnShutdown
(
cb
);
...
...
@@ -134,92 +113,7 @@ public:
}
m_playResultCB
=
cb
;
}
void
setOnVideoCB
(
const
function
<
void
(
const
H264Frame
&
frame
)
>
&
cb
)
override
{
if
(
m_parser
)
{
m_parser
->
setOnVideoCB
(
cb
);
}
m_onGetVideoCB
=
cb
;
}
void
setOnAudioCB
(
const
function
<
void
(
const
AACFrame
&
frame
)
>
&
cb
)
override
{
if
(
m_parser
)
{
m_parser
->
setOnAudioCB
(
cb
);
}
m_onGetAudioCB
=
cb
;
}
int
getVideoHeight
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getVideoHeight
();
}
return
PlayerBase
::
getVideoHeight
();
}
int
getVideoWidth
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getVideoWidth
();
}
return
PlayerBase
::
getVideoWidth
();
}
float
getVideoFps
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getVideoFps
();
}
return
PlayerBase
::
getVideoFps
();
}
int
getAudioSampleRate
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getAudioSampleRate
();
}
return
PlayerBase
::
getAudioSampleRate
();
}
int
getAudioSampleBit
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getAudioSampleBit
();
}
return
PlayerBase
::
getAudioSampleBit
();
}
int
getAudioChannel
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getAudioChannel
();
}
return
PlayerBase
::
getAudioChannel
();
}
const
string
&
getPps
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getPps
();
}
return
PlayerBase
::
getPps
();
}
const
string
&
getSps
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getSps
();
}
return
PlayerBase
::
getSps
();
}
const
string
&
getAudioCfg
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getAudioCfg
();
}
return
PlayerBase
::
getAudioCfg
();
}
bool
containAudio
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
containAudio
();
}
return
PlayerBase
::
containAudio
();
}
bool
containVideo
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
containVideo
();
}
return
PlayerBase
::
containVideo
();
}
bool
isInited
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
isInited
();
...
...
@@ -237,21 +131,33 @@ public:
return
m_parser
->
getProgress
();
}
return
PlayerBase
::
getProgress
();
}
;
}
void
seekTo
(
float
fProgress
)
override
{
if
(
m_parser
)
{
return
m_parser
->
seekTo
(
fProgress
);
}
return
PlayerBase
::
seekTo
(
fProgress
);
}
;
}
void
setMediaSouce
(
const
MediaSource
::
Ptr
&
src
)
override
{
if
(
m_parser
)
{
return
m_parser
->
setMediaSouce
(
src
);
}
m_pMediaSrc
=
src
;
}
;
}
virtual
int
getTrackCount
()
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getTrackCount
();
}
return
PlayerBase
::
getTrackCount
();
}
virtual
Track
::
Ptr
getTrack
(
int
index
)
const
override
{
if
(
m_parser
)
{
return
m_parser
->
getTrack
(
index
);
}
return
PlayerBase
::
getTrack
(
index
);
}
protected
:
void
onShutdown
(
const
SockException
&
ex
)
override
{
if
(
m_shutdownCB
)
{
...
...
@@ -268,11 +174,9 @@ protected:
function
<
void
(
const
SockException
&
ex
)
>
m_shutdownCB
;
function
<
void
(
const
SockException
&
ex
)
>
m_playResultCB
;
std
::
shared_ptr
<
Parser
>
m_parser
;
function
<
void
(
const
H264Frame
&
frame
)
>
m_onGetVideoCB
;
function
<
void
(
const
AACFrame
&
frame
)
>
m_onGetAudioCB
;
MediaSource
::
Ptr
m_pMediaSrc
;
};
}
/* namespace Player */
}
/* namespace ZL */
...
...
src/Player/Track.cpp
查看文件 @
49daa1ba
...
...
@@ -3,3 +3,51 @@
//
#include "Track.h"
#include "Util/util.h"
#include "Util/base64.h"
using
namespace
ZL
::
Util
;
Track
::
Ptr
Track
::
getTrackBySdp
(
const
string
&
sdp
)
{
if
(
strcasestr
(
sdp
.
data
(),
"mpeg4-generic"
)
!=
nullptr
)
{
string
aac_cfg_str
=
FindField
(
sdp
.
c_str
(),
"config="
,
"
\r\n
"
);
if
(
aac_cfg_str
.
size
()
!=
4
)
{
aac_cfg_str
=
FindField
(
sdp
.
c_str
(),
"config="
,
";"
);
}
if
(
aac_cfg_str
.
size
()
!=
4
)
{
return
nullptr
;
}
string
aac_cfg
;
unsigned
int
cfg1
;
sscanf
(
aac_cfg_str
.
substr
(
0
,
2
).
c_str
(),
"%02X"
,
&
cfg1
);
cfg1
&=
0x00FF
;
aac_cfg
.
push_back
(
cfg1
);
unsigned
int
cfg2
;
sscanf
(
aac_cfg_str
.
substr
(
2
,
2
).
c_str
(),
"%02X"
,
&
cfg2
);
cfg2
&=
0x00FF
;
aac_cfg
.
push_back
(
cfg2
);
return
std
::
make_shared
<
AACTrack
>
(
aac_cfg
);
}
if
(
strcasestr
(
sdp
.
data
(),
"h264"
)
!=
nullptr
)
{
string
sps_pps
=
FindField
(
sdp
.
c_str
(),
"sprop-parameter-sets="
,
"
\r\n
"
);
if
(
sps_pps
.
empty
()){
return
std
::
make_shared
<
H264Track
>
();
}
string
base64_SPS
=
FindField
(
sps_pps
.
c_str
(),
NULL
,
","
);
string
base64_PPS
=
FindField
(
sps_pps
.
c_str
(),
","
,
NULL
);
if
(
base64_PPS
.
back
()
==
';'
){
base64_PPS
.
pop_back
();
}
auto
sps
=
decodeBase64
(
base64_SPS
);
auto
pps
=
decodeBase64
(
base64_PPS
);
return
std
::
make_shared
<
H264Track
>
(
sps
,
pps
,
0
,
0
);
}
return
nullptr
;
}
src/Player/Track.h
查看文件 @
49daa1ba
...
...
@@ -20,6 +20,8 @@ public:
typedef
std
::
shared_ptr
<
Track
>
Ptr
;
Track
(){}
virtual
~
Track
(){}
static
Ptr
getTrackBySdp
(
const
string
&
sdp
);
};
class
VideoTrack
:
public
Track
{
...
...
@@ -72,6 +74,11 @@ class H264Track : public VideoTrack{
public
:
/**
* 不指定sps pps构造h264类型的媒体
* 在随后的inputFrame中获取sps pps
*/
H264Track
(){}
/**
* 构造h264类型的媒体
* @param sps sps帧数据
* @param pps pps帧数据
...
...
@@ -98,7 +105,6 @@ public:
parseSps
(
_sps
);
}
/**
* 返回不带0x00 00 00 01头的sps
* @return
...
...
@@ -142,6 +148,68 @@ public:
float
getVideoFps
()
const
override
{
return
_fps
;
}
TrackType
getTrackType
()
const
override
{
if
(
_sps
.
empty
()
||
_pps
.
empty
()){
return
TrackInvalid
;
}
return
TrackAudio
;
}
/**
* 输入数据帧,并获取sps pps
* @param frame 数据帧
* @param key_pos 是否为关键帧
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
,
bool
key_pos
)
override
{
int
type
=
(
*
((
uint8_t
*
)
frame
->
data
()
+
frame
->
prefixSize
()))
&
0x1F
;
switch
(
type
){
case
7
:{
//sps
bool
flag
=
_sps
.
empty
();
_sps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
if
(
flag
&&
_width
==
0
){
parseSps
(
_sps
);
}
}
break
;
case
8
:{
//pps
_pps
=
string
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
}
break
;
case
5
:{
//I
if
(
!
_sps
.
empty
()){
H264Frame
::
Ptr
insertFrame
=
std
::
make_shared
<
H264Frame
>
();
insertFrame
->
timeStamp
=
frame
->
stamp
();
insertFrame
->
type
=
7
;
insertFrame
->
buffer
=
_sps
;
insertFrame
->
iPrefixSize
=
0
;
VideoTrack
::
inputFrame
(
insertFrame
,
true
);
}
if
(
!
_pps
.
empty
()){
H264Frame
::
Ptr
insertFrame
=
std
::
make_shared
<
H264Frame
>
();
insertFrame
->
timeStamp
=
frame
->
stamp
();
insertFrame
->
type
=
8
;
insertFrame
->
buffer
=
_pps
;
insertFrame
->
iPrefixSize
=
0
;
VideoTrack
::
inputFrame
(
insertFrame
,
false
);
}
VideoTrack
::
inputFrame
(
frame
,
false
);
}
break
;
case
1
:{
//B or P
VideoTrack
::
inputFrame
(
frame
,
false
);
}
break
;
}
}
private
:
/**
* 解析sps获取宽高fps
...
...
src/RTP/RtpCodec.cpp
查看文件 @
49daa1ba
...
...
@@ -6,12 +6,12 @@
#include "AACRtpCodec.h"
#include "H264RtpCodec.h"
RtpCodec
::
Ptr
RtpCodec
::
getRtpCodec
(
CodecId
codecId
,
uint32_t
ui32Ssrc
,
uint32_t
ui32MtuSize
,
uint32_t
ui32SampleRate
,
uint8_t
ui8PlayloadType
,
uint8_t
ui8Interleaved
)
{
RtpCodec
::
Ptr
RtpCodec
::
getRtpCodec
ById
(
CodecId
codecId
,
uint32_t
ui32Ssrc
,
uint32_t
ui32MtuSize
,
uint32_t
ui32SampleRate
,
uint8_t
ui8PlayloadType
,
uint8_t
ui8Interleaved
)
{
switch
(
codecId
){
case
CodecH264
:
return
std
::
make_shared
<
H264RtpEncoder
>
(
ui32Ssrc
,
ui32MtuSize
,
ui32SampleRate
,
ui8PlayloadType
,
ui8Interleaved
);
...
...
src/RTP/RtpCodec.h
查看文件 @
49daa1ba
...
...
@@ -55,7 +55,7 @@ public:
RtpRing
(){
//禁用缓存
_rtpRing
=
std
::
make_shared
<
RingType
>
(
1
);
_rtpRing
=
std
::
make_shared
<
RingType
>
();
}
virtual
~
RtpRing
(){}
...
...
@@ -143,12 +143,12 @@ public:
RtpCodec
(){}
virtual
~
RtpCodec
(){}
static
Ptr
getRtpCodec
(
CodecId
codecId
,
uint32_t
ui32Ssrc
,
uint32_t
ui32MtuSize
,
uint32_t
ui32SampleRate
,
uint8_t
ui8PlayloadType
,
uint8_t
ui8Interleaved
);
static
Ptr
getRtpCodec
ById
(
CodecId
codecId
,
uint32_t
ui32Ssrc
,
uint32_t
ui32MtuSize
,
uint32_t
ui32SampleRate
,
uint8_t
ui8PlayloadType
,
uint8_t
ui8Interleaved
);
};
...
...
src/Rtmp/RtmpMediaSource.h
查看文件 @
49daa1ba
...
...
@@ -85,7 +85,7 @@ public:
lock_guard
<
recursive_mutex
>
lock
(
m_mtxMap
);
m_metadata
=
_metadata
;
RtmpParser
parser
(
_metadata
);
m_iCfgFrameSize
=
parser
.
containAudio
()
+
parser
.
containVideo
();
m_iCfgFrameSize
=
parser
.
getTrackCount
();
if
(
ready
()){
MediaSource
::
regist
();
m_bRegisted
=
true
;
...
...
src/Rtmp/RtmpParser.h
查看文件 @
49daa1ba
...
...
@@ -53,58 +53,6 @@ public:
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
);
void
setOnVideoCB
(
const
function
<
void
(
const
H264Frame
&
frame
)
>
&
cb
)
override
{
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
onVideo
=
cb
;
}
void
setOnAudioCB
(
const
function
<
void
(
const
AACFrame
&
frame
)
>
&
cb
)
override
{
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
onAudio
=
cb
;
}
int
getVideoHeight
()
const
override
{
return
m_iVideoHeight
;
}
int
getVideoWidth
()
const
override
{
return
m_iVideoWidth
;
}
float
getVideoFps
()
const
override
{
return
m_fVideoFps
;
}
int
getAudioSampleRate
()
const
override
{
return
m_iSampleRate
;
}
int
getAudioSampleBit
()
const
override
{
return
m_iSampleBit
;
}
int
getAudioChannel
()
const
override
{
return
m_iChannel
;
}
const
string
&
getPps
()
const
override
{
return
m_strPPS
;
}
const
string
&
getSps
()
const
override
{
return
m_strSPS
;
}
const
string
&
getAudioCfg
()
const
override
{
return
m_strAudioCfg
;
}
bool
containAudio
()
const
override
{
//音频只支持aac
return
m_iAudioCodecID
==
AAC_CODEC_ID
;
}
bool
containVideo
()
const
override
{
//视频只支持264
return
m_iVideoCodecID
==
H264_CODEC_ID
;
}
bool
isInited
()
const
override
{
if
((
m_iAudioCodecID
|
m_iVideoCodecID
)
==
0
){
//音视频codec_id都未获取到,说明还未初始化成功
...
...
src/Rtmp/RtmpPlayerImp.h
查看文件 @
49daa1ba
...
...
@@ -69,8 +69,9 @@ private:
}
try
{
m_parser
.
reset
(
new
RtmpParser
(
val
));
m_parser
->
setOnVideoCB
(
m_onGetVideoCB
);
m_parser
->
setOnAudioCB
(
m_onGetAudioCB
);
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
return
true
;
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
...
...
src/Rtmp/RtmpToRtspMediaSource.cpp
查看文件 @
49daa1ba
...
...
@@ -79,76 +79,79 @@ void RtmpToRtspMediaSource::makeSDP() {
strSDP
+=
StrPrinter
<<
"0-"
<<
m_pParser
->
getDuration
()
<<
"
\r\n
"
<<
endl
;
}
strSDP
+=
"a=control:*
\r\n
"
;
if
(
m_pParser
->
containVideo
())
{
uint32_t
ssrc0
;
memcpy
(
&
ssrc0
,
makeRandStr
(
4
,
false
).
data
(),
4
);
auto
lam
=
[
this
](
const
RtpPacket
::
Ptr
&
pkt
,
bool
bKeyPos
)
{
m_pRtspSrc
->
onGetRTP
(
pkt
,
bKeyPos
);
};
GET_CONFIG_AND_REGISTER
(
uint32_t
,
videoMtu
,
Config
::
Rtp
::
kVideoMtuSize
);
m_pRtpMaker_h264
.
reset
(
new
RtpMaker_H264
(
lam
,
ssrc0
,
videoMtu
));
char
strTemp
[
100
];
int
profile_level_id
=
0
;
string
strSPS
=
m_pParser
->
getSps
().
substr
(
4
);
string
strPPS
=
m_pParser
->
getPps
().
substr
(
4
);
if
(
strSPS
.
length
()
>=
4
)
{
// sanity check
profile_level_id
=
(
strSPS
[
1
]
<<
16
)
|
(
strSPS
[
2
]
<<
8
)
|
strSPS
[
3
];
// profile_idc|constraint_setN_flag|level_idc
}
//视频通道
strSDP
+=
StrPrinter
<<
"m=video 0 RTP/AVP "
<<
m_pRtpMaker_h264
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
strSDP
+=
"b=AS:5100
\r\n
"
;
strSDP
+=
StrPrinter
<<
"a=rtpmap:"
<<
m_pRtpMaker_h264
->
getPlayloadType
()
<<
" H264/"
<<
m_pRtpMaker_h264
->
getSampleRate
()
<<
"
\r\n
"
<<
endl
;
strSDP
+=
StrPrinter
<<
"a=fmtp:"
<<
m_pRtpMaker_h264
->
getPlayloadType
()
<<
" packetization-mode=1;profile-level-id="
<<
endl
;
memset
(
strTemp
,
0
,
100
);
sprintf
(
strTemp
,
"%06X"
,
profile_level_id
);
strSDP
+=
strTemp
;
strSDP
+=
";sprop-parameter-sets="
;
memset
(
strTemp
,
0
,
100
);
av_base64_encode
(
strTemp
,
100
,
(
uint8_t
*
)
strSPS
.
data
(),
strSPS
.
size
());
strSDP
+=
strTemp
;
strSDP
+=
","
;
memset
(
strTemp
,
0
,
100
);
av_base64_encode
(
strTemp
,
100
,
(
uint8_t
*
)
strPPS
.
data
(),
strPPS
.
size
());
strSDP
+=
strTemp
;
strSDP
+=
"
\r\n
"
;
strSDP
+=
StrPrinter
<<
"a=control:trackID="
<<
m_pRtpMaker_h264
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
}
if
(
m_pParser
->
containAudio
())
{
uint32_t
ssrc1
;
memcpy
(
&
ssrc1
,
makeRandStr
(
8
,
false
).
data
()
+
4
,
4
);
auto
lam
=
[
this
](
const
RtpPacket
::
Ptr
&
pkt
,
bool
bKeyPos
)
{
m_pRtspSrc
->
onGetRTP
(
pkt
,
bKeyPos
);
};
GET_CONFIG_AND_REGISTER
(
uint32_t
,
audioMtu
,
Config
::
Rtp
::
kAudioMtuSize
);
m_pRtpMaker_aac
.
reset
(
new
RtpMaker_AAC
(
lam
,
ssrc1
,
audioMtu
,
m_pParser
->
getAudioSampleRate
()));
char
configStr
[
32
];
const
string
&
strAacCfg
=
m_pParser
->
getAudioCfg
();
snprintf
(
configStr
,
sizeof
(
configStr
),
"%02X%02x"
,
strAacCfg
[
0
],
strAacCfg
[
1
]);
strSDP
+=
StrPrinter
<<
"m=audio 0 RTP/AVP "
<<
m_pRtpMaker_aac
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
strSDP
+=
"b=AS:96
\r\n
"
;
strSDP
+=
StrPrinter
<<
"a=rtpmap:"
<<
m_pRtpMaker_aac
->
getPlayloadType
()
<<
" MPEG4-GENERIC/"
<<
m_pRtpMaker_aac
->
getSampleRate
()
<<
"
\r\n
"
<<
endl
;
strSDP
+=
StrPrinter
<<
"a=fmtp:"
<<
m_pRtpMaker_aac
->
getPlayloadType
()
<<
" streamtype=5;profile-level-id=1;mode=AAC-hbr;"
<<
"sizelength=13;indexlength=3;indexdeltalength=3;config="
<<
endl
;
strSDP
.
append
(
configStr
,
4
);
strSDP
+=
"
\r\n
"
;
strSDP
+=
StrPrinter
<<
"a=control:trackID="
<<
m_pRtpMaker_aac
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
}
//todo(xzl) 修复此处
// if (m_pParser->containVideo()) {
// uint32_t ssrc0;
// memcpy(&ssrc0, makeRandStr(4, false).data(), 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
// m_pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
//
// GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
// m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
//
// char strTemp[100];
// int profile_level_id = 0;
// string strSPS =m_pParser->getSps().substr(4);
// string strPPS =m_pParser->getPps().substr(4);
// if (strSPS.length() >= 4) { // sanity check
// profile_level_id = (strSPS[1] << 16) | (strSPS[2] << 8) | strSPS[3]; // profile_idc|constraint_setN_flag|level_idc
// }
//
// //视频通道
// strSDP += StrPrinter << "m=video 0 RTP/AVP " << m_pRtpMaker_h264->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:5100\r\n";
// strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_h264->getPlayloadType()
// << " H264/" << m_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
// strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_h264->getPlayloadType()
// << " packetization-mode=1;profile-level-id=" << endl;
//
// memset(strTemp, 0, 100);
// sprintf(strTemp, "%06X", profile_level_id);
// strSDP += strTemp;
// strSDP += ";sprop-parameter-sets=";
// memset(strTemp, 0, 100);
// av_base64_encode(strTemp, 100, (uint8_t *) strSPS.data(), strSPS.size());
// strSDP += strTemp;
// strSDP += ",";
// memset(strTemp, 0, 100);
// av_base64_encode(strTemp, 100, (uint8_t *) strPPS.data(), strPPS.size());
// strSDP += strTemp;
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" << m_pRtpMaker_h264->getInterleaved() / 2
// << "\r\n" << endl;
// }
//
// if (m_pParser->containAudio()) {
// uint32_t ssrc1;
// memcpy(&ssrc1, makeRandStr(8, false).data() + 4, 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
// m_pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
// GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
// m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,m_pParser->getAudioSampleRate()));
//
// char configStr[32];
// const string & strAacCfg = m_pParser->getAudioCfg();
// snprintf(configStr, sizeof(configStr), "%02X%02x", strAacCfg[0], strAacCfg[1]);
// strSDP += StrPrinter << "m=audio 0 RTP/AVP " << m_pRtpMaker_aac->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:96\r\n";
// strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType()
// << " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n"
// << endl;
// strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType()
// << " streamtype=5;profile-level-id=1;mode=AAC-hbr;"
// << "sizelength=13;indexlength=3;indexdeltalength=3;config="
// << endl;
// strSDP.append(configStr, 4);
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" << m_pRtpMaker_aac->getInterleaved() / 2
// << "\r\n" << endl;
// }
m_pRtspSrc
.
reset
(
new
RtspMediaSource
(
getVhost
(),
getApp
(),
getId
()));
m_pRtspSrc
->
setListener
(
m_listener
);
...
...
src/Rtmp/RtmpToRtspMediaSource.h
查看文件 @
49daa1ba
...
...
@@ -67,8 +67,10 @@ public:
try
{
m_pParser
.
reset
(
new
RtmpParser
(
_metadata
));
m_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
m_pParser
,
m_bEnableHls
,
m_bEnableMp4
));
m_pParser
->
setOnAudioCB
(
std
::
bind
(
&
RtmpToRtspMediaSource
::
onGetAdts
,
this
,
placeholders
::
_1
));
m_pParser
->
setOnVideoCB
(
std
::
bind
(
&
RtmpToRtspMediaSource
::
onGetH264
,
this
,
placeholders
::
_1
));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAdts, this, placeholders::_1));
// m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
}
catch
(
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
}
...
...
src/Rtsp/RtpParser.cpp
查看文件 @
49daa1ba
...
...
@@ -91,8 +91,8 @@ RtpParser::RtpParser(const string& sdp) {
RtpParser
::~
RtpParser
()
{
}
bool
RtpParser
::
inputRtp
(
const
RtpPacket
&
rtp
)
{
auto
&
track
=
m_mapTracks
[
rtp
.
PT
];
bool
RtpParser
::
inputRtp
(
const
RtpPacket
::
Ptr
&
rtp
)
{
auto
&
track
=
m_mapTracks
[
rtp
->
PT
];
switch
(
track
.
type
)
{
case
TrackVideo
:
if
(
m_bHaveVideo
)
{
...
...
@@ -109,205 +109,19 @@ bool RtpParser::inputRtp(const RtpPacket& rtp) {
}
}
inline
bool
RtpParser
::
inputVideo
(
const
RtpPacket
&
rtppack
,
const
RtspTrack
&
track
)
{
const
uint8_t
*
frame
=
(
uint8_t
*
)
rtppack
.
payload
+
rtppack
.
offset
;
int
length
=
rtppack
.
length
-
rtppack
.
offset
;
NALU
nal
;
MakeNalu
(
*
frame
,
nal
);
//Type==1:P frame
//Type==6:SEI frame
//Type==7:SPS frame
//Type==8:PPS frame
if
(
nal
.
type
>=
0
&&
nal
.
type
<
24
)
{
//a full frame
m_h264frame
.
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
m_h264frame
.
buffer
.
append
((
char
*
)
frame
,
length
);
m_h264frame
.
type
=
nal
.
type
;
m_h264frame
.
timeStamp
=
rtppack
.
timeStamp
/
90
;
m_h264frame
.
sequence
=
rtppack
.
sequence
;
_onGetH264
(
m_h264frame
);
m_h264frame
.
buffer
.
clear
();
return
(
m_h264frame
.
type
==
7
);
}
if
(
nal
.
type
==
28
)
{
//FU-A
FU
fu
;
MakeFU
(
frame
[
1
],
fu
);
if
(
fu
.
S
==
1
)
{
//FU-A start
char
tmp
=
(
nal
.
forbidden_zero_bit
<<
7
|
nal
.
nal_ref_idc
<<
5
|
fu
.
type
);
m_h264frame
.
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
m_h264frame
.
buffer
.
push_back
(
tmp
);
m_h264frame
.
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
m_h264frame
.
type
=
fu
.
type
;
m_h264frame
.
timeStamp
=
rtppack
.
timeStamp
/
90
;
m_h264frame
.
sequence
=
rtppack
.
sequence
;
return
(
m_h264frame
.
type
==
7
);
//i frame
}
inline
bool
RtpParser
::
inputVideo
(
const
RtpPacket
::
Ptr
&
rtp
,
const
RtspTrack
&
track
)
{
if
(
rtppack
.
sequence
!=
(
uint16_t
)(
m_h264frame
.
sequence
+
1
))
{
m_h264frame
.
buffer
.
clear
();
WarnL
<<
"丢包,帧废弃:"
<<
rtppack
.
sequence
<<
","
<<
m_h264frame
.
sequence
;
return
false
;
}
m_h264frame
.
sequence
=
rtppack
.
sequence
;
if
(
fu
.
E
==
1
)
{
//FU-A end
m_h264frame
.
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
m_h264frame
.
timeStamp
=
rtppack
.
timeStamp
/
90
;
_onGetH264
(
m_h264frame
);
m_h264frame
.
buffer
.
clear
();
return
false
;
}
//FU-A mid
m_h264frame
.
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
return
false
;
}
WarnL
<<
nal
.
type
<<
" "
<<
rtppack
.
sequence
;
return
false
;
// 29 FU-B 单NAL单元B模式
// 24 STAP-A 单一时间的组合包
// 25 STAP-B 单一时间的组合包
// 26 MTAP16 多个时间的组合包
// 27 MTAP24 多个时间的组合包
// 0 udef
// 30 udef
// 31 udef
}
inline
void
RtpParser
::
onGetAudioTrack
(
const
RtspTrack
&
audio
)
{
for
(
auto
&
ch
:
const_cast
<
string
&>
(
audio
.
trackSdp
))
{
ch
=
tolower
(
ch
);
}
if
(
audio
.
trackSdp
.
find
(
"mpeg4-generic"
)
==
string
::
npos
)
{
throw
std
::
runtime_error
(
"只支持aac格式的音频!"
);
}
string
fConfigStr
=
FindField
(
audio
.
trackSdp
.
c_str
(),
"config="
,
"
\r\n
"
);
if
(
fConfigStr
.
size
()
!=
4
)
{
fConfigStr
=
FindField
(
audio
.
trackSdp
.
c_str
(),
"config="
,
";"
);
}
if
(
fConfigStr
.
size
()
!=
4
)
{
throw
std
::
runtime_error
(
"解析aac格式头失败!"
);
}
m_strAudioCfg
.
clear
();
unsigned
int
cfg1
;
sscanf
(
fConfigStr
.
substr
(
0
,
2
).
c_str
(),
"%02X"
,
&
cfg1
);
cfg1
&=
0x00FF
;
m_strAudioCfg
.
push_back
(
cfg1
);
unsigned
int
cfg2
;
sscanf
(
fConfigStr
.
substr
(
2
,
2
).
c_str
(),
"%02X"
,
&
cfg2
);
cfg2
&=
0x00FF
;
m_strAudioCfg
.
push_back
(
cfg2
);
makeAdtsHeader
(
m_strAudioCfg
,
m_adts
);
getAACInfo
(
m_adts
,
m_iSampleRate
,
m_iChannel
);
if
(
m_adts
.
profile
>=
3
){
throw
std
::
runtime_error
(
"不支持该profile的AAC"
);
}
}
inline
void
RtpParser
::
onGetVideoTrack
(
const
RtspTrack
&
video
)
{
if
(
video
.
trackSdp
.
find
(
"H264"
)
==
string
::
npos
)
{
throw
std
::
runtime_error
(
"只支持264格式的视频!"
);
}
string
sps_pps
=
FindField
(
video
.
trackSdp
.
c_str
(),
"sprop-parameter-sets="
,
"
\r\n
"
);
if
(
sps_pps
.
empty
()){
//SDP里面没SPS_PPS描述,需要在后续rtp中获取
m_bParseSpsDelay
=
true
;
return
;
}
string
base64_SPS
=
FindField
(
sps_pps
.
c_str
(),
NULL
,
","
);
string
base64_PPS
=
FindField
(
sps_pps
.
c_str
(),
","
,
NULL
);
if
(
base64_PPS
.
back
()
==
';'
){
base64_PPS
.
pop_back
();
}
uint8_t
SPS_BUF
[
256
],
PPS_BUF
[
256
];
int
SPS_LEN
=
av_base64_decode
(
SPS_BUF
,
base64_SPS
.
c_str
(),
sizeof
(
SPS_BUF
));
int
PPS_LEN
=
av_base64_decode
(
PPS_BUF
,
base64_PPS
.
c_str
(),
sizeof
(
PPS_BUF
));
m_strSPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
m_strSPS
.
append
((
char
*
)
SPS_BUF
,
SPS_LEN
);
m_strPPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
m_strPPS
.
append
((
char
*
)
PPS_BUF
,
PPS_LEN
);
string
strTmp
((
char
*
)
SPS_BUF
,
SPS_LEN
);
if
(
!
getAVCInfo
(
strTmp
,
m_iVideoWidth
,
m_iVideoHeight
,
m_fVideoFps
))
{
throw
std
::
runtime_error
(
"parse sdp failed"
);
}
}
inline
bool
RtpParser
::
inputAudio
(
const
RtpPacket
&
rtppack
,
const
RtspTrack
&
track
)
{
char
*
frame
=
(
char
*
)
rtppack
.
payload
+
rtppack
.
offset
;
int
length
=
rtppack
.
length
-
rtppack
.
offset
;
if
(
m_adts
.
aac_frame_length
+
length
-
4
>
sizeof
(
AACFrame
::
buffer
))
{
m_adts
.
aac_frame_length
=
7
;
return
false
;
}
memcpy
(
m_adts
.
buffer
+
m_adts
.
aac_frame_length
,
frame
+
4
,
length
-
4
);
m_adts
.
aac_frame_length
+=
(
length
-
4
);
if
(
rtppack
.
mark
==
true
)
{
m_adts
.
sequence
=
rtppack
.
sequence
;
m_adts
.
timeStamp
=
rtppack
.
timeStamp
*
(
1000.0
/
m_iSampleRate
);
writeAdtsHeader
(
m_adts
,
m_adts
.
buffer
);
onGetAdts
(
m_adts
);
m_adts
.
aac_frame_length
=
7
;
}
return
false
;
}
inline
void
RtpParser
::
_onGetH264
(
H264Frame
&
frame
)
{
switch
(
frame
.
type
)
{
case
5
:
{
//I
H264Frame
insertedFrame
;
insertedFrame
.
type
=
7
;
//SPS
insertedFrame
.
timeStamp
=
frame
.
timeStamp
;
insertedFrame
.
buffer
=
m_strSPS
;
onGetH264
(
insertedFrame
);
insertedFrame
.
type
=
8
;
//PPS
insertedFrame
.
timeStamp
=
frame
.
timeStamp
;
insertedFrame
.
buffer
=
m_strPPS
;
onGetH264
(
insertedFrame
);
onGetH264
(
frame
);
}
break
;
case
7
:
{
//SPS
m_strSPS
=
frame
.
buffer
;
if
(
m_bParseSpsDelay
&&
!
m_strSPS
.
empty
()){
m_bParseSpsDelay
=
false
;
getAVCInfo
(
m_strSPS
,
m_iVideoWidth
,
m_iVideoHeight
,
m_fVideoFps
);
}
}
break
;
case
8
:
//PPS
m_strPPS
=
frame
.
buffer
;
break
;
case
1
:
//B or P
onGetH264
(
frame
);
break
;
default
:
break
;
}
}
inline
void
RtpParser
::
onGetVideoTrack
(
const
RtspTrack
&
video
)
{
inline
void
RtpParser
::
onGetH264
(
H264Frame
&
frame
)
{
//frame.timeStamp=ticker0.elapsedTime();
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
if
(
onVideo
)
{
onVideo
(
frame
);
}
}
inline
void
RtpParser
::
onGetAdts
(
AACFrame
&
frame
)
{
//frame.timeStamp=ticker1.elapsedTime();
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
if
(
onAudio
)
{
onAudio
(
frame
);
}
inline
bool
RtpParser
::
inputAudio
(
const
RtpPacket
::
Ptr
&
rtppack
,
const
RtspTrack
&
track
)
{
}
}
/* namespace Rtsp */
...
...
src/Rtsp/RtpParser.h
查看文件 @
49daa1ba
...
...
@@ -47,57 +47,12 @@ public:
RtpParser
(
const
string
&
sdp
);
virtual
~
RtpParser
();
//返回值:true 代表是i帧第一个rtp包
bool
inputRtp
(
const
RtpPacket
&
rtp
);
void
setOnVideoCB
(
const
function
<
void
(
const
H264Frame
&
frame
)
>
&
cb
)
override
{
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
onVideo
=
cb
;
}
void
setOnAudioCB
(
const
function
<
void
(
const
AACFrame
&
frame
)
>
&
cb
)
override
{
lock_guard
<
recursive_mutex
>
lck
(
m_mtxCB
);
onAudio
=
cb
;
}
int
getVideoHeight
()
const
override
{
return
m_iVideoHeight
;
}
bool
inputRtp
(
const
RtpPacket
::
Ptr
&
rtp
);
int
getVideoWidth
()
const
override
{
return
m_iVideoWidth
;
}
float
getVideoFps
()
const
override
{
return
m_fVideoFps
;
}
int
getAudioSampleRate
()
const
override
{
return
m_iSampleRate
;
}
int
getAudioSampleBit
()
const
override
{
return
m_iSampleBit
;
}
int
getAudioChannel
()
const
override
{
return
m_iChannel
;
}
const
string
&
getPps
()
const
override
{
return
m_strPPS
;
}
const
string
&
getSps
()
const
override
{
return
m_strSPS
;
float
getDuration
()
const
override
{
return
m_fDuration
;
}
const
string
&
getAudioCfg
()
const
override
{
return
m_strAudioCfg
;
}
bool
containAudio
()
const
override
{
return
m_bHaveAudio
;
}
bool
containVideo
()
const
override
{
return
m_bHaveVideo
;
}
bool
isInited
()
const
override
{
if
(
m_bHaveAudio
&&
!
m_strAudioCfg
.
size
())
{
return
false
;
...
...
@@ -107,9 +62,6 @@ public:
}
return
true
;
}
float
getDuration
()
const
override
{
return
m_fDuration
;
}
private
:
std
::
unordered_map
<
uint8_t
,
RtspTrack
>
m_mapTracks
;
...
...
@@ -117,33 +69,16 @@ private:
inline
void
onGetVideoTrack
(
const
RtspTrack
&
video
);
//返回值:true 代表是i帧第一个rtp包
inline
bool
inputVideo
(
const
RtpPacket
&
rtp
,
const
RtspTrack
&
track
);
inline
bool
inputAudio
(
const
RtpPacket
&
rtp
,
const
RtspTrack
&
track
);
inline
void
_onGetH264
(
H264Frame
&
frame
);
inline
void
onGetH264
(
H264Frame
&
frame
);
inline
void
onGetAdts
(
AACFrame
&
frame
);
//video
H264Frame
m_h264frame
;
//aduio
AACFrame
m_adts
;
int
m_iSampleRate
=
44100
;
int
m_iSampleBit
=
16
;
int
m_iChannel
=
1
;
inline
bool
inputVideo
(
const
RtpPacket
::
Ptr
&
rtp
,
const
RtspTrack
&
track
);
inline
bool
inputAudio
(
const
RtpPacket
::
Ptr
&
rtp
,
const
RtspTrack
&
track
);
string
m_strSPS
;
string
m_strPPS
;
string
m_strAudioCfg
;
int
m_iVideoWidth
=
0
;
int
m_iVideoHeight
=
0
;
float
m_fVideoFps
=
0
;
bool
m_bHaveAudio
=
false
;
bool
m_bHaveVideo
=
false
;
float
m_fDuration
=
0
;
bool
m_bParseSpsDelay
=
false
;
function
<
void
(
const
H264Frame
&
frame
)
>
onVideo
;
function
<
void
(
const
AACFrame
&
frame
)
>
onAudio
;
recursive_mutex
m_mtxCB
;
};
...
...
src/Rtsp/RtspEncoder.h
查看文件 @
49daa1ba
...
...
@@ -108,12 +108,12 @@ public:
* @param mtu mtu大小,一般小于1500字节,推荐1400
*/
virtual
void
createRtpEncoder
(
uint32_t
ssrc
,
int
mtu
)
{
_encoder
=
RtpCodec
::
getRtpCodec
(
getCodecId
(),
ssrc
,
mtu
,
_sample_rate
,
_playload_type
,
getTrackType
()
*
2
);
_encoder
=
RtpCodec
::
getRtpCodec
ById
(
getCodecId
(),
ssrc
,
mtu
,
_sample_rate
,
_playload_type
,
getTrackType
()
*
2
);
}
private
:
RtpCodec
::
Ptr
_encoder
;
...
...
@@ -275,10 +275,8 @@ public:
* 构成函数
*/
RtspEncoder
(){
//自适应缓存
_rtpRing
=
std
::
make_shared
<
RtpRingInterface
::
RingType
>
(
0
);
//禁用缓存
_frameRing
=
std
::
make_shared
<
FrameRingInterface
::
RingType
>
(
1
);
_rtpRing
=
std
::
make_shared
<
RtpRingInterface
::
RingType
>
();
_frameRing
=
std
::
make_shared
<
FrameRingInterface
::
RingType
>
();
}
virtual
~
RtspEncoder
(){}
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
49daa1ba
...
...
@@ -442,7 +442,8 @@ bool RtspPlayer::sendPause(bool bPause,float fTime){
if
(
m_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
m_adFistStamp
[
i
]
=
m_adNowStamp
[
i
]
+
iTimeInc
*
90000.0
;
}
else
if
(
m_aTrackInfo
[
i
].
type
==
TrackAudio
){
m_adFistStamp
[
i
]
=
m_adNowStamp
[
i
]
+
iTimeInc
*
getAudioSampleRate
();
//todo(xzl) 修复此处
// m_adFistStamp[i] = m_adNowStamp[i] + iTimeInc * getAudioSampleRate();
}
m_adNowStamp
[
i
]
=
m_adFistStamp
[
i
];
}
...
...
@@ -718,7 +719,10 @@ float RtspPlayer::getProgressTime() const{
if
(
m_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
iTime
[
i
]
=
(
m_adNowStamp
[
i
]
-
m_adFistStamp
[
i
])
/
90000.0
;
}
else
if
(
m_aTrackInfo
[
i
].
type
==
TrackAudio
){
iTime
[
i
]
=
(
m_adNowStamp
[
i
]
-
m_adFistStamp
[
i
])
/
getAudioSampleRate
();
//todo(xzl) 修复此处
#if 0
iTime[i] = (m_adNowStamp[i] - m_adFistStamp[i]) / getAudioSampleRate();
#endif
}
}
return
m_fSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
...
...
src/Rtsp/RtspPlayerImp.h
查看文件 @
49daa1ba
...
...
@@ -71,8 +71,9 @@ private:
}
try
{
m_parser
.
reset
(
new
RtpParser
(
sdp
));
m_parser
->
setOnVideoCB
(
m_onGetVideoCB
);
m_parser
->
setOnAudioCB
(
m_onGetAudioCB
);
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
return
true
;
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
...
...
@@ -81,7 +82,7 @@ private:
}
void
onRecvRTP
(
const
RtpPacket
::
Ptr
&
rtppt
,
const
RtspTrack
&
track
)
override
{
if
(
m_parser
){
m_parser
->
inputRtp
(
*
rtppt
);
m_parser
->
inputRtp
(
rtppt
);
}
if
(
m_pRtspMediaSrc
){
...
...
src/Rtsp/RtspToRtmpMediaSource.cpp
查看文件 @
49daa1ba
...
...
@@ -63,8 +63,10 @@ void RtspToRtmpMediaSource::makeVideoConfigPkt() {
////////////sps
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
string
m_sps
=
m_pParser
->
getSps
().
substr
(
4
);
string
m_pps
=
m_pParser
->
getPps
().
substr
(
4
);
//todo(xzl) 修复此处
string
m_sps
;
//= m_pParser->getSps().substr(4);
string
m_pps
;
//= m_pParser->getPps().substr(4);
//DebugL<<hexdump(m_sps.data(), m_sps.size());
rtmpPkt
->
strBuf
.
push_back
(
m_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
m_sps
[
2
]);
// compat
...
...
@@ -145,6 +147,8 @@ void RtspToRtmpMediaSource::onGetAdts(const AACFrame& frame) {
}
void
RtspToRtmpMediaSource
::
makeAudioConfigPkt
()
{
//todo(xzl) 修复此处
#if 0
uint8_t flvStereoOrMono = (m_pParser->getAudioChannel() > 1);
uint8_t flvSampleRate;
switch (m_pParser->getAudioSampleRate()) {
...
...
@@ -182,6 +186,8 @@ void RtspToRtmpMediaSource::makeAudioConfigPkt() {
rtmpPkt->timeStamp = 0;
rtmpPkt->typeId = MSG_AUDIO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
#endif
}
void
RtspToRtmpMediaSource
::
makeMetaData
()
{
...
...
@@ -190,6 +196,9 @@ void RtspToRtmpMediaSource::makeMetaData() {
AMFValue
metaData
(
AMF_OBJECT
);
metaData
.
set
(
"duration"
,
m_pParser
->
getDuration
());
metaData
.
set
(
"fileSize"
,
0
);
//todo(xzl) 修复此处
#if 0
if (m_pParser->containVideo()) {
metaData.set("width", m_pParser->getVideoWidth());
metaData.set("height", m_pParser->getVideoHeight());
...
...
@@ -208,6 +217,7 @@ void RtspToRtmpMediaSource::makeMetaData() {
makeAudioConfigPkt();
}
#endif
m_pRtmpSrc
->
onGetMetaData
(
metaData
);
}
}
/* namespace Rtsp */
...
...
src/Rtsp/RtspToRtmpMediaSource.h
查看文件 @
49daa1ba
...
...
@@ -54,8 +54,9 @@ public:
try
{
m_pParser
.
reset
(
new
RtpParser
(
strSdp
));
m_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
m_pParser
,
m_bEnableHls
,
m_bEnableMp4
));
m_pParser
->
setOnAudioCB
(
std
::
bind
(
&
RtspToRtmpMediaSource
::
onGetAdts
,
this
,
placeholders
::
_1
));
m_pParser
->
setOnVideoCB
(
std
::
bind
(
&
RtspToRtmpMediaSource
::
onGetH264
,
this
,
placeholders
::
_1
));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAdts, this, placeholders::_1));
// m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
makeMetaData
();
}
catch
(
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
...
...
@@ -64,7 +65,7 @@ public:
}
virtual
void
onGetRTP
(
const
RtpPacket
::
Ptr
&
pRtppkt
,
bool
bKeyPos
)
override
{
if
(
m_pParser
)
{
bKeyPos
=
m_pParser
->
inputRtp
(
*
pRtppkt
);
bKeyPos
=
m_pParser
->
inputRtp
(
pRtppkt
);
}
RtspMediaSource
::
onGetRTP
(
pRtppkt
,
bKeyPos
);
}
...
...
@@ -77,7 +78,8 @@ public:
for
(
auto
&
pr
:
m_mapTracks
)
{
switch
(
pr
.
second
.
type
)
{
case
TrackAudio
:
{
pr
.
second
.
timeStamp
=
uiStamp
*
(
m_pParser
->
getAudioSampleRate
()
/
1000
.
0
);
//todo(xzl) 修复此处
// pr.second.timeStamp = uiStamp * (m_pParser->getAudioSampleRate() / 1000.0);
}
break
;
case
TrackVideo
:
{
...
...
@@ -89,6 +91,14 @@ public:
}
}
}
protected
:
void
onGetH264
(
const
H264Frame
&
frame
);
void
onGetAdts
(
const
AACFrame
&
frame
);
private
:
void
makeVideoConfigPkt
();
void
makeAudioConfigPkt
();
void
makeMetaData
();
private
:
RtpParser
::
Ptr
m_pParser
;
RtmpMediaSource
::
Ptr
m_pRtmpSrc
;
...
...
@@ -96,11 +106,7 @@ private:
MediaRecorder
::
Ptr
m_pRecorder
;
bool
m_bEnableHls
;
bool
m_bEnableMp4
;
void
onGetH264
(
const
H264Frame
&
frame
);
void
onGetAdts
(
const
AACFrame
&
frame
);
void
makeVideoConfigPkt
();
void
makeAudioConfigPkt
();
void
makeMetaData
();
};
}
/* namespace Rtsp */
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论