ZLMediaKit/src/Rtsp/RtspEncoder.h

390 lines
10 KiB
C
Raw Normal View History

2018-09-20 15:43:49 +08:00
//
2018-09-18 23:49:48 +08:00
// Created by xzl on 2018/9/18.
//
#ifndef ZLMEDIAKIT_RTSPMAKER_H
#define ZLMEDIAKIT_RTSPMAKER_H
2018-10-23 11:09:21 +08:00
#include "RTP/H264RtpCodec.h"
#include "RTP/AACRtpCodec.h"
#include "Util/base64.h"
2018-09-18 23:49:48 +08:00
namespace ZL{
namespace Rtsp{
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* sdp基类
*/
2018-10-23 14:32:06 +08:00
class Sdp : public FrameRingInterface , public RtpRingInterface , public CodecInfo{
2018-09-18 23:49:48 +08:00
public:
typedef std::shared_ptr<Sdp> Ptr;
2018-10-23 14:32:06 +08:00
/**
* sdp
* @param sample_rate
* @param playload_type pt类型
*/
2018-10-23 11:38:56 +08:00
Sdp(uint32_t sample_rate, uint8_t playload_type){
_sample_rate = sample_rate;
_playload_type = playload_type;
}
2018-09-18 23:49:48 +08:00
virtual ~Sdp(){}
2018-10-23 14:32:06 +08:00
2018-09-19 12:34:29 +08:00
/**
* sdp字符串
* @return
*/
2018-10-23 11:09:21 +08:00
virtual string getSdp() const = 0;
2018-09-19 12:34:29 +08:00
2018-10-23 14:32:06 +08:00
/**
*
* @return
*/
2018-10-23 11:09:21 +08:00
TrackType getTrackType() const override {
return TrackInvalid;
}
2018-09-19 12:34:29 +08:00
2018-10-23 14:32:06 +08:00
/**
* id
* @return
*/
2018-10-23 11:09:21 +08:00
CodecId getCodecId() const override{
return CodecInvalid;
}
2018-10-23 14:32:06 +08:00
/**
*
* @return
*/
2018-10-23 11:09:21 +08:00
FrameRingInterface::RingType::Ptr getFrameRing() const override {
return _encoder->getFrameRing();
}
2018-10-23 14:32:06 +08:00
/**
* rtp环形缓存
* @return
*/
2018-10-23 11:09:21 +08:00
RtpRingInterface::RingType::Ptr getRtpRing() const override{
return _encoder->getRtpRing();
}
2018-10-23 14:32:06 +08:00
/**
* rtp打包
* @param frame
* @param key_pos
*/
2018-10-23 11:09:21 +08:00
void inputFrame(const Frame::Ptr &frame,bool key_pos) override{
_encoder->inputFrame(frame,key_pos);
}
2018-10-23 14:32:06 +08:00
/**
* rtp后直接输入rtp
* @param rtp rtp数据包
* @param key_pos rtp包
*/
2018-10-23 11:09:21 +08:00
void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{
_encoder->inputRtp(rtp,key_pos);
}
2018-10-23 14:32:06 +08:00
/**
* rtp打包器共用一个环形缓存
* @param ring
*/
2018-10-23 11:09:21 +08:00
void setFrameRing(const FrameRingInterface::RingType::Ptr &ring) override{
2018-10-23 11:47:27 +08:00
_encoder->setFrameRing(ring);
2018-10-23 11:09:21 +08:00
}
2018-10-23 14:32:06 +08:00
/**
* rtp打包器共用一个环形缓存
* @param ring
*/
2018-10-23 11:09:21 +08:00
void setRtpRing(const RtpRingInterface::RingType::Ptr &ring) override{
2018-10-23 11:47:27 +08:00
_encoder->setRtpRing(ring);
2018-10-23 11:09:21 +08:00
}
2018-10-23 14:32:06 +08:00
/**
* Rtp打包器
* @param ssrc ssrc0
* @param mtu mtu大小15001400
*/
2018-10-23 11:38:56 +08:00
virtual void createRtpEncoder(uint32_t ssrc, int mtu) {
2018-10-23 16:41:25 +08:00
_encoder = RtpCodec::getRtpCodecById(getCodecId(),
ssrc,
mtu,
_sample_rate,
_playload_type,
getTrackType() * 2);
2018-10-23 11:38:56 +08:00
}
private:
RtpCodec::Ptr _encoder;
uint8_t _playload_type;
uint32_t _sample_rate;
2018-09-18 23:49:48 +08:00
};
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* sdp中除音视频外的其他描述部分
*/
2018-10-23 11:47:27 +08:00
class TitleSdp : public Sdp{
2018-09-18 23:49:48 +08:00
public:
2018-09-19 12:34:29 +08:00
/**
* title类型sdp
* @param dur_sec rtsp点播时长0
* @param header sdp描述
* @param version sdp版本
*/
2018-10-23 11:47:27 +08:00
TitleSdp(float dur_sec = 0,
2018-09-18 23:49:48 +08:00
const map<string,string> &header = map<string,string>(),
2018-10-23 11:38:56 +08:00
int version = 0) : Sdp(0,0){
2018-09-18 23:49:48 +08:00
_printer << "v=" << version << "\r\n";
if(!header.empty()){
for (auto &pr : header){
_printer << pr.first << "=" << pr.second << "\r\n";
}
} else {
_printer << "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
2018-10-23 11:09:21 +08:00
_printer << "s=RTSP Session, streamed by the ZLMediaKit\r\n";
_printer << "i=ZLMediaKit Live Stream\r\n";
2018-09-18 23:49:48 +08:00
_printer << "c=IN IP4 0.0.0.0\r\n";
_printer << "t=0 0\r\n";
}
if(dur_sec <= 0){
_printer << "a=range:npt=0-\r\n";
}else{
_printer << "a=range:npt=0-" << dur_sec << "\r\n";
}
_printer << "a=control:*\r\n";
}
2018-09-19 12:34:29 +08:00
string getSdp() const override {
2018-09-18 23:49:48 +08:00
return _printer;
}
private:
_StrPrinter _printer;
};
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* h264类型sdp
*/
2018-10-23 11:47:27 +08:00
class H264Sdp : public Sdp {
2018-09-18 23:49:48 +08:00
public:
2018-09-19 12:34:29 +08:00
/**
*
* @param sps 264 sps,0x00000001
* @param pps 264 pps,0x00000001
2018-10-23 14:32:06 +08:00
* @param playload_type rtp playload type 96
2018-09-19 12:34:29 +08:00
* @param bitrate
*/
2018-10-23 11:47:27 +08:00
H264Sdp(const string &sps,
2018-09-18 23:49:48 +08:00
const string &pps,
int playload_type = 96,
2018-10-23 14:32:06 +08:00
int bitrate = 4000) : Sdp(90000,playload_type) {
2018-09-18 23:49:48 +08:00
//视频通道
_printer << "m=video 0 RTP/AVP " << playload_type << "\r\n";
_printer << "b=AS:" << bitrate << "\r\n";
2018-10-23 14:32:06 +08:00
_printer << "a=rtpmap:" << playload_type << " H264/" << 90000 << "\r\n";
2018-09-18 23:49:48 +08:00
_printer << "a=fmtp:" << playload_type << " packetization-mode=1;profile-level-id=";
char strTemp[100];
int profile_level_id = 0;
string strSPS = sps.substr(4);
string strPPS = pps.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
}
memset(strTemp, 0, 100);
sprintf(strTemp, "%06X", profile_level_id);
_printer << strTemp;
_printer << ";sprop-parameter-sets=";
memset(strTemp, 0, 100);
av_base64_encode(strTemp, 100, (uint8_t *) strSPS.data(), strSPS.size());
_printer << strTemp << ",";
memset(strTemp, 0, 100);
av_base64_encode(strTemp, 100, (uint8_t *) strPPS.data(), strPPS.size());
_printer << strTemp << "\r\n";
2018-10-23 11:38:56 +08:00
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
2018-09-18 23:49:48 +08:00
}
2018-09-19 12:34:29 +08:00
string getSdp() const override {
2018-09-18 23:49:48 +08:00
return _printer;
}
2018-09-19 12:34:29 +08:00
TrackType getTrackType() const override {
2018-09-18 23:49:48 +08:00
return TrackVideo;
2018-10-23 11:09:21 +08:00
}
2018-09-18 23:49:48 +08:00
2018-10-23 11:09:21 +08:00
CodecId getCodecId() const override {
return CodecH264;
}
2018-09-18 23:49:48 +08:00
private:
_StrPrinter _printer;
};
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* aac类型SDP
*/
2018-10-23 11:47:27 +08:00
class AACSdp : public Sdp {
2018-09-18 23:49:48 +08:00
public:
2018-09-19 12:34:29 +08:00
/**
2018-10-23 14:32:06 +08:00
*
2018-09-19 12:34:29 +08:00
* @param aac_cfg aac两个字节的配置描述
* @param sample_rate
2018-10-23 14:32:06 +08:00
* @param playload_type rtp playload type 98
2018-09-19 12:34:29 +08:00
* @param bitrate
*/
2018-10-23 11:47:27 +08:00
AACSdp(const string &aac_cfg,
2018-09-18 23:49:48 +08:00
int sample_rate,
int playload_type = 98,
2018-10-23 11:38:56 +08:00
int bitrate = 128) : Sdp(sample_rate,playload_type){
2018-09-18 23:49:48 +08:00
_printer << "m=audio 0 RTP/AVP " << playload_type << "\r\n";
_printer << "b=AS:" << bitrate << "\r\n";
_printer << "a=rtpmap:" << playload_type << " MPEG4-GENERIC/" << sample_rate << "\r\n";
char configStr[32] = {0};
snprintf(configStr, sizeof(configStr), "%02X%02x", aac_cfg[0], aac_cfg[1]);
_printer << "a=fmtp:" << playload_type << " streamtype=5;profile-level-id=1;mode=AAC-hbr;"
<< "sizelength=13;indexlength=3;indexdeltalength=3;config="
<< configStr << "\r\n";
2018-10-23 11:38:56 +08:00
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
2018-09-18 23:49:48 +08:00
}
2018-09-19 12:34:29 +08:00
string getSdp() const override {
2018-09-18 23:49:48 +08:00
return _printer;
}
2018-09-19 12:34:29 +08:00
TrackType getTrackType() const override {
2018-09-18 23:49:48 +08:00
return TrackAudio;
};
2018-10-23 11:09:21 +08:00
CodecId getCodecId() const override {
return CodecAAC;
}
2018-09-18 23:49:48 +08:00
private:
_StrPrinter _printer;
};
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* rtsp生成器
*/
class RtspEncoder : public FrameRingInterface , public RtpRingInterface{
2018-09-18 23:49:48 +08:00
public:
2018-09-19 12:34:29 +08:00
/**
*
*/
2018-10-23 11:09:21 +08:00
RtspEncoder(){
2018-10-23 16:41:25 +08:00
_rtpRing = std::make_shared<RtpRingInterface::RingType>();
_frameRing = std::make_shared<FrameRingInterface::RingType>();
2018-09-18 23:49:48 +08:00
}
2018-10-23 11:09:21 +08:00
virtual ~RtspEncoder(){}
2018-09-19 12:34:29 +08:00
/**
* track
2018-10-23 11:09:21 +08:00
* @param sdp
2018-09-19 12:34:29 +08:00
* @param ssrc rtp ssrc
* @param mtu rtp mtu
*/
2018-10-23 11:09:21 +08:00
void addTrack(const Sdp::Ptr & sdp,uint32_t ssrc = 0,int mtu = 1400){
2018-09-19 12:34:29 +08:00
if(ssrc == 0){
2018-10-23 11:09:21 +08:00
ssrc = ((uint64_t) sdp.get()) & 0xFFFFFFFF;
2018-09-18 23:49:48 +08:00
}
2018-10-23 11:09:21 +08:00
sdp->createRtpEncoder(ssrc, mtu);
sdp->setFrameRing(_frameRing);
sdp->setRtpRing(_rtpRing);
_sdp_map[sdp->getTrackType()] = sdp;
2018-09-18 23:49:48 +08:00
}
2018-09-19 12:34:29 +08:00
/**
* SDP字符串
* @return SDP字符串
*/
2018-09-18 23:49:48 +08:00
string getSdp() {
2018-10-23 11:09:21 +08:00
_StrPrinter printer;
for(auto &pr : _sdp_map){
printer << pr.second->getSdp() ;
}
return printer;
2018-09-18 23:49:48 +08:00
}
2018-09-19 12:34:29 +08:00
/**
2018-10-23 11:09:21 +08:00
* rtp
* @param frame
* @param key_pos
2018-09-19 12:34:29 +08:00
*/
2018-10-23 11:09:21 +08:00
void inputFrame(const Frame::Ptr &frame,bool key_pos = true) override {
auto it = _sdp_map.find(frame->getTrackType());
if(it == _sdp_map.end()){
return ;
2018-09-18 23:49:48 +08:00
}
2018-10-23 11:09:21 +08:00
it->second->inputFrame(frame,key_pos);
2018-09-18 23:49:48 +08:00
}
2018-10-23 11:09:21 +08:00
/**
* rtp然后再写入
* @param rtp rtp包
* @param key_pos rtp包
*/
void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override {
2018-10-23 11:38:56 +08:00
auto it = _sdp_map.find(rtp->getTrackType());
if(it == _sdp_map.end()){
return ;
}
it->second->inputRtp(rtp,key_pos);
2018-10-23 11:09:21 +08:00
}
2018-09-18 23:49:48 +08:00
2018-10-23 11:09:21 +08:00
/**
* rtp环形缓存
* @return
*/
RtpRingInterface::RingType::Ptr getRtpRing() const override{
return _rtpRing;
}
2018-09-18 23:49:48 +08:00
2018-10-23 11:09:21 +08:00
/**
*
* @return
*/
FrameRingInterface::RingType::Ptr getFrameRing() const override{
return _frameRing;
}
/**
*
* @param ring
*/
void setFrameRing(const FrameRingInterface::RingType::Ptr &ring) override{
_frameRing = ring;
for(auto &pr : _sdp_map){
pr.second->setFrameRing(ring);
}
}
2018-09-18 23:49:48 +08:00
2018-10-23 11:09:21 +08:00
/**
* rtp环形缓存
* @param ring
*/
void setRtpRing(const RtpRingInterface::RingType::Ptr &ring) override{
_rtpRing = ring;
for(auto &pr : _sdp_map){
pr.second->setRtpRing(ring);
}
}
private:
map<int,Sdp::Ptr> _sdp_map;
RtpRingInterface::RingType::Ptr _rtpRing;
FrameRingInterface::RingType::Ptr _frameRing;
};
2018-09-18 23:49:48 +08:00
}
}
#endif //ZLMEDIAKIT_RTSPMAKER_H