diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index 4f4f4a1b..ca0cf734 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -181,7 +181,7 @@ void MediaSink::emitAllTrackReady() { void MediaSink::onAllTrackReady_l() { //是否添加静音音频 GET_CONFIG(bool, addMuteAudio, General::kAddMuteAudio); - if (addMuteAudio && !_track_map[TrackAudio]) { + if (addMuteAudio && _track_map.find(TrackAudio) == _track_map.end()) { addMuteAudioTrack(); } onAllTrackReady(); @@ -253,11 +253,12 @@ bool MuteAudioMaker::inputFrame(const Frame::Ptr &frame) { } bool MediaSink::addMuteAudioTrack() { - if (getTrack(TrackAudio, false)) { + if (_track_map.find(TrackAudio) != _track_map.end()) { WarnL << "audio track already existed"; return false; } - if (addTrack(std::make_shared())) { + + if (MediaSink::addTrack(std::make_shared(makeAacConfig(MUTE_ADTS_DATA, ADTS_HEADER_LEN)))) { _mute_audio_maker = std::make_shared(); _mute_audio_maker->addDelegate(std::make_shared([this](const Frame::Ptr &frame) { return inputFrame(frame); diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 964ca497..dab61670 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -305,7 +305,6 @@ const string kRtspPwdIsMD5 = "rtsp_pwd_md5"; const string kTimeoutMS = "protocol_timeout_ms"; const string kMediaTimeoutMS = "media_timeout_ms"; const string kBeatIntervalMS = "beat_interval_ms"; -const string kMaxAnalysisMS = "max_analysis_ms"; const string kBenchmarkMode = "benchmark_mode"; } diff --git a/src/Common/config.h b/src/Common/config.h index b8def890..dbf193c4 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -329,8 +329,6 @@ extern const string kTimeoutMS; extern const string kMediaTimeoutMS; //rtsp/rtmp心跳时间,默认5000毫秒 extern const string kBeatIntervalMS; -//Track编码格式探测最大时间,单位毫秒,默认2000 -extern const string kMaxAnalysisMS; //是否为性能测试模式,性能测试模式开启后不会解析rtp或rtmp包 extern const string kBenchmarkMode; } diff --git a/src/Player/MediaPlayer.cpp b/src/Player/MediaPlayer.cpp index 9d8be6c1..8d564bef 100644 --- a/src/Player/MediaPlayer.cpp +++ b/src/Player/MediaPlayer.cpp @@ -20,9 +20,6 @@ MediaPlayer::MediaPlayer(const EventPoller::Ptr &poller) { _poller = poller ? poller : EventPollerPool::Instance().getPoller(); } -MediaPlayer::~MediaPlayer() { -} - static void setOnCreateSocket_l(const std::shared_ptr &delegate, const Socket::onCreateSocket &cb){ auto helper = dynamic_pointer_cast(delegate); if (helper) { @@ -41,10 +38,10 @@ void MediaPlayer::play(const string &url) { _delegate = PlayerBase::createPlayer(_poller, url); assert(_delegate); setOnCreateSocket_l(_delegate, _on_create_socket); - _delegate->setOnShutdown(_shutdownCB); - _delegate->setOnPlayResult(_playResultCB); - _delegate->setOnResume(_resumeCB); - _delegate->setMediaSource(_pMediaSrc); + _delegate->setOnShutdown(_on_shutdown); + _delegate->setOnPlayResult(_on_play_result); + _delegate->setOnResume(_on_resume); + _delegate->setMediaSource(_media_src); _delegate->mINI::operator=(*this); _delegate->play(url); } @@ -58,23 +55,4 @@ void MediaPlayer::setOnCreateSocket(Socket::onCreateSocket cb){ _on_create_socket = std::move(cb); } -void MediaPlayer::pause(bool pause) { - if (_delegate) { - _delegate->pause(pause); - } -} - -void MediaPlayer::speed(float speed) { - if (_delegate) { - _delegate->speed(speed); - } -} - -void MediaPlayer::teardown() { - if (_delegate) { - _delegate->teardown(); - } -} - - } /* namespace mediakit */ diff --git a/src/Player/MediaPlayer.h b/src/Player/MediaPlayer.h index a65f6b9a..47dae5e9 100644 --- a/src/Player/MediaPlayer.h +++ b/src/Player/MediaPlayer.h @@ -21,16 +21,14 @@ using namespace toolkit; namespace mediakit { -class MediaPlayer : public PlayerImp { +class MediaPlayer : public PlayerImp { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; MediaPlayer(const EventPoller::Ptr &poller = nullptr); - virtual ~MediaPlayer(); + ~MediaPlayer() override = default; + void play(const string &url) override; - void pause(bool pause) override; - void speed(float speed) override; - void teardown() override; EventPoller::Ptr getPoller(); void setOnCreateSocket(Socket::onCreateSocket cb); diff --git a/src/Player/PlayerBase.cpp b/src/Player/PlayerBase.cpp index bb6c31eb..1ee52c98 100644 --- a/src/Player/PlayerBase.cpp +++ b/src/Player/PlayerBase.cpp @@ -13,14 +13,15 @@ #include "Rtsp/RtspPlayerImp.h" #include "Rtmp/RtmpPlayerImp.h" #include "Http/HlsPlayer.h" + using namespace toolkit; namespace mediakit { -PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &url_in) { - static auto releasePlayer = [](PlayerBase *ptr){ - onceToken token(nullptr,[&](){ - delete ptr; +PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller, const string &url_in) { + static auto releasePlayer = [](PlayerBase *ptr) { + onceToken token(nullptr, [&]() { + delete ptr; }); ptr->teardown(); }; @@ -32,98 +33,91 @@ PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const st url = url.substr(0, pos); } - if (strcasecmp("rtsps",prefix.data()) == 0) { - return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); + if (strcasecmp("rtsps", prefix.data()) == 0) { + return PlayerBase::Ptr(new TcpClientWithSSL(poller), releasePlayer); } - if (strcasecmp("rtsp",prefix.data()) == 0) { - return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); + if (strcasecmp("rtsp", prefix.data()) == 0) { + return PlayerBase::Ptr(new RtspPlayerImp(poller), releasePlayer); } - if (strcasecmp("rtmps",prefix.data()) == 0) { - return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); + if (strcasecmp("rtmps", prefix.data()) == 0) { + return PlayerBase::Ptr(new TcpClientWithSSL(poller), releasePlayer); } - if (strcasecmp("rtmp",prefix.data()) == 0) { - return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer); + if (strcasecmp("rtmp", prefix.data()) == 0) { + return PlayerBase::Ptr(new RtmpPlayerImp(poller), releasePlayer); } - if ((strcasecmp("http",prefix.data()) == 0 || strcasecmp("https",prefix.data()) == 0) && end_with(url, ".m3u8")) { - return PlayerBase::Ptr(new HlsPlayerImp(poller),releasePlayer); + if ((strcasecmp("http", prefix.data()) == 0 || strcasecmp("https", prefix.data()) == 0) && end_with(url, ".m3u8")) { + return PlayerBase::Ptr(new HlsPlayerImp(poller), releasePlayer); } - return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); + return PlayerBase::Ptr(new RtspPlayerImp(poller), releasePlayer); } PlayerBase::PlayerBase() { this->mINI::operator[](kTimeoutMS) = 10000; this->mINI::operator[](kMediaTimeoutMS) = 5000; this->mINI::operator[](kBeatIntervalMS) = 5000; - this->mINI::operator[](kMaxAnalysisMS) = 5000; } ///////////////////////////Demuxer////////////////////////////// -bool Demuxer::isInited(int analysisMs) { - if(analysisMs && _ticker.createdTime() > (uint64_t)analysisMs){ - //analysisMs毫秒后强制初始化完毕 - return true; - } - if (_videoTrack && !_videoTrack->ready()) { - //视频未准备好 - return false; - } - if (_audioTrack && !_audioTrack->ready()) { - //音频未准备好 - return false; - } - return true; -} -vector Demuxer::getTracks(bool trackReady) const { - vector ret; - if(_videoTrack){ - if(trackReady){ - if(_videoTrack->ready()){ - ret.emplace_back(_videoTrack); - } - }else{ - ret.emplace_back(_videoTrack); - } - } - if(_audioTrack){ - if(trackReady){ - if(_audioTrack->ready()){ - ret.emplace_back(_audioTrack); - } - }else{ - ret.emplace_back(_audioTrack); - } +bool Demuxer::addTrack(const Track::Ptr &track) { + auto ret = MediaSink::addTrack(track); + if (ret) { + track->addDelegate(std::make_shared([this](const Frame::Ptr &frame) { + return inputFrame(frame); + })); } return ret; } -float Demuxer::getDuration() const { - return _fDuration; -} - -bool Demuxer::addTrack(const Track::Ptr &track){ - return _listener ? _listener->addTrack(track) : false; -} - -void Demuxer::addTrackCompleted(){ - if(_listener){ - _listener->addTrackCompleted(); - } -} - -void Demuxer::resetTracks() { - if (_listener) { - _listener->resetTracks(); - } -} - void Demuxer::setTrackListener(TrackListener *listener) { _listener = listener; } +bool Demuxer::onTrackReady(const Track::Ptr &track) { + _tracks[track->getTrackType()] = track->clone(); + return true; +} + +void Demuxer::onAllTrackReady() { + if (!_listener) { + return; + } + for (auto &track : _tracks) { + if (track) { + _listener->addTrack(track); + } + } + _listener->addTrackCompleted(); +} + +bool Demuxer::onTrackFrame(const Frame::Ptr &frame) { + return _tracks[frame->getTrackType()]->inputFrame(frame); +} + +void Demuxer::resetTracks() { + MediaSink::resetTracks(); + for (auto &track : _tracks) { + track = nullptr; + } + if (_listener) { + _listener->resetTracks(); + } +} + +vector Demuxer::getTracks(bool ready) const { + vector ret; + for (auto &track : _tracks) { + if (!track || (ready && !track->ready())) { + continue; + } + ret.emplace_back(track); + } + return ret; +} + } /* namespace mediakit */ diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 8d277614..8877f2f2 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -22,292 +22,242 @@ #include "Common/MediaSink.h" #include "Extension/Frame.h" #include "Extension/Track.h" + using namespace toolkit; namespace mediakit { -class DemuxerBase : public TrackSource{ +class PlayerBase : public TrackSource, public mINI { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; + using Event = std::function; - /** - * 获取节目总时长,单位秒 - * @return - */ - virtual float getDuration() const { return 0;} - - /** - * 是否初始化完毕,完毕后方可调用getTrack方法 - * @param analysisMs 数据流最大分析时间 单位毫秒 - * @return - */ - virtual bool isInited(int analysisMs) { return true; } -}; - - -class PlayerBase : public DemuxerBase, public mINI{ -public: - typedef std::shared_ptr Ptr; - static Ptr createPlayer(const EventPoller::Ptr &poller,const string &strUrl); + static Ptr createPlayer(const EventPoller::Ptr &poller, const string &strUrl); PlayerBase(); - virtual ~PlayerBase(){} + ~PlayerBase() override = default; /** * 开始播放 - * @param strUrl 视频url,支持rtsp/rtmp + * @param url 视频url,支持rtsp/rtmp */ - virtual void play(const string &strUrl) {} + virtual void play(const string &url) {}; /** * 暂停或恢复 - * @param bPause + * @param flag true:暂停,false:恢复 */ - virtual void pause(bool bPause) {} + virtual void pause(bool flag) {}; + + /** + * 获取节目总时长,单位秒 + */ + virtual float getDuration() const { return 0; }; /** * 倍数播放 * @param speed 1.0 2.0 0.5 */ - virtual void speed(float speed) {} + virtual void speed(float speed) {}; /** * 中断播放 */ - virtual void teardown() {} - - /** - * 设置异常中断回调 - * @param cb - */ - virtual void setOnShutdown( const function &cb) {} - - /** - * 设置播放结果回调 - * @param cb - */ - virtual void setOnPlayResult( const function &cb) {} - - /** - * 设置播放恢复回调 - * @param cb - */ - virtual void setOnResume( const function &cb) {} + virtual void teardown() {}; /** * 获取播放进度,取值 0.0 ~ 1.0 - * @return */ - virtual float getProgress() const { return 0;} + virtual float getProgress() const { return 0; }; /** * 获取播放进度pos,取值 相对开始时间增量 单位秒 - * @return */ - virtual uint32_t getProgressPos() const { return 0; } + virtual uint32_t getProgressPos() const { return 0; }; /** * 拖动进度条 - * @param fProgress 进度,取值 0.0 ~ 1.0 + * @param progress 进度,取值 0.0 ~ 1.0 */ - virtual void seekTo(float fProgress) {} + virtual void seekTo(float progress) {}; /** * 拖动进度条 - * @param seekPos 进度,取值 相对于开始时间的增量 单位秒 + * @param pos 进度,取值 相对于开始时间的增量 单位秒 */ - virtual void seekTo(uint32_t seekPos) {} - - /** - * 设置一个MediaSource,直接生产rtsp/rtmp代理 - * @param src - */ - virtual void setMediaSource(const MediaSource::Ptr & src) {} + virtual void seekTo(uint32_t pos) {}; /** * 获取丢包率,只支持rtsp - * @param trackType 音频或视频,TrackInvalid时为总丢包率 - * @return + * @param type 音频或视频,TrackInvalid时为总丢包率 */ - virtual float getPacketLossRate(TrackType trackType) const {return 0; } + virtual float getPacketLossRate(TrackType type) const { return 0; }; /** * 获取所有track */ - vector getTracks(bool trackReady = true) const override{ - return vector(); - } -protected: - virtual void onShutdown(const SockException &ex) {} - virtual void onPlayResult(const SockException &ex) {} + vector getTracks(bool ready = true) const override { return vector(); }; + /** - * 暂停后恢复播放时间 + * 设置一个MediaSource,直接生产rtsp/rtmp代理 */ - virtual void onResume(){}; + virtual void setMediaSource(const MediaSource::Ptr &src) = 0; + + /** + * 设置异常中断回调 + */ + virtual void setOnShutdown(const Event &cb) = 0; + + /** + * 设置播放结果回调 + */ + virtual void setOnPlayResult(const Event &cb) = 0; + + /** + * 设置播放恢复回调 + */ + virtual void setOnResume(const function &cb) = 0; + +protected: + virtual void onResume() = 0; + virtual void onShutdown(const SockException &ex) = 0; + virtual void onPlayResult(const SockException &ex) = 0; }; -template +template class PlayerImp : public Parent { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; template - PlayerImp(ArgsType &&...args):Parent(std::forward(args)...) {} - virtual ~PlayerImp() {} + PlayerImp(ArgsType &&...args) : Parent(std::forward(args)...) {} + ~PlayerImp() override = default; - void setOnShutdown(const function &cb) override { - if (_delegate) { - _delegate->setOnShutdown(cb); - } - _shutdownCB = cb; + void play(const string &url) override { + return _delegate ? _delegate->play(url) : Parent::play(url); } - void setOnPlayResult(const function &cb) override { - if (_delegate) { - _delegate->setOnPlayResult(cb); - } - _playResultCB = cb; + void pause(bool flag) override { + return _delegate ? _delegate->pause(flag) : Parent::pause(flag); } - void setOnResume(const function &cb) override { - if (_delegate) { - _delegate->setOnResume(cb); - } - _resumeCB = cb; + void speed(float speed) override { + return _delegate ? _delegate->speed(speed) : Parent::speed(speed); } - bool isInited(int analysisMs) override { - if (_delegate) { - return _delegate->isInited(analysisMs); - } - return Parent::isInited(analysisMs); + void teardown() override { + return _delegate ? _delegate->teardown() : Parent::teardown(); + } + + float getPacketLossRate(TrackType type) const override { + return _delegate ? _delegate->getPacketLossRate(type) : Parent::getPacketLossRate(type); } float getDuration() const override { - if (_delegate) { - return _delegate->getDuration(); - } - return Parent::getDuration(); + return _delegate ? _delegate->getDuration() : Parent::getDuration(); } float getProgress() const override { - if (_delegate) { - return _delegate->getProgress(); - } - return Parent::getProgress(); + return _delegate ? _delegate->getProgress() : Parent::getProgress(); } uint32_t getProgressPos() const override { - if (_delegate) { - return _delegate->getProgressPos(); - } - return Parent::getProgressPos(); + return _delegate ? _delegate->getProgressPos() : Parent::getProgressPos(); } - void seekTo(float fProgress) override { - if (_delegate) { - return _delegate->seekTo(fProgress); - } - return Parent::seekTo(fProgress); + void seekTo(float progress) override { + return _delegate ? _delegate->seekTo(progress) : Parent::seekTo(progress); } - void seekTo(uint32_t seekPos) override { - if (_delegate) { - return _delegate->seekTo(seekPos); - } - return Parent::seekTo(seekPos); + void seekTo(uint32_t pos) override { + return _delegate ? _delegate->seekTo(pos) : Parent::seekTo(pos); } - void setMediaSource(const MediaSource::Ptr &src) override { - if (_delegate) { - _delegate->setMediaSource(src); - } - _pMediaSrc = src; - } - - vector getTracks(bool trackReady = true) const override { - if (_delegate) { - return _delegate->getTracks(trackReady); - } - return Parent::getTracks(trackReady); + vector getTracks(bool ready = true) const override { + return _delegate ? _delegate->getTracks(ready) : Parent::getTracks(ready); } std::shared_ptr getSockInfo() const { return dynamic_pointer_cast(_delegate); } + void setMediaSource(const MediaSource::Ptr &src) override { + if (_delegate) { + _delegate->setMediaSource(src); + } + _media_src = src; + } + + void setOnShutdown(const function &cb) override { + if (_delegate) { + _delegate->setOnShutdown(cb); + } + _on_shutdown = cb; + } + + void setOnPlayResult(const function &cb) override { + if (_delegate) { + _delegate->setOnPlayResult(cb); + } + _on_play_result = cb; + } + + void setOnResume(const function &cb) override { + if (_delegate) { + _delegate->setOnResume(cb); + } + _on_resume = cb; + } + protected: void onShutdown(const SockException &ex) override { - if (_shutdownCB) { - _shutdownCB(ex); - _shutdownCB = nullptr; + if (_on_shutdown) { + _on_shutdown(ex); + _on_shutdown = nullptr; } } void onPlayResult(const SockException &ex) override { - if(_playResultCB) { - _playResultCB(ex); - _playResultCB = nullptr; + if (_on_play_result) { + _on_play_result(ex); + _on_play_result = nullptr; } } - void onResume() override{ - if(_resumeCB){ - _resumeCB(); + void onResume() override { + if (_on_resume) { + _on_resume(); } } + protected: - function _shutdownCB; - function _playResultCB; - function _resumeCB; + function _on_resume; + PlayerBase::Event _on_shutdown; + PlayerBase::Event _on_play_result; + MediaSource::Ptr _media_src; std::shared_ptr _delegate; - MediaSource::Ptr _pMediaSrc; }; -class Demuxer : public PlayerBase, public TrackListener{ +class Demuxer : protected MediaSink { public: Demuxer() = default; ~Demuxer() override = default; - /** - * 返回是否完成初始化完毕 - * 在构造RtspDemuxer对象时有些rtsp的sdp不包含sps pps信息 - * 所以要等待接收到到sps的rtp包后才能完成 - * - * 在构造RtmpDemuxer对象时是无法获取sps pps aac_cfg等这些信息, - * 所以要调用inputRtmp后才会获取到这些信息,这时才初始化成功 - * @param analysisMs 数据流最大分析时间 单位毫秒 - * @return - */ - bool isInited(int analysisMs) override; - - /** - * 获取所有Track - * @return 所有Track - */ - vector getTracks(bool trackReady = true) const override; - - /** - * 获取节目总时长 - * @return 节目总时长,单位秒 - */ - float getDuration() const override; - /** * 设置track监听器 */ void setTrackListener(TrackListener *listener); + vector getTracks(bool ready = true) const override; protected: - bool addTrack(const Track::Ptr &track) override; - void addTrackCompleted() override; + bool addTrack(const Track::Ptr & track) override; void resetTracks() override; + bool onTrackReady(const Track::Ptr & track) override; + void onAllTrackReady() override; + bool onTrackFrame(const Frame::Ptr &frame) override; -protected: - float _fDuration = 0; - Ticker _ticker; - AudioTrack::Ptr _audioTrack; - VideoTrack::Ptr _videoTrack; +private: + Track::Ptr _tracks[TrackMax]; TrackListener *_listener = nullptr; }; diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 84709d42..c36bf00e 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -160,7 +160,7 @@ bool PlayerProxy::close(MediaSource &sender, bool force) { } int PlayerProxy::totalReaderCount() { - return (_muxer ? _muxer->totalReaderCount() : 0) + (_pMediaSrc ? _pMediaSrc->readerCount() : 0); + return (_muxer ? _muxer->totalReaderCount() : 0) + (_media_src ? _media_src->readerCount() : 0); } int PlayerProxy::totalReaderCount(MediaSource &sender) { @@ -181,12 +181,12 @@ std::shared_ptr PlayerProxy::getOriginSock(MediaSource &sender) const void PlayerProxy::onPlaySuccess() { GET_CONFIG(bool, resetWhenRePlay, General::kResetWhenRePlay); - if (dynamic_pointer_cast(_pMediaSrc)) { + if (dynamic_pointer_cast(_media_src)) { //rtsp拉流代理 if (resetWhenRePlay || !_muxer) { _muxer.reset(new MultiMediaSourceMuxer(_vhost, _app, _stream_id, getDuration(), false, true, _enable_hls, _enable_mp4)); } - } else if (dynamic_pointer_cast(_pMediaSrc)) { + } else if (dynamic_pointer_cast(_media_src)) { //rtmp拉流代理 if (resetWhenRePlay || !_muxer) { _muxer.reset(new MultiMediaSourceMuxer(_vhost, _app, _stream_id, getDuration(), true, false, _enable_hls, _enable_mp4)); @@ -218,9 +218,9 @@ void PlayerProxy::onPlaySuccess() { //添加完毕所有track,防止单track情况下最大等待3秒 _muxer->addTrackCompleted(); - if (_pMediaSrc) { + if (_media_src) { //让_muxer对象拦截一部分事件(比如说录像相关事件) - _pMediaSrc->setListener(_muxer); + _media_src->setListener(_muxer); } } diff --git a/src/Rtmp/RtmpDemuxer.cpp b/src/Rtmp/RtmpDemuxer.cpp index 4b82e8a0..357e1d98 100644 --- a/src/Rtmp/RtmpDemuxer.cpp +++ b/src/Rtmp/RtmpDemuxer.cpp @@ -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(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(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(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(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 */ \ No newline at end of file diff --git a/src/Rtmp/RtmpDemuxer.h b/src/Rtmp/RtmpDemuxer.h index 29bfdd7c..65f6181e 100644 --- a/src/Rtmp/RtmpDemuxer.h +++ b/src/Rtmp/RtmpDemuxer.h @@ -23,9 +23,9 @@ using namespace toolkit; namespace mediakit { -class RtmpDemuxer : public Demuxer{ +class RtmpDemuxer : public Demuxer { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; 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; }; diff --git a/src/Rtmp/RtmpPlayerImp.h b/src/Rtmp/RtmpPlayerImp.h index 9d7ec790..f3a106ce 100644 --- a/src/Rtmp/RtmpPlayerImp.h +++ b/src/Rtmp/RtmpPlayerImp.h @@ -24,11 +24,12 @@ using namespace mediakit::Client; namespace mediakit { -class RtmpPlayerImp: public PlayerImp { +class RtmpPlayerImp: public PlayerImp, private TrackListener { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; + using Super = PlayerImp; - RtmpPlayerImp(const EventPoller::Ptr &poller) : PlayerImp(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::play(strUrl); + + float getDuration() const override { + return _demuxer ? _demuxer->getDuration() : 0; + } + + vector 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(_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(_media_src); + if (_rtmp_src) { + _rtmp_src->setMetaData(val); + } + _demuxer = std::make_shared(); + _demuxer->setTrackListener(this); + _demuxer->loadMetaData(val); + } + +private: + RtmpDemuxer::Ptr _demuxer; RtmpMediaSource::Ptr _rtmp_src; - bool _set_meta_data = false; }; diff --git a/src/Rtsp/RtspDemuxer.cpp b/src/Rtsp/RtspDemuxer.cpp index d82ddfc8..ca4c835b 100644 --- a/src/Rtsp/RtspDemuxer.cpp +++ b/src/Rtsp/RtspDemuxer.cpp @@ -18,13 +18,13 @@ using namespace std; namespace mediakit { -void RtspDemuxer::loadSdp(const string &sdp){ +void RtspDemuxer::loadSdp(const string &sdp) { loadSdp(SdpParser(sdp)); } void RtspDemuxer::loadSdp(const SdpParser &attr) { auto tracks = attr.getAvailableTrack(); - for (auto &track : tracks){ + for (auto &track : tracks) { switch (track->_type) { case TrackVideo: { makeVideoTrack(track); @@ -42,31 +42,35 @@ void RtspDemuxer::loadSdp(const SdpParser &attr) { addTrackCompleted(); auto titleTrack = attr.getTrack(TrackTitle); - if(titleTrack){ - _fDuration = titleTrack->_duration; - } -} -bool RtspDemuxer::inputRtp(const RtpPacket::Ptr & rtp) { - switch (rtp->type) { - case TrackVideo:{ - if(_videoRtpDecoder){ - return _videoRtpDecoder->inputRtp(rtp, true); - } - return false; - } - case TrackAudio:{ - if(_audioRtpDecoder){ - _audioRtpDecoder->inputRtp(rtp, false); - return false; - } - return false; - } - default: - return false; + if (titleTrack) { + _duration = titleTrack->_duration; } } -static void setBitRate(const SdpTrack::Ptr &sdp, const Track::Ptr &track){ +float RtspDemuxer::getDuration() const { + return _duration; +} + +bool RtspDemuxer::inputRtp(const RtpPacket::Ptr &rtp) { + switch (rtp->type) { + case TrackVideo: { + if (_videoRtpDecoder) { + return _videoRtpDecoder->inputRtp(rtp, true); + } + return false; + } + case TrackAudio: { + if (_audioRtpDecoder) { + _audioRtpDecoder->inputRtp(rtp, false); + return false; + } + return false; + } + default: return false; + } +} + +static void setBitRate(const SdpTrack::Ptr &sdp, const Track::Ptr &track) { if (!sdp->_b.empty()) { int data_rate = 0; sscanf(sdp->_b.data(), "AS:%d", &data_rate); @@ -78,38 +82,40 @@ static void setBitRate(const SdpTrack::Ptr &sdp, const Track::Ptr &track){ void RtspDemuxer::makeAudioTrack(const SdpTrack::Ptr &audio) { //生成Track对象 - _audioTrack = dynamic_pointer_cast(Factory::getTrackBySdp(audio)); - if(_audioTrack){ - setBitRate(audio, _audioTrack); - //生成RtpCodec对象以便解码rtp - _audioRtpDecoder = Factory::getRtpDecoderByTrack(_audioTrack); - if(_audioRtpDecoder){ - //设置rtp解码器代理,生成的frame写入该Track - _audioRtpDecoder->addDelegate(_audioTrack); - addTrack(_audioTrack); - } else{ - //找不到相应的rtp解码器,该track无效 - _audioTrack.reset(); - } + _audio_track = dynamic_pointer_cast(Factory::getTrackBySdp(audio)); + if (!_audio_track) { + return; } + setBitRate(audio, _audio_track); + //生成RtpCodec对象以便解码rtp + _audioRtpDecoder = Factory::getRtpDecoderByTrack(_audio_track); + if (!_audioRtpDecoder) { + //找不到相应的rtp解码器,该track无效 + _audio_track.reset(); + return; + } + //设置rtp解码器代理,生成的frame写入该Track + _audioRtpDecoder->addDelegate(_audio_track); + addTrack(_audio_track); } void RtspDemuxer::makeVideoTrack(const SdpTrack::Ptr &video) { //生成Track对象 - _videoTrack = dynamic_pointer_cast(Factory::getTrackBySdp(video)); - if(_videoTrack){ - setBitRate(video, _videoTrack); - //生成RtpCodec对象以便解码rtp - _videoRtpDecoder = Factory::getRtpDecoderByTrack(_videoTrack); - if(_videoRtpDecoder){ - //设置rtp解码器代理,生成的frame写入该Track - _videoRtpDecoder->addDelegate(_videoTrack); - addTrack(_videoTrack); - }else{ - //找不到相应的rtp解码器,该track无效 - _videoTrack.reset(); - } + _video_track = dynamic_pointer_cast(Factory::getTrackBySdp(video)); + if (!_video_track) { + return; } + setBitRate(video, _video_track); + //生成RtpCodec对象以便解码rtp + _videoRtpDecoder = Factory::getRtpDecoderByTrack(_video_track); + if (!_videoRtpDecoder) { + //找不到相应的rtp解码器,该track无效 + _video_track.reset(); + return; + } + //设置rtp解码器代理,生成的frame写入该Track + _videoRtpDecoder->addDelegate(_video_track); + addTrack(_video_track); } } /* namespace mediakit */ diff --git a/src/Rtsp/RtspDemuxer.h b/src/Rtsp/RtspDemuxer.h index 082ccf6d..abdd1937 100644 --- a/src/Rtsp/RtspDemuxer.h +++ b/src/Rtsp/RtspDemuxer.h @@ -21,7 +21,7 @@ using namespace toolkit; namespace mediakit { -class RtspDemuxer : public Demuxer{ +class RtspDemuxer : public Demuxer { public: typedef std::shared_ptr Ptr; RtspDemuxer() = default; @@ -38,11 +38,22 @@ public: * @return true 代表是i帧第一个rtp包 */ bool inputRtp(const RtpPacket::Ptr &rtp); + + /** + * 获取节目总时长 + * @return 节目总时长,单位秒 + */ + float getDuration() const; + private: void makeAudioTrack(const SdpTrack::Ptr &audio); void makeVideoTrack(const SdpTrack::Ptr &video); void loadSdp(const SdpParser &parser); + private: + float _duration = 0; + AudioTrack::Ptr _audio_track; + VideoTrack::Ptr _video_track; RtpCodec::Ptr _audioRtpDecoder; RtpCodec::Ptr _videoRtpDecoder; }; diff --git a/src/Rtsp/RtspPlayerImp.h b/src/Rtsp/RtspPlayerImp.h index 180c17c3..103a94c9 100644 --- a/src/Rtsp/RtspPlayerImp.h +++ b/src/Rtsp/RtspPlayerImp.h @@ -25,12 +25,14 @@ using namespace toolkit; namespace mediakit { -class RtspPlayerImp : public PlayerImp { +class RtspPlayerImp : public PlayerImp ,private TrackListener { public: - typedef std::shared_ptr Ptr; + using Ptr = std::shared_ptr; + using Super = PlayerImp; - RtspPlayerImp(const EventPoller::Ptr &poller) : PlayerImp(poller) {} - ~RtspPlayerImp() override{ + RtspPlayerImp(const EventPoller::Ptr &poller) : Super(poller) {} + + ~RtspPlayerImp() override { DebugL << endl; } @@ -39,7 +41,6 @@ public: return getProgressMilliSecond() / (getDuration() * 1000); } return PlayerBase::getProgress(); - } uint32_t getProgressPos() const override { @@ -55,29 +56,33 @@ public: } void seekTo(uint32_t seekPos) override { - uint32_t pos = MAX(float(0), MIN(seekPos, getDuration()))*1000; + uint32_t pos = MAX(float(0), MIN(seekPos, getDuration())) * 1000; seekToMilliSecond(pos); } + float getDuration() const override { + return _demuxer ? _demuxer->getDuration() : 0; + } + + vector getTracks(bool ready = true) const override { + return _demuxer ? _demuxer->getTracks(ready) : Super::getTracks(ready); + } + private: //派生类回调函数 bool onCheckSDP(const string &sdp) override { - _rtsp_media_src = dynamic_pointer_cast(_pMediaSrc); + _rtsp_media_src = dynamic_pointer_cast(_media_src); if (_rtsp_media_src) { _rtsp_media_src->setSdp(sdp); } - _delegate.reset(new RtspDemuxer); - _delegate->loadSdp(sdp); + _demuxer = std::make_shared(); + _demuxer->setTrackListener(this); + _demuxer->loadSdp(sdp); return true; } void onRecvRTP(RtpPacket::Ptr rtp, const SdpTrack::Ptr &track) override { - _delegate->inputRtp(rtp); - if (_max_analysis_ms && _delegate->isInited(_max_analysis_ms)) { - PlayerImp::onPlayResult(SockException(Err_success, "play rtsp success")); - _max_analysis_ms = 0; - } - + _demuxer->inputRtp(rtp); if (_rtsp_media_src) { // rtsp直接代理是无法判断该rtp是否是I帧,所以GOP缓存基本是无效的 // 为了减少内存使用,那么我们设置为一直关键帧以便清空GOP缓存 @@ -85,23 +90,21 @@ private: } } - //在RtspPlayer中触发onPlayResult事件只是代表收到play回复了, - //并不代表所有track初始化成功了(这跟rtmp播放器不一样) - //如果sdp里面信息不完整,只能尝试延后从rtp中恢复关键信息并初始化track - //如果超过这个时间还未获取成功,那么会强制触发onPlayResult事件(虽然此时有些track还未初始化成功) void onPlayResult(const SockException &ex) override { - //isInited判断条件:无超时 - if (ex || _delegate->isInited(0)) { - //已经初始化成功,说明sdp里面有完善的信息 - PlayerImp::onPlayResult(ex); - } else { - //还没初始化成功,说明sdp里面信息不完善,还有一些track未初始化成功 - _max_analysis_ms = (*this)[Client::kMaxAnalysisMS]; + 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: - int _max_analysis_ms = 0; + RtspDemuxer::Ptr _demuxer; RtspMediaSource::Ptr _rtsp_media_src; };