mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
Refine: 修复hls播放器丢失首帧关键帧的问题
This commit is contained in:
parent
8f60ec9900
commit
c2b0f3c07b
@ -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);
|
||||||
|
|
||||||
|
bool inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
|
||||||
|
bool addTrack(const Track::Ptr &track) override {
|
||||||
|
return _delegate.addTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlsPlayerImp::setOnPacket(const TSSegment::onSegment &cb){
|
void addTrackCompleted() override {
|
||||||
_on_ts = cb;
|
_delegate.addTrackCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HlsPlayerImp::onPacket(const char *data,size_t len) {
|
void resetTracks() override {
|
||||||
if (_on_ts) {
|
((MediaSink &)_delegate).resetTracks();
|
||||||
_on_ts(data, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_decoder) {
|
vector<Track::Ptr> getTracks(bool ready = true) const override {
|
||||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this);
|
return _delegate.getTracks(ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_decoder) {
|
private:
|
||||||
_decoder->input((uint8_t *) data, len);
|
void onTick();
|
||||||
}
|
int64_t getBufferMS();
|
||||||
}
|
int64_t getPlayPosition();
|
||||||
|
void setPlayPosition(int64_t pos);
|
||||||
|
|
||||||
void HlsPlayerImp::onAllTrackReady() {
|
private:
|
||||||
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(SockException(Err_success,"play hls success"));
|
int64_t _ticker_offset = 0;
|
||||||
}
|
Ticker _ticker;
|
||||||
|
Stamp _stamp[2];
|
||||||
|
Timer::Ptr _timer;
|
||||||
|
MediaSinkDelegate _delegate;
|
||||||
|
multimap<int64_t, Frame::Ptr> _frame_cache;
|
||||||
|
};
|
||||||
|
|
||||||
void HlsPlayerImp::onPlayResult(const SockException &ex) {
|
void HlsDemuxer::start(const EventPoller::Ptr &poller, TrackListener *listener) {
|
||||||
if (ex) {
|
|
||||||
PlayerImp<HlsPlayer, PlayerBase>::onPlayResult(ex);
|
|
||||||
} else {
|
|
||||||
_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
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user