ZLMediaKit/src/Player/PlayerProxy.cpp

232 lines
7.8 KiB
C++
Raw Normal View History

2017-10-09 22:11:01 +08:00
/*
2020-04-04 20:30:09 +08:00
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
2017-09-27 16:20:30 +08:00
*
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
2017-09-27 16:20:30 +08:00
*
2020-04-04 20:30:09 +08:00
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
2017-04-01 16:35:56 +08:00
*/
2017-05-02 17:15:12 +08:00
#include "Common/config.h"
2017-04-01 16:35:56 +08:00
#include "PlayerProxy.h"
2017-04-25 11:35:41 +08:00
#include "Util/mini.h"
2017-04-01 16:35:56 +08:00
#include "Util/MD5.h"
#include "Util/logger.h"
2019-06-28 17:25:53 +08:00
#include "Extension/AAC.h"
2017-04-01 16:35:56 +08:00
2018-10-24 17:17:55 +08:00
using namespace toolkit;
using namespace std;
2017-04-01 16:35:56 +08:00
2018-10-24 17:17:55 +08:00
namespace mediakit {
2017-04-01 16:35:56 +08:00
2020-08-01 10:22:12 +08:00
PlayerProxy::PlayerProxy(const string &vhost, const string &app, const string &stream_id,
2020-09-20 09:26:00 +08:00
bool enable_hls, bool enable_mp4, int retry_count, const EventPoller::Ptr &poller)
: MediaPlayer(poller) {
2020-08-01 10:22:12 +08:00
_vhost = vhost;
_app = app;
_stream_id = stream_id;
_enable_hls = enable_hls;
_enable_mp4 = enable_mp4;
_retry_count = retry_count;
_on_close = [](const SockException &) {};
(*this)[Client::kWaitTrackReady] = false;
2017-04-01 16:35:56 +08:00
}
2019-05-20 18:08:55 +08:00
void PlayerProxy::setPlayCallbackOnce(const function<void(const SockException &ex)> &cb) {
2020-08-01 10:22:12 +08:00
_on_play = cb;
2019-05-20 18:08:55 +08:00
}
2019-05-27 14:14:42 +08:00
void PlayerProxy::setOnClose(const function<void(const SockException &ex)> &cb) {
_on_close = cb ? cb : [](const SockException &) {};
2019-05-27 14:14:42 +08:00
}
2019-03-27 18:41:52 +08:00
void PlayerProxy::play(const string &strUrlTmp) {
2020-03-20 11:51:24 +08:00
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
std::shared_ptr<int> piFailedCnt(new int(0)); //连续播放失败次数
setOnPlayResult([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) {
2020-03-20 11:51:24 +08:00
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
2020-03-20 11:51:24 +08:00
return;
}
2019-05-20 18:08:55 +08:00
if (strongSelf->_on_play) {
2020-08-01 10:22:12 +08:00
strongSelf->_on_play(err);
strongSelf->_on_play = nullptr;
2019-05-20 18:08:55 +08:00
}
if (!err) {
// 取消定时器,避免hls拉流索引文件因为网络波动失败重连成功后出现循环重试的情况
strongSelf->_timer.reset();
2020-03-20 11:51:24 +08:00
// 播放成功
*piFailedCnt = 0;//连续播放失败次数清0
strongSelf->onPlaySuccess();
} else if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
2020-03-20 11:51:24 +08:00
// 播放失败,延时重试播放
strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++);
} else {
//达到了最大重试次数,回调关闭
strongSelf->_on_close(err);
2020-03-20 11:51:24 +08:00
}
});
setOnShutdown([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) {
2020-03-20 11:51:24 +08:00
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
2020-03-20 11:51:24 +08:00
return;
}
//注销直接拉流代理产生的流:#532
strongSelf->setMediaSource(nullptr);
if (strongSelf->_muxer) {
2020-09-06 17:54:52 +08:00
auto tracks = strongSelf->MediaPlayer::getTracks(false);
for (auto &track : tracks) {
2020-08-01 10:22:12 +08:00
track->delDelegate(strongSelf->_muxer.get());
2020-03-20 11:51:24 +08:00
}
GET_CONFIG(bool, resetWhenRePlay, General::kResetWhenRePlay);
2020-03-20 11:51:24 +08:00
if (resetWhenRePlay) {
2020-08-01 10:22:12 +08:00
strongSelf->_muxer.reset();
2020-03-20 11:51:24 +08:00
} else {
2020-08-01 10:22:12 +08:00
strongSelf->_muxer->resetTracks();
2020-03-20 11:51:24 +08:00
}
}
//播放异常中断,延时重试播放
if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++);
} else {
//达到了最大重试次数,回调关闭
strongSelf->_on_close(err);
2020-03-20 11:51:24 +08:00
}
});
MediaPlayer::play(strUrlTmp);
2020-09-27 11:32:49 +08:00
_pull_url = strUrlTmp;
2021-01-17 10:22:51 +08:00
setDirectProxy();
}
void PlayerProxy::setDirectProxy() {
2020-03-20 11:51:24 +08:00
MediaSource::Ptr mediaSource;
2021-01-17 10:22:51 +08:00
if (dynamic_pointer_cast<RtspPlayer>(_delegate)) {
2020-03-20 11:51:24 +08:00
//rtsp拉流
2021-01-17 10:22:51 +08:00
GET_CONFIG(bool, directProxy, Rtsp::kDirectProxy);
if (directProxy) {
2020-08-01 10:22:12 +08:00
mediaSource = std::make_shared<RtspMediaSource>(_vhost, _app, _stream_id);
2020-03-20 11:51:24 +08:00
}
2021-01-17 10:22:51 +08:00
} else if (dynamic_pointer_cast<RtmpPlayer>(_delegate)) {
2020-09-20 09:26:00 +08:00
//rtmp拉流,rtmp强制直接代理
mediaSource = std::make_shared<RtmpMediaSource>(_vhost, _app, _stream_id);
2020-03-20 11:51:24 +08:00
}
2021-01-17 10:22:51 +08:00
if (mediaSource) {
2020-10-24 23:30:06 +08:00
setMediaSource(mediaSource);
2020-03-20 11:51:24 +08:00
mediaSource->setListener(shared_from_this());
}
2017-04-01 16:35:56 +08:00
}
PlayerProxy::~PlayerProxy() {
2020-03-20 11:51:24 +08:00
_timer.reset();
2017-04-01 16:35:56 +08:00
}
2020-08-01 10:22:12 +08:00
void PlayerProxy::rePlay(const string &strUrl, int iFailedCnt) {
auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60 * 1000));
2020-03-20 11:51:24 +08:00
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
_timer = std::make_shared<Timer>(iDelay / 1000.0f, [weakSelf, strUrl, iFailedCnt]() {
2020-03-20 11:51:24 +08:00
//播放失败次数越多,则延时越长
auto strongPlayer = weakSelf.lock();
if (!strongPlayer) {
2020-03-20 11:51:24 +08:00
return false;
}
WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl;
2020-03-20 11:51:24 +08:00
strongPlayer->MediaPlayer::play(strUrl);
2021-01-17 10:22:51 +08:00
strongPlayer->setDirectProxy();
2020-03-20 11:51:24 +08:00
return false;
}, getPoller());
2017-04-01 16:35:56 +08:00
}
bool PlayerProxy::close(MediaSource &sender, bool force) {
if (!force && totalReaderCount()) {
2019-05-27 18:39:43 +08:00
return false;
}
2020-03-20 11:51:24 +08:00
//通知其停止推流
2020-08-01 10:22:12 +08:00
weak_ptr<PlayerProxy> weakSelf = dynamic_pointer_cast<PlayerProxy>(shared_from_this());
getPoller()->async_first([weakSelf]() {
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
return;
}
strongSelf->_muxer.reset();
2020-10-24 23:30:06 +08:00
strongSelf->setMediaSource(nullptr);
2020-08-01 10:22:12 +08:00
strongSelf->teardown();
2020-03-20 11:51:24 +08:00
});
_on_close(SockException(Err_shutdown, "closed by user"));
2019-05-29 18:08:50 +08:00
WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force;
return true;
}
2017-04-01 16:35:56 +08:00
int PlayerProxy::totalReaderCount() {
return (_muxer ? _muxer->totalReaderCount() : 0) + (_media_src ? _media_src->readerCount() : 0);
2019-12-28 16:48:11 +08:00
}
int PlayerProxy::totalReaderCount(MediaSource &sender) {
2020-03-20 11:51:24 +08:00
return totalReaderCount();
2019-12-28 16:48:11 +08:00
}
MediaOriginType PlayerProxy::getOriginType(MediaSource &sender) const {
2020-09-27 11:32:49 +08:00
return MediaOriginType::pull;
}
string PlayerProxy::getOriginUrl(MediaSource &sender) const {
2020-09-27 11:32:49 +08:00
return _pull_url;
}
std::shared_ptr<SockInfo> PlayerProxy::getOriginSock(MediaSource &sender) const {
2020-09-27 11:32:49 +08:00
return getSockInfo();
}
2018-10-26 17:14:39 +08:00
void PlayerProxy::onPlaySuccess() {
GET_CONFIG(bool, resetWhenRePlay, General::kResetWhenRePlay);
if (dynamic_pointer_cast<RtspMediaSource>(_media_src)) {
2020-03-20 11:51:24 +08:00
//rtsp拉流代理
2020-08-01 10:22:12 +08:00
if (resetWhenRePlay || !_muxer) {
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), false, true, _enable_hls, _enable_mp4);
2020-03-20 11:51:24 +08:00
}
} else if (dynamic_pointer_cast<RtmpMediaSource>(_media_src)) {
2020-03-20 11:51:24 +08:00
//rtmp拉流代理
2020-08-01 10:22:12 +08:00
if (resetWhenRePlay || !_muxer) {
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), true, false, _enable_hls, _enable_mp4);
2020-03-20 11:51:24 +08:00
}
} else {
//其他拉流代理
2020-08-01 10:22:12 +08:00
if (resetWhenRePlay || !_muxer) {
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), true, true, _enable_hls, _enable_mp4);
2020-03-20 11:51:24 +08:00
}
}
2020-08-01 10:22:12 +08:00
_muxer->setMediaListener(shared_from_this());
2018-10-26 17:14:39 +08:00
2020-08-01 10:22:12 +08:00
auto videoTrack = getTrack(TrackVideo, false);
if (videoTrack) {
2020-03-20 11:51:24 +08:00
//添加视频
2020-08-01 10:22:12 +08:00
_muxer->addTrack(videoTrack);
2020-03-20 11:51:24 +08:00
//视频数据写入_mediaMuxer
2020-08-01 10:22:12 +08:00
videoTrack->addDelegate(_muxer);
2020-03-20 11:51:24 +08:00
}
2018-10-26 17:14:39 +08:00
2020-03-20 11:51:24 +08:00
auto audioTrack = getTrack(TrackAudio, false);
2020-08-01 10:22:12 +08:00
if (audioTrack) {
2020-03-20 11:51:24 +08:00
//添加音频
2020-08-01 10:22:12 +08:00
_muxer->addTrack(audioTrack);
2020-03-20 11:51:24 +08:00
//音频数据写入_mediaMuxer
2020-08-01 10:22:12 +08:00
audioTrack->addDelegate(_muxer);
2020-03-20 11:51:24 +08:00
}
2019-12-17 09:05:34 +08:00
2020-03-20 11:51:24 +08:00
//添加完毕所有track防止单track情况下最大等待3秒
2020-08-01 10:22:12 +08:00
_muxer->addTrackCompleted();
if (_media_src) {
//让_muxer对象拦截一部分事件(比如说录像相关事件)
_media_src->setListener(_muxer);
2019-12-17 09:05:34 +08:00
}
}
2018-10-24 17:17:55 +08:00
} /* namespace mediakit */