PlayerProxy.cpp 7.91 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
xiongziliang committed
3
 *
4
 * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
xiongziliang committed
5
 *
xiongziliang committed
6 7 8
 * 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.
xzl committed
9 10
 */

xiongziliang committed
11
#include "Common/config.h"
xzl committed
12
#include "PlayerProxy.h"
xiongzilaing committed
13
#include "Util/mini.h"
xzl committed
14 15
#include "Util/MD5.h"
#include "Util/logger.h"
xiongziliang committed
16
#include "Extension/AAC.h"
mtdxc committed
17 18 19 20
#include "Rtmp/RtmpMediaSource.h"
#include "Rtsp/RtspMediaSource.h"
#include "Rtmp/RtmpPlayer.h"
#include "Rtsp/RtspPlayer.h"
xzl committed
21

xiongziliang committed
22
using namespace toolkit;
夏楚 committed
23
using namespace std;
xzl committed
24

xiongziliang committed
25
namespace mediakit {
xzl committed
26

27 28
PlayerProxy::PlayerProxy(const string &vhost, const string &app, const string &stream_id, const ProtocolOption &option,
                         int retry_count, const EventPoller::Ptr &poller) : MediaPlayer(poller) , _option(option) {
29 30 31 32
    _vhost = vhost;
    _app = app;
    _stream_id = stream_id;
    _retry_count = retry_count;
33
    _on_close = [](const SockException &) {};
34
    (*this)[Client::kWaitTrackReady] = false;
xzl committed
35
}
36

37
void PlayerProxy::setPlayCallbackOnce(const function<void(const SockException &ex)> &cb) {
38
    _on_play = cb;
39
}
40

41 42
void PlayerProxy::setOnClose(const function<void(const SockException &ex)> &cb) {
    _on_close = cb ? cb : [](const SockException &) {};
43 44
}

xiongziliang committed
45
void PlayerProxy::play(const string &strUrlTmp) {
46 47
    weak_ptr<PlayerProxy> weakSelf = shared_from_this();
    std::shared_ptr<int> piFailedCnt(new int(0)); //连续播放失败次数
48
    setOnPlayResult([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) {
49
        auto strongSelf = weakSelf.lock();
50
        if (!strongSelf) {
51 52
            return;
        }
53

54
        if (strongSelf->_on_play) {
55 56
            strongSelf->_on_play(err);
            strongSelf->_on_play = nullptr;
57 58
        }

59
        if (!err) {
60 61
            // 取消定时器,避免hls拉流索引文件因为网络波动失败重连成功后出现循环重试的情况
           strongSelf->_timer.reset();
62 63 64
            // 播放成功
            *piFailedCnt = 0;//连续播放失败次数清0
            strongSelf->onPlaySuccess();
65
        } else if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
66
            // 播放失败,延时重试播放
67 68 69 70
            strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++);
        } else {
            //达到了最大重试次数,回调关闭
            strongSelf->_on_close(err);
71 72
        }
    });
73
    setOnShutdown([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) {
74
        auto strongSelf = weakSelf.lock();
75
        if (!strongSelf) {
76 77
            return;
        }
78 79 80 81

        //注销直接拉流代理产生的流:#532
        strongSelf->setMediaSource(nullptr);

82
        if (strongSelf->_muxer) {
83
            auto tracks = strongSelf->MediaPlayer::getTracks(false);
84
            for (auto &track : tracks) {
85
                track->delDelegate(strongSelf->_muxer.get());
86
            }
87

88 89
            GET_CONFIG(bool, reset_when_replay, General::kResetWhenRePlay);
            if (reset_when_replay) {
90
                strongSelf->_muxer.reset();
91
            } else {
92
                strongSelf->_muxer->resetTracks();
93 94 95
            }
        }
        //播放异常中断,延时重试播放
96 97 98 99 100
        if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) {
            strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++);
        } else {
            //达到了最大重试次数,回调关闭
            strongSelf->_on_close(err);
101 102 103
        }
    });
    MediaPlayer::play(strUrlTmp);
104
    _pull_url = strUrlTmp;
105 106
    setDirectProxy();
}
107

108
void PlayerProxy::setDirectProxy() {
109
    MediaSource::Ptr mediaSource;
110
    if (dynamic_pointer_cast<RtspPlayer>(_delegate)) {
111
        //rtsp拉流
112 113
        GET_CONFIG(bool, directProxy, Rtsp::kDirectProxy);
        if (directProxy) {
114
            mediaSource = std::make_shared<RtspMediaSource>(_vhost, _app, _stream_id);
115
        }
116
    } else if (dynamic_pointer_cast<RtmpPlayer>(_delegate)) {
117 118
        //rtmp拉流,rtmp强制直接代理
        mediaSource = std::make_shared<RtmpMediaSource>(_vhost, _app, _stream_id);
119
    }
120
    if (mediaSource) {
xiongziliang committed
121
        setMediaSource(mediaSource);
122
    }
xzl committed
123 124 125
}

PlayerProxy::~PlayerProxy() {
126
    _timer.reset();
127 128 129 130 131
    // 避免析构时, 忘记回调api请求
     if(_on_play) {
        _on_play(SockException(Err_shutdown, "player proxy close"));
        _on_play = nullptr;
    }
xzl committed
132
}
133

134 135
void PlayerProxy::rePlay(const string &strUrl, int iFailedCnt) {
    auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60 * 1000));
136
    weak_ptr<PlayerProxy> weakSelf = shared_from_this();
137
    _timer = std::make_shared<Timer>(iDelay / 1000.0f, [weakSelf, strUrl, iFailedCnt]() {
138 139
        //播放失败次数越多,则延时越长
        auto strongPlayer = weakSelf.lock();
140
        if (!strongPlayer) {
141 142
            return false;
        }
143
        WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl;
144
        strongPlayer->MediaPlayer::play(strUrl);
145
        strongPlayer->setDirectProxy();
146 147
        return false;
    }, getPoller());
xzl committed
148
}
149

150
bool PlayerProxy::close(MediaSource &sender) {
151
    //通知其停止推流
152 153 154 155 156 157 158
    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();
xiongziliang committed
159
        strongSelf->setMediaSource(nullptr);
160
        strongSelf->teardown();
161
    });
162
    _on_close(SockException(Err_shutdown, "closed by user"));
163
    WarnL << "close media: " << sender.getUrl();
164 165
    return true;
}
xzl committed
166

167
int PlayerProxy::totalReaderCount() {
168
    return (_muxer ? _muxer->totalReaderCount() : 0) + (_media_src ? _media_src->readerCount() : 0);
169 170 171
}

int PlayerProxy::totalReaderCount(MediaSource &sender) {
172
    return totalReaderCount();
173 174
}

175
MediaOriginType PlayerProxy::getOriginType(MediaSource &sender) const {
176 177 178
    return MediaOriginType::pull;
}

179
string PlayerProxy::getOriginUrl(MediaSource &sender) const {
180 181 182
    return _pull_url;
}

183
std::shared_ptr<SockInfo> PlayerProxy::getOriginSock(MediaSource &sender) const {
184 185 186
    return getSockInfo();
}

187 188 189 190
float PlayerProxy::getLossRate(MediaSource &sender, TrackType type) {
    return getPacketLossRate(type);
}

xiongziliang committed
191
void PlayerProxy::onPlaySuccess() {
192
    GET_CONFIG(bool, reset_when_replay, General::kResetWhenRePlay);
193
    if (dynamic_pointer_cast<RtspMediaSource>(_media_src)) {
194
        //rtsp拉流代理
195 196 197
        if (reset_when_replay || !_muxer) {
            _option.enable_rtsp = false;
            _muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
198
        }
199
    } else if (dynamic_pointer_cast<RtmpMediaSource>(_media_src)) {
200
        //rtmp拉流代理
201 202 203
        if (reset_when_replay || !_muxer) {
            _option.enable_rtmp = false;
            _muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
204 205 206
        }
    } else {
        //其他拉流代理
207 208
        if (reset_when_replay || !_muxer) {
            _muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
209 210
        }
    }
211
    _muxer->setMediaListener(shared_from_this());
xiongziliang committed
212

213 214
    auto videoTrack = getTrack(TrackVideo, false);
    if (videoTrack) {
215
        //添加视频
216
        _muxer->addTrack(videoTrack);
217
        //视频数据写入_mediaMuxer
218
        videoTrack->addDelegate(_muxer);
219
    }
xiongziliang committed
220

221
    auto audioTrack = getTrack(TrackAudio, false);
222
    if (audioTrack) {
223
        //添加音频
224
        _muxer->addTrack(audioTrack);
225
        //音频数据写入_mediaMuxer
226
        audioTrack->addDelegate(_muxer);
227
    }
xiongziliang committed
228

229
    //添加完毕所有track,防止单track情况下最大等待3秒
230
    _muxer->addTrackCompleted();
231

232
    if (_media_src) {
233
        //让_muxer对象拦截一部分事件(比如说录像相关事件)
234
        _media_src->setListener(_muxer);
xiongziliang committed
235
    }
236 237
}

xiongziliang committed
238
} /* namespace mediakit */