parent
f8bd7f606e
commit
2a6013a3b8
|
|
@ -430,8 +430,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart)
|
|||
|
||||
add_subdirectory(3rdpart)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if(ENABLE_SRT)
|
||||
add_subdirectory(srt)
|
||||
endif()
|
||||
|
|
@ -444,6 +442,8 @@ if(ENABLE_API)
|
|||
add_subdirectory(api)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
# IOS 不编译可执行程序
|
||||
if(IOS)
|
||||
return()
|
||||
|
|
|
|||
|
|
@ -64,7 +64,9 @@ ProtocolOption::ProtocolOption() {
|
|||
GET_CONFIG(bool, s_enable_rtmp, Protocol::kEnableRtmp);
|
||||
GET_CONFIG(bool, s_enable_ts, Protocol::kEnableTS);
|
||||
GET_CONFIG(bool, s_enable_fmp4, Protocol::kEnableFMP4);
|
||||
|
||||
GET_CONFIG(bool, s_enable_rtc, Protocol::kEnableRtc);
|
||||
GET_CONFIG(bool, s_audio_transcode, Protocol::kAudioTranscode);
|
||||
GET_CONFIG(bool, s_rtc_demand, Protocol::kRtcDemand);
|
||||
GET_CONFIG(bool, s_hls_demand, Protocol::kHlsDemand);
|
||||
GET_CONFIG(bool, s_rtsp_demand, Protocol::kRtspDemand);
|
||||
GET_CONFIG(bool, s_rtmp_demand, Protocol::kRtmpDemand);
|
||||
|
|
@ -88,7 +90,9 @@ ProtocolOption::ProtocolOption() {
|
|||
enable_rtmp = s_enable_rtmp;
|
||||
enable_ts = s_enable_ts;
|
||||
enable_fmp4 = s_enable_fmp4;
|
||||
|
||||
enable_rtc = s_enable_rtc;
|
||||
audio_transcode = s_audio_transcode;
|
||||
rtc_demand = s_rtc_demand;
|
||||
hls_demand = s_hls_demand;
|
||||
rtsp_demand = s_rtsp_demand;
|
||||
rtmp_demand = s_rtmp_demand;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public:
|
|||
bool enable_hls;
|
||||
//是否开启MP4录制
|
||||
bool enable_mp4;
|
||||
//是否开启转换为rtsp/webrtc
|
||||
//是否开启转换为rtsp
|
||||
bool enable_rtsp;
|
||||
//是否开启转换为rtmp/flv
|
||||
bool enable_rtmp;
|
||||
|
|
@ -154,7 +154,11 @@ public:
|
|||
bool enable_ts;
|
||||
//是否开启转换为http-fmp4/ws-fmp4
|
||||
bool enable_fmp4;
|
||||
|
||||
//是否开启转换为webrtc
|
||||
bool enable_rtc;
|
||||
// 是否启用音频转码
|
||||
bool audio_transcode;
|
||||
bool rtc_demand;
|
||||
// hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
|
||||
bool hls_demand;
|
||||
// rtsp[s]协议是否按需生成
|
||||
|
|
@ -190,6 +194,9 @@ public:
|
|||
GET_OPT_VALUE(enable_rtmp);
|
||||
GET_OPT_VALUE(enable_ts);
|
||||
GET_OPT_VALUE(enable_fmp4);
|
||||
GET_OPT_VALUE(enable_rtc);
|
||||
GET_OPT_VALUE(audio_transcode);
|
||||
GET_OPT_VALUE(rtc_demand);
|
||||
|
||||
GET_OPT_VALUE(hls_demand);
|
||||
GET_OPT_VALUE(rtsp_demand);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,20 @@
|
|||
#include <math.h>
|
||||
#include "Common/config.h"
|
||||
#include "MultiMediaSourceMuxer.h"
|
||||
#include "Extension/AAC.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Rtp/RtpSender.h"
|
||||
#include "Record/HlsRecorder.h"
|
||||
#include "Record/HlsMediaSource.h"
|
||||
#include "Rtsp/RtspMediaSourceMuxer.h"
|
||||
#include "Rtmp/RtmpMediaSourceMuxer.h"
|
||||
#include "TS/TSMediaSourceMuxer.h"
|
||||
#include "FMP4/FMP4MediaSourceMuxer.h"
|
||||
|
||||
#ifdef ENABLE_FFMPEG
|
||||
#include "Codec/Transcode.h"
|
||||
#endif
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
|
|
@ -93,6 +106,11 @@ MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &
|
|||
if (option.enable_rtsp) {
|
||||
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleSdp>(dur_sec));
|
||||
}
|
||||
if (option.enable_rtc) {
|
||||
#if defined(ENABLE_WEBRTC)
|
||||
_rtc = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleSdp>(dur_sec), RTC_SCHEMA);
|
||||
#endif
|
||||
}
|
||||
if (option.enable_hls) {
|
||||
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, vhost, app, stream, option));
|
||||
}
|
||||
|
|
@ -102,6 +120,14 @@ MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &
|
|||
if (option.enable_ts) {
|
||||
_ts = std::make_shared<TSMediaSourceMuxer>(vhost, app, stream, option);
|
||||
}
|
||||
if (option.audio_transcode) {
|
||||
#if defined(ENABLE_FFMPEG)
|
||||
_audio_transcode = option.audio_transcode;
|
||||
InfoL << "enable audio_transcode";
|
||||
#else
|
||||
InfoL << "without ffmpeg disable audio_transcode";
|
||||
#endif
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (option.enable_fmp4) {
|
||||
_fmp4 = std::make_shared<FMP4MediaSourceMuxer>(vhost, app, stream, option);
|
||||
|
|
@ -127,6 +153,9 @@ void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr<MediaSourceEven
|
|||
if (_ts) {
|
||||
_ts->setListener(self);
|
||||
}
|
||||
if (_rtc) {
|
||||
_rtc->setListener(self);
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->setListener(self);
|
||||
|
|
@ -143,21 +172,21 @@ void MultiMediaSourceMuxer::setTrackListener(const std::weak_ptr<Listener> &list
|
|||
}
|
||||
|
||||
int MultiMediaSourceMuxer::totalReaderCount() const {
|
||||
auto hls = _hls;
|
||||
auto ret = (_rtsp ? _rtsp->readerCount() : 0) +
|
||||
(_rtmp ? _rtmp->readerCount() : 0) +
|
||||
(_ts ? _ts->readerCount() : 0) +
|
||||
#if defined(ENABLE_MP4)
|
||||
(_fmp4 ? _fmp4->readerCount() : 0) +
|
||||
#endif
|
||||
(_mp4 ? _option.mp4_as_player : 0) +
|
||||
(hls ? hls->readerCount() : 0);
|
||||
int ret = 0;
|
||||
if (_rtsp) ret += _rtsp->readerCount();
|
||||
if (_rtmp) ret += _rtmp->readerCount();
|
||||
if (_rtc) ret += _rtc->readerCount();
|
||||
if (_ts) ret += _ts->readerCount();
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) ret += _fmp4->readerCount();
|
||||
#endif
|
||||
if (_mp4) ret += _option.mp4_as_player;
|
||||
if (_hls) ret += _hls->readerCount();
|
||||
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
return ret + (int)_rtp_sender.size();
|
||||
#else
|
||||
return ret;
|
||||
ret += (int)_rtp_sender.size();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MultiMediaSourceMuxer::setTimeStamp(uint32_t stamp) {
|
||||
|
|
@ -313,15 +342,73 @@ EventPoller::Ptr MultiMediaSourceMuxer::getOwnerPoller(MediaSource &sender) {
|
|||
bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) {
|
||||
|
||||
bool ret = false;
|
||||
if (_rtmp) {
|
||||
ret = _rtmp->addTrack(track) ? true : ret;
|
||||
}
|
||||
if (_rtsp) {
|
||||
ret = _rtsp->addTrack(track) ? true : ret;
|
||||
}
|
||||
if (_ts) {
|
||||
ret = _ts->addTrack(track) ? true : ret;
|
||||
auto rtmp = _rtmp;
|
||||
auto rtc = _rtc;
|
||||
#if defined(ENABLE_FFMPEG)
|
||||
if (_audio_transcode) {
|
||||
if (track->getCodecId() == CodecAAC) {
|
||||
if (rtmp) {
|
||||
rtmp->addTrack(track);
|
||||
rtmp = nullptr;
|
||||
}
|
||||
_audio_dec = nullptr;
|
||||
_audio_enc = nullptr;
|
||||
if (rtc) {
|
||||
Track::Ptr newTrack(new OpusTrack());
|
||||
GET_CONFIG(int, bitrate, General::kOpusBitrate);
|
||||
newTrack->setBitRate(bitrate);
|
||||
rtc->addTrack(newTrack);
|
||||
rtc = nullptr;
|
||||
|
||||
// aac to opus
|
||||
_audio_dec.reset(new FFmpegDecoder(track));
|
||||
_audio_enc.reset(new FFmpegEncoder(newTrack));
|
||||
_audio_dec->setOnDecode([this](const FFmpegFrame::Ptr & frame) {
|
||||
_audio_enc->inputFrame(frame, false);
|
||||
});
|
||||
_audio_enc->setOnEncode([this](const Frame::Ptr& frame) {
|
||||
// fill data to _rtc
|
||||
if (_rtc && _rtc->isEnabled())
|
||||
_rtc->inputFrame(frame);
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (track->getTrackType() == TrackAudio) {
|
||||
if (rtc) {
|
||||
rtc->addTrack(track);
|
||||
rtc = nullptr;
|
||||
}
|
||||
_audio_dec = nullptr;
|
||||
_audio_enc = nullptr;
|
||||
if (rtmp) {
|
||||
Track::Ptr newTrack(new AACTrack(44100, std::dynamic_pointer_cast<AudioTrack>(track)->getAudioChannel()));
|
||||
GET_CONFIG(int, bitrate, General::kAacBitrate);
|
||||
newTrack->setBitRate(bitrate);
|
||||
rtmp->addTrack(newTrack);
|
||||
rtmp = nullptr;
|
||||
|
||||
_audio_dec.reset(new FFmpegDecoder(track));
|
||||
_audio_enc.reset(new FFmpegEncoder(newTrack));
|
||||
_audio_dec->setOnDecode([this](const FFmpegFrame::Ptr & frame) {
|
||||
_audio_enc->inputFrame(frame, false);
|
||||
});
|
||||
_audio_enc->setOnEncode([this](const Frame::Ptr& frame) {
|
||||
// fill aac frame to rtmp
|
||||
if (_rtmp && _rtmp->isEnabled())
|
||||
_rtmp->inputFrame(frame);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (rtc && rtc->addTrack(track))
|
||||
ret = true;
|
||||
if (rtmp && rtmp->addTrack(track))
|
||||
ret = true;
|
||||
if (_rtsp && _rtsp->addTrack(track))
|
||||
ret = true;
|
||||
if (_ts && _ts->addTrack(track))
|
||||
ret = true;
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
ret = _fmp4->addTrack(track) ? true : ret;
|
||||
|
|
@ -350,6 +437,9 @@ void MultiMediaSourceMuxer::onAllTrackReady() {
|
|||
if (_rtsp) {
|
||||
_rtsp->onAllTrackReady();
|
||||
}
|
||||
if (_rtc) {
|
||||
_rtc->onAllTrackReady();
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->onAllTrackReady();
|
||||
|
|
@ -374,6 +464,13 @@ void MultiMediaSourceMuxer::resetTracks() {
|
|||
if (_ts) {
|
||||
_ts->resetTracks();
|
||||
}
|
||||
if (_rtc) {
|
||||
_rtc->resetTracks();
|
||||
}
|
||||
#if defined(ENABLE_FFMPEG)
|
||||
_audio_dec = nullptr;
|
||||
_audio_dec = nullptr;
|
||||
#endif
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->resetTracks();
|
||||
|
|
@ -406,15 +503,41 @@ bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) {
|
|||
}
|
||||
|
||||
bool ret = false;
|
||||
if (_rtmp) {
|
||||
ret = _rtmp->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
if (_rtsp) {
|
||||
ret = _rtsp->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
if (_ts) {
|
||||
ret = _ts->inputFrame(frame) ? true : ret;
|
||||
RtspMediaSourceMuxer::Ptr rtc;
|
||||
RtmpMediaSourceMuxer::Ptr rtmp;
|
||||
if (_rtc && _rtc->isEnabled())
|
||||
rtc = _rtc;
|
||||
if (_rtmp && _rtmp->isEnabled())
|
||||
rtmp = _rtmp;
|
||||
#if defined(ENABLE_FFMPEG)
|
||||
if (_audio_transcode) {
|
||||
if (frame->getCodecId() == CodecAAC) {
|
||||
if (rtc) {
|
||||
if (_audio_dec && rtc->readerCount())
|
||||
_audio_dec->inputFrame(frame, true, false, false);
|
||||
rtc = nullptr;
|
||||
}
|
||||
}
|
||||
else if (frame->getTrackType() == TrackAudio) {
|
||||
if (rtmp) {
|
||||
if (_audio_dec && rtmp->readerCount())
|
||||
_audio_dec->inputFrame(frame, true, false, false);
|
||||
rtmp = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (rtc && rtc->inputFrame(frame))
|
||||
ret = true;
|
||||
|
||||
if (rtmp && rtmp->inputFrame(frame))
|
||||
ret = true;
|
||||
|
||||
if (_rtsp && _rtsp->inputFrame(frame))
|
||||
ret = true;
|
||||
|
||||
if (_ts && _ts->inputFrame(frame))
|
||||
ret = true;
|
||||
|
||||
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
||||
//此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优
|
||||
|
|
@ -450,9 +573,10 @@ bool MultiMediaSourceMuxer::isEnabled(){
|
|||
auto flag = (_rtmp ? _rtmp->isEnabled() : false) ||
|
||||
(_rtsp ? _rtsp->isEnabled() : false) ||
|
||||
(_ts ? _ts->isEnabled() : false) ||
|
||||
#if defined(ENABLE_MP4)
|
||||
(_rtc && _rtc->isEnabled()) ||
|
||||
#if defined(ENABLE_MP4)
|
||||
(_fmp4 ? _fmp4->isEnabled() : false) ||
|
||||
#endif
|
||||
#endif
|
||||
(hls ? hls->isEnabled() : false) || _mp4;
|
||||
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
|
|
|
|||
|
|
@ -15,15 +15,17 @@
|
|||
#include "Common/MediaSource.h"
|
||||
#include "Common/MediaSink.h"
|
||||
#include "Record/Recorder.h"
|
||||
#include "Rtp/RtpSender.h"
|
||||
#include "Record/HlsRecorder.h"
|
||||
#include "Record/HlsMediaSource.h"
|
||||
#include "Rtsp/RtspMediaSourceMuxer.h"
|
||||
#include "Rtmp/RtmpMediaSourceMuxer.h"
|
||||
#include "TS/TSMediaSourceMuxer.h"
|
||||
#include "FMP4/FMP4MediaSourceMuxer.h"
|
||||
|
||||
namespace mediakit {
|
||||
class HlsRecorder;
|
||||
class RtspMediaSourceMuxer;
|
||||
class RtmpMediaSourceMuxer;
|
||||
class TSMediaSourceMuxer;
|
||||
class FMP4MediaSourceMuxer;
|
||||
class RtpSender;
|
||||
#ifdef ENABLE_FFMPEG
|
||||
class FFmpegDecoder;
|
||||
class FFmpegEncoder;
|
||||
#endif
|
||||
|
||||
class MultiMediaSourceMuxer : public MediaSourceEventInterceptor, public MediaSink, public std::enable_shared_from_this<MultiMediaSourceMuxer>{
|
||||
public:
|
||||
|
|
@ -162,17 +164,23 @@ private:
|
|||
Stamp _stamp[2];
|
||||
std::weak_ptr<Listener> _track_listener;
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
std::unordered_map<std::string, RtpSender::Ptr> _rtp_sender;
|
||||
std::unordered_map<std::string, std::shared_ptr<RtpSender>> _rtp_sender;
|
||||
#endif //ENABLE_RTPPROXY
|
||||
|
||||
#if defined(ENABLE_MP4)
|
||||
FMP4MediaSourceMuxer::Ptr _fmp4;
|
||||
std::shared_ptr<FMP4MediaSourceMuxer> _fmp4;
|
||||
#endif
|
||||
std::shared_ptr<RtmpMediaSourceMuxer> _rtmp;
|
||||
std::shared_ptr<RtspMediaSourceMuxer> _rtsp;
|
||||
std::shared_ptr<TSMediaSourceMuxer> _ts;
|
||||
std::shared_ptr<RtspMediaSourceMuxer> _rtc;
|
||||
#if defined(ENABLE_FFMPEG)
|
||||
bool _audio_transcode = false;
|
||||
std::shared_ptr<FFmpegDecoder> _audio_dec;
|
||||
std::shared_ptr<FFmpegEncoder> _audio_enc;
|
||||
#endif
|
||||
RtmpMediaSourceMuxer::Ptr _rtmp;
|
||||
RtspMediaSourceMuxer::Ptr _rtsp;
|
||||
TSMediaSourceMuxer::Ptr _ts;
|
||||
MediaSinkInterface::Ptr _mp4;
|
||||
HlsRecorder::Ptr _hls;
|
||||
std::shared_ptr<HlsRecorder> _hls;
|
||||
toolkit::EventPoller::Ptr _poller;
|
||||
|
||||
//对象个数统计
|
||||
|
|
|
|||
|
|
@ -75,12 +75,16 @@ const string kEnableFFmpegLog = GENERAL_FIELD "enable_ffmpeg_log";
|
|||
const string kWaitTrackReadyMS = GENERAL_FIELD "wait_track_ready_ms";
|
||||
const string kWaitAddTrackMS = GENERAL_FIELD "wait_add_track_ms";
|
||||
const string kUnreadyFrameCache = GENERAL_FIELD "unready_frame_cache";
|
||||
const string kOpusBitrate = GENERAL_FIELD"opusBitrate";
|
||||
const string kAacBitrate = GENERAL_FIELD"aacBitrate";
|
||||
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kFlowThreshold] = 1024;
|
||||
mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000;
|
||||
mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000;
|
||||
mINI::Instance()[kEnableVhost] = 0;
|
||||
mINI::Instance()[kOpusBitrate] = 64000;
|
||||
mINI::Instance()[kAacBitrate] = 64000;
|
||||
mINI::Instance()[kResetWhenRePlay] = 1;
|
||||
mINI::Instance()[kMergeWriteMS] = 0;
|
||||
mINI::Instance()[kMediaServerId] = makeRandStr(16);
|
||||
|
|
@ -106,6 +110,8 @@ const string kEnableRtsp = PROTOCOL_FIELD "enable_rtsp";
|
|||
const string kEnableRtmp = PROTOCOL_FIELD "enable_rtmp";
|
||||
const string kEnableTS = PROTOCOL_FIELD "enable_ts";
|
||||
const string kEnableFMP4 = PROTOCOL_FIELD "enable_fmp4";
|
||||
const string kEnableRtc = PROTOCOL_FIELD "enable_rtc";
|
||||
const string kAudioTranscode = PROTOCOL_FIELD "audio_transcode";
|
||||
|
||||
const string kMP4AsPlayer = PROTOCOL_FIELD "mp4_as_player";
|
||||
const string kMP4MaxSecond = PROTOCOL_FIELD "mp4_max_second";
|
||||
|
|
@ -113,6 +119,7 @@ const string kMP4SavePath = PROTOCOL_FIELD "mp4_save_path";
|
|||
|
||||
const string kHlsSavePath = PROTOCOL_FIELD "hls_save_path";
|
||||
|
||||
const string kRtcDemand = PROTOCOL_FIELD "rtc_demand";
|
||||
const string kHlsDemand = PROTOCOL_FIELD "hls_demand";
|
||||
const string kRtspDemand = PROTOCOL_FIELD "rtsp_demand";
|
||||
const string kRtmpDemand = PROTOCOL_FIELD "rtmp_demand";
|
||||
|
|
@ -131,6 +138,8 @@ static onceToken token([]() {
|
|||
mINI::Instance()[kEnableRtmp] = 1;
|
||||
mINI::Instance()[kEnableTS] = 1;
|
||||
mINI::Instance()[kEnableFMP4] = 1;
|
||||
mINI::Instance()[kEnableRtc] = 1;
|
||||
mINI::Instance()[kAudioTranscode] = 1;
|
||||
|
||||
mINI::Instance()[kMP4AsPlayer] = 0;
|
||||
mINI::Instance()[kMP4MaxSecond] = 3600;
|
||||
|
|
@ -138,6 +147,7 @@ static onceToken token([]() {
|
|||
|
||||
mINI::Instance()[kHlsSavePath] = "./www";
|
||||
|
||||
mINI::Instance()[kRtcDemand] = 0;
|
||||
mINI::Instance()[kHlsDemand] = 0;
|
||||
mINI::Instance()[kRtspDemand] = 0;
|
||||
mINI::Instance()[kRtmpDemand] = 0;
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ extern const std::string kWaitTrackReadyMS;
|
|||
extern const std::string kWaitAddTrackMS;
|
||||
// 如果track未就绪,我们先缓存帧数据,但是有最大个数限制(100帧时大约4秒),防止内存溢出
|
||||
extern const std::string kUnreadyFrameCache;
|
||||
extern const std::string kOpusBitrate;
|
||||
extern const std::string kAacBitrate;
|
||||
} // namespace General
|
||||
|
||||
namespace Protocol {
|
||||
|
|
@ -205,6 +207,8 @@ extern const std::string kEnableRtmp;
|
|||
extern const std::string kEnableTS;
|
||||
//是否开启转换为http-fmp4/ws-fmp4
|
||||
extern const std::string kEnableFMP4;
|
||||
extern const std::string kEnableRtc;
|
||||
extern const std::string kAudioTranscode;
|
||||
|
||||
//是否将mp4录制当做观看者
|
||||
extern const std::string kMP4AsPlayer;
|
||||
|
|
@ -217,6 +221,7 @@ extern const std::string kMP4SavePath;
|
|||
extern const std::string kHlsSavePath;
|
||||
|
||||
// 按需转协议的开关
|
||||
extern const std::string kRtcDemand;
|
||||
extern const std::string kHlsDemand;
|
||||
extern const std::string kRtspDemand;
|
||||
extern const std::string kRtmpDemand;
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ public:
|
|||
RtspMediaSource(const std::string &vhost,
|
||||
const std::string &app,
|
||||
const std::string &stream_id,
|
||||
const std::string &schema = RTSP_SCHEMA,
|
||||
int ring_size = RTP_GOP_SIZE) :
|
||||
MediaSource(RTSP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {}
|
||||
MediaSource(schema, vhost, app, stream_id), _ring_size(ring_size) {}
|
||||
|
||||
~RtspMediaSource() override { flush(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ void RtspMediaSource::onWrite(RtpPacket::Ptr rtp, bool keyPos) {
|
|||
PacketCache<RtpPacket>::inputPacket(stamp, is_video, std::move(rtp), keyPos);
|
||||
}
|
||||
|
||||
RtspMediaSourceImp::RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize)
|
||||
: RtspMediaSource(vhost, app, id, ringSize)
|
||||
RtspMediaSourceImp::RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, const std::string &schema, int ringSize)
|
||||
: RtspMediaSource(vhost, app, id, schema, ringSize)
|
||||
{
|
||||
_demuxer = std::make_shared<RtspDemuxer>();
|
||||
_demuxer->setTrackListener(this);
|
||||
|
|
@ -113,7 +113,12 @@ void RtspMediaSourceImp::setProtocolOption(const ProtocolOption &option)
|
|||
//开启直接代理模式时,rtsp直接代理,不重复产生;但是有些rtsp推流端,由于sdp中已有sps pps,rtp中就不再包括sps pps,
|
||||
//导致rtc无法播放,所以在rtsp推流rtc播放时,建议关闭直接代理模式
|
||||
_option = option;
|
||||
_option.enable_rtsp = !direct_proxy;
|
||||
if (direct_proxy) {
|
||||
if (getSchema() == RTC_SCHEMA)
|
||||
_option.enable_rtc = false;
|
||||
if (getSchema() == RTSP_SCHEMA)
|
||||
_option.enable_rtsp = false;
|
||||
}
|
||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), _option);
|
||||
_muxer->setMediaListener(getListener());
|
||||
_muxer->setTrackListener(std::static_pointer_cast<RtspMediaSourceImp>(shared_from_this()));
|
||||
|
|
@ -127,5 +132,42 @@ void RtspMediaSourceImp::setProtocolOption(const ProtocolOption &option)
|
|||
}
|
||||
|
||||
|
||||
bool RtspMediaSourceImp::addTrack(const Track::Ptr &track)
|
||||
{
|
||||
if (_muxer) {
|
||||
if (_muxer->addTrack(track)) {
|
||||
track->addDelegate(_muxer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RtspMediaSourceImp::addTrackCompleted()
|
||||
{
|
||||
if (_muxer) {
|
||||
_muxer->addTrackCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
void RtspMediaSourceImp::resetTracks()
|
||||
{
|
||||
if (_muxer) {
|
||||
_muxer->resetTracks();
|
||||
}
|
||||
}
|
||||
|
||||
void RtspMediaSourceImp::setListener(const std::weak_ptr<MediaSourceEvent> &listener)
|
||||
{
|
||||
if (_muxer) {
|
||||
//_muxer对象不能处理的事件再给listener处理
|
||||
_muxer->setMediaListener(listener);
|
||||
}
|
||||
else {
|
||||
//未创建_muxer对象,事件全部给listener处理
|
||||
MediaSource::setListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,11 @@
|
|||
#define SRC_RTSP_RTSPTORTMPMEDIASOURCE_H_
|
||||
|
||||
#include "RtspMediaSource.h"
|
||||
#include "RtspDemuxer.h"
|
||||
#include "Common/MultiMediaSourceMuxer.h"
|
||||
|
||||
namespace mediakit {
|
||||
class RtspDemuxer;
|
||||
class RtspMediaSourceImp final : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener {
|
||||
class RtspMediaSourceImp : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<RtspMediaSourceImp>;
|
||||
|
||||
|
|
@ -28,7 +27,7 @@ public:
|
|||
* @param id 流id
|
||||
* @param ringSize 环形缓存大小
|
||||
*/
|
||||
RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize = RTP_GOP_SIZE);
|
||||
RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, const std::string &schema = RTSP_SCHEMA, int ringSize = RTP_GOP_SIZE);
|
||||
|
||||
~RtspMediaSourceImp() override = default;
|
||||
|
||||
|
|
@ -61,30 +60,14 @@ public:
|
|||
/**
|
||||
* _demuxer触发的添加Track事件
|
||||
*/
|
||||
bool addTrack(const Track::Ptr &track) override {
|
||||
if (_muxer) {
|
||||
if (_muxer->addTrack(track)) {
|
||||
track->addDelegate(_muxer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool addTrack(const Track::Ptr &track) override;
|
||||
|
||||
/**
|
||||
* _demuxer触发的Track添加完毕事件
|
||||
*/
|
||||
void addTrackCompleted() override {
|
||||
if (_muxer) {
|
||||
_muxer->addTrackCompleted();
|
||||
}
|
||||
}
|
||||
void addTrackCompleted() override;
|
||||
|
||||
void resetTracks() override {
|
||||
if (_muxer) {
|
||||
_muxer->resetTracks();
|
||||
}
|
||||
}
|
||||
void resetTracks() override;
|
||||
|
||||
/**
|
||||
* _muxer触发的所有Track就绪的事件
|
||||
|
|
@ -97,20 +80,12 @@ public:
|
|||
* 设置事件监听器
|
||||
* @param listener 监听器
|
||||
*/
|
||||
void setListener(const std::weak_ptr<MediaSourceEvent> &listener) override{
|
||||
if (_muxer) {
|
||||
//_muxer对象不能处理的事件再给listener处理
|
||||
_muxer->setMediaListener(listener);
|
||||
} else {
|
||||
//未创建_muxer对象,事件全部给listener处理
|
||||
MediaSource::setListener(listener);
|
||||
}
|
||||
}
|
||||
void setListener(const std::weak_ptr<MediaSourceEvent> &listener) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool _all_track_ready = false;
|
||||
ProtocolOption _option;
|
||||
RtspDemuxer::Ptr _demuxer;
|
||||
std::shared_ptr<RtspDemuxer> _demuxer;
|
||||
MultiMediaSourceMuxer::Ptr _muxer;
|
||||
};
|
||||
} /* namespace mediakit */
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace mediakit {
|
||||
|
||||
class RtspMediaSourceMuxer final : public RtspMuxer, public MediaSourceEventInterceptor,
|
||||
class RtspMediaSourceMuxer : public RtspMuxer, public MediaSourceEventInterceptor,
|
||||
public std::enable_shared_from_this<RtspMediaSourceMuxer> {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<RtspMediaSourceMuxer>;
|
||||
|
|
@ -25,9 +25,12 @@ public:
|
|||
const std::string &strApp,
|
||||
const std::string &strId,
|
||||
const ProtocolOption &option,
|
||||
const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title) {
|
||||
const TitleSdp::Ptr &title = nullptr,
|
||||
const std::string &schema = RTSP_SCHEMA
|
||||
): RtspMuxer(title) {
|
||||
_option = option;
|
||||
_media_src = std::make_shared<RtspMediaSource>(vhost,strApp,strId);
|
||||
_on_demand = schema == RTSP_SCHEMA ? option.rtsp_demand : option.rtc_demand;
|
||||
_media_src = std::make_shared<RtspMediaSource>(vhost, strApp, strId, schema);
|
||||
getRtpRing()->setDelegate(_media_src);
|
||||
}
|
||||
|
||||
|
|
@ -51,19 +54,19 @@ public:
|
|||
}
|
||||
|
||||
void onReaderChanged(MediaSource &sender, int size) override {
|
||||
_enabled = _option.rtsp_demand ? size : true;
|
||||
if (!size && _option.rtsp_demand) {
|
||||
_enabled = _on_demand ? size : true;
|
||||
if (!size && _on_demand) {
|
||||
_clear_cache = true;
|
||||
}
|
||||
MediaSourceEventInterceptor::onReaderChanged(sender, size);
|
||||
}
|
||||
|
||||
bool inputFrame(const Frame::Ptr &frame) override {
|
||||
if (_clear_cache && _option.rtsp_demand) {
|
||||
if (_clear_cache && _on_demand) {
|
||||
_clear_cache = false;
|
||||
_media_src->clearCache();
|
||||
}
|
||||
if (_enabled || !_option.rtsp_demand) {
|
||||
if (_enabled || !_on_demand) {
|
||||
return RtspMuxer::inputFrame(frame);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -71,12 +74,13 @@ public:
|
|||
|
||||
bool isEnabled() {
|
||||
//缓存尚未清空时,还允许触发inputFrame函数,以便及时清空缓存
|
||||
return _option.rtsp_demand ? (_clear_cache ? true : _enabled) : true;
|
||||
return _on_demand ? (_clear_cache ? true : _enabled) : true;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool _enabled = true;
|
||||
bool _clear_cache = false;
|
||||
bool _on_demand = false;
|
||||
ProtocolOption _option;
|
||||
RtspMediaSource::Ptr _media_src;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void WebRtcPusher::onRecvRtp(MediaTrack &track, const string &rid, RtpPacket::Pt
|
|||
auto &src = _push_src_sim[rid];
|
||||
if (!src) {
|
||||
auto stream_id = rid.empty() ? _push_src->getId() : _push_src->getId() + "_" + rid;
|
||||
auto src_imp = std::make_shared<RtspMediaSourceImp>(_push_src->getVhost(), _push_src->getApp(), stream_id);
|
||||
auto src_imp = std::make_shared<RtspMediaSourceImp>(_push_src->getVhost(), _push_src->getApp(), stream_id, _push_src->getSchema());
|
||||
_push_src_sim_ownership[rid] = src_imp->getOwnership();
|
||||
src_imp->setSdp(_push_src->getSdp());
|
||||
src_imp->setProtocolOption(_push_src->getProtocolOption());
|
||||
|
|
|
|||
|
|
@ -1161,10 +1161,10 @@ void push_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||
cb(WebRtcException(SockException(Err_other, err)));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string schema = RTC_SCHEMA;
|
||||
RtspMediaSourceImp::Ptr push_src;
|
||||
std::shared_ptr<void> push_src_ownership;
|
||||
auto src = MediaSource::find(RTSP_SCHEMA, info._vhost, info._app, info._streamid);
|
||||
auto src = MediaSource::find(schema, info._vhost, info._app, info._streamid);
|
||||
auto push_failed = (bool)src;
|
||||
|
||||
while (src) {
|
||||
|
|
@ -1191,7 +1191,7 @@ void push_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||
}
|
||||
|
||||
if (!push_src) {
|
||||
push_src = std::make_shared<RtspMediaSourceImp>(info._vhost, info._app, info._streamid);
|
||||
push_src = std::make_shared<RtspMediaSourceImp>(info._vhost, info._app, info._streamid, schema);
|
||||
push_src_ownership = push_src->getOwnership();
|
||||
push_src->setProtocolOption(option);
|
||||
}
|
||||
|
|
@ -1218,9 +1218,8 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||
cb(WebRtcException(SockException(Err_other, err)));
|
||||
return;
|
||||
}
|
||||
|
||||
// webrtc播放的是rtsp的源
|
||||
info._schema = RTSP_SCHEMA;
|
||||
info._schema = RTC_SCHEMA;
|
||||
MediaSource::findAsync(info, session_ptr, [=](const MediaSource::Ptr &src_in) mutable {
|
||||
auto src = dynamic_pointer_cast<RtspMediaSource>(src_in);
|
||||
if (!src) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue