Commit 7b04385b by xiongziliang

合并http-ts播放器特性: #1336

parent a4c69e61
...@@ -51,7 +51,7 @@ void HttpTSPlayer::onResponseBody(const char *buf, size_t size, size_t recved_si ...@@ -51,7 +51,7 @@ void HttpTSPlayer::onResponseBody(const char *buf, size_t size, size_t recved_si
if (_split_ts) { if (_split_ts) {
try { try {
_segment.input(buf, size); _segment.input(buf, size);
}catch (std::exception &ex) { } catch (std::exception &ex) {
WarnL << ex.what(); WarnL << ex.what();
//ts解析失败,清空缓存数据 //ts解析失败,清空缓存数据
_segment.reset(); _segment.reset();
......
// /*
// Created by alex on 2021/4/6. * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved.
// * Created by alex on 2021/4/6.
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* 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.
*/
#include "TsPlayer.h" #include "TsPlayer.h"
namespace mediakit { namespace mediakit {
TsPlayer::TsPlayer(const EventPoller::Ptr &poller):HttpTSPlayer(poller, true) {} TsPlayer::TsPlayer(const EventPoller::Ptr &poller) : HttpTSPlayer(poller, true) {}
TsPlayer::~TsPlayer() {} void TsPlayer::play(const string &strUrl) {
void TsPlayer::play(const string &strUrl) {
_ts_url.append(strUrl); _ts_url.append(strUrl);
playTs(); playTs();
} }
void TsPlayer::teardown_l(const SockException &ex) { void TsPlayer::teardown_l(const SockException &ex) {
HttpClient::clear(); HttpClient::clear();
shutdown(ex); shutdown(ex);
} }
void TsPlayer::teardown() { void TsPlayer::teardown() {
teardown_l(SockException(Err_shutdown, "teardown")); teardown_l(SockException(Err_shutdown, "teardown"));
} }
void TsPlayer::playTs() { void TsPlayer::playTs() {
if (waitResponse()) { if (waitResponse()) {
//播放器目前还存活,正在下载中 //播放器目前还存活,正在下载中
return; return;
} }
WarnL << "fetch:" << _ts_url; WarnL << "fetch:" << _ts_url;
_request_complete = false; _request_complete = false;
weak_ptr<TsPlayer> weak_self = dynamic_pointer_cast<TsPlayer>(shared_from_this()); weak_ptr <TsPlayer> weak_self = dynamic_pointer_cast<TsPlayer>(shared_from_this());
setMethod("GET"); setMethod("GET");
sendRequest(_ts_url, 3600 * 2, 60); sendRequest(_ts_url, 3600 * 2, 60);
} }
void TsPlayer::onResponseCompleted() { void TsPlayer::onResponseCompleted() {
//接收完毕 //接收完毕
teardown_l(SockException(Err_success, StrPrinter << _ts_url << ": play completed")); teardown_l(SockException(Err_success, StrPrinter << _ts_url << ": play completed"));
} }
void TsPlayer::onDisconnect(const SockException &ex) { void TsPlayer::onDisconnect(const SockException &ex) {
WarnL << _ts_url << " :" << ex.getErrCode() << " " << ex.what(); WarnL << _ts_url << " :" << ex.getErrCode() << " " << ex.what();
if (_first) { if (_first) {
//第一次失败,则播放失败 //第一次失败,则播放失败
...@@ -51,18 +55,19 @@ namespace mediakit { ...@@ -51,18 +55,19 @@ namespace mediakit {
} }
if (ex.getErrCode() == Err_shutdown) { if (ex.getErrCode() == Err_shutdown) {
onShutdown(ex); onShutdown(ex);
}else{ } else {
onResponseCompleted(); onResponseCompleted();
onShutdown(ex); onShutdown(ex);
} }
} }
ssize_t TsPlayer::onResponseHeader(const string &status, const HttpClient::HttpHeader &header) { ssize_t TsPlayer::onResponseHeader(const string &status, const HttpClient::HttpHeader &header) {
ssize_t ret = HttpTSPlayer::onResponseHeader(status, header); ssize_t ret = HttpTSPlayer::onResponseHeader(status, header);
if (_first) { if (_first) {
_first = false; _first = false;
onPlayResult(SockException(Err_success, "play success")); onPlayResult(SockException(Err_success, "play success"));
} }
return ret; return ret;
} }
}//namespace mediakit }//namespace mediakit
\ No newline at end of file
//
// Created by alex on 2021/4/6.
//
/* /*
* Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved. * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved.
* * Created by alex on 2021/4/6.
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
* *
* Use of this source code is governed by MIT license that can be found in the * Use of this source code is governed by MIT license that can be found in the
...@@ -24,37 +20,37 @@ ...@@ -24,37 +20,37 @@
#include "Rtp/TSDecoder.h" #include "Rtp/TSDecoder.h"
#include "HttpTSPlayer.h" #include "HttpTSPlayer.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
class TsPlayer : public HttpTSPlayer , public PlayerBase { class TsPlayer : public HttpTSPlayer, public PlayerBase {
public: public:
TsPlayer(const EventPoller::Ptr &poller); TsPlayer(const EventPoller::Ptr &poller);
~TsPlayer() override; ~TsPlayer() override = default;
/** /**
* 开始播放 * 开始播放
* @param strUrl
*/ */
void play(const string &strUrl) override; void play(const string &url) override;
/** /**
* 停止播放 * 停止播放
*/ */
void teardown() override; void teardown() override;
private:
private:
void playTs(); void playTs();
void teardown_l(const SockException &ex); void teardown_l(const SockException &ex);
protected: protected:
virtual void onResponseCompleted() override; virtual void onResponseCompleted() override;
virtual void onDisconnect(const SockException &ex) override; virtual void onDisconnect(const SockException &ex) override;
virtual ssize_t onResponseHeader(const string &status, const HttpHeader &header) override; virtual ssize_t onResponseHeader(const string &status, const HttpHeader &header) override;
private:
private:
bool _first = true; bool _first = true;
string _ts_url; string _ts_url;
}; };
}//namespace mediakit }//namespace mediakit
#endif //HTTP_TSPLAYER_H #endif //HTTP_TSPLAYER_H
// /*
// Created by alex on 2021/7/5. * Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved.
// * Created by alex on 2021/4/6.
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* 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.
*/
#ifndef HTTP_TSPLAYERIMP_H #ifndef HTTP_TSPLAYERIMP_H
#define HTTP_TSPLAYERIMP_H #define HTTP_TSPLAYERIMP_H
...@@ -15,12 +21,12 @@ ...@@ -15,12 +21,12 @@
#include "TsPlayer.h" #include "TsPlayer.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
class TsDemuxer : public MediaSinkInterface, public TrackSource, public std::enable_shared_from_this<TsDemuxer> { class TsDemuxer : public MediaSinkInterface, public TrackSource, public std::enable_shared_from_this<TsDemuxer> {
public: public:
TsDemuxer() = default; TsDemuxer() = default;
~TsDemuxer() override { _timer = nullptr; } ~TsDemuxer() override { _timer = nullptr; }
void start(const EventPoller::Ptr &poller, TrackListener *listener); void start(const EventPoller::Ptr &poller, TrackListener *listener);
...@@ -43,54 +49,47 @@ namespace mediakit { ...@@ -43,54 +49,47 @@ namespace mediakit {
return _delegate.getTracks(ready); return _delegate.getTracks(ready);
} }
private: private:
void onTick(); void onTick();
int64_t getBufferMS(); int64_t getBufferMS();
int64_t getPlayPosition(); int64_t getPlayPosition();
void setPlayPosition(int64_t pos); void setPlayPosition(int64_t pos);
private: private:
int64_t _ticker_offset = 0; int64_t _ticker_offset = 0;
Ticker _ticker; Ticker _ticker;
Stamp _stamp[2]; Stamp _stamp[2];
Timer::Ptr _timer; Timer::Ptr _timer;
MediaSinkDelegate _delegate; MediaSinkDelegate _delegate;
multimap<int64_t, Frame::Ptr> _frame_cache; multimap<int64_t, Frame::Ptr> _frame_cache;
}; };
class TsPlayerImp : public PlayerImp<TsPlayer, PlayerBase>, private TrackListener { class TsPlayerImp : public PlayerImp<TsPlayer, PlayerBase>, private TrackListener {
public: public:
typedef std::shared_ptr<TsPlayerImp> Ptr; using Ptr = std::shared_ptr<TsPlayerImp>;
TsPlayerImp(const EventPoller::Ptr &poller = nullptr); TsPlayerImp(const EventPoller::Ptr &poller = nullptr);
~TsPlayerImp() override = default; ~TsPlayerImp() override = default;
private: private:
//// HlsPlayer override//// //// HlsPlayer override////
void onPacket(const char *data, size_t len) override; void onPacket(const char *data, size_t len) override;
private: private:
//// PlayerBase override//// //// PlayerBase override////
void onPlayResult(const SockException &ex) override; void onPlayResult(const SockException &ex) override;
vector<Track::Ptr> getTracks(bool ready = true) const override; vector<Track::Ptr> getTracks(bool ready = true) const override;
void onShutdown(const SockException &ex) override; void onShutdown(const SockException &ex) override;
private: private:
//// TrackListener override//// //// TrackListener override////
bool addTrack(const Track::Ptr &track) override { return true; }; bool addTrack(const Track::Ptr &track) override { return true; };
void addTrackCompleted() override; void addTrackCompleted() override;
private: private:
DecoderImp::Ptr _decoder; DecoderImp::Ptr _decoder;
MediaSinkInterface::Ptr _demuxer; MediaSinkInterface::Ptr _demuxer;
}; };
}//namespace mediakit }//namespace mediakit
#endif //HTTP_TSPLAYERIMP_H #endif //HTTP_TSPLAYERIMP_H
/*
* Copyright (c) 2020 The ZLMediaKit project authors. All Rights Reserved.
* Created by alex on 2021/4/6.
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
*
* 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.
*/
#include "TsPlayerImp.h" #include "TsPlayerImp.h"
namespace mediakit { namespace mediakit {
void TsDemuxer::start(const EventPoller::Ptr &poller, TrackListener *listener) {
void TsDemuxer::start(const EventPoller::Ptr &poller, TrackListener *listener) {
_frame_cache.clear(); _frame_cache.clear();
_stamp[TrackAudio].setRelativeStamp(0); _stamp[TrackAudio].setRelativeStamp(0);
_stamp[TrackVideo].setRelativeStamp(0); _stamp[TrackVideo].setRelativeStamp(0);
...@@ -11,7 +22,7 @@ namespace mediakit { ...@@ -11,7 +22,7 @@ namespace mediakit {
_delegate.setTrackListener(listener); _delegate.setTrackListener(listener);
//每50毫秒执行一次 //每50毫秒执行一次
weak_ptr<TsDemuxer> weak_self = shared_from_this(); weak_ptr <TsDemuxer> weak_self = shared_from_this();
_timer = std::make_shared<Timer>(0.05f, [weak_self]() { _timer = std::make_shared<Timer>(0.05f, [weak_self]() {
auto strong_self = weak_self.lock(); auto strong_self = weak_self.lock();
if (!strong_self) { if (!strong_self) {
...@@ -20,9 +31,9 @@ namespace mediakit { ...@@ -20,9 +31,9 @@ namespace mediakit {
strong_self->onTick(); strong_self->onTick();
return true; return true;
}, poller); }, poller);
} }
bool TsDemuxer::inputFrame(const Frame::Ptr &frame) { bool TsDemuxer::inputFrame(const Frame::Ptr &frame) {
//为了避免track准备时间过长, 因此在没准备好之前, 直接消费掉所有的帧 //为了避免track准备时间过长, 因此在没准备好之前, 直接消费掉所有的帧
if (!_delegate.isAllTrackReady()) { if (!_delegate.isAllTrackReady()) {
_delegate.inputFrame(frame); _delegate.inputFrame(frame);
...@@ -33,8 +44,6 @@ namespace mediakit { ...@@ -33,8 +44,6 @@ namespace mediakit {
//根据时间戳缓存frame //根据时间戳缓存frame
_stamp[frame->getTrackType()].revise(frame->dts(), frame->pts(), dts, pts); _stamp[frame->getTrackType()].revise(frame->dts(), frame->pts(), dts, pts);
_frame_cache.emplace(dts, Frame::getCacheAbleFrame(frame)); _frame_cache.emplace(dts, Frame::getCacheAbleFrame(frame));
//根据时间戳缓存frame
// _frame_cache.emplace(dts, Frame::getCacheAbleFrame(frame));
if (getBufferMS() > 30 * 1000) { if (getBufferMS() > 30 * 1000) {
//缓存超过30秒,强制消费至15秒(减少延时或内存占用) //缓存超过30秒,强制消费至15秒(减少延时或内存占用)
...@@ -46,25 +55,25 @@ namespace mediakit { ...@@ -46,25 +55,25 @@ namespace mediakit {
setPlayPosition(_frame_cache.begin()->first); setPlayPosition(_frame_cache.begin()->first);
} }
return true; return true;
} }
int64_t TsDemuxer::getPlayPosition() { int64_t TsDemuxer::getPlayPosition() {
return _ticker.elapsedTime() + _ticker_offset; return _ticker.elapsedTime() + _ticker_offset;
} }
int64_t TsDemuxer::getBufferMS() { int64_t TsDemuxer::getBufferMS() {
if (_frame_cache.empty()) { if (_frame_cache.empty()) {
return 0; return 0;
} }
return _frame_cache.rbegin()->first - _frame_cache.begin()->first; return _frame_cache.rbegin()->first - _frame_cache.begin()->first;
} }
void TsDemuxer::setPlayPosition(int64_t pos) { void TsDemuxer::setPlayPosition(int64_t pos) {
_ticker.resetTime(); _ticker.resetTime();
_ticker_offset = pos; _ticker_offset = pos;
} }
void TsDemuxer::onTick() { void TsDemuxer::onTick() {
auto it = _frame_cache.begin(); auto it = _frame_cache.begin();
while (it != _frame_cache.end()) { while (it != _frame_cache.end()) {
if (it->first > getPlayPosition()) { if (it->first > getPlayPosition()) {
...@@ -80,13 +89,13 @@ namespace mediakit { ...@@ -80,13 +89,13 @@ namespace mediakit {
_delegate.inputFrame(it->second); _delegate.inputFrame(it->second);
it = _frame_cache.erase(it); it = _frame_cache.erase(it);
} }
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
TsPlayerImp::TsPlayerImp(const EventPoller::Ptr &poller) : PlayerImp<TsPlayer, PlayerBase>(poller) {} TsPlayerImp::TsPlayerImp(const EventPoller::Ptr &poller) : PlayerImp<TsPlayer, PlayerBase>(poller) {}
void TsPlayerImp::onPacket(const char *data, size_t len) { void TsPlayerImp::onPacket(const char *data, size_t len) {
if (!_decoder) { if (!_decoder) {
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _demuxer.get()); _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _demuxer.get());
} }
...@@ -94,13 +103,13 @@ namespace mediakit { ...@@ -94,13 +103,13 @@ namespace mediakit {
if (_decoder && _demuxer) { if (_decoder && _demuxer) {
_decoder->input((uint8_t *) data, len); _decoder->input((uint8_t *) data, len);
} }
} }
void TsPlayerImp::addTrackCompleted() { void TsPlayerImp::addTrackCompleted() {
PlayerImp<TsPlayer, PlayerBase>::onPlayResult(SockException(Err_success, "play hls success")); PlayerImp<TsPlayer, PlayerBase>::onPlayResult(SockException(Err_success, "play hls success"));
} }
void TsPlayerImp::onPlayResult(const SockException &ex) { void TsPlayerImp::onPlayResult(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what(); WarnL << ex.getErrCode() << " " << ex.what();
if (ex) { if (ex) {
PlayerImp<TsPlayer, PlayerBase>::onPlayResult(ex); PlayerImp<TsPlayer, PlayerBase>::onPlayResult(ex);
...@@ -109,15 +118,15 @@ namespace mediakit { ...@@ -109,15 +118,15 @@ namespace mediakit {
demuxer->start(getPoller(), this); demuxer->start(getPoller(), this);
_demuxer = std::move(demuxer); _demuxer = std::move(demuxer);
} }
} }
void TsPlayerImp::onShutdown(const SockException &ex) { void TsPlayerImp::onShutdown(const SockException &ex) {
PlayerImp<TsPlayer, PlayerBase>::onShutdown(ex); PlayerImp<TsPlayer, PlayerBase>::onShutdown(ex);
_demuxer = nullptr; _demuxer = nullptr;
} }
vector<Track::Ptr> TsPlayerImp::getTracks(bool ready) const { vector <Track::Ptr> TsPlayerImp::getTracks(bool ready) const {
return static_pointer_cast<TsDemuxer>(_demuxer)->getTracks(ready); return static_pointer_cast<TsDemuxer>(_demuxer)->getTracks(ready);
} }
}//namespace mediakit }//namespace mediakit
\ No newline at end of file
...@@ -48,14 +48,13 @@ PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller, const s ...@@ -48,14 +48,13 @@ PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller, const s
if (strcasecmp("rtmp", prefix.data()) == 0) { if (strcasecmp("rtmp", prefix.data()) == 0) {
return PlayerBase::Ptr(new RtmpPlayerImp(poller), releasePlayer); return PlayerBase::Ptr(new RtmpPlayerImp(poller), releasePlayer);
} }
if ((strcasecmp("http",prefix.data()) == 0 || strcasecmp("https",prefix.data()) == 0)) { if ((strcasecmp("http", prefix.data()) == 0 || strcasecmp("https", prefix.data()) == 0)) {
if (end_with(url, ".m3u8") || end_with(url_in, ".m3u8")) { if (end_with(url, ".m3u8") || end_with(url_in, ".m3u8")) {
return PlayerBase::Ptr(new HlsPlayerImp(poller),releasePlayer); return PlayerBase::Ptr(new HlsPlayerImp(poller), releasePlayer);
} else if (end_with(url, ".ts") || end_with(url_in, ".ts")) {
return PlayerBase::Ptr(new TsPlayerImp(poller), releasePlayer);
} }
else if (end_with(url, ".ts") || end_with(url_in, ".ts")) { return PlayerBase::Ptr(new TsPlayerImp(poller), releasePlayer);
return PlayerBase::Ptr(new TsPlayerImp(poller),releasePlayer);
}
return PlayerBase::Ptr(new TsPlayerImp(poller),releasePlayer);
} }
return PlayerBase::Ptr(new RtspPlayerImp(poller), releasePlayer); return PlayerBase::Ptr(new RtspPlayerImp(poller), releasePlayer);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论