RtmpPlayer.h 4.91 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 29
 */

#ifndef SRC_RTMP_RtmpPlayer2_H_
#define SRC_RTMP_RtmpPlayer2_H_

xiongzilaing committed
30
#include <memory>
xzl committed
31 32 33
#include <string>
#include <functional>
#include "amf.h"
xiongzilaing committed
34
#include "Rtmp.h"
xzl committed
35
#include "RtmpProtocol.h"
xiongzilaing committed
36 37 38 39 40 41
#include "Player/PlayerBase.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "Util/TimeTicker.h"
#include "Network/Socket.h"
#include "Network/TcpClient.h"
xzl committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

using namespace std;
using namespace ZL::Util;
using namespace ZL::Player;
using namespace ZL::Network;

namespace ZL {
namespace Rtmp {

class RtmpPlayer:public PlayerBase, public TcpClient,  public RtmpProtocol{
public:
	typedef std::shared_ptr<RtmpPlayer> Ptr;
	RtmpPlayer();
	virtual ~RtmpPlayer();

xiongziliang committed
57
	void play(const char* strUrl) override;
xzl committed
58 59 60 61
	void pause(bool bPause) override;
	void teardown() override;
protected:
	virtual bool onCheckMeta(AMFValue &val) =0;
xiongziliang committed
62
	virtual void onMediaData(const RtmpPacket::Ptr &chunkData) =0;
xzl committed
63 64 65 66 67 68 69 70 71 72
	float getProgressTime() const;
	void seekToTime(float fTime);
private:
	void _onShutdown(const SockException &ex) {
		WarnL << ex.getErrCode() << " " << ex.what();
		m_pPlayTimer.reset();
		m_pMediaTimer.reset();
		m_pBeatTimer.reset();
		onShutdown(ex);
	}
xiongziliang committed
73
	void _onMediaData(const RtmpPacket::Ptr &chunkData) {
xzl committed
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 109 110
		m_mediaTicker.resetTime();
		onMediaData(chunkData);
	}
	void _onPlayResult(const SockException &ex) {
		WarnL << ex.getErrCode() << " " << ex.what();
		m_pPlayTimer.reset();
		m_pMediaTimer.reset();
		if (!ex) {
			m_mediaTicker.resetTime();
			weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
			m_pMediaTimer.reset( new Timer(5, [weakSelf]() {
				auto strongSelf=weakSelf.lock();
				if(!strongSelf) {
					return false;
				}
				if(strongSelf->m_mediaTicker.elapsedTime()>10000) {
					//recv media timeout!
					strongSelf->_onShutdown(SockException(Err_timeout,"recv rtmp timeout"));
					strongSelf->teardown();
					return false;
				}
				return true;
			}));
		}
		onPlayResult(ex);
	}

	//for Tcpclient
	void onRecv(const Socket::Buffer::Ptr &pBuf) override;
	void onConnect(const SockException &err) override;
	void onErr(const SockException &ex) override;
	//fro RtmpProtocol
	void onRtmpChunk(RtmpPacket &chunkData) override;
	void onStreamDry(uint32_t ui32StreamId) override;
	void onSendRawData(const char *pcRawData, int iSize) override {
		send(pcRawData, iSize);
	}
xiongziliang committed
111 112 113 114
	void onSendRawData(string &&strData) override {
		send(std::move(strData));
	}

xzl committed
115 116 117

	template<typename FUN>
	inline void addOnResultCB(const FUN &fun) {
118
		lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
xzl committed
119 120 121 122
		m_mapOnResultCB.emplace(m_iReqID, fun);
	}
	template<typename FUN>
	inline void addOnStatusCB(const FUN &fun) {
123
		lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
xzl committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
		m_dqOnStatusCB.emplace_back(fun);
	}

	void onCmd_result(AMFDecoder &dec);
	void onCmd_onStatus(AMFDecoder &dec);
	void onCmd_onMetaData(AMFDecoder &dec);

	inline void send_connect();
	inline void send_createStream();
	inline void send_play();
	inline void send_pause(bool bPause);

	string m_strApp;
	string m_strStream;
	string m_strTcUrl;
	bool m_bPaused = false;

	unordered_map<int, function<void(AMFDecoder &dec)> > m_mapOnResultCB;
142
	recursive_mutex m_mtxOnResultCB;
xzl committed
143
	deque<function<void(AMFValue &dec)> > m_dqOnStatusCB;
144
	recursive_mutex m_mtxOnStatusCB;
xzl committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

	typedef void (RtmpPlayer::*rtmpCMDHandle)(AMFDecoder &dec);
	static unordered_map<string, rtmpCMDHandle> g_mapCmd;

	//超时功能实现
	Ticker m_mediaTicker;
	std::shared_ptr<Timer> m_pMediaTimer;
	std::shared_ptr<Timer> m_pPlayTimer;
	//心跳定时器
	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 Rtmp */
} /* namespace ZL */

#endif /* SRC_RTMP_RtmpPlayer2_H_ */