PlayerProxy.cpp 8.75 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
 */

xiongziliang committed
27
#include "Common/config.h"
xzl committed
28
#include "PlayerProxy.h"
xiongzilaing committed
29
#include "Util/mini.h"
xzl committed
30 31
#include "Util/MD5.h"
#include "Util/logger.h"
xiongzilaing committed
32
#include "Thread/AsyncTaskThread.h"
xzl committed
33

xiongziliang committed
34
using namespace toolkit;
xzl committed
35

xiongziliang committed
36
namespace mediakit {
xzl committed
37

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, 0xe0, 0x34, 0x20, 0xad, 0xf2, 0x3f, 0xb5, 0xdd,
                                0x73, 0xac, 0xbd, 0xca, 0xd7, 0x7d, 0x4a, 0x13, 0x2d, 0x2e, 0xa2, 0x62, 0x02, 0x70, 0x3c, 0x1c,
                                0xc5, 0x63, 0x55, 0x69, 0x94, 0xb5, 0x8d, 0x70, 0xd7, 0x24, 0x6a, 0x9e, 0x2e, 0x86, 0x24, 0xea,
                                0x4f, 0xd4, 0xf8, 0x10, 0x53, 0xa5, 0x4a, 0xb2, 0x9a, 0xf0, 0xa1, 0x4f, 0x2f, 0x66, 0xf9, 0xd3,
                                0x8c, 0xa6, 0x97, 0xd5, 0x84, 0xac, 0x09, 0x25, 0x98, 0x0b, 0x1d, 0x77, 0x04, 0xb8, 0x55, 0x49,
                                0x85, 0x27, 0x06, 0x23, 0x58, 0xcb, 0x22, 0xc3, 0x20, 0x3a, 0x12, 0x09, 0x48, 0x24, 0x86, 0x76,
                                0x95, 0xe3, 0x45, 0x61, 0x43, 0x06, 0x6b, 0x4a, 0x61, 0x14, 0x24, 0xa9, 0x16, 0xe0, 0x97, 0x34,
                                0xb6, 0x58, 0xa4, 0x38, 0x34, 0x90, 0x19, 0x5d, 0x00, 0x19, 0x4a, 0xc2, 0x80, 0x4b, 0xdc, 0xb7,
                                0x00, 0x18, 0x12, 0x3d, 0xd9, 0x93, 0xee, 0x74, 0x13, 0x95, 0xad, 0x0b, 0x59, 0x51, 0x0e, 0x99,
                                0xdf, 0x49, 0x98, 0xde, 0xa9, 0x48, 0x4b, 0xa5, 0xfb, 0xe8, 0x79, 0xc9, 0xe2, 0xd9, 0x60, 0xa5,
                                0xbe, 0x74, 0xa6, 0x6b, 0x72, 0x0e, 0xe3, 0x7b, 0x28, 0xb3, 0x0e, 0x52, 0xcc, 0xf6, 0x3d, 0x39,
                                0xb7, 0x7e, 0xbb, 0xf0, 0xc8, 0xce, 0x5c, 0x72, 0xb2, 0x89, 0x60, 0x33, 0x7b, 0xc5, 0xda, 0x49,
                                0x1a, 0xda, 0x33, 0xba, 0x97, 0x9e, 0xa8, 0x1b, 0x6d, 0x5a, 0x77, 0xb6, 0xf1, 0x69, 0x5a, 0xd1,
                                0xbd, 0x84, 0xd5, 0x4e, 0x58, 0xa8, 0x5e, 0x8a, 0xa0, 0xc2, 0xc9, 0x22, 0xd9, 0xa5, 0x53, 0x11,
                                0x18, 0xc8, 0x3a, 0x39, 0xcf, 0x3f, 0x57, 0xb6, 0x45, 0x19, 0x1e, 0x8a, 0x71, 0xa4, 0x46, 0x27,
                                0x9e, 0xe9, 0xa4, 0x86, 0xdd, 0x14, 0xd9, 0x4d, 0xe3, 0x71, 0xe3, 0x26, 0xda, 0xaa, 0x17, 0xb4,
                                0xac, 0xe1, 0x09, 0xc1, 0x0d, 0x75, 0xba, 0x53, 0x0a, 0x37, 0x8b, 0xac, 0x37, 0x39, 0x41, 0x27,
                                0x6a, 0xf0, 0xe9, 0xb4, 0xc2, 0xac, 0xb0, 0x39, 0x73, 0x17, 0x64, 0x95, 0xf4, 0xdc, 0x33, 0xbb,
                                0x84, 0x94, 0x3e, 0xf8, 0x65, 0x71, 0x60, 0x7b, 0xd4, 0x5f, 0x27, 0x79, 0x95, 0x6a, 0xba, 0x76,
                                0xa6, 0xa5, 0x9a, 0xec, 0xae, 0x55, 0x3a, 0x27, 0x48, 0x23, 0xcf, 0x5c, 0x4d, 0xbc, 0x0b, 0x35,
                                0x5c, 0xa7, 0x17, 0xcf, 0x34, 0x57, 0xc9, 0x58, 0xc5, 0x20, 0x09, 0xee, 0xa5, 0xf2, 0x9c, 0x6c,
                                0x39, 0x1a, 0x77, 0x92, 0x9b, 0xff, 0xc6, 0xae, 0xf8, 0x36, 0xba, 0xa8, 0xaa, 0x6b, 0x1e, 0x8c,
                                0xc5, 0x97, 0x39, 0x6a, 0xb8, 0xa2, 0x55, 0xa8, 0xf8};
#define MUTE_ADTS_DATA s_mute_adts
#define MUTE_ADTS_DATA_LEN sizeof(s_mute_adts)
63
#define MUTE_ADTS_DATA_MS 130
64

65 66 67 68 69 70
PlayerProxy::PlayerProxy(const char *strVhost,
                         const char *strApp,
                         const char *strSrc,
                         bool bEnableHls,
                         bool bEnableMp4,
                         int iRetryCount){
71 72 73 74 75 76
	_strVhost = strVhost;
	_strApp = strApp;
	_strSrc = strSrc;
    _bEnableHls = bEnableHls;
    _bEnableMp4 = bEnableMp4;
    _iRetryCount = iRetryCount;
xzl committed
77
}
xiongziliang committed
78
void PlayerProxy::play(const char* strUrl) {
xzl committed
79
	weak_ptr<PlayerProxy> weakSelf = shared_from_this();
80
	std::shared_ptr<int> piFailedCnt(new int(0)); //连续播放失败次数
xiongziliang committed
81 82
	string strUrlTmp(strUrl);
	setOnPlayResult([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) {
xzl committed
83 84 85 86 87 88 89
		auto strongSelf = weakSelf.lock();
		if(!strongSelf) {
			return;
		}
		if(!err) {
			// 播放成功
			*piFailedCnt = 0;//连续播放失败次数清0
xiongziliang committed
90
			strongSelf->onPlaySuccess();
91
		}else if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
xzl committed
92
			// 播放失败,延时重试播放
xiongziliang committed
93
			strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
xzl committed
94 95
		}
	});
xiongziliang committed
96
	setOnShutdown([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) {
xzl committed
97 98 99 100
		auto strongSelf = weakSelf.lock();
		if(!strongSelf) {
			return;
		}
101
		if(strongSelf->_mediaMuxer) {
xiongziliang committed
102 103
			auto tracks = strongSelf->getTracks();
			for (auto & track : tracks){
104
				track->delDelegate(strongSelf->_mediaMuxer.get());
xiongziliang committed
105
			}
106
			strongSelf->_mediaMuxer.reset();
xzl committed
107 108
		}
		//播放异常中断,延时重试播放
109
		if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
xiongziliang committed
110
			strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
xzl committed
111 112
		}
	});
xiongziliang committed
113
	MediaPlayer::play(strUrl);
xzl committed
114 115 116 117 118 119
}

PlayerProxy::~PlayerProxy() {
	auto iTaskId = reinterpret_cast<uint64_t>(this);
	AsyncTaskThread::Instance().CancelTask(iTaskId);
}
120
void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){
xzl committed
121
	auto iTaskId = reinterpret_cast<uint64_t>(this);
122
	auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000,60*1000));
xiongziliang committed
123
	weak_ptr<PlayerProxy> weakSelf = shared_from_this();
xzl committed
124
	AsyncTaskThread::Instance().CancelTask(iTaskId);
xiongziliang committed
125
	AsyncTaskThread::Instance().DoTaskDelay(iTaskId, iDelay, [weakSelf,strUrl,iFailedCnt]() {
xzl committed
126
		//播放失败次数越多,则延时越长
xiongziliang committed
127
		auto strongPlayer = weakSelf.lock();
xzl committed
128 129 130 131
		if(!strongPlayer) {
			return false;
		}
		WarnL << "重试播放[" << iFailedCnt << "]:"  << strUrl;
xiongziliang committed
132
		strongPlayer->MediaPlayer::play(strUrl.data());
xzl committed
133 134 135
		return false;
	});
}
136
bool PlayerProxy::close() {
137 138
    //通知其停止推流
    weak_ptr<PlayerProxy> weakSlef = dynamic_pointer_cast<PlayerProxy>(shared_from_this());
xiongziliang committed
139 140 141 142 143
	auto executor = getExecutor();
	if(executor) {
		executor->async_first([weakSlef]() {
			auto stronSelf = weakSlef.lock();
			if (stronSelf) {
144
				stronSelf->_mediaMuxer.reset();
xiongziliang committed
145 146 147 148
				stronSelf->teardown();
			}
		});
	}
149 150
    return true;
}
xzl committed
151

xiongziliang committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

class MuteAudioMaker : public FrameRingInterfaceDelegate{
public:
	typedef std::shared_ptr<MuteAudioMaker> Ptr;

	MuteAudioMaker(){};
	virtual ~MuteAudioMaker(){}
	void inputFrame(const Frame::Ptr &frame) override {
		if(frame->getTrackType() == TrackVideo){
			auto iAudioIndex = frame->stamp() / MUTE_ADTS_DATA_MS;
			if(_iAudioIndex != iAudioIndex){
				_iAudioIndex = iAudioIndex;
				auto aacFrame = std::make_shared<AACFrameNoCopyAble>((char *)MUTE_ADTS_DATA,
																	 MUTE_ADTS_DATA_LEN,
																	  _iAudioIndex * MUTE_ADTS_DATA_MS);
				FrameRingInterfaceDelegate::inputFrame(aacFrame);
			}
		}
	}
private:
	int _iAudioIndex = 0;
};

void PlayerProxy::onPlaySuccess() {
176 177
	_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost.data(),_strApp.data(),_strSrc.data(),getDuration(),_bEnableHls,_bEnableMp4));
	_mediaMuxer->setListener(shared_from_this());
xiongziliang committed
178 179 180 181

	auto videoTrack = getTrack(TrackVideo);
	if(videoTrack){
		//添加视频
182
		_mediaMuxer->addTrack(videoTrack);
xiongziliang committed
183
		//视频数据写入_pChn
184
		videoTrack->addDelegate(_mediaMuxer);
xiongziliang committed
185 186 187 188 189
	}

	auto audioTrack = getTrack(TrackAudio);
	if(audioTrack){
		//添加音频
190
		_mediaMuxer->addTrack(audioTrack);
xiongziliang committed
191
		//音频数据写入_pChn
192
        audioTrack->addDelegate(_mediaMuxer);
xiongziliang committed
193 194 195 196 197 198
    }else if(videoTrack){
		//没有音频信息,产生一个静音音频
		MuteAudioMaker::Ptr audioMaker = std::make_shared<MuteAudioMaker>();
		//videoTrack把数据写入MuteAudioMaker
		videoTrack->addDelegate(audioMaker);
		//添加一个静音Track至_pChn
199
		_mediaMuxer->addTrack(std::make_shared<AACTrack>());
xiongziliang committed
200
		//MuteAudioMaker生成静音音频然后写入_pChn;
201
		audioMaker->addDelegate(_mediaMuxer);
202 203 204
	}
}

xzl committed
205

xiongziliang committed
206
} /* namespace mediakit */