/* * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). * * Use of this source code is governed by MIT license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #include "MultiMediaSourceMuxer.h" namespace mediakit { MultiMuxerPrivate::~MultiMuxerPrivate() {} MultiMuxerPrivate::MultiMuxerPrivate(const string &vhost, const string &app, const string &stream, float dur_sec, bool enable_rtsp, bool enable_rtmp, bool enable_hls, bool enable_mp4) { if (enable_rtmp) { _rtmp = std::make_shared(vhost, app, stream, std::make_shared(dur_sec)); _enable_rtxp = true; } if (enable_rtsp) { _rtsp = std::make_shared(vhost, app, stream, std::make_shared(dur_sec)); _enable_rtxp = true; } if (enable_hls) { _hls = Recorder::createRecorder(Recorder::type_hls, vhost, app, stream); _enable_record = true; } if (enable_mp4) { _mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream); _enable_record = true; } } void MultiMuxerPrivate::resetTracks() { if (_rtmp) { _rtmp->resetTracks(); } if (_rtsp) { _rtsp->resetTracks(); } //拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题 auto hls = _hls; if (hls) { hls->resetTracks(); } auto mp4 = _mp4; if (mp4) { mp4->resetTracks(); } } void MultiMuxerPrivate::setMediaListener(const std::weak_ptr &listener) { if (_rtmp) { _rtmp->setListener(listener); } if (_rtsp) { _rtsp->setListener(listener); } auto hls_src = getHlsMediaSource(); if (hls_src) { hls_src->setListener(listener); } _meida_listener = listener; } int MultiMuxerPrivate::totalReaderCount() const { auto hls_src = getHlsMediaSource(); return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + (hls_src ? hls_src->readerCount() : 0); } static std::shared_ptr makeRecorder(const vector &tracks, Recorder::type type, const string &custom_path, MediaSource &sender){ auto recorder = Recorder::createRecorder(type, sender.getVhost(), sender.getApp(), sender.getId(), custom_path); for (auto &track : tracks) { recorder->addTrack(track); } return recorder; } //此函数可能跨线程调用 bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path){ switch (type) { case Recorder::type_hls : { if (start && !_hls) { //开始录制 _hls = makeRecorder(getTracks(true), type, custom_path, sender); auto hls_src = getHlsMediaSource(); if (hls_src) { //设置HlsMediaSource的事件监听器 hls_src->setListener(_meida_listener); hls_src->setTrackSource(shared_from_this()); } } else if (!start && _hls) { //停止录制 _hls = nullptr; } _enable_record = _hls || _mp4; return true; } case Recorder::type_mp4 : { if (start && !_mp4) { //开始录制 _mp4 = makeRecorder(getTracks(true), type, custom_path, sender); } else if (!start && _mp4) { //停止录制 _mp4 = nullptr; } _enable_record = _hls || _mp4; return true; } default : return false; } } //此函数可能跨线程调用 bool MultiMuxerPrivate::isRecording(MediaSource &sender, Recorder::type type){ switch (type){ case Recorder::type_hls : return _hls ? true : false; case Recorder::type_mp4 : return _mp4 ? true : false; default: return false; } } void MultiMuxerPrivate::setTimeStamp(uint32_t stamp) { if (_rtmp) { _rtmp->setTimeStamp(stamp); } if (_rtsp) { _rtsp->setTimeStamp(stamp); } } void MultiMuxerPrivate::setTrackListener(Listener *listener) { _listener = listener; } void MultiMuxerPrivate::onTrackReady(const Track::Ptr &track) { if (_rtmp) { _rtmp->addTrack(track); } if (_rtsp) { _rtsp->addTrack(track); } //拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题 auto hls = _hls; if (hls) { hls->addTrack(track); } auto mp4 = _mp4; if (mp4) { mp4->addTrack(track); } } bool MultiMuxerPrivate::isEnabled(){ return _enable_rtxp || _enable_record; } void MultiMuxerPrivate::onTrackFrame(const Frame::Ptr &frame) { if (_rtmp) { _rtmp->inputFrame(frame); } if (_rtsp) { _rtsp->inputFrame(frame); } //拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题 //此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优 auto hls = _hls; if (hls) { hls->inputFrame(frame); } auto mp4 = _mp4; if (mp4) { mp4->inputFrame(frame); } } void MultiMuxerPrivate::onAllTrackReady() { if (_rtmp) { _rtmp->setTrackSource(shared_from_this()); _rtmp->onAllTrackReady(); } if (_rtsp) { _rtsp->setTrackSource(shared_from_this()); _rtsp->onAllTrackReady(); } auto hls_src = getHlsMediaSource(); if (hls_src) { hls_src->setTrackSource(shared_from_this()); } if (_listener) { _listener->onAllTrackReady(); } } MediaSource::Ptr MultiMuxerPrivate::getHlsMediaSource() const { auto recorder = dynamic_pointer_cast(_hls); if (recorder) { return recorder->getMediaSource(); } return nullptr; } ///////////////////////////////////////////////////////////////// MultiMediaSourceMuxer::~MultiMediaSourceMuxer() {} MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &app, const string &stream, float dur_sec, bool enable_rtsp, bool enable_rtmp, bool enable_hls, bool enable_mp4) { _muxer.reset(new MultiMuxerPrivate(vhost, app, stream, dur_sec, enable_rtsp, enable_rtmp, enable_hls, enable_mp4)); } void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr &listener) { _muxer->setMediaListener(shared_from_this()); _listener = listener; } int MultiMediaSourceMuxer::totalReaderCount() const { return _muxer->totalReaderCount(); } void MultiMediaSourceMuxer::setTimeStamp(uint32_t stamp) { _muxer->setTimeStamp(stamp); } void MultiMediaSourceMuxer::setTrackListener(Listener *listener) { _muxer->setTrackListener(listener); } vector MultiMediaSourceMuxer::getTracks(bool trackReady) const { return _muxer->getTracks(trackReady); } bool MultiMediaSourceMuxer::seekTo(MediaSource &sender, uint32_t ui32Stamp) { auto listener = _listener.lock(); if (!listener) { return false; } return listener->seekTo(sender, ui32Stamp); } bool MultiMediaSourceMuxer::close(MediaSource &sender, bool force) { auto listener = _listener.lock(); if (!listener) { return false; } return listener->close(sender, force); } int MultiMediaSourceMuxer::totalReaderCount(MediaSource &sender) { auto listener = _listener.lock(); if (!listener) { return _muxer->totalReaderCount(); } return listener->totalReaderCount(sender); } bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path) { return _muxer->setupRecord(sender,type,start,custom_path); } bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type) { return _muxer->isRecording(sender,type); } void MultiMediaSourceMuxer::addTrack(const Track::Ptr &track) { _muxer->addTrack(track); } void MultiMediaSourceMuxer::addTrackCompleted() { _muxer->addTrackCompleted(); } void MultiMediaSourceMuxer::resetTracks() { _muxer->resetTracks(); } void MultiMediaSourceMuxer::inputFrame(const Frame::Ptr &frame) { _muxer->inputFrame(frame); } bool MultiMediaSourceMuxer::isEnabled(){ return _muxer->isEnabled(); } }//namespace mediakit