Refine: 修复hls播放器丢失首帧关键帧的问题

This commit is contained in:
ziyue 2021-12-01 22:09:05 +08:00
parent 8f60ec9900
commit c2b0f3c07b
2 changed files with 109 additions and 71 deletions

View File

@ -238,65 +238,68 @@ void HlsPlayer::onPacket_l(const char *data, size_t len){
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
HlsPlayerImp::HlsPlayerImp(const EventPoller::Ptr &poller) : PlayerImp<HlsPlayer, PlayerBase>(poller) { class HlsDemuxer : public MediaSinkInterface, public TrackSource, public std::enable_shared_from_this<HlsDemuxer> {
public:
HlsDemuxer() = default;
~HlsDemuxer() override { _timer = nullptr; }
} void start(const EventPoller::Ptr &poller, TrackListener *listener);
void HlsPlayerImp::setOnPacket(const TSSegment::onSegment &cb){ bool inputFrame(const Frame::Ptr &frame) override;
_on_ts = cb;
}
void HlsPlayerImp::onPacket(const char *data,size_t len) { bool addTrack(const Track::Ptr &track) override {
if (_on_ts) { return _delegate.addTrack(track);
_on_ts(data, len);
} }
if (!_decoder) { void addTrackCompleted() override {
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this); _delegate.addTrackCompleted();
} }
if (_decoder) { void resetTracks() override {
_decoder->input((uint8_t *) data, len); ((MediaSink &)_delegate).resetTracks();
} }
}
void HlsPlayerImp::onAllTrackReady() { vector<Track::Ptr> getTracks(bool ready = true) const override {
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(SockException(Err_success,"play hls success")); return _delegate.getTracks(ready);
} }
void HlsPlayerImp::onPlayResult(const SockException &ex) { private:
if (ex) { void onTick();
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(ex); int64_t getBufferMS();
} else { int64_t getPlayPosition();
void setPlayPosition(int64_t pos);
private:
int64_t _ticker_offset = 0;
Ticker _ticker;
Stamp _stamp[2];
Timer::Ptr _timer;
MediaSinkDelegate _delegate;
multimap<int64_t, Frame::Ptr> _frame_cache;
};
void HlsDemuxer::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);
_stamp[TrackAudio].syncTo(_stamp[TrackVideo]); _stamp[TrackAudio].syncTo(_stamp[TrackVideo]);
setPlayPosition(0); setPlayPosition(0);
weak_ptr<HlsPlayerImp> weakSelf = dynamic_pointer_cast<HlsPlayerImp>(shared_from_this()); _delegate.setTrackListener(listener);
//每50毫秒执行一次 //每50毫秒执行一次
_timer = std::make_shared<Timer>(0.05f, [weakSelf]() { weak_ptr<HlsDemuxer> weak_self = shared_from_this();
auto strongSelf = weakSelf.lock(); _timer = std::make_shared<Timer>(0.05f, [weak_self]() {
if (!strongSelf) { auto strong_self = weak_self.lock();
if (!strong_self) {
return false; return false;
} }
strongSelf->onTick(); strong_self->onTick();
return true; return true;
}, getPoller()); }, poller);
}
} }
void HlsPlayerImp::onShutdown(const SockException &ex) { bool HlsDemuxer::inputFrame(const Frame::Ptr &frame) {
PlayerImp<HlsPlayer, PlayerBase>::onShutdown(ex);
_timer = nullptr;
}
vector<Track::Ptr> HlsPlayerImp::getTracks(bool trackReady) const {
return MediaSink::getTracks(trackReady);
}
bool HlsPlayerImp::inputFrame(const Frame::Ptr &frame) {
//计算相对时间戳 //计算相对时间戳
int64_t dts, pts; int64_t dts, pts;
_stamp[frame->getTrackType()].revise(frame->dts(), frame->pts(), dts, pts); _stamp[frame->getTrackType()].revise(frame->dts(), frame->pts(), dts, pts);
@ -306,7 +309,7 @@ bool HlsPlayerImp::inputFrame(const Frame::Ptr &frame) {
if (getBufferMS() > 30 * 1000) { if (getBufferMS() > 30 * 1000) {
//缓存超过30秒强制消费至15秒(减少延时或内存占用) //缓存超过30秒强制消费至15秒(减少延时或内存占用)
while (getBufferMS() > 15 * 1000) { while (getBufferMS() > 15 * 1000) {
MediaSink::inputFrame(_frame_cache.begin()->second); _delegate.inputFrame(_frame_cache.begin()->second);
_frame_cache.erase(_frame_cache.begin()); _frame_cache.erase(_frame_cache.begin());
} }
//接着播放缓存中最早的帧 //接着播放缓存中最早的帧
@ -315,23 +318,23 @@ bool HlsPlayerImp::inputFrame(const Frame::Ptr &frame) {
return true; return true;
} }
int64_t HlsPlayerImp::getPlayPosition(){ int64_t HlsDemuxer::getPlayPosition() {
return _ticker.elapsedTime() + _ticker_offset; return _ticker.elapsedTime() + _ticker_offset;
} }
int64_t HlsPlayerImp::getBufferMS(){ int64_t HlsDemuxer::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 HlsPlayerImp::setPlayPosition(int64_t pos){ void HlsDemuxer::setPlayPosition(int64_t pos) {
_ticker.resetTime(); _ticker.resetTime();
_ticker_offset = pos; _ticker_offset = pos;
} }
void HlsPlayerImp::onTick() { void HlsDemuxer::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()) {
@ -346,10 +349,46 @@ void HlsPlayerImp::onTick() {
} }
//消费掉已经到期的帧 //消费掉已经到期的帧
MediaSink::inputFrame(it->second); _delegate.inputFrame(it->second);
it = _frame_cache.erase(it); it = _frame_cache.erase(it);
} }
} }
//////////////////////////////////////////////////////////////////////////
HlsPlayerImp::HlsPlayerImp(const EventPoller::Ptr &poller) : PlayerImp<HlsPlayer, PlayerBase>(poller) {}
void HlsPlayerImp::onPacket(const char *data,size_t len) {
if (!_decoder) {
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _demuxer.get());
}
if (_decoder && _demuxer) {
_decoder->input((uint8_t *) data, len);
}
}
void HlsPlayerImp::addTrackCompleted() {
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(SockException(Err_success, "play hls success"));
}
void HlsPlayerImp::onPlayResult(const SockException &ex) {
if (ex) {
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(ex);
} else {
auto demuxer = std::make_shared<HlsDemuxer>();
demuxer->start(getPoller(), this);
_demuxer = std::move(demuxer);
}
}
void HlsPlayerImp::onShutdown(const SockException &ex) {
PlayerImp<HlsPlayer, PlayerBase>::onShutdown(ex);
_demuxer = nullptr;
}
vector<Track::Ptr> HlsPlayerImp::getTracks(bool ready) const {
return static_pointer_cast<HlsDemuxer>(_demuxer)->getTracks(ready);
}
}//namespace mediakit }//namespace mediakit

