diff --git a/src/Common/Device.cpp b/src/Common/Device.cpp index 163541ba..0e4bebdf 100644 --- a/src/Common/Device.cpp +++ b/src/Common/Device.cpp @@ -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((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:"<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); - } + if(pcAdtsHeader + 7 == pcDataWithoutAdts){ + inputFrame(std::make_shared((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(dataWithAdts,iDataLen + 7,uiStamp,7)); + delete [] dataWithAdts; } } -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); - } - } else { - makeSDP(_strSdp); - } -} - -void DevChannel::makeSDP(const string& strSdp) { - onGetSDP(strSdp); -} void DevChannel::initVideo(const VideoInfo& info) { - _video.reset(new VideoInfo(info)); + _video = std::make_shared(info); + addTrack(std::make_shared()); } void DevChannel::initAudio(const AudioInfo& info) { - _audio.reset(new AudioInfo(info)); - _pAdtsHeader = std::make_shared(); + _audio = std::make_shared(info); + addTrack(std::make_shared()); - _pAdtsHeader->syncword = 0x0FFF; - _pAdtsHeader->id = 0; - _pAdtsHeader->layer = 0; - _pAdtsHeader->protection_absent = 1; - _pAdtsHeader->profile = info.iProfile;//audioObjectType - 1; + 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 */ diff --git a/src/Common/Device.h b/src/Common/Device.h index 01019d20..032e89fc 100644 --- a/src/Common/Device.h +++ b/src/Common/Device.h @@ -31,10 +31,8 @@ #include #include #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 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 _pH264Enc; #endif //ENABLE_X264 @@ -105,25 +150,13 @@ private: #ifdef ENABLE_FAAC std::shared_ptr _pAacEnc; #endif //ENABLE_FAAC - RtpMaker_AAC::Ptr _pRtpMaker_aac; - RtpMaker_H264::Ptr _pRtpMaker_h264; - bool _bSdp_gotH264 = false; - bool _bSdp_gotAAC = false; + std::shared_ptr _video; + std::shared_ptr _audio; - unsigned char _aucSPS[256]; - unsigned int _uiSPSLen = 0; - unsigned char _aucPPS[256]; - unsigned int _uiPPSLen = 0; - std::shared_ptr _video; - std::shared_ptr _audio; SmoothTicker _aTicker[2]; - std::shared_ptr _pAdtsHeader; + uint8_t _adtsHeader[7]; }; -#endif //0 - -typedef MultiMediaSourceMuxer DevChannel; - } /* namespace mediakit */ #endif /* DEVICE_DEVICE_H_ */ diff --git a/src/MediaFile/HLSMaker.cpp b/src/MediaFile/HLSMaker.cpp index 35e88d77..221ac9ac 100644 --- a/src/MediaFile/HLSMaker.cpp +++ b/src/MediaFile/HLSMaker.cpp @@ -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;