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
19b6a292
Commit
19b6a292
authored
Oct 29, 2018
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完成DevChannel类的视频
parent
d8a11734
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
101 行增加
和
225 行删除
+101
-225
src/Common/Device.cpp
+37
-194
src/Common/Device.h
+62
-29
src/MediaFile/HLSMaker.cpp
+2
-2
没有找到文件。
src/Common/Device.cpp
查看文件 @
19b6a292
...
...
@@ -35,31 +35,15 @@ using namespace toolkit;
namespace
mediakit
{
#if 0
DevChannel
::
DevChannel
(
const
char
*
strVhost
,
const
char
*
strApp
,
const
char
*
strId
,
float
fDuration
,
bool
bEanbleHls
,
bool bEnableMp4
) :
RtspToRtmpMediaSource(strVhost,strApp,strId,bEanbleHls,bEnableMp4) {
bool
bEnableMp4
)
:
MultiMediaSourceMuxer
(
strVhost
,
strApp
,
strId
,
fDuration
,
bEanbleHls
,
bEnableMp4
)
{}
_strSdp = "v=0\r\n";
_strSdp += "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
_strSdp += "s=RTSP Session, streamed by the ZL\r\n";
_strSdp += "i=ZL Live Stream\r\n";
_strSdp += "c=IN IP4 0.0.0.0\r\n";
_strSdp += "t=0 0\r\n";
//直播,时间长度永远
if(fDuration <= 0){
_strSdp += "a=range:npt=0-\r\n";
}else{
_strSdp += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl;
}
_strSdp += "a=control:*\r\n";
}
DevChannel::~DevChannel() {
}
DevChannel
::~
DevChannel
()
{}
#ifdef ENABLE_X264
void
DevChannel
::
inputYUV
(
char
*
apcYuv
[
3
],
int
aiYuvLen
[
3
],
uint32_t
uiStamp
)
{
...
...
@@ -100,211 +84,70 @@ void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
}
#endif //ENABLE_FAAC
void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t uiStamp) {
if (!_pRtpMaker_h264) {
uint32_t ui32Ssrc;
memcpy(&ui32Ssrc, makeRandStr(4, false).data(), 4);
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
onWrite(pkt,bKeyPos);
};
GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Rtp::kVideoMtuSize);
_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
}
if (!_bSdp_gotH264 && _video) {
makeSDP_264((unsigned char*) pcData, iDataLen);
}
int iOffset = 4;
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
iOffset = 3;
}
void
DevChannel
::
inputH264
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
,
int
prefixeSize
)
{
if
(
uiStamp
==
0
){
uiStamp
=
(
uint32_t
)
_aTicker
[
0
].
elapsedTime
();
}
_pRtpMaker_h264->makeRtp(pcData + iOffset, iDataLen - iOffset, uiStamp
);
inputFrame
(
std
::
make_shared
<
H264FrameNoCopyAble
>
((
char
*
)
pcData
,
iDataLen
,
uiStamp
,
prefixeSize
)
);
}
void
DevChannel
::
inputAAC
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
,
bool
withAdtsHeader
)
{
if
(
withAdtsHeader
){
inputAAC
(
pcData
+
7
,
iDataLen
-
7
,
uiStamp
,
pcData
);
} else if(_pAdtsHeader){
_pAdtsHeader->aac_frame_length = iDataLen;
writeAdtsHeader(*_pAdtsHeader,(uint8_t *)_pAdtsHeader->buffer);
inputAAC(pcData,iDataLen,uiStamp,(const char *)_pAdtsHeader->buffer);
}
else
{
inputAAC
(
pcData
,
iDataLen
,
uiStamp
,(
char
*
)
_adtsHeader
);
}
}
void
DevChannel
::
inputAAC
(
const
char
*
pcDataWithoutAdts
,
int
iDataLen
,
uint32_t
uiStamp
,
const
char
*
pcAdtsHeader
){
if (!_pRtpMaker_aac) {
uint32_t ssrc;
memcpy(&ssrc, makeRandStr(8, false).data() + 4, 4);
auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) {
onWrite(pkt,keyPos);
};
GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Rtp::kAudioMtuSize);
_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,_audio->iSampleRate));
}
if (!_bSdp_gotAAC && _audio && pcAdtsHeader) {
makeSDP_AAC((unsigned char*) pcAdtsHeader);
}
if
(
uiStamp
==
0
){
uiStamp
=
(
uint32_t
)
_aTicker
[
1
].
elapsedTime
();
}
if(pcDataWithoutAdts && iDataLen){
_pRtpMaker_aac->makeRtp(pcDataWithoutAdts, iDataLen, uiStamp);
}
}
inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) {
int offset = 4;
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
offset = 3;
}
switch (pcData[offset] & 0x1F) {
case 7:/*SPS frame*/
{
if (_uiSPSLen != 0) {
break;
}
memcpy(_aucSPS, pcData + offset, iDataLen - offset);
_uiSPSLen = iDataLen - offset;
}
break;
case 8:/*PPS frame*/
{
if (_uiPPSLen != 0) {
break;
}
memcpy(_aucPPS, pcData + offset, iDataLen - offset);
_uiPPSLen = iDataLen - offset;
}
break;
default:
break;
}
if (!_uiSPSLen || !_uiPPSLen) {
return;
}
char acTmp[256];
int profile_level_id = 0;
if (_uiSPSLen >= 4) { // sanity check
profile_level_id = (_aucSPS[1] << 16) | (_aucSPS[2] << 8) | _aucSPS[3]; // profile_idc|constraint_setN_flag|level_idc
}
//视频通道
_strSdp += StrPrinter << "m=video 0 RTP/AVP "
<< _pRtpMaker_h264->getPlayloadType() << "\r\n" << endl;
_strSdp += "b=AS:5100\r\n";
_strSdp += StrPrinter << "a=rtpmap:" << _pRtpMaker_h264->getPlayloadType()
<< " H264/" << _pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
_strSdp += StrPrinter << "a=fmtp:" << _pRtpMaker_h264->getPlayloadType()
<< " packetization-mode=1;profile-level-id=" << endl;
memset(acTmp, 0, sizeof(acTmp));
sprintf(acTmp, "%06X", profile_level_id);
_strSdp += acTmp;
_strSdp += ";sprop-parameter-sets=";
memset(acTmp, 0, sizeof(acTmp));
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) _aucSPS, _uiSPSLen);
//WarnL<<"SPS base64:"<<strTemp;
//WarnL<<"SPS hexdump:"<<hexdump(SPS_BUF, SPS_LEN);
_strSdp += acTmp;
_strSdp += ",";
memset(acTmp, 0, sizeof(acTmp));
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) _aucPPS, _uiPPSLen);
_strSdp += acTmp;
_strSdp += "\r\n";
if (_video->iFrameRate > 0 && _video->iHeight > 0 && _video->iWidth > 0) {
_strSdp += "a=framerate:";
_strSdp += StrPrinter << _video->iFrameRate << endl;
_strSdp += StrPrinter << "\r\na=framesize:"
<< _pRtpMaker_h264->getPlayloadType() << " " << endl;
_strSdp += StrPrinter << _video->iWidth << endl;
_strSdp += "-";
_strSdp += StrPrinter << _video->iHeight << endl;
_strSdp += "\r\n";
}
_strSdp += StrPrinter << "a=control:trackID="
<< _pRtpMaker_h264->getInterleaved() / 2 << "\r\n" << endl;
_bSdp_gotH264 = true;
if (_audio) {
if (_bSdp_gotAAC) {
makeSDP(_strSdp);
}
} else {
makeSDP(_strSdp);
}
}
inline void DevChannel::makeSDP_AAC(unsigned char *fixedHeader) {
auto audioSpecificConfig = makeAdtsConfig(fixedHeader);
if (audioSpecificConfig.size() != 2) {
return;
}
char fConfigStr[5] = { 0 };
sprintf(fConfigStr, "%02X%02x", (uint8_t)audioSpecificConfig[0],(uint8_t)audioSpecificConfig[1]);
_strSdp += StrPrinter << "m=audio 0 RTP/AVP "
<< _pRtpMaker_aac->getPlayloadType() << "\r\n" << endl;
_strSdp += "b=AS:96\r\n";
_strSdp += StrPrinter << "a=rtpmap:" << _pRtpMaker_aac->getPlayloadType()
<< " MPEG4-GENERIC/" << _pRtpMaker_aac->getSampleRate() << "\r\n"
<< endl;
_strSdp += StrPrinter << "a=fmtp:" << _pRtpMaker_aac->getPlayloadType()
<< " streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
<< endl;
_strSdp += fConfigStr;
_strSdp += "\r\n";
_strSdp += StrPrinter << "a=control:trackID="
<< _pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl;
_bSdp_gotAAC = true;
if (_video) {
if (_bSdp_gotH264) {
makeSDP(_strSdp);
}
if
(
pcAdtsHeader
+
7
==
pcDataWithoutAdts
){
inputFrame
(
std
::
make_shared
<
AACFrameNoCopyAble
>
((
char
*
)
pcDataWithoutAdts
-
7
,
iDataLen
+
7
,
uiStamp
,
7
));
}
else
{
makeSDP(_strSdp);
char
*
dataWithAdts
=
new
char
[
iDataLen
+
7
];
memcpy
(
dataWithAdts
,
pcAdtsHeader
,
7
);
memcpy
(
dataWithAdts
+
7
,
pcDataWithoutAdts
,
iDataLen
);
inputFrame
(
std
::
make_shared
<
AACFrameNoCopyAble
>
(
dataWithAdts
,
iDataLen
+
7
,
uiStamp
,
7
));
delete
[]
dataWithAdts
;
}
}
void DevChannel::makeSDP(const string& strSdp) {
onGetSDP(strSdp);
}
void
DevChannel
::
initVideo
(
const
VideoInfo
&
info
)
{
_video.reset(new VideoInfo(info));
_video
=
std
::
make_shared
<
VideoInfo
>
(
info
);
addTrack
(
std
::
make_shared
<
H264Track
>
());
}
void
DevChannel
::
initAudio
(
const
AudioInfo
&
info
)
{
_audio.reset(new AudioInfo(info));
_pAdtsHeader = std::make_shared<AACFrame>();
_pAdtsHeader->syncword = 0x0FFF;
_pAdtsHeader->id = 0;
_pAdtsHeader->layer = 0;
_pAdtsHeader->protection_absent = 1;
_pAdtsHeader->profile = info.iProfile;//audioObjectType - 1;
_audio
=
std
::
make_shared
<
AudioInfo
>
(
info
);
addTrack
(
std
::
make_shared
<
AACTrack
>
());
AACFrame
adtsHeader
;
adtsHeader
.
syncword
=
0x0FFF
;
adtsHeader
.
id
=
0
;
adtsHeader
.
layer
=
0
;
adtsHeader
.
protection_absent
=
1
;
adtsHeader
.
profile
=
info
.
iProfile
;
//audioObjectType - 1;
int
i
=
0
;
for
(
auto
rate
:
samplingFrequencyTable
){
if
(
rate
==
info
.
iSampleRate
){
_pAdtsHeader->
sf_index = i;
adtsHeader
.
sf_index
=
i
;
};
++
i
;
}
_pAdtsHeader->private_bit = 0;
_pAdtsHeader->channel_configuration = info.iChannel;
_pAdtsHeader->original = 0;
_pAdtsHeader->home = 0;
_pAdtsHeader->copyright_identification_bit = 0;
_pAdtsHeader->copyright_identification_start = 0;
_pAdtsHeader->aac_frame_length = 7;
_pAdtsHeader->adts_buffer_fullness = 2047;
_pAdtsHeader->no_raw_data_blocks_in_frame = 0;
adtsHeader
.
private_bit
=
0
;
adtsHeader
.
channel_configuration
=
info
.
iChannel
;
adtsHeader
.
original
=
0
;
adtsHeader
.
home
=
0
;
adtsHeader
.
copyright_identification_bit
=
0
;
adtsHeader
.
copyright_identification_start
=
0
;
adtsHeader
.
aac_frame_length
=
7
;
adtsHeader
.
adts_buffer_fullness
=
2047
;
adtsHeader
.
no_raw_data_blocks_in_frame
=
0
;
writeAdtsHeader
(
adtsHeader
,
_adtsHeader
);
}
#endif
}
/* namespace mediakit */
src/Common/Device.h
查看文件 @
19b6a292
...
...
@@ -31,10 +31,8 @@
#include <string>
#include <functional>
#include "Util/util.h"
#include "Player/Player.h"
#include "Rtsp/RtspToRtmpMediaSource.h"
#include "RtspMuxer/RtspSdp.h"
#include "Util/TimeTicker.h"
#include "Player/Player.h"
#include "Common/MultiMediaSourceMuxer.h"
using
namespace
std
;
...
...
@@ -52,7 +50,6 @@ using namespace toolkit;
namespace
mediakit
{
#if 0
class
VideoInfo
{
public
:
int
iWidth
;
...
...
@@ -67,37 +64,85 @@ public:
int
iProfile
;
};
class DevChannel : public RtspToRtmpMediaSource{
/**
* 该类已经废弃,保留只为兼容旧代码,请直接使用MultiMediaSourceMuxer类!
*/
class
DevChannel
:
public
MultiMediaSourceMuxer
{
public
:
typedef
std
::
shared_ptr
<
DevChannel
>
Ptr
;
//fDuration<=0为直播,否则为点播
DevChannel(const char *strVhost,
DevChannel
(
const
char
*
strVhost
,
const
char
*
strApp
,
const
char
*
strId
,
float
fDuration
=
0
,
bool
bEanbleHls
=
true
,
bool
bEnableMp4
=
false
);
virtual
~
DevChannel
();
void initVideo(const VideoInfo &info);
/**
* 初始化h264视频Track
* 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr );
* @param info
*/
void
initVideo
(
const
VideoInfo
&
info
);
/**
* 初始化aac音频Track
* 相当于MultiMediaSourceMuxer::addTrack(AACTrack::Ptr );
* @param info
*/
void
initAudio
(
const
AudioInfo
&
info
);
void inputH264(const char *pcData, int iDataLen, uint32_t uiStamp);
/**
* 输入264帧
* @param pcData 264单帧数据指针
* @param iDataLen 数据指针长度
* @param uiStamp 时间戳,单位毫秒
* @param prefixSize 264 其实头字节数,起始头可以是0x00 00 00 01 或 0x 00 00 01 或者没有起始头
*/
void
inputH264
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
,
int
prefixSize
=
4
);
/**
* 输入可能带adts头的aac帧
* @param pcDataWithAdts 可能带adts头的aac帧
* @param iDataLen 帧数据长度
* @param uiStamp 时间戳,单位毫秒
* @param withAdtsHeader 是否带adts头
*/
void
inputAAC
(
const
char
*
pcDataWithAdts
,
int
iDataLen
,
uint32_t
uiStamp
,
bool
withAdtsHeader
=
true
);
/**
* 输入不带adts头的aac帧
* @param pcDataWithoutAdts 不带adts头的aac帧
* @param iDataLen 帧数据长度
* @param uiStamp 时间戳,单位毫秒
* @param pcAdtsHeader adts头
*/
void
inputAAC
(
const
char
*
pcDataWithoutAdts
,
int
iDataLen
,
uint32_t
uiStamp
,
const
char
*
pcAdtsHeader
);
#ifdef ENABLE_X264
void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp);
/**
* 输入yuv420p视频帧,内部会完成编码并调用inputH264方法
* @param apcYuv
* @param aiYuvLen
* @param uiStamp
*/
void
inputYUV
(
char
*
apcYuv
[
3
],
int
aiYuvLen
[
3
],
uint32_t
uiStamp
);
#endif //ENABLE_X264
#ifdef ENABLE_FAAC
void inputPCM(char *pcData, int iDataLen, uint32_t uiStamp);
/**
* 输入pcm数据,内部会完成编码并调用inputAAC方法
* @param pcData
* @param iDataLen
* @param uiStamp
*/
void
inputPCM
(
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
);
#endif //ENABLE_FAAC
private
:
inline void makeSDP_264(unsigned char *pucData, int iDataLen);
inline void makeSDP_AAC(unsigned char *pucData);
inline void makeSDP(const string& strSdp);
#ifdef ENABLE_X264
std
::
shared_ptr
<
H264Encoder
>
_pH264Enc
;
#endif //ENABLE_X264
...
...
@@ -105,25 +150,13 @@ private:
#ifdef ENABLE_FAAC
std
::
shared_ptr
<
AACEncoder
>
_pAacEnc
;
#endif //ENABLE_FAAC
RtpMaker_AAC::Ptr _pRtpMaker_aac;
RtpMaker_H264::Ptr _pRtpMaker_h264;
bool _bSdp_gotH264 = false;
bool _bSdp_gotAAC = false;
unsigned char _aucSPS[256];
unsigned int _uiSPSLen = 0;
unsigned char _aucPPS[256];
unsigned int _uiPPSLen = 0;
std::shared_ptr<VideoInfo> _video;
std::shared_ptr<AudioInfo> _audio;
std
::
shared_ptr
<
VideoInfo
>
_video
;
std
::
shared_ptr
<
AudioInfo
>
_audio
;
SmoothTicker
_aTicker
[
2
];
std::shared_ptr<AACFrame> _pAdtsHeader
;
uint8_t
_adtsHeader
[
7
]
;
};
#endif //0
typedef
MultiMediaSourceMuxer
DevChannel
;
}
/* namespace mediakit */
#endif
/* DEVICE_DEVICE_H_ */
src/MediaFile/HLSMaker.cpp
查看文件 @
19b6a292
...
...
@@ -185,10 +185,10 @@ bool HLSMaker::removets() {
void
HLSMaker
::
onTrackFrame
(
const
Frame
::
Ptr
&
frame
)
{
switch
(
frame
->
getCodecId
()){
case
CodecH264
:{
if
(
frame
->
prefixSize
()
==
4
){
if
(
frame
->
prefixSize
()
!=
0
){
inputH264
(
frame
->
data
(),
frame
->
size
(),
frame
->
stamp
());
}
else
{
WarnL
<<
"h264必须要有头4个字节的前缀"
;
WarnL
<<
"h264必须要有头4个
或3个
字节的前缀"
;
}
}
break
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论