RtspPlayer.h 5.86 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * MIT License
xzl committed
3
 *
xiongziliang committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 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.
xzl committed
25 26 27 28
 */

#ifndef SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
#define SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
xiongzilaing committed
29

xzl committed
30
#include <string>
xiongzilaing committed
31 32
#include <memory>
#include "Rtsp.h"
xzl committed
33
#include "RtspSession.h"
xiongzilaing committed
34 35
#include "RtspMediaSource.h"
#include "Player/PlayerBase.h"
xzl committed
36
#include "Util/util.h"
xiongzilaing committed
37
#include "Util/logger.h"
xzl committed
38
#include "Util/TimeTicker.h"
xiongzilaing committed
39 40 41
#include "Poller/Timer.h"
#include "Network/Socket.h"
#include "Network/TcpClient.h"
xzl committed
42 43 44 45

using namespace std;
using namespace ZL::Rtsp;
using namespace ZL::Player;
xiongzilaing committed
46 47 48 49
using namespace ZL::Util;
using namespace ZL::Poller;
using namespace ZL::Network;

xzl committed
50 51 52 53 54 55 56
namespace ZL {
namespace Rtsp {

//实现了rtsp播放器协议部分的功能
class RtspPlayer: public PlayerBase,public TcpClient {
public:
	typedef std::shared_ptr<RtspPlayer> Ptr;
xiongziliang committed
57
	//设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播)
58
	//设置方法:player[RtspPlayer::kRtpType] = 0/1/2;
xiongziliang committed
59 60
	static const char kRtpType[];

xzl committed
61 62
	RtspPlayer();
	virtual ~RtspPlayer(void);
xiongziliang committed
63
	void play(const char* strUrl) override;
xzl committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	void pause(bool bPause) override;
	void teardown() override;
	float getRtpLossRate(int iTrackId) const override;
protected:
	//派生类回调函数
	virtual bool onCheckSDP(const string &strSdp, const RtspTrack *pTrack, int iTrackCnt) = 0;
	virtual void onRecvRTP(const RtpPacket::Ptr &pRtppt, const RtspTrack &track) = 0;
    float getProgressTime() const;
    void seekToTime(float fTime);
private:
	 void _onShutdown(const SockException &ex) {
		WarnL << ex.getErrCode() << " " << ex.what();
		m_pPlayTimer.reset();
		m_pRtpTimer.reset();
		m_pBeatTimer.reset();
		onShutdown(ex);
	}
	void _onRecvRTP(const RtpPacket::Ptr &pRtppt, const RtspTrack &track) {
		m_rtpTicker.resetTime();
		onRecvRTP(pRtppt,track);
	}
	void _onPlayResult(const SockException &ex) {
		WarnL << ex.getErrCode() << " " << ex.what();
        m_pPlayTimer.reset();
        m_pRtpTimer.reset();
		if (!ex) {
			m_rtpTicker.resetTime();
			weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
			m_pRtpTimer.reset( new Timer(5, [weakSelf]() {
				auto strongSelf=weakSelf.lock();
				if(!strongSelf) {
					return false;
				}
				if(strongSelf->m_rtpTicker.elapsedTime()>10000) {
					//recv rtp timeout!
					strongSelf->_onShutdown(SockException(Err_timeout,"recv rtp timeout"));
					strongSelf->teardown();
					return false;
				}
				return true;
			}));
		}
		onPlayResult(ex);
	}

xiongziliang committed
109
	void play(const char* strUrl, const char *strUser, const char *strPwd,  eRtpType eType);
xzl committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
	void onConnect(const SockException &err) override;
	void onRecv(const Socket::Buffer::Ptr &pBuf) override;
	void onErr(const SockException &ex) override;

	void HandleResSETUP(const Parser &parser, unsigned int uiTrackIndex);
	void HandleResDESCRIBE(const Parser &parser);
	void HandleResPAUSE(const Parser &parser, bool bPause);

	//发数据给服务器
	inline int write(const char *strMsg, ...);
	inline int onProcess(const char* strBuf);
	//生成rtp包结构体
	inline void splitRtp(unsigned char *pucData, unsigned int uiLen);
	//发送SETUP命令
	inline void sendSetup(unsigned int uiTrackIndex);
    inline void sendPause(bool bPause,float fTime);
	//处理一个rtp包
	inline bool HandleOneRtp(int iTrackidx, unsigned char *ucData, unsigned int uiLen);
	bool sendOptions();
	inline void _onRecvRTP(const RtpPacket::Ptr &pRtppt, int iTrackidx);
	inline int getTrackIndex(int iTrackId) const{
		for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
			if (m_aTrackInfo[i].trackId == iTrackId) {
				return i;
			}
		}
		return -1;
	}

	string m_strUrl;
	unsigned int m_uiTrackCnt = 0;
	RtspTrack m_aTrackInfo[2];

	function<void(const Parser&)> m_onHandshake;
	RtspMediaSource::PoolType m_pktPool;

	uint8_t *m_pucRtpBuf = nullptr;
	unsigned int m_uiRtpBufLen = 0;
	Socket::Ptr m_apUdpSock[2];
	//rtsp info
	string m_strSession;
	unsigned int m_uiCseq = 1;
	uint32_t m_aui32SsrcErrorCnt[2] = { 0, 0 };
	string m_strAuthorization;
	string m_strContentBase;
	eRtpType m_eType = RTP_TCP;
	/* RTP包排序所用参数 */
	uint16_t m_aui16LastSeq[2] = { 0 , 0 };
	uint64_t m_aui64SeqOkCnt[2] = { 0 , 0};
	bool m_abSortStarted[2] = { 0 , 0};
	map<uint32_t , RtpPacket::Ptr> m_amapRtpSort[2];

	/* 丢包率统计需要用到的参数 */
	uint16_t m_aui16FirstSeq[2] = { 0 , 0};
	uint16_t m_aui16NowSeq[2] = { 0 , 0 };
	uint64_t m_aui64RtpRecv[2] = { 0 , 0};

	//超时功能实现
	Ticker m_rtpTicker;
	std::shared_ptr<Timer> m_pPlayTimer;
	std::shared_ptr<Timer> m_pRtpTimer;
	//心跳定时器
	std::shared_ptr<Timer> m_pBeatTimer;
    
    //播放进度控制
    float m_fSeekTo = 0;
    double m_adFistStamp[2] = {0,0};
    double m_adNowStamp[2] = {0,0};
    Ticker m_aNowStampTicker[2];
};

} /* namespace Rtsp */
} /* namespace ZL */

#endif /* SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_ */