mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-07 04:08:13 +08:00
Demuxer/Player: 修改解复用与播放器底层逻辑,确保触发播放成功回调时不丢帧
This commit is contained in:
@@ -25,7 +25,7 @@ bool RtmpDemuxer::loadMetaData(const AMFValue &val){
|
||||
const AMFValue *videocodecid = nullptr;
|
||||
val.object_for_each([&](const string &key, const AMFValue &val) {
|
||||
if (key == "duration") {
|
||||
_fDuration = (float)val.as_number();
|
||||
_duration = (float)val.as_number();
|
||||
return;
|
||||
}
|
||||
if (key == "audiosamplerate") {
|
||||
@@ -80,6 +80,10 @@ bool RtmpDemuxer::loadMetaData(const AMFValue &val){
|
||||
return ret;
|
||||
}
|
||||
|
||||
float RtmpDemuxer::getDuration() const {
|
||||
return _duration;
|
||||
}
|
||||
|
||||
void RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
|
||||
switch (pkt->type_id) {
|
||||
case MSG_VIDEO: {
|
||||
@@ -111,41 +115,42 @@ void RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
|
||||
|
||||
void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec, int bit_rate) {
|
||||
//生成Track对象
|
||||
_videoTrack = dynamic_pointer_cast<VideoTrack>(Factory::getVideoTrackByAmf(videoCodec));
|
||||
if (_videoTrack) {
|
||||
_videoTrack->setBitRate(bit_rate);
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_video_rtmp_decoder = Factory::getRtmpCodecByTrack(_videoTrack, false);
|
||||
if (_video_rtmp_decoder) {
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_video_rtmp_decoder->addDelegate(_videoTrack);
|
||||
addTrack(_videoTrack);
|
||||
_try_get_video_track = true;
|
||||
} else {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_videoTrack.reset();
|
||||
}
|
||||
_video_track = dynamic_pointer_cast<VideoTrack>(Factory::getVideoTrackByAmf(videoCodec));
|
||||
if (!_video_track) {
|
||||
return;
|
||||
}
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_video_rtmp_decoder = Factory::getRtmpCodecByTrack(_video_track, false);
|
||||
if (!_video_rtmp_decoder) {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_video_track.reset();
|
||||
return;
|
||||
}
|
||||
_video_track->setBitRate(bit_rate);
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_video_rtmp_decoder->addDelegate(_video_track);
|
||||
addTrack(_video_track);
|
||||
_try_get_video_track = true;
|
||||
}
|
||||
|
||||
void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int channels, int sample_bit, int bit_rate) {
|
||||
//生成Track对象
|
||||
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit));
|
||||
if (_audioTrack) {
|
||||
_audioTrack->setBitRate(bit_rate);
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_audio_rtmp_decoder = Factory::getRtmpCodecByTrack(_audioTrack, false);
|
||||
if (_audio_rtmp_decoder) {
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_audio_rtmp_decoder->addDelegate(_audioTrack);
|
||||
addTrack(_audioTrack);
|
||||
_try_get_audio_track = true;
|
||||
} else {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_audioTrack.reset();
|
||||
}
|
||||
_audio_track = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit));
|
||||
if (!_audio_track) {
|
||||
return;
|
||||
}
|
||||
//生成rtmpCodec对象以便解码rtmp
|
||||
_audio_rtmp_decoder = Factory::getRtmpCodecByTrack(_audio_track, false);
|
||||
if (!_audio_rtmp_decoder) {
|
||||
//找不到相应的rtmp解码器,该track无效
|
||||
_audio_track.reset();
|
||||
return;
|
||||
}
|
||||
_audio_track->setBitRate(bit_rate);
|
||||
//设置rtmp解码器代理,生成的frame写入该Track
|
||||
_audio_rtmp_decoder->addDelegate(_audio_track);
|
||||
addTrack(_audio_track);
|
||||
_try_get_audio_track = true;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace mediakit */
|
||||
} /* namespace mediakit */
|
||||
@@ -23,9 +23,9 @@ using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class RtmpDemuxer : public Demuxer{
|
||||
class RtmpDemuxer : public Demuxer {
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpDemuxer> Ptr;
|
||||
using Ptr = std::shared_ptr<RtmpDemuxer>;
|
||||
|
||||
RtmpDemuxer() = default;
|
||||
~RtmpDemuxer() override = default;
|
||||
@@ -38,6 +38,12 @@ public:
|
||||
*/
|
||||
void inputRtmp(const RtmpPacket::Ptr &pkt);
|
||||
|
||||
/**
|
||||
* 获取节目总时长
|
||||
* @return 节目总时长,单位秒
|
||||
*/
|
||||
float getDuration() const;
|
||||
|
||||
private:
|
||||
void makeVideoTrack(const AMFValue &val, int bit_rate);
|
||||
void makeAudioTrack(const AMFValue &val, int sample_rate, int channels, int sample_bit, int bit_rate);
|
||||
@@ -45,6 +51,9 @@ private:
|
||||
private:
|
||||
bool _try_get_video_track = false;
|
||||
bool _try_get_audio_track = false;
|
||||
float _duration = 0;
|
||||
AudioTrack::Ptr _audio_track;
|
||||
VideoTrack::Ptr _video_track;
|
||||
RtmpCodec::Ptr _audio_rtmp_decoder;
|
||||
RtmpCodec::Ptr _video_rtmp_decoder;
|
||||
};
|
||||
|
||||
@@ -24,11 +24,12 @@ using namespace mediakit::Client;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class RtmpPlayerImp: public PlayerImp<RtmpPlayer,RtmpDemuxer> {
|
||||
class RtmpPlayerImp: public PlayerImp<RtmpPlayer,PlayerBase>, private TrackListener {
|
||||
public:
|
||||
typedef std::shared_ptr<RtmpPlayerImp> Ptr;
|
||||
using Ptr = std::shared_ptr<RtmpPlayerImp>;
|
||||
using Super = PlayerImp<RtmpPlayer,PlayerBase>;
|
||||
|
||||
RtmpPlayerImp(const EventPoller::Ptr &poller) : PlayerImp<RtmpPlayer, RtmpDemuxer>(poller) {};
|
||||
RtmpPlayerImp(const EventPoller::Ptr &poller) : Super(poller) {};
|
||||
|
||||
~RtmpPlayerImp() override {
|
||||
DebugL << endl;
|
||||
@@ -50,43 +51,60 @@ public:
|
||||
uint32_t pos = MAX(float(0), MIN(seekPos, getDuration())) * 1000;
|
||||
seekToMilliSecond(pos);
|
||||
}
|
||||
|
||||
void play(const string &strUrl) override {
|
||||
PlayerImp<RtmpPlayer, RtmpDemuxer>::play(strUrl);
|
||||
|
||||
float getDuration() const override {
|
||||
return _demuxer ? _demuxer->getDuration() : 0;
|
||||
}
|
||||
|
||||
vector<Track::Ptr> getTracks(bool ready = true) const override {
|
||||
return _demuxer ? _demuxer->getTracks(ready) : Super::getTracks(ready);
|
||||
}
|
||||
|
||||
private:
|
||||
//派生类回调函数
|
||||
bool onCheckMeta(const AMFValue &val) override {
|
||||
_rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc);
|
||||
if (_rtmp_src) {
|
||||
_rtmp_src->setMetaData(val);
|
||||
_set_meta_data = true;
|
||||
}
|
||||
_delegate.reset(new RtmpDemuxer);
|
||||
_delegate->loadMetaData(val);
|
||||
onCheckMeta_l(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
void onMediaData(RtmpPacket::Ptr chunkData) override {
|
||||
if (!_delegate) {
|
||||
//这个流没有metadata
|
||||
_delegate.reset(new RtmpDemuxer());
|
||||
if (!_demuxer) {
|
||||
//有些rtmp流没metadata
|
||||
onCheckMeta_l(TitleMeta().getMetadata());
|
||||
}
|
||||
_delegate->inputRtmp(chunkData);
|
||||
|
||||
_demuxer->inputRtmp(chunkData);
|
||||
if (_rtmp_src) {
|
||||
if (!_set_meta_data && !chunkData->isCfgFrame()) {
|
||||
_set_meta_data = true;
|
||||
_rtmp_src->setMetaData(TitleMeta().getMetadata());
|
||||
}
|
||||
_rtmp_src->onWrite(std::move(chunkData));
|
||||
}
|
||||
}
|
||||
|
||||
void onPlayResult(const SockException &ex) override {
|
||||
if (ex) {
|
||||
Super::onPlayResult(ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool addTrack(const Track::Ptr &track) override { return true; }
|
||||
|
||||
void addTrackCompleted() override {
|
||||
Super::onPlayResult(SockException(Err_success, "play success"));
|
||||
}
|
||||
|
||||
private:
|
||||
void onCheckMeta_l(const AMFValue &val) {
|
||||
_rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(_media_src);
|
||||
if (_rtmp_src) {
|
||||
_rtmp_src->setMetaData(val);
|
||||
}
|
||||
_demuxer = std::make_shared<RtmpDemuxer>();
|
||||
_demuxer->setTrackListener(this);
|
||||
_demuxer->loadMetaData(val);
|
||||
}
|
||||
|
||||
private:
|
||||
RtmpDemuxer::Ptr _demuxer;
|
||||
RtmpMediaSource::Ptr _rtmp_src;
|
||||
bool _set_meta_data = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user