Demuxer/Player: 修改解复用与播放器底层逻辑,确保触发播放成功回调时不丢帧

This commit is contained in:
ziyue
2021-11-10 10:58:43 +08:00
parent 37fdb8d135
commit fdfde17ec7
14 changed files with 391 additions and 421 deletions

View File

@@ -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 */

View File

@@ -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;
};

View File

@@ -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;
};