From fbe159db0e1d44797976986c78b67f85c865fc5a Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Fri, 8 Dec 2023 21:45:24 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3rdpart/CMakeLists.txt | 6 +- CMakeLists.txt | 1 - api/source/mk_common.cpp | 4 +- api/source/mk_player.cpp | 1 - api/source/mk_tcp_private.h | 5 +- api/source/mk_thread.cpp | 4 - api/source/mk_track.cpp | 20 +-- conf/config.ini | 9 ++ server/Process.cpp | 4 +- server/WebApi.h | 6 - server/WebHook.cpp | 2 +- server/main.cpp | 12 +- src/Codec/Transcode.h | 2 - src/Common/Device.h | 1 - src/Common/JemallocUtil.h | 3 - src/Common/MediaSink.cpp | 3 +- src/Common/MediaSink.h | 17 +- src/Common/MediaSource.h | 6 - src/Common/MultiMediaSourceMuxer.h | 2 - src/Common/PacketCache.h | 10 +- src/Common/Parser.cpp | 1 - src/Common/Parser.h | 7 - src/Common/Stamp.h | 12 +- src/Common/config.cpp | 4 + src/Common/config.h | 4 + src/Common/macros.h | 1 - src/Extension/AAC.cpp | 99 ++++++------ src/Extension/AAC.h | 25 ++- src/Extension/AACRtmp.cpp | 88 ++--------- src/Extension/AACRtmp.h | 28 +--- src/Extension/AACRtp.cpp | 70 ++------- src/Extension/AACRtp.h | 31 +--- src/Extension/CommonRtmp.cpp | 38 ++--- src/Extension/CommonRtmp.h | 24 +-- src/Extension/CommonRtp.cpp | 13 +- src/Extension/CommonRtp.h | 22 +-- src/Extension/Factory.cpp | 68 ++++---- src/Extension/Factory.h | 21 ++- src/Extension/Frame.cpp | 18 ++- src/Extension/Frame.h | 17 +- src/Extension/G711.cpp | 28 ++-- src/Extension/G711.h | 4 +- src/Extension/G711Rtp.cpp | 8 +- src/Extension/G711Rtp.h | 13 +- src/Extension/H264.cpp | 126 ++++++++++----- src/Extension/H264.h | 27 +--- src/Extension/H264Rtmp.cpp | 167 ++++---------------- src/Extension/H264Rtmp.h | 30 +--- src/Extension/H264Rtp.cpp | 14 +- src/Extension/H264Rtp.h | 22 +-- src/Extension/H265.cpp | 97 +++++++----- src/Extension/H265.h | 20 +-- src/Extension/H265Rtmp.cpp | 242 ++++++++--------------------- src/Extension/H265Rtmp.h | 23 +-- src/Extension/H265Rtp.cpp | 20 +-- src/Extension/H265Rtp.h | 21 +-- src/Extension/JPEG.cpp | 7 +- src/Extension/JPEG.h | 27 ++-- src/Extension/JPEGRtp.cpp | 20 +-- src/Extension/JPEGRtp.h | 11 +- src/Extension/L16.cpp | 31 ++-- src/Extension/L16.h | 4 +- src/Extension/Opus.cpp | 20 +-- src/Extension/Opus.h | 6 +- src/Extension/Track.h | 84 +++++++--- src/FMP4/FMP4MediaSource.h | 1 - src/Http/HlsParser.h | 3 - src/Http/HlsPlayer.h | 3 - src/Http/HttpBody.cpp | 1 - src/Http/HttpBody.h | 6 - src/Http/HttpClient.cpp | 2 +- src/Http/HttpClient.h | 6 - src/Http/HttpClientImp.h | 2 - src/Http/HttpCookie.h | 3 - src/Http/HttpCookieManager.h | 2 - src/Http/HttpDownloader.h | 1 - src/Http/HttpFileManager.cpp | 2 - src/Http/HttpFileManager.h | 2 - src/Http/HttpRequestSplitter.cpp | 12 +- src/Http/HttpRequestSplitter.h | 8 +- src/Http/HttpRequester.h | 3 - src/Http/HttpSession.cpp | 37 +++-- src/Http/HttpSession.h | 7 +- src/Http/HttpTSPlayer.h | 1 - src/Http/TsPlayer.h | 1 - src/Http/TsPlayerImp.h | 1 - src/Http/WebSocketClient.h | 4 +- src/Http/WebSocketSession.h | 5 - src/Http/WebSocketSplitter.h | 6 +- src/Player/MediaPlayer.h | 1 - src/Player/PlayerBase.h | 2 - src/Player/PlayerProxy.cpp | 7 +- src/Pusher/MediaPusher.cpp | 2 - src/Pusher/MediaPusher.h | 2 - src/Pusher/PusherBase.h | 1 - src/Record/HlsMediaSource.h | 1 - src/Record/HlsRecorder.h | 2 - src/Record/MP4.cpp | 4 +- src/Record/MP4.h | 9 +- src/Record/MP4Demuxer.cpp | 96 ++++-------- src/Record/MP4Demuxer.h | 4 - src/Record/MP4Muxer.cpp | 185 ++++------------------ src/Record/MP4Muxer.h | 13 +- src/Record/MP4Reader.cpp | 14 +- src/Record/MP4Reader.h | 8 +- src/Record/MPEG.h | 1 - src/Record/Recorder.cpp | 8 +- src/Rtcp/Rtcp.cpp | 2 - src/Rtmp/FlvMuxer.h | 2 - src/Rtmp/FlvPlayer.h | 1 - src/Rtmp/FlvSplitter.h | 4 - src/Rtmp/Rtmp.cpp | 39 +---- src/Rtmp/Rtmp.h | 55 ++++--- src/Rtmp/RtmpCodec.h | 25 ++- src/Rtmp/RtmpDemuxer.cpp | 8 +- src/Rtmp/RtmpDemuxer.h | 3 - src/Rtmp/RtmpMediaSourceImp.cpp | 11 +- src/Rtmp/RtmpMediaSourceImp.h | 2 - src/Rtmp/RtmpMuxer.cpp | 27 ++-- src/Rtmp/RtmpMuxer.h | 1 - src/Rtmp/RtmpProtocol.cpp | 2 - src/Rtmp/RtmpSession.cpp | 2 - src/Rtmp/RtmpSession.h | 1 - src/Rtp/Decoder.h | 3 +- src/Rtp/GB28181Process.cpp | 2 - src/Rtp/GB28181Process.h | 1 - src/Rtp/PSEncoder.cpp | 16 +- src/Rtp/PSEncoder.h | 2 +- src/Rtp/ProcessInterface.h | 1 - src/Rtp/RawEncoder.cpp | 23 ++- src/Rtp/RtpCache.h | 3 - src/Rtp/RtpProcess.cpp | 2 +- src/Rtp/RtpSelector.h | 4 - src/Rtp/RtpSender.cpp | 2 +- src/Rtp/RtpServer.h | 1 - src/Rtp/RtpSession.cpp | 68 ++++---- src/Rtp/RtpSplitter.h | 4 - src/Rtp/TSDecoder.h | 1 - src/Rtsp/RtpCodec.h | 33 ++-- src/Rtsp/RtpMultiCaster.h | 1 - src/Rtsp/RtpReceiver.h | 10 +- src/Rtsp/Rtsp.h | 7 +- src/Rtsp/RtspDemuxer.h | 2 - src/Rtsp/RtspMediaSourceImp.h | 2 - src/Rtsp/RtspMuxer.cpp | 68 +++++--- src/Rtsp/RtspMuxer.h | 4 +- src/Rtsp/RtspPlayer.cpp | 2 +- src/Rtsp/RtspSession.cpp | 18 +-- src/Rtsp/RtspSession.h | 1 - src/Rtsp/RtspSplitter.cpp | 9 +- src/Rtsp/RtspSplitter.h | 3 - src/Shell/ShellCMD.h | 2 - src/Shell/ShellSession.cpp | 2 - src/Shell/ShellSession.h | 1 - src/TS/TSMediaSource.h | 1 - srt/SrtSession.cpp | 2 - srt/SrtSession.hpp | 1 - webrtc/Nack.h | 4 - webrtc/RtpExt.h | 2 - webrtc/TwccContext.h | 3 - webrtc/WebRtcEchoTest.h | 1 - webrtc/WebRtcPlayer.h | 1 - webrtc/WebRtcPusher.h | 1 - webrtc/WebRtcSession.cpp | 2 - webrtc/WebRtcSession.h | 1 - webrtc/WebRtcTransport.cpp | 118 +++++++++++++- webrtc/WebRtcTransport.h | 12 +- 167 files changed, 1075 insertions(+), 1817 deletions(-) diff --git a/3rdpart/CMakeLists.txt b/3rdpart/CMakeLists.txt index 5fc879e0..f55fc6c7 100644 --- a/3rdpart/CMakeLists.txt +++ b/3rdpart/CMakeLists.txt @@ -47,7 +47,7 @@ set(MediaServer_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/media-server") # TODO: 补一个函数处理各种库 # 添加 mov、flv 库用于 MP4 录制 -if (ENABLE_MP4 OR ENABLE_HLS_FMP4) +if (ENABLE_MP4) # MOV set(MediaServer_MOV_ROOT ${MediaServer_ROOT}/libmov) aux_source_directory(${MediaServer_MOV_ROOT}/include MOV_SRC_LIST) @@ -80,10 +80,6 @@ if (ENABLE_MP4 OR ENABLE_HLS_FMP4) message(STATUS "ENABLE_MP4 defined") update_cached_list(MK_COMPILE_DEFINITIONS ENABLE_MP4) endif () - if (ENABLE_HLS_FMP4) - message(STATUS "ENABLE_HLS_FMP4 defined") - update_cached_list(MK_COMPILE_DEFINITIONS ENABLE_HLS_FMP4) - endif () endif () # 添加 mpeg 用于支持 ts 生成 diff --git a/CMakeLists.txt b/CMakeLists.txt index 22afa0dd..ec958e43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,6 @@ option(ENABLE_JEMALLOC_STATIC "Enable static linking to the jemalloc library" OF option(ENABLE_JEMALLOC_DUMP "Enable jemalloc to dump malloc statistics" OFF) option(ENABLE_MEM_DEBUG "Enable Memory Debug" OFF) option(ENABLE_MP4 "Enable MP4" ON) -option(ENABLE_HLS_FMP4 "Enable HLS-FMP4" ON) option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" ON) option(ENABLE_MYSQL "Enable MySQL" OFF) option(ENABLE_OPENSSL "Enable OpenSSL" ON) diff --git a/api/source/mk_common.cpp b/api/source/mk_common.cpp index a45068ce..689b57d2 100644 --- a/api/source/mk_common.cpp +++ b/api/source/mk_common.cpp @@ -280,7 +280,6 @@ API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port) { class WebRtcArgsUrl : public mediakit::WebRtcArgs { public: WebRtcArgsUrl(std::string url) { _url = std::move(url); } - ~WebRtcArgsUrl() = default; toolkit::variant operator[](const std::string &key) const override { if (key == "url") { @@ -305,7 +304,8 @@ API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(void *user_data, on_user_data auto session = std::make_shared(Socket::createSocket()); std::string offer_str = offer; std::shared_ptr ptr(user_data, user_data_free ? user_data_free : [](void *) {}); - WebRtcPluginManager::Instance().getAnswerSdp(*session, type, WebRtcArgsUrl(url), + auto args = std::make_shared(url); + WebRtcPluginManager::Instance().getAnswerSdp(*session, type, *args, [offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable { try { auto sdp_answer = exchangeSdp(exchanger, offer_str); diff --git a/api/source/mk_player.cpp b/api/source/mk_player.cpp index 82adc411..87cbcd3c 100755 --- a/api/source/mk_player.cpp +++ b/api/source/mk_player.cpp @@ -24,7 +24,6 @@ public: MediaPlayerForC(){ _player = std::make_shared(); } - ~MediaPlayerForC() = default; MediaPlayer *operator->(){ return _player.get(); diff --git a/api/source/mk_tcp_private.h b/api/source/mk_tcp_private.h index e569ca16..c2a6d113 100644 --- a/api/source/mk_tcp_private.h +++ b/api/source/mk_tcp_private.h @@ -33,9 +33,8 @@ private: class SessionForC : public toolkit::Session { public: - SessionForC(const toolkit::Socket::Ptr &pSock) ; - ~SessionForC() override = default; - void onRecv(const toolkit::Buffer::Ptr &buffer) override ; + SessionForC(const toolkit::Socket::Ptr &pSock); + void onRecv(const toolkit::Buffer::Ptr &buffer) override; void onError(const toolkit::SockException &err) override; void onManager() override; std::shared_ptr _user_data; diff --git a/api/source/mk_thread.cpp b/api/source/mk_thread.cpp index 29775b43..9614dab6 100644 --- a/api/source/mk_thread.cpp +++ b/api/source/mk_thread.cpp @@ -80,8 +80,6 @@ public: _user_data = std::move(user_data); } - ~TimerForC() = default; - uint64_t operator()(){ lock_guard lck(_mxt); if(!_cb){ @@ -135,8 +133,6 @@ API_EXPORT void API_CALL mk_timer_release(mk_timer ctx){ class WorkThreadPoolForC : public TaskExecutorGetterImp { public: - ~WorkThreadPoolForC() override = default; - WorkThreadPoolForC(const char *name, size_t n_thread, int priority) { //最低优先级 addPoller(name, n_thread, (ThreadPool::Priority) priority, false); diff --git a/api/source/mk_track.cpp b/api/source/mk_track.cpp index d20b01d0..aaef0caa 100644 --- a/api/source/mk_track.cpp +++ b/api/source/mk_track.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). @@ -27,8 +27,6 @@ public: } } - ~VideoTrackForC() override = default; - int getVideoHeight() const override { return _args.video.height; } @@ -45,16 +43,16 @@ public: return _codec_id; } - bool ready() override { + bool ready() const override { return true; } - Track::Ptr clone() override { - auto track_in = std::shared_ptr(shared_from_this()); + Track::Ptr clone() const override { + auto track_in = std::shared_ptr(const_cast(this)->shared_from_this()); return Factory::getTrackByAbstractTrack(track_in); } - Sdp::Ptr getSdp() override { + Sdp::Ptr getSdp(uint8_t) const override { return nullptr; } @@ -65,17 +63,15 @@ private: class AudioTrackForC : public AudioTrackImp, public std::enable_shared_from_this { public: - ~AudioTrackForC() override = default; - AudioTrackForC(int codec_id, codec_args *args) : AudioTrackImp((CodecId) codec_id, args->audio.sample_rate, args->audio.channels, 16) {} - Track::Ptr clone() override { - auto track_in = std::shared_ptr(shared_from_this()); + Track::Ptr clone() const override { + auto track_in = std::shared_ptr(const_cast(this)->shared_from_this()); return Factory::getTrackByAbstractTrack(track_in); } - Sdp::Ptr getSdp() override { + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } }; diff --git a/conf/config.ini b/conf/config.ini index af8f071a..d1d8246c 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -286,6 +286,10 @@ keepAliveSecond=15 port=1935 #rtmps服务器监听地址 sslport=0 +# rtmp是否直接代理模式 +directProxy=1 +#h265 rtmp打包采用增强型rtmp标准还是国内拓展标准 +enhanced=1 [rtp] #音频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400 @@ -347,6 +351,11 @@ preferredCodecA=PCMU,PCMA,opus,mpeg4-generic #以下范例为所有支持的视频codec preferredCodecV=H264,H265,AV1,VP9,VP8 +#webrtc比特率设置 +start_bitrate=0 +max_bitrate=0 +min_bitrate=0 + [srt] #srt播放推流、播放超时时间,单位秒 timeoutSec=5 diff --git a/server/Process.cpp b/server/Process.cpp index 0f7bc14d..bfb60c92 100644 --- a/server/Process.cpp +++ b/server/Process.cpp @@ -157,12 +157,12 @@ void Process::run(const string &cmd, string log_file) { WarnL << "clone process failed:" << get_uv_errmsg(); free(_process_stack); _process_stack = nullptr; - throw std::runtime_error(StrPrinter << "fork child process failed,err:" << get_uv_errmsg()); + throw std::runtime_error(StrPrinter << "clone child process failed, cmd: " << cmd << ",err:" << get_uv_errmsg()); } #else _pid = fork(); if (_pid == -1) { - throw std::runtime_error(StrPrinter << "fork child process failed,err:" << get_uv_errmsg()); + throw std::runtime_error(StrPrinter << "fork child process failed, cmd: " << cmd << ",err:" << get_uv_errmsg()); } if (_pid == 0) { //子进程 diff --git a/server/WebApi.h b/server/WebApi.h index 346a6767..1294cc1d 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -53,7 +53,6 @@ public: ApiRetException(const char *str = "success" ,int code = API::Success):runtime_error(str){ _code = code; } - ~ApiRetException() = default; int code(){ return _code; } private: int _code; @@ -62,19 +61,16 @@ private: class AuthException : public ApiRetException { public: AuthException(const char *str):ApiRetException(str,API::AuthFailed){} - ~AuthException() = default; }; class InvalidArgsException: public ApiRetException { public: InvalidArgsException(const char *str):ApiRetException(str,API::InvalidArgs){} - ~InvalidArgsException() = default; }; class SuccessException: public ApiRetException { public: SuccessException():ApiRetException("success",API::Success){} - ~SuccessException() = default; }; using ApiArgsType = std::map; @@ -155,8 +151,6 @@ public: } } - ~HttpAllArgs() = default; - template toolkit::variant operator[](const Key &key) const { return (toolkit::variant)_get_value(*(HttpAllArgs*)this, key); diff --git a/server/WebHook.cpp b/server/WebHook.cpp index f0e68972..8a02e41d 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -174,7 +174,7 @@ void do_http_hook(const string &url, const ArgsType &body, const function(body)["mediaServerId"] = mediaServerId; - const_cast(body)["hook_index"] = s_hook_index++; + const_cast(body)["hook_index"] = (Json::UInt64)(s_hook_index++); auto requester = std::make_shared(); requester->setMethod("POST"); diff --git a/server/main.cpp b/server/main.cpp index d79c78e5..f48ea620 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -203,11 +203,6 @@ public: "日志保存文件夹路径",/*该选项说明文字*/ nullptr); } - - ~CMD_main() override{} - const char *description() const override{ - return "主程序命令参数"; - } }; //全局变量,在WebApi中用于保存配置文件用 @@ -264,13 +259,13 @@ int start_main(int argc,char *argv[]) { loadIniConfig(g_ini_file.data()); if (!File::is_dir(ssl_file)) { - //不是文件夹,加载证书,证书包含公钥和私钥 + // 不是文件夹,加载证书,证书包含公钥和私钥 SSL_Initor::Instance().loadCertificate(ssl_file.data()); } else { //加载文件夹下的所有证书 - File::scanDir(ssl_file, [](const string &path, bool isDir) { + File::scanDir(ssl_file,[](const string &path, bool isDir){ if (!isDir) { - //最后的一个证书会当做默认证书(客户端ssl握手时未指定主机) + // 最后的一个证书会当做默认证书(客户端ssl握手时未指定主机) SSL_Initor::Instance().loadCertificate(path.data()); } return true; @@ -290,6 +285,7 @@ int start_main(int argc,char *argv[]) { //如果需要调用getSnap和addFFmpegSource接口,可以关闭cpu亲和性 EventPollerPool::setPoolSize(threads); + WorkThreadPool::setPoolSize(threads); EventPollerPool::enableCpuAffinity(affinity); //简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象 diff --git a/src/Codec/Transcode.h b/src/Codec/Transcode.h index 8c33b711..fb58c691 100644 --- a/src/Codec/Transcode.h +++ b/src/Codec/Transcode.h @@ -65,7 +65,6 @@ private: class TaskManager { public: - TaskManager() = default; virtual ~TaskManager(); void setMaxTaskSize(size_t size); @@ -84,7 +83,6 @@ private: class ThreadExitException : public std::runtime_error { public: ThreadExitException() : std::runtime_error("exit") {} - ~ThreadExitException() = default; }; private: diff --git a/src/Common/Device.h b/src/Common/Device.h index cb99657d..2a0ba3bb 100644 --- a/src/Common/Device.h +++ b/src/Common/Device.h @@ -49,7 +49,6 @@ public: //fDuration<=0为直播,否则为点播 DevChannel(const MediaTuple& tuple, float duration = 0, const ProtocolOption &option = ProtocolOption()) : MultiMediaSourceMuxer(tuple, duration, option) {} - ~DevChannel() override = default; /** * 初始化视频Track diff --git a/src/Common/JemallocUtil.h b/src/Common/JemallocUtil.h index 71f7722b..b0f921f0 100644 --- a/src/Common/JemallocUtil.h +++ b/src/Common/JemallocUtil.h @@ -16,9 +16,6 @@ namespace mediakit { class JemallocUtil { public: - JemallocUtil() = default; - ~JemallocUtil() = default; - static void enable_profiling(); static void disable_profiling(); diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index d90d5798..25c53327 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -205,7 +205,6 @@ class FrameFromStaticPtr : public FrameFromPtr { public: template FrameFromStaticPtr(ARGS &&...args) : FrameFromPtr(std::forward(args)...) {}; - ~FrameFromStaticPtr() override = default; bool cacheAble() const override { return true; @@ -260,7 +259,7 @@ bool MediaSink::addMuteAudioTrack() { if (_track_map.find(TrackAudio) != _track_map.end()) { return false; } - auto audio = std::make_shared(makeAacConfig(MUTE_ADTS_DATA, ADTS_HEADER_LEN)); + auto audio = std::make_shared(MUTE_ADTS_DATA, ADTS_HEADER_LEN); _track_map[audio->getTrackType()] = std::make_pair(audio, true); audio->addDelegate([this](const Frame::Ptr &frame) { return onTrackFrame(frame); diff --git a/src/Common/MediaSink.h b/src/Common/MediaSink.h index ea207bae..8afcbc82 100644 --- a/src/Common/MediaSink.h +++ b/src/Common/MediaSink.h @@ -21,7 +21,6 @@ namespace mediakit{ class TrackListener { public: - TrackListener() = default; virtual ~TrackListener() = default; /** @@ -45,9 +44,6 @@ public: class MediaSinkInterface : public FrameWriterInterface, public TrackListener { public: using Ptr = std::shared_ptr; - - MediaSinkInterface() = default; - ~MediaSinkInterface() override = default; }; /** @@ -56,8 +52,6 @@ public: class MuteAudioMaker : public FrameDispatcher { public: using Ptr = std::shared_ptr; - MuteAudioMaker() = default; - ~MuteAudioMaker() override = default; bool inputFrame(const Frame::Ptr &frame) override; private: @@ -71,9 +65,6 @@ private: class MediaSink : public MediaSinkInterface, public TrackSource{ public: using Ptr = std::shared_ptr; - MediaSink() = default; - ~MediaSink() override = default; - /** * 输入frame * @param frame @@ -112,7 +103,7 @@ public: std::vector getTracks(bool trackReady = true) const override; /** - * 返回是否所有track已经准备完成 + * 判断是否已经触发onAllTrackReady事件 */ bool isAllTrackReady() const; @@ -188,9 +179,6 @@ private: class MediaSinkDelegate : public MediaSink { public: - MediaSinkDelegate() = default; - ~MediaSinkDelegate() override = default; - /** * 设置track监听器 */ @@ -207,9 +195,6 @@ private: class Demuxer : protected TrackListener, public TrackSource { public: - Demuxer() = default; - ~Demuxer() override = default; - void setTrackListener(TrackListener *listener, bool wait_track_ready = false); std::vector getTracks(bool trackReady = true) const override; diff --git a/src/Common/MediaSource.h b/src/Common/MediaSource.h index 9aba7df4..a9a9cd2d 100644 --- a/src/Common/MediaSource.h +++ b/src/Common/MediaSource.h @@ -50,10 +50,8 @@ public: public: template NotImplemented(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~NotImplemented() override = default; }; - MediaSourceEvent() = default; virtual ~MediaSourceEvent() = default; // 获取媒体源类型 @@ -254,9 +252,6 @@ private: //该对象用于拦截感兴趣的MediaSourceEvent事件 class MediaSourceEventInterceptor : public MediaSourceEvent { public: - MediaSourceEventInterceptor() = default; - ~MediaSourceEventInterceptor() override = default; - void setDelegate(const std::weak_ptr &listener); std::shared_ptr getDelegate() const; @@ -289,7 +284,6 @@ private: */ class MediaInfo: public MediaTuple { public: - ~MediaInfo() = default; MediaInfo() = default; MediaInfo(const std::string &url) { parse(url); } void parse(const std::string &url); diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index 7e0708fd..74808379 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -32,13 +32,11 @@ public: class Listener { public: - Listener() = default; virtual ~Listener() = default; virtual void onAllTrackReady() = 0; }; MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_sec = 0.0,const ProtocolOption &option = ProtocolOption()); - ~MultiMediaSourceMuxer() override = default; /** * 设置事件监听器 diff --git a/src/Common/PacketCache.h b/src/Common/PacketCache.h index fd9032a1..43bcf359 100644 --- a/src/Common/PacketCache.h +++ b/src/Common/PacketCache.h @@ -18,9 +18,6 @@ namespace mediakit { /// 缓存刷新策略类 class FlushPolicy { public: - FlushPolicy() = default; - ~FlushPolicy() = default; - bool isFlushAble(bool is_video, bool is_key, uint64_t new_stamp, size_t cache_size); private: @@ -79,13 +76,8 @@ private: // 但是却对性能提升很大,这样做还是比较划算的 GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); - GET_CONFIG(int, rtspLowLatency, Rtsp::kLowLatency); - if (std::is_same::value && rtspLowLatency) { - return true; - } - - return std::is_same::value ? false : (mergeWriteMS <= 0); + return std::is_same::value ? rtspLowLatency : (mergeWriteMS <= 0); } private: diff --git a/src/Common/Parser.cpp b/src/Common/Parser.cpp index 15636c33..09c7839d 100644 --- a/src/Common/Parser.cpp +++ b/src/Common/Parser.cpp @@ -293,7 +293,6 @@ void RtspUrl::setup(bool is_ssl, const string &url, const string &user, const st uint16_t port = is_ssl ? 322 : 554; splitUrl(ip, ip, port); - _url = std::move(url); _user = strCoding::UrlDecode(std::move(user)); _passwd = strCoding::UrlDecode(std::move(passwd)); diff --git a/src/Common/Parser.h b/src/Common/Parser.h index a2165ce1..17d075dc 100644 --- a/src/Common/Parser.h +++ b/src/Common/Parser.h @@ -31,8 +31,6 @@ struct StrCaseCompare { class StrCaseMap : public std::multimap { public: using Super = multimap; - StrCaseMap() = default; - ~StrCaseMap() = default; std::string &operator[](const std::string &k) { auto it = find(k); @@ -60,9 +58,6 @@ public: // rtsp/http/sip解析类 class Parser { public: - Parser() = default; - ~Parser() = default; - // 解析http/rtsp/sip请求,需要确保buf以\0结尾 void parse(const char *buf, size_t size); @@ -132,8 +127,6 @@ public: std::string _host; public: - RtspUrl() = default; - ~RtspUrl() = default; void parse(const std::string &url); private: diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index 243c250c..8344a77b 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -17,10 +17,10 @@ namespace mediakit { -class DeltaStamp{ +class DeltaStamp { public: DeltaStamp(); - ~DeltaStamp() = default; + virtual ~DeltaStamp() = default; /** * 计算时间戳增量 @@ -48,9 +48,6 @@ protected: //计算相对时间戳或者产生平滑时间戳 class Stamp : public DeltaStamp{ public: - Stamp() = default; - ~Stamp() = default; - /** * 求取相对时间戳,同时实现了音视频同步、限制dts回退等功能 * @param dts 输入dts,如果为0则根据系统时间戳生成 @@ -116,8 +113,6 @@ private: //pts排序后就是dts class DtsGenerator{ public: - DtsGenerator() = default; - ~DtsGenerator() = default; bool getDts(uint64_t pts, uint64_t &dts); private: @@ -136,9 +131,6 @@ private: class NtpStamp { public: - NtpStamp() = default; - ~NtpStamp() = default; - void setNtpStamp(uint32_t rtp_stamp, uint64_t ntp_stamp_ms); uint64_t getNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate); diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 2a7b1432..f7f47bcb 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -235,10 +235,14 @@ namespace Rtmp { #define RTMP_FIELD "rtmp." const string kHandshakeSecond = RTMP_FIELD "handshakeSecond"; const string kKeepAliveSecond = RTMP_FIELD "keepAliveSecond"; +const string kDirectProxy = RTMP_FIELD "directProxy"; +const string kEnhanced = RTMP_FIELD "enhanced"; static onceToken token([]() { mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15; + mINI::Instance()[kDirectProxy] = 1; + mINI::Instance()[kEnhanced] = 1; }); } // namespace Rtmp diff --git a/src/Common/config.h b/src/Common/config.h index 65bd3715..578b86a6 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -297,6 +297,10 @@ namespace Rtmp { extern const std::string kHandshakeSecond; // 维持链接超时时间,默认15秒 extern const std::string kKeepAliveSecond; +// 是否直接代理 +extern const std::string kDirectProxy; +// h265-rtmp是否采用增强型(或者国内扩展) +extern const std::string kEnhanced; } // namespace Rtmp ////////////RTP配置/////////// diff --git a/src/Common/macros.h b/src/Common/macros.h index cc31202e..8e014489 100644 --- a/src/Common/macros.h +++ b/src/Common/macros.h @@ -75,7 +75,6 @@ class AssertFailedException : public std::runtime_error { public: template AssertFailedException(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~AssertFailedException() override = default; }; extern const char kServerName[]; diff --git a/src/Extension/AAC.cpp b/src/Extension/AAC.cpp index 27f18359..8aa14448 100644 --- a/src/Extension/AAC.cpp +++ b/src/Extension/AAC.cpp @@ -205,39 +205,31 @@ public: /** * 构造函数 * @param aac_cfg aac两个字节的配置描述 + * @param payload_type rtp payload type * @param sample_rate 音频采样率 - * @param payload_type rtp payload type 默认98 + * @param channels 通道数 * @param bitrate 比特率 */ - AACSdp(const string &aac_cfg, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type){ + AACSdp(const string &aac_cfg, int payload_type, int sample_rate, int channels, int bitrate) + : Sdp(sample_rate, payload_type) { _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecAAC) << "/" << sample_rate << "/" << channels << "\r\n"; string configStr; - char buf[4] = {0}; - for(auto &ch : aac_cfg){ + char buf[4] = { 0 }; + for (auto &ch : aac_cfg) { snprintf(buf, sizeof(buf), "%02X", (uint8_t)ch); configStr.append(buf); } _printer << "a=fmtp:" << payload_type << " streamtype=5;profile-level-id=1;mode=AAC-hbr;" << "sizelength=13;indexlength=3;indexdeltalength=3;config=" << configStr << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; } - string getSdp() const override { - return _printer; - } + string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecAAC; - } private: _StrPrinter _printer; }; @@ -249,18 +241,16 @@ AACTrack::AACTrack(const string &aac_cfg) { throw std::invalid_argument("adts配置必须最少2个字节"); } _cfg = aac_cfg; - onReady(); + update(); } -const string &AACTrack::getConfig() const { - return _cfg; -} +AACTrack::AACTrack(const uint8_t *adts, size_t size) : AACTrack(makeAacConfig(adts, size)) {} CodecId AACTrack::getCodecId() const { return CodecAAC; } -bool AACTrack::ready() { +bool AACTrack::ready() const { return !_cfg.empty(); } @@ -276,9 +266,23 @@ int AACTrack::getAudioChannel() const { return _channel; } +static Frame::Ptr addADTSHeader(const Frame::Ptr &frame_in, const std::string &aac_config) { + auto frame = FrameImp::create(); + frame->_codec_id = CodecAAC; + // 生成adts头 + char adts_header[32] = { 0 }; + auto size = dumpAacConfig(aac_config, frame_in->size(), (uint8_t *)adts_header, sizeof(adts_header)); + CHECK(size > 0, "Invalid adts config"); + frame->_prefix_size = size; + frame->_dts = frame_in->dts(); + frame->_buffer.assign(adts_header, size); + frame->_buffer.append(frame_in->data(), frame_in->size()); + return frame; +} + bool AACTrack::inputFrame(const Frame::Ptr &frame) { if (!frame->prefixSize()) { - return inputFrame_l(frame); + return inputFrame_l(addADTSHeader(frame, getExtraData()->toString())); } bool ret = false; @@ -289,14 +293,14 @@ bool AACTrack::inputFrame(const Frame::Ptr &frame) { auto ptr = frame->data(); auto end = frame->data() + frame->size(); while (ptr < end) { - auto frame_len = getAacFrameLength((uint8_t *) ptr, end - ptr); + auto frame_len = getAacFrameLength((uint8_t *)ptr, end - ptr); if (frame_len < ADTS_HEADER_LEN) { break; } if (frame_len == (int)frame->size()) { return inputFrame_l(frame); } - auto sub_frame = std::make_shared >(frame, (char *) ptr, frame_len, ADTS_HEADER_LEN,dts,pts); + auto sub_frame = std::make_shared>(frame, (char *)ptr, frame_len, ADTS_HEADER_LEN, dts, pts); ptr += frame_len; if (ptr > end) { WarnL << "invalid aac length in adts header: " << frame_len @@ -307,52 +311,51 @@ bool AACTrack::inputFrame(const Frame::Ptr &frame) { if (inputFrame_l(sub_frame)) { ret = true; } - dts += 1024*1000/getAudioSampleRate(); - pts += 1024*1000/getAudioSampleRate(); + dts += 1024 * 1000 / getAudioSampleRate(); + pts += 1024 * 1000 / getAudioSampleRate(); } return ret; } bool AACTrack::inputFrame_l(const Frame::Ptr &frame) { - if (_cfg.empty()) { - //未获取到aac_cfg信息 - if (frame->prefixSize()) { - //根据7个字节的adts头生成aac config - _cfg = makeAacConfig((uint8_t *) (frame->data()), frame->prefixSize()); - onReady(); - } else { - WarnL << "无法获取adts头!"; - } + if (_cfg.empty() && frame->prefixSize()) { + // 未获取到aac_cfg信息,根据7个字节的adts头生成aac config + _cfg = makeAacConfig((uint8_t *)(frame->data()), frame->prefixSize()); + update(); } if (frame->size() > frame->prefixSize()) { - //除adts头外,有实际负载 + // 除adts头外,有实际负载 return AudioTrack::inputFrame(frame); } return false; } +toolkit::Buffer::Ptr AACTrack::getExtraData() const { + CHECK(ready()); + return std::make_shared(_cfg); +} + +void AACTrack::setExtraData(const uint8_t *data, size_t size) { + CHECK(size >= 2); + _cfg.assign((char *)data, size); + update(); +} + bool AACTrack::update() { return parseAacConfig(_cfg, _sampleRate, _channel); } -void AACTrack::onReady() { - if (!parseAacConfig(_cfg, _sampleRate, _channel)) { - _cfg.clear(); - } +Track::Ptr AACTrack::clone() const { + return std::make_shared(*this); } -Track::Ptr AACTrack::clone() { - return std::make_shared::type>(*this); -} - -Sdp::Ptr AACTrack::getSdp() { - if(!ready()){ +Sdp::Ptr AACTrack::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - update(); - return std::make_shared(getConfig(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); + return std::make_shared(getExtraData()->toString(), payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); } }//namespace mediakit \ No newline at end of file diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h index 32cf934b..fdbc5c75 100644 --- a/src/Extension/AAC.h +++ b/src/Extension/AAC.h @@ -17,47 +17,40 @@ namespace mediakit{ -std::string makeAacConfig(const uint8_t *hex, size_t length); -int getAacFrameLength(const uint8_t *hex, size_t length); int dumpAacConfig(const std::string &config, size_t length, uint8_t *out, size_t out_size); -bool parseAacConfig(const std::string &config, int &samplerate, int &channels); /** * aac音频通道 */ -class AACTrack : public AudioTrack{ +class AACTrack : public AudioTrack { public: using Ptr = std::shared_ptr; - /** - * 延后获取adts头信息 - * 在随后的inputFrame中获取adts头信息 - */ AACTrack() = default; /** - * 构造aac类型的媒体 - * @param aac_cfg aac配置信息 + * 通过aac extra data 构造对象 */ AACTrack(const std::string &aac_cfg); /** - * 获取aac 配置信息 + * 通过aac adts头 构造对象 */ - const std::string &getConfig() const; + AACTrack(const uint8_t *adts, size_t size); - bool ready() override; + bool ready() const override; CodecId getCodecId() const override; int getAudioChannel() const override; int getAudioSampleRate() const override; int getAudioSampleBit() const override; bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; bool update() override; private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; bool inputFrame_l(const Frame::Ptr &frame); private: diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index f1fdbab9..cf47de9d 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -16,90 +16,18 @@ using namespace toolkit; namespace mediakit { -static string getConfig(const RtmpPacket &thiz) { - string ret; - if ((RtmpAudioCodec)thiz.getRtmpCodecId() != RtmpAudioCodec::aac) { - return ret; - } - if (thiz.buffer.size() < 4) { - WarnL << "get aac config failed, rtmp packet is: " << hexdump(thiz.data(), thiz.size()); - return ret; - } - ret = thiz.buffer.substr(2); - return ret; -} - void AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { + CHECK(pkt->size() > 2); if (pkt->isConfigFrame()) { - _aac_cfg = getConfig(*pkt); - if (!_aac_cfg.empty()) { - onGetAAC(nullptr, 0, 0); - } + getTrack()->setExtraData((uint8_t *)pkt->data() + 2, pkt->size() - 2); return; } - - if (!_aac_cfg.empty()) { - onGetAAC(pkt->buffer.data() + 2, pkt->buffer.size() - 2, pkt->time_stamp); - } -} - -void AACRtmpDecoder::onGetAAC(const char* data, size_t len, uint32_t stamp) { - auto frame = FrameImp::create(); - frame->_codec_id = CodecAAC; - - //生成adts头 - char adts_header[32] = {0}; - auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header)); - if (size > 0) { - frame->_buffer.assign(adts_header, size); - frame->_prefix_size = size; - } else { - frame->_buffer.clear(); - frame->_prefix_size = 0; - } - - if(len > 0){ - //追加负载数据 - frame->_buffer.append(data, len); - frame->_dts = stamp; - } - - if(size > 0 || len > 0){ - //有adts头或者实际aac负载 - RtmpCodec::inputFrame(frame); - } + RtmpCodec::inputFrame(std::make_shared(CodecAAC, pkt->buffer.data() + 2, pkt->buffer.size() - 2, pkt->time_stamp)); } ///////////////////////////////////////////////////////////////////////////////////// -AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void AACRtmpEncoder::makeConfigPacket() { - if (_track && _track->ready()) { - //从track中和获取aac配置信息 - _aac_cfg = _track->getConfig(); - } - - if (!_aac_cfg.empty()) { - makeAudioConfigPkt(); - } -} - bool AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (_aac_cfg.empty()) { - if (frame->prefixSize()) { - // 包含adts头,从adts头获取aac配置信息 - _aac_cfg = makeAacConfig((uint8_t *)(frame->data()), frame->prefixSize()); - } - makeConfigPacket(); - } - - if (_aac_cfg.empty()) { - return false; - } - auto pkt = RtmpPacket::create(); // header pkt->buffer.push_back(_audio_flv_flags); @@ -115,14 +43,18 @@ bool AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { return true; } -void AACRtmpEncoder::makeAudioConfigPkt() { - _audio_flv_flags = getAudioRtmpFlags(std::make_shared(_aac_cfg)); +void AACRtmpEncoder::makeConfigPacket() { + _audio_flv_flags = getAudioRtmpFlags(getTrack()); auto pkt = RtmpPacket::create(); // header pkt->buffer.push_back(_audio_flv_flags); pkt->buffer.push_back((uint8_t)RtmpAACPacketType::aac_config_header); + // aac config - pkt->buffer.append(_aac_cfg); + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); + pkt->body_size = pkt->buffer.size(); pkt->chunk_id = CHUNK_AUDIO; pkt->stream_index = STREAM_MEDIA; diff --git a/src/Extension/AACRtmp.h b/src/Extension/AACRtmp.h index fd34c495..2028ec35 100644 --- a/src/Extension/AACRtmp.h +++ b/src/Extension/AACRtmp.h @@ -19,35 +19,23 @@ namespace mediakit{ /** * aac Rtmp转adts类 */ -class AACRtmpDecoder : public RtmpCodec{ +class AACRtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - AACRtmpDecoder() {} - ~AACRtmpDecoder() {} + AACRtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入Rtmp并解码 * @param rtmp Rtmp数据包 */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - - CodecId getCodecId() const override{ - return CodecAAC; - } - -private: - void onGetAAC(const char *data, size_t len, uint32_t stamp); - -private: - std::string _aac_cfg; }; - /** * aac adts转Rtmp类 */ -class AACRtmpEncoder : public AACRtmpDecoder{ +class AACRtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -57,8 +45,7 @@ public: * 那么inputFrame时可以不输入adts头 * @param track */ - AACRtmpEncoder(const Track::Ptr &track); - ~AACRtmpEncoder() {} + AACRtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入aac 数据,可以不带adts头 @@ -72,12 +59,7 @@ public: void makeConfigPacket() override; private: - void makeAudioConfigPkt(); - -private: - uint8_t _audio_flv_flags; - AACTrack::Ptr _track; - std::string _aac_cfg; + uint8_t _audio_flv_flags {0}; }; }//namespace mediakit diff --git a/src/Extension/AACRtp.cpp b/src/Extension/AACRtp.cpp index b5c5ab39..580c27d4 100644 --- a/src/Extension/AACRtp.cpp +++ b/src/Extension/AACRtp.cpp @@ -12,63 +12,36 @@ namespace mediakit{ -AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType, - uint8_t ui8Interleaved) : - RtpInfo(ui32Ssrc, - ui32MtuSize, - ui32SampleRate, - ui8PayloadType, - ui8Interleaved){ -} - bool AACRtpEncoder::inputFrame(const Frame::Ptr &frame) { - auto stamp = frame->dts(); - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto ptr = (char *) data; - auto remain_size = len; - auto max_size = getMaxSize() - 4; + auto ptr = (char *)frame->data() + frame->prefixSize(); + auto size = frame->size() - frame->prefixSize(); + auto remain_size = size; + auto max_size = getRtpInfo().getMaxSize() - 4; while (remain_size > 0) { if (remain_size <= max_size) { - _section_buf[0] = 0; - _section_buf[1] = 16; - _section_buf[2] = (len >> 5) & 0xFF; - _section_buf[3] = ((len & 0x1F) << 3) & 0xFF; - memcpy(_section_buf + 4, ptr, remain_size); - makeAACRtp(_section_buf, remain_size + 4, true, stamp); + outputRtp(ptr, remain_size, size, true, frame->dts()); break; } - _section_buf[0] = 0; - _section_buf[1] = 16; - _section_buf[2] = ((len) >> 5) & 0xFF; - _section_buf[3] = ((len & 0x1F) << 3) & 0xFF; - memcpy(_section_buf + 4, ptr, max_size); - makeAACRtp(_section_buf, max_size + 4, false, stamp); + outputRtp(ptr, max_size, size, false, frame->dts()); ptr += max_size; remain_size -= max_size; } - return len > 0; + return true; } -void AACRtpEncoder::makeAACRtp(const void *data, size_t len, bool mark, uint64_t stamp) { - RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, mark, stamp), false); +void AACRtpEncoder::outputRtp(const char *data, size_t len, size_t total_len, bool mark, uint64_t stamp) { + auto rtp = getRtpInfo().makeRtp(TrackAudio, nullptr, len + 4, mark, stamp); + auto payload = rtp->data() + RtpPacket::kRtpTcpHeaderSize + RtpPacket::kRtpHeaderSize; + payload[0] = 0; + payload[1] = 16; + payload[2] = ((total_len) >> 5) & 0xFF; + payload[3] = ((total_len & 0x1F) << 3) & 0xFF; + memcpy(payload + 4, data, len); + RtpCodec::inputRtp(std::move(rtp), false); } ///////////////////////////////////////////////////////////////////////////////////// -AACRtpDecoder::AACRtpDecoder(const Track::Ptr &track) { - auto aacTrack = std::dynamic_pointer_cast(track); - if (!aacTrack || !aacTrack->ready()) { - WarnL << "该aac track无效!"; - } else { - _aac_cfg = aacTrack->getConfig(); - } - obtainFrame(); -} - AACRtpDecoder::AACRtpDecoder() { obtainFrame(); } @@ -145,17 +118,8 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { void AACRtpDecoder::flushData() { auto ptr = reinterpret_cast(_frame->data()); if ((ptr[0] == 0xFF && (ptr[1] & 0xF0) == 0xF0) && _frame->size() > ADTS_HEADER_LEN) { - //adts头打入了rtp包,不符合规范,兼容EasyPusher的bug + // adts头打入了rtp包,不符合规范,兼容EasyPusher的bug _frame->_prefix_size = ADTS_HEADER_LEN; - } else { - //没有adts头则插入adts头 - char adts_header[128] = {0}; - auto size = dumpAacConfig(_aac_cfg, _frame->_buffer.size(), (uint8_t *) adts_header, sizeof(adts_header)); - if (size > 0) { - //插入adts头 - _frame->_buffer.insert(0, adts_header, size); - _frame->_prefix_size = size; - } } RtpCodec::inputFrame(_frame); obtainFrame(); diff --git a/src/Extension/AACRtp.h b/src/Extension/AACRtp.h index fd9de2a9..5e0a1d9d 100644 --- a/src/Extension/AACRtp.h +++ b/src/Extension/AACRtp.h @@ -21,8 +21,7 @@ class AACRtpDecoder : public RtpCodec { public: using Ptr = std::shared_ptr; - AACRtpDecoder(const Track::Ptr &track); - ~AACRtpDecoder() {} + AACRtpDecoder(); /** * 输入rtp并解码 @@ -31,20 +30,12 @@ public: */ bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; - CodecId getCodecId() const override { - return CodecAAC; - } - -protected: - AACRtpDecoder(); - private: void obtainFrame(); void flushData(); private: uint64_t _last_dts = 0; - std::string _aac_cfg; FrameImp::Ptr _frame; }; @@ -52,24 +43,10 @@ private: /** * aac adts转rtp类 */ -class AACRtpEncoder : public AACRtpDecoder , public RtpInfo { +class AACRtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - /** - * @param ui32Ssrc ssrc - * @param ui32MtuSize mtu 大小 - * @param ui32SampleRate 采样率 - * @param ui8PayloadType pt类型 - * @param ui8Interleaved rtsp interleaved 值 - */ - AACRtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType = 97, - uint8_t ui8Interleaved = TrackAudio * 2); - ~AACRtpEncoder() {} - /** * 输入aac 数据,必须带dats头 * @param frame 带dats头的aac数据 @@ -77,10 +54,8 @@ public: bool inputFrame(const Frame::Ptr &frame) override; private: - void makeAACRtp(const void *data, size_t len, bool mark, uint64_t stamp); + void outputRtp(const char *data, size_t len, size_t total_len, bool mark, uint64_t stamp); -private: - unsigned char _section_buf[1600]; }; }//namespace mediakit diff --git a/src/Extension/CommonRtmp.cpp b/src/Extension/CommonRtmp.cpp index 671e21a1..fc912159 100644 --- a/src/Extension/CommonRtmp.cpp +++ b/src/Extension/CommonRtmp.cpp @@ -10,46 +10,26 @@ #include "CommonRtmp.h" -namespace mediakit{ - -CommonRtmpDecoder::CommonRtmpDecoder(CodecId codec) { - _codec = codec; - obtainFrame(); -} - -CodecId CommonRtmpDecoder::getCodecId() const { - return _codec; -} - -void CommonRtmpDecoder::obtainFrame() { - _frame = FrameImp::create(); - _frame->_codec_id = _codec; -} +namespace mediakit { void CommonRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp) { - //拷贝负载 - _frame->_buffer.assign(rtmp->buffer.data() + 1, rtmp->buffer.size() - 1); - _frame->_dts = rtmp->time_stamp; - //写入环形缓存 - RtmpCodec::inputFrame(_frame); - //创建下一帧 - obtainFrame(); + auto frame = FrameImp::create(); + frame->_codec_id = getTrack()->getCodecId(); + frame->_buffer.assign(rtmp->buffer.data() + 1, rtmp->buffer.size() - 1); + frame->_dts = rtmp->time_stamp; + RtmpCodec::inputFrame(frame); } ///////////////////////////////////////////////////////////////////////////////////// -CommonRtmpEncoder::CommonRtmpEncoder(const Track::Ptr &track) : CommonRtmpDecoder(track->getCodecId()) { - _audio_flv_flags = getAudioRtmpFlags(track); -} - bool CommonRtmpEncoder::inputFrame(const Frame::Ptr &frame) { if (!_audio_flv_flags) { - return false; + _audio_flv_flags = getAudioRtmpFlags(getTrack()); } auto rtmp = RtmpPacket::create(); - //header + // header rtmp->buffer.push_back(_audio_flv_flags); - //data + // data rtmp->buffer.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize()); rtmp->body_size = rtmp->buffer.size(); rtmp->chunk_id = CHUNK_AUDIO; diff --git a/src/Extension/CommonRtmp.h b/src/Extension/CommonRtmp.h index 8c28238a..e85528df 100644 --- a/src/Extension/CommonRtmp.h +++ b/src/Extension/CommonRtmp.h @@ -23,42 +23,26 @@ class CommonRtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - ~CommonRtmpDecoder() override {} - /** * 构造函数 - * @param codec 编码id */ - CommonRtmpDecoder(CodecId codec); - - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; + CommonRtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入Rtmp并解码 * @param rtmp Rtmp数据包 */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - -private: - void obtainFrame(); - -private: - CodecId _codec; - FrameImp::Ptr _frame; }; /** * 通用 rtmp编码类 */ -class CommonRtmpEncoder : public CommonRtmpDecoder { +class CommonRtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - CommonRtmpEncoder(const Track::Ptr &track); - ~CommonRtmpEncoder() override{} + CommonRtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入帧数据 @@ -66,7 +50,7 @@ public: bool inputFrame(const Frame::Ptr &frame) override; private: - uint8_t _audio_flv_flags = 0; + uint8_t _audio_flv_flags { 0 }; }; }//namespace mediakit diff --git a/src/Extension/CommonRtp.cpp b/src/Extension/CommonRtp.cpp index 68767a6f..2a4fce9d 100644 --- a/src/Extension/CommonRtp.cpp +++ b/src/Extension/CommonRtp.cpp @@ -18,10 +18,6 @@ CommonRtpDecoder::CommonRtpDecoder(CodecId codec, size_t max_frame_size ){ obtainFrame(); } -CodecId CommonRtpDecoder::getCodecId() const { - return _codec; -} - void CommonRtpDecoder::obtainFrame() { _frame = FrameImp::create(); _frame->_codec_id = _codec; @@ -66,17 +62,12 @@ bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){ //////////////////////////////////////////////////////////////// -CommonRtpEncoder::CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, - uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved) - : CommonRtpDecoder(codec), RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) { -} - bool CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){ auto stamp = frame->pts(); auto ptr = frame->data() + frame->prefixSize(); auto len = frame->size() - frame->prefixSize(); auto remain_size = len; - auto max_size = getMaxSize(); + auto max_size = getRtpInfo().getMaxSize(); bool is_key = frame->keyFrame(); bool mark = false; while (remain_size > 0) { @@ -87,7 +78,7 @@ bool CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){ rtp_size = remain_size; mark = true; } - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), is_key); + RtpCodec::inputRtp(getRtpInfo().makeRtp(frame->getTrackType(), ptr, rtp_size, mark, stamp), is_key); ptr += rtp_size; remain_size -= rtp_size; is_key = false; diff --git a/src/Extension/CommonRtp.h b/src/Extension/CommonRtp.h index 6553207e..6d063463 100644 --- a/src/Extension/CommonRtp.h +++ b/src/Extension/CommonRtp.h @@ -23,8 +23,6 @@ class CommonRtpDecoder : public RtpCodec { public: using Ptr = std::shared_ptr ; - ~CommonRtpDecoder() override {} - /** * 构造函数 * @param codec 编码id @@ -32,11 +30,6 @@ public: */ CommonRtpDecoder(CodecId codec, size_t max_frame_size = 2 * 1024); - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; - /** * 输入rtp并解码 * @param rtp rtp数据包 @@ -59,23 +52,10 @@ private: /** * 通用 rtp编码类 */ -class CommonRtpEncoder : public CommonRtpDecoder, public RtpInfo { +class CommonRtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr ; - ~CommonRtpEncoder() override {} - - /** - * 构造函数 - * @param codec 编码类型 - * @param ssrc ssrc - * @param mtu_size mtu 大小 - * @param sample_rate 采样率 - * @param payload_type pt类型 - * @param interleaved rtsp interleaved 值 - */ - CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved); - /** * 输入帧数据并编码成rtp */ diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index 63a2bbd5..3be898dd 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -91,9 +91,7 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) { return std::make_shared(vps, sps, pps, 0, 0, 0); } - case CodecJPEG : { - return std::make_shared(); - } + case CodecJPEG : return std::make_shared(); default: { //其他codec不支持 @@ -129,53 +127,30 @@ Track::Ptr Factory::getTrackByAbstractTrack(const Track::Ptr& track) { } } -RtpCodec::Ptr Factory::getRtpEncoderByCodecId(CodecId codec_id, uint32_t sample_rate, uint8_t pt, uint32_t ssrc) { - GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); - GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); - auto type = getTrackType(codec_id); - auto mtu = type == TrackVideo ? video_mtu : audio_mtu; - auto interleaved = type * 2; +RtpCodec::Ptr Factory::getRtpEncoderByCodecId(CodecId codec_id, uint8_t pt) { switch (codec_id) { - case CodecH264: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - case CodecH265: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); - case CodecAAC: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); + case CodecH264: return std::make_shared(); + case CodecH265: return std::make_shared(); + case CodecAAC: return std::make_shared(); case CodecL16: - case CodecOpus: return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); + case CodecOpus: return std::make_shared(); case CodecG711A: case CodecG711U: { if (pt == Rtsp::PT_PCMA || pt == Rtsp::PT_PCMU) { - return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved, 1); + return std::make_shared(codec_id, 1); } - return std::make_shared(codec_id, ssrc, mtu, sample_rate, pt, interleaved); + return std::make_shared(); } - case CodecJPEG: return std::make_shared(ssrc, mtu, sample_rate, pt, interleaved); + case CodecJPEG: return std::make_shared(); default: WarnL << "暂不支持该CodecId:" << codec_id; return nullptr; } } -RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) { - // ssrc不冲突即可,可以为任意的32位整形 - static atomic s_ssrc(0); - uint32_t ssrc = s_ssrc++; - if (!ssrc) { - // ssrc不能为0 - ssrc = s_ssrc++; - } - if (sdp->getTrackType() == TrackVideo) { - //视频的ssrc是偶数,方便调试 - ssrc = 2 * ssrc; - } else { - //音频ssrc是奇数 - ssrc = 2 * ssrc + 1; - } - return getRtpEncoderByCodecId(sdp->getCodecId(), sdp->getSampleRate(), sdp->getPayloadType(), ssrc); -} - RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) { switch (track->getCodecId()){ case CodecH264 : return std::make_shared(); case CodecH265 : return std::make_shared(); - case CodecAAC : return std::make_shared(track->clone()); + case CodecAAC : return std::make_shared(); case CodecL16 : case CodecOpus : case CodecG711A : @@ -267,7 +242,19 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int return getTrackByCodecId(codecId, sample_rate, channels, sample_bit); } -RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode) { +RtmpCodec::Ptr Factory::getRtmpDecoderByTrack(const Track::Ptr &track) { + switch (track->getCodecId()){ + case CodecH264 : return std::make_shared(track); + case CodecAAC : return std::make_shared(track); + case CodecH265 : return std::make_shared(track); + case CodecOpus : + case CodecG711A : + case CodecG711U : return std::make_shared(track); + default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr; + } +} + +RtmpCodec::Ptr Factory::getRtmpEncoderByTrack(const Track::Ptr &track) { switch (track->getCodecId()){ case CodecH264 : return std::make_shared(track); case CodecAAC : return std::make_shared(track); @@ -276,9 +263,7 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_enc case CodecG711A : case CodecG711U : { auto audio_track = dynamic_pointer_cast(track); - if (is_encode && (audio_track->getAudioSampleRate() != 8000 || - audio_track->getAudioChannel() != 1 || - audio_track->getAudioSampleBit() != 16)) { + if (audio_track->getAudioSampleRate() != 8000 || audio_track->getAudioChannel() != 1 || audio_track->getAudioSampleBit() != 16) { //rtmp对g711只支持8000/1/16规格,但是ZLMediaKit可以解析其他规格的G711 WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:" << audio_track->getAudioSampleRate() << "/" @@ -294,13 +279,16 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_enc } AMFValue Factory::getAmfByCodecId(CodecId codecId) { + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); switch (codecId) { case CodecAAC: return AMFValue((int)RtmpAudioCodec::aac); case CodecH264: return AMFValue((int)RtmpVideoCodec::h264); - case CodecH265: return AMFValue((int)RtmpVideoCodec::h265); + case CodecH265: return enhanced ? AMFValue((int)RtmpVideoCodec::fourcc_hevc) : AMFValue((int)RtmpVideoCodec::h265); case CodecG711A: return AMFValue((int)RtmpAudioCodec::g711a); case CodecG711U: return AMFValue((int)RtmpAudioCodec::g711u); case CodecOpus: return AMFValue((int)RtmpAudioCodec::opus); + case CodecAV1: return AMFValue((int)RtmpVideoCodec::fourcc_av1); + case CodecVP9: return AMFValue((int)RtmpVideoCodec::fourcc_vp9); default: return AMFValue(AMF_NULL); } } diff --git a/src/Extension/Factory.h b/src/Extension/Factory.h index d0045865..c6fcb16c 100644 --- a/src/Extension/Factory.h +++ b/src/Extension/Factory.h @@ -42,20 +42,12 @@ public: */ static Track::Ptr getTrackByAbstractTrack(const Track::Ptr& track); - /** - * 根据sdp生成rtp编码器 - * @param sdp sdp对象 - */ - static RtpCodec::Ptr getRtpEncoderBySdp(const Sdp::Ptr &sdp); - /** * 根据codec id生成rtp编码器 * @param codec_id 编码id - * @param sample_rate 采样率,视频固定为90000 * @param pt rtp payload type - * @param ssrc rtp ssrc */ - static RtpCodec::Ptr getRtpEncoderByCodecId(CodecId codec_id, uint32_t sample_rate, uint8_t pt, uint32_t ssrc); + static RtpCodec::Ptr getRtpEncoderByCodecId(CodecId codec_id, uint8_t pt); /** * 根据Track生成Rtp解包器 @@ -78,11 +70,16 @@ public: static Track::Ptr getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int channels, int sample_bit); /** - * 根据Track获取Rtmp的编解码器 + * 根据Track获取Rtmp的编码器 * @param track 媒体描述对象 - * @param is_encode 是否为编码器还是解码器 */ - static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode); + static RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track); + + /** + * 根据Track获取Rtmp的解码器 + * @param track 媒体描述对象 + */ + static RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track); /** * 根据codecId获取rtmp的codec描述 diff --git a/src/Extension/Frame.cpp b/src/Extension/Frame.cpp index 152eea1f..c14337b8 100644 --- a/src/Extension/Frame.cpp +++ b/src/Extension/Frame.cpp @@ -94,6 +94,10 @@ TrackType CodecInfo::getTrackType() const { return mediakit::getTrackType(getCodecId()); } +std::string CodecInfo::getTrackTypeStr() const { + return getTrackString(getTrackType()); +} + static size_t constexpr kMaxFrameCacheSize = 100; bool FrameMerger::willFlush(const Frame::Ptr &frame) const{ @@ -165,7 +169,19 @@ void FrameMerger::doMerge(BufferLikeString &merged, const Frame::Ptr &frame) con } } +static bool isNeedMerge(CodecId codec){ + switch (codec) { + case CodecH264: + case CodecH265: return true; + default: return false; + } +} + bool FrameMerger::inputFrame(const Frame::Ptr &frame, onOutput cb, BufferLikeString *buffer) { + if (frame && !isNeedMerge(frame->getCodecId())) { + cb(frame->dts(), frame->pts(), frame, true); + return true; + } if (willFlush(frame)) { Frame::Ptr back = _frame_cache.back(); Buffer::Ptr merged_frame = back; @@ -233,8 +249,6 @@ public: */ FrameWriterInterfaceHelper(onWriteFrame cb) { _callback = std::move(cb); } - virtual ~FrameWriterInterfaceHelper() = default; - /** * 写入帧数据 */ diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index a1b2b6dc..34338869 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -85,7 +85,6 @@ class CodecInfo { public: using Ptr = std::shared_ptr; - CodecInfo() = default; virtual ~CodecInfo() = default; /** @@ -102,6 +101,7 @@ public: * 获取音视频类型 */ TrackType getTrackType() const; + std::string getTrackTypeStr() const; }; /** @@ -110,7 +110,6 @@ public: class Frame : public toolkit::Buffer, public CodecInfo { public: using Ptr = std::shared_ptr; - virtual ~Frame() = default; /** * 返回解码时间戳,单位毫秒 @@ -267,7 +266,6 @@ private: class FrameWriterInterface { public: using Ptr = std::shared_ptr; - FrameWriterInterface() = default; virtual ~FrameWriterInterface() = default; /** @@ -287,8 +285,6 @@ public: class FrameDispatcher : public FrameWriterInterface { public: using Ptr = std::shared_ptr; - FrameDispatcher() = default; - ~FrameDispatcher() override = default; /** * 添加代理 @@ -404,10 +400,8 @@ class FrameFromPtr : public Frame { public: using Ptr = std::shared_ptr; - FrameFromPtr( - CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, - bool is_key = false) - : FrameFromPtr(ptr, size, dts, pts, prefix_size, is_key) { + FrameFromPtr(CodecId codec_id, char *ptr, size_t size, uint64_t dts, uint64_t pts = 0, size_t prefix_size = 0, bool is_key = false) + : FrameFromPtr(ptr, size, dts, pts, prefix_size,is_key) { _codec_id = codec_id; } @@ -477,8 +471,6 @@ public: _decode_able = frame->decodeAble(); } - ~FrameCacheAble() override = default; - /** * 可以被缓存 */ @@ -528,8 +520,6 @@ private: template class FrameWrapper : public Parent { public: - ~FrameWrapper() = default; - /** * 构造frame * @param buf 数据缓存 @@ -580,7 +570,6 @@ public: }; FrameMerger(int type); - ~FrameMerger() = default; /** * 刷新输出缓冲,注意此时会调用FrameMerger::inputFrame传入的onOutput回调 diff --git a/src/Extension/G711.cpp b/src/Extension/G711.cpp index 6f505bef..5065ae46 100644 --- a/src/Extension/G711.cpp +++ b/src/Extension/G711.cpp @@ -23,41 +23,34 @@ public: /** * G711采样率固定为8000 * @param codecId G711A G711U + * @param payload_type rtp payload type * @param sample_rate 音频采样率 - * @param payload_type rtp payload + * @param channels 通道数 * @param bitrate 比特率 */ - G711Sdp(CodecId codecId, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type), _codecId(codecId){ + G711Sdp(CodecId codecId, int payload_type, int sample_rate, int channels, int bitrate) + : Sdp(sample_rate, payload_type) { _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(codecId) << "/" << sample_rate << "/" << channels << "\r\n"; } string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return _codecId; - } private: _StrPrinter _printer; - CodecId _codecId; }; -Track::Ptr G711Track::clone() { - return std::make_shared::type>(*this); +Track::Ptr G711Track::clone() const { + return std::make_shared(*this); } -Sdp::Ptr G711Track::getSdp() { - if(!ready()){ +Sdp::Ptr G711Track::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } @@ -66,13 +59,12 @@ Sdp::Ptr G711Track::getSdp() { const auto sample_rate = getAudioSampleRate(); const auto audio_channel = getAudioChannel(); const auto bitrate = getBitRate() >> 10; - auto payload_type = 98; if (sample_rate == 8000 && audio_channel == 1) { // https://datatracker.ietf.org/doc/html/rfc3551#section-6 payload_type = (codec == CodecG711U) ? Rtsp::PT_PCMU : Rtsp::PT_PCMA; } - return std::make_shared(codec, sample_rate, audio_channel, bitrate, payload_type); + return std::make_shared(codec, payload_type, sample_rate, audio_channel, bitrate); } }//namespace mediakit diff --git a/src/Extension/G711.h b/src/Extension/G711.h index 550acbc4..9c146a79 100644 --- a/src/Extension/G711.h +++ b/src/Extension/G711.h @@ -25,8 +25,8 @@ public: G711Track(CodecId codecId, int sample_rate, int channels, int sample_bit) : AudioTrackImp(codecId, 8000, 1, 16) {} private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; }; }//namespace mediakit diff --git a/src/Extension/G711Rtp.cpp b/src/Extension/G711Rtp.cpp index ce74eda1..2760f8a6 100644 --- a/src/Extension/G711Rtp.cpp +++ b/src/Extension/G711Rtp.cpp @@ -2,11 +2,7 @@ namespace mediakit { -G711RtpEncoder::G711RtpEncoder( - CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved, - uint32_t channels) - : CommonRtpDecoder(codec) - , RtpInfo(ssrc, mtu_size, sample_rate, payload_type, interleaved) { +G711RtpEncoder::G711RtpEncoder(CodecId codec, uint32_t channels){ _cache_frame = FrameImp::create(); _cache_frame->_codec_id = codec; _channels = channels; @@ -40,7 +36,7 @@ bool G711RtpEncoder::inputFrame(const Frame::Ptr &frame) { } n++; stamp += 20; - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, rtp_size, mark, stamp), false); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackAudio, ptr, rtp_size, mark, stamp), false); ptr += rtp_size; remain_size -= rtp_size; } diff --git a/src/Extension/G711Rtp.h b/src/Extension/G711Rtp.h index ffc8ffe8..0740119b 100644 --- a/src/Extension/G711Rtp.h +++ b/src/Extension/G711Rtp.h @@ -20,23 +20,16 @@ namespace mediakit { /** * G711 rtp编码类 */ -class G711RtpEncoder : public CommonRtpDecoder, public RtpInfo { +class G711RtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - ~G711RtpEncoder() override = default; - /** * 构造函数 * @param codec 编码类型 - * @param ssrc ssrc - * @param mtu_size mtu 大小 - * @param sample_rate 采样率 - * @param payload_type pt类型 - * @param interleaved rtsp interleaved 值 + * @param channels 通道数 */ - G711RtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_size, uint32_t sample_rate, uint8_t payload_type, - uint8_t interleaved, uint32_t channels); + G711RtpEncoder(CodecId codec, uint32_t channels); /** * 输入帧数据并编码成rtp diff --git a/src/Extension/H264.cpp b/src/Extension/H264.cpp index eda6b188..39ef8238 100644 --- a/src/Extension/H264.cpp +++ b/src/Extension/H264.cpp @@ -14,6 +14,10 @@ #include "Util/base64.h" #include "Common/config.h" +#ifdef ENABLE_MP4 +#include "mpeg4-avc.h" +#endif + using namespace std; using namespace toolkit; @@ -109,24 +113,7 @@ size_t prefixSize(const char *ptr, size_t len) { H264Track::H264Track(const string &sps, const string &pps, int sps_prefix_len, int pps_prefix_len) { _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); - onReady(); -} - -H264Track::H264Track(const Frame::Ptr &sps, const Frame::Ptr &pps) { - if (sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264) { - throw std::invalid_argument("必须输入H264类型的帧"); - } - _sps = string(sps->data() + sps->prefixSize(), sps->size() - sps->prefixSize()); - _pps = string(pps->data() + pps->prefixSize(), pps->size() - pps->prefixSize()); - onReady(); -} - -const string &H264Track::getSps() const { - return _sps; -} - -const string &H264Track::getPps() const { - return _pps; + update(); } CodecId H264Track::getCodecId() const { @@ -145,7 +132,7 @@ float H264Track::getVideoFps() const { return _fps; } -bool H264Track::ready() { +bool H264Track::ready() const { return !_sps.empty() && !_pps.empty(); } @@ -168,19 +155,87 @@ bool H264Track::inputFrame(const Frame::Ptr &frame) { return ret; } +toolkit::Buffer::Ptr H264Track::getExtraData() const { + CHECK(ready()); + +#ifdef ENABLE_MP4 + struct mpeg4_avc_t avc; + memset(&avc, 0, sizeof(avc)); + string sps_pps = string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; + h264_annexbtomp4(&avc, sps_pps.data(), (int)sps_pps.size(), NULL, 0, NULL, NULL); + + std::string extra_data; + extra_data.resize(1024); + auto extra_data_size = mpeg4_avc_decoder_configuration_record_save(&avc, (uint8_t *)extra_data.data(), extra_data.size()); + if (extra_data_size == -1) { + WarnL << "生成H264 extra_data 失败"; + return nullptr; + } + extra_data.resize(extra_data_size); + return std::make_shared(std::move(extra_data)); +#else + std::string extra_data; + // AVCDecoderConfigurationRecord start + extra_data.push_back(1); // version + extra_data.push_back(_sps[1]); // profile + extra_data.push_back(_sps[2]); // compat + extra_data.push_back(_sps[3]); // level + extra_data.push_back((char)0xff); // 6 bits reserved + 2 bits nal size length - 1 (11) + extra_data.push_back((char)0xe1); // 3 bits reserved + 5 bits number of sps (00001) + // sps + uint16_t size = (uint16_t)_sps.size(); + size = htons(size); + extra_data.append((char *)&size, 2); + extra_data.append(_sps); + // pps + extra_data.push_back(1); // version + size = (uint16_t)_pps.size(); + size = htons(size); + extra_data.append((char *)&size, 2); + extra_data.append(_pps); + return std::make_shared(std::move(extra_data)); +#endif +} + +void H264Track::setExtraData(const uint8_t *data, size_t bytes) { +#ifdef ENABLE_MP4 + struct mpeg4_avc_t avc; + memset(&avc, 0, sizeof(avc)); + if (mpeg4_avc_decoder_configuration_record_load(data, bytes, &avc) > 0) { + std::vector config(bytes * 2); + int size = mpeg4_avc_to_nalu(&avc, config.data(), bytes * 2); + if (size > 4) { + splitH264((char *)config.data(), size, 4, [&](const char *ptr, size_t len, size_t prefix) { + inputFrame_l(std::make_shared((char *)ptr, len, 0, 0, prefix)); + }); + update(); + } + } +#else + CHECK(bytes >= 8); // 6 + 2 + size_t offset = 6; + + uint16_t sps_size = data[offset] << 8 | data[offset + 1]; + auto sps_ptr = data + offset + 2; + offset += (2 + sps_size); + CHECK(bytes >= offset + 2); // + pps_size + _sps.assign((char *)sps_ptr, sps_size); + + uint16_t pps_size = data[offset] << 8 | data[offset + 1]; + auto pps_ptr = data + offset + 2; + offset += (2 + pps_size); + CHECK(bytes >= offset); + _pps.assign((char *)pps_ptr, pps_size); + update(); +#endif +} + bool H264Track::update() { return getAVCInfo(_sps, _width, _height, _fps); } -void H264Track::onReady() { - if (!getAVCInfo(_sps, _width, _height, _fps)) { - _sps.clear(); - _pps.clear(); - } -} - -Track::Ptr H264Track::clone() { - return std::make_shared::type>(*this); +Track::Ptr H264Track::clone() const { + return std::make_shared(*this); } bool H264Track::inputFrame_l(const Frame::Ptr &frame) { @@ -218,7 +273,7 @@ bool H264Track::inputFrame_l(const Frame::Ptr &frame) { } if (_width == 0 && ready()) { - onReady(); + update(); } return ret; } @@ -245,14 +300,12 @@ void H264Track::insertConfigFrame(const Frame::Ptr &frame) { class H264Sdp : public Sdp { public: - H264Sdp(const string &strSPS, const string &strPPS, int bitrate, int payload_type = 96) - : Sdp(90000, payload_type) { - //视频通道 + H264Sdp(const string &strSPS, const string &strPPS, int payload_type, int bitrate) : Sdp(90000, payload_type) { _printer << "m=video 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << 90000 << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecH264) << "/" << 90000 << "\r\n"; /** Single NAI Unit Mode = 0. // Single NAI mode (Only nals from 1-23 are allowed) @@ -275,23 +328,20 @@ public: _printer << "; sprop-parameter-sets="; _printer << encodeBase64(strSPS) << ","; _printer << encodeBase64(strPPS) << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } string getSdp() const { return _printer; } - CodecId getCodecId() const { return CodecH264; } - private: _StrPrinter _printer; }; -Sdp::Ptr H264Track::getSdp() { +Sdp::Ptr H264Track::getSdp(uint8_t payload_type) const { if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getSps(), getPps(), getBitRate() / 1024); + return std::make_shared(_sps, _pps, payload_type, getBitRate() / 1024); } } // namespace mediakit diff --git a/src/Extension/H264.h b/src/Extension/H264.h index 0afe593d..1ef1a78f 100644 --- a/src/Extension/H264.h +++ b/src/Extension/H264.h @@ -18,7 +18,6 @@ namespace mediakit{ -bool getAVCInfo(const std::string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); void splitH264(const char *ptr, size_t len, size_t prefix, const std::function &cb); size_t prefixSize(const char *ptr, size_t len); @@ -43,8 +42,6 @@ public: this->_codec_id = CodecH264; } - ~H264FrameHelper() override = default; - bool keyFrame() const override { auto nal_ptr = (uint8_t *) this->data() + this->prefixSize(); return H264_TYPE(*nal_ptr) == NAL_IDR && decodeAble(); @@ -107,33 +104,21 @@ public: * @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 * @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01 */ - H264Track(const std::string &sps,const std::string &pps,int sps_prefix_len = 4,int pps_prefix_len = 4); + H264Track(const std::string &sps, const std::string &pps, int sps_prefix_len = 4, int pps_prefix_len = 4); - /** - * 构造h264类型的媒体 - * @param sps sps帧 - * @param pps pps帧 - */ - H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps); - - /** - * 返回不带0x00 00 00 01头的sps/pps - */ - const std::string &getSps() const; - const std::string &getPps() const; - - bool ready() override; + bool ready() const override; CodecId getCodecId() const override; int getVideoHeight() const override; int getVideoWidth() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; bool update() override; private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; bool inputFrame_l(const Frame::Ptr &frame); void insertConfigFrame(const Frame::Ptr &frame); diff --git a/src/Extension/H264Rtmp.cpp b/src/Extension/H264Rtmp.cpp index 9e62896d..0db16292 100644 --- a/src/Extension/H264Rtmp.cpp +++ b/src/Extension/H264Rtmp.cpp @@ -16,139 +16,50 @@ using namespace toolkit; namespace mediakit { -H264RtmpDecoder::H264RtmpDecoder() { - _h264frame = obtainFrame(); -} - -H264Frame::Ptr H264RtmpDecoder::obtainFrame() { - auto frame = FrameImp::create(); - frame->_prefix_size = 4; - return frame; -} - -/** - * 返回不带0x00 00 00 01头的sps pps - */ -static bool getH264Config(const RtmpPacket &thiz, string &sps, string &pps) { - if ((RtmpVideoCodec)thiz.getRtmpCodecId() != RtmpVideoCodec::h264) { - return false; - } - if (thiz.buffer.size() < 13) { - return false; - } - uint16_t sps_size; - memcpy(&sps_size, thiz.buffer.data() + 11, 2); - sps_size = ntohs(sps_size); - - if ((int) thiz.buffer.size() < 13 + sps_size + 1 + 2) { - return false; - } - uint16_t pps_size; - memcpy(&pps_size, thiz.buffer.data() + 13 + sps_size + 1, 2); - pps_size = ntohs(pps_size); - - if ((int) thiz.buffer.size() < 13 + sps_size + 1 + 2 + pps_size) { - return false; - } - sps.assign(thiz.buffer.data() + 13, sps_size); - pps.assign(thiz.buffer.data() + 13 + sps_size + 1 + 2, pps_size); - return true; -} - void H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { if (pkt->isConfigFrame()) { - //缓存sps pps,后续插入到I帧之前 - if (!getH264Config(*pkt, _sps, _pps)) { - WarnL << "get h264 sps/pps failed, rtmp packet is: " << hexdump(pkt->data(), pkt->size()); - return; - } - onGetH264(_sps.data(), _sps.size(), pkt->time_stamp, pkt->time_stamp); - onGetH264(_pps.data(), _pps.size(), pkt->time_stamp, pkt->time_stamp); + CHECK(pkt->size() > 5); + getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); return; } - if (pkt->buffer.size() > 9) { - auto total_len = pkt->buffer.size(); - size_t offset = 5; - uint8_t *cts_ptr = (uint8_t *) (pkt->buffer.data() + 2); - int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; - auto pts = pkt->time_stamp + cts; - while (offset + 4 < total_len) { - uint32_t frame_len; - memcpy(&frame_len, pkt->buffer.data() + offset, 4); - frame_len = ntohl(frame_len); - offset += 4; - if (frame_len + offset > total_len) { - break; - } - onGetH264(pkt->buffer.data() + offset, frame_len, pkt->time_stamp, pts); - offset += frame_len; + CHECK(pkt->size() > 9); + uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); + int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; + auto pts = pkt->time_stamp + cts; + splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); +} + +void H264RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts) { + auto end = data + size; + while (data + 4 < end) { + uint32_t frame_len = load_be32(data); + data += 4; + if (data + frame_len > end) { + break; } + outputFrame((const char *)data, frame_len, dts, pts); + data += frame_len; } } -inline void H264RtmpDecoder::onGetH264(const char* data, size_t len, uint32_t dts, uint32_t pts) { - if (!len) { - return; - } - _h264frame->_dts = dts; - _h264frame->_pts = pts; - _h264frame->_buffer.assign("\x00\x00\x00\x01", 4); //添加264头 - _h264frame->_buffer.append(data, len); - - //写入环形缓存 - RtmpCodec::inputFrame(_h264frame); - _h264frame = obtainFrame(); +void H264RtmpDecoder::outputFrame(const char *data, size_t len, uint32_t dts, uint32_t pts) { + auto frame = FrameImp::create(); + frame->_prefix_size = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加264头 + frame->_buffer.append(data, len); + RtmpCodec::inputFrame(frame); } //////////////////////////////////////////////////////////////////////// -H264RtmpEncoder::H264RtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void H264RtmpEncoder::makeConfigPacket(){ - if (_track && _track->ready()) { - //尝试从track中获取sps pps信息 - _sps = _track->getSps(); - _pps = _track->getPps(); - } - - if (!_sps.empty() && !_pps.empty()) { - //获取到sps/pps - makeVideoConfigPkt(); - _got_config_frame = true; - } -} - void H264RtmpEncoder::flush() { inputFrame(nullptr); } bool H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (frame) { - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto type = H264_TYPE(data[0]); - switch (type) { - case H264Frame::NAL_SPS: { - if (!_got_config_frame) { - _sps = string(data, len); - makeConfigPacket(); - } - break; - } - case H264Frame::NAL_PPS: { - if (!_got_config_frame) { - _pps = string(data, len); - makeConfigPacket(); - } - break; - } - default: break; - } - } - if (!_rtmp_packet) { _rtmp_packet = RtmpPacket::create(); //flags/not config/cts预占位 @@ -173,11 +84,7 @@ bool H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { }, &_rtmp_packet->buffer); } -void H264RtmpEncoder::makeVideoConfigPkt() { - if (_sps.size() < 4) { - WarnL << "sps长度不足4字节"; - return; - } +void H264RtmpEncoder::makeConfigPacket() { auto flags = (uint8_t)RtmpVideoCodec::h264; flags |= ((uint8_t)RtmpFrameType::key_frame << 4); auto pkt = RtmpPacket::create(); @@ -187,23 +94,9 @@ void H264RtmpEncoder::makeVideoConfigPkt() { // cts pkt->buffer.append("\x0\x0\x0", 3); // AVCDecoderConfigurationRecord start - pkt->buffer.push_back(1); // version - pkt->buffer.push_back(_sps[1]); // profile - pkt->buffer.push_back(_sps[2]); // compat - pkt->buffer.push_back(_sps[3]); // level - pkt->buffer.push_back((char)0xff); // 6 bits reserved + 2 bits nal size length - 1 (11) - pkt->buffer.push_back((char)0xe1); // 3 bits reserved + 5 bits number of sps (00001) - // sps - uint16_t size = (uint16_t)_sps.size(); - size = htons(size); - pkt->buffer.append((char *)&size, 2); - pkt->buffer.append(_sps); - // pps - pkt->buffer.push_back(1); // version - size = (uint16_t)_pps.size(); - size = htons(size); - pkt->buffer.append((char *)&size, 2); - pkt->buffer.append(_pps); + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); pkt->body_size = pkt->buffer.size(); pkt->chunk_id = CHUNK_VIDEO; diff --git a/src/Extension/H264Rtmp.h b/src/Extension/H264Rtmp.h index 5849ba2a..ea8f7471 100644 --- a/src/Extension/H264Rtmp.h +++ b/src/Extension/H264Rtmp.h @@ -24,8 +24,7 @@ class H264RtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - H264RtmpDecoder(); - ~H264RtmpDecoder() {} + H264RtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入264 Rtmp包 @@ -33,24 +32,15 @@ public: */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - CodecId getCodecId() const override{ - return CodecH264; - } - -protected: - void onGetH264(const char *data, size_t len, uint32_t dts, uint32_t pts); - H264Frame::Ptr obtainFrame(); - -protected: - H264Frame::Ptr _h264frame; - std::string _sps; - std::string _pps; +private: + void outputFrame(const char *data, size_t len, uint32_t dts, uint32_t pts); + void splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts); }; /** * 264 Rtmp打包类 */ -class H264RtmpEncoder : public H264RtmpDecoder{ +class H264RtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -60,8 +50,7 @@ public: * 那么inputFrame时可以不输入sps pps * @param track */ - H264RtmpEncoder(const Track::Ptr &track); - ~H264RtmpEncoder() = default; + H264RtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入264帧,可以不带sps pps @@ -80,13 +69,8 @@ public: void makeConfigPacket() override; private: - void makeVideoConfigPkt(); - -private: - bool _got_config_frame = false; - H264Track::Ptr _track; RtmpPacket::Ptr _rtmp_packet; - FrameMerger _merger{FrameMerger::mp4_nal_size}; + FrameMerger _merger { FrameMerger::mp4_nal_size }; }; }//namespace mediakit diff --git a/src/Extension/H264Rtp.cpp b/src/Extension/H264Rtp.cpp index 442205a6..512a60f1 100644 --- a/src/Extension/H264Rtp.cpp +++ b/src/Extension/H264Rtp.cpp @@ -192,10 +192,6 @@ void H264RtpDecoder::outputFrame(const RtpPacket::Ptr &rtp, const H264Frame::Ptr //////////////////////////////////////////////////////////////////////// -H264RtpEncoder::H264RtpEncoder(uint32_t ssrc, uint32_t mtu, uint32_t sample_rate, uint8_t pt, uint8_t interleaved) - : RtpInfo(ssrc, mtu, sample_rate, pt, interleaved) { -} - void H264RtpEncoder::insertConfigFrame(uint64_t pts){ if (!_sps || !_pps) { return; @@ -206,7 +202,7 @@ void H264RtpEncoder::insertConfigFrame(uint64_t pts){ } void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - if (len + 3 <= getMaxSize()) { + if (len + 3 <= getRtpInfo().getMaxSize()) { // 采用STAP-A/Single NAL unit packet per H.264 模式 packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos); } else { @@ -216,7 +212,7 @@ void H264RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_ } void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - auto packet_size = getMaxSize() - 2; + auto packet_size = getRtpInfo().getMaxSize() - 2; if (len <= packet_size + 1) { // 小于FU-A打包最小字节长度要求,采用STAP-A/Single NAL unit packet per H.264 模式 packRtpSmallFrame(ptr, len, pts, is_mark, gop_pos); @@ -238,7 +234,7 @@ void H264RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i } //传入nullptr先不做payload的内存拷贝 - auto rtp = makeRtp(getTrackType(), nullptr, packet_size + 2, fu_flags->end_bit && is_mark, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, packet_size + 2, fu_flags->end_bit && is_mark, pts); //rtp payload 负载部分 uint8_t *payload = rtp->getPayload(); //FU-A 第1个字节 @@ -266,7 +262,7 @@ void H264RtpEncoder::packRtpSmallFrame(const char *data, size_t len, uint64_t pt void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ // 如果帧长度不超过mtu,为了兼容性 webrtc,采用STAP-A模式打包 - auto rtp = makeRtp(getTrackType(), nullptr, len + 3, is_mark, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, len + 3, is_mark, pts); uint8_t *payload = rtp->getPayload(); //STAP-A payload[0] = (ptr[0] & (~0x1F)) | 24; @@ -279,7 +275,7 @@ void H264RtpEncoder::packRtpStapA(const char *ptr, size_t len, uint64_t pts, boo void H264RtpEncoder::packRtpSingleNalu(const char *data, size_t len, uint64_t pts, bool is_mark, bool gop_pos) { // Single NAL unit packet per H.264 模式 - RtpCodec::inputRtp(makeRtp(getTrackType(), data, len, is_mark, pts), gop_pos); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackVideo, data, len, is_mark, pts), gop_pos); } bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame) { diff --git a/src/Extension/H264Rtp.h b/src/Extension/H264Rtp.h index 98d49cda..3f531bce 100644 --- a/src/Extension/H264Rtp.h +++ b/src/Extension/H264Rtp.h @@ -28,7 +28,6 @@ public: using Ptr = std::shared_ptr; H264RtpDecoder(); - ~H264RtpDecoder() override = default; /** * 输入264 rtp包 @@ -37,10 +36,6 @@ public: */ bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; - CodecId getCodecId() const override{ - return CodecH264; - } - private: bool singleFrame(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); bool unpackStapA(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); @@ -62,26 +57,11 @@ private: /** * 264 rtp打包类 */ -class H264RtpEncoder : public H264RtpDecoder ,public RtpInfo{ +class H264RtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; /** - * @param ssrc ssrc - * @param mtu mtu大小 - * @param sample_rate 采样率,强制为90000 - * @param pt pt类型 - * @param interleaved rtsp interleaved - */ - H264RtpEncoder(uint32_t ssrc, - uint32_t mtu = 1400, - uint32_t sample_rate = 90000, - uint8_t pt = 96, - uint8_t interleaved = TrackVideo * 2); - - ~H264RtpEncoder() override = default; - - /** * 输入264帧 * @param frame 帧数据,必须 */ diff --git a/src/Extension/H265.cpp b/src/Extension/H265.cpp index 926ab2a4..f68530d8 100644 --- a/src/Extension/H265.cpp +++ b/src/Extension/H265.cpp @@ -12,6 +12,10 @@ #include "SPSParser.h" #include "Util/base64.h" +#ifdef ENABLE_MP4 +#include "mpeg4-hevc.h" +#endif + using namespace std; using namespace toolkit; @@ -58,19 +62,7 @@ H265Track::H265Track(const string &vps,const string &sps, const string &pps,int _vps = vps.substr(vps_prefix_len); _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); - onReady(); -} - -const string &H265Track::getVps() const { - return _vps; -} - -const string &H265Track::getSps() const { - return _sps; -} - -const string &H265Track::getPps() const { - return _pps; + update(); } CodecId H265Track::getCodecId() const { @@ -89,7 +81,7 @@ float H265Track::getVideoFps() const { return _fps; } -bool H265Track::ready() { +bool H265Track::ready() const { return !_vps.empty() && !_sps.empty() && !_pps.empty(); } @@ -139,25 +131,58 @@ bool H265Track::inputFrame_l(const Frame::Ptr &frame) { } } if (_width == 0 && ready()) { - onReady(); + update(); } return ret; } +toolkit::Buffer::Ptr H265Track::getExtraData() const { + CHECK(ready()); +#ifdef ENABLE_MP4 + struct mpeg4_hevc_t hevc; + memset(&hevc, 0, sizeof(hevc)); + string vps_sps_pps = string("\x00\x00\x00\x01", 4) + _vps + string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; + h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int) vps_sps_pps.size(), NULL, 0, NULL, NULL); + + std::string extra_data; + extra_data.resize(1024); + auto extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, (uint8_t *)extra_data.data(), extra_data.size()); + if (extra_data_size == -1) { + WarnL << "生成H265 extra_data 失败"; + return nullptr; + } + return std::make_shared(std::move(extra_data)); +#else + WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265的支持不完善"; + return nullptr; +#endif +} + +void H265Track::setExtraData(const uint8_t *data, size_t bytes) { +#ifdef ENABLE_MP4 + struct mpeg4_hevc_t hevc; + memset(&hevc, 0, sizeof(hevc)); + if (mpeg4_hevc_decoder_configuration_record_load(data, bytes, &hevc) > 0) { + std::vector config(bytes * 2); + int size = mpeg4_hevc_to_nalu(&hevc, config.data(), bytes * 2); + if (size > 4) { + splitH264((char *)config.data(), size, 4, [&](const char *ptr, size_t len, size_t prefix) { + inputFrame_l(std::make_shared((char *)ptr, len, 0, 0, prefix)); + }); + update(); + } + } +#else + WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265的支持不完善"; +#endif +} + bool H265Track::update() { return getHEVCInfo(_vps, _sps, _width, _height, _fps); } -void H265Track::onReady() { - if (!getHEVCInfo(_vps, _sps, _width, _height, _fps)) { - _vps.clear(); - _sps.clear(); - _pps.clear(); - } -} - -Track::Ptr H265Track::clone() { - return std::make_shared::type>(*this); +Track::Ptr H265Track::clone() const { + return std::make_shared(*this); } void H265Track::insertConfigFrame(const Frame::Ptr &frame) { @@ -205,17 +230,13 @@ public: * @param payload_type rtp payload type 默认96 * @param bitrate 比特率 */ - H265Sdp(const string &strVPS, - const string &strSPS, - const string &strPPS, - int bitrate = 4000, - int payload_type = 96) : Sdp(90000,payload_type) { + H265Sdp(const string &strVPS, const string &strSPS, const string &strPPS, int payload_type, int bitrate) : Sdp(90000, payload_type) { //视频通道 _printer << "m=video 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << 90000 << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecH265) << "/" << 90000 << "\r\n"; _printer << "a=fmtp:" << payload_type << " "; _printer << "sprop-vps="; _printer << encodeBase64(strVPS) << "; "; @@ -223,26 +244,20 @@ public: _printer << encodeBase64(strSPS) << "; "; _printer << "sprop-pps="; _printer << encodeBase64(strPPS) << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } - string getSdp() const override { - return _printer; - } + string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecH265; - } private: _StrPrinter _printer; }; -Sdp::Ptr H265Track::getSdp() { - if(!ready()){ +Sdp::Ptr H265Track::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getVps(), getSps(), getPps(), getBitRate() / 1024); + return std::make_shared(_vps, _sps, _pps, payload_type, getBitRate() / 1024); } }//namespace mediakit diff --git a/src/Extension/H265.h b/src/Extension/H265.h index 912f1f46..f2db3b14 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -19,8 +19,6 @@ namespace mediakit { -bool getHEVCInfo(const std::string &strVps, const std::string &strSps, int &iVideoWidth, int &iVideoHeight, float &iVideoFps); - template class H265FrameHelper : public Parent{ public: @@ -64,8 +62,6 @@ public: this->_codec_id = CodecH265; } - ~H265FrameHelper() override = default; - bool keyFrame() const override { auto nal_ptr = (uint8_t *) this->data() + this->prefixSize(); auto type = H265_TYPE(*nal_ptr); @@ -137,25 +133,19 @@ public: */ H265Track(const std::string &vps,const std::string &sps, const std::string &pps,int vps_prefix_len = 4, int sps_prefix_len = 4, int pps_prefix_len = 4); - /** - * 返回不带0x00 00 00 01头的vps/sps/pps - */ - const std::string &getVps() const; - const std::string &getSps() const; - const std::string &getPps() const; - - bool ready() override; + bool ready() const override; CodecId getCodecId() const override; int getVideoWidth() const override; int getVideoHeight() const override; float getVideoFps() const override; bool inputFrame(const Frame::Ptr &frame) override; + toolkit::Buffer::Ptr getExtraData() const override; + void setExtraData(const uint8_t *data, size_t size) override; bool update() override; private: - void onReady(); - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; bool inputFrame_l(const Frame::Ptr &frame); void insertConfigFrame(const Frame::Ptr &frame); diff --git a/src/Extension/H265Rtmp.cpp b/src/Extension/H265Rtmp.cpp index af685d36..175d4ba1 100644 --- a/src/Extension/H265Rtmp.cpp +++ b/src/Extension/H265Rtmp.cpp @@ -8,8 +8,9 @@ * may be found in the AUTHORS file in the root of the source tree. */ -#include "Rtmp/utils.h" #include "H265Rtmp.h" +#include "Rtmp/utils.h" +#include "Common/config.h" #ifdef ENABLE_MP4 #include "mpeg4-hevc.h" #endif // ENABLE_MP4 @@ -19,48 +20,6 @@ using namespace toolkit; namespace mediakit { -H265RtmpDecoder::H265RtmpDecoder() { - _h265frame = obtainFrame(); -} - -H265Frame::Ptr H265RtmpDecoder::obtainFrame() { - auto frame = FrameImp::create(); - frame->_prefix_size = 4; - return frame; -} - -#ifdef ENABLE_MP4 - -static bool decode_HEVCDecoderConfigurationRecord(uint8_t *extra, size_t bytes, string &frame) { - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - if (mpeg4_hevc_decoder_configuration_record_load((uint8_t *)extra, bytes, &hevc) > 0) { - uint8_t *config = new uint8_t[bytes * 2]; - int size = mpeg4_hevc_to_nalu(&hevc, config, bytes * 2); - if (size > 4) { - frame.assign((char *)config + 4, size - 4); - } - delete[] config; - return size > 4; - } - return false; -} - -/** - * 返回不带0x00 00 00 01头的sps - */ -static bool getH265ConfigFrame(const RtmpPacket &thiz, string &frame) { - if ((RtmpVideoCodec)thiz.getRtmpCodecId() != RtmpVideoCodec::h265) { - return false; - } - if (thiz.buffer.size() < 6) { - WarnL << "bad H265 cfg!"; - return false; - } - return decode_HEVCDecoderConfigurationRecord((uint8_t *)thiz.buffer.data() + 5, thiz.buffer.size() - 5, frame); -} -#endif - void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { if (_info.codec == CodecInvalid) { // 先判断是否为增强型rtmp @@ -73,75 +32,47 @@ void H265RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) { if (!_info.is_enhanced || _info.codec != CodecH265) { throw std::invalid_argument("Invalid enhanced-rtmp hevc packet!"); } - auto data = (uint8_t *)pkt->data() + 5; - auto size = pkt->size() - 5; + switch (_info.video.pkt_type) { case RtmpPacketType::PacketTypeSequenceStart: { -#ifdef ENABLE_MP4 - string config; - if (decode_HEVCDecoderConfigurationRecord(data, size, config)) { - onGetH265(config.data(), config.size(), pkt->time_stamp, pkt->time_stamp); - } -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif + getTrack()->setExtraData((uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize, pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize); break; } case RtmpPacketType::PacketTypeCodedFramesX: case RtmpPacketType::PacketTypeCodedFrames: { + auto data = (uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize; + auto size = pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize; auto pts = pkt->time_stamp; + CHECK(size > 3); if (RtmpPacketType::PacketTypeCodedFrames == _info.video.pkt_type) { // SI24 = [CompositionTime Offset] - CHECK(size > 7); int32_t cts = (((data[0] << 16) | (data[1] << 8) | (data[2])) + 0xff800000) ^ 0xff800000; pts += cts; data += 3; size -= 3; } + CHECK(size > 4); splitFrame(data, size, pkt->time_stamp, pts); break; } - - case RtmpPacketType::PacketTypeMetadata: { - // The body does not contain video data. The body is an AMF encoded metadata. - // The metadata will be represented by a series of [name, value] pairs. - // For now the only defined [name, value] pair is [“colorInfo”, Object] - // See Metadata Frame section for more details of this object. - // - // For a deeper understanding of the encoding please see description - // of SCRIPTDATA and SSCRIPTDATAVALUE in the FLV file spec. - // DATA = [“colorInfo”, Object] - break; - } - case RtmpPacketType::PacketTypeSequenceEnd: { - // signals end of sequence - break; - } - default: break; + default: WarnL << "Unknown pkt_type: " << (int)_info.video.pkt_type; break; } return; } // 国内扩展(12) H265 rtmp if (pkt->isConfigFrame()) { -#ifdef ENABLE_MP4 - string config; - if (getH265ConfigFrame(*pkt, config)) { - onGetH265(config.data(), config.size(), pkt->time_stamp, pkt->time_stamp); - } -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif + CHECK(pkt->size() > 5); + getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5); return; } - if (pkt->buffer.size() > 9) { - uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); - int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; - auto pts = pkt->time_stamp + cts; - splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); - } + CHECK(pkt->size() > 9); + uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2); + int32_t cts = (((cts_ptr[0] << 16) | (cts_ptr[1] << 8) | (cts_ptr[2])) + 0xff800000) ^ 0xff800000; + auto pts = pkt->time_stamp + cts; + splitFrame((uint8_t *)pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pts); } void H265RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts) { @@ -152,100 +83,51 @@ void H265RtmpDecoder::splitFrame(const uint8_t *data, size_t size, uint32_t dts, if (data + frame_len > end) { break; } - onGetH265((const char *)data, frame_len, dts, pts); + outputFrame((const char *)data, frame_len, dts, pts); data += frame_len; } } -inline void H265RtmpDecoder::onGetH265(const char *data, size_t size, uint32_t dts, uint32_t pts) { - if (size == 0) { - return; - } -#if 1 - _h265frame->_dts = dts; - _h265frame->_pts = pts; - _h265frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加265头 - _h265frame->_buffer.append(data, size); - - // 写入环形缓存 - RtmpCodec::inputFrame(_h265frame); - _h265frame = obtainFrame(); -#else - // 防止内存拷贝,这样产生的265帧不会有0x00 00 01头 - auto frame = std::make_shared((char *)data, size, dts, pts, 0); +inline void H265RtmpDecoder::outputFrame(const char *data, size_t size, uint32_t dts, uint32_t pts) { + auto frame = FrameImp::create(); + frame->_prefix_size = 4; + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01", 4); // 添加265头 + frame->_buffer.append(data, size); RtmpCodec::inputFrame(frame); -#endif } //////////////////////////////////////////////////////////////////////// -H265RtmpEncoder::H265RtmpEncoder(const Track::Ptr &track) { - _track = dynamic_pointer_cast(track); -} - -void H265RtmpEncoder::makeConfigPacket() { - if (_track && _track->ready()) { - // 尝试从track中获取sps pps信息 - _sps = _track->getSps(); - _pps = _track->getPps(); - _vps = _track->getVps(); - } - - if (!_sps.empty() && !_pps.empty() && !_vps.empty()) { - // 获取到sps/pps - makeVideoConfigPkt(); - _got_config_frame = true; - } -} - void H265RtmpEncoder::flush() { inputFrame(nullptr); } bool H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) { - if (frame) { - auto data = frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); - auto type = H265_TYPE(data[0]); - switch (type) { - case H265Frame::NAL_SPS: { - if (!_got_config_frame) { - _sps = string(data, len); - makeConfigPacket(); - } - break; - } - case H265Frame::NAL_PPS: { - if (!_got_config_frame) { - _pps = string(data, len); - makeConfigPacket(); - } - break; - } - case H265Frame::NAL_VPS: { - if (!_got_config_frame) { - _vps = string(data, len); - makeConfigPacket(); - } - break; - } - default: break; - } - } - if (!_rtmp_packet) { _rtmp_packet = RtmpPacket::create(); - // flags/not_config/cts预占位 - _rtmp_packet->buffer.resize(5); + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + _rtmp_packet->buffer.resize((enhanced ? RtmpPacketInfo::kEnhancedRtmpHeaderSize : 2) + 3); } return _merger.inputFrame(frame, [this](uint64_t dts, uint64_t pts, const Buffer::Ptr &, bool have_key_frame) { - // flags - _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h265 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); - _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + if (enhanced) { + auto header = (RtmpVideoHeaderEnhanced *)_rtmp_packet->data(); + header->enhanced = 1; + header->pkt_type = (int)RtmpPacketType::PacketTypeCodedFrames; + header->frame_type = have_key_frame ? (int)RtmpFrameType::key_frame : (int)RtmpFrameType::inter_frame; + header->fourcc = htonl((uint32_t)RtmpVideoCodec::fourcc_hevc); + } else { + // flags + _rtmp_packet->buffer[0] = (uint8_t)RtmpVideoCodec::h265 | ((uint8_t)(have_key_frame ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4); + _rtmp_packet->buffer[1] = (uint8_t)RtmpH264PacketType::h264_nalu; + } + int32_t cts = pts - dts; // cts - set_be24(&_rtmp_packet->buffer[2], cts); + set_be24(&_rtmp_packet->buffer[enhanced ? 5 : 2], cts); _rtmp_packet->time_stamp = dts; _rtmp_packet->body_size = _rtmp_packet->buffer.size(); _rtmp_packet->chunk_id = CHUNK_VIDEO; @@ -257,38 +139,36 @@ bool H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) { }, &_rtmp_packet->buffer); } -void H265RtmpEncoder::makeVideoConfigPkt() { -#ifdef ENABLE_MP4 - auto flags = (uint8_t)RtmpVideoCodec::h265; - flags |= ((uint8_t)RtmpFrameType::key_frame << 4); +void H265RtmpEncoder::makeConfigPacket() { auto pkt = RtmpPacket::create(); - // header - pkt->buffer.push_back(flags); - pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); - // cts - pkt->buffer.append("\x0\x0\x0", 3); - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - string vps_sps_pps = string("\x00\x00\x00\x01", 4) + _vps + string("\x00\x00\x00\x01", 4) + _sps + string("\x00\x00\x00\x01", 4) + _pps; - h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int)vps_sps_pps.size(), NULL, 0, NULL, NULL); - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H265 extra_data 失败"; - return; + GET_CONFIG(bool, enhanced, Rtmp::kEnhanced); + if (enhanced) { + pkt->buffer.resize(RtmpPacketInfo::kEnhancedRtmpHeaderSize); + auto header = (RtmpVideoHeaderEnhanced *)pkt->data(); + header->enhanced = 1; + header->pkt_type = (int)RtmpPacketType::PacketTypeSequenceStart; + header->frame_type = (int)RtmpFrameType::key_frame; + header->fourcc = htonl((uint32_t)RtmpVideoCodec::fourcc_hevc); + } else { + auto flags = (uint8_t)RtmpVideoCodec::h265; + flags |= ((uint8_t)RtmpFrameType::key_frame << 4); + // header + pkt->buffer.push_back(flags); + pkt->buffer.push_back((uint8_t)RtmpH264PacketType::h264_config_header); + // cts + pkt->buffer.append("\x0\x0\x0", 3); } + // HEVCDecoderConfigurationRecord - pkt->buffer.append((char *)extra_data, extra_data_size); + auto extra_data = getTrack()->getExtraData(); + CHECK(extra_data); + pkt->buffer.append(extra_data->data(), extra_data->size()); pkt->body_size = pkt->buffer.size(); pkt->chunk_id = CHUNK_VIDEO; pkt->stream_index = STREAM_MEDIA; pkt->time_stamp = 0; pkt->type_id = MSG_VIDEO; RtmpCodec::inputRtmp(pkt); -#else - WarnL << "请开启MP4相关功能并使能\"ENABLE_MP4\",否则对H265-RTMP支持不完善"; -#endif } } // namespace mediakit diff --git a/src/Extension/H265Rtmp.h b/src/Extension/H265Rtmp.h index 527728f6..94dbb501 100644 --- a/src/Extension/H265Rtmp.h +++ b/src/Extension/H265Rtmp.h @@ -24,8 +24,7 @@ class H265RtmpDecoder : public RtmpCodec { public: using Ptr = std::shared_ptr; - H265RtmpDecoder(); - ~H265RtmpDecoder() = default; + H265RtmpDecoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入265 Rtmp包 @@ -33,23 +32,18 @@ public: */ void inputRtmp(const RtmpPacket::Ptr &rtmp) override; - CodecId getCodecId() const override { return CodecH265; } - protected: - H265Frame::Ptr obtainFrame(); - - void onGetH265(const char *data, size_t size, uint32_t dts, uint32_t pts); + void outputFrame(const char *data, size_t size, uint32_t dts, uint32_t pts); void splitFrame(const uint8_t *data, size_t size, uint32_t dts, uint32_t pts); protected: RtmpPacketInfo _info; - H265Frame::Ptr _h265frame; }; /** * 265 Rtmp打包类 */ -class H265RtmpEncoder : public H265RtmpDecoder { +class H265RtmpEncoder : public RtmpCodec { public: using Ptr = std::shared_ptr; @@ -59,8 +53,7 @@ public: * 那么inputFrame时可以不输入sps pps * @param track */ - H265RtmpEncoder(const Track::Ptr &track); - ~H265RtmpEncoder() = default; + H265RtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {} /** * 输入265帧,可以不带sps pps @@ -79,14 +72,6 @@ public: void makeConfigPacket() override; private: - void makeVideoConfigPkt(); - -private: - bool _got_config_frame = false; - std::string _vps; - std::string _sps; - std::string _pps; - H265Track::Ptr _track; RtmpPacket::Ptr _rtmp_packet; FrameMerger _merger { FrameMerger::mp4_nal_size }; }; diff --git a/src/Extension/H265Rtp.cpp b/src/Extension/H265Rtp.cpp index 22866ff4..dbce564e 100644 --- a/src/Extension/H265Rtp.cpp +++ b/src/Extension/H265Rtp.cpp @@ -248,20 +248,8 @@ void H265RtpDecoder::outputFrame(const RtpPacket::Ptr &rtp, const H265Frame::Ptr //////////////////////////////////////////////////////////////////////// -H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PayloadType, - uint8_t ui8Interleaved) : - RtpInfo(ui32Ssrc, - ui32MtuSize, - ui32SampleRate, - ui8PayloadType, - ui8Interleaved) { -} - void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - auto max_size = getMaxSize() - 3; + auto max_size = getRtpInfo().getMaxSize() - 3; auto nal_type = H265_TYPE(ptr[0]); //获取NALU的5bit 帧类型 unsigned char s_e_flags; bool fu_start = true; @@ -283,7 +271,7 @@ void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i { // 传入nullptr先不做payload的内存拷贝 - auto rtp = makeRtp(getTrackType(), nullptr, max_size + 3, mark_bit, pts); + auto rtp = getRtpInfo().makeRtp(TrackVideo, nullptr, max_size + 3, mark_bit, pts); // rtp payload 负载部分 uint8_t *payload = rtp->getPayload(); // FU 第1个字节,表明为FU @@ -304,9 +292,9 @@ void H265RtpEncoder::packRtpFu(const char *ptr, size_t len, uint64_t pts, bool i } void H265RtpEncoder::packRtp(const char *ptr, size_t len, uint64_t pts, bool is_mark, bool gop_pos){ - if (len <= getMaxSize()) { + if (len <= getRtpInfo().getMaxSize()) { //signal-nalu - RtpCodec::inputRtp(makeRtp(getTrackType(), ptr, len, is_mark, pts), gop_pos); + RtpCodec::inputRtp(getRtpInfo().makeRtp(TrackVideo, ptr, len, is_mark, pts), gop_pos); } else { //FU-A模式 packRtpFu(ptr, len, pts, is_mark, gop_pos); diff --git a/src/Extension/H265Rtp.h b/src/Extension/H265Rtp.h index 569d8091..67d91e60 100644 --- a/src/Extension/H265Rtp.h +++ b/src/Extension/H265Rtp.h @@ -28,7 +28,6 @@ public: using Ptr = std::shared_ptr; H265RtpDecoder(); - ~H265RtpDecoder() {} /** * 输入265 rtp包 @@ -37,10 +36,6 @@ public: */ bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; - CodecId getCodecId() const override{ - return CodecH265; - } - private: bool unpackAp(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp); bool mergeFu(const RtpPacket::Ptr &rtp, const uint8_t *ptr, ssize_t size, uint64_t stamp, uint16_t seq); @@ -63,24 +58,10 @@ private: /** * 265 rtp打包类 */ -class H265RtpEncoder : public H265RtpDecoder ,public RtpInfo{ +class H265RtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - /** - * @param ui32Ssrc ssrc - * @param ui32MtuSize mtu大小 - * @param ui32SampleRate 采样率,强制为90000 - * @param ui8PayloadType pt类型 - * @param ui8Interleaved rtsp interleaved - */ - H265RtpEncoder(uint32_t ui32Ssrc, - uint32_t ui32MtuSize = 1400, - uint32_t ui32SampleRate = 90000, - uint8_t ui8PayloadType = 96, - uint8_t ui8Interleaved = TrackVideo * 2); - ~H265RtpEncoder() {} - /** * 输入265帧 * @param frame 帧数据,必须 diff --git a/src/Extension/JPEG.cpp b/src/Extension/JPEG.cpp index de024a03..52d98073 100644 --- a/src/Extension/JPEG.cpp +++ b/src/Extension/JPEG.cpp @@ -31,23 +31,20 @@ void JPEGTrack::getVideoResolution(const uint8_t *buf, int len) { class JPEGSdp : public Sdp { public: - JPEGSdp(int bitrate): Sdp(90000, Rtsp::PT_JPEG) { + JPEGSdp(int bitrate) : Sdp(90000, Rtsp::PT_JPEG) { _printer << "m=video 0 RTP/AVP " << (int)getPayloadType() << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=control:trackID=" << (int)TrackVideo << "\r\n"; } std::string getSdp() const { return _printer; } - CodecId getCodecId() const { return CodecJPEG; } - private: _StrPrinter _printer; }; -Sdp::Ptr JPEGTrack::getSdp() { +Sdp::Ptr JPEGTrack::getSdp(uint8_t) const { return std::make_shared(getBitRate() / 1024); } } // namespace mediakit diff --git a/src/Extension/JPEG.h b/src/Extension/JPEG.h index 016c6620..d9e6006d 100644 --- a/src/Extension/JPEG.h +++ b/src/Extension/JPEG.h @@ -14,12 +14,12 @@ public: int getVideoHeight() const override { return _height; } int getVideoWidth() const override { return _width; } float getVideoFps() const override { return _fps; } - bool ready() override { return _fps > 0; } + bool ready() const override { return _fps > 0; } bool inputFrame(const Frame::Ptr &frame) override; private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override { return std::make_shared::type>(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override { return std::make_shared(*this); } void getVideoResolution(const uint8_t *buf, int len); private: @@ -31,35 +31,36 @@ private: class JPEGFrame : public Frame { public: + static constexpr auto kJFIFSize = 20u; /** * JPEG/MJPEG帧 * @param buffer 帧数据 * @param dts 时间戳,单位毫秒 * @param pix_type pixel format type; AV_PIX_FMT_YUVJ422P || (AVCOL_RANGE_JPEG && AV_PIX_FMT_YUV422P) : 1; AV_PIX_FMT_YUVJ420P || (AVCOL_RANGE_JPEG && AV_PIX_FMT_YUV420P) : 0 - * @param prefix_size JFIF头大小 + * @param offset buffer有效帧数据偏移量 */ - JPEGFrame(toolkit::Buffer::Ptr buffer, uint64_t dts, uint8_t pix_type = 0, size_t prefix_size = 0) { + JPEGFrame(toolkit::Buffer::Ptr buffer, uint64_t dts, uint8_t pix_type = 0, size_t offset = 0) { _buffer = std::move(buffer); _dts = dts; _pix_type = pix_type; - _prefix_size = prefix_size; + _offset = offset; + // JFIF头固定20个字节长度 + CHECK(_buffer->size() > _offset + kJFIFSize); } - ~JPEGFrame() override = default; - uint64_t dts() const override { return _dts; } - size_t prefixSize() const override { return _prefix_size; } + size_t prefixSize() const override { return 0; } bool keyFrame() const override { return true; } bool configFrame() const override { return false; } CodecId getCodecId() const override { return CodecJPEG; } - char *data() const override { return _buffer->data(); } - size_t size() const override { return _buffer->size(); } + char *data() const override { return _buffer->data() + _offset; } + size_t size() const override { return _buffer->size() - _offset; } - uint8_t pixType() const {return _pix_type; } + uint8_t pixType() const { return _pix_type; } private: uint8_t _pix_type; - size_t _prefix_size; + size_t _offset; uint64_t _dts; toolkit::Buffer::Ptr _buffer; }; diff --git a/src/Extension/JPEGRtp.cpp b/src/Extension/JPEGRtp.cpp index 384f8296..c4fa1854 100644 --- a/src/Extension/JPEGRtp.cpp +++ b/src/Extension/JPEGRtp.cpp @@ -745,10 +745,10 @@ void JPEGRtpEncoder::rtpSendJpeg(const uint8_t *buf, int size, uint64_t pts, uin hdr_size += 4 + 64 * nb_qtables; /* payload max in one packet */ - len = MIN(size, (int)getMaxSize() - hdr_size); + len = MIN(size, (int)getRtpInfo().getMaxSize() - hdr_size); /* marker bit is last packet in frame */ - auto rtp_packet = makeRtp(getTrackType(), nullptr, len + hdr_size, size == len, pts); + auto rtp_packet = getRtpInfo().makeRtp(TrackVideo, nullptr, len + hdr_size, size == len, pts); p = rtp_packet->getPayload(); /* set main header */ @@ -788,10 +788,6 @@ JPEGRtpDecoder::JPEGRtpDecoder() { memset(&_ctx.timestamp, 0, sizeof(_ctx) - offsetof(decltype(_ctx), timestamp)); } -CodecId JPEGRtpDecoder::getCodecId() const { - return CodecJPEG; -} - bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { auto payload = rtp->getPayload(); auto size = rtp->getPayloadSize(); @@ -807,7 +803,7 @@ bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { if (0 == jpeg_parse_packet(nullptr, &_ctx, &stamp, payload, size, seq, marker ? RTP_FLAG_MARKER : 0, &type)) { auto buffer = std::make_shared(std::move(_ctx.frame)); // JFIF头固定20个字节长度 - auto frame = std::make_shared(std::move(buffer), stamp / 90, type, 20); + auto frame = std::make_shared(std::move(buffer), stamp / 90, type); _ctx.frame.clear(); RtpCodec::inputFrame(std::move(frame)); } @@ -817,14 +813,10 @@ bool JPEGRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool) { //////////////////////////////////////////////////////////////////////// -JPEGRtpEncoder::JPEGRtpEncoder( - uint32_t ssrc, uint32_t mtu, uint32_t sample_rate, uint8_t payload_type, uint8_t interleaved) - : RtpInfo(ssrc, mtu, sample_rate, payload_type, interleaved) {} - - bool JPEGRtpEncoder::inputFrame(const Frame::Ptr &frame) { - auto ptr = (uint8_t *)frame->data() + frame->prefixSize(); - auto len = frame->size() - frame->prefixSize(); + // JFIF头固定20个字节长度 + auto ptr = (uint8_t *)frame->data() + frame->prefixSize() + JPEGFrame::kJFIFSize; + auto len = frame->size() - frame->prefixSize() - JPEGFrame::kJFIFSize; auto pts = frame->pts(); auto type = 1; auto jpeg = dynamic_pointer_cast(frame); diff --git a/src/Extension/JPEGRtp.h b/src/Extension/JPEGRtp.h index 00b6c47b..db5a4b70 100644 --- a/src/Extension/JPEGRtp.h +++ b/src/Extension/JPEGRtp.h @@ -25,12 +25,6 @@ public: typedef std::shared_ptr Ptr; JPEGRtpDecoder(); - ~JPEGRtpDecoder() override = default; - - /** - * 返回编码类型ID - */ - CodecId getCodecId() const override; /** * 输入rtp并解码 @@ -43,13 +37,10 @@ private: struct PayloadContext _ctx; }; -class JPEGRtpEncoder : public JPEGRtpDecoder, public RtpInfo { +class JPEGRtpEncoder : public RtpCodec { public: using Ptr = std::shared_ptr; - JPEGRtpEncoder(uint32_t ssrc, uint32_t mtu = 1400, uint32_t sample_rate = 90000, uint8_t payload_type = 96, uint8_t interleaved = TrackVideo * 2); - ~JPEGRtpEncoder() = default; - bool inputFrame(const Frame::Ptr &frame) override; private: diff --git a/src/Extension/L16.cpp b/src/Extension/L16.cpp index dff70a2e..3669d75c 100644 --- a/src/Extension/L16.cpp +++ b/src/Extension/L16.cpp @@ -22,47 +22,36 @@ class L16Sdp : public Sdp { public: /** * L16采样位数固定为16位 - * @param codecId CodecL16 + * @param payload_type rtp payload type + * @param channels 通道数 * @param sample_rate 音频采样率 - * @param payload_type rtp payload * @param bitrate 比特率 */ - L16Sdp(CodecId codecId, - int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type), _codecId(codecId){ + L16Sdp(int payload_type, int sample_rate, int channels, int bitrate) : Sdp(sample_rate, payload_type) { _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecL16) << "/" << sample_rate << "/" << channels << "\r\n"; } - string getSdp() const override { - return _printer; - } + string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return _codecId; - } private: _StrPrinter _printer; - CodecId _codecId; }; -Sdp::Ptr L16Track::getSdp() { +Sdp::Ptr L16Track::getSdp(uint8_t payload_type) const { WarnL << "Enter L16Track::getSdp function"; - if(!ready()){ + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getCodecId(), getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); + return std::make_shared(payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); } -Track::Ptr L16Track::clone() { - return std::make_shared::type >(*this); +Track::Ptr L16Track::clone() const { + return std::make_shared(*this); } }//namespace mediakit diff --git a/src/Extension/L16.h b/src/Extension/L16.h index ca58ab8f..adeae1b3 100644 --- a/src/Extension/L16.h +++ b/src/Extension/L16.h @@ -25,8 +25,8 @@ public: L16Track(int sample_rate, int channels) : AudioTrackImp(CodecL16,sample_rate,channels,16){} private: - Sdp::Ptr getSdp() override; - Track::Ptr clone() override; + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; }; }//namespace mediakit diff --git a/src/Extension/Opus.cpp b/src/Extension/Opus.cpp index 0e0100a2..931a9659 100644 --- a/src/Extension/Opus.cpp +++ b/src/Extension/Opus.cpp @@ -22,39 +22,33 @@ class OpusSdp : public Sdp { public: /** * 构造opus sdp + * @param payload_type rtp payload type * @param sample_rate 音频采样率 - * @param payload_type rtp payload + * @param channels 通道数 * @param bitrate 比特率 */ - OpusSdp(int sample_rate, - int channels, - int bitrate = 128, - int payload_type = 98) : Sdp(sample_rate,payload_type){ + OpusSdp(int payload_type, int sample_rate, int channels, int bitrate) : Sdp(sample_rate, payload_type) { _printer << "m=audio 0 RTP/AVP " << payload_type << "\r\n"; if (bitrate) { _printer << "b=AS:" << bitrate << "\r\n"; } - _printer << "a=rtpmap:" << payload_type << " " << getCodecName() << "/" << sample_rate << "/" << channels << "\r\n"; - _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; + _printer << "a=rtpmap:" << payload_type << " " << getCodecName(CodecOpus) << "/" << sample_rate << "/" << channels << "\r\n"; } string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecOpus; - } private: _StrPrinter _printer; }; -Sdp::Ptr OpusTrack::getSdp() { - if(!ready()){ +Sdp::Ptr OpusTrack::getSdp(uint8_t payload_type) const { + if (!ready()) { WarnL << getCodecName() << " Track未准备好"; return nullptr; } - return std::make_shared(getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); + return std::make_shared(payload_type, getAudioSampleRate(), getAudioChannel(), getBitRate() / 1024); } }//namespace mediakit \ No newline at end of file diff --git a/src/Extension/Opus.h b/src/Extension/Opus.h index 08dea847..a734fc26 100644 --- a/src/Extension/Opus.h +++ b/src/Extension/Opus.h @@ -26,11 +26,11 @@ public: private: //克隆该Track - Track::Ptr clone() override { - return std::make_shared::type >(*this); + Track::Ptr clone() const override { + return std::make_shared(*this); } //生成sdp - Sdp::Ptr getSdp() override ; + Sdp::Ptr getSdp(uint8_t payload_type) const override ; }; }//namespace mediakit diff --git a/src/Extension/Track.h b/src/Extension/Track.h index 3a1b8519..a75fd953 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -21,23 +21,32 @@ namespace mediakit{ /** * 媒体通道描述类,也支持帧输入输出 */ -class Track : public FrameDispatcher , public CodecInfo{ +class Track : public FrameDispatcher, public CodecInfo { public: using Ptr = std::shared_ptr; + + /** + * 默认构造 + */ Track() = default; - virtual ~Track() = default; + + /** + * 复制拷贝,只能拷贝派生类的信息, + * 环形缓存和代理关系不能拷贝,否则会关系紊乱 + */ + Track(const Track &that) { _bit_rate = that._bit_rate; } /** * 是否准备好,准备好才能获取譬如sps pps等信息 */ - virtual bool ready() = 0; + virtual bool ready() const = 0; /** * 克隆接口,用于复制本对象用 * 在调用该接口时只会复制派生类的信息 * 环形缓存和代理关系不能拷贝,否则会关系紊乱 */ - virtual Track::Ptr clone() = 0; + virtual Track::Ptr clone() const = 0; /** * 更新track信息,比如触发sps/pps解析 @@ -46,9 +55,19 @@ public: /** * 生成sdp - * @return sdp对象 + * @return sdp对象 */ - virtual Sdp::Ptr getSdp() = 0; + virtual Sdp::Ptr getSdp(uint8_t payload_type) const = 0; + + /** + * 获取extra data, 一般用于rtmp/mp4生成 + */ + virtual toolkit::Buffer::Ptr getExtraData() const { return nullptr; } + + /** + * 设置extra data, + */ + virtual void setExtraData(const uint8_t *data, size_t size) {} /** * 返回比特率 @@ -62,14 +81,6 @@ public: */ virtual void setBitRate(int bit_rate) { _bit_rate = bit_rate; } - /** - * 复制拷贝,只能拷贝派生类的信息, - * 环形缓存和代理关系不能拷贝,否则会关系紊乱 - */ - Track(const Track &that){ - _bit_rate = that._bit_rate; - } - private: int _bit_rate = 0; }; @@ -97,6 +108,40 @@ public: virtual float getVideoFps() const { return 0; } }; +class VideoTrackImp : public VideoTrack { +public: + using Ptr = std::shared_ptr; + + /** + * 构造函数 + * @param codec_id 编码类型 + * @param width 宽 + * @param height 高 + * @param fps 帧率 + */ + VideoTrackImp(CodecId codec_id, int width, int height, int fps) { + _codec_id = codec_id; + _width = width; + _height = height; + _fps = fps; + } + + int getVideoHeight() const override { return _width; } + int getVideoWidth() const override { return _height; } + float getVideoFps() const override { return _fps; } + bool ready() const override { return true; } + + Track::Ptr clone() const override { return std::make_shared(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } + CodecId getCodecId() const override { return _codec_id; } + +private: + CodecId _codec_id; + int _width = 0; + int _height = 0; + float _fps = 0; +}; + /** * 音频Track派生类,支持采样率通道数,采用位数信息 */ @@ -131,7 +176,7 @@ public: * @param channels 通道数 * @param sample_bit 采样位数,一般为16 */ - AudioTrackImp(CodecId codecId,int sample_rate, int channels, int sample_bit){ + AudioTrackImp(CodecId codecId, int sample_rate, int channels, int sample_bit){ _codecid = codecId; _sample_rate = sample_rate; _channels = channels; @@ -148,7 +193,7 @@ public: /** * 是否已经初始化 */ - bool ready() override { + bool ready() const override { return true; } @@ -172,6 +217,10 @@ public: int getAudioChannel() const override{ return _channels; } + + Track::Ptr clone() const override { return std::make_shared(*this); } + Sdp::Ptr getSdp(uint8_t payload_type) const override { return nullptr; } + private: CodecId _codecid; int _sample_rate; @@ -179,9 +228,8 @@ private: int _sample_bit; }; -class TrackSource{ +class TrackSource { public: - TrackSource() = default; virtual ~TrackSource() = default; /** diff --git a/src/FMP4/FMP4MediaSource.h b/src/FMP4/FMP4MediaSource.h index 13674ebe..8609b86c 100644 --- a/src/FMP4/FMP4MediaSource.h +++ b/src/FMP4/FMP4MediaSource.h @@ -26,7 +26,6 @@ public: template FMP4Packet(ARGS && ...args) : toolkit::BufferString(std::forward(args)...) {}; - ~FMP4Packet() override = default; public: uint64_t time_stamp = 0; diff --git a/src/Http/HlsParser.h b/src/Http/HlsParser.h index c54fc6e5..ec1640aa 100644 --- a/src/Http/HlsParser.h +++ b/src/Http/HlsParser.h @@ -36,9 +36,6 @@ typedef struct{ class HlsParser { public: - HlsParser() = default; - ~HlsParser() = default; - bool parse(const std::string &http_url,const std::string &m3u8); /** diff --git a/src/Http/HlsPlayer.h b/src/Http/HlsPlayer.h index 82cd2696..fac11c4c 100644 --- a/src/Http/HlsPlayer.h +++ b/src/Http/HlsPlayer.h @@ -25,7 +25,6 @@ namespace mediakit { class HlsDemuxer : public MediaSinkInterface , public TrackSource, public std::enable_shared_from_this { public: - HlsDemuxer() = default; ~HlsDemuxer() override { _timer = nullptr; } void start(const toolkit::EventPoller::Ptr &poller, TrackListener *listener); @@ -53,7 +52,6 @@ private: class HlsPlayer : public HttpClientImp , public PlayerBase , public HlsParser{ public: HlsPlayer(const toolkit::EventPoller::Ptr &poller); - ~HlsPlayer() override = default; /** * 开始播放 @@ -120,7 +118,6 @@ class HlsPlayerImp : public PlayerImp, private TrackListe public: using Ptr = std::shared_ptr; HlsPlayerImp(const toolkit::EventPoller::Ptr &poller = nullptr); - ~HlsPlayerImp() override = default; private: //// HlsPlayer override//// diff --git a/src/Http/HttpBody.cpp b/src/Http/HttpBody.cpp index a2442750..da3ec8b1 100644 --- a/src/Http/HttpBody.cpp +++ b/src/Http/HttpBody.cpp @@ -189,7 +189,6 @@ public: _data = map_addr.get() + offset; _size = size; } - ~BufferMmap() override = default; //返回数据长度 char *data() const override { return _data; } size_t size() const override { return _size; } diff --git a/src/Http/HttpBody.h b/src/Http/HttpBody.h index a23de2b1..668d344d 100644 --- a/src/Http/HttpBody.h +++ b/src/Http/HttpBody.h @@ -30,8 +30,6 @@ namespace mediakit { class HttpBody : public std::enable_shared_from_this{ public: using Ptr = std::shared_ptr; - HttpBody() = default; - virtual ~HttpBody() = default; /** @@ -75,7 +73,6 @@ class HttpStringBody : public HttpBody{ public: using Ptr = std::shared_ptr; HttpStringBody(std::string str); - ~HttpStringBody() override = default; int64_t remainSize() override; toolkit::Buffer::Ptr readData(size_t size) override ; @@ -92,7 +89,6 @@ class HttpBufferBody : public HttpBody{ public: using Ptr = std::shared_ptr; HttpBufferBody(toolkit::Buffer::Ptr buffer); - ~HttpBufferBody() override = default; int64_t remainSize() override; toolkit::Buffer::Ptr readData(size_t size) override; @@ -114,7 +110,6 @@ public: * @param use_mmap 是否使用mmap方式访问文件 */ HttpFileBody(const std::string &file_path, bool use_mmap = true); - ~HttpFileBody() override = default; /** * 设置读取范围 @@ -151,7 +146,6 @@ public: * @param boundary boundary字符串 */ HttpMultiFormBody(const HttpArgs &args,const std::string &filePath,const std::string &boundary = "0xKhTmLbOuNdArY"); - virtual ~HttpMultiFormBody() = default; int64_t remainSize() override ; toolkit::Buffer::Ptr readData(size_t size) override; diff --git a/src/Http/HttpClient.cpp b/src/Http/HttpClient.cpp index fbe76eab..6ce4c509 100644 --- a/src/Http/HttpClient.cpp +++ b/src/Http/HttpClient.cpp @@ -235,7 +235,7 @@ ssize_t HttpClient::onRecvHeader(const char *data, size_t len) { _total_body_size = _recved_body_size; if (_recved_body_size > 0) { onResponseCompleted_l(SockException(Err_success, "success")); - }else{ + } else { onResponseCompleted_l(SockException(Err_other, "no body")); } } diff --git a/src/Http/HttpClient.h b/src/Http/HttpClient.h index 813562e8..16198b84 100644 --- a/src/Http/HttpClient.h +++ b/src/Http/HttpClient.h @@ -29,9 +29,6 @@ namespace mediakit { class HttpArgs : public std::map { public: - HttpArgs() = default; - ~HttpArgs() = default; - std::string make() const { std::string ret; for (auto &pr : *this) { @@ -52,9 +49,6 @@ public: using HttpHeader = StrCaseMap; using Ptr = std::shared_ptr; - HttpClient() = default; - ~HttpClient() override = default; - /** * 发送http[s]请求 * @param url 请求url diff --git a/src/Http/HttpClientImp.h b/src/Http/HttpClientImp.h index 2d32f065..ba5849a1 100644 --- a/src/Http/HttpClientImp.h +++ b/src/Http/HttpClientImp.h @@ -19,8 +19,6 @@ namespace mediakit { class HttpClientImp : public toolkit::TcpClientWithSSL { public: using Ptr = std::shared_ptr; - HttpClientImp() = default; - ~HttpClientImp() override = default; protected: void onConnect(const toolkit::SockException &ex) override; diff --git a/src/Http/HttpCookie.h b/src/Http/HttpCookie.h index 60e3fbcb..af3cfdee 100644 --- a/src/Http/HttpCookie.h +++ b/src/Http/HttpCookie.h @@ -27,8 +27,6 @@ class HttpCookie { public: using Ptr = std::shared_ptr; friend class HttpCookieStorage; - HttpCookie() = default; - ~HttpCookie() = default; void setPath(const std::string &path); void setHost(const std::string &host); @@ -52,7 +50,6 @@ private: */ class HttpCookieStorage{ public: - ~HttpCookieStorage() = default; static HttpCookieStorage &Instance(); void set(const HttpCookie::Ptr &cookie); std::vector get(const std::string &host,const std::string &path); diff --git a/src/Http/HttpCookieManager.h b/src/Http/HttpCookieManager.h index 53775b79..2053cd43 100644 --- a/src/Http/HttpCookieManager.h +++ b/src/Http/HttpCookieManager.h @@ -113,8 +113,6 @@ private: */ class RandStrGenerator { public: - RandStrGenerator() = default; - ~RandStrGenerator() = default; /** * 获取不碰撞的随机字符串 diff --git a/src/Http/HttpDownloader.h b/src/Http/HttpDownloader.h index 44a198a6..236d7502 100644 --- a/src/Http/HttpDownloader.h +++ b/src/Http/HttpDownloader.h @@ -20,7 +20,6 @@ public: using Ptr = std::shared_ptr; using onDownloadResult = std::function; - HttpDownloader() = default; ~HttpDownloader() override; /** diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index dfb499a0..9beebbd8 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -300,8 +300,6 @@ static bool emitHlsPlayed(const Parser &parser, const MediaInfo &media_info, con class SockInfoImp : public SockInfo{ public: using Ptr = std::shared_ptr; - SockInfoImp() = default; - ~SockInfoImp() override = default; string get_local_ip() override { return _local_ip; diff --git a/src/Http/HttpFileManager.h b/src/Http/HttpFileManager.h index a3c0c1f3..cf6efcee 100644 --- a/src/Http/HttpFileManager.h +++ b/src/Http/HttpFileManager.h @@ -24,8 +24,6 @@ public: typedef std::function HttpResponseInvokerLambda0; typedef std::function HttpResponseInvokerLambda1; - HttpResponseInvokerImp() = default; - ~HttpResponseInvokerImp() = default; template HttpResponseInvokerImp(const C &c):HttpResponseInvokerImp(typename toolkit::function_traits::stl_function_type(c)) {} HttpResponseInvokerImp(const HttpResponseInvokerLambda0 &lambda); diff --git a/src/Http/HttpRequestSplitter.cpp b/src/Http/HttpRequestSplitter.cpp index a7883f2f..1c9dac2c 100644 --- a/src/Http/HttpRequestSplitter.cpp +++ b/src/Http/HttpRequestSplitter.cpp @@ -22,7 +22,7 @@ namespace mediakit { void HttpRequestSplitter::input(const char *data,size_t len) { { auto size = remainDataSize(); - if (size > kMaxCacheSize) { + if (size > _max_cache_size) { //缓存太多数据无法处理则上抛异常 reset(); throw std::out_of_range("remain data size is too huge, now cleared:" + to_string(size)); @@ -142,6 +142,16 @@ const char *HttpRequestSplitter::remainData() const { return _remain_data.data(); } +void HttpRequestSplitter::setMaxCacheSize(size_t max_cache_size) { + if (!max_cache_size) { + max_cache_size = kMaxCacheSize; + } + _max_cache_size = max_cache_size; +} + +HttpRequestSplitter::HttpRequestSplitter() { + setMaxCacheSize(0); +} } /* namespace mediakit */ diff --git a/src/Http/HttpRequestSplitter.h b/src/Http/HttpRequestSplitter.h index 5ad78bea..258f040a 100644 --- a/src/Http/HttpRequestSplitter.h +++ b/src/Http/HttpRequestSplitter.h @@ -18,7 +18,7 @@ namespace mediakit { class HttpRequestSplitter { public: - HttpRequestSplitter() = default; + HttpRequestSplitter(); virtual ~HttpRequestSplitter() = default; /** @@ -44,6 +44,11 @@ public: */ const char *remainData() const; + /** + * 设置最大缓存大小 + */ + void setMaxCacheSize(size_t max_cache_size); + protected: /** * 收到请求头 @@ -80,6 +85,7 @@ protected: private: ssize_t _content_len = 0; + size_t _max_cache_size = 0; size_t _remain_data_size = 0; toolkit::BufferLikeString _remain_data; }; diff --git a/src/Http/HttpRequester.h b/src/Http/HttpRequester.h index 067bb0e8..efeebcdb 100644 --- a/src/Http/HttpRequester.h +++ b/src/Http/HttpRequester.h @@ -20,9 +20,6 @@ public: using Ptr = std::shared_ptr; using HttpRequesterResult = std::function; - HttpRequester() = default; - ~HttpRequester() override = default; - void setOnResult(const HttpRequesterResult &onResult); void startRequester(const std::string &url, const HttpRequesterResult &on_result, float timeout_sec = 10); void setRetry(size_t count, size_t delay); diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index c6d390d1..96751d80 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -24,12 +24,11 @@ using namespace toolkit; namespace mediakit { HttpSession::HttpSession(const Socket::Ptr &pSock) : Session(pSock) { - GET_CONFIG(uint32_t, keep_alive_sec, Http::kKeepAliveSecond); - pSock->setSendTimeOutSecond(keep_alive_sec); + //设置默认参数 + setMaxReqSize(0); + setTimeoutSec(0); } -HttpSession::~HttpSession() = default; - void HttpSession::onHttpRequest_HEAD() { // 暂时全部返回200 OK,因为HTTP GET存在按需生成流的操作,所以不能按照HTTP GET的流程返回 // 如果直接返回404,那么又会导致按需生成流的逻辑失效,所以HTTP HEAD在静态文件或者已存在资源时才有效 @@ -99,11 +98,10 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) { return _on_recv_body ? -1 : 0; } - GET_CONFIG(size_t, maxReqSize, Http::kMaxReqSize); - if (content_len > maxReqSize) { + if (content_len > _max_req_size) { //// 不定长body或超大body //// if (content_len != SIZE_MAX) { - WarnL << "Http body size is too huge: " << content_len << " > " << maxReqSize + WarnL << "Http body size is too huge: " << content_len << " > " << _max_req_size << ", please set " << Http::kMaxReqSize << " in config.ini file."; } @@ -176,11 +174,27 @@ void HttpSession::onError(const SockException &err) { } } -void HttpSession::onManager() { - GET_CONFIG(uint32_t, keepAliveSec, Http::kKeepAliveSecond); +void HttpSession::setTimeoutSec(size_t keep_alive_sec) { + if (!keep_alive_sec) { + GET_CONFIG(size_t, s_keep_alive_sec, Http::kKeepAliveSecond); + keep_alive_sec = s_keep_alive_sec; + } + _keep_alive_sec = keep_alive_sec; + getSock()->setSendTimeOutSecond(keep_alive_sec); +} - if (_ticker.elapsedTime() > keepAliveSec * 1000) { - // 1分钟超时 +void HttpSession::setMaxReqSize(size_t max_req_size) { + if (!max_req_size) { + GET_CONFIG(size_t, s_max_req_size, Http::kMaxReqSize); + max_req_size = s_max_req_size; + } + _max_req_size = max_req_size; + setMaxCacheSize(max_req_size); +} + +void HttpSession::onManager() { + if (_ticker.elapsedTime() > _keep_alive_sec * 1000) { + //http超时 shutdown(SockException(Err_timeout, "session timeout")); } } @@ -509,7 +523,6 @@ public: _body = body; _close_when_complete = close_when_complete; } - ~AsyncSenderData() = default; private: std::weak_ptr _session; diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index 98b43d71..92507d3f 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -40,12 +40,13 @@ public: using HttpAccessPathInvoker = std::function; HttpSession(const toolkit::Socket::Ptr &pSock); - ~HttpSession() override; void onRecv(const toolkit::Buffer::Ptr &) override; void onError(const toolkit::SockException &err) override; void onManager() override; static std::string urlDecode(const std::string &str); + void setTimeoutSec(size_t second); + void setMaxReqSize(size_t max_req_size); protected: //FlvMuxer override @@ -129,6 +130,10 @@ protected: private: bool _is_live_stream = false; bool _live_over_websocket = false; + //超时时间 + size_t _keep_alive_sec = 0; + //最大http请求字节大小 + size_t _max_req_size = 0; //消耗的总流量 uint64_t _total_bytes_usage = 0; Parser _parser; diff --git a/src/Http/HttpTSPlayer.h b/src/Http/HttpTSPlayer.h index d9dfd135..ab5b6ef7 100644 --- a/src/Http/HttpTSPlayer.h +++ b/src/Http/HttpTSPlayer.h @@ -24,7 +24,6 @@ public: using onComplete = std::function; HttpTSPlayer(const toolkit::EventPoller::Ptr &poller = nullptr); - ~HttpTSPlayer() override = default; /** * 设置下载完毕或异常断开回调 diff --git a/src/Http/TsPlayer.h b/src/Http/TsPlayer.h index dfe69996..9f4ab4ec 100644 --- a/src/Http/TsPlayer.h +++ b/src/Http/TsPlayer.h @@ -19,7 +19,6 @@ namespace mediakit { class TsPlayer : public HttpTSPlayer, public PlayerBase { public: TsPlayer(const toolkit::EventPoller::Ptr &poller); - ~TsPlayer() override = default; /** * 开始播放 diff --git a/src/Http/TsPlayerImp.h b/src/Http/TsPlayerImp.h index 5dc32ed2..4796fa48 100644 --- a/src/Http/TsPlayerImp.h +++ b/src/Http/TsPlayerImp.h @@ -21,7 +21,6 @@ public: using Ptr = std::shared_ptr; TsPlayerImp(const toolkit::EventPoller::Ptr &poller = nullptr); - ~TsPlayerImp() override = default; private: //// TsPlayer override//// diff --git a/src/Http/WebSocketClient.h b/src/Http/WebSocketClient.h index 5850b027..f46860d3 100644 --- a/src/Http/WebSocketClient.h +++ b/src/Http/WebSocketClient.h @@ -37,9 +37,7 @@ public: template ClientTypeImp(ArgsType &&...args) : ClientType(std::forward(args)...) {} - ~ClientTypeImp() override = default; -protected: /** * 发送前拦截并打包为websocket协议 */ @@ -50,6 +48,7 @@ protected: return ClientType::send(std::move(buf)); } +protected: /** * 设置发送数据截取回调函数 * @param cb 截取回调函数 @@ -74,7 +73,6 @@ public: _Sec_WebSocket_Key = encodeBase64(toolkit::makeRandStr(16, false)); setPoller(delegate->getPoller()); } - ~HttpWsClient() = default; /** * 发起ws握手 diff --git a/src/Http/WebSocketSession.h b/src/Http/WebSocketSession.h index 8978330c..d57c1512 100644 --- a/src/Http/WebSocketSession.h +++ b/src/Http/WebSocketSession.h @@ -21,7 +21,6 @@ class SendInterceptor{ public: using onBeforeSendCB =std::function; - SendInterceptor() = default; virtual ~SendInterceptor() = default; virtual void setOnBeforeSendCB(const onBeforeSendCB &cb) = 0; }; @@ -38,8 +37,6 @@ public: SessionTypeImp(const mediakit::Parser &header, const mediakit::HttpSession &parent, const toolkit::Socket::Ptr &pSock) : SessionType(pSock) {} - ~SessionTypeImp() = default; - /** * 设置发送数据截取回调函数 * @param cb 截取回调函数 @@ -82,7 +79,6 @@ template,HttpSessionType,DataType>{ public: WebSocketSession(const toolkit::Socket::Ptr &pSock) : WebSocketSessionBase,HttpSessionType,DataType>(pSock){} - virtual ~WebSocketSession() = default; }; #endif //ZLMEDIAKIT_WEBSOCKETSESSION_H diff --git a/src/Http/WebSocketSplitter.h b/src/Http/WebSocketSplitter.h index 72b71664..21be7b72 100644 --- a/src/Http/WebSocketSplitter.h +++ b/src/Http/WebSocketSplitter.h @@ -51,6 +51,7 @@ public: //根据内存地址设置掩码随机数 _mask.assign((uint8_t*)(&ptr), (uint8_t*)(&ptr) + 4); } + virtual ~WebSocketHeader() = default; public: @@ -71,8 +72,6 @@ public: WebSocketBuffer(WebSocketHeader::Type headType, bool fin, ARGS &&...args) : toolkit::BufferString(std::forward(args)...), _fin(fin), _head_type(headType){} - ~WebSocketBuffer() override = default; - WebSocketHeader::Type headType() const { return _head_type; } bool isFinished() const { return _fin; }; @@ -84,9 +83,6 @@ private: class WebSocketSplitter : public WebSocketHeader{ public: - WebSocketSplitter() = default; - virtual ~WebSocketSplitter() = default; - /** * 输入数据以便解包webSocket数据以及处理粘包问题 * 可能触发onWebSocketDecodeHeader和onWebSocketDecodePayload回调 diff --git a/src/Player/MediaPlayer.h b/src/Player/MediaPlayer.h index a425f956..4910625b 100644 --- a/src/Player/MediaPlayer.h +++ b/src/Player/MediaPlayer.h @@ -22,7 +22,6 @@ public: using Ptr = std::shared_ptr; MediaPlayer(const toolkit::EventPoller::Ptr &poller = nullptr); - ~MediaPlayer() override = default; void play(const std::string &url) override; toolkit::EventPoller::Ptr getPoller(); diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 73c9d3ee..acbf39c9 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -32,7 +32,6 @@ public: static Ptr createPlayer(const toolkit::EventPoller::Ptr &poller, const std::string &strUrl); PlayerBase(); - ~PlayerBase() override = default; /** * 开始播放 @@ -128,7 +127,6 @@ public: template PlayerImp(ArgsType &&...args) : Parent(std::forward(args)...) {} - ~PlayerImp() override = default; void play(const std::string &url) override { return _delegate ? _delegate->play(url) : Parent::play(url); diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 73e46b71..9ca1886a 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -191,8 +191,11 @@ void PlayerProxy::setDirectProxy() { mediaSource = std::make_shared(_tuple); } } else if (dynamic_pointer_cast(_delegate)) { - // rtmp拉流,rtmp强制直接代理 - mediaSource = std::make_shared(_tuple); + // rtmp拉流 + GET_CONFIG(bool, directProxy, Rtmp::kDirectProxy); + if (directProxy) { + mediaSource = std::make_shared(_tuple); + } } if (mediaSource) { setMediaSource(mediaSource); diff --git a/src/Pusher/MediaPusher.cpp b/src/Pusher/MediaPusher.cpp index f0ea401b..5cbaa7d7 100644 --- a/src/Pusher/MediaPusher.cpp +++ b/src/Pusher/MediaPusher.cpp @@ -31,8 +31,6 @@ MediaPusher::MediaPusher(const string &schema, MediaPusher(MediaSource::find(schema, vhost, app, stream), poller){ } -MediaPusher::~MediaPusher() = default; - static void setOnCreateSocket_l(const std::shared_ptr &delegate, const Socket::onCreateSocket &cb){ auto helper = dynamic_pointer_cast(delegate); if (helper) { diff --git a/src/Pusher/MediaPusher.h b/src/Pusher/MediaPusher.h index 52bd4ec3..82c74bfb 100644 --- a/src/Pusher/MediaPusher.h +++ b/src/Pusher/MediaPusher.h @@ -30,8 +30,6 @@ public: MediaPusher(const MediaSource::Ptr &src, const toolkit::EventPoller::Ptr &poller = nullptr); - virtual ~MediaPusher(); - void publish(const std::string &url) override; toolkit::EventPoller::Ptr getPoller(); void setOnCreateSocket(toolkit::Socket::onCreateSocket cb); diff --git a/src/Pusher/PusherBase.h b/src/Pusher/PusherBase.h index 8d97588b..504b9dc5 100644 --- a/src/Pusher/PusherBase.h +++ b/src/Pusher/PusherBase.h @@ -66,7 +66,6 @@ public: template PusherImp(ArgsType &&...args) : Parent(std::forward(args)...) {} - ~PusherImp() override = default; /** * 开始推流 diff --git a/src/Record/HlsMediaSource.h b/src/Record/HlsMediaSource.h index 1e0ecd14..8ab562ea 100644 --- a/src/Record/HlsMediaSource.h +++ b/src/Record/HlsMediaSource.h @@ -26,7 +26,6 @@ public: using Ptr = std::shared_ptr; HlsMediaSource(const std::string &schema, const MediaTuple &tuple) : MediaSource(schema, tuple) {} - ~HlsMediaSource() override = default; /** * 获取媒体源的环形缓冲 diff --git a/src/Record/HlsRecorder.h b/src/Record/HlsRecorder.h index aa1a4960..269074e3 100644 --- a/src/Record/HlsRecorder.h +++ b/src/Record/HlsRecorder.h @@ -33,8 +33,6 @@ public: _hls->clearCache(); } - ~HlsRecorderBase() override = default; - void setMediaSource(const MediaTuple& tuple) { _hls->setMediaSource(tuple.vhost, tuple.app, tuple.stream); } diff --git a/src/Record/MP4.cpp b/src/Record/MP4.cpp index 10f1b0ee..2d569944 100644 --- a/src/Record/MP4.cpp +++ b/src/Record/MP4.cpp @@ -8,7 +8,7 @@ * may be found in the AUTHORS file in the root of the source tree. */ -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "MP4.h" #include "Util/File.h" @@ -177,4 +177,4 @@ int MP4FileMemory::onWrite(const void *data, size_t bytes){ } }//namespace mediakit -#endif // defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif // defined(ENABLE_MP4) diff --git a/src/Record/MP4.h b/src/Record/MP4.h index 63e7af9c..3c09340f 100644 --- a/src/Record/MP4.h +++ b/src/Record/MP4.h @@ -11,7 +11,7 @@ #ifndef ZLMEDIAKIT_MP4_H #define ZLMEDIAKIT_MP4_H -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include #include @@ -33,7 +33,6 @@ public: using Writer = std::shared_ptr; using Reader = std::shared_ptr; - MP4FileIO() = default; virtual ~MP4FileIO() = default; /** @@ -83,8 +82,6 @@ public: class MP4FileDisk : public MP4FileIO { public: using Ptr = std::shared_ptr; - MP4FileDisk() = default; - ~MP4FileDisk() override = default; /** * 打开磁盘文件 @@ -111,8 +108,6 @@ private: class MP4FileMemory : public MP4FileIO{ public: using Ptr = std::shared_ptr; - MP4FileMemory() = default; - ~MP4FileMemory() override = default; /** * 获取文件大小 @@ -136,5 +131,5 @@ private: }; }//namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif //defined(ENABLE_MP4) #endif //ZLMEDIAKIT_MP4_H diff --git a/src/Record/MP4Demuxer.cpp b/src/Record/MP4Demuxer.cpp index 87936137..98ca373a 100644 --- a/src/Record/MP4Demuxer.cpp +++ b/src/Record/MP4Demuxer.cpp @@ -23,8 +23,6 @@ using namespace toolkit; namespace mediakit { -MP4Demuxer::MP4Demuxer() = default; - MP4Demuxer::~MP4Demuxer() { closeMP4(); } @@ -86,80 +84,65 @@ static const char *getObjectName(int obj_id) { SWITCH_CASE(MOV_OBJECT_G711a); SWITCH_CASE(MOV_OBJECT_G711u); SWITCH_CASE(MOV_OBJECT_AV1); - default: - return "unknown mp4 object"; + default: return "unknown mp4 object"; } } void MP4Demuxer::onVideoTrack(uint32_t track, uint8_t object, int width, int height, const void *extra, size_t bytes) { + Track::Ptr video; switch (object) { case MOV_OBJECT_H264: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); - - struct mpeg4_avc_t avc; - memset(&avc, 0, sizeof(avc)); - if (mpeg4_avc_decoder_configuration_record_load((uint8_t *) extra, bytes, &avc) > 0) { - uint8_t config[1024 * 10] = {0}; - int size = mpeg4_avc_to_nalu(&avc, config, sizeof(config)); - if (size > 0) { - video->inputFrame(std::make_shared((char *)config, size, 0, 0,4)); - } - } + video = std::make_shared(); + _track_to_codec.emplace(track, video); break; } case MOV_OBJECT_HEVC: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - if (mpeg4_hevc_decoder_configuration_record_load((uint8_t *) extra, bytes, &hevc) > 0) { - uint8_t config[1024 * 10] = {0}; - int size = mpeg4_hevc_to_nalu(&hevc, config, sizeof(config)); - if (size > 0) { - video->inputFrame(std::make_shared((char *) config, size, 0, 0,4)); - } - } + video = std::make_shared(); + _track_to_codec.emplace(track, video); break; } case MOV_OBJECT_JPEG: { - auto video = std::make_shared(); - _track_to_codec.emplace(track,video); + video = std::make_shared(); + _track_to_codec.emplace(track, video); break; } default: WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); break; } + if (extra && bytes) { + video->setExtraData((uint8_t *)extra, bytes); + } } void MP4Demuxer::onAudioTrack(uint32_t track_id, uint8_t object, int channel_count, int bit_per_sample, int sample_rate, const void *extra, size_t bytes) { + Track::Ptr audio; switch(object){ case MOV_OBJECT_AAC:{ - auto audio = std::make_shared(bytes > 0 ? string((char *)extra,bytes) : ""); + audio = std::make_shared(); _track_to_codec.emplace(track_id, audio); break; } case MOV_OBJECT_G711a: case MOV_OBJECT_G711u:{ - auto audio = std::make_shared(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count ); + audio = std::make_shared(object == MOV_OBJECT_G711a ? CodecG711A : CodecG711U, sample_rate, channel_count, bit_per_sample / channel_count ); _track_to_codec.emplace(track_id, audio); break; } case MOV_OBJECT_OPUS: { - auto audio = std::make_shared(); + audio = std::make_shared(); _track_to_codec.emplace(track_id, audio); break; } - default: - WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); - break; + default: WarnL << "不支持该编码类型的MP4,已忽略:" << getObjectName(object); break; + } + if (extra && bytes) { + audio->setExtraData((uint8_t *)extra, bytes); } } @@ -180,8 +163,6 @@ struct Context { BufferRaw::Ptr buffer; }; -#define DATA_OFFSET ADTS_HEADER_LEN - Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) { keyFrame = false; eof = false; @@ -194,9 +175,9 @@ Frame::Ptr MP4Demuxer::readFrame(bool &keyFrame, bool &eof) { ctx->track_id = track_id; ctx->buffer = ctx->thiz->_buffer_pool.obtain2(); - ctx->buffer->setCapacity(bytes + DATA_OFFSET + 1); - ctx->buffer->setSize(bytes + DATA_OFFSET); - return ctx->buffer->data() + DATA_OFFSET; + ctx->buffer->setCapacity(bytes + 1); + ctx->buffer->setSize(bytes); + return ctx->buffer->data(); }; Context ctx(this); @@ -225,14 +206,14 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 if (it == _track_to_codec.end()) { return nullptr; } - auto bytes = buf->size() - DATA_OFFSET; - auto data = buf->data() + DATA_OFFSET; - auto codec = it->second->getCodecId(); Frame::Ptr ret; + auto codec = it->second->getCodecId(); switch (codec) { case CodecH264 : case CodecH265 : { - uint32_t offset = 0; + auto bytes = buf->size(); + auto data = buf->data(); + auto offset = 0u; while (offset < bytes) { uint32_t frame_len; memcpy(&frame_len, data + offset, 4); @@ -244,35 +225,22 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 offset += (frame_len + 4); } if (codec == CodecH264) { - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, DATA_OFFSET); + ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0); break; } - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, DATA_OFFSET); + ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 4, 0); break; } case CodecJPEG: { - ret = std::make_shared(buf, (uint64_t)dts, 0, DATA_OFFSET); + ret = std::make_shared(buf, (uint64_t)dts, 0, 0); break; } - case CodecAAC: { - AACTrack::Ptr track = dynamic_pointer_cast(it->second); - assert(track); - //加上adts头 - dumpAacConfig(track->getConfig(), buf->size() - DATA_OFFSET, (uint8_t *) buf->data() + (DATA_OFFSET - ADTS_HEADER_LEN), ADTS_HEADER_LEN); - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, ADTS_HEADER_LEN, DATA_OFFSET - ADTS_HEADER_LEN, codec); + default: { + ret = std::make_shared>(buf, (uint64_t)dts, (uint64_t)pts, 0, 0, codec); break; } - - case CodecOpus: - case CodecG711A: - case CodecG711U: { - ret = std::make_shared >(buf, (uint64_t)dts, (uint64_t)pts, 0, DATA_OFFSET, codec); - break; - } - - default: return nullptr; } if (ret) { it->second->inputFrame(ret); @@ -283,7 +251,7 @@ Frame::Ptr MP4Demuxer::makeFrame(uint32_t track_id, const Buffer::Ptr &buf, int6 vector MP4Demuxer::getTracks(bool trackReady) const { vector ret; for (auto &pr : _track_to_codec) { - if(trackReady && !pr.second->ready()){ + if (trackReady && !pr.second->ready()) { continue; } ret.push_back(pr.second); diff --git a/src/Record/MP4Demuxer.h b/src/Record/MP4Demuxer.h index 220f143a..727f1f1e 100644 --- a/src/Record/MP4Demuxer.h +++ b/src/Record/MP4Demuxer.h @@ -20,10 +20,6 @@ class MP4Demuxer : public TrackSource { public: using Ptr = std::shared_ptr; - /** - * 创建mp4解复用器 - */ - MP4Demuxer(); ~MP4Demuxer() override; /** diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 5458a31d..19e317f9 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -8,14 +8,9 @@ * may be found in the AUTHORS file in the root of the source tree. */ -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "MP4Muxer.h" -#include "Extension/AAC.h" -#include "Extension/G711.h" -#include "Extension/H264.h" -#include "Extension/H265.h" -#include "Extension/JPEG.h" #include "Common/config.h" using namespace std; @@ -121,18 +116,6 @@ bool MP4MuxerInterface::inputFrame(const Frame::Ptr &frame) { }); break; } - case CodecJPEG:{ - int64_t dts_out, pts_out; - track_info.stamp.revise(frame->dts(), frame->pts(), dts_out, pts_out); - mp4_writer_write(_mov_writter.get(), - track_info.track_id, - frame->data(), - frame->size(), - pts_out, - dts_out, - frame->keyFrame() ? MOV_AV_FLAG_KEYFREAME : 0); - break; - } default: { int64_t dts_out, pts_out; @@ -159,6 +142,8 @@ static uint8_t getObject(CodecId codecId) { case CodecH264 : return MOV_OBJECT_H264; case CodecH265 : return MOV_OBJECT_HEVC; case CodecJPEG : return MOV_OBJECT_JPEG; + case CodecVP9: return MOV_OBJECT_VP9; + case CodecAV1: return MOV_OBJECT_AV1; default : return 0; } } @@ -199,147 +184,39 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) { } track->update(); - switch (track->getCodecId()) { - case CodecG711A: - case CodecG711U: - case CodecOpus: { - auto audio_track = dynamic_pointer_cast(track); - if (!audio_track) { - WarnL << "不是音频Track:" << track->getCodecName(); - return false; - } - auto track_id = mp4_writer_add_audio(_mov_writter.get(), - mp4_object, - audio_track->getAudioChannel(), - audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), - audio_track->getAudioSampleRate(), - nullptr, 0); - if (track_id < 0) { - WarnL << "添加Track[" << track->getCodecName() << "]失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - break; + auto extra = track->getExtraData(); + auto extra_data = extra ? extra->data() : nullptr; + auto extra_size = extra ? extra->size() : 0; + if (track->getTrackType() == TrackVideo) { + auto video_track = dynamic_pointer_cast(track); + if (!video_track) { + WarnL << "不是VideoTrack"; + return false; } - case CodecAAC: { - auto audio_track = dynamic_pointer_cast(track); - if (!audio_track) { - WarnL << "不是AAC Track"; - return false; - } - - auto track_id = mp4_writer_add_audio(_mov_writter.get(), - mp4_object, - audio_track->getAudioChannel(), - audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), - audio_track->getAudioSampleRate(), - audio_track->getConfig().data(), - audio_track->getConfig().size()); - if (track_id < 0) { - WarnL << "添加AAC Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - break; + auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, video_track->getVideoWidth(), video_track->getVideoHeight(), extra_data, extra_size); + if (track_id < 0) { + WarnL << "添加Video Track失败:" << video_track->getCodecName(); + return false; + } + _codec_to_trackid[track->getCodecId()].track_id = track_id; + _have_video = true; + } else if (track->getTrackType() == TrackAudio) { + auto audio_track = dynamic_pointer_cast(track); + if (!audio_track) { + WarnL << "不是音频Track:" << track->getCodecName(); + return false; } - case CodecH264: { - auto h264_track = dynamic_pointer_cast(track); - if (!h264_track) { - WarnL << "不是H264 Track"; - return false; - } - - struct mpeg4_avc_t avc; - memset(&avc, 0, sizeof(avc)); - string sps_pps = string("\x00\x00\x00\x01", 4) + h264_track->getSps() + - string("\x00\x00\x00\x01", 4) + h264_track->getPps(); - h264_annexbtomp4(&avc, sps_pps.data(), (int) sps_pps.size(), NULL, 0, NULL, NULL); - - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_avc_decoder_configuration_record_save(&avc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H264 extra_data 失败"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - h264_track->getVideoWidth(), - h264_track->getVideoHeight(), - extra_data, - extra_data_size); - - if (track_id < 0) { - WarnL << "添加H264 Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; + auto track_id = mp4_writer_add_audio(_mov_writter.get(), mp4_object, audio_track->getAudioChannel(), + audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), + audio_track->getAudioSampleRate(), extra_data, extra_size); + if (track_id < 0) { + WarnL << "添加Track[" << track->getCodecName() << "]失败:" << track_id; + return false; } - - case CodecH265: { - auto h265_track = dynamic_pointer_cast(track); - if (!h265_track) { - WarnL << "不是H265 Track"; - return false; - } - - struct mpeg4_hevc_t hevc; - memset(&hevc, 0, sizeof(hevc)); - string vps_sps_pps = string("\x00\x00\x00\x01", 4) + h265_track->getVps() + - string("\x00\x00\x00\x01", 4) + h265_track->getSps() + - string("\x00\x00\x00\x01", 4) + h265_track->getPps(); - h265_annexbtomp4(&hevc, vps_sps_pps.data(), (int) vps_sps_pps.size(), NULL, 0, NULL, NULL); - - uint8_t extra_data[1024]; - int extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&hevc, extra_data, sizeof(extra_data)); - if (extra_data_size == -1) { - WarnL << "生成H265 extra_data 失败"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - h265_track->getVideoWidth(), - h265_track->getVideoHeight(), - extra_data, - extra_data_size); - if (track_id < 0) { - WarnL << "添加H265 Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; - } - - case CodecJPEG: { - auto jpeg_track = dynamic_pointer_cast(track); - if (!jpeg_track) { - WarnL << "不是JPEG Track"; - return false; - } - - auto track_id = mp4_writer_add_video(_mov_writter.get(), - mp4_object, - jpeg_track->getVideoWidth(), - jpeg_track->getVideoHeight(), - nullptr, - 0); - if (track_id < 0) { - WarnL << "添加JPEG Track失败:" << track_id; - return false; - } - _codec_to_trackid[track->getCodecId()].track_id = track_id; - _have_video = true; - break; - } - - default: WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); return false; + _codec_to_trackid[track->getCodecId()].track_id = track_id; } //尝试音视频同步 @@ -398,4 +275,4 @@ bool MP4MuxerMemory::inputFrame(const Frame::Ptr &frame) { } }//namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif //defined(ENABLE_MP4) diff --git a/src/Record/MP4Muxer.h b/src/Record/MP4Muxer.h index 3b48ad7c..76126928 100644 --- a/src/Record/MP4Muxer.h +++ b/src/Record/MP4Muxer.h @@ -11,7 +11,7 @@ #ifndef ZLMEDIAKIT_MP4MUXER_H #define ZLMEDIAKIT_MP4MUXER_H -#if defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) #include "Common/MediaSink.h" #include "Common/Stamp.h" @@ -21,8 +21,6 @@ namespace mediakit { class MP4MuxerInterface : public MediaSinkInterface { public: - MP4MuxerInterface() = default; - ~MP4MuxerInterface() override = default; /** * 添加已经ready状态的track @@ -85,10 +83,7 @@ private: class MP4Muxer : public MP4MuxerInterface{ public: using Ptr = std::shared_ptr; - - MP4Muxer() = default; ~MP4Muxer() override; - /** * 重置所有track */ @@ -116,7 +111,6 @@ private: class MP4MuxerMemory : public MP4MuxerInterface{ public: MP4MuxerMemory(); - ~MP4MuxerMemory() override = default; /** * 重置所有track @@ -162,9 +156,6 @@ namespace mediakit { class MP4MuxerMemory : public MediaSinkInterface { public: - MP4MuxerMemory() = default; - ~MP4MuxerMemory() override = default; - bool addTrack(const Track::Ptr & track) override { return false; } bool inputFrame(const Frame::Ptr &frame) override { return false; } const std::string &getInitSegment() { static std::string kNull; return kNull; }; @@ -181,5 +172,5 @@ protected: } // namespace mediakit -#endif //defined(ENABLE_MP4) || defined(ENABLE_HLS_FMP4) +#endif //defined(ENABLE_MP4) #endif //ZLMEDIAKIT_MP4MUXER_H diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index d1f408dd..8ec30a5c 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -20,24 +20,25 @@ using namespace toolkit; namespace mediakit { -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path) { +MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, + toolkit::EventPoller::Ptr poller) { ProtocolOption option; // 读取mp4文件并流化时,不重复生成mp4/hls文件 option.enable_mp4 = false; option.enable_hls = false; option.enable_hls_fmp4 = false; - setup(vhost, app, stream_id, file_path, option); + setup(vhost, app, stream_id, file_path, option, std::move(poller)); } -MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, const ProtocolOption &option) { - setup(vhost, app, stream_id, file_path, option); +MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { + setup(vhost, app, stream_id, file_path, option, std::move(poller)); } -void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option) { +void MP4Reader::setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller) { //读写文件建议放在后台线程 auto tuple = MediaTuple{vhost, app, stream_id}; - _poller = WorkThreadPool::Instance().getPoller(); + _poller = poller ? std::move(poller) : WorkThreadPool::Instance().getPoller(); _file_path = file_path; if (_file_path.empty()) { GET_CONFIG(string, recordPath, Protocol::kMP4SavePath); @@ -122,6 +123,7 @@ void MP4Reader::stopReadMP4() { void MP4Reader::startReadMP4(uint64_t sample_ms, bool ref_self, bool file_repeat) { GET_CONFIG(uint32_t, sampleMS, Record::kSampleMS); + setCurrentStamp(0); auto strong_self = shared_from_this(); if (_muxer) { //一直读到所有track就绪为止 diff --git a/src/Record/MP4Reader.h b/src/Record/MP4Reader.h index ac07e9e8..bbcb7e83 100644 --- a/src/Record/MP4Reader.h +++ b/src/Record/MP4Reader.h @@ -29,12 +29,10 @@ public: * @param file_path 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 */ MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path = ""); + const std::string &file_path = "", toolkit::EventPoller::Ptr poller = nullptr); MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, - const std::string &file_path, const ProtocolOption &option); - - ~MP4Reader() override = default; + const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller = nullptr); /** * 开始解复用MP4文件 @@ -71,7 +69,7 @@ private: void setCurrentStamp(uint32_t stamp); bool seekTo(uint32_t stamp_seek); - void setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option); + void setup(const std::string &vhost, const std::string &app, const std::string &stream_id, const std::string &file_path, const ProtocolOption &option, toolkit::EventPoller::Ptr poller); private: bool _file_repeat = false; diff --git a/src/Record/MPEG.h b/src/Record/MPEG.h index 567d1b74..36f9be76 100644 --- a/src/Record/MPEG.h +++ b/src/Record/MPEG.h @@ -87,7 +87,6 @@ namespace mediakit { class MpegMuxer : public MediaSinkInterface { public: MpegMuxer(bool is_ps = false) {} - ~MpegMuxer() override = default; bool addTrack(const Track::Ptr &track) override { return false; } void resetTracks() override {} bool inputFrame(const Frame::Ptr &frame) override { return false; } diff --git a/src/Record/Recorder.cpp b/src/Record/Recorder.cpp index 6183ff1c..7da99248 100644 --- a/src/Record/Recorder.cpp +++ b/src/Record/Recorder.cpp @@ -98,22 +98,22 @@ std::shared_ptr Recorder::createRecorder(type type, const Me } case Recorder::type_hls_fmp4: { -#if defined(ENABLE_HLS_FMP4) +#if defined(ENABLE_MP4) auto path = Recorder::getRecordPath(type, tuple, option.hls_save_path); GET_CONFIG(bool, enable_vhost, General::kEnableVhost); auto ret = std::make_shared(path, enable_vhost ? string(VHOST_KEY) + "=" + tuple.vhost : "", option); ret->setMediaSource(tuple); return ret; #else - throw std::invalid_argument("hls.fmp4相关功能未打开,请开启ENABLE_HLS_FMP4宏后编译再测试"); + throw std::invalid_argument("hls.fmp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试"); #endif } case Recorder::type_fmp4: { -#if defined(ENABLE_HLS_FMP4) || defined(ENABLE_MP4) +#if defined(ENABLE_MP4) return std::make_shared(tuple, option); #else - throw std::invalid_argument("fmp4相关功能未打开,请开启ENABLE_HLS_FMP4或ENABLE_MP4宏后编译再测试"); + throw std::invalid_argument("fmp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试"); #endif } diff --git a/src/Rtcp/Rtcp.cpp b/src/Rtcp/Rtcp.cpp index a31df64d..b946a120 100644 --- a/src/Rtcp/Rtcp.cpp +++ b/src/Rtcp/Rtcp.cpp @@ -242,8 +242,6 @@ vector RtcpHeader::loadFromBytes(char *data, size_t len) { class BufferRtcp : public Buffer { public: BufferRtcp(std::shared_ptr rtcp) { _rtcp = std::move(rtcp); } - ~BufferRtcp() override = default; - char *data() const override { return (char *)_rtcp.get(); } size_t size() const override { return _rtcp->getSize(); } diff --git a/src/Rtmp/FlvMuxer.h b/src/Rtmp/FlvMuxer.h index 4adc68d9..9c3f6cf8 100644 --- a/src/Rtmp/FlvMuxer.h +++ b/src/Rtmp/FlvMuxer.h @@ -47,8 +47,6 @@ private: class FlvRecorder : public FlvMuxer , public std::enable_shared_from_this{ public: using Ptr = std::shared_ptr; - FlvRecorder() = default; - ~FlvRecorder() override = default; void startRecord(const toolkit::EventPoller::Ptr &poller, const RtmpMediaSource::Ptr &media, const std::string &file_path); void startRecord(const toolkit::EventPoller::Ptr &poller, const std::string &vhost, const std::string &app, const std::string &stream, const std::string &file_path); diff --git a/src/Rtmp/FlvPlayer.h b/src/Rtmp/FlvPlayer.h index 2e79dac2..70878572 100644 --- a/src/Rtmp/FlvPlayer.h +++ b/src/Rtmp/FlvPlayer.h @@ -20,7 +20,6 @@ namespace mediakit { class FlvPlayer : public PlayerBase, public HttpClientImp, private FlvSplitter { public: FlvPlayer(const toolkit::EventPoller::Ptr &poller); - ~FlvPlayer() override = default; void play(const std::string &url) override; void teardown() override; diff --git a/src/Rtmp/FlvSplitter.h b/src/Rtmp/FlvSplitter.h index 78f2d1d5..9aeaaa72 100644 --- a/src/Rtmp/FlvSplitter.h +++ b/src/Rtmp/FlvSplitter.h @@ -18,10 +18,6 @@ namespace mediakit { class FlvSplitter : public HttpRequestSplitter { -public: - FlvSplitter() = default; - ~FlvSplitter() = default; - protected: void onRecvContent(const char *data,size_t len) override; ssize_t onRecvHeader(const char *data,size_t len) override; diff --git a/src/Rtmp/Rtmp.cpp b/src/Rtmp/Rtmp.cpp index 33c46f11..8698f1ca 100644 --- a/src/Rtmp/Rtmp.cpp +++ b/src/Rtmp/Rtmp.cpp @@ -9,6 +9,7 @@ */ #include "Rtmp.h" +#include "Common/config.h" #include "Extension/Factory.h" namespace mediakit { @@ -35,8 +36,7 @@ VideoMeta::VideoMeta(const VideoTrack::Ptr &video) { if (video->getBitRate()) { _metadata.set("videodatarate", video->getBitRate() / 1024); } - _codecId = video->getCodecId(); - _metadata.set("videocodecid", Factory::getAmfByCodecId(_codecId)); + _metadata.set("videocodecid", Factory::getAmfByCodecId(video->getCodecId())); } AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) { @@ -52,8 +52,7 @@ AudioMeta::AudioMeta(const AudioTrack::Ptr &audio) { if (audio->getAudioChannel() > 0) { _metadata.set("stereo", audio->getAudioChannel() > 1); } - _codecId = audio->getCodecId(); - _metadata.set("audiocodecid", Factory::getAmfByCodecId(_codecId)); + _metadata.set("audiocodecid", Factory::getAmfByCodecId(audio->getCodecId())); } uint8_t getAudioRtmpFlags(const Track::Ptr &track) { @@ -259,36 +258,6 @@ void RtmpHandshake::random_generate(char *bytes, int size) { } } -#pragma pack(push, 1) - -struct RtmpVideoHeaderEnhanced { -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t enhanced : 1; - uint8_t frame_type : 3; - uint8_t pkt_type : 4; - uint32_t fourcc; -#else - uint8_t pkt_type : 4; - uint8_t frame_type : 3; - uint8_t enhanced : 1; - uint32_t fourcc; -#endif -}; - -struct RtmpVideoHeaderClassic { -#if __BYTE_ORDER == __BIG_ENDIAN - uint8_t frame_type : 4; - uint8_t codec_id : 4; - uint8_t h264_pkt_type; -#else - uint8_t codec_id : 4; - uint8_t frame_type : 4; - uint8_t h264_pkt_type; -#endif -}; - -#pragma pack(pop) - CodecId parseVideoRtmpPacket(const uint8_t *data, size_t size, RtmpPacketInfo *info) { RtmpPacketInfo save; info = info ? info : &save; @@ -298,7 +267,7 @@ CodecId parseVideoRtmpPacket(const uint8_t *data, size_t size, RtmpPacketInfo *i RtmpVideoHeaderEnhanced *enhanced_header = (RtmpVideoHeaderEnhanced *)data; if (enhanced_header->enhanced) { // IsExHeader == 1 - CHECK(size >= 5, "Invalid rtmp buffer size: ", size); + CHECK(size > RtmpPacketInfo::kEnhancedRtmpHeaderSize, "Invalid rtmp buffer size: ", size); info->is_enhanced = true; info->video.frame_type = (RtmpFrameType)(enhanced_header->frame_type); info->video.pkt_type = (RtmpPacketType)(enhanced_header->pkt_type); diff --git a/src/Rtmp/Rtmp.h b/src/Rtmp/Rtmp.h index 66908af2..0faa89d7 100644 --- a/src/Rtmp/Rtmp.h +++ b/src/Rtmp/Rtmp.h @@ -132,6 +132,32 @@ public: uint8_t streamid[3] = {0}; /* Always 0. */ }; +struct RtmpVideoHeaderEnhanced { +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t enhanced : 1; + uint8_t frame_type : 3; + uint8_t pkt_type : 4; + uint32_t fourcc; +#else + uint8_t pkt_type : 4; + uint8_t frame_type : 3; + uint8_t enhanced : 1; + uint32_t fourcc; +#endif +}; + +struct RtmpVideoHeaderClassic { +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t frame_type : 4; + uint8_t codec_id : 4; + uint8_t h264_pkt_type; +#else + uint8_t codec_id : 4; + uint8_t frame_type : 4; + uint8_t h264_pkt_type; +#endif +}; + #pragma pack(pop) class RtmpPacket : public toolkit::Buffer{ @@ -188,17 +214,17 @@ private: /** * rtmp metadata基类,用于描述rtmp格式信息 */ -class Metadata : public CodecInfo{ +class Metadata { public: using Ptr = std::shared_ptr; Metadata(): _metadata(AMF_OBJECT) {} - virtual ~Metadata() = default; const AMFValue &getMetadata() const{ return _metadata; } static void addTrack(AMFValue &metadata, const Track::Ptr &track); + protected: AMFValue _metadata; }; @@ -206,7 +232,7 @@ protected: /** * metadata中除音视频外的其他描述部分 */ -class TitleMeta : public Metadata{ +class TitleMeta : public Metadata { public: using Ptr = std::shared_ptr; @@ -214,37 +240,20 @@ public: size_t fileSize = 0, const std::map &header = std::map()); - CodecId getCodecId() const override{ - return CodecInvalid; - } }; -class VideoMeta : public Metadata{ +class VideoMeta : public Metadata { public: using Ptr = std::shared_ptr; VideoMeta(const VideoTrack::Ptr &video); - virtual ~VideoMeta() = default; - - CodecId getCodecId() const override{ - return _codecId; - } -private: - CodecId _codecId; }; -class AudioMeta : public Metadata{ +class AudioMeta : public Metadata { public: using Ptr = std::shared_ptr; AudioMeta(const AudioTrack::Ptr &audio); - virtual ~AudioMeta() = default; - - CodecId getCodecId() const override{ - return _codecId; - } -private: - CodecId _codecId; }; //根据音频track获取flags @@ -353,6 +362,8 @@ enum class RtmpAACPacketType : uint8_t { //////////////////////////////////////////// struct RtmpPacketInfo { + enum { kEnhancedRtmpHeaderSize = sizeof(RtmpVideoHeaderEnhanced) }; + CodecId codec = CodecInvalid; bool is_enhanced; union { diff --git a/src/Rtmp/RtmpCodec.h b/src/Rtmp/RtmpCodec.h index 67c9ce92..484e3e49 100644 --- a/src/Rtmp/RtmpCodec.h +++ b/src/Rtmp/RtmpCodec.h @@ -22,20 +22,12 @@ public: using Ptr = std::shared_ptr; using RingType = toolkit::RingBuffer; - RtmpRing() = default; virtual ~RtmpRing() = default; - /** - * 获取rtmp环形缓存 - */ - virtual RingType::Ptr getRtmpRing() const { - return _ring; - } - /** * 设置rtmp环形缓存 */ - virtual void setRtmpRing(const RingType::Ptr &ring) { + void setRtmpRing(const RingType::Ptr &ring) { _ring = ring; } @@ -53,12 +45,19 @@ protected: RingType::Ptr _ring; }; -class RtmpCodec : public RtmpRing, public FrameDispatcher, public CodecInfo { +class RtmpCodec : public RtmpRing, public FrameWriterInterface { public: using Ptr = std::shared_ptr; - RtmpCodec() = default; - ~RtmpCodec() override = default; - virtual void makeConfigPacket() {}; + RtmpCodec(Track::Ptr track) { _track = std::move(track); } + + virtual void makeConfigPacket() {} + + bool inputFrame(const Frame::Ptr &frame) override { return _track->inputFrame(frame); } + + const Track::Ptr &getTrack() const { return _track; } + +private: + Track::Ptr _track; }; diff --git a/src/Rtmp/RtmpDemuxer.cpp b/src/Rtmp/RtmpDemuxer.cpp index 20d8f052..fb2bd5e8 100644 --- a/src/Rtmp/RtmpDemuxer.cpp +++ b/src/Rtmp/RtmpDemuxer.cpp @@ -146,15 +146,13 @@ void RtmpDemuxer::makeVideoTrack(const Track::Ptr &track, int bit_rate) { return; } // 生成rtmpCodec对象以便解码rtmp - _video_rtmp_decoder = Factory::getRtmpCodecByTrack(_video_track, false); + _video_rtmp_decoder = Factory::getRtmpDecoderByTrack(_video_track); 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; } @@ -169,15 +167,13 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec, int sample_rate, in return; } // 生成rtmpCodec对象以便解码rtmp - _audio_rtmp_decoder = Factory::getRtmpCodecByTrack(_audio_track, false); + _audio_rtmp_decoder = Factory::getRtmpDecoderByTrack(_audio_track); 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; } diff --git a/src/Rtmp/RtmpDemuxer.h b/src/Rtmp/RtmpDemuxer.h index 4cf0412b..303cf028 100644 --- a/src/Rtmp/RtmpDemuxer.h +++ b/src/Rtmp/RtmpDemuxer.h @@ -24,9 +24,6 @@ class RtmpDemuxer : public Demuxer { public: using Ptr = std::shared_ptr; - RtmpDemuxer() = default; - ~RtmpDemuxer() override = default; - static size_t trackCount(const AMFValue &metadata); bool loadMetaData(const AMFValue &metadata); diff --git a/src/Rtmp/RtmpMediaSourceImp.cpp b/src/Rtmp/RtmpMediaSourceImp.cpp index 4a6f8975..ff5320e6 100644 --- a/src/Rtmp/RtmpMediaSourceImp.cpp +++ b/src/Rtmp/RtmpMediaSourceImp.cpp @@ -105,7 +105,11 @@ void RtmpMediaSourceImp::onWrite(RtmpPacket::Ptr pkt, bool /*= true*/) { // 未获取到所有Track后,或者开启转协议,那么需要解复用rtmp _demuxer->inputRtmp(pkt); } - RtmpMediaSource::onWrite(std::move(pkt)); + GET_CONFIG(bool, directProxy, Rtmp::kDirectProxy); + if (directProxy) { + //直接代理模式才直接使用原始rtmp + RtmpMediaSource::onWrite(std::move(pkt)); + } } int RtmpMediaSourceImp::totalReaderCount() { @@ -113,10 +117,9 @@ int RtmpMediaSourceImp::totalReaderCount() { } void RtmpMediaSourceImp::setProtocolOption(const ProtocolOption &option) { - // 不重复生成rtmp + GET_CONFIG(bool, direct_proxy, Rtmp::kDirectProxy); _option = option; - // 不重复生成rtmp协议 - _option.enable_rtmp = false; + _option.enable_rtmp = !direct_proxy; _muxer = std::make_shared(_tuple, _demuxer->getDuration(), _option); _muxer->setMediaListener(getListener()); _muxer->setTrackListener(std::static_pointer_cast(shared_from_this())); diff --git a/src/Rtmp/RtmpMediaSourceImp.h b/src/Rtmp/RtmpMediaSourceImp.h index 31fa24fe..3f975933 100644 --- a/src/Rtmp/RtmpMediaSourceImp.h +++ b/src/Rtmp/RtmpMediaSourceImp.h @@ -37,8 +37,6 @@ public: */ RtmpMediaSourceImp(const MediaTuple& tuple, int ringSize = RTMP_GOP_SIZE); - ~RtmpMediaSourceImp() override = default; - /** * 设置metadata */ diff --git a/src/Rtmp/RtmpMuxer.cpp b/src/Rtmp/RtmpMuxer.cpp index 4be4ac5d..8f00a532 100644 --- a/src/Rtmp/RtmpMuxer.cpp +++ b/src/Rtmp/RtmpMuxer.cpp @@ -14,9 +14,9 @@ namespace mediakit { RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) { - if(!title){ + if (!title) { _metadata = std::make_shared()->getMetadata(); - }else{ + } else { _metadata = title->getMetadata(); } _rtmp_ring = std::make_shared(); @@ -24,16 +24,20 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) { bool RtmpMuxer::addTrack(const Track::Ptr &track) { auto &encoder = _encoder[track->getTrackType()]; - //生成rtmp编码器,克隆该Track,防止循环引用 - encoder = Factory::getRtmpCodecByTrack(track->clone(), true); + if (encoder) { + WarnL << "Already add a track kind of: " << track->getTrackTypeStr() + << ", ignore track: " << track->getCodecName(); + return false; + } + encoder = Factory::getRtmpEncoderByTrack(track); if (!encoder) { return false; } - //设置rtmp输出环形缓存 + // 设置rtmp输出环形缓存 encoder->setRtmpRing(_rtmp_ring); - //添加metadata + // 添加metadata Metadata::addTrack(_metadata, track); return true; } @@ -51,9 +55,9 @@ void RtmpMuxer::flush() { } } -void RtmpMuxer::makeConfigPacket(){ - for(auto &encoder : _encoder){ - if(encoder){ +void RtmpMuxer::makeConfigPacket() { + for (auto &encoder : _encoder) { + if (encoder) { encoder->makeConfigPacket(); } } @@ -69,10 +73,9 @@ RtmpRing::RingType::Ptr RtmpMuxer::getRtmpRing() const { void RtmpMuxer::resetTracks() { _metadata.clear(); - for(auto &encoder : _encoder){ + for (auto &encoder : _encoder) { encoder = nullptr; } } - -}/* namespace mediakit */ \ No newline at end of file +} /* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtmp/RtmpMuxer.h b/src/Rtmp/RtmpMuxer.h index 430166c2..e127ddd7 100644 --- a/src/Rtmp/RtmpMuxer.h +++ b/src/Rtmp/RtmpMuxer.h @@ -26,7 +26,6 @@ public: * 构造函数 */ RtmpMuxer(const TitleMeta::Ptr &title); - ~RtmpMuxer() override = default; /** * 获取完整的SDP字符串 diff --git a/src/Rtmp/RtmpProtocol.cpp b/src/Rtmp/RtmpProtocol.cpp index 386f5205..0dee1e5f 100644 --- a/src/Rtmp/RtmpProtocol.cpp +++ b/src/Rtmp/RtmpProtocol.cpp @@ -187,8 +187,6 @@ public: _size = size; } - ~BufferPartial() override = default; - char *data() const override { return _data; } diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index fa3058be..8888f18a 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -22,8 +22,6 @@ RtmpSession::RtmpSession(const Socket::Ptr &sock) : Session(sock) { sock->setSendTimeOutSecond(keep_alive_sec); } -RtmpSession::~RtmpSession() = default; - void RtmpSession::onError(const SockException& err) { bool is_player = !_push_src_ownership; uint64_t duration = _ticker.createdTime() / 1000; diff --git a/src/Rtmp/RtmpSession.h b/src/Rtmp/RtmpSession.h index f51b567e..cb6e5db5 100644 --- a/src/Rtmp/RtmpSession.h +++ b/src/Rtmp/RtmpSession.h @@ -27,7 +27,6 @@ public: using Ptr = std::shared_ptr; RtmpSession(const toolkit::Socket::Ptr &sock); - ~RtmpSession() override; void onRecv(const toolkit::Buffer::Ptr &buf) override; void onError(const toolkit::SockException &err) override; diff --git a/src/Rtp/Decoder.h b/src/Rtp/Decoder.h index c6f8aacf..b85f1f44 100644 --- a/src/Rtp/Decoder.h +++ b/src/Rtp/Decoder.h @@ -37,12 +37,11 @@ protected: onStream _on_stream; }; -class DecoderImp{ +class DecoderImp { public: typedef enum { decoder_ts = 0, decoder_ps } Type; using Ptr = std::shared_ptr; - ~DecoderImp() = default; static Ptr createDecoder(Type type, MediaSinkInterface *sink); ssize_t input(const uint8_t *data, size_t bytes); diff --git a/src/Rtp/GB28181Process.cpp b/src/Rtp/GB28181Process.cpp index 204d98f8..089aa902 100644 --- a/src/Rtp/GB28181Process.cpp +++ b/src/Rtp/GB28181Process.cpp @@ -45,8 +45,6 @@ public: setNtpStamp(0, 0); } - ~RtpReceiverImp() override = default; - bool inputRtp(TrackType type, uint8_t *ptr, size_t len) { return RtpTrack::inputRtp(type, _sample_rate, ptr, len).operator bool(); } diff --git a/src/Rtp/GB28181Process.h b/src/Rtp/GB28181Process.h index 2ab688cf..621f99be 100644 --- a/src/Rtp/GB28181Process.h +++ b/src/Rtp/GB28181Process.h @@ -27,7 +27,6 @@ public: using Ptr = std::shared_ptr; GB28181Process(const MediaInfo &media_info, MediaSinkInterface *sink); - ~GB28181Process() override = default; /** * 输入rtp diff --git a/src/Rtp/PSEncoder.cpp b/src/Rtp/PSEncoder.cpp index 78cedb34..ff9cd9e6 100644 --- a/src/Rtp/PSEncoder.cpp +++ b/src/Rtp/PSEncoder.cpp @@ -22,23 +22,23 @@ namespace mediakit{ PSEncoderImp::PSEncoderImp(uint32_t ssrc, uint8_t payload_type) : MpegMuxer(true) { GET_CONFIG(uint32_t,video_mtu,Rtp::kVideoMtuSize); - _rtp_encoder = std::make_shared(CodecInvalid, ssrc, video_mtu, 90000, payload_type, 0); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key){ - onRTP(std::move(rtp),is_key); - })); - InfoL << this << " " << printSSRC(_rtp_encoder->getSsrc()); + _rtp_encoder = std::make_shared(); + _rtp_encoder->setRtpInfo(ssrc, video_mtu, 90000, payload_type, 0); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + _rtp_encoder->setRtpRing(std::move(ring)); + InfoL << this << " " << ssrc; } PSEncoderImp::~PSEncoderImp() { - InfoL << this << " " << printSSRC(_rtp_encoder->getSsrc()); + InfoL << this; } void PSEncoderImp::onWrite(std::shared_ptr buffer, uint64_t stamp, bool key_pos) { if (!buffer) { return; } - _rtp_encoder->inputFrame(std::make_shared(buffer->data(), buffer->size(), stamp, stamp,0,key_pos)); + _rtp_encoder->inputFrame(std::make_shared(CodecH264/*只用于识别为视频*/, buffer->data(), buffer->size(), stamp, stamp, 0, key_pos)); } }//namespace mediakit diff --git a/src/Rtp/PSEncoder.h b/src/Rtp/PSEncoder.h index 12a6e639..47fa5688 100644 --- a/src/Rtp/PSEncoder.h +++ b/src/Rtp/PSEncoder.h @@ -25,7 +25,7 @@ public: protected: //rtp打包后回调 - virtual void onRTP(toolkit::Buffer::Ptr rtp,bool is_key = false) = 0; + virtual void onRTP(toolkit::Buffer::Ptr rtp, bool is_key = false) = 0; protected: void onWrite(std::shared_ptr buffer, uint64_t stamp, bool key_pos) override; diff --git a/src/Rtp/ProcessInterface.h b/src/Rtp/ProcessInterface.h index 6cd7fa9c..1b046471 100644 --- a/src/Rtp/ProcessInterface.h +++ b/src/Rtp/ProcessInterface.h @@ -20,7 +20,6 @@ namespace mediakit { class ProcessInterface { public: using Ptr = std::shared_ptr; - ProcessInterface() = default; virtual ~ProcessInterface() = default; /** diff --git a/src/Rtp/RawEncoder.cpp b/src/Rtp/RawEncoder.cpp index a4f11ddc..12d41fd0 100644 --- a/src/Rtp/RawEncoder.cpp +++ b/src/Rtp/RawEncoder.cpp @@ -13,6 +13,7 @@ #include "RawEncoder.h" #include "Extension/Factory.h" #include "Rtsp/RtspMuxer.h" +#include "Common//config.h" using namespace toolkit; @@ -30,17 +31,17 @@ RawEncoderImp::~RawEncoderImp() { bool RawEncoderImp::addTrack(const Track::Ptr &track) { if (_send_audio && track->getTrackType() == TrackType::TrackAudio && !_rtp_encoder) { // audio _rtp_encoder = createRtpEncoder(track); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared( - [this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), true); })); + _rtp_encoder->setRtpRing(std::move(ring)); return true; } if (!_send_audio && track->getTrackType() == TrackType::TrackVideo && !_rtp_encoder) { _rtp_encoder = createRtpEncoder(track); - _rtp_encoder->setRtpRing(std::make_shared()); - _rtp_encoder->getRtpRing()->setDelegate(std::make_shared( - [this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + auto ring = std::make_shared(); + ring->setDelegate(std::make_shared([this](RtpPacket::Ptr rtp, bool is_key) { onRTP(std::move(rtp), is_key); })); + _rtp_encoder->setRtpRing(std::move(ring)); return true; } return true; @@ -62,11 +63,17 @@ bool RawEncoderImp::inputFrame(const Frame::Ptr &frame) { } RtpCodec::Ptr RawEncoderImp::createRtpEncoder(const Track::Ptr &track) { - uint32_t sample_rate = 90000; + GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); + GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); + auto sample_rate = 90000u; + auto mtu = video_mtu; if (track->getTrackType() == TrackType::TrackAudio) { + mtu = audio_mtu; sample_rate = std::static_pointer_cast(track)->getAudioSampleRate(); } - return Factory::getRtpEncoderByCodecId(track->getCodecId(), sample_rate, _payload_type, _ssrc); + auto ret = Factory::getRtpEncoderByCodecId(track->getCodecId(), _payload_type); + ret->setRtpInfo(_ssrc, mtu, sample_rate, _payload_type, 2 * track->getTrackType()); + return ret; } } // namespace mediakit diff --git a/src/Rtp/RtpCache.h b/src/Rtp/RtpCache.h index a3882222..8dc0e451 100644 --- a/src/Rtp/RtpCache.h +++ b/src/Rtp/RtpCache.h @@ -23,7 +23,6 @@ class RtpCache : protected PacketCache { public: using onFlushed = std::function >)>; RtpCache(onFlushed cb); - ~RtpCache() override = default; protected: /** @@ -42,7 +41,6 @@ private: class RtpCachePS : public RtpCache, public PSEncoderImp { public: RtpCachePS(onFlushed cb, uint32_t ssrc, uint8_t payload_type = 96) : RtpCache(std::move(cb)), PSEncoderImp(ssrc, payload_type) {}; - ~RtpCachePS() override = default; void flush() override; protected: @@ -52,7 +50,6 @@ protected: class RtpCacheRaw : public RtpCache, public RawEncoderImp { public: RtpCacheRaw(onFlushed cb, uint32_t ssrc, uint8_t payload_type = 96, bool send_audio = true) : RtpCache(std::move(cb)), RawEncoderImp(ssrc, payload_type, send_audio) {}; - ~RtpCacheRaw() override = default; void flush() override; protected: diff --git a/src/Rtp/RtpProcess.cpp b/src/Rtp/RtpProcess.cpp index 33df2829..b31e88df 100644 --- a/src/Rtp/RtpProcess.cpp +++ b/src/Rtp/RtpProcess.cpp @@ -305,4 +305,4 @@ float RtpProcess::getLossRate(MediaSource &sender, TrackType type) { } }//namespace mediakit -#endif//defined(ENABLE_RTPPROXY) +#endif//defined(ENABLE_RTPPROXY) \ No newline at end of file diff --git a/src/Rtp/RtpSelector.h b/src/Rtp/RtpSelector.h index db0683e8..2abefb2d 100644 --- a/src/Rtp/RtpSelector.h +++ b/src/Rtp/RtpSelector.h @@ -41,14 +41,10 @@ private: class RtpSelector : public std::enable_shared_from_this{ public: - RtpSelector() = default; - ~RtpSelector() = default; - class ProcessExisted : public std::runtime_error { public: template ProcessExisted(T && ...args) : std::runtime_error(std::forward(args)...) {} - ~ProcessExisted() override = default; }; static bool getSSRC(const char *data,size_t data_len, uint32_t &ssrc); diff --git a/src/Rtp/RtpSender.cpp b/src/Rtp/RtpSender.cpp index 628696fa..87edf3ad 100644 --- a/src/Rtp/RtpSender.cpp +++ b/src/Rtp/RtpSender.cpp @@ -279,7 +279,7 @@ void RtpSender::onSendRtpUdp(const toolkit::Buffer::Ptr &buf, bool check) { return; } auto rtp = static_pointer_cast(buf); - _rtcp_context->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->getStampMS(), 90000 /*not used*/, rtp->size()); + _rtcp_context->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, 90000 /*not used*/, rtp->size()); if (!check) { //减少判断次数 diff --git a/src/Rtp/RtpServer.h b/src/Rtp/RtpServer.h index 71aa88e7..12cc4d94 100644 --- a/src/Rtp/RtpServer.h +++ b/src/Rtp/RtpServer.h @@ -31,7 +31,6 @@ public: using onRecv = std::function; enum TcpMode { NONE = 0, PASSIVE, ACTIVE }; - RtpServer() = default; ~RtpServer(); /** diff --git a/src/Rtp/RtpSession.cpp b/src/Rtp/RtpSession.cpp index 70c8dc7a..db3ecc2d 100644 --- a/src/Rtp/RtpSession.cpp +++ b/src/Rtp/RtpSession.cpp @@ -35,7 +35,8 @@ void RtpSession::setParams(mINI &ini) { _only_audio = ini[kOnlyAudio]; } -RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) { +RtpSession::RtpSession(const Socket::Ptr &sock) + : Session(sock) { socklen_t addr_len = sizeof(_addr); getpeername(sock->rawFD(), (struct sockaddr *)&_addr, &addr_len); _is_udp = sock->sockType() == SockNum::Sock_UDP; @@ -46,8 +47,8 @@ RtpSession::RtpSession(const Socket::Ptr &sock) : Session(sock) { } RtpSession::~RtpSession() { - if(_process){ - RtpSelector::Instance().delProcess(_stream_id,_process.get()); + if (_process) { + RtpSelector::Instance().delProcess(_stream_id, _process.get()); } } @@ -64,11 +65,11 @@ void RtpSession::onError(const SockException &err) { } void RtpSession::onManager() { - if(_process && !_process->alive()){ + if (_process && !_process->alive()) { shutdown(SockException(Err_timeout, "receive rtp timeout")); } - if(!_process && _ticker.createdTime() > 10 * 1000){ + if (!_process && _ticker.createdTime() > 10 * 1000) { shutdown(SockException(Err_timeout, "illegal connection")); } } @@ -160,12 +161,12 @@ bool RtpSession::close(MediaSource &sender) { } static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) { - //rtp前面必须预留两个字节的长度字段 + // rtp前面必须预留两个字节的长度字段 for (ssize_t i = 2; i <= len - 4; ++i) { - auto ptr = (const uint8_t *) data + i; - if (ptr[0] == (ssrc >> 24) && ptr[1] == ((ssrc >> 16) & 0xFF) && - ptr[2] == ((ssrc >> 8) & 0xFF) && ptr[3] == (ssrc & 0xFF)) { - return (const char *) ptr; + auto ptr = (const uint8_t *)data + i; + if (ptr[0] == (ssrc >> 24) && ptr[1] == ((ssrc >> 16) & 0xFF) && ptr[2] == ((ssrc >> 8) & 0xFF) + && ptr[3] == (ssrc & 0xFF)) { + return (const char *)ptr; } } return nullptr; @@ -173,17 +174,17 @@ static const char *findSSRC(const char *data, ssize_t len, uint32_t ssrc) { static const char *findPsHeaderFlag(const char *data, ssize_t len) { for (ssize_t i = 2; i <= len - 4; ++i) { - auto ptr = (const uint8_t *) data + i; - //PsHeader 0x000001ba、PsSystemHeader0x000001bb(关键帧标识) + auto ptr = (const uint8_t *)data + i; + // PsHeader 0x000001ba、PsSystemHeader0x000001bb(关键帧标识) if (ptr[0] == (0x00) && ptr[1] == (0x00) && ptr[2] == (0x01) && ptr[3] == (0xbb)) { - return (const char *) ptr; + return (const char *)ptr; } } return nullptr; } -//rtp长度到ssrc间的长度固定为10 +// rtp长度到ssrc间的长度固定为10 static size_t constexpr kSSRCOffset = 2 + 4 + 4; // rtp长度到ps header间的长度固定为14 (暂时不采用找ps header,采用找system header代替) // rtp长度到ps system header间的长度固定为20 (关键帧标识) @@ -191,81 +192,80 @@ static size_t constexpr kPSHeaderOffset = 2 + 4 + 4 + 4 + 20; const char *RtpSession::onSearchPacketTail(const char *data, size_t len) { if (!_search_rtp) { - //tcp上下文正常,不用搜索ssrc + // tcp上下文正常,不用搜索ssrc return RtpSplitter::onSearchPacketTail(data, len); } if (!_process) { InfoL << "ssrc未获取到,无法通过ssrc恢复tcp上下文;尝试搜索PsSystemHeader恢复tcp上下文。"; - auto rtp_ptr1 = searchByPsHeaderFlag(data,len); + auto rtp_ptr1 = searchByPsHeaderFlag(data, len); return rtp_ptr1; } - auto rtp_ptr0 = searchBySSRC(data,len); - if(rtp_ptr0) { + auto rtp_ptr0 = searchBySSRC(data, len); + if (rtp_ptr0) { return rtp_ptr0; } // ssrc搜索失败继续尝试搜索ps header flag - auto rtp_ptr2 = searchByPsHeaderFlag(data,len); + auto rtp_ptr2 = searchByPsHeaderFlag(data, len); return rtp_ptr2; } const char *RtpSession::searchBySSRC(const char *data, size_t len) { InfoL << "尝试rtp搜索ssrc..._ssrc=" << _ssrc; - //搜索第一个rtp的ssrc + // 搜索第一个rtp的ssrc auto ssrc_ptr0 = findSSRC(data, len, _ssrc); if (!ssrc_ptr0) { - //未搜索到任意rtp,返回数据不够 + // 未搜索到任意rtp,返回数据不够 InfoL << "rtp搜索ssrc失败(第一个数据不够),丢弃rtp数据为:" << len; return nullptr; } - //这两个字节是第一个rtp的长度字段 + // 这两个字节是第一个rtp的长度字段 auto rtp_len_ptr = (ssrc_ptr0 - kSSRCOffset); auto rtp_len = ((uint8_t *)rtp_len_ptr)[0] << 8 | ((uint8_t *)rtp_len_ptr)[1]; - //搜索第二个rtp的ssrc - auto ssrc_ptr1 = findSSRC(ssrc_ptr0 + rtp_len, data + (ssize_t) len - ssrc_ptr0 - rtp_len, _ssrc); + // 搜索第二个rtp的ssrc + auto ssrc_ptr1 = findSSRC(ssrc_ptr0 + rtp_len, data + (ssize_t)len - ssrc_ptr0 - rtp_len, _ssrc); if (!ssrc_ptr1) { - //未搜索到第二个rtp,返回数据不够 + // 未搜索到第二个rtp,返回数据不够 InfoL << "rtp搜索ssrc失败(第二个数据不够),丢弃rtp数据为:" << len; return nullptr; } - //两个ssrc的间隔正好等于rtp的长度(外加rtp长度字段),那么说明找到rtp + // 两个ssrc的间隔正好等于rtp的长度(外加rtp长度字段),那么说明找到rtp auto ssrc_offset = ssrc_ptr1 - ssrc_ptr0; if (ssrc_offset == rtp_len + 2 || ssrc_offset == rtp_len + 4) { InfoL << "rtp搜索ssrc成功,tcp上下文恢复成功,丢弃的rtp残余数据为:" << rtp_len_ptr - data; _search_rtp_finished = true; if (rtp_len_ptr == data) { - //停止搜索rtp,否则会进入死循环 + // 停止搜索rtp,否则会进入死循环 _search_rtp = false; } - //前面的数据都需要丢弃,这个是rtp的起始 + // 前面的数据都需要丢弃,这个是rtp的起始 return rtp_len_ptr; } - //第一个rtp长度不匹配,说明第一个找到的ssrc不是rtp,丢弃之,我们从第二个ssrc所在rtp开始搜索 + // 第一个rtp长度不匹配,说明第一个找到的ssrc不是rtp,丢弃之,我们从第二个ssrc所在rtp开始搜索 return ssrc_ptr1 - kSSRCOffset; } const char *RtpSession::searchByPsHeaderFlag(const char *data, size_t len) { - InfoL << "尝试rtp搜索PsSystemHeaderFlag..._ssrc=" << _ssrc; + InfoL << "尝试rtp搜索PsSystemHeaderFlag..._ssrc=" << _ssrc; // 搜索rtp中的第一个PsHeaderFlag - auto ps_header_flag_ptr = findPsHeaderFlag(data,len); + auto ps_header_flag_ptr = findPsHeaderFlag(data, len); if (!ps_header_flag_ptr) { InfoL << "rtp搜索flag失败,丢弃rtp数据为:" << len; return nullptr; } - auto rtp_ptr = ps_header_flag_ptr - kPSHeaderOffset; _search_rtp_finished = true; if (rtp_ptr == data) { - //停止搜索rtp,否则会进入死循环 + // 停止搜索rtp,否则会进入死循环 _search_rtp = false; } InfoL << "rtp搜索flag成功,tcp上下文恢复成功,丢弃的rtp残余数据为:" << rtp_ptr - data; // TODO or Not ? 更新设置ssrc uint32_t rtp_ssrc = 0; - RtpSelector::getSSRC(rtp_ptr+2, len, rtp_ssrc); + RtpSelector::getSSRC(rtp_ptr + 2, len, rtp_ssrc); _ssrc = rtp_ssrc; InfoL << "设置_ssrc为:" << _ssrc; // RtpServer::updateSSRC(uint32_t ssrc) diff --git a/src/Rtp/RtpSplitter.h b/src/Rtp/RtpSplitter.h index a2990a7f..d7a6afb5 100644 --- a/src/Rtp/RtpSplitter.h +++ b/src/Rtp/RtpSplitter.h @@ -17,10 +17,6 @@ namespace mediakit{ class RtpSplitter : public HttpRequestSplitter{ -public: - RtpSplitter() = default; - ~RtpSplitter() override = default; - protected: /** * 收到rtp包回调 diff --git a/src/Rtp/TSDecoder.h b/src/Rtp/TSDecoder.h index fb306502..0984581e 100644 --- a/src/Rtp/TSDecoder.h +++ b/src/Rtp/TSDecoder.h @@ -25,7 +25,6 @@ class TSSegment : public HttpRequestSplitter { public: typedef std::function onSegment; TSSegment(size_t size = TS_PACKET_SIZE) : _size(size){} - ~TSSegment() = default; void setOnSegment(onSegment cb); static bool isTSPacket(const char *data, size_t len); diff --git a/src/Rtsp/RtpCodec.h b/src/Rtsp/RtpCodec.h index b1acde58..56824567 100644 --- a/src/Rtsp/RtpCodec.h +++ b/src/Rtsp/RtpCodec.h @@ -23,23 +23,14 @@ public: using Ptr = std::shared_ptr; using RingType = toolkit::RingBuffer; - RtpRing() = default; virtual ~RtpRing() = default; - /** - * 获取rtp环形缓存 - * @return - */ - virtual RingType::Ptr getRtpRing() const { - return _ring; - } - /** * 设置rtp环形缓存 * @param ring */ - virtual void setRtpRing(const RingType::Ptr &ring) { - _ring = ring; + void setRtpRing(RingType::Ptr ring) { + _ring = std::move(ring); } /** @@ -74,17 +65,11 @@ public: _interleaved = interleaved; } - virtual ~RtpInfo() = default; - //返回rtp负载最大长度 size_t getMaxSize() const { return _mtu_size - RtpPacket::kRtpHeaderSize; } - uint32_t getSsrc() const { - return _ssrc; - } - RtpPacket::Ptr makeRtp(TrackType type,const void *data, size_t len, bool mark, uint64_t stamp); private: @@ -96,17 +81,21 @@ private: size_t _mtu_size; }; -class RtpCodec : public RtpRing, public FrameDispatcher, public CodecInfo { +class RtpCodec : public RtpRing, public FrameDispatcher { public: using Ptr = std::shared_ptr; - RtpCodec() = default; - ~RtpCodec() override = default; + void setRtpInfo(uint32_t ssrc, size_t mtu_size, uint32_t sample_rate, uint8_t pt, uint8_t interleaved) { + _rtp_info.reset(new RtpInfo(ssrc, mtu_size, sample_rate, pt, interleaved)); + } + + RtpInfo &getRtpInfo() { return *_rtp_info; } + +private: + std::unique_ptr _rtp_info; }; }//namespace mediakit - - #endif //ZLMEDIAKIT_RTPCODEC_H diff --git a/src/Rtsp/RtpMultiCaster.h b/src/Rtsp/RtpMultiCaster.h index 98ce46fe..a2534ad2 100644 --- a/src/Rtsp/RtpMultiCaster.h +++ b/src/Rtsp/RtpMultiCaster.h @@ -22,7 +22,6 @@ namespace mediakit{ class MultiCastAddressMaker { public: - ~MultiCastAddressMaker() = default; static MultiCastAddressMaker& Instance(); static bool isMultiCastAddress(uint32_t addr); static std::string toString(uint32_t addr); diff --git a/src/Rtsp/RtpReceiver.h b/src/Rtsp/RtpReceiver.h index d8dbc48d..433910cf 100644 --- a/src/Rtsp/RtpReceiver.h +++ b/src/Rtsp/RtpReceiver.h @@ -28,8 +28,7 @@ public: static constexpr SEQ SEQ_MAX = (std::numeric_limits::max)(); using iterator = typename std::map::iterator; - PacketSortor() = default; - ~PacketSortor() = default; + virtual ~PacketSortor() = default; void setOnSort(std::function cb) { _cb = std::move(cb); } @@ -102,7 +101,7 @@ private: ret = next_seq - seq; } if (ret > SEQ_MAX >> 1) { - return SEQ_MAX - ret + 1; + return SEQ_MAX - ret; } return ret; } @@ -201,11 +200,9 @@ public: public: template BadRtpException(Type &&type) : invalid_argument(std::forward(type)) {} - ~BadRtpException() = default; }; RtpTrack(); - virtual ~RtpTrack() = default; void clear(); uint32_t getSSRC() const; @@ -230,9 +227,6 @@ public: using OnSorted = std::function; using BeforeSorted = std::function; - RtpTrackImp() = default; - ~RtpTrackImp() override = default; - void setOnSorted(OnSorted cb); void setBeforeSorted(BeforeSorted cb); diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index dc34f918..bba9abf2 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -166,6 +166,8 @@ public: // ntp时间戳 uint64_t ntp_stamp; + bool disable_ntp = false; + static Ptr create(); private: @@ -232,7 +234,6 @@ public: SdpParser() = default; SdpParser(const std::string &sdp) { load(sdp); } - ~SdpParser() = default; void load(const std::string &sdp); bool available() const; @@ -248,7 +249,7 @@ private: /** * rtsp sdp基类 */ -class Sdp : public CodecInfo { +class Sdp { public: using Ptr = std::shared_ptr; @@ -303,8 +304,6 @@ public: std::string getSdp() const override { return _printer; } - CodecId getCodecId() const override { return CodecInvalid; } - float getDuration() const { return _dur_sec; } private: diff --git a/src/Rtsp/RtspDemuxer.h b/src/Rtsp/RtspDemuxer.h index 51b7bfea..3444587d 100644 --- a/src/Rtsp/RtspDemuxer.h +++ b/src/Rtsp/RtspDemuxer.h @@ -20,8 +20,6 @@ namespace mediakit { class RtspDemuxer : public Demuxer { public: using Ptr = std::shared_ptr; - RtspDemuxer() = default; - virtual ~RtspDemuxer() = default; /** * 加载sdp diff --git a/src/Rtsp/RtspMediaSourceImp.h b/src/Rtsp/RtspMediaSourceImp.h index 483d7610..6ce27bba 100644 --- a/src/Rtsp/RtspMediaSourceImp.h +++ b/src/Rtsp/RtspMediaSourceImp.h @@ -30,8 +30,6 @@ public: */ RtspMediaSourceImp(const MediaTuple& tuple, int ringSize = RTP_GOP_SIZE); - ~RtspMediaSourceImp() override = default; - /** * 设置sdp */ diff --git a/src/Rtsp/RtspMuxer.cpp b/src/Rtsp/RtspMuxer.cpp index 1665000c..b1548c36 100644 --- a/src/Rtsp/RtspMuxer.cpp +++ b/src/Rtsp/RtspMuxer.cpp @@ -9,35 +9,32 @@ */ #include "RtspMuxer.h" +#include "Common/config.h" #include "Extension/Factory.h" using namespace std; using namespace toolkit; -#define ENABLE_NTP_STAMP 1 - namespace mediakit { void RtspMuxer::onRtp(RtpPacket::Ptr in, bool is_key) { -#if ENABLE_NTP_STAMP if (_live) { if (_rtp_stamp[in->type] != in->getHeader()->stamp) { - //rtp时间戳变化才计算ntp,节省cpu资源 + // rtp时间戳变化才计算ntp,节省cpu资源 int64_t stamp_ms = in->getStamp() * uint64_t(1000) / in->sample_rate; int64_t stamp_ms_inc; - //求rtp时间戳增量 + // 求rtp时间戳增量 _stamp[in->type].revise(stamp_ms, stamp_ms, stamp_ms_inc, stamp_ms_inc); _rtp_stamp[in->type] = in->getHeader()->stamp; _ntp_stamp[in->type] = stamp_ms_inc + _ntp_stamp_start; } - //rtp拦截入口,此处统一赋值ntp + // rtp拦截入口,此处统一赋值ntp in->ntp_stamp = _ntp_stamp[in->type]; } else { - //点播情况下设置ntp时间戳为rtp时间戳加基准ntp时间戳 + // 点播情况下设置ntp时间戳为rtp时间戳加基准ntp时间戳 in->ntp_stamp = _ntp_stamp_start + (in->getStamp() * uint64_t(1000) / in->sample_rate); } -#endif _rtpRing->write(std::move(in), is_key); } @@ -54,44 +51,72 @@ RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) { onRtp(std::move(in), is_key); })); -#if ENABLE_NTP_STAMP _ntp_stamp_start = getCurrentMillisecond(true); -#endif } bool RtspMuxer::addTrack(const Track::Ptr &track) { - //根据track生成sdp - Sdp::Ptr sdp = track->getSdp(); + auto &encoder = _encoder[track->getTrackType()]; + if (encoder) { + WarnL << "Already add a track kind of: " << track->getTrackTypeStr() + << ", ignore track: " << track->getCodecName(); + return false; + } + // payload type 96以后则为动态pt + Sdp::Ptr sdp = track->getSdp(96 + _index); if (!sdp) { + WarnL << "rtsp复用器不支持该编码:" << track->getCodecName(); return false; } - auto &encoder = _encoder[track->getTrackType()]; - encoder = Factory::getRtpEncoderBySdp(sdp); + encoder = Factory::getRtpEncoderByCodecId(track->getCodecId(), sdp->getPayloadType()); if (!encoder) { return false; } - //设置rtp输出环形缓存 + { + static atomic s_ssrc(0); + uint32_t ssrc = s_ssrc++; + if (!ssrc) { + // ssrc不能为0 + ssrc = s_ssrc++; + } + if (track->getTrackType() == TrackVideo) { + // 视频的ssrc是偶数,方便调试 + ssrc = 2 * ssrc; + } else { + // 音频ssrc是奇数 + ssrc = 2 * ssrc + 1; + } + GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize); + GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize); + auto mtu = track->getTrackType() == TrackVideo ? video_mtu : audio_mtu; + encoder->setRtpInfo(ssrc, mtu, sdp->getSampleRate(), sdp->getPayloadType(), 2 * track->getTrackType()); + } + + // 设置rtp输出环形缓存 encoder->setRtpRing(_rtpInterceptor); - //添加其sdp - _sdp.append(sdp->getSdp()); + auto str = sdp->getSdp(); + str += "a=control:trackID="; + str += std::to_string(_index); + str += "\r\n"; + + // 添加其sdp + _sdp.append(str); trySyncTrack(); // rtp的时间戳是pts,允许回退 - _stamp[TrackAudio].enableRollback(true); _stamp[TrackVideo].enableRollback(true); + + ++_index; return true; } void RtspMuxer::trySyncTrack() { -#if ENABLE_NTP_STAMP if (_encoder[TrackAudio] && _encoder[TrackVideo]) { - //音频时间戳同步于视频,因为音频时间戳被修改后不影响播放 + // 音频时间戳同步于视频,因为音频时间戳被修改后不影响播放 _stamp[TrackAudio].syncTo(_stamp[TrackVideo]); } -#endif } bool RtspMuxer::inputFrame(const Frame::Ptr &frame) { @@ -122,5 +147,4 @@ void RtspMuxer::resetTracks() { } } - } /* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtsp/RtspMuxer.h b/src/Rtsp/RtspMuxer.h index 6b5cfa56..2ab1ba59 100644 --- a/src/Rtsp/RtspMuxer.h +++ b/src/Rtsp/RtspMuxer.h @@ -22,8 +22,6 @@ class RingDelegateHelper : public toolkit::RingDelegate { public: using onRtp = std::function ; - ~RingDelegateHelper() override = default; - RingDelegateHelper(onRtp on_rtp) { _on_rtp = std::move(on_rtp); } @@ -47,7 +45,6 @@ public: * 构造函数 */ RtspMuxer(const TitleSdp::Ptr &title = nullptr); - ~RtspMuxer() override = default; /** * 获取完整的SDP字符串 @@ -88,6 +85,7 @@ private: private: bool _live = true; + uint8_t _index {0}; uint32_t _rtp_stamp[TrackMax]{0}; uint64_t _ntp_stamp[TrackMax]{0}; uint64_t _ntp_stamp_start; diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index f6a13fda..6a913653 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -479,7 +479,7 @@ void RtspPlayer::handleResPAUSE(const Parser &parser, int type) { DebugL << "seekTo(ms):" << iSeekTo; } - onPlayResult_l(SockException(Err_success, type == type_seek ? "resum rtsp success" : "rtsp play success"), !_play_check_timer); + onPlayResult_l(SockException(Err_success, type == type_seek ? "resume rtsp success" : "rtsp play success"), !_play_check_timer); } void RtspPlayer::onWholeRtspPacket(Parser &parser) { diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index ea647300..615617b9 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -56,8 +56,6 @@ RtspSession::RtspSession(const Socket::Ptr &sock) : Session(sock) { sock->setSendTimeOutSecond(keep_alive_sec); } -RtspSession::~RtspSession() = default; - void RtspSession::onError(const SockException &err) { bool is_player = !_push_src_ownership; uint64_t duration = _alive_ticker.createdTime() / 1000; @@ -679,17 +677,17 @@ void RtspSession::handleReq_Setup(const Parser &parser) { switch (_rtp_type) { case Rtsp::RTP_TCP: { - if(_push_src){ - //rtsp推流时,interleaved由推流者决定 - auto key_values = Parser::parseArgs(parser["Transport"],";","="); - int interleaved_rtp = -1 , interleaved_rtcp = -1; - if(2 == sscanf(key_values["interleaved"].data(),"%d-%d",&interleaved_rtp,&interleaved_rtcp)){ + if (_push_src) { + // rtsp推流时,interleaved由推流者决定 + auto key_values = Parser::parseArgs(parser["Transport"], ";", "="); + int interleaved_rtp = -1, interleaved_rtcp = -1; + if (2 == sscanf(key_values["interleaved"].data(), "%d-%d", &interleaved_rtp, &interleaved_rtcp)) { trackRef->_interleaved = interleaved_rtp; - }else{ + } else { throw SockException(Err_shutdown, "can not find interleaved when setup of rtp over tcp"); } - }else{ - //rtsp播放时,由于数据共享分发,所以interleaved必须由服务器决定 + } else { + // rtsp播放时,由于数据共享分发,所以interleaved必须由服务器决定 trackRef->_interleaved = 2 * trackRef->_type; } sendRtspResponse("200 OK", diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index 4b476dd0..6444f343 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -34,7 +34,6 @@ public: using onAuth = std::function; RtspSession(const toolkit::Socket::Ptr &sock); - virtual ~RtspSession(); ////Session override//// void onRecv(const toolkit::Buffer::Ptr &buf) override; void onError(const toolkit::SockException &err) override; diff --git a/src/Rtsp/RtspSplitter.cpp b/src/Rtsp/RtspSplitter.cpp index f5d1e792..d23fc202 100644 --- a/src/Rtsp/RtspSplitter.cpp +++ b/src/Rtsp/RtspSplitter.cpp @@ -57,13 +57,16 @@ const char *RtspSplitter::onSearchPacketTail_l(const char *data, size_t len) { } ssize_t RtspSplitter::onRecvHeader(const char *data, size_t len) { - if(_isRtpPacket){ - onRtpPacket(data,len); + if (_isRtpPacket) { + onRtpPacket(data, len); + return 0; + } + if (len == 4 && !memcmp(data, "\r\n\r\n", 4)) { return 0; } _parser.parse(data, len); auto ret = getContentLength(_parser); - if(ret == 0){ + if (ret == 0) { onWholeRtspPacket(_parser); _parser.clear(); } diff --git a/src/Rtsp/RtspSplitter.h b/src/Rtsp/RtspSplitter.h index ca9daed2..1bdfa027 100644 --- a/src/Rtsp/RtspSplitter.h +++ b/src/Rtsp/RtspSplitter.h @@ -18,9 +18,6 @@ namespace mediakit{ class RtspSplitter : public HttpRequestSplitter{ public: - RtspSplitter() = default; - virtual ~RtspSplitter() = default; - /** * 是否允许接收rtp包 * @param enable diff --git a/src/Shell/ShellCMD.h b/src/Shell/ShellCMD.h index 2e283b00..595630ad 100644 --- a/src/Shell/ShellCMD.h +++ b/src/Shell/ShellCMD.h @@ -55,8 +55,6 @@ public: (*_parser) << toolkit::Option('s', "stream", toolkit::Option::ArgRequired, nullptr, false, "流id筛选", nullptr); } - virtual ~CMD_media() {} - const char *description() const override { return "媒体源相关操作."; } diff --git a/src/Shell/ShellSession.cpp b/src/Shell/ShellSession.cpp index 85c682ee..98f51632 100644 --- a/src/Shell/ShellSession.cpp +++ b/src/Shell/ShellSession.cpp @@ -28,8 +28,6 @@ ShellSession::ShellSession(const Socket::Ptr &_sock) : Session(_sock) { pleaseInputUser(); } -ShellSession::~ShellSession() = default; - void ShellSession::onRecv(const Buffer::Ptr&buf) { //DebugL << hexdump(buf->data(), buf->size()); GET_CONFIG(uint32_t,maxReqSize,Shell::kMaxReqSize); diff --git a/src/Shell/ShellSession.h b/src/Shell/ShellSession.h index 46113a27..e96ee016 100644 --- a/src/Shell/ShellSession.h +++ b/src/Shell/ShellSession.h @@ -20,7 +20,6 @@ namespace mediakit { class ShellSession: public toolkit::Session { public: ShellSession(const toolkit::Socket::Ptr &_sock); - virtual ~ShellSession(); void onRecv(const toolkit::Buffer::Ptr &) override; void onError(const toolkit::SockException &err) override; diff --git a/src/TS/TSMediaSource.h b/src/TS/TSMediaSource.h index b691d15f..ccf9e06e 100644 --- a/src/TS/TSMediaSource.h +++ b/src/TS/TSMediaSource.h @@ -26,7 +26,6 @@ public: template TSPacket(ARGS && ...args) : BufferOffset(std::forward(args)...) {}; - ~TSPacket() override = default; public: uint64_t time_stamp = 0; diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index 9f83ddde..5211fd4c 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -16,8 +16,6 @@ SrtSession::SrtSession(const Socket::Ptr &sock) // TraceL<<"after addr len "<data(); size_t size = buffer->size(); diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp index 004a61a1..4064534f 100644 --- a/srt/SrtSession.hpp +++ b/srt/SrtSession.hpp @@ -11,7 +11,6 @@ using namespace toolkit; class SrtSession : public Session { public: SrtSession(const Socket::Ptr &sock); - ~SrtSession() override; void onRecv(const Buffer::Ptr &) override; void onError(const SockException &err) override; diff --git a/webrtc/Nack.h b/webrtc/Nack.h index 8780e27a..4993da85 100644 --- a/webrtc/Nack.h +++ b/webrtc/Nack.h @@ -22,9 +22,6 @@ namespace mediakit { class NackList { public: - NackList() = default; - ~NackList() = default; - void pushBack(RtpPacket::Ptr rtp); void forEach(const FCI_NACK &nack, const std::function &cb); @@ -58,7 +55,6 @@ public: static_assert(kNackRtpSize >=0 && kNackRtpSize <= FCI_NACK::kBitSize, "NackContext::kNackRtpSize must between 0 and 16"); NackContext(); - ~NackContext() = default; void received(uint16_t seq, bool is_rtx = false); void setOnNack(onNack cb); diff --git a/webrtc/RtpExt.h b/webrtc/RtpExt.h index 524fa3bb..2e691580 100644 --- a/webrtc/RtpExt.h +++ b/webrtc/RtpExt.h @@ -53,7 +53,6 @@ public: template friend void appendExt(std::map &ret, uint8_t *ptr, const uint8_t *end); friend class RtpExtContext; - ~RtpExt() = default; static std::map getExtValue(const RtpHeader *header); static RtpExtType getExtType(const std::string &url); @@ -119,7 +118,6 @@ public: using OnGetRtp = std::function; RtpExtContext(const RtcMedia &media); - ~RtpExtContext() = default; void setOnGetRtp(OnGetRtp cb); std::string getRid(uint32_t ssrc) const; diff --git a/webrtc/TwccContext.h b/webrtc/TwccContext.h index db81edc6..7a650f22 100644 --- a/webrtc/TwccContext.h +++ b/webrtc/TwccContext.h @@ -26,9 +26,6 @@ public: //每个twcc rtcp包发送的最大时间间隔,单位毫秒 static constexpr size_t kMaxTimeDelta = 256; - TwccContext() = default; - ~TwccContext() = default; - void onRtp(uint32_t ssrc, uint16_t twcc_ext_seq, uint64_t stamp_ms); void setOnSendTwccCB(onSendTwccCB cb); diff --git a/webrtc/WebRtcEchoTest.h b/webrtc/WebRtcEchoTest.h index 0ab74e7b..1926c1cb 100644 --- a/webrtc/WebRtcEchoTest.h +++ b/webrtc/WebRtcEchoTest.h @@ -18,7 +18,6 @@ namespace mediakit { class WebRtcEchoTest : public WebRtcTransportImp { public: using Ptr = std::shared_ptr; - ~WebRtcEchoTest() override = default; static Ptr create(const EventPoller::Ptr &poller); protected: diff --git a/webrtc/WebRtcPlayer.h b/webrtc/WebRtcPlayer.h index 02208f6d..4e04e820 100644 --- a/webrtc/WebRtcPlayer.h +++ b/webrtc/WebRtcPlayer.h @@ -19,7 +19,6 @@ namespace mediakit { class WebRtcPlayer : public WebRtcTransportImp { public: using Ptr = std::shared_ptr; - ~WebRtcPlayer() override = default; static Ptr create(const EventPoller::Ptr &poller, const RtspMediaSource::Ptr &src, const MediaInfo &info, bool preferred_tcp = false); MediaInfo getMediaInfo() { return _media_info; } diff --git a/webrtc/WebRtcPusher.h b/webrtc/WebRtcPusher.h index 8d309395..061ccb46 100644 --- a/webrtc/WebRtcPusher.h +++ b/webrtc/WebRtcPusher.h @@ -19,7 +19,6 @@ namespace mediakit { class WebRtcPusher : public WebRtcTransportImp, public MediaSourceEvent { public: using Ptr = std::shared_ptr; - ~WebRtcPusher() override = default; static Ptr create(const EventPoller::Ptr &poller, const RtspMediaSource::Ptr &src, const std::shared_ptr &ownership, const MediaInfo &info, const ProtocolOption &option, bool preferred_tcp = false); diff --git a/webrtc/WebRtcSession.cpp b/webrtc/WebRtcSession.cpp index ee3051c0..fba9cf92 100644 --- a/webrtc/WebRtcSession.cpp +++ b/webrtc/WebRtcSession.cpp @@ -51,8 +51,6 @@ WebRtcSession::WebRtcSession(const Socket::Ptr &sock) : Session(sock) { _over_tcp = sock->sockType() == SockNum::Sock_TCP; } -WebRtcSession::~WebRtcSession() = default; - void WebRtcSession::attachServer(const Server &server) { _server = std::static_pointer_cast(const_cast(server).shared_from_this()); } diff --git a/webrtc/WebRtcSession.h b/webrtc/WebRtcSession.h index 9cf7343c..d728e2f9 100644 --- a/webrtc/WebRtcSession.h +++ b/webrtc/WebRtcSession.h @@ -27,7 +27,6 @@ using namespace toolkit; class WebRtcSession : public Session, public HttpRequestSplitter { public: WebRtcSession(const Socket::Ptr &sock); - ~WebRtcSession() override; void attachServer(const Server &server) override; void onRecv(const Buffer::Ptr &) override; diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index eafe579b..443ae701 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -10,6 +10,8 @@ #include #include +#include "Util/base64.h" +#include "Network/sockutil.h" #include "Common/config.h" #include "RtpExt.h" #include "Rtcp/Rtcp.h" @@ -22,7 +24,6 @@ #include "WebRtcEchoTest.h" #include "WebRtcPlayer.h" #include "WebRtcPusher.h" - #include "Rtsp/RtspMediaSourceImp.h" #define RTP_SSRC_OFFSET 1 @@ -47,15 +48,23 @@ const string kExternIP = RTC_FIELD "externIP"; const string kRembBitRate = RTC_FIELD "rembBitRate"; // webrtc单端口udp服务器 const string kPort = RTC_FIELD "port"; - const string kTcpPort = RTC_FIELD "tcpPort"; +// 比特率设置 +const string kStartBitrate = RTC_FIELD "start_bitrate"; +const string kMaxBitrate = RTC_FIELD "max_bitrate"; +const string kMinBitrate = RTC_FIELD "min_bitrate"; + static onceToken token([]() { mINI::Instance()[kTimeOutSec] = 15; mINI::Instance()[kExternIP] = ""; mINI::Instance()[kRembBitRate] = 0; mINI::Instance()[kPort] = 0; mINI::Instance()[kTcpPort] = 0; + + mINI::Instance()[kStartBitrate] = 0; + mINI::Instance()[kMaxBitrate] = 0; + mINI::Instance()[kMinBitrate] = 0; }); } // namespace RTC @@ -77,6 +86,28 @@ static void translateIPFromEnv(std::vector &v) { } } +static std::string getServerPrefix() { + //stun_user_name格式: base64(ip+udp_port+tcp_port) + _ + number + //其中ip为二进制char[4], udp_port/tcp_port为大端 uint16. + //number为自增长数,确保短时间内唯一 + GET_CONFIG(uint16_t, udp_port, Rtc::kPort); + GET_CONFIG(uint16_t, tcp_port, Rtc::kTcpPort); + char buf[8]; + auto host = SockUtil::get_local_ip(); + auto addr = SockUtil::make_sockaddr(host.data(), udp_port); + //拷贝ipv4地址 + memcpy(buf, &(reinterpret_cast(&addr)->sin_addr), 4); + //拷贝udp端口 + memcpy(buf + 4, &(reinterpret_cast(&addr)->sin_port), 2); + //tcp端口转大端模式 + addr = SockUtil::make_sockaddr(host.data(), tcp_port); + //拷贝tcp端口 + memcpy(buf + 6, &(reinterpret_cast(&addr)->sin_port), 2); + auto ret = encodeBase64(string(buf, 8)) + '_'; + InfoL << "MediaServer(" << host << ":" << udp_port << ":" << tcp_port << ") prefix: " << ret; + return ret; +} + const char* sockTypeStr(Session* session) { if (session) { switch (session->getSock()->sockType()) { @@ -90,7 +121,8 @@ const char* sockTypeStr(Session* session) { WebRtcTransport::WebRtcTransport(const EventPoller::Ptr &poller) { _poller = poller; - _identifier = "zlm" + to_string(++s_key); + static auto prefix = getServerPrefix(); + _identifier = prefix + to_string(++s_key); _packet_pool.setSize(64); } @@ -295,6 +327,20 @@ void WebRtcTransport::onRtcConfigure(RtcConfigure &configure) const { configure.enableTWCC(!remb_bit_rate); } +static void setSdpBitrate(RtcSession &sdp) { + GET_CONFIG(size_t, max_bitrate, Rtc::kMaxBitrate); + GET_CONFIG(size_t, min_bitrate, Rtc::kMinBitrate); + GET_CONFIG(size_t, start_bitrate, Rtc::kStartBitrate); + + auto m = (RtcMedia *)(sdp.getMedia(TrackType::TrackVideo)); + if (m) { + auto &plan = m->plan[0]; + if (max_bitrate) plan.fmtp["x-google-max-bitrate"] = std::to_string(max_bitrate); + if (min_bitrate) plan.fmtp["x-google-min-bitrate"] = std::to_string(min_bitrate); + if (start_bitrate) plan.fmtp["x-google-start-bitrate"] = std::to_string(start_bitrate); + } +} + std::string WebRtcTransport::getAnswerSdp(const string &offer) { try { //// 解析offer sdp //// @@ -316,6 +362,7 @@ std::string WebRtcTransport::getAnswerSdp(const string &offer) { //// 生成answer sdp //// _answer_sdp = configure.createAnswer(*_offer_sdp); onCheckSdp(SdpType::answer, *_answer_sdp); + setSdpBitrate(*_answer_sdp); _answer_sdp->checkValid(); return _answer_sdp->toString(); } catch (exception &ex) { @@ -636,7 +683,7 @@ makeIceCandidate(std::string ip, uint16_t port, uint32_t priority = 100, std::st candidate->foundation = proto + "candidate"; // 优先级,单candidate时随便 candidate->priority = priority; - candidate->address = ip; + candidate->address = std::move(ip); candidate->port = port; candidate->type = "host"; if (proto == "tcp") { @@ -647,6 +694,12 @@ makeIceCandidate(std::string ip, uint16_t port, uint32_t priority = 100, std::st void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const { WebRtcTransport::onRtcConfigure(configure); + if (!_cands.empty()) { + for (auto &cand : _cands) { + configure.addCandidate(cand); + } + return; + } GET_CONFIG(uint16_t, local_udp_port, Rtc::kPort); GET_CONFIG(uint16_t, local_tcp_port, Rtc::kTcpPort); @@ -674,6 +727,10 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const { } } +void WebRtcTransportImp::setIceCandidate(vector cands) { + _cands = std::move(cands); +} + /////////////////////////////////////////////////////////////////// class RtpChannel : public RtpTrackImp, public std::enable_shared_from_this { @@ -687,8 +744,6 @@ public: _nack_ctx.setOnNack([this](const FCI_NACK &nack) { onNack(nack); }); } - ~RtpChannel() override = default; - RtpPacket::Ptr inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len, bool is_rtx) { auto rtp = RtpTrack::inputRtp(type, sample_rate, ptr, len); if (!rtp) { @@ -786,7 +841,6 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) { if (!rtp_chn) { WarnL << "未识别的sr rtcp包:" << rtcp->dumpString(); } else { - // InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate(); // 设置rtp时间戳与ntp时间戳的对应关系 rtp_chn->setNtpStamp(sr->rtpts, sr->getNtpUnixStampMS()); auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp); @@ -1168,8 +1222,26 @@ std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& off return const_cast(exchanger).getAnswerSdp(offer); } -void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb) { +void WebRtcPluginManager::setListener(Listener cb) { lock_guard lck(_mtx_creator); + _listener = std::move(cb); +} + +void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb_in) { + onCreateRtc cb; + lock_guard lck(_mtx_creator); + if (_listener) { + auto listener = _listener; + auto args_ptr = args.shared_from_this(); + auto sender_ptr = static_pointer_cast(sender.shared_from_this()); + cb = [listener, sender_ptr, type, args_ptr, cb_in](const WebRtcInterface &rtc) { + listener(*sender_ptr, type, *args_ptr, rtc); + cb_in(rtc); + }; + } else { + cb = cb_in; + } + auto it = _map_creator.find(type); if (it == _map_creator.end()) { cb(WebRtcException(SockException(Err_other, "the type can not supported"))); @@ -1272,10 +1344,40 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana } } +static void set_webrtc_cands(const WebRtcArgs &args, const WebRtcInterface &rtc) { + vector cands; + { + auto cand_str = trim(args["cand_udp"]); + auto ip_port = toolkit::split(cand_str, ":"); + if (ip_port.size() == 2) { + // udp优先 + auto ice_cand = makeIceCandidate(ip_port[0], atoi(ip_port[1].data()), 120, "udp"); + cands.emplace_back(std::move(*ice_cand)); + } + } + { + auto cand_str = trim(args["cand_tcp"]); + auto ip_port = toolkit::split(cand_str, ":"); + if (ip_port.size() == 2) { + // tcp模式 + auto ice_cand = makeIceCandidate(ip_port[0], atoi(ip_port[1].data()), 100, "tcp"); + cands.emplace_back(std::move(*ice_cand)); + } + } + if (!cands.empty()) { + // udp优先 + const_cast(rtc).setIceCandidate(std::move(cands)); + } +} + static onceToken s_rtc_auto_register([]() { WebRtcPluginManager::Instance().registerPlugin("echo", echo_plugin); WebRtcPluginManager::Instance().registerPlugin("push", push_plugin); WebRtcPluginManager::Instance().registerPlugin("play", play_plugin); + + WebRtcPluginManager::Instance().setListener([](Session &sender, const std::string &type, const WebRtcArgs &args, const WebRtcInterface &rtc) { + set_webrtc_cands(args, rtc); + }); }); }// namespace mediakit \ No newline at end of file diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index 2d1e6bbf..2f70f14c 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -37,11 +37,11 @@ extern const std::string kTimeOutSec; class WebRtcInterface { public: - WebRtcInterface() = default; virtual ~WebRtcInterface() = default; virtual std::string getAnswerSdp(const std::string &offer) = 0; virtual const std::string& getIdentifier() const = 0; virtual const std::string& deleteRandStr() const { static std::string s_null; return s_null; } + virtual void setIceCandidate(std::vector cands) {} }; std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& offer); @@ -49,7 +49,6 @@ std::string exchangeSdp(const WebRtcInterface &exchanger, const std::string& off class WebRtcException : public WebRtcInterface { public: WebRtcException(const SockException &ex) : _ex(ex) {}; - ~WebRtcException() override = default; std::string getAnswerSdp(const std::string &offer) override { throw _ex; } @@ -70,7 +69,6 @@ class WebRtcTransport : public WebRtcInterface, public RTC::DtlsTransport::Liste public: using Ptr = std::shared_ptr; WebRtcTransport(const EventPoller::Ptr &poller); - ~WebRtcTransport() override = default; /** * 创建对象 @@ -251,6 +249,7 @@ public: void onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool rtx = false); void createRtpChannel(const std::string &rid, uint32_t ssrc, MediaTrack &track); + void setIceCandidate(std::vector cands) override; void removeTuple(RTC::TransportTuple* tuple); void safeShutdown(const SockException &ex); @@ -306,6 +305,7 @@ private: std::unordered_map _ssrc_to_track; //根据接收rtp的pt获取相关信息 std::unordered_map> _pt_to_track; + std::vector _cands; }; class WebRtcTransportManager { @@ -324,9 +324,8 @@ private: std::unordered_map > _map; }; -class WebRtcArgs { +class WebRtcArgs : public std::enable_shared_from_this { public: - WebRtcArgs() = default; virtual ~WebRtcArgs() = default; virtual variant operator[](const std::string &key) const = 0; @@ -336,17 +335,20 @@ class WebRtcPluginManager { public: using onCreateRtc = std::function; using Plugin = std::function; + using Listener = std::function; static WebRtcPluginManager &Instance(); void registerPlugin(const std::string &type, Plugin cb); void getAnswerSdp(Session &sender, const std::string &type, const WebRtcArgs &args, const onCreateRtc &cb); + void setListener(Listener cb); private: WebRtcPluginManager() = default; private: mutable std::mutex _mtx_creator; + Listener _listener; std::unordered_map _map_creator; };