RtspPlayer.h 4.72 KB
Newer Older
xzl committed
1 2 3 4 5 6 7 8 9
/*
 * RtspPlayer.h
 *
 *  Created on: 2016年8月17日
 *      Author: xzl
 */

#ifndef SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
#define SRC_RTSPPLAYER_RTSPPLAYER_H_TXT_
xiongzilaing committed
10

xzl committed
11
#include <string>
xiongzilaing committed
12 13
#include <memory>
#include "Rtsp.h"
xzl committed
14
#include "RtspSession.h"
xiongzilaing committed
15 16
#include "RtspMediaSource.h"
#include "Player/PlayerBase.h"
xzl committed
17
#include "Util/util.h"
xiongzilaing committed
18
#include "Util/logger.h"
xzl committed
19
#include "Util/TimeTicker.h"
xiongzilaing committed
20 21 22
#include "Poller/Timer.h"
#include "Network/Socket.h"
#include "Network/TcpClient.h"
xzl committed
23 24 25 26

using namespace std;
using namespace ZL::Rtsp;
using namespace ZL::Player;
xiongzilaing committed
27 28 29 30
using namespace ZL::Util;
using namespace ZL::Poller;
using namespace ZL::Network;

xzl committed
31 32 33 34 35 36 37
namespace ZL {
namespace Rtsp {

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

xzl committed
42 43
	RtspPlayer();
	virtual ~RtspPlayer(void);
xiongziliang committed
44
	void play(const char* strUrl) override;
xzl committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 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
	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
90
	void play(const char* strUrl, const char *strUser, const char *strPwd,  eRtpType eType);
xzl committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 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
	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_ */