diff --git a/src/Player/Player.cpp b/src/Player/Player.cpp index a4b64636..8ad171c0 100644 --- a/src/Player/Player.cpp +++ b/src/Player/Player.cpp @@ -118,12 +118,15 @@ void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){ 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 *)strSps.data() + 1; - tGetBitBuf.iBufSize = strSps.size() - 1; + tGetBitBuf.pu8Buf = (uint8_t*)sps + 1; + tGetBitBuf.iBufSize = sps_len - 1; if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){ return false; } diff --git a/src/Player/Player.h b/src/Player/Player.h index 0d00cf07..78cb1682 100644 --- a/src/Player/Player.h +++ b/src/Player/Player.h @@ -45,5 +45,7 @@ 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); + #endif /* SRC_PLAYER_PLAYER_H_ */ diff --git a/src/Player/Track.h b/src/Player/Track.h index 21718f45..dd75b733 100644 --- a/src/Player/Track.h +++ b/src/Player/Track.h @@ -10,11 +10,12 @@ #include "Frame.h" #include "Util/RingBuffer.h" #include "Rtsp/Rtsp.h" +#include "Player.h" using namespace std; using namespace ZL::Util; -class Track : public FrameRingInterface , public CodecInfo{ +class Track : public FrameRing , public CodecInfo{ public: typedef std::shared_ptr Ptr; Track(){} @@ -24,52 +25,231 @@ public: class VideoTrack : public Track { public: 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; }; class AudioTrack : public Track { public: 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; }; class H264Track : public VideoTrack{ public: - H264Track(const string &sps,const string &pps){ - _sps = sps; - _pps = pps; + + /** + * 构造h264类型的媒体 + * @param sps sps帧数据 + * @param pps pps帧数据 + * @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 + * @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 + */ + H264Track(const string &sps,const string &pps,int sps_prefix_len = 4,int pps_prefix_len = 4){ + _sps = sps.substr(sps_prefix_len); + _pps = pps.substr(pps_prefix_len); + parseSps(_sps); } + + /** + * 构造h264类型的媒体 + * @param sps sps帧 + * @param pps pps帧 + */ + H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps){ + if(sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){ + throw std::invalid_argument("必须输入H264类型的帧"); + } + _sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize()); + _pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize()); + parseSps(_sps); + } + + + /** + * 返回不带0x00 00 00 01头的sps + * @return + */ const string &getSps() const{ return _sps; } + + /** + * 返回不带0x00 00 00 01头的pps + * @return + */ const string &getPps() const{ return _pps; } - CodecId getCodecId() const override{ + + CodecId getCodecId() const override { return CodecH264; } + + /** + * 返回视频高度 + * @return + */ + int getVideoHeight() const override{ + return _width; + } + + /** + * 返回视频宽度 + * @return + */ + int getVideoWidth() const override{ + return _height; + } + + /** + * 返回视频fps + * @return + */ + float getVideoFps() const override{ + return _fps; + } +private: + /** + * 解析sps获取宽高fps + * @param sps sps不含头数据 + */ + void parseSps(const string &sps){ + getAVCInfo(sps,_width,_height,_fps); + } private: string _sps; string _pps; + int _width = 0; + int _height = 0; + float _fps = 0; }; class AACTrack : public AudioTrack{ public: + /** + * 构造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; } + + /** + * 返回音频采样率 + * @return + */ + int getAudioSampleRate() const override{ + return _sampleRate; + } + /** + * 返回音频采样位数,一般为16或8 + * @return + */ + int getAudioSampleBit() const override{ + return _sampleBit; + } + /** + * 返回音频通道数 + * @return + */ + int getAudioChannel() const override{ + return _channel; + } + +private: + /** + * 解析2个字节的aac配置 + * @param aac_cfg + */ + void parseAacCfg(const string &aac_cfg){ + AACFrame aacFrame; + makeAdtsHeader(aac_cfg,aacFrame); + getAACInfo(aacFrame,_sampleRate,_channel); + } private: string _cfg; + int _sampleRate = 0; + int _sampleBit = 16; + int _channel = 0; }; diff --git a/src/Rtsp/RtspEncoder.h b/src/Rtsp/RtspEncoder.h index aff44e75..247751e6 100644 --- a/src/Rtsp/RtspEncoder.h +++ b/src/Rtsp/RtspEncoder.h @@ -15,51 +15,98 @@ namespace Rtsp{ /** * sdp基类 */ -class Sdp : public Track , public RtpRingInterface{ +class Sdp : public FrameRingInterface , public RtpRingInterface , public CodecInfo{ public: typedef std::shared_ptr Ptr; + + /** + * 构造sdp + * @param sample_rate 采样率 + * @param playload_type pt类型 + */ Sdp(uint32_t sample_rate, uint8_t playload_type){ _sample_rate = sample_rate; _playload_type = playload_type; } virtual ~Sdp(){} + /** * 获取sdp字符串 * @return */ virtual string getSdp() const = 0; + /** + * 返回音频或视频类型 + * @return + */ TrackType getTrackType() const override { return TrackInvalid; } + /** + * 返回编码器id + * @return + */ CodecId getCodecId() const override{ return CodecInvalid; } + /** + * 获取帧环形缓存 + * @return + */ FrameRingInterface::RingType::Ptr getFrameRing() const override { return _encoder->getFrameRing(); } + /** + * 获取rtp环形缓存 + * @return + */ RtpRingInterface::RingType::Ptr getRtpRing() const override{ return _encoder->getRtpRing(); } + /** + * 输入帧数据,驱动rtp打包 + * @param frame 帧数据 + * @param key_pos 是否为关键帧 + */ void inputFrame(const Frame::Ptr &frame,bool key_pos) override{ _encoder->inputFrame(frame,key_pos); } + /** + * 也可以在外部打包rtp后直接输入rtp + * @param rtp rtp数据包 + * @param key_pos 是否为关键帧第一个rtp包 + */ void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ _encoder->inputRtp(rtp,key_pos); } + /** + * 替换帧环形缓存,目的是多个rtp打包器共用一个环形缓存 + * @param ring + */ void setFrameRing(const FrameRingInterface::RingType::Ptr &ring) override{ _encoder->setFrameRing(ring); } + + /** + * 替换帧环形缓存,目的是多个rtp打包器共用一个环形缓存 + * @param ring + */ void setRtpRing(const RtpRingInterface::RingType::Ptr &ring) override{ _encoder->setRtpRing(ring); } + /** + * 创建Rtp打包器 + * @param ssrc 打包器ssrc,可以为0 + * @param mtu mtu大小,一般小于1500字节,推荐1400 + */ virtual void createRtpEncoder(uint32_t ssrc, int mtu) { _encoder = RtpCodec::getRtpCodec (getCodecId(), ssrc, @@ -127,20 +174,17 @@ public: * * @param sps 264 sps,带0x00000001头 * @param pps 264 pps,带0x00000001头 - * @param sample_rate 时间戳采样率,视频默认90000 - * @param playload_type rtp playload type 默认96 - * @param track_id trackID 默认为TrackVideo + * @param playload_type rtp playload type 默认96 * @param bitrate 比特率 */ H264Sdp(const string &sps, const string &pps, - int sample_rate = 90000, int playload_type = 96, - int bitrate = 4000) : Sdp(sample_rate,playload_type) { + int bitrate = 4000) : Sdp(90000,playload_type) { //视频通道 _printer << "m=video 0 RTP/AVP " << playload_type << "\r\n"; _printer << "b=AS:" << bitrate << "\r\n"; - _printer << "a=rtpmap:" << playload_type << " H264/" << sample_rate << "\r\n"; + _printer << "a=rtpmap:" << playload_type << " H264/" << 90000 << "\r\n"; _printer << "a=fmtp:" << playload_type << " packetization-mode=1;profile-level-id="; char strTemp[100]; @@ -186,11 +230,10 @@ class AACSdp : public Sdp { public: /** - * 构造aac sdp + * * @param aac_cfg aac两个字节的配置描述 * @param sample_rate 音频采样率 - * @param playload_type rtp playload type 默认96 - * @param track_id trackID 默认为TrackVideo + * @param playload_type rtp playload type 默认98 * @param bitrate 比特率 */ AACSdp(const string &aac_cfg,