diff --git a/src/Common/Device.h b/src/Common/Device.h index 73832294..5fc933cc 100644 --- a/src/Common/Device.h +++ b/src/Common/Device.h @@ -32,7 +32,6 @@ #include #include "Util/util.h" #include "Util/TimeTicker.h" -#include "Player/Player.h" #include "Common/MultiMediaSourceMuxer.h" using namespace std; diff --git a/src/Common/MediaSink.h b/src/Common/MediaSink.h index a57dac2b..0963f73d 100644 --- a/src/Common/MediaSink.h +++ b/src/Common/MediaSink.h @@ -29,8 +29,8 @@ #include #include -#include "Player/Frame.h" -#include "Player/Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" using namespace std; using namespace toolkit; diff --git a/src/Extension/AAC.cpp b/src/Extension/AAC.cpp new file mode 100644 index 00000000..2e43da8c --- /dev/null +++ b/src/Extension/AAC.cpp @@ -0,0 +1,120 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include "AAC.h" + +namespace mediakit{ + +void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) { + pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit + pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit + pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit + pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit + pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit + + pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit + pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit + pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit + pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit + + pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit + pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit + pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit + pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit + pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit + pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit + + pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit + + pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit + pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit + + pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit + pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit +} +string makeAdtsConfig(const uint8_t *pcAdts){ + if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) { + return ""; + } + // Get and check the 'profile': + unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits + if (profile == 3) { + return ""; + } + + // Get and check the 'sampling_frequency_index': + unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits + if (samplingFrequencyTable[sampling_frequency_index] == 0) { + return ""; + } + + // Get and check the 'channel_configuration': + unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2) + | ((pcAdts[3] & 0xC0) >> 6); // 3 bits + + unsigned char audioSpecificConfig[2]; + unsigned char const audioObjectType = profile + 1; + audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1); + audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3); + return string((char *)audioSpecificConfig,2); +} +void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) { + uint8_t cfg1 = strAudioCfg[0]; + uint8_t cfg2 = strAudioCfg[1]; + + int audioObjectType; + int sampling_frequency_index; + int channel_configuration; + + audioObjectType = cfg1 >> 3; + sampling_frequency_index = ((cfg1 & 0x07) << 1) | (cfg2 >> 7); + channel_configuration = (cfg2 & 0x7F) >> 3; + + adts.syncword = 0x0FFF; + adts.id = 0; + adts.layer = 0; + adts.protection_absent = 1; + adts.profile = audioObjectType - 1; + adts.sf_index = sampling_frequency_index; + adts.private_bit = 0; + adts.channel_configuration = channel_configuration; + adts.original = 0; + adts.home = 0; + adts.copyright_identification_bit = 0; + adts.copyright_identification_start = 0; + adts.aac_frame_length = 7; + adts.adts_buffer_fullness = 2047; + adts.no_raw_data_blocks_in_frame = 0; +} +void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){ + iSampleRate = samplingFrequencyTable[adts.sf_index]; + iChannel = adts.channel_configuration; +} + +}//namespace mediakit + + diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h new file mode 100644 index 00000000..c2a130fe --- /dev/null +++ b/src/Extension/AAC.h @@ -0,0 +1,266 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ZLMEDIAKIT_AAC_H +#define ZLMEDIAKIT_AAC_H + +#include "Frame.h" +#include "Track.h" + +namespace mediakit{ + +class AACFrame; + +unsigned const samplingFrequencyTable[16] = { 96000, 88200, + 64000, 48000, + 44100, 32000, + 24000, 22050, + 16000, 12000, + 11025, 8000, + 7350, 0, 0, 0 }; + +void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts); +void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ; +string makeAdtsConfig(const uint8_t *pcAdts); +void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel); + + + /** + * aac帧,包含adts头 + */ +class AACFrame : public Frame { +public: + typedef std::shared_ptr Ptr; + + char *data() const override{ + return (char *)buffer; + } + uint32_t size() const override { + return aac_frame_length; + } + uint32_t stamp() const override { + return timeStamp; + } + uint32_t prefixSize() const override{ + return iPrefixSize; + } + + TrackType getTrackType() const override{ + return TrackAudio; + } + + CodecId getCodecId() const override{ + return CodecAAC; + } + + bool keyFrame() const override { + return false; + } +public: + unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 + unsigned int id; //1 bslbf MPEG 标示符, 设置为1 + unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ + unsigned int protection_absent; //1 bslbf 表示是否误码校验 + unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC + unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 + unsigned int private_bit; //1 bslbf + unsigned int channel_configuration; //3 uimsbf 表示声道数 + unsigned int original; //1 bslbf + unsigned int home; //1 bslbf + //下面的为改变的参数即每一帧都不同 + unsigned int copyright_identification_bit; //1 bslbf + unsigned int copyright_identification_start; //1 bslbf + unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block + unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 +//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. +//所以说number_of_raw_data_blocks_in_frame == 0 +//表示说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; +} ; + +class AACFrameNoCopyAble : public FrameNoCopyAble { +public: + typedef std::shared_ptr Ptr; + + AACFrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 7){ + buffer_ptr = ptr; + buffer_size = size; + timeStamp = stamp; + iPrefixSize = prefixeSize; + } + + TrackType getTrackType() const override{ + return TrackAudio; + } + + CodecId getCodecId() const override{ + return CodecAAC; + } + + bool keyFrame() const override { + return false; + } +} ; + + +/** + * aac音频通道 + */ +class AACTrack : public AudioTrack{ +public: + typedef std::shared_ptr Ptr; + + /** + * 延后获取adts头信息 + * 在随后的inputFrame中获取adts头信息 + */ + AACTrack(){} + + /** + * 构造aac类型的媒体 + * @param aac_cfg aac两个字节的配置信息 + */ + AACTrack(const string &aac_cfg){ + if(aac_cfg.size() != 2){ + throw std::invalid_argument("adts配置必须为2个字节"); + } + _cfg = aac_cfg; + parseAacCfg(_cfg); + } + + /** + * 构造aac类型的媒体 + * @param adts_header adts头,7个字节 + * @param adts_header_len adts头长度,不少于7个字节 + */ + AACTrack(const char *adts_header,int adts_header_len = 7){ + if(adts_header_len < 7){ + throw std::invalid_argument("adts头必须不少于7个字节"); + } + _cfg = makeAdtsConfig((uint8_t*)adts_header); + parseAacCfg(_cfg); + } + + /** + * 构造aac类型的媒体 + * @param aac_frame_with_adts 带adts头的aac帧 + */ + AACTrack(const Frame::Ptr &aac_frame_with_adts){ + if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){ + throw std::invalid_argument("必须输入带adts头的aac帧"); + } + _cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data()); + parseAacCfg(_cfg); + } + + /** + * 获取aac两个字节的配置 + * @return + */ + const string &getAacCfg() const{ + return _cfg; + } + + /** + * 返回编码类型 + * @return + */ + CodecId getCodecId() const override{ + return CodecAAC; + } + + /** + * 在获取aac_cfg前是无效的Track + * @return + */ + bool ready() override { + return !_cfg.empty(); + } + + + /** + * 返回音频采样率 + * @return + */ + int getAudioSampleRate() const override{ + return _sampleRate; + } + /** + * 返回音频采样位数,一般为16或8 + * @return + */ + int getAudioSampleBit() const override{ + return _sampleBit; + } + /** + * 返回音频通道数 + * @return + */ + int getAudioChannel() const override{ + return _channel; + } + + /** + * 输入数据帧,并获取aac_cfg + * @param frame 数据帧 + */ + void inputFrame(const Frame::Ptr &frame) override{ + if(_cfg.empty() && frame->prefixSize() >= 7){ + //7个字节的adts头 + _cfg = makeAdtsConfig(reinterpret_cast(frame->data())); + parseAacCfg(_cfg); + } + AudioTrack::inputFrame(frame); + } +private: + /** + * 解析2个字节的aac配置 + * @param aac_cfg + */ + void parseAacCfg(const string &aac_cfg){ + AACFrame aacFrame; + makeAdtsHeader(aac_cfg,aacFrame); + getAACInfo(aacFrame,_sampleRate,_channel); + } + Track::Ptr clone() override { + return std::make_shared::type >(*this); + } +private: + string _cfg; + int _sampleRate = 0; + int _sampleBit = 16; + int _channel = 0; +}; + + +}//namespace mediakit + + +#endif //ZLMEDIAKIT_AAC_H diff --git a/src/Common/Factory.cpp b/src/Extension/Factory.cpp similarity index 100% rename from src/Common/Factory.cpp rename to src/Extension/Factory.cpp diff --git a/src/Common/Factory.h b/src/Extension/Factory.h similarity index 99% rename from src/Common/Factory.h rename to src/Extension/Factory.h index 926db15d..a0924ad1 100644 --- a/src/Common/Factory.h +++ b/src/Extension/Factory.h @@ -29,7 +29,7 @@ #include #include "Rtmp/amf.h" -#include "Player/Track.h" +#include "Extension/Track.h" #include "RtspMuxer/RtspSdp.h" #include "RtspMuxer/RtpCodec.h" #include "RtmpMuxer/RtmpCodec.h" diff --git a/src/Player/Frame.h b/src/Extension/Frame.h similarity index 61% rename from src/Player/Frame.h rename to src/Extension/Frame.h index b7a1547b..18dff05d 100644 --- a/src/Player/Frame.h +++ b/src/Extension/Frame.h @@ -40,6 +40,7 @@ namespace mediakit{ typedef enum { CodecInvalid = -1, CodecH264 = 0, + CodecH265, CodecAAC, CodecMax = 0x7FFF } CodecId; @@ -261,106 +262,6 @@ private: map _delegateMap; }; - -/** - * 264帧类 - */ -class H264Frame : public Frame { -public: - typedef std::shared_ptr Ptr; - - char *data() const override{ - return (char *)buffer.data(); - } - uint32_t size() const override { - return buffer.size(); - } - uint32_t stamp() const override { - return timeStamp; - } - uint32_t prefixSize() const override{ - return iPrefixSize; - } - - TrackType getTrackType() const override{ - return TrackVideo; - } - - CodecId getCodecId() const override{ - return CodecH264; - } - - bool keyFrame() const override { - return type == 5; - } -public: - uint16_t sequence; - uint32_t timeStamp; - unsigned char type; - string buffer; - uint32_t iPrefixSize = 4; -}; - - -/** - * aac帧,包含adts头 - */ -class AACFrame : public Frame { -public: - typedef std::shared_ptr Ptr; - - char *data() const override{ - return (char *)buffer; - } - uint32_t size() const override { - return aac_frame_length; - } - uint32_t stamp() const override { - return timeStamp; - } - uint32_t prefixSize() const override{ - return iPrefixSize; - } - - TrackType getTrackType() const override{ - return TrackAudio; - } - - CodecId getCodecId() const override{ - return CodecAAC; - } - - bool keyFrame() const override { - return false; - } -public: - unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 - unsigned int id; //1 bslbf MPEG 标示符, 设置为1 - unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ - unsigned int protection_absent; //1 bslbf 表示是否误码校验 - unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC - unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 - unsigned int private_bit; //1 bslbf - unsigned int channel_configuration; //3 uimsbf 表示声道数 - unsigned int original; //1 bslbf - unsigned int home; //1 bslbf - //下面的为改变的参数即每一帧都不同 - unsigned int copyright_identification_bit; //1 bslbf - unsigned int copyright_identification_start; //1 bslbf - unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block - unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 -//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. -//所以说number_of_raw_data_blocks_in_frame == 0 -//表示说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; -} ; - - - class FrameNoCopyAble : public Frame{ public: typedef std::shared_ptr Ptr; @@ -384,53 +285,7 @@ public: }; -class H264FrameNoCopyAble : public FrameNoCopyAble { -public: - typedef std::shared_ptr Ptr; - H264FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){ - buffer_ptr = ptr; - buffer_size = size; - timeStamp = stamp; - iPrefixSize = prefixeSize; - } - - TrackType getTrackType() const override{ - return TrackVideo; - } - - CodecId getCodecId() const override{ - return CodecH264; - } - - bool keyFrame() const override { - return (buffer_ptr[iPrefixSize] & 0x1F) == 5; - } -}; - -class AACFrameNoCopyAble : public FrameNoCopyAble { -public: - typedef std::shared_ptr Ptr; - - AACFrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 7){ - buffer_ptr = ptr; - buffer_size = size; - timeStamp = stamp; - iPrefixSize = prefixeSize; - } - - TrackType getTrackType() const override{ - return TrackAudio; - } - - CodecId getCodecId() const override{ - return CodecAAC; - } - - bool keyFrame() const override { - return false; - } -} ; }//namespace mediakit diff --git a/src/Player/Player.h b/src/Extension/H264.cpp similarity index 56% rename from src/Player/Player.h rename to src/Extension/H264.cpp index a9b090c7..c62aa09a 100644 --- a/src/Player/Player.h +++ b/src/Extension/H264.cpp @@ -24,29 +24,33 @@ * SOFTWARE. */ -#ifndef SRC_PLAYER_PLAYER_H_ -#define SRC_PLAYER_PLAYER_H_ -#include -#include "Frame.h" +#include "H264.h" +#include "H264/SPSParser.h" +#include "Util/logger.h" +using namespace toolkit; -using namespace std; -using namespace mediakit; +namespace mediakit{ -unsigned const samplingFrequencyTable[16] = { 96000, 88200, - 64000, 48000, - 44100, 32000, - 24000, 22050, - 16000, 12000, - 11025, 8000, - 7350, 0, 0, 0 }; +bool getAVCInfo(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) { + return getAVCInfo(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps); +} +bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){ + T_GetBitContext tGetBitBuf; + T_SPS tH264SpsInfo; + memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); + memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo)); + tGetBitBuf.pu8Buf = (uint8_t*)sps + 1; + tGetBitBuf.iBufSize = sps_len - 1; + if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){ + return false; + } + h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight); + h264GeFramerate(&tH264SpsInfo, &iVideoFps); + //ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; + return true; +} -void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts); -void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ; -string makeAdtsConfig(const uint8_t *pcAdts); -void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel); -bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); -bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); +}//namespace mediakit -#endif /* SRC_PLAYER_PLAYER_H_ */ diff --git a/src/Player/Track.h b/src/Extension/H264.h similarity index 56% rename from src/Player/Track.h rename to src/Extension/H264.h index 7ecb2058..13acc97e 100644 --- a/src/Player/Track.h +++ b/src/Extension/H264.h @@ -24,107 +24,82 @@ * SOFTWARE. */ -#ifndef ZLMEDIAKIT_TRACK_H -#define ZLMEDIAKIT_TRACK_H +#ifndef ZLMEDIAKIT_H264_H +#define ZLMEDIAKIT_H264_H -#include -#include #include "Frame.h" -#include "Util/RingBuffer.h" -#include "Rtsp/Rtsp.h" -#include "Player.h" -using namespace toolkit; +#include "Track.h" namespace mediakit{ -/** - * 媒体通道描述类,也支持帧输入输出 - */ -class Track : public FrameRingInterfaceDelegate , public CodecInfo{ -public: - typedef std::shared_ptr Ptr; - Track(){} - - virtual ~Track(){} - - /** - * 是否准备好,准备好才能获取譬如sps pps等信息 - * @return - */ - virtual bool ready() = 0; - - /** - * 克隆接口,用于复制本对象用 - * 在调用该接口时只会复制派生类的信息 - * 环形缓存和代理关系不能拷贝,否则会关系紊乱 - * @return - */ - virtual Track::Ptr clone() = 0; - - /** - * 复制拷贝,只能拷贝派生类的信息, - * 环形缓存和代理关系不能拷贝,否则会关系紊乱 - * @param that - */ - Track(const Track &that){} -}; +bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); +bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); /** - * 视频通道描述Track类,支持获取宽高fps信息 + * 264帧类 */ -class VideoTrack : public Track { +class H264Frame : public Frame { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - TrackType getTrackType() const override { return TrackVideo;}; + char *data() const override{ + return (char *)buffer.data(); + } + uint32_t size() const override { + return buffer.size(); + } + uint32_t stamp() const override { + return timeStamp; + } + uint32_t prefixSize() const override{ + return iPrefixSize; + } - /** - * 返回视频高度 - * @return - */ - virtual int getVideoHeight() const = 0; + TrackType getTrackType() const override{ + return TrackVideo; + } - /** - * 返回视频宽度 - * @return - */ - virtual int getVideoWidth() const = 0; + CodecId getCodecId() const override{ + return CodecH264; + } - /** - * 返回视频fps - * @return - */ - virtual float getVideoFps() const = 0; + bool keyFrame() const override { + return type == 5; + } +public: + uint16_t sequence; + uint32_t timeStamp; + unsigned char type; + string buffer; + uint32_t iPrefixSize = 4; }; -/** - * 音频Track派生类,支持采样率通道数,采用位数信息 - */ -class AudioTrack : public Track { + +class H264FrameNoCopyAble : public FrameNoCopyAble { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - TrackType getTrackType() const override { return TrackAudio;}; + H264FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){ + buffer_ptr = ptr; + buffer_size = size; + timeStamp = stamp; + iPrefixSize = prefixeSize; + } - /** - * 返回音频采样率 - * @return - */ - virtual int getAudioSampleRate() const = 0; + TrackType getTrackType() const override{ + return TrackVideo; + } - /** - * 返回音频采样位数,一般为16或8 - * @return - */ - virtual int getAudioSampleBit() const = 0; + CodecId getCodecId() const override{ + return CodecH264; + } - /** - * 返回音频通道数 - * @return - */ - virtual int getAudioChannel() const = 0; + bool keyFrame() const override { + return (buffer_ptr[iPrefixSize] & 0x1F) == 5; + } }; + /** * 264视频通道 */ @@ -298,135 +273,8 @@ private: H264Frame::Ptr _ppsFrame; }; -/** - * aac音频通道 - */ -class AACTrack : public AudioTrack{ -public: - typedef std::shared_ptr Ptr; - - /** - * 延后获取adts头信息 - * 在随后的inputFrame中获取adts头信息 - */ - AACTrack(){} - - /** - * 构造aac类型的媒体 - * @param aac_cfg aac两个字节的配置信息 - */ - AACTrack(const string &aac_cfg){ - if(aac_cfg.size() != 2){ - throw std::invalid_argument("adts配置必须为2个字节"); - } - _cfg = aac_cfg; - parseAacCfg(_cfg); - } - - /** - * 构造aac类型的媒体 - * @param adts_header adts头,7个字节 - * @param adts_header_len adts头长度,不少于7个字节 - */ - AACTrack(const char *adts_header,int adts_header_len = 7){ - if(adts_header_len < 7){ - throw std::invalid_argument("adts头必须不少于7个字节"); - } - _cfg = makeAdtsConfig((uint8_t*)adts_header); - parseAacCfg(_cfg); - } - - /** - * 构造aac类型的媒体 - * @param aac_frame_with_adts 带adts头的aac帧 - */ - AACTrack(const Frame::Ptr &aac_frame_with_adts){ - if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){ - throw std::invalid_argument("必须输入带adts头的aac帧"); - } - _cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data()); - parseAacCfg(_cfg); - } - - /** - * 获取aac两个字节的配置 - * @return - */ - const string &getAacCfg() const{ - return _cfg; - } - - /** - * 返回编码类型 - * @return - */ - CodecId getCodecId() const override{ - return CodecAAC; - } - - /** - * 在获取aac_cfg前是无效的Track - * @return - */ - bool ready() override { - return !_cfg.empty(); - } - - - /** - * 返回音频采样率 - * @return - */ - int getAudioSampleRate() const override{ - return _sampleRate; - } - /** - * 返回音频采样位数,一般为16或8 - * @return - */ - int getAudioSampleBit() const override{ - return _sampleBit; - } - /** - * 返回音频通道数 - * @return - */ - int getAudioChannel() const override{ - return _channel; - } - - /** - * 输入数据帧,并获取aac_cfg - * @param frame 数据帧 - */ - void inputFrame(const Frame::Ptr &frame) override{ - if(_cfg.empty() && frame->prefixSize() >= 7){ - //7个字节的adts头 - _cfg = makeAdtsConfig(reinterpret_cast(frame->data())); - parseAacCfg(_cfg); - } - AudioTrack::inputFrame(frame); - } -private: - /** - * 解析2个字节的aac配置 - * @param aac_cfg - */ - void parseAacCfg(const string &aac_cfg){ - AACFrame aacFrame; - makeAdtsHeader(aac_cfg,aacFrame); - getAACInfo(aacFrame,_sampleRate,_channel); - } - Track::Ptr clone() override { - return std::make_shared::type >(*this); - } -private: - string _cfg; - int _sampleRate = 0; - int _sampleBit = 16; - int _channel = 0; -}; }//namespace mediakit -#endif //ZLMEDIAKIT_TRACK_H + +#endif //ZLMEDIAKIT_H264_H diff --git a/src/Player/Frame.cpp b/src/Extension/H265.cpp similarity index 96% rename from src/Player/Frame.cpp rename to src/Extension/H265.cpp index 58e81068..c0173b65 100644 --- a/src/Player/Frame.cpp +++ b/src/Extension/H265.cpp @@ -24,8 +24,10 @@ * SOFTWARE. */ -#include "Frame.h" +#include "H265.h" namespace mediakit{ -} \ No newline at end of file + +}//namespace mediakit + diff --git a/src/Extension/H265.h b/src/Extension/H265.h new file mode 100644 index 00000000..8d0383ec --- /dev/null +++ b/src/Extension/H265.h @@ -0,0 +1,104 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef ZLMEDIAKIT_H265_H +#define ZLMEDIAKIT_H265_H + +#include "Frame.h" +#include "Track.h" + +namespace mediakit{ + +/** +* 265帧类 +*/ +class H265Frame : public Frame { +public: + typedef std::shared_ptr Ptr; + + char *data() const override{ + return (char *)buffer.data(); + } + uint32_t size() const override { + return buffer.size(); + } + uint32_t stamp() const override { + return timeStamp; + } + uint32_t prefixSize() const override{ + return iPrefixSize; + } + + TrackType getTrackType() const override{ + return TrackVideo; + } + + CodecId getCodecId() const override{ + return CodecH265; + } + + bool keyFrame() const override { + return type == 5; + } +public: + uint16_t sequence; + uint32_t timeStamp; + unsigned char type; + string buffer; + uint32_t iPrefixSize = 4; +}; + + +class H265FrameNoCopyAble : public FrameNoCopyAble { +public: + typedef std::shared_ptr Ptr; + + H265FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){ + buffer_ptr = ptr; + buffer_size = size; + timeStamp = stamp; + iPrefixSize = prefixeSize; + } + + TrackType getTrackType() const override{ + return TrackVideo; + } + + CodecId getCodecId() const override{ + return CodecH265; + } + + bool keyFrame() const override { + return (buffer_ptr[iPrefixSize] & 0x1F) == 5; + } +}; + + +}//namespace mediakit + + +#endif //ZLMEDIAKIT_H265_H diff --git a/src/Extension/Track.h b/src/Extension/Track.h new file mode 100644 index 00000000..47a15c90 --- /dev/null +++ b/src/Extension/Track.h @@ -0,0 +1,130 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ZLMEDIAKIT_TRACK_H +#define ZLMEDIAKIT_TRACK_H + +#include +#include +#include "Frame.h" +#include "Util/RingBuffer.h" +#include "Rtsp/Rtsp.h" +using namespace toolkit; + +namespace mediakit{ + +/** + * 媒体通道描述类,也支持帧输入输出 + */ +class Track : public FrameRingInterfaceDelegate , public CodecInfo{ +public: + typedef std::shared_ptr Ptr; + Track(){} + + virtual ~Track(){} + + /** + * 是否准备好,准备好才能获取譬如sps pps等信息 + * @return + */ + virtual bool ready() = 0; + + /** + * 克隆接口,用于复制本对象用 + * 在调用该接口时只会复制派生类的信息 + * 环形缓存和代理关系不能拷贝,否则会关系紊乱 + * @return + */ + virtual Track::Ptr clone() = 0; + + /** + * 复制拷贝,只能拷贝派生类的信息, + * 环形缓存和代理关系不能拷贝,否则会关系紊乱 + * @param that + */ + Track(const Track &that){} +}; + +/** + * 视频通道描述Track类,支持获取宽高fps信息 + */ +class VideoTrack : public Track { +public: + typedef std::shared_ptr Ptr; + + TrackType getTrackType() const override { return TrackVideo;}; + + /** + * 返回视频高度 + * @return + */ + virtual int getVideoHeight() const = 0; + + /** + * 返回视频宽度 + * @return + */ + virtual int getVideoWidth() const = 0; + + /** + * 返回视频fps + * @return + */ + virtual float getVideoFps() const = 0; +}; + +/** + * 音频Track派生类,支持采样率通道数,采用位数信息 + */ +class AudioTrack : public Track { +public: + typedef std::shared_ptr Ptr; + + TrackType getTrackType() const override { return TrackAudio;}; + + /** + * 返回音频采样率 + * @return + */ + virtual int getAudioSampleRate() const = 0; + + /** + * 返回音频采样位数,一般为16或8 + * @return + */ + virtual int getAudioSampleBit() const = 0; + + /** + * 返回音频通道数 + * @return + */ + virtual int getAudioChannel() const = 0; +}; + + +}//namespace mediakit + +#endif //ZLMEDIAKIT_TRACK_H diff --git a/src/MediaFile/Mp4Maker.cpp b/src/MediaFile/Mp4Maker.cpp index 9e579b4f..110c7b07 100644 --- a/src/MediaFile/Mp4Maker.cpp +++ b/src/MediaFile/Mp4Maker.cpp @@ -34,6 +34,9 @@ #include "Util/mini.h" #include "Util/util.h" #include "Util/NoticeCenter.h" +#include "Extension/H264.h" +#include "Extension/AAC.h" + using namespace toolkit; namespace mediakit { diff --git a/src/MediaFile/Mp4Maker.h b/src/MediaFile/Mp4Maker.h index 3ff1e699..29e810e5 100644 --- a/src/MediaFile/Mp4Maker.h +++ b/src/MediaFile/Mp4Maker.h @@ -38,7 +38,7 @@ #include "Util/TimeTicker.h" #include "Util/TimeTicker.h" #include "Common/MediaSink.h" -#include "Player/Track.h" +#include "Extension/Track.h" using namespace toolkit; diff --git a/src/Player/MediaPlayer.h b/src/Player/MediaPlayer.h index 13649781..b2e047cc 100644 --- a/src/Player/MediaPlayer.h +++ b/src/Player/MediaPlayer.h @@ -29,7 +29,6 @@ #include #include -#include "Player.h" #include "PlayerBase.h" #include "Rtsp/RtspPlayer.h" #include "Rtmp/RtmpPlayer.h" diff --git a/src/Player/Player.cpp b/src/Player/Player.cpp deleted file mode 100644 index 6825a2aa..00000000 --- a/src/Player/Player.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2016 xiongziliang <771730766@qq.com> - * - * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include "Player.h" -#include "H264/SPSParser.h" -#include "Util/logger.h" -using namespace toolkit; - -void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) { - pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit - pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit - pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit - pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit - pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit - - pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit - pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit - pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit - pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit - - pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit - pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit - pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit - pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit - pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit - pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit - - pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit - - pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit - pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit - - pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit - pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit -} -string makeAdtsConfig(const uint8_t *pcAdts){ - if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) { - return ""; - } - // Get and check the 'profile': - unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits - if (profile == 3) { - return ""; - } - - // Get and check the 'sampling_frequency_index': - unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits - if (samplingFrequencyTable[sampling_frequency_index] == 0) { - return ""; - } - - // Get and check the 'channel_configuration': - unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2) - | ((pcAdts[3] & 0xC0) >> 6); // 3 bits - - unsigned char audioSpecificConfig[2]; - unsigned char const audioObjectType = profile + 1; - audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1); - audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3); - return string((char *)audioSpecificConfig,2); -} -void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) { - uint8_t cfg1 = strAudioCfg[0]; - uint8_t cfg2 = strAudioCfg[1]; - - int audioObjectType; - int sampling_frequency_index; - int channel_configuration; - - audioObjectType = cfg1 >> 3; - sampling_frequency_index = ((cfg1 & 0x07) << 1) | (cfg2 >> 7); - channel_configuration = (cfg2 & 0x7F) >> 3; - - adts.syncword = 0x0FFF; - adts.id = 0; - adts.layer = 0; - adts.protection_absent = 1; - adts.profile = audioObjectType - 1; - adts.sf_index = sampling_frequency_index; - adts.private_bit = 0; - adts.channel_configuration = channel_configuration; - adts.original = 0; - adts.home = 0; - adts.copyright_identification_bit = 0; - adts.copyright_identification_start = 0; - adts.aac_frame_length = 7; - adts.adts_buffer_fullness = 2047; - adts.no_raw_data_blocks_in_frame = 0; -} -void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){ - iSampleRate = samplingFrequencyTable[adts.sf_index]; - iChannel = adts.channel_configuration; -} -bool getAVCInfo(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) { - return getAVCInfo(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps); -} -bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){ - T_GetBitContext tGetBitBuf; - T_SPS tH264SpsInfo; - memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); - memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo)); - tGetBitBuf.pu8Buf = (uint8_t*)sps + 1; - tGetBitBuf.iBufSize = sps_len - 1; - if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){ - return false; - } - h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight); - h264GeFramerate(&tH264SpsInfo, &iVideoFps); - //ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; - return true; -} diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index d2b21f61..cfcae547 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -31,13 +31,12 @@ #include #include #include -#include "Player.h" #include "Network/Socket.h" #include "Util/mini.h" #include "Util/RingBuffer.h" #include "Common/MediaSource.h" -#include "Frame.h" -#include "Track.h" +#include "Extension/Frame.h" +#include "Extension/Track.h" using namespace toolkit; namespace mediakit { diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index a639bf5f..d2f0579c 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -24,7 +24,6 @@ * SOFTWARE. */ -#include "Player/Player.h" #include "Common/config.h" #include "PlayerProxy.h" #include "Util/mini.h" diff --git a/src/RtmpMuxer/AACRtmpCodec.cpp b/src/RtmpMuxer/AACRtmpCodec.cpp index 1a4e4178..6f9a1272 100644 --- a/src/RtmpMuxer/AACRtmpCodec.cpp +++ b/src/RtmpMuxer/AACRtmpCodec.cpp @@ -23,7 +23,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include #include "AACRtmpCodec.h" namespace mediakit{ diff --git a/src/RtmpMuxer/AACRtmpCodec.h b/src/RtmpMuxer/AACRtmpCodec.h index d1e0332d..855593e9 100644 --- a/src/RtmpMuxer/AACRtmpCodec.h +++ b/src/RtmpMuxer/AACRtmpCodec.h @@ -28,7 +28,8 @@ #define ZLMEDIAKIT_AACRTMPCODEC_H #include "RtmpCodec.h" -#include "Player/Track.h" +#include "Extension/Track.h" +#include "Extension/AAC.h" namespace mediakit{ /** diff --git a/src/RtmpMuxer/H264RtmpCodec.h b/src/RtmpMuxer/H264RtmpCodec.h index 6648574a..aef99fcd 100644 --- a/src/RtmpMuxer/H264RtmpCodec.h +++ b/src/RtmpMuxer/H264RtmpCodec.h @@ -28,8 +28,9 @@ #define ZLMEDIAKIT_H264RTMPCODEC_H #include "RtmpCodec.h" -#include "Player/Track.h" +#include "Extension/Track.h" #include "Util/ResourcePool.h" +#include "Extension/H264.h" using namespace toolkit; namespace mediakit{ diff --git a/src/RtmpMuxer/RtmpCodec.h b/src/RtmpMuxer/RtmpCodec.h index 45e919fe..f9c89a62 100644 --- a/src/RtmpMuxer/RtmpCodec.h +++ b/src/RtmpMuxer/RtmpCodec.h @@ -28,7 +28,7 @@ #define ZLMEDIAKIT_RTMPCODEC_H #include "Rtmp/Rtmp.h" -#include "Player/Frame.h" +#include "Extension/Frame.h" #include "Util/RingBuffer.h" using namespace toolkit; diff --git a/src/RtmpMuxer/RtmpDemuxer.cpp b/src/RtmpMuxer/RtmpDemuxer.cpp index 412b9256..8c1fa67d 100644 --- a/src/RtmpMuxer/RtmpDemuxer.cpp +++ b/src/RtmpMuxer/RtmpDemuxer.cpp @@ -25,7 +25,7 @@ */ #include "RtmpDemuxer.h" -#include "Common/Factory.h" +#include "Extension/Factory.h" namespace mediakit { diff --git a/src/RtmpMuxer/RtmpDemuxer.h b/src/RtmpMuxer/RtmpDemuxer.h index e3a12912..50165d84 100644 --- a/src/RtmpMuxer/RtmpDemuxer.h +++ b/src/RtmpMuxer/RtmpDemuxer.h @@ -31,7 +31,6 @@ #include #include "Rtmp/amf.h" #include "Rtmp/Rtmp.h" -#include "Player/Player.h" #include "Player/PlayerBase.h" #include "Util/TimeTicker.h" #include "RtmpCodec.h" diff --git a/src/RtmpMuxer/RtmpMetedata.h b/src/RtmpMuxer/RtmpMetedata.h index fa193b8b..f0851579 100644 --- a/src/RtmpMuxer/RtmpMetedata.h +++ b/src/RtmpMuxer/RtmpMetedata.h @@ -30,9 +30,9 @@ #include "RtmpMuxer/H264RtmpCodec.h" #include "RtmpMuxer/AACRtmpCodec.h" #include "Util/base64.h" -#include "Player/Track.h" +#include "Extension/Track.h" #include "Rtmp/amf.h" -#include "Common/Factory.h" +#include "Extension/Factory.h" namespace mediakit { diff --git a/src/RtmpMuxer/RtmpMuxer.h b/src/RtmpMuxer/RtmpMuxer.h index 979e9fd3..cfb15b00 100644 --- a/src/RtmpMuxer/RtmpMuxer.h +++ b/src/RtmpMuxer/RtmpMuxer.h @@ -28,7 +28,7 @@ #define ZLMEDIAKIT_RTMPMUXER_H #include "RtmpMetedata.h" -#include "Player/Frame.h" +#include "Extension/Frame.h" #include "Common/MediaSink.h" namespace mediakit{ diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index 9c75f93d..89fca892 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -32,7 +32,7 @@ #include #include "Common/config.h" #include "Util/util.h" -#include "Player/Frame.h" +#include "Extension/Frame.h" using namespace std; using namespace toolkit; diff --git a/src/RtspMuxer/AACRtpCodec.h b/src/RtspMuxer/AACRtpCodec.h index fd05c9d5..35f9aaf6 100644 --- a/src/RtspMuxer/AACRtpCodec.h +++ b/src/RtspMuxer/AACRtpCodec.h @@ -28,7 +28,7 @@ #define ZLMEDIAKIT_AACRTPCODEC_H #include "RtpCodec.h" - +#include "Extension/AAC.h" namespace mediakit{ /** * aac rtp转adts类 diff --git a/src/RtspMuxer/H264RtpCodec.h b/src/RtspMuxer/H264RtpCodec.h index b2e5f999..c905f4c5 100644 --- a/src/RtspMuxer/H264RtpCodec.h +++ b/src/RtspMuxer/H264RtpCodec.h @@ -29,6 +29,7 @@ #include "RtpCodec.h" #include "Util/ResourcePool.h" +#include "Extension/H264.h" using namespace toolkit; namespace mediakit{ diff --git a/src/RtspMuxer/H265RtpCodec.cpp b/src/RtspMuxer/H265RtpCodec.cpp new file mode 100644 index 00000000..d59f626f --- /dev/null +++ b/src/RtspMuxer/H265RtpCodec.cpp @@ -0,0 +1,265 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "H265RtpCodec.h" + +namespace mediakit{ + + +typedef struct { + unsigned forbidden_zero_bit :1; + unsigned nal_ref_idc :2; + unsigned type :5; +} NALU; + +typedef struct { + unsigned S :1; + unsigned E :1; + unsigned R :1; + unsigned type :5; +} FU; + +bool MakeNalu(uint8_t in, NALU &nal) { + nal.forbidden_zero_bit = in >> 7; + if (nal.forbidden_zero_bit) { + return false; + } + nal.nal_ref_idc = (in & 0x60) >> 5; + nal.type = in & 0x1f; + return true; +} +bool MakeFU(uint8_t in, FU &fu) { + fu.S = in >> 7; + fu.E = (in >> 6) & 0x01; + fu.R = (in >> 5) & 0x01; + fu.type = in & 0x1f; + if (fu.R != 0) { + return false; + } + return true; +} + + +H265RtpDecoder::H265RtpDecoder() { + _h265frame = obtainFrame(); +} + +H265Frame::Ptr H265RtpDecoder::obtainFrame() { + //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 + auto frame = ResourcePoolHelper::obtainObj(); + frame->buffer.clear(); + frame->iPrefixSize = 4; + return frame; +} + +bool H265RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { + key_pos = decodeRtp(rtp); + RtpCodec::inputRtp(rtp, key_pos); + return key_pos; +} + +bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { + /** + * h265帧类型 + * Type==1:P/B frame + * Type==5:IDR frame + * Type==6:SEI frame + * Type==7:SPS frame + * Type==8:PPS frame + */ + + const uint8_t *frame = (uint8_t *) rtppack->payload + rtppack->offset; + int length = rtppack->length - rtppack->offset; + NALU nal; + MakeNalu(*frame, nal); + + if (nal.type >= 0 && nal.type < 24) { + //a full frame + _h265frame->buffer.assign("\x0\x0\x0\x1", 4); + _h265frame->buffer.append((char *)frame, length); + _h265frame->type = nal.type; + _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->sequence = rtppack->sequence; + auto isIDR = _h265frame->type == 5; + onGetH265(_h265frame); + return (isIDR); //i frame + } + + 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); + _h265frame->buffer.assign("\x0\x0\x0\x1", 4); + _h265frame->buffer.push_back(tmp); + _h265frame->buffer.append((char *)frame + 2, length - 2); + _h265frame->type = fu.type; + _h265frame->timeStamp = rtppack->timeStamp; + _h265frame->sequence = rtppack->sequence; + return (_h265frame->type == 5); //i frame + } + + if (rtppack->sequence != (uint16_t)(_h265frame->sequence + 1)) { + _h265frame->buffer.clear(); + WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h265frame->sequence; + return false; + } + _h265frame->sequence = rtppack->sequence; + if (fu.E == 1) { + //FU-A end + _h265frame->buffer.append((char *)frame + 2, length - 2); + _h265frame->timeStamp = rtppack->timeStamp; + auto isIDR = _h265frame->type == 5; + onGetH265(_h265frame); + return isIDR; + } + //FU-A mid + _h265frame->buffer.append((char *)frame + 2, length - 2); + return false; + } + + WarnL << "不支持的rtp类型:" << 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 +} + +void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) { + //写入环形缓存 + RtpCodec::inputFrame(frame); + _h265frame = obtainFrame(); +} + + +//////////////////////////////////////////////////////////////////////// + +H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc, + uint32_t ui32MtuSize, + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType, + uint8_t ui8Interleaved) : + RtpInfo(ui32Ssrc, + ui32MtuSize, + ui32SampleRate, + ui8PlayloadType, + ui8Interleaved) { +} + +void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) { + RtpCodec::inputFrame(frame); + + GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Rtp::kCycleMS); + auto pcData = frame->data() + frame->prefixSize(); + auto uiStamp = frame->stamp(); + auto iLen = frame->size() - frame->prefixSize(); + + uiStamp %= cycleMS; + int iSize = _ui32MtuSize - 2; + if (iLen > iSize) { //超过MTU + const unsigned char s_e_r_Start = 0x80; + const unsigned char s_e_r_Mid = 0x00; + const unsigned char s_e_r_End = 0x40; + //获取帧头数据,1byte + unsigned char naluType = *((unsigned char *) pcData) & 0x1f; //获取NALU的5bit 帧类型 + + unsigned char nal_ref_idc = *((unsigned char *) pcData) & 0x60; //获取NALU的2bit 帧重要程度 00 可以丢 11不能丢 + //nal_ref_idc = 0x60; + //组装FU-A帧头数据 2byte + unsigned char f_nri_type = nal_ref_idc + 28;//F为0 1bit,nri上面获取到2bit,28为FU-A分片类型5bit + unsigned char s_e_r_type = naluType; + bool bFirst = true; + bool mark = false; + int nOffset = 1; + while (!mark) { + if (iLen < nOffset + iSize) { //是否拆分结束 + iSize = iLen - nOffset; + mark = true; + s_e_r_type = s_e_r_End + naluType; + } else { + if (bFirst == true) { + s_e_r_type = s_e_r_Start + naluType; + bFirst = false; + } else { + s_e_r_type = s_e_r_Mid + naluType; + } + } + memcpy(_aucSectionBuf, &f_nri_type, 1); + memcpy(_aucSectionBuf + 1, &s_e_r_type, 1); + memcpy(_aucSectionBuf + 2, (unsigned char *) pcData + nOffset, iSize); + nOffset += iSize; + makeH265Rtp(_aucSectionBuf, iSize + 2, mark, uiStamp); + } + } else { + makeH265Rtp(pcData, iLen, true, uiStamp); + } +} + +void H265RtpEncoder::makeH265Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) { + uint16_t ui16RtpLen = len + 12; + uint32_t ts = htonl((_ui32SampleRate / 1000) * uiStamp); + uint16_t sq = htons(_ui16Sequence); + uint32_t sc = htonl(_ui32Ssrc); + + auto rtppkt = ResourcePoolHelper::obtainObj(); + unsigned char *pucRtp = rtppkt->payload; + pucRtp[0] = '$'; + pucRtp[1] = _ui8Interleaved; + pucRtp[2] = ui16RtpLen >> 8; + pucRtp[3] = ui16RtpLen & 0x00FF; + pucRtp[4] = 0x80; + pucRtp[5] = (mark << 7) | _ui8PlayloadType; + memcpy(&pucRtp[6], &sq, 2); + memcpy(&pucRtp[8], &ts, 4); + //ssrc + memcpy(&pucRtp[12], &sc, 4); + //playload + memcpy(&pucRtp[16], data, len); + + rtppkt->PT = _ui8PlayloadType; + rtppkt->interleaved = _ui8Interleaved; + rtppkt->mark = mark; + rtppkt->length = len + 16; + rtppkt->sequence = _ui16Sequence; + rtppkt->timeStamp = uiStamp; + rtppkt->ssrc = _ui32Ssrc; + rtppkt->type = TrackVideo; + rtppkt->offset = 16; + + uint8_t type = ((uint8_t *) (data))[0] & 0x1F; + RtpCodec::inputRtp(rtppkt,type == 7); + _ui16Sequence++; + _ui32TimeStamp = uiStamp; +} + +}//namespace mediakit \ No newline at end of file diff --git a/src/RtspMuxer/H265RtpCodec.h b/src/RtspMuxer/H265RtpCodec.h new file mode 100644 index 00000000..e38fefc6 --- /dev/null +++ b/src/RtspMuxer/H265RtpCodec.h @@ -0,0 +1,104 @@ +/* + * MIT License + * + * Copyright (c) 2016 xiongziliang <771730766@qq.com> + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ZLMEDIAKIT_H265RTPCODEC_H +#define ZLMEDIAKIT_H265RTPCODEC_H + +#include "RtpCodec.h" +#include "Util/ResourcePool.h" +#include "Extension/H265.h" + +using namespace toolkit; + +namespace mediakit{ + +/** + * h265 rtp解码类 + */ +class H265RtpDecoder : public RtpCodec , public ResourcePoolHelper { +public: + typedef std::shared_ptr Ptr; + + H265RtpDecoder(); + ~H265RtpDecoder() {} + + /** + * 输入265 rtp包 + * @param rtp rtp包 + * @param key_pos 此参数忽略之 + */ + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; + + TrackType getTrackType() const override{ + return TrackVideo; + } + + CodecId getCodecId() const override{ + return CodecH265; + } +private: + bool decodeRtp(const RtpPacket::Ptr &rtp); + void onGetH265(const H265Frame::Ptr &frame); + H265Frame::Ptr obtainFrame(); +private: + H265Frame::Ptr _h265frame; +}; + +/** + * 265 rtp打包类 + */ +class H265RtpEncoder : public H265RtpDecoder ,public RtpInfo{ +public: + typedef std::shared_ptr Ptr; + + /** + * @param ui32Ssrc ssrc + * @param ui32MtuSize mtu大小 + * @param ui32SampleRate 采样率,强制为90000 + * @param ui8PlayloadType pt类型 + * @param ui8Interleaved rtsp interleaved + */ + H265RtpEncoder(uint32_t ui32Ssrc, + uint32_t ui32MtuSize = 1400, + uint32_t ui32SampleRate = 90000, + uint8_t ui8PlayloadType = 96, + uint8_t ui8Interleaved = TrackVideo * 2); + ~H265RtpEncoder() {} + + /** + * 输入265帧 + * @param frame 帧数据,必须 + */ + void inputFrame(const Frame::Ptr &frame) override; +private: + void makeH265Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); +private: + unsigned char _aucSectionBuf[1600]; +}; + +}//namespace mediakit{ + +#endif //ZLMEDIAKIT_H265RTPCODEC_H diff --git a/src/RtspMuxer/RtspDemuxer.cpp b/src/RtspMuxer/RtspDemuxer.cpp index 1933af74..b59d4bbb 100644 --- a/src/RtspMuxer/RtspDemuxer.cpp +++ b/src/RtspMuxer/RtspDemuxer.cpp @@ -29,7 +29,7 @@ #include "RtspDemuxer.h" #include "Util/base64.h" #include "H264/SPSParser.h" -#include "Common/Factory.h" +#include "Extension/Factory.h" using namespace std; diff --git a/src/RtspMuxer/RtspDemuxer.h b/src/RtspMuxer/RtspDemuxer.h index b61a9a8e..49f81762 100644 --- a/src/RtspMuxer/RtspDemuxer.h +++ b/src/RtspMuxer/RtspDemuxer.h @@ -29,7 +29,6 @@ #include #include "Rtsp/Rtsp.h" -#include "Player/Player.h" #include "Player/PlayerBase.h" #include "Util/TimeTicker.h" #include "RtspMuxer/RtpCodec.h" diff --git a/src/RtspMuxer/RtspMuxer.cpp b/src/RtspMuxer/RtspMuxer.cpp index 68c0a1a4..bbd8d412 100644 --- a/src/RtspMuxer/RtspMuxer.cpp +++ b/src/RtspMuxer/RtspMuxer.cpp @@ -25,7 +25,7 @@ */ #include "RtspMuxer.h" -#include "Common/Factory.h" +#include "Extension/Factory.h" namespace mediakit { diff --git a/src/RtspMuxer/RtspMuxer.h b/src/RtspMuxer/RtspMuxer.h index d5482540..3f9930d2 100644 --- a/src/RtspMuxer/RtspMuxer.h +++ b/src/RtspMuxer/RtspMuxer.h @@ -28,7 +28,7 @@ #define ZLMEDIAKIT_RTSPMUXER_H #include "RtspSdp.h" -#include "Player/Frame.h" +#include "Extension/Frame.h" #include "Common/MediaSink.h" namespace mediakit{ diff --git a/src/RtspMuxer/RtspSdp.cpp b/src/RtspMuxer/RtspSdp.cpp index 69160d27..fbfee1a4 100644 --- a/src/RtspMuxer/RtspSdp.cpp +++ b/src/RtspMuxer/RtspSdp.cpp @@ -24,7 +24,7 @@ * SOFTWARE. */ #include "RtspSdp.h" -#include "Common/Factory.h" +#include "Extension/Factory.h" namespace mediakit{ diff --git a/src/RtspMuxer/RtspSdp.h b/src/RtspMuxer/RtspSdp.h index 78e49ae2..83971381 100644 --- a/src/RtspMuxer/RtspSdp.h +++ b/src/RtspMuxer/RtspSdp.h @@ -29,7 +29,7 @@ #include "RtspMuxer/H264RtpCodec.h" #include "RtspMuxer/AACRtpCodec.h" #include "Util/base64.h" -#include "Player/Track.h" +#include "Extension/Track.h" namespace mediakit {