View File

@ -22,6 +22,7 @@
#include "Rtp/TSDecoder.h" #include "Rtp/TSDecoder.h"
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
class HlsPlayer : public HttpClientImp , public PlayerBase , public HlsParser{ class HlsPlayer : public HttpClientImp , public PlayerBase , public HlsParser{
@ -123,34 +124,32 @@ private:
TSSegment _segment; TSSegment _segment;
}; };
class HlsPlayerImp : public PlayerImp<HlsPlayer, PlayerBase> , public MediaSink{ class HlsPlayerImp : public PlayerImp<HlsPlayer, PlayerBase>, private TrackListener {
public: public:
typedef std::shared_ptr<HlsPlayerImp> Ptr; typedef std::shared_ptr<HlsPlayerImp> Ptr;
HlsPlayerImp(const EventPoller::Ptr &poller = nullptr); HlsPlayerImp(const EventPoller::Ptr &poller = nullptr);
~HlsPlayerImp() override {}; ~HlsPlayerImp() override {};
void setOnPacket(const TSSegment::onSegment &cb); void setOnPacket(const TSSegment::onSegment &cb);
private: private:
//// HlsPlayer override////
void onPacket(const char *data, size_t len) override; void onPacket(const char *data, size_t len) override;
void onAllTrackReady() override;
void onPlayResult(const SockException &ex) override;
vector<Track::Ptr> getTracks(bool trackReady = true) const override;
bool inputFrame(const Frame::Ptr &frame) override;
void onShutdown(const SockException &ex) override;
void onTick();
int64_t getPlayPosition();
void setPlayPosition(int64_t pos);
int64_t getBufferMS();
private: private:
int64_t _ticker_offset = 0; //// PlayerBase override////
Ticker _ticker; void onPlayResult(const SockException &ex) override;
Stamp _stamp[2]; vector<Track::Ptr> getTracks(bool ready = true) const override;
Timer::Ptr _timer; void onShutdown(const SockException &ex) override;
private:
//// TrackListener override////
bool addTrack(const Track::Ptr &track) override { return true; };
void addTrackCompleted() override;
private:
DecoderImp::Ptr _decoder; DecoderImp::Ptr _decoder;
TSSegment::onSegment _on_ts; MediaSinkInterface::Ptr _demuxer;
multimap<int64_t, Frame::Ptr> _frame_cache;
}; };
}//namespace mediakit }//namespace mediakit