diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 7d4de2a11..7a8729e67 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -951,6 +951,15 @@ vhost rtc.vhost.srs.com { # [8000, 320000] # default: 48000 aac_bitrate 48000; + ############################################################### + # Whether initialize RTP rate from SDP sample rate for immediate A/V sync. + # When enabled, the RTP rate (units per millisecond) is initialized from the SDP + # sample rate (e.g., 90 for video 90kHz, 48 for audio 48kHz) before receiving + # 2 RTCP SR packets. This allows immediate audio/video synchronization. + # The rate will be updated to a more precise value after receiving the 2nd SR. + # Overwrite by env SRS_VHOST_RTC_INIT_RATE_FROM_SDP for all vhosts. + # Default: off + init_rate_from_sdp off; } ############################################################### # For transmuxing RTMP to RTC, it will impact the default values if RTC is on. diff --git a/trunk/configure b/trunk/configure index 5fb52bbc3..f9100c909 100755 --- a/trunk/configure +++ b/trunk/configure @@ -381,12 +381,14 @@ if [[ $SRS_UTEST == YES ]]; then "srs_utest_manual_protocol" "srs_utest_manual_protocol2" "srs_utest_manual_kernel2" "srs_utest_manual_st" "srs_utest_manual_fmp4" "srs_utest_manual_source_lock" "srs_utest_manual_stream_token" "srs_utest_manual_rtc_recv_track" "srs_utest_manual_st2" "srs_utest_manual_hevc_structs" "srs_utest_manual_coworkers" "srs_utest_manual_pithy_print" "srs_utest_manual_protocol3" - "srs_utest_manual_app" "srs_utest_manual_mock" "srs_utest_workflow_rtc_playstream" "srs_utest_workflow_rtc_publishstream" - "srs_utest_workflow_rtc_conn" "srs_utest_workflow_rtmp_conn" "srs_utest_workflow_srt_conn" "srs_utest_workflow_http_conn") + "srs_utest_manual_app" "srs_utest_manual_mock") + MODULE_FILES+=("srs_utest_workflow_rtc_playstream" "srs_utest_workflow_rtc_publishstream" + "srs_utest_workflow_rtc_conn" "srs_utest_workflow_rtmp_conn" "srs_utest_workflow_srt_conn" "srs_utest_workflow_http_conn" + "srs_utest_workflow_forward" "srs_utest_workflow_rtc2rtmp" "srs_utest_workflow_rtmp2rtc") MODULE_FILES+=("srs_utest_ai01" "srs_utest_ai02" "srs_utest_ai03" "srs_utest_ai04" "srs_utest_ai05" "srs_utest_ai06" "srs_utest_ai07" "srs_utest_ai08" "srs_utest_ai09" "srs_utest_ai10" "srs_utest_ai11" "srs_utest_ai12" "srs_utest_ai13" "srs_utest_ai14" "srs_utest_ai15" "srs_utest_ai16" "srs_utest_ai17" - "srs_utest_ai18" "srs_utest_ai19" "srs_utest_ai20" "srs_utest_workflow_forward") + "srs_utest_ai18" "srs_utest_ai19" "srs_utest_ai20" "srs_utest_ai24") if [[ $SRS_GB28181 == YES ]]; then MODULE_FILES+=("srs_utest_manual_gb28181" "srs_utest_ai23") fi diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 7a353826a..faf0155a3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2340,7 +2340,7 @@ srs_error_t SrsConfig::check_normal_config() } else if (n == "rtc") { for (int j = 0; j < (int)conf->directives_.size(); j++) { string m = conf->at(j)->name_; - if (m != "enabled" && m != "nack" && m != "twcc" && m != "nack_no_copy" && m != "bframe" && m != "aac" && m != "stun_timeout" && m != "stun_strict_check" && m != "dtls_role" && m != "dtls_version" && m != "drop_for_pt" && m != "rtc_to_rtmp" && m != "pli_for_rtmp" && m != "rtmp_to_rtc" && m != "keep_bframe" && m != "opus_bitrate" && m != "aac_bitrate" && m != "keep_avc_nalu_sei") { + if (m != "enabled" && m != "nack" && m != "twcc" && m != "nack_no_copy" && m != "bframe" && m != "aac" && m != "stun_timeout" && m != "stun_strict_check" && m != "dtls_role" && m != "dtls_version" && m != "drop_for_pt" && m != "rtc_to_rtmp" && m != "pli_for_rtmp" && m != "rtmp_to_rtc" && m != "keep_bframe" && m != "opus_bitrate" && m != "aac_bitrate" && m != "keep_avc_nalu_sei" && m != "init_rate_from_sdp") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.rtc.%s of %s", m.c_str(), vhost->arg0().c_str()); } } @@ -4065,6 +4065,25 @@ int SrsConfig::get_rtc_aac_bitrate(string vhost) return v; } +bool SrsConfig::get_rtc_init_rate_from_sdp(string vhost) +{ + SRS_OVERWRITE_BY_ENV_BOOL("srs.vhost.rtc.init_rate_from_sdp"); // SRS_VHOST_RTC_INIT_RATE_FROM_SDP + + static bool DEFAULT = false; + + SrsConfDirective *conf = get_rtc(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("init_rate_from_sdp"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PREFER_FALSE(conf->arg0()); +} + SrsConfDirective *SrsConfig::get_vhost(string vhost, bool try_default_vhost) { srs_assert(root_); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index d72dd1b69..b294692ef 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -481,6 +481,7 @@ public: virtual SrsConfDirective *get_vhost_on_unpublish(std::string vhost) = 0; virtual int get_rtc_drop_for_pt(std::string vhost) = 0; virtual bool get_rtc_twcc_enabled(std::string vhost) = 0; + virtual bool get_rtc_init_rate_from_sdp(std::string vhost) = 0; virtual bool get_srt_enabled() = 0; virtual bool get_srt_enabled(std::string vhost) = 0; virtual std::string get_srt_default_streamid() = 0; @@ -909,6 +910,7 @@ public: bool get_rtc_twcc_enabled(std::string vhost); int get_rtc_opus_bitrate(std::string vhost); int get_rtc_aac_bitrate(std::string vhost); + bool get_rtc_init_rate_from_sdp(std::string vhost); // vhost specified section public: diff --git a/trunk/src/app/srs_app_dash.cpp b/trunk/src/app/srs_app_dash.cpp index 0e04e314d..349dbef8c 100644 --- a/trunk/src/app/srs_app_dash.cpp +++ b/trunk/src/app/srs_app_dash.cpp @@ -878,7 +878,7 @@ SrsDash::~SrsDash() void SrsDash::dispose() { - // We disabled the reload, so DASH will not be enabled by reloading. + // We disabled the reload, so DASH will not be enabled by reloading. // As a result, if DASH is disabled, we don't need to dispose. if (!enabled_) { return; diff --git a/trunk/src/app/srs_app_factory.cpp b/trunk/src/app/srs_app_factory.cpp index 7322d521d..0c6325def 100644 --- a/trunk/src/app/srs_app_factory.cpp +++ b/trunk/src/app/srs_app_factory.cpp @@ -23,7 +23,9 @@ #ifdef SRS_RTSP #include #endif +#include #include +#include #include #include #include @@ -212,6 +214,23 @@ ISrsHttpResponseWriter *SrsAppFactory::create_http_response_writer(ISrsProtocolR return new SrsHttpResponseWriter(io); } +#ifdef SRS_FFMPEG_FIT +SrsRtcFrameBuilder *SrsAppFactory::create_rtc_frame_builder(ISrsFrameTarget *target) +{ + return new SrsRtcFrameBuilder(this, target); +} + +ISrsRtcFrameBuilderAudioPacketCache *SrsAppFactory::create_rtc_frame_builder_audio_packet_cache() +{ + return new SrsRtcFrameBuilderAudioPacketCache(); +} + +ISrsAudioTranscoder *SrsAppFactory::create_audio_transcoder() +{ + return new SrsAudioTranscoder(); +} +#endif + ISrsCoroutine *SrsAppFactory::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid) { return kernel_factory_->create_coroutine(name, handler, cid); diff --git a/trunk/src/app/srs_app_factory.hpp b/trunk/src/app/srs_app_factory.hpp index 852a7c4bb..208bc6fdd 100644 --- a/trunk/src/app/srs_app_factory.hpp +++ b/trunk/src/app/srs_app_factory.hpp @@ -50,6 +50,10 @@ class ISrsRtcPlayStream; class ISrsRtcPacketSender; class ISrsHttpResponseWriter; class ISrsProtocolReadWriter; +class SrsRtcFrameBuilder; +class ISrsFrameTarget; +class ISrsRtcFrameBuilderAudioPacketCache; +class ISrsAudioTranscoder; // The factory to create app objects. class ISrsAppFactory : public ISrsKernelFactory @@ -93,6 +97,11 @@ public: virtual ISrsRtcPublishStream *create_rtc_publish_stream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expire, ISrsRtcPacketReceiver *receiver, const SrsContextId &cid) = 0; virtual ISrsRtcPlayStream *create_rtc_play_stream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expire, ISrsRtcPacketSender *sender, const SrsContextId &cid) = 0; virtual ISrsHttpResponseWriter *create_http_response_writer(ISrsProtocolReadWriter *io) = 0; +#ifdef SRS_FFMPEG_FIT + virtual SrsRtcFrameBuilder *create_rtc_frame_builder(ISrsFrameTarget *target) = 0; + virtual ISrsRtcFrameBuilderAudioPacketCache *create_rtc_frame_builder_audio_packet_cache() = 0; + virtual ISrsAudioTranscoder *create_audio_transcoder() = 0; +#endif }; // The factory to create app objects. @@ -141,6 +150,11 @@ public: virtual ISrsRtcPublishStream *create_rtc_publish_stream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expire, ISrsRtcPacketReceiver *receiver, const SrsContextId &cid); virtual ISrsRtcPlayStream *create_rtc_play_stream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expire, ISrsRtcPacketSender *sender, const SrsContextId &cid); virtual ISrsHttpResponseWriter *create_http_response_writer(ISrsProtocolReadWriter *io); +#ifdef SRS_FFMPEG_FIT + virtual SrsRtcFrameBuilder *create_rtc_frame_builder(ISrsFrameTarget *target); + virtual ISrsRtcFrameBuilderAudioPacketCache *create_rtc_frame_builder_audio_packet_cache(); + virtual ISrsAudioTranscoder *create_audio_transcoder(); +#endif public: virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid); diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 0c8fef9cc..5394256d8 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -2549,7 +2549,7 @@ srs_error_t SrsHls::do_reload(int *reloading, int *reloaded, int *refreshed) void SrsHls::dispose() { - // We disabled the reload, so HLS will not be enabled by reloading. + // We disabled the reload, so HLS will not be enabled by reloading. // As a result, if HLS is disabled, we don't need to dispose. if (!enabled_) { return; diff --git a/trunk/src/app/srs_app_rtc_codec.cpp b/trunk/src/app/srs_app_rtc_codec.cpp index cd99181ff..c4409b03f 100644 --- a/trunk/src/app/srs_app_rtc_codec.cpp +++ b/trunk/src/app/srs_app_rtc_codec.cpp @@ -42,49 +42,57 @@ static const AVCodec *srs_find_encoder_by_id(SrsAudioCodecId id) return NULL; } -class SrsFFmpegLogHelper +SrsFFmpegLogHelper::SrsFFmpegLogHelper() { -public: - SrsFFmpegLogHelper() - { - av_log_set_callback(ffmpeg_log_callback); - av_log_set_level(AV_LOG_TRACE); + av_log_set_callback(ffmpeg_log_callback); + av_log_set_level(AV_LOG_TRACE); +} +SrsFFmpegLogHelper::~SrsFFmpegLogHelper() +{ + av_log_set_callback(NULL); +} + +bool SrsFFmpegLogHelper::disabled_ = false; + +void SrsFFmpegLogHelper::disable_ffmpeg_log() +{ + disabled_ = true; +} + +void SrsFFmpegLogHelper::ffmpeg_log_callback(void *, int level, const char *fmt, va_list vl) +{ + if (disabled_) { + return; } - static void ffmpeg_log_callback(void *, int level, const char *fmt, va_list vl) - { - static char buf[4096] = {0}; - int nbytes = vsnprintf(buf, sizeof(buf), fmt, vl); - if (nbytes > 0 && nbytes < (int)sizeof(buf)) { - // Srs log is always start with new line, replcae '\n' to '\0', make log easy to read. - if (buf[nbytes - 1] == '\n') { - buf[nbytes - 1] = '\0'; - } - switch (level) { - case AV_LOG_PANIC: - case AV_LOG_FATAL: - case AV_LOG_ERROR: - srs_error("%s", buf); - break; - case AV_LOG_WARNING: - srs_warn("%s", buf); - break; - case AV_LOG_INFO: - srs_trace("%s", buf); - break; - case AV_LOG_VERBOSE: - case AV_LOG_DEBUG: - case AV_LOG_TRACE: - default: - srs_verbose("%s", buf); - break; - } + static char buf[4096] = {0}; + int nbytes = vsnprintf(buf, sizeof(buf), fmt, vl); + if (nbytes > 0 && nbytes < (int)sizeof(buf)) { + // Srs log is always start with new line, replcae '\n' to '\0', make log easy to read. + if (buf[nbytes - 1] == '\n') { + buf[nbytes - 1] = '\0'; + } + switch (level) { + case AV_LOG_PANIC: + case AV_LOG_FATAL: + case AV_LOG_ERROR: + srs_error("%s", buf); + break; + case AV_LOG_WARNING: + srs_warn("%s", buf); + break; + case AV_LOG_INFO: + srs_trace("%s", buf); + break; + case AV_LOG_VERBOSE: + case AV_LOG_DEBUG: + case AV_LOG_TRACE: + default: + srs_verbose("%s", buf); + break; } } -}; - -// Register FFmpeg log callback funciton. -SrsFFmpegLogHelper _srs_ffmpeg_log_helper; +} ISrsAudioTranscoder::ISrsAudioTranscoder() { diff --git a/trunk/src/app/srs_app_rtc_codec.hpp b/trunk/src/app/srs_app_rtc_codec.hpp index a754dca49..6fa571385 100644 --- a/trunk/src/app/srs_app_rtc_codec.hpp +++ b/trunk/src/app/srs_app_rtc_codec.hpp @@ -31,6 +31,22 @@ extern "C" { } #endif +// Register FFmpeg log callback funciton. +class SrsFFmpegLogHelper +{ +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + static bool disabled_; + +public: + SrsFFmpegLogHelper(); + virtual ~SrsFFmpegLogHelper(); + +public: + static void disable_ffmpeg_log(); + static void ffmpeg_log_callback(void *, int level, const char *fmt, va_list vl); +}; + // The interface for audio transcoder. class ISrsAudioTranscoder { diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 216b757d5..04d76df4e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1223,6 +1223,7 @@ SrsRtcPublishStream::SrsRtcPublishStream(ISrsExecRtcAsyncTask *exec, ISrsExpire live_sources_ = _srs_sources; srt_sources_ = _srs_srt_sources; circuit_breaker_ = _srs_circuit_breaker; + app_factory_ = _srs_app_factory; } SrsRtcPublishStream::~SrsRtcPublishStream() @@ -1268,6 +1269,7 @@ SrsRtcPublishStream::~SrsRtcPublishStream() live_sources_ = NULL; srt_sources_ = NULL; circuit_breaker_ = NULL; + app_factory_ = NULL; } srs_error_t SrsRtcPublishStream::initialize(ISrsRequest *r, SrsRtcSourceDescription *stream_desc) @@ -1289,13 +1291,16 @@ srs_error_t SrsRtcPublishStream::initialize(ISrsRequest *r, SrsRtcSourceDescript return srs_error_wrap(err, "rtc: stat client"); } + // Use SDP sample rate to initialize track rate for A/V sync. + bool init_rate_from_sdp = config_->get_rtc_init_rate_from_sdp(req_->vhost_); + if (stream_desc->audio_track_desc_) { - audio_tracks_.push_back(new SrsRtcAudioRecvTrack(receiver_, stream_desc->audio_track_desc_)); + audio_tracks_.push_back(new SrsRtcAudioRecvTrack(receiver_, stream_desc->audio_track_desc_, init_rate_from_sdp)); } for (int i = 0; i < (int)stream_desc->video_track_descs_.size(); ++i) { SrsRtcTrackDescription *desc = stream_desc->video_track_descs_.at(i); - video_tracks_.push_back(new SrsRtcVideoRecvTrack(receiver_, desc)); + video_tracks_.push_back(new SrsRtcVideoRecvTrack(receiver_, desc, init_rate_from_sdp)); } int twcc_id = -1; @@ -1367,7 +1372,7 @@ srs_error_t SrsRtcPublishStream::initialize(ISrsRequest *r, SrsRtcSourceDescript } // Create the bridge for RTC. - SrsRtcBridge *bridge = new SrsRtcBridge(); + SrsRtcBridge *bridge = new SrsRtcBridge(app_factory_); // Bridge to RTMP. // TODO: Support bridge to RTSP. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 288481084..ccaa41c9d 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -515,13 +515,6 @@ public: // A RTC publish stream, client push and publish stream to SRS. class SrsRtcPublishStream : public ISrsRtcPublishStream { -// clang-format off -SRS_DECLARE_PRIVATE: // clang-format on - ISrsExecRtcAsyncTask *exec_; - ISrsExpire *expire_; - ISrsRtcPacketReceiver *receiver_; - ISrsCircuitBreaker *circuit_breaker_; - // clang-format off SRS_DECLARE_PRIVATE: // clang-format on ISrsStatistic *stat_; @@ -529,6 +522,14 @@ SRS_DECLARE_PRIVATE: // clang-format on ISrsRtcSourceManager *rtc_sources_; ISrsLiveSourceManager *live_sources_; ISrsSrtSourceManager *srt_sources_; + ISrsAppFactory *app_factory_; + +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsExecRtcAsyncTask *exec_; + ISrsExpire *expire_; + ISrsRtcPacketReceiver *receiver_; + ISrsCircuitBreaker *circuit_breaker_; // clang-format off SRS_DECLARE_PRIVATE: // clang-format on diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 6ba964878..71fe59dec 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -32,11 +32,10 @@ #include #include #include - #ifdef SRS_FFMPEG_FIT #include #endif - +#include #include #include #include @@ -401,6 +400,8 @@ SrsRtcSource::SrsRtcSource() pli_for_rtmp_ = pli_elapsed_ = 0; stream_die_at_ = 0; + + app_factory_ = _srs_app_factory; } SrsRtcSource::~SrsRtcSource() @@ -417,6 +418,8 @@ SrsRtcSource::~SrsRtcSource() if (cid.empty()) cid = _pre_source_id; srs_trace("free rtc source id=[%s]", cid.c_str()); + + app_factory_ = NULL; } // CRITICAL: This method is called AFTER the source has been added to the source pool @@ -879,14 +882,14 @@ srs_error_t SrsRtcSource::on_timer(srs_utime_t interval) #ifdef SRS_FFMPEG_FIT -SrsRtcRtpBuilder::SrsRtcRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr source) +SrsRtcRtpBuilder::SrsRtcRtpBuilder(ISrsAppFactory *factory, ISrsRtpTarget *target, SrsSharedPtr source) { rtp_target_ = target; source_ = source; req_ = NULL; format_ = new SrsRtmpFormat(); - codec_ = new SrsAudioTranscoder(); + codec_ = factory->create_audio_transcoder(); latest_codec_ = SrsAudioCodecIdForbidden; keep_bframe_ = false; keep_avc_nalu_sei_ = true; @@ -902,6 +905,8 @@ SrsRtcRtpBuilder::SrsRtcRtpBuilder(ISrsRtpTarget *target, SrsSharedPtrcreate_audio_transcoder(); // Initialize the codec according to the codec in stream. int bitrate = _srs_config->get_rtc_opus_bitrate(req_->vhost_); // The output bitrate in bps. @@ -1377,6 +1384,14 @@ srs_error_t SrsRtcRtpBuilder::consume_packets(vector &pkts) return err; } +ISrsRtcFrameBuilderVideoPacketCache::ISrsRtcFrameBuilderVideoPacketCache() +{ +} + +ISrsRtcFrameBuilderVideoPacketCache::~ISrsRtcFrameBuilderVideoPacketCache() +{ +} + SrsRtcFrameBuilderVideoPacketCache::SrsRtcFrameBuilderVideoPacketCache() { memset(cache_pkts_, 0, sizeof(cache_pkts_)); @@ -1496,7 +1511,7 @@ int32_t SrsRtcFrameBuilderVideoPacketCache::find_next_lost_sn(uint16_t current_s } } - srs_error("cache overflow. the packet count of video frame is more than %u", cache_size_); + srs_warn("cache overflow. the packet count of video frame is more than %u", cache_size_); return -2; } @@ -1536,7 +1551,15 @@ bool SrsRtcFrameBuilderVideoPacketCache::check_frame_complete(const uint16_t sta return nn_fu_start == nn_fu_end; } -SrsRtcFrameBuilderVideoFrameDetector::SrsRtcFrameBuilderVideoFrameDetector(SrsRtcFrameBuilderVideoPacketCache *cache) +ISrsRtcFrameBuilderVideoFrameDetector::ISrsRtcFrameBuilderVideoFrameDetector() +{ +} + +ISrsRtcFrameBuilderVideoFrameDetector::~ISrsRtcFrameBuilderVideoFrameDetector() +{ +} + +SrsRtcFrameBuilderVideoFrameDetector::SrsRtcFrameBuilderVideoFrameDetector(ISrsRtcFrameBuilderVideoPacketCache *cache) { video_cache_ = cache; header_sn_ = 0; @@ -1640,6 +1663,14 @@ bool SrsRtcFrameBuilderVideoFrameDetector::is_lost_sn(uint16_t received) return lost_sn_ == received; } +ISrsRtcFrameBuilderAudioPacketCache::ISrsRtcFrameBuilderAudioPacketCache() +{ +} + +ISrsRtcFrameBuilderAudioPacketCache::~ISrsRtcFrameBuilderAudioPacketCache() +{ +} + SrsRtcFrameBuilderAudioPacketCache::SrsRtcFrameBuilderAudioPacketCache() { last_audio_seq_num_ = 0; @@ -1752,17 +1783,19 @@ void SrsRtcFrameBuilderAudioPacketCache::clear_all() audio_buffer_.clear(); } -SrsRtcFrameBuilder::SrsRtcFrameBuilder(ISrsFrameTarget *target) +SrsRtcFrameBuilder::SrsRtcFrameBuilder(ISrsAppFactory *factory, ISrsFrameTarget *target) { frame_target_ = target; is_first_audio_ = true; audio_transcoder_ = NULL; video_codec_ = SrsVideoCodecIdAVC; - audio_cache_ = new SrsRtcFrameBuilderAudioPacketCache(); + audio_cache_ = factory->create_rtc_frame_builder_audio_packet_cache(); video_cache_ = new SrsRtcFrameBuilderVideoPacketCache(); frame_detector_ = new SrsRtcFrameBuilderVideoFrameDetector(video_cache_); sync_state_ = -1; obs_whip_vps_ = obs_whip_sps_ = obs_whip_pps_ = NULL; + + app_factory_ = factory; } SrsRtcFrameBuilder::~SrsRtcFrameBuilder() @@ -1774,6 +1807,8 @@ SrsRtcFrameBuilder::~SrsRtcFrameBuilder() srs_freep(obs_whip_vps_); srs_freep(obs_whip_sps_); srs_freep(obs_whip_pps_); + + app_factory_ = NULL; } srs_error_t SrsRtcFrameBuilder::initialize(ISrsRequest *r, SrsAudioCodecId audio_codec, SrsVideoCodecId video_codec) @@ -1781,7 +1816,7 @@ srs_error_t SrsRtcFrameBuilder::initialize(ISrsRequest *r, SrsAudioCodecId audio srs_error_t err = srs_success; srs_freep(audio_transcoder_); - audio_transcoder_ = new SrsAudioTranscoder(); + audio_transcoder_ = app_factory_->create_audio_transcoder(); SrsAudioCodecId to = SrsAudioCodecIdAAC; // The output audio codec. int channels = 2; // The output audio channels. @@ -1820,8 +1855,9 @@ srs_error_t SrsRtcFrameBuilder::on_rtp(SrsRtpPacket *pkt) return err; } - // Have no received any sender report, can't calculate avsync_time, - // discard it to avoid timestamp problem in live source + // Check if avsync_time is valid (> 0). + // NOTE: This check should NEVER fail unless SDP has no sample rate, in which case packets are discarded + // to avoid timestamp problems in live source. const SrsRtpHeader &h = pkt->header_; if (pkt->get_avsync_time() <= 0) { if (sync_state_ < 0) { @@ -1879,6 +1915,9 @@ srs_error_t SrsRtcFrameBuilder::transcode_audio(SrsRtpPacket *pkt) int header_len = 0; uint8_t *header = NULL; audio_transcoder_->aac_codec_header(&header, &header_len); + if (header_len <= 0) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "no aac header"); + } SrsRtmpCommonMessage out_rtmp; packet_aac(&out_rtmp, (char *)header, header_len, ts, is_first_audio_); @@ -3089,7 +3128,7 @@ ISrsRtcPacketReceiver::~ISrsRtcPacketReceiver() { } -SrsRtcRecvTrack::SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc, bool is_audio) +SrsRtcRecvTrack::SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc, bool is_audio, bool init_rate_from_sdp) { receiver_ = receiver; track_desc_ = track_desc->copy(); @@ -3105,7 +3144,17 @@ SrsRtcRecvTrack::SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDes last_sender_report_rtp_time_ = 0; last_sender_report_rtp_time1_ = 0; + + // Initialize rate from SDP sample rate + // rate_ is RTP units per millisecond (e.g., 90 for video 90kHz, 48 for audio 48kHz) + // This allows immediate A/V sync before receiving 2 RTCP SR packets + // Will be updated to precise rate after receiving 2nd SR rate_ = 0.0; + if (init_rate_from_sdp && track_desc_->media_) { + rate_ = static_cast(track_desc_->media_->sample_) / 1000.0; + srs_trace("RTC: Init %s track, ssrc=%u, rate from SDP=%.0f (RTP units per ms, will be updated after 2nd SR)", + track_desc_->type_.c_str(), track_desc_->ssrc_, rate_); + } last_sender_report_sys_time_ = 0; } @@ -3163,8 +3212,14 @@ void SrsRtcRecvTrack::update_send_report_time(const SrsNtp &ntp, uint32_t rtp_ti double rtp_time_elpased = static_cast(last_sender_report_rtp_time_) - static_cast(last_sender_report_rtp_time1_); double rate = round(rtp_time_elpased / sys_time_elapsed); - // TODO: FIXME: use the sample rate from sdp. if (rate > 0) { + if (rate_ != rate) { + srs_warn("RTC: SR update %s, ssrc=%u, ntp_ms=%u->%u (delta=%.0fms), rtp_time=%u->%u (delta=%.0f), rate %.0f->%.0f", + track_desc_->type_.c_str(), track_desc_->ssrc_, + last_sender_report_ntp1_.system_ms_, last_sender_report_ntp_.system_ms_, sys_time_elapsed, + (uint32_t)last_sender_report_rtp_time1_, (uint32_t)last_sender_report_rtp_time_, rtp_time_elpased, + rate_, rate); + } rate_ = rate; } } @@ -3282,8 +3337,8 @@ srs_error_t SrsRtcRecvTrack::do_check_send_nacks(uint32_t &timeout_nacks) return err; } -SrsRtcAudioRecvTrack::SrsRtcAudioRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc) - : SrsRtcRecvTrack(receiver, track_desc, true) +SrsRtcAudioRecvTrack::SrsRtcAudioRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc, bool init_rate_from_sdp) + : SrsRtcRecvTrack(receiver, track_desc, true, init_rate_from_sdp) { } @@ -3330,8 +3385,8 @@ srs_error_t SrsRtcAudioRecvTrack::check_send_nacks() return err; } -SrsRtcVideoRecvTrack::SrsRtcVideoRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc) - : SrsRtcRecvTrack(receiver, track_desc, false) +SrsRtcVideoRecvTrack::SrsRtcVideoRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc, bool init_rate_from_sdp) + : SrsRtcRecvTrack(receiver, track_desc, false, init_rate_from_sdp) { } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 3021562ee..dba5e8b03 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -44,6 +44,7 @@ class SrsRtpVideoBuilder; class ISrsRtcConsumer; class ISrsCircuitBreaker; class ISrsRtcPublishStream; +class ISrsAppFactory; // Firefox defaults as 109, Chrome is 111. const int kAudioPayloadType = 111; @@ -227,11 +228,12 @@ class SrsRtcSource : public ISrsRtpTarget, public ISrsFastTimerHandler, public I { // clang-format off SRS_DECLARE_PRIVATE: // clang-format on - // The RTP bridge, convert RTP packets to other protocols. - ISrsRtcBridge *rtc_bridge_; + ISrsAppFactory *app_factory_; // clang-format off SRS_DECLARE_PRIVATE: // clang-format on + // The RTP bridge, convert RTP packets to other protocols. + ISrsRtcBridge *rtc_bridge_; // Circuit breaker for protecting server resources. ISrsCircuitBreaker *circuit_breaker_; // For publish, it's the publish client id. @@ -347,6 +349,10 @@ SRS_DECLARE_PRIVATE: // clang-format on // Convert AV frame to RTC RTP packets. class SrsRtcRtpBuilder { +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; + // clang-format off SRS_DECLARE_PRIVATE: // clang-format on ISrsRequest *req_; @@ -380,7 +386,7 @@ SRS_DECLARE_PRIVATE: // clang-format on bool video_initialized_; public: - SrsRtcRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr source); + SrsRtcRtpBuilder(ISrsAppFactory *factory, ISrsRtpTarget *target, SrsSharedPtr source); virtual ~SrsRtcRtpBuilder(); // clang-format off @@ -419,9 +425,25 @@ SRS_DECLARE_PRIVATE: // clang-format on srs_error_t consume_packets(std::vector &pkts); }; +// Video packet cache interface +class ISrsRtcFrameBuilderVideoPacketCache +{ +public: + ISrsRtcFrameBuilderVideoPacketCache(); + virtual ~ISrsRtcFrameBuilderVideoPacketCache(); + +public: + virtual SrsRtpPacket *get_packet(uint16_t sequence_number) = 0; + virtual void store_packet(SrsRtpPacket *pkt) = 0; + virtual void clear_all() = 0; + virtual SrsRtpPacket *take_packet(uint16_t sequence_number) = 0; + virtual int32_t find_next_lost_sn(uint16_t current_sn, uint16_t header_sn, uint16_t &end_sn) = 0; + virtual bool check_frame_complete(const uint16_t start, const uint16_t end) = 0; +}; + // Video packet cache for RTP packet management // TODO: Maybe should use SrsRtpRingBuffer? -class SrsRtcFrameBuilderVideoPacketCache +class SrsRtcFrameBuilderVideoPacketCache : public ISrsRtcFrameBuilderVideoPacketCache { // clang-format off SRS_DECLARE_PRIVATE: // clang-format on @@ -462,18 +484,33 @@ SRS_DECLARE_PRIVATE: // clang-format on } }; +// Video frame detector interface +class ISrsRtcFrameBuilderVideoFrameDetector +{ +public: + ISrsRtcFrameBuilderVideoFrameDetector(); + virtual ~ISrsRtcFrameBuilderVideoFrameDetector(); + +public: + virtual void on_keyframe_start(SrsRtpPacket *pkt) = 0; + virtual srs_error_t detect_frame(uint16_t received, uint16_t &frame_start, uint16_t &frame_end, bool &frame_ready) = 0; + virtual srs_error_t detect_next_frame(uint16_t next_head, uint16_t &next_start, uint16_t &next_end, bool &next_ready) = 0; + virtual void on_keyframe_detached() = 0; + virtual bool is_lost_sn(uint16_t received) = 0; +}; + // Video frame detector for managing frame boundaries and packet loss detection -class SrsRtcFrameBuilderVideoFrameDetector +class SrsRtcFrameBuilderVideoFrameDetector : public ISrsRtcFrameBuilderVideoFrameDetector { // clang-format off SRS_DECLARE_PRIVATE: // clang-format on - SrsRtcFrameBuilderVideoPacketCache *video_cache_; + ISrsRtcFrameBuilderVideoPacketCache *video_cache_; uint16_t header_sn_; uint16_t lost_sn_; int64_t rtp_key_frame_ts_; public: - SrsRtcFrameBuilderVideoFrameDetector(SrsRtcFrameBuilderVideoPacketCache *cache); + SrsRtcFrameBuilderVideoFrameDetector(ISrsRtcFrameBuilderVideoPacketCache *cache); virtual ~SrsRtcFrameBuilderVideoFrameDetector(); public: @@ -484,8 +521,20 @@ public: bool is_lost_sn(uint16_t received); }; +// Audio packet cache interface +class ISrsRtcFrameBuilderAudioPacketCache +{ +public: + ISrsRtcFrameBuilderAudioPacketCache(); + virtual ~ISrsRtcFrameBuilderAudioPacketCache(); + +public: + virtual srs_error_t process_packet(SrsRtpPacket *src, std::vector &ready_packets) = 0; + virtual void clear_all() = 0; +}; + // Audio packet cache for RTP packet jitter buffer management -class SrsRtcFrameBuilderAudioPacketCache +class SrsRtcFrameBuilderAudioPacketCache : public ISrsRtcFrameBuilderAudioPacketCache { // clang-format off SRS_DECLARE_PRIVATE: // clang-format on @@ -518,6 +567,10 @@ public: // Collect and build WebRTC RTP packets to AV frames. class SrsRtcFrameBuilder { +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; + // clang-format off SRS_DECLARE_PRIVATE: // clang-format on ISrsFrameTarget *frame_target_; @@ -530,9 +583,9 @@ SRS_DECLARE_PRIVATE: // clang-format on // clang-format off SRS_DECLARE_PRIVATE: // clang-format on - SrsRtcFrameBuilderAudioPacketCache *audio_cache_; - SrsRtcFrameBuilderVideoPacketCache *video_cache_; - SrsRtcFrameBuilderVideoFrameDetector *frame_detector_; + ISrsRtcFrameBuilderAudioPacketCache *audio_cache_; + ISrsRtcFrameBuilderVideoPacketCache *video_cache_; + ISrsRtcFrameBuilderVideoFrameDetector *frame_detector_; // clang-format off SRS_DECLARE_PRIVATE: // clang-format on @@ -547,7 +600,7 @@ SRS_DECLARE_PRIVATE: // clang-format on SrsRtpPacket *obs_whip_pps_; public: - SrsRtcFrameBuilder(ISrsFrameTarget *target); + SrsRtcFrameBuilder(ISrsAppFactory *factory, ISrsFrameTarget *target); virtual ~SrsRtcFrameBuilder(); public: @@ -830,7 +883,7 @@ SRS_DECLARE_PROTECTED: // clang-format on uint64_t last_sender_report_sys_time_; public: - SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *stream_descs, bool is_audio); + SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *stream_descs, bool is_audio, bool init_rate_from_sdp); virtual ~SrsRtcRecvTrack(); public: @@ -864,7 +917,7 @@ SRS_DECLARE_PROTECTED: // clang-format on class SrsRtcAudioRecvTrack : public SrsRtcRecvTrack, public ISrsRtpPacketDecodeHandler { public: - SrsRtcAudioRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc); + SrsRtcAudioRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc, bool init_rate_from_sdp); virtual ~SrsRtcAudioRecvTrack(); public: @@ -878,7 +931,7 @@ public: class SrsRtcVideoRecvTrack : public SrsRtcRecvTrack, public ISrsRtpPacketDecodeHandler { public: - SrsRtcVideoRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *stream_descs); + SrsRtcVideoRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *stream_descs, bool init_rate_from_sdp); virtual ~SrsRtcVideoRecvTrack(); public: diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index a116b3f69..3370fa55d 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -16,6 +16,7 @@ using namespace std; #include #include +#include #include #include #include @@ -229,6 +230,7 @@ SrsRtmpConn::SrsRtmpConn(ISrsRtmpTransport *transport, string cip, int cport) publish_1stpkt_timeout_ = 0; publish_normal_timeout_ = 0; + app_factory_ = _srs_app_factory; config_ = _srs_config; manager_ = _srs_conn_manager; stream_publish_tokens_ = _srs_stream_publish_tokens; @@ -269,6 +271,7 @@ SrsRtmpConn::~SrsRtmpConn() srs_freep(refer_); srs_freep(security_); + app_factory_ = NULL; config_ = NULL; manager_ = NULL; stream_publish_tokens_ = NULL; @@ -1064,7 +1067,7 @@ srs_error_t SrsRtmpConn::acquire_publish(SrsSharedPtr source) // Bridge to RTC streaming. // TODO: FIXME: Need to convert RTMP to SRT. - SrsRtmpBridge *bridge = new SrsRtmpBridge(); + SrsRtmpBridge *bridge = new SrsRtmpBridge(app_factory_); #if defined(SRS_FFMPEG_FIT) bool rtmp_to_rtc = config_->get_rtc_from_rtmp(req->vhost_); diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp index cb8f46c91..133e6df88 100644 --- a/trunk/src/app/srs_app_rtmp_conn.hpp +++ b/trunk/src/app/srs_app_rtmp_conn.hpp @@ -47,6 +47,7 @@ class ISrsStreamPublishTokenManager; class ISrsLiveSourceManager; class ISrsStatistic; class ISrsHttpHooks; +class ISrsAppFactory; class ISrsRtcSourceManager; class ISrsSrtSourceManager; class ISrsRtspSourceManager; @@ -174,6 +175,7 @@ class SrsRtmpConn : public ISrsConnection, // It's a resource. // clang-format off SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; ISrsResourceManager *manager_; ISrsAppConfig *config_; ISrsStreamPublishTokenManager *stream_publish_tokens_; diff --git a/trunk/src/app/srs_app_srt_conn.cpp b/trunk/src/app/srs_app_srt_conn.cpp index 1e84714ba..619726a16 100644 --- a/trunk/src/app/srs_app_srt_conn.cpp +++ b/trunk/src/app/srs_app_srt_conn.cpp @@ -9,6 +9,7 @@ using namespace std; #include +#include #include #include #include @@ -501,7 +502,7 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish() } // Bridge to RTMP and RTC streaming. - SrsSrtBridge *bridge = new SrsSrtBridge(); + SrsSrtBridge *bridge = new SrsSrtBridge(_srs_app_factory); bool srt_to_rtmp = config_->get_srt_to_rtmp(req_->vhost_); if (srt_to_rtmp && edge) { @@ -620,14 +621,15 @@ srs_error_t SrsMpegtsSrtConn::do_playing() int nb_packets = 0; while (true) { - if ((err = trd_->pull()) != srs_success) { - return srs_error_wrap(err, "srt play thread"); - } - + // Check recv thread error first, so we can detect the client disconnecting event. if ((err = srt_recv_trd.get_recv_err()) != srs_success) { return srs_error_wrap(err, "srt play recv thread"); } + if ((err = trd_->pull()) != srs_success) { + return srs_error_wrap(err, "srt play thread"); + } + // Wait for amount of packets. SrsSrtPacket *pkt_raw = NULL; consumer->dump_packet(&pkt_raw); diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp index eefcd50f1..6e8921d65 100644 --- a/trunk/src/app/srs_app_stream_bridge.cpp +++ b/trunk/src/app/srs_app_stream_bridge.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,7 @@ ISrsRtmpBridge::~ISrsRtmpBridge() { } -SrsRtmpBridge::SrsRtmpBridge() +SrsRtmpBridge::SrsRtmpBridge(ISrsAppFactory *factory) { #ifdef SRS_FFMPEG_FIT rtp_builder_ = NULL; @@ -63,6 +64,8 @@ SrsRtmpBridge::SrsRtmpBridge() rtsp_target_ = NULL; #endif rtc_target_ = NULL; + + app_factory_ = factory; } SrsRtmpBridge::~SrsRtmpBridge() @@ -75,6 +78,8 @@ SrsRtmpBridge::~SrsRtmpBridge() rtsp_target_ = NULL; #endif rtc_target_ = NULL; + + app_factory_ = NULL; } bool SrsRtmpBridge::empty() @@ -111,7 +116,7 @@ srs_error_t SrsRtmpBridge::initialize(ISrsRequest *r) #ifdef SRS_FFMPEG_FIT if (rtc_target_.get()) { srs_freep(rtp_builder_); - rtp_builder_ = new SrsRtcRtpBuilder(rtc_target_.get(), rtc_target_); + rtp_builder_ = new SrsRtcRtpBuilder(app_factory_, rtc_target_.get(), rtc_target_); if ((err = rtp_builder_->initialize(r)) != srs_success) { return srs_error_wrap(err, "rtp builder initialize"); } @@ -211,7 +216,7 @@ ISrsSrtBridge::~ISrsSrtBridge() { } -SrsSrtBridge::SrsSrtBridge() +SrsSrtBridge::SrsSrtBridge(ISrsAppFactory *factory) { frame_builder_ = new SrsSrtFrameBuilder(this); rtmp_target_ = NULL; @@ -220,6 +225,8 @@ SrsSrtBridge::SrsSrtBridge() rtp_builder_ = NULL; #endif rtc_target_ = NULL; + + app_factory_ = factory; } SrsSrtBridge::~SrsSrtBridge() @@ -231,6 +238,8 @@ SrsSrtBridge::~SrsSrtBridge() #ifdef SRS_FFMPEG_FIT srs_freep(rtp_builder_); #endif + + app_factory_ = NULL; } bool SrsSrtBridge::empty() @@ -259,7 +268,7 @@ srs_error_t SrsSrtBridge::initialize(ISrsRequest *r) #ifdef SRS_FFMPEG_FIT if (rtc_target_.get()) { srs_freep(rtp_builder_); - rtp_builder_ = new SrsRtcRtpBuilder(rtc_target_.get(), rtc_target_); + rtp_builder_ = new SrsRtcRtpBuilder(app_factory_, rtc_target_.get(), rtc_target_); if ((err = rtp_builder_->initialize(r)) != srs_success) { return srs_error_wrap(err, "rtp builder initialize"); } @@ -356,13 +365,15 @@ ISrsRtcBridge::~ISrsRtcBridge() { } -SrsRtcBridge::SrsRtcBridge() +SrsRtcBridge::SrsRtcBridge(ISrsAppFactory *factory) { req_ = NULL; #ifdef SRS_FFMPEG_FIT frame_builder_ = NULL; #endif rtmp_target_ = NULL; + + app_factory_ = factory; } SrsRtcBridge::~SrsRtcBridge() @@ -372,6 +383,8 @@ SrsRtcBridge::~SrsRtcBridge() srs_freep(frame_builder_); #endif rtmp_target_ = NULL; + + app_factory_ = NULL; } void SrsRtcBridge::enable_rtc2rtmp(SrsSharedPtr rtmp_target) @@ -394,7 +407,7 @@ srs_error_t SrsRtcBridge::initialize(ISrsRequest *r) #ifdef SRS_FFMPEG_FIT srs_assert(rtmp_target_.get()); srs_freep(frame_builder_); - frame_builder_ = new SrsRtcFrameBuilder(rtmp_target_.get()); + frame_builder_ = app_factory_->create_rtc_frame_builder(rtmp_target_.get()); #endif return err; diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp index 7257e7c52..c6fddccad 100644 --- a/trunk/src/app/srs_app_stream_bridge.hpp +++ b/trunk/src/app/srs_app_stream_bridge.hpp @@ -28,6 +28,7 @@ class SrsRtcFrameBuilder; class ISrsStreamBridge; class SrsSrtFrameBuilder; class SrsSrtPacket; +class ISrsAppFactory; // A target to feed AV frame, such as a RTMP live source, or a RTMP bridge // that take frame and converts to RTC packets, or a SRT bridge that converts @@ -85,6 +86,10 @@ public: // Then, deliver the RTP packets to RTP target, which binds to a RTC/RTSP source. class SrsRtmpBridge : public ISrsRtmpBridge { +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; + // clang-format off SRS_DECLARE_PRIVATE: // clang-format on #ifdef SRS_FFMPEG_FIT @@ -100,7 +105,7 @@ SRS_DECLARE_PRIVATE: // clang-format on #endif public: - SrsRtmpBridge(); + SrsRtmpBridge(ISrsAppFactory *factory); virtual ~SrsRtmpBridge(); public: @@ -136,6 +141,10 @@ public: // Then, deliver the AV frames to frame target, which binds to a RTMP/RTC source. class SrsSrtBridge : public ISrsSrtBridge, public ISrsFrameTarget { +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; + // clang-format off SRS_DECLARE_PRIVATE: // clang-format on // Convert SRT TS packets to media frame packets. @@ -150,7 +159,7 @@ SRS_DECLARE_PRIVATE: // clang-format on SrsSharedPtr rtc_target_; public: - SrsSrtBridge(); + SrsSrtBridge(ISrsAppFactory *factory); virtual ~SrsSrtBridge(); public: @@ -186,6 +195,10 @@ public: // Then, deliver the RTMP frame packet to RTMP target, which binds to a live source. class SrsRtcBridge : public ISrsRtcBridge { +// clang-format off +SRS_DECLARE_PRIVATE: // clang-format on + ISrsAppFactory *app_factory_; + // clang-format off SRS_DECLARE_PRIVATE: // clang-format on ISrsRequest *req_; @@ -197,7 +210,7 @@ SRS_DECLARE_PRIVATE: // clang-format on SrsSharedPtr rtmp_target_; public: - SrsRtcBridge(); + SrsRtcBridge(ISrsAppFactory *factory); virtual ~SrsRtcBridge(); public: diff --git a/trunk/src/kernel/srs_kernel_packet.cpp b/trunk/src/kernel/srs_kernel_packet.cpp index 790306e15..dfc8481b0 100644 --- a/trunk/src/kernel/srs_kernel_packet.cpp +++ b/trunk/src/kernel/srs_kernel_packet.cpp @@ -142,6 +142,25 @@ srs_error_t SrsParsedPacket::add_sample(char *bytes, int size) return err; } +SrsParsedPacket *SrsParsedPacket::copy() +{ + SrsParsedPacket *p = new SrsParsedPacket(); + do_copy(p); + return p; +} + +void SrsParsedPacket::do_copy(SrsParsedPacket *p) +{ + p->codec_ = codec_; + p->nb_samples_ = nb_samples_; + for (int i = 0; i < nb_samples_; i++) { + p->samples_[i].size_ = samples_[i].size_; + p->samples_[i].bytes_ = samples_[i].bytes_; + } + p->dts_ = dts_; + p->cts_ = cts_; +} + SrsParsedAudioPacket::SrsParsedAudioPacket() { aac_packet_type_ = SrsAudioAacFrameTraitForbidden; @@ -156,6 +175,16 @@ SrsAudioCodecConfig *SrsParsedAudioPacket::acodec() return (SrsAudioCodecConfig *)codec_; } +SrsParsedAudioPacket *SrsParsedAudioPacket::copy() +{ + SrsParsedAudioPacket *p = new SrsParsedAudioPacket(); + + do_copy(p); + p->aac_packet_type_ = aac_packet_type_; + + return p; +} + SrsParsedVideoPacket::SrsParsedVideoPacket() { frame_type_ = SrsVideoAvcFrameTypeForbidden; @@ -213,6 +242,21 @@ srs_error_t SrsParsedVideoPacket::add_sample(char *bytes, int size) return err; } +SrsParsedVideoPacket *SrsParsedVideoPacket::copy() +{ + SrsParsedVideoPacket *p = new SrsParsedVideoPacket(); + + do_copy(p); + p->frame_type_ = frame_type_; + p->avc_packet_type_ = avc_packet_type_; + p->has_idr_ = has_idr_; + p->has_aud_ = has_aud_; + p->has_sps_pps_ = has_sps_pps_; + p->first_nalu_type_ = first_nalu_type_; + + return p; +} + SrsVideoCodecConfig *SrsParsedVideoPacket::vcodec() { return (SrsVideoCodecConfig *)codec_; diff --git a/trunk/src/kernel/srs_kernel_packet.hpp b/trunk/src/kernel/srs_kernel_packet.hpp index 3ac7609cb..23d4cf1f0 100644 --- a/trunk/src/kernel/srs_kernel_packet.hpp +++ b/trunk/src/kernel/srs_kernel_packet.hpp @@ -109,6 +109,12 @@ public: virtual srs_error_t initialize(SrsCodecConfig *c); // Add a sample to frame. virtual srs_error_t add_sample(char *bytes, int size); + +// clang-format off +SRS_DECLARE_PROTECTED: // clang-format on + // Copy the packet. + virtual SrsParsedPacket *copy(); + virtual void do_copy(SrsParsedPacket *p); }; // A parsed audio packet, besides a frame, contains the audio frame info, such as frame type. @@ -123,6 +129,10 @@ public: public: virtual SrsAudioCodecConfig *acodec(); + +// clang-format off +SRS_DECLARE_PROTECTED: // clang-format on + virtual SrsParsedAudioPacket *copy(); }; // A parsed video packet, besides a frame, contains the video frame info, such as frame type. @@ -151,6 +161,10 @@ public: // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data. virtual srs_error_t add_sample(char *bytes, int size); +// clang-format off +SRS_DECLARE_PROTECTED: // clang-format on + virtual SrsParsedVideoPacket *copy(); + public: virtual SrsVideoCodecConfig *vcodec(); diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index b94b1323c..a20439151 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include #include #include #include @@ -63,6 +64,11 @@ SrsConfig *_srs_config = NULL; ISrsAppFactory *_srs_app_factory = new SrsAppFactory(); ISrsKernelFactory *_srs_kernel_factory = _srs_app_factory; +#ifdef SRS_FFMPEG_FIT +// Register FFmpeg log callback funciton. +SrsFFmpegLogHelper _srs_ffmpeg_log_helper; +#endif + // @global version of srs, which can grep keyword "XCORE" extern const char *_srs_version; diff --git a/trunk/src/protocol/srs_protocol_http_stack.cpp b/trunk/src/protocol/srs_protocol_http_stack.cpp index 6afcb3398..ceedfc223 100644 --- a/trunk/src/protocol/srs_protocol_http_stack.cpp +++ b/trunk/src/protocol/srs_protocol_http_stack.cpp @@ -1165,7 +1165,7 @@ srs_error_t SrsHttpAuthMux::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessag { srs_error_t err; if ((err = do_auth(w, r)) != srs_success) { - srs_error("do_auth %s", srs_error_desc(err).c_str()); + srs_warn("do_auth %s", srs_error_desc(err).c_str()); srs_freep(err); w->write_header(SRS_CONSTS_HTTP_Unauthorized); return w->final_request(); diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index aa24ee97d..2dd89f953 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -32,6 +32,7 @@ using namespace std; // For TCP test server and client #include +#include #include // Temporary disk config. @@ -53,6 +54,11 @@ bool _srs_config_by_env = false; ISrsAppFactory *_srs_app_factory = new SrsAppFactory(); ISrsKernelFactory *_srs_kernel_factory = _srs_app_factory; +#ifdef SRS_FFMPEG_FIT +// Register FFmpeg log callback funciton. +SrsFFmpegLogHelper _srs_ffmpeg_log_helper; +#endif + // The binary name of SRS. const char *_srs_binary = NULL; @@ -97,6 +103,11 @@ srs_error_t prepare_main() return srs_error_wrap(err, "srt log initialize"); } +#ifdef SRS_FFMPEG_FIT + // Disable FFmpeg detail log in utest. + _srs_ffmpeg_log_helper.disable_ffmpeg_log(); +#endif + // Prevent the output of srt logs in utest. srt_setloghandler(NULL, srs_srt_utest_null_log_handler); // Set SRT log level to FATAL to suppress ERROR and WARNING logs in unit tests. diff --git a/trunk/src/utest/srs_utest_ai08.cpp b/trunk/src/utest/srs_utest_ai08.cpp index 130381dae..7d5f69dca 100644 --- a/trunk/src/utest/srs_utest_ai08.cpp +++ b/trunk/src/utest/srs_utest_ai08.cpp @@ -242,7 +242,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_BasicFunctionality) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); // Test initial state - bridge should be empty EXPECT_TRUE(bridge->empty()); @@ -260,7 +260,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_WithRtcTarget) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create and enable RTC target first @@ -287,7 +287,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_WithRtspTarget) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create and enable RTSP target first @@ -313,7 +313,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_WithRtcAndRtspTargets) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create and enable both RTC and RTSP targets @@ -348,7 +348,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspTargetReplacement) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Set first RTSP target @@ -377,7 +377,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_FrameHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -407,7 +407,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_OnFrameRtpBuilder) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Test frame handling without any targets first @@ -444,7 +444,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_OnFrameRtspBuilder) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -479,7 +479,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_OnFrameBothBuilders) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Enable both RTC and RTSP targets @@ -512,7 +512,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_BasicFunctionality) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); // Test initial state - bridge should be empty EXPECT_TRUE(bridge->empty()); @@ -530,7 +530,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_WithRtmpTarget) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -558,7 +558,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_WithRtcTarget) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create and enable RTC target first @@ -584,7 +584,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_PacketHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -606,7 +606,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_FrameHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -628,7 +628,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_OnFrameRtmpTarget) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -662,7 +662,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_OnFrameRtpBuilder) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -697,7 +697,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_OnFrameBothTargets) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Enable both RTMP and RTC targets @@ -728,7 +728,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_OnFrameBothTargets) // Test SrsRtcBridge basic functionality VOID TEST(StreamBridgeTest, SrsRtcBridge_BasicFunctionality) { - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); // Test initial state - bridge should be empty EXPECT_TRUE(bridge->empty()); @@ -740,7 +740,7 @@ VOID TEST(StreamBridgeTest, SrsRtcBridge_BasicFunctionality) // Test SrsRtcBridge with RTMP target VOID TEST(StreamBridgeTest, SrsRtcBridge_WithRtmpTarget) { - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); // Create a mock RTMP target using shared pointer SrsSharedPtr rtmp_source(new SrsLiveSource()); @@ -758,7 +758,7 @@ VOID TEST(StreamBridgeTest, SrsRtcBridge_RtpPacketHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTMP target for the bridge @@ -793,7 +793,7 @@ VOID TEST(StreamBridgeTest, SrsRtcBridge_RtpPacketTypes) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTMP target for the bridge @@ -829,7 +829,7 @@ VOID TEST(StreamBridgeTest, SrsRtcBridge_RtpWithoutFrameBuilder) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Test RTP handling without proper initialization (no frame builder) @@ -844,7 +844,7 @@ VOID TEST(StreamBridgeTest, SrsRtcBridge_RtpLifecycle) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTMP target @@ -877,7 +877,7 @@ VOID TEST(StreamBridgeTest, Bridge_ErrorHandling) srs_error_t err; // Test SrsRtmpBridge with invalid frame - SrsUniquePtr rtmp_bridge(new SrsRtmpBridge()); + SrsUniquePtr rtmp_bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); HELPER_EXPECT_SUCCESS(rtmp_bridge->initialize(req.get())); @@ -886,7 +886,7 @@ VOID TEST(StreamBridgeTest, Bridge_ErrorHandling) HELPER_EXPECT_SUCCESS(rtmp_bridge->on_frame(NULL)); // Test SrsSrtBridge with invalid packet - SrsUniquePtr srt_bridge(new SrsSrtBridge()); + SrsUniquePtr srt_bridge(new SrsSrtBridge(_srs_app_factory)); HELPER_EXPECT_SUCCESS(srt_bridge->initialize(req.get())); // Note: Skip NULL packet test as it causes segmentation fault @@ -899,7 +899,7 @@ VOID TEST(StreamBridgeTest, Bridge_LifecycleManagement) srs_error_t err; // Test multiple initialize calls - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // First initialize @@ -930,7 +930,7 @@ VOID TEST(StreamBridgeTest, SrsSrtBridge_MultipleTargets) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -970,7 +970,7 @@ VOID TEST(StreamBridgeTest, Bridge_TargetReplacement) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Initialize bridge @@ -1001,7 +1001,7 @@ VOID TEST(StreamBridgeTest, Bridge_StateConsistency) { srs_error_t err; - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Test empty state consistency @@ -1029,7 +1029,7 @@ VOID TEST(StreamBridgeTest, Bridge_MemoryManagement) // Test that bridges properly manage their internal components { - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); HELPER_EXPECT_SUCCESS(bridge->initialize(req.get())); @@ -1048,7 +1048,7 @@ VOID TEST(StreamBridgeTest, Bridge_MemoryManagement) } { - SrsUniquePtr bridge(new SrsSrtBridge()); + SrsUniquePtr bridge(new SrsSrtBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); HELPER_EXPECT_SUCCESS(bridge->initialize(req.get())); @@ -1064,7 +1064,7 @@ VOID TEST(StreamBridgeTest, Bridge_MemoryManagement) } { - SrsUniquePtr bridge(new SrsRtcBridge()); + SrsUniquePtr bridge(new SrsRtcBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); SrsSharedPtr rtmp_source(new SrsLiveSource()); @@ -1086,7 +1086,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspFrameHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create and enable RTSP target @@ -1115,7 +1115,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspLifecycle) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Test lifecycle without target @@ -1143,7 +1143,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspErrorHandling) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTSP target @@ -1167,7 +1167,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspMemoryManagement) // Test multiple RTSP bridge creation and destruction for (int i = 0; i < 5; ++i) { - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); SrsSharedPtr rtsp_source(new SrsRtspSource()); @@ -1192,7 +1192,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtmpToRtspConversion) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTSP target for protocol conversion @@ -1227,7 +1227,7 @@ VOID TEST(StreamBridgeTest, SrsRtmpBridge_RtspCodecChanges) { srs_error_t err; - SrsUniquePtr bridge(new SrsRtmpBridge()); + SrsUniquePtr bridge(new SrsRtmpBridge(_srs_app_factory)); SrsUniquePtr req(new MockStreamBridgeRequest()); // Create RTSP target @@ -1265,7 +1265,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterSEIFiltering) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1344,7 +1344,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterBFrameFilteringAVC) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1425,7 +1425,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterBFrameFilteringHEVC) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1500,7 +1500,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterCombinedSEIAndBFrameFiltering HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1587,7 +1587,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterIDRDetection) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1641,7 +1641,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterErrorHandling) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1687,7 +1687,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterNonAVCCodecSkipsSEIFiltering) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1755,7 +1755,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_FilterZeroSamples) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1797,7 +1797,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoMergeNalusMultipleSamples) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1871,7 +1871,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoLargeNaluPackageFuA) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -1956,7 +1956,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoExtremelyLargeNaluPackageFuA HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2036,7 +2036,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoMergeNalusWithMultipleNalus) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2119,7 +2119,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoMultipleLargeNalusPackageFuA HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2199,7 +2199,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoMergeNalusLargePayload) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2286,7 +2286,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioRealAacFrames) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2353,7 +2353,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioAddSampleFailure) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2409,7 +2409,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioTranscodeFailure) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2463,7 +2463,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioMemoryCleanup) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2522,7 +2522,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoComprehensiveCoverage) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2587,7 +2587,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoUnsupportedCodec) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2627,7 +2627,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoNoVcodecParsed) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2666,7 +2666,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoInitializeTrackError) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2730,7 +2730,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoFilterMethod) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2815,7 +2815,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoFormatError) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2878,7 +2878,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnVideoCodecSwitching) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2956,7 +2956,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_BasicInstantiation) MockRtpTarget rtp_target; // Test basic instantiation - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -2976,7 +2976,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_InitializeAudioTrack) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder first HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3022,7 +3022,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_InitializeVideoTrack) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder first HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3068,7 +3068,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_TrackInitializationCodecs) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder first HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3166,7 +3166,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_TrackInitializationWithSourceTracks rtc_source->set_stream_desc(source_desc); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3220,7 +3220,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioFormatConsumeSuccess) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3282,7 +3282,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioFormatConsumeError) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3328,7 +3328,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioNoAcodecParsed) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3377,7 +3377,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioUnsupportedCodec) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3456,7 +3456,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioSupportedCodecs) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3543,7 +3543,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioCodecValidationFailure) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3606,7 +3606,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_OnAudioComprehensiveCoverage) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3709,7 +3709,7 @@ VOID TEST(StreamBridgeTest, SrsRtcRtpBuilder_LazyInitialization) HELPER_EXPECT_SUCCESS(rtc_source->initialize(req.get())); MockRtpTarget rtp_target; - SrsRtcRtpBuilder builder(&rtp_target, rtc_source); + SrsRtcRtpBuilder builder(_srs_app_factory, &rtp_target, rtc_source); // Initialize the builder HELPER_EXPECT_SUCCESS(builder.initialize(req.get())); @@ -3796,8 +3796,8 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_MultipleBuilders) srs_error_t err; MockRtcFrameTarget target1, target2; - SrsRtcFrameBuilder builder1(&target1); - SrsRtcFrameBuilder builder2(&target2); + SrsRtcFrameBuilder builder1(_srs_app_factory, &target1); + SrsRtcFrameBuilder builder2(_srs_app_factory, &target2); // Initialize both builders SrsUniquePtr req1(new MockRtcRequest("vhost1", "app1", "stream1")); @@ -3826,14 +3826,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_Success) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(2); // Mock transcoder will output 2 packets // Access private member through friendship (utests have access to private members) @@ -3873,14 +3873,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_TranscoderError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); srs_error_t mock_error = srs_error_new(ERROR_RTC_RTP_MUXER, "mock transcoder error"); mock_transcoder->set_transcode_error(mock_error); @@ -3918,14 +3918,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_FrameTargetError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(1); // Mock transcoder will output 1 packet builder.audio_transcoder_ = mock_transcoder; @@ -3965,14 +3965,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_MultipleOutputPackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(5); // Mock transcoder will output 5 packets builder.audio_transcoder_ = mock_transcoder; @@ -4011,14 +4011,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_NoOutputPackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(0); // Mock transcoder will output 0 packets builder.audio_transcoder_ = mock_transcoder; @@ -4055,14 +4055,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_FrameTargetErrorOnTranscodedFrame) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(3); // Mock transcoder will output 3 packets builder.audio_transcoder_ = mock_transcoder; @@ -4126,14 +4126,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_SpecificCodePath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); // Set up mock transcoder to output packets with specific timestamps and sample data const char sample_data[] = {0x21, 0x10, 0x04, 0x60, (char)0x8C}; // Mock AAC data @@ -4187,14 +4187,14 @@ VOID TEST(RtcFrameBuilderTest, TranscodeAudio_ErrorInTranscoderLoop) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(3); // Mock transcoder will output 3 packets builder.audio_transcoder_ = mock_transcoder; @@ -4257,7 +4257,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_CompleteFrameDetectionWithPacketVideo srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4308,7 +4308,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_IsLostSnTrueErrorPath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4379,7 +4379,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_PreciseLostSequenceScenario) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4438,7 +4438,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoRtmp_RecursiveCallErrorHandling) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4506,7 +4506,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_ExactIsLostSnCodePathCoverage srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); diff --git a/trunk/src/utest/srs_utest_ai09.cpp b/trunk/src/utest/srs_utest_ai09.cpp index 03c5498ab..0769ed5c8 100644 --- a/trunk/src/utest/srs_utest_ai09.cpp +++ b/trunk/src/utest/srs_utest_ai09.cpp @@ -50,21 +50,24 @@ void MockRtcFrameTarget::reset() srs_freep(frame_error_); } -MockAudioTranscoder::MockAudioTranscoder() +MockAudioTranscoderForUtest::MockAudioTranscoderForUtest() { transcode_error_ = srs_success; should_output_packets_ = false; - aac_header_data_ = NULL; - aac_header_len_ = 0; + // Set default AAC header for mock transcoder + aac_header_len_ = 2; + aac_header_data_ = new uint8_t[aac_header_len_]; + aac_header_data_[0] = 0x12; // Mock AAC header byte 1 + aac_header_data_[1] = 0x10; // Mock AAC header byte 2 } -MockAudioTranscoder::~MockAudioTranscoder() +MockAudioTranscoderForUtest::~MockAudioTranscoderForUtest() { reset(); srs_freepa(aac_header_data_); } -srs_error_t MockAudioTranscoder::initialize(SrsAudioCodecId from, SrsAudioCodecId to, int channels, int sample_rate, int bit_rate) +srs_error_t MockAudioTranscoderForUtest::initialize(SrsAudioCodecId from, SrsAudioCodecId to, int channels, int sample_rate, int bit_rate) { // Create default AAC header for testing if (!aac_header_data_) { @@ -76,7 +79,7 @@ srs_error_t MockAudioTranscoder::initialize(SrsAudioCodecId from, SrsAudioCodecI return srs_success; } -srs_error_t MockAudioTranscoder::transcode(SrsParsedAudioPacket *in, std::vector &outs) +srs_error_t MockAudioTranscoderForUtest::transcode(SrsParsedAudioPacket *in, std::vector &outs) { if (transcode_error_ != srs_success) { return srs_error_copy(transcode_error_); @@ -105,7 +108,7 @@ srs_error_t MockAudioTranscoder::transcode(SrsParsedAudioPacket *in, std::vector return srs_success; } -void MockAudioTranscoder::free_frames(std::vector &frames) +void MockAudioTranscoderForUtest::free_frames(std::vector &frames) { for (std::vector::iterator it = frames.begin(); it != frames.end(); ++it) { SrsParsedAudioPacket *p = *it; @@ -119,13 +122,13 @@ void MockAudioTranscoder::free_frames(std::vector &frame } } -void MockAudioTranscoder::aac_codec_header(uint8_t **data, int *len) +void MockAudioTranscoderForUtest::aac_codec_header(uint8_t **data, int *len) { *data = aac_header_data_; *len = aac_header_len_; } -void MockAudioTranscoder::reset() +void MockAudioTranscoderForUtest::reset() { srs_freep(transcode_error_); @@ -141,7 +144,7 @@ void MockAudioTranscoder::reset() should_output_packets_ = false; } -void MockAudioTranscoder::set_output_packets(int count, const char *sample_data, int sample_size) +void MockAudioTranscoderForUtest::set_output_packets(int count, const char *sample_data, int sample_size) { reset(); should_output_packets_ = true; @@ -167,7 +170,7 @@ void MockAudioTranscoder::set_output_packets(int count, const char *sample_data, } } -void MockAudioTranscoder::set_transcode_error(srs_error_t err) +void MockAudioTranscoderForUtest::set_transcode_error(srs_error_t err) { srs_freep(transcode_error_); transcode_error_ = srs_error_copy(err); @@ -362,7 +365,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_NoPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -385,7 +388,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_NoAvsyncTime_InitialState) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -407,7 +410,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_NoAvsyncTime_StateZero) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -431,7 +434,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ValidAvsyncTime_SyncStateTransition) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -457,7 +460,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ValidAvsyncTime_SyncStateAlreadyTwo) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -483,7 +486,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_AudioPacketProcessing) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -508,7 +511,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_VideoPacketProcessing) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -529,7 +532,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_MixedAudioVideoPackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -555,7 +558,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_DifferentSSRCValues) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -580,7 +583,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_DifferentSequenceNumbers) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -605,7 +608,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_DifferentTimestamps) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -630,7 +633,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_SyncStateTransitions) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -664,7 +667,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_BoundaryAvsyncTimeValues) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -696,7 +699,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_NullPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -713,7 +716,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_RapidPacketSequence) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -738,7 +741,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_AlternatingAudioVideo) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -763,7 +766,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcPayload_WithVPSS srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -786,7 +789,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcPayload_MissingV srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -829,7 +832,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcPayload_MissingS srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -872,7 +875,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcPayload_MissingP srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -915,7 +918,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipVPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -955,7 +958,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -995,7 +998,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1035,7 +1038,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipMissingVPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1074,7 +1077,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipMissingSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1113,7 +1116,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_OBSWhipMissingPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1152,7 +1155,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcWithOBSWhipVPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1204,7 +1207,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcWithOBSWhipSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1256,7 +1259,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_STAPHevcWithOBSWhipPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1308,7 +1311,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_NonHEVCCodec) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec (not HEVC) SrsUniquePtr req(new MockRtcRequest()); @@ -1331,7 +1334,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_NonVPSSPSPPSRawPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1354,7 +1357,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_NullPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1385,7 +1388,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_CacheResetAfterUse) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1432,7 +1435,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderHevc_ComprehensiveCoverage) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1479,7 +1482,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_SameTimestampDifferentSequence) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1504,7 +1507,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_FrameTargetError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1529,7 +1532,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_FrameTargetError) VOID TEST(RtcFrameBuilderTest, OnRtp_UninitializedBuilder) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Do NOT initialize the builder @@ -1553,7 +1556,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_LargePayloadPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1584,7 +1587,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ZeroLengthPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1615,7 +1618,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_MaxSequenceNumber) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1639,7 +1642,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_MaxTimestamp) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1663,7 +1666,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ComprehensiveCoverage) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1705,7 +1708,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_TraceLogScenarios) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1739,7 +1742,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ComprehensiveCodePathCoverage) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -1848,7 +1851,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_STAPAPayload_WithSPSAndPP srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1871,7 +1874,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_STAPAPayload_MissingSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1909,7 +1912,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_STAPAPayload_MissingPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1947,7 +1950,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_OBSWhipSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -1979,7 +1982,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_OBSWhipPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2011,7 +2014,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_OBSWhipMissingSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2042,7 +2045,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_OBSWhipMissingPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2073,7 +2076,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_STAPAWithOBSWhipSPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2120,7 +2123,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_STAPAWithOBSWhipPPS) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2167,7 +2170,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_NonSPSPPSRawPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2190,7 +2193,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_EmptySTAPAPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2224,7 +2227,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_FrameTargetError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2249,7 +2252,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_CacheCleanup) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2284,7 +2287,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_NoSTAPANoRawPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2320,7 +2323,7 @@ VOID TEST(RtcFrameBuilderTest, PacketSequenceHeaderAvc_ComprehensiveCoverage) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2359,7 +2362,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ExactSyncStateTransitions) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -2394,7 +2397,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_AvsyncTimeBoundaryConditions) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -2427,7 +2430,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_AudioPacketProcessingPath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -2466,7 +2469,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_VideoPacketProcessingPath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -2501,7 +2504,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_MixedAudioVideoWithPayloads) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -2565,7 +2568,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_ErrorHandlingPacketVideoRtmpFails) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2618,7 +2621,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_FrameTargetFailureInPacketVideoRtmp) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2661,7 +2664,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_LostPacketRecoveryErrorPath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2703,7 +2706,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_MultipleFrameCompletionErrorHandling) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2752,7 +2755,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_HEVCCodecErrorHandling) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2845,7 +2848,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_BoundarySequenceNumbersErrorHandling) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2891,7 +2894,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_ErrorHandlingPacketVideoRtmpF srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -2934,7 +2937,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_HEVCErrorHandling) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3001,7 +3004,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_LostSequenceNumberErrorPath) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3045,7 +3048,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_SequenceHeaderAndFrameErrors) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3084,7 +3087,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_BoundarySequenceNumbers) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3128,7 +3131,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_ComprehensiveErrorPathCoverag srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3187,7 +3190,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ErrorPropagationFromPacketAudio) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3212,7 +3215,7 @@ VOID TEST(RtcFrameBuilderTest, OnRtp_ErrorPropagationFromPacketVideo) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3237,7 +3240,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_SinglePacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3279,7 +3282,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_MultipleSequentialPackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3319,7 +3322,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_OutOfOrderPackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3380,7 +3383,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_DuplicatePackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3433,7 +3436,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_LatePackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3488,7 +3491,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_LatePackets) VOID TEST(RtcFrameBuilderTest, PacketAudio_NullPacket) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3515,7 +3518,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_NoPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3548,7 +3551,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_ZeroLengthPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3583,7 +3586,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_LargePayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3620,7 +3623,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_FrameTargetError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3661,7 +3664,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_SequenceWrapAround) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3717,7 +3720,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_TimestampWrapAround) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3773,7 +3776,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_DifferentSSRC) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3824,7 +3827,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_RapidSequence) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -3867,7 +3870,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_VPSPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3905,7 +3908,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_STAPAPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3953,7 +3956,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_FUAPayloadIDR) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -3993,7 +3996,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_FUAPayloadNonIDR) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4033,7 +4036,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_AudioPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4068,7 +4071,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_AudioPacket) VOID TEST(RtcFrameBuilderTest, PacketVideo_NullPacket) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4094,7 +4097,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_NoPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4124,7 +4127,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_ZeroLengthPayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4159,7 +4162,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_LargePayload) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4196,7 +4199,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_SequenceWrapAround) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4245,7 +4248,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_TimestampWrapAround) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4294,7 +4297,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_DifferentSSRC) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4340,7 +4343,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_FrameTargetError) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4382,7 +4385,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_RapidSequence) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4425,7 +4428,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_MixedKeyframeSequence) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4474,7 +4477,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_KeyframeAVC) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4512,7 +4515,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_KeyframeHEVC) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with HEVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4550,7 +4553,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_NonKeyframe) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4588,7 +4591,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_SPSPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4626,7 +4629,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideo_PPSPacket) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); @@ -4664,7 +4667,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_MixedPayloadSizes) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4706,7 +4709,7 @@ VOID TEST(RtcFrameBuilderTest, PacketAudio_ComprehensiveScenario) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder SrsUniquePtr req(new MockRtcRequest()); @@ -4783,7 +4786,7 @@ VOID TEST(RtcFrameBuilderTest, PacketVideoKeyFrame_OutOfOrderKeyframePackets) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtcRequest()); diff --git a/trunk/src/utest/srs_utest_ai09.hpp b/trunk/src/utest/srs_utest_ai09.hpp index df79788ec..e61905081 100644 --- a/trunk/src/utest/srs_utest_ai09.hpp +++ b/trunk/src/utest/srs_utest_ai09.hpp @@ -39,7 +39,7 @@ public: }; // Mock audio transcoder for testing SrsRtcFrameBuilder::transcode_audio -class MockAudioTranscoder : public ISrsAudioTranscoder +class MockAudioTranscoderForUtest : public ISrsAudioTranscoder { public: // Control behavior @@ -50,8 +50,8 @@ public: int aac_header_len_; public: - MockAudioTranscoder(); - virtual ~MockAudioTranscoder(); + MockAudioTranscoderForUtest(); + virtual ~MockAudioTranscoderForUtest(); public: // ISrsAudioTranscoder interface diff --git a/trunk/src/utest/srs_utest_ai10.cpp b/trunk/src/utest/srs_utest_ai10.cpp index a95ffbbcd..1a655668e 100644 --- a/trunk/src/utest/srs_utest_ai10.cpp +++ b/trunk/src/utest/srs_utest_ai10.cpp @@ -63,7 +63,7 @@ SrsCodecPayload *create_test_codec_payload(uint8_t pt, std::string name, int sam VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeBasic) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test with NULL packet int null_size = builder.calculate_packet_payload_size(NULL); @@ -84,7 +84,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeBasic) VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeFUA) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.264 FU-A payload (SrsRtpFUAPayload2) - start fragment SrsUniquePtr fua_start_pkt(new SrsRtpPacket()); @@ -149,7 +149,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeFUA) VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeSTAP) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.264 STAP-A payload (SrsRtpSTAPPayload) with multiple NALUs SrsUniquePtr stap_pkt(new SrsRtpPacket()); @@ -221,7 +221,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeSTAP) VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeFUAHevc) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.265 FU-A payload (SrsRtpFUAPayloadHevc2) - start fragment SrsUniquePtr fua_hevc_start_pkt(new SrsRtpPacket()); @@ -286,7 +286,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeFUAHevc) VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeSTAPHevc) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.265 STAP payload (SrsRtpSTAPPayloadHevc) with multiple NALUs SrsUniquePtr stap_hevc_pkt(new SrsRtpPacket()); @@ -366,7 +366,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeSTAPHevc) VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeEdgeCases) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test with unknown payload type (should fall through to default case) SrsUniquePtr unknown_pkt(new SrsRtpPacket()); @@ -394,7 +394,7 @@ VOID TEST(SrsRtcFrameBuilderTest, CalculatePacketPayloadSizeEdgeCases) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferRaw) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with raw payload SrsUniquePtr pkt(new SrsRtpPacket()); @@ -435,7 +435,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferRaw) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAStart) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.264 FU-A start fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -482,7 +482,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAStart) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAMiddle) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.264 FU-A middle fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -523,7 +523,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAMiddle) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAEnd) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.264 FU-A end fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -579,7 +579,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAEnd) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevc) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.265 FU-A start fragment SrsUniquePtr hevc_pkt(new SrsRtpPacket()); @@ -623,7 +623,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevc) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAEdgeCases) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Test H.264 FU-A with zero-size payload SrsUniquePtr zero_pkt(new SrsRtpPacket()); @@ -694,7 +694,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAEdgeCases) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUASequence) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); char buffer_data[1024]; SrsBuffer buffer(buffer_data, sizeof(buffer_data)); @@ -782,7 +782,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUASequence) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAP) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.264 STAP payload SrsUniquePtr pkt(new SrsRtpPacket()); @@ -857,7 +857,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAP) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAPWithEmptyNALUs) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.264 STAP payload SrsUniquePtr pkt(new SrsRtpPacket()); @@ -930,7 +930,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAPWithEmptyNALUs) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcStart) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.265 FU-A start fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -978,7 +978,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcStart) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcMiddle) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.265 FU-A middle fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -1018,7 +1018,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcMiddle) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcEnd) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.265 FU-A end fragment SrsUniquePtr pkt(new SrsRtpPacket()); @@ -1073,7 +1073,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferFUAHevcEnd) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAPHevc) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.265 STAP payload SrsUniquePtr pkt(new SrsRtpPacket()); @@ -1148,7 +1148,7 @@ VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAPHevc) VOID TEST(SrsRtcFrameBuilderTest, WritePacketPayloadToBufferSTAPHevcWithEmptyNALUs) { MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Create test RTP packet with H.265 STAP payload SrsUniquePtr pkt(new SrsRtpPacket()); @@ -1229,7 +1229,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluBasic) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1280,7 +1280,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluNoNextFrame) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1323,7 +1323,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluRecursiveCall) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1377,7 +1377,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluMultipleEmptyFrames) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1438,7 +1438,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluZeroSizePayloads) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1497,7 +1497,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluHevc) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.265 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1548,7 +1548,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluSequenceWrapAround) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -1597,7 +1597,7 @@ VOID TEST(SrsRtcFrameBuilderTest, PacketVideoRtmpEmptyNaluFrameProcessing) srs_error_t err; MockRtcFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize builder with H.264 codec SrsUniquePtr req(new MockRtcRequest()); @@ -2253,7 +2253,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadEmptyBuffer) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2276,7 +2276,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264RawNALU) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2307,7 +2307,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264STAP) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2342,7 +2342,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264FUA) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2376,7 +2376,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCRawNALU) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H265", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2407,7 +2407,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCSTAP) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H265", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2444,7 +2444,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCFUA) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H265", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2479,7 +2479,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadUnknownCodec) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("VP8", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2510,7 +2510,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadNoMediaCodec) srs_freep(desc->media_); desc->media_ = NULL; - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2529,7 +2529,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264IDR) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2560,7 +2560,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCIDR) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H265", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2591,7 +2591,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadSingleByte) { MockRtcPacketReceiver mock_receiver; SrsUniquePtr desc(create_video_track_description("H264", 12345)); - SrsRtcVideoRecvTrack track(&mock_receiver, desc.get()); + SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false); SrsUniquePtr pkt(create_test_rtp_packet(100, 1000, 12345)); @@ -2928,7 +2928,7 @@ VOID TEST(SrsRtcAudioRecvTrackTest, OnBeforeDecodePayload) // Create the audio receive track MockRtcPacketReceiver mock_receiver; - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc, false); // Test case 1: Empty buffer - should return early without setting payload { @@ -2996,7 +2996,7 @@ VOID TEST(SrsRtcAudioRecvTrackTest, CheckSendNacksWithMock) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("audio", 12345)); - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get()); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get(), false); // Test case 1: Basic check_send_nacks call - should execute successfully HELPER_EXPECT_SUCCESS(audio_track.check_send_nacks()); @@ -3017,7 +3017,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, CheckSendNacksWithMock) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("video", 54321)); - SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get()); + SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get(), false); // Test case 1: Basic check_send_nacks call - should execute successfully HELPER_EXPECT_SUCCESS(video_track.check_send_nacks()); @@ -3038,7 +3038,7 @@ VOID TEST(SrsRtcRecvTrackTest, DoCheckSendNacksBasic) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("audio", 98765)); - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get()); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get(), false); // Test case 1: do_check_send_nacks should execute successfully uint32_t timeout_nacks = 999; @@ -3060,7 +3060,7 @@ VOID TEST(SrsRtcAudioRecvTrackTest, CheckSendNacksMultipleCalls) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("audio", 11111)); - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get()); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get(), false); // Test multiple consecutive calls - all should succeed HELPER_EXPECT_SUCCESS(audio_track.check_send_nacks()); @@ -3079,7 +3079,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, CheckSendNacksTimeoutScenarios) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("video", 22222)); - SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get()); + SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get(), false); // Test multiple calls - all should succeed HELPER_EXPECT_SUCCESS(video_track.check_send_nacks()); @@ -3106,7 +3106,7 @@ VOID TEST(SrsRtcRecvTrackTest, DoCheckSendNacksDifferentSSRC) uint32_t test_ssrc = test_ssrcs[i]; SrsUniquePtr track_desc(create_test_track_description("video", test_ssrc)); - SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get()); + SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get(), false); uint32_t timeout_nacks = 999; HELPER_EXPECT_SUCCESS(video_track.do_check_send_nacks(timeout_nacks)); @@ -3123,7 +3123,7 @@ VOID TEST(SrsRtcAudioRecvTrackTest, CheckSendNacksEdgeCases) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("audio", 33333)); - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get()); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc.get(), false); // Test multiple calls with different scenarios - all should succeed HELPER_EXPECT_SUCCESS(audio_track.check_send_nacks()); @@ -3142,7 +3142,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, CheckSendNacksEdgeCases) MockRtcPacketReceiver mock_receiver; SrsUniquePtr track_desc(create_test_track_description("video", 44444)); - SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get()); + SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc.get(), false); // Test multiple calls with different scenarios - all should succeed HELPER_EXPECT_SUCCESS(video_track.check_send_nacks()); @@ -3163,8 +3163,8 @@ VOID TEST(SrsRtcRecvTrackTest, NackReceiverParameterPassing) SrsUniquePtr track_desc1(create_test_track_description("audio", 55555)); SrsUniquePtr track_desc2(create_test_track_description("video", 66666)); - SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc1.get()); - SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc2.get()); + SrsRtcAudioRecvTrack audio_track(&mock_receiver, track_desc1.get(), false); + SrsRtcVideoRecvTrack video_track(&mock_receiver, track_desc2.get(), false); // Test audio track functionality uint32_t timeout_nacks = 0; diff --git a/trunk/src/utest/srs_utest_ai11.cpp b/trunk/src/utest/srs_utest_ai11.cpp index 5fb340550..59d4674fc 100644 --- a/trunk/src/utest/srs_utest_ai11.cpp +++ b/trunk/src/utest/srs_utest_ai11.cpp @@ -1835,7 +1835,7 @@ VOID TEST(RtcPublishStreamTest, SendRtcpXrRrtr) audio_desc->id_ = "audio_track_1"; audio_desc->ssrc_ = 12345; audio_desc->is_active_ = true; - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc, false); publish_stream->audio_tracks_.push_back(audio_track); // Create video track @@ -1844,7 +1844,7 @@ VOID TEST(RtcPublishStreamTest, SendRtcpXrRrtr) video_desc->id_ = "video_track_1"; video_desc->ssrc_ = 67890; video_desc->is_active_ = true; - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc, false); publish_stream->video_tracks_.push_back(video_track); // Test successful case @@ -1899,8 +1899,8 @@ VOID TEST(RtcPublishStreamTest, SendRtcpRrSuccess) audio_track_desc->ssrc_ = 67890; // Create video and audio recv tracks - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc.get()); - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc.get()); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc.get(), false); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc.get(), false); // Add tracks to publish stream (using private member access) // The publish stream will take ownership and free them in destructor @@ -1934,7 +1934,7 @@ VOID TEST(RtcPublishStreamTest, SendRtcpRrVideoTrackError) video_track_desc->ssrc_ = 12345; // Create video recv track - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc.get()); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc.get(), false); // Add track to publish stream (only video track to simplify) publish_stream->video_tracks_.push_back(video_track); @@ -2003,10 +2003,10 @@ VOID TEST(RtcPublishStreamTest, SendRtcpRrMultipleTracks) audio_track_desc2->ssrc_ = 67891; // Create tracks - SrsRtcVideoRecvTrack *video_track1 = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc1.get()); - SrsRtcVideoRecvTrack *video_track2 = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc2.get()); - SrsRtcAudioRecvTrack *audio_track1 = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc1.get()); - SrsRtcAudioRecvTrack *audio_track2 = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc2.get()); + SrsRtcVideoRecvTrack *video_track1 = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc1.get(), false); + SrsRtcVideoRecvTrack *video_track2 = new SrsRtcVideoRecvTrack(&mock_receiver, video_track_desc2.get(), false); + SrsRtcAudioRecvTrack *audio_track1 = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc1.get(), false); + SrsRtcAudioRecvTrack *audio_track2 = new SrsRtcAudioRecvTrack(&mock_receiver, audio_track_desc2.get(), false); // Add tracks to publish stream publish_stream->video_tracks_.push_back(video_track1); diff --git a/trunk/src/utest/srs_utest_ai12.cpp b/trunk/src/utest/srs_utest_ai12.cpp index 8b5cd25dd..e97d0f3ec 100644 --- a/trunk/src/utest/srs_utest_ai12.cpp +++ b/trunk/src/utest/srs_utest_ai12.cpp @@ -23,7 +23,7 @@ extern bool srs_sdp_has_h264_profile(const SrsSdp &sdp, const string &profile); // Mock video recv track implementation MockRtcVideoRecvTrackForNack::MockRtcVideoRecvTrackForNack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc) - : SrsRtcVideoRecvTrack(receiver, track_desc) + : SrsRtcVideoRecvTrack(receiver, track_desc, false) { check_send_nacks_error_ = srs_success; check_send_nacks_count_ = 0; @@ -52,7 +52,7 @@ void MockRtcVideoRecvTrackForNack::reset() // Mock audio recv track implementation MockRtcAudioRecvTrackForNack::MockRtcAudioRecvTrackForNack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDescription *track_desc) - : SrsRtcAudioRecvTrack(receiver, track_desc) + : SrsRtcAudioRecvTrack(receiver, track_desc, false) { check_send_nacks_error_ = srs_success; check_send_nacks_count_ = 0; @@ -200,7 +200,7 @@ VOID TEST(SrsRtcPublishStreamTest, OnRtpPlaintextTypicalScenario) video_desc.id_ = "video_track_test"; video_desc.ssrc_ = 0xDEF01234; // SSRC from RTP packet (0xDE, 0xF0, 0x12, 0x34) video_desc.is_active_ = true; - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc, false); publish_stream->video_tracks_.push_back(video_track); // Enable tracks for processing @@ -308,12 +308,12 @@ VOID TEST(SrsRtcPublishStreamTest, OnBeforeDecodePayloadTypicalScenario) // Create video track with proper codec payload SrsUniquePtr video_desc(create_video_track_description_with_codec("H264", 0x12345678)); - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc.get()); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc.get(), false); publish_stream->video_tracks_.push_back(video_track); // Create audio track with proper codec payload SrsUniquePtr audio_desc(create_test_track_description("audio", 0x87654321)); - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get()); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get(), false); publish_stream->audio_tracks_.push_back(audio_track); // Test scenario 1: Empty buffer - should return early without processing @@ -484,7 +484,7 @@ VOID TEST(SrsRtcPublishStreamTest, OnRtcpXrPathTypicalScenario) video_desc.id_ = "video_track_xr_path_test"; video_desc.ssrc_ = 0x12345678; video_desc.is_active_ = true; - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc, false); publish_stream->video_tracks_.push_back(video_track); // Create a valid RTCP XR packet with DLRR block (block type 5) @@ -535,7 +535,7 @@ VOID TEST(SrsRtcPublishStreamTest, OnRtcpXrTypicalScenario) video_desc.id_ = "video_track_xr_test"; video_desc.ssrc_ = 0x12345678; video_desc.is_active_ = true; - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, &video_desc, false); publish_stream->video_tracks_.push_back(video_track); // Create a valid RTCP XR packet with DLRR block (block type 5) @@ -625,7 +625,7 @@ VOID TEST(SrsRtcPublishStreamTest, UpdateRttTypicalScenario) audio_desc.id_ = "audio_track_rtt_test"; audio_desc.ssrc_ = 0x87654321; audio_desc.is_active_ = true; - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, &audio_desc); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, &audio_desc, false); publish_stream->audio_tracks_.push_back(audio_track); // Test typical RTT update scenario for audio track @@ -660,7 +660,7 @@ VOID TEST(SrsRtcPublishStreamTest, UpdateSendReportTimeTypicalScenario) // Create test audio track SrsUniquePtr audio_desc(create_test_track_description("audio", 0x87654321)); audio_desc->media_ = new SrsAudioPayload(111, "opus", 48000, 2); - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get()); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get(), false); publish_stream->audio_tracks_.push_back(audio_track); // Test typical scenario: update send report time for audio track @@ -740,7 +740,7 @@ VOID TEST(SrsRtcPublishStreamTest, DoOnRtpPlaintextAudioTrackTypicalScenario) // Create audio track with matching SSRC for the RTP packet SrsUniquePtr audio_desc(create_test_track_description("audio", 0x87654321)); audio_desc->media_ = new SrsAudioPayload(111, "opus", 48000, 2); - SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get()); + SrsRtcAudioRecvTrack *audio_track = new SrsRtcAudioRecvTrack(&mock_receiver, audio_desc.get(), false); publish_stream->audio_tracks_.push_back(audio_track); // The publish stream already has its own source_ created in constructor, no need to create a new one @@ -2266,7 +2266,7 @@ VOID TEST(SrsRtcConnectionTest, OnRtpPlaintextTypicalScenario) // Create video track with matching SSRC for the RTP packet using helper function SrsUniquePtr video_desc(create_video_track_description_with_codec("H264", test_ssrc)); - SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc.get()); + SrsRtcVideoRecvTrack *video_track = new SrsRtcVideoRecvTrack(&mock_receiver, video_desc.get(), false); publish_stream->video_tracks_.push_back(video_track); // Enable tracks for processing diff --git a/trunk/src/utest/srs_utest_ai24.cpp b/trunk/src/utest/srs_utest_ai24.cpp new file mode 100644 index 000000000..362f41cd4 --- /dev/null +++ b/trunk/src/utest/srs_utest_ai24.cpp @@ -0,0 +1,305 @@ +// +// Copyright (c) 2013-2025 The SRS Authors +// +// SPDX-License-Identifier: MIT +// +#include + +#include +#include +#include +#include + +using namespace std; + +// Mock class to access protected members of SrsRtcRecvTrack +class MockSrsRtcRecvTrackForAVSync : public SrsRtcRecvTrack +{ + SRS_DECLARE_PRIVATE: + static SrsRtcTrackDescription* create_track_desc(const string& type, uint32_t ssrc, int sample_rate) + { + SrsRtcTrackDescription *desc = new SrsRtcTrackDescription(); + desc->type_ = type; + desc->id_ = "test_track"; + desc->ssrc_ = ssrc; + desc->is_active_ = true; + + // Create media description with sample rate + desc->media_ = new SrsAudioPayload(); + desc->media_->sample_ = sample_rate; + + return desc; + } + +public: + MockSrsRtcRecvTrackForAVSync(const string &type, uint32_t ssrc, int sample_rate, bool is_audio) + : SrsRtcRecvTrack(NULL, create_track_desc(type, ssrc, sample_rate), is_audio, true) + { + } + + // Expose protected methods for testing + double get_rate() const { return rate_; } + + void set_rate(double rate) { rate_ = rate; } + + int64_t test_cal_avsync_time(uint32_t rtp_time) + { + return cal_avsync_time(rtp_time); + } + + void test_update_send_report_time(const SrsNtp &ntp, uint32_t rtp_time) + { + update_send_report_time(ntp, rtp_time); + } + + // Implement pure virtual methods + virtual srs_error_t on_rtp(SrsSharedPtr &source, SrsRtpPacket *pkt) + { + return srs_success; + } + + virtual srs_error_t check_send_nacks() + { + return srs_success; + } +}; + +// Test: Rate initialization from SDP for audio track (48kHz) +VOID TEST(RtcAVSyncTest, AudioRateInitFromSDP) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // Rate should be initialized to 48 (48000 Hz / 1000 = 48 RTP units per ms) + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); +} + +// Test: Rate initialization from SDP for video track (90kHz) +VOID TEST(RtcAVSyncTest, VideoRateInitFromSDP) +{ + MockSrsRtcRecvTrackForAVSync track("video", 67890, 90000, false); + + // Rate should be initialized to 90 (90000 Hz / 1000 = 90 RTP units per ms) + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); +} + +// Test: cal_avsync_time with SDP rate (before receiving SR) +VOID TEST(RtcAVSyncTest, CalAVSyncTimeWithSDPRate) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // Simulate first SR received + SrsNtp ntp; + ntp.system_ms_ = 1000; // 1000 ms + uint32_t rtp_time = 48000; // 48000 RTP units + track.test_update_send_report_time(ntp, rtp_time); + + // Calculate avsync time for a later RTP packet + // RTP time: 48000 + 4800 = 52800 (100ms later at 48kHz) + // Expected avsync_time: 1000 + (52800 - 48000) / 48 = 1000 + 100 = 1100 ms + int64_t avsync_time = track.test_cal_avsync_time(52800); + EXPECT_EQ(1100, avsync_time); +} + +// Test: cal_avsync_time returns -1 when rate is 0 +VOID TEST(RtcAVSyncTest, CalAVSyncTimeWithZeroRate) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // Manually set rate to 0 + track.set_rate(0.0); + + // Should return -1 when rate is too small + int64_t avsync_time = track.test_cal_avsync_time(1000); + EXPECT_EQ(-1, avsync_time); +} + +// Test: Rate update after receiving 2nd SR (audio) +VOID TEST(RtcAVSyncTest, AudioRateUpdateAfter2ndSR) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // Initial rate from SDP + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 48000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Rate should still be 48 (from SDP) + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); + + // Second SR (20ms later, RTP increased by 960) + SrsNtp ntp2; + ntp2.system_ms_ = 1020; // 20ms later + uint32_t rtp_time2 = 48960; // 960 RTP units later (48 * 20) + track.test_update_send_report_time(ntp2, rtp_time2); + + // Rate should be updated to calculated value: 960 / 20 = 48 + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); +} + +// Test: Rate update after receiving 2nd SR (video) +VOID TEST(RtcAVSyncTest, VideoRateUpdateAfter2ndSR) +{ + MockSrsRtcRecvTrackForAVSync track("video", 67890, 90000, false); + + // Initial rate from SDP + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 2000; + uint32_t rtp_time1 = 180000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Rate should still be 90 (from SDP) + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); + + // Second SR (100ms later, RTP increased by 9000) + SrsNtp ntp2; + ntp2.system_ms_ = 2100; // 100ms later + uint32_t rtp_time2 = 189000; // 9000 RTP units later (90 * 100) + track.test_update_send_report_time(ntp2, rtp_time2); + + // Rate should be updated to calculated value: 9000 / 100 = 90 + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); +} + +// Test: Rate calculation with clock drift (slightly off from SDP) +VOID TEST(RtcAVSyncTest, RateUpdateWithClockDrift) +{ + MockSrsRtcRecvTrackForAVSync track("video", 67890, 90000, false); + + // Initial rate from SDP + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 90000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Second SR with slight clock drift + // Expected: 100ms -> 9000 RTP units + // Actual: 100ms -> 9010 RTP units (slight drift) + SrsNtp ntp2; + ntp2.system_ms_ = 1100; + uint32_t rtp_time2 = 99010; // Slightly more than expected + track.test_update_send_report_time(ntp2, rtp_time2); + + // Rate should be updated to: round(9010 / 100) = 90 + EXPECT_DOUBLE_EQ(90.0, track.get_rate()); +} + +// Test: Rate calculation with larger time interval +VOID TEST(RtcAVSyncTest, RateUpdateWithLargeInterval) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 5000; + uint32_t rtp_time1 = 240000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Second SR (1000ms later) + SrsNtp ntp2; + ntp2.system_ms_ = 6000; + uint32_t rtp_time2 = 288000; // 48000 RTP units later (48 * 1000) + track.test_update_send_report_time(ntp2, rtp_time2); + + // Rate should be: 48000 / 1000 = 48 + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); +} + +// Test: cal_avsync_time with precise rate after 2nd SR +VOID TEST(RtcAVSyncTest, CalAVSyncTimeAfter2ndSR) +{ + MockSrsRtcRecvTrackForAVSync track("video", 67890, 90000, false); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 90000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Second SR + SrsNtp ntp2; + ntp2.system_ms_ = 1100; + uint32_t rtp_time2 = 99000; + track.test_update_send_report_time(ntp2, rtp_time2); + + // Now calculate avsync time for a packet + // RTP time: 99000 + 4500 = 103500 (50ms later at 90kHz) + // Expected: 1100 + (103500 - 99000) / 90 = 1100 + 50 = 1150 ms + int64_t avsync_time = track.test_cal_avsync_time(103500); + EXPECT_EQ(1150, avsync_time); +} + +// Test: Immediate A/V sync availability (issue #4418 fix) +VOID TEST(RtcAVSyncTest, ImmediateAVSyncAvailability) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // Before any SR, rate should be available from SDP + EXPECT_DOUBLE_EQ(48.0, track.get_rate()); + + // First SR received + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 48000; + track.test_update_send_report_time(ntp1, rtp_time1); + + // Should be able to calculate avsync_time immediately (not -1) + int64_t avsync_time = track.test_cal_avsync_time(48480); // 10ms later + EXPECT_GT(avsync_time, 0); // Should be > 0, not -1 + EXPECT_EQ(1010, avsync_time); // Should be 1000 + 10 = 1010 +} + +// Test: RTP timestamp wraparound handling +VOID TEST(RtcAVSyncTest, RTPTimestampWraparound) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // First SR near wraparound + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 0xFFFFF000; // Near max uint32_t + track.test_update_send_report_time(ntp1, rtp_time1); + + // Second SR after wraparound + SrsNtp ntp2; + ntp2.system_ms_ = 1020; // 20ms later + uint32_t rtp_time2 = 0x000003C0; // Wrapped around, 960 units after wraparound + track.test_update_send_report_time(ntp2, rtp_time2); + + // Note: Current implementation may not handle wraparound correctly + // This test documents the current behavior + // Rate calculation: (0x000003C0 - 0xFFFFF000) will underflow + // This is a known limitation that may need fixing in the future +} + +// Test: Zero time elapsed between SRs (edge case) +VOID TEST(RtcAVSyncTest, ZeroTimeElapsedBetweenSRs) +{ + MockSrsRtcRecvTrackForAVSync track("audio", 12345, 48000, true); + + // First SR + SrsNtp ntp1; + ntp1.system_ms_ = 1000; + uint32_t rtp_time1 = 48000; + track.test_update_send_report_time(ntp1, rtp_time1); + + double rate_before = track.get_rate(); + + // Second SR with same timestamp (0ms elapsed) + SrsNtp ntp2; + ntp2.system_ms_ = 1000; // Same time + uint32_t rtp_time2 = 48000; // Same RTP time + track.test_update_send_report_time(ntp2, rtp_time2); + + // Rate should remain unchanged (SDP rate) + EXPECT_DOUBLE_EQ(rate_before, track.get_rate()); +} diff --git a/trunk/src/utest/srs_utest_ai24.hpp b/trunk/src/utest/srs_utest_ai24.hpp new file mode 100644 index 000000000..1a34c0082 --- /dev/null +++ b/trunk/src/utest/srs_utest_ai24.hpp @@ -0,0 +1,11 @@ +// +// Copyright (c) 2013-2025 The SRS Authors +// +// SPDX-License-Identifier: MIT +// +#ifndef SRS_UTEST_AI_RTC_AVSYNC_HPP +#define SRS_UTEST_AI_RTC_AVSYNC_HPP + +#include + +#endif diff --git a/trunk/src/utest/srs_utest_manual_app_rtc2rtmp.cpp b/trunk/src/utest/srs_utest_manual_app_rtc2rtmp.cpp index 615afd157..1fa3caf90 100644 --- a/trunk/src/utest/srs_utest_manual_app_rtc2rtmp.cpp +++ b/trunk/src/utest/srs_utest_manual_app_rtc2rtmp.cpp @@ -334,7 +334,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_SameKeyframeTimestampVideoSequence) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -404,7 +404,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_SameStapForIdrVideoSequence) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -456,7 +456,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_DifferentKeyframeTimestampVideoSequen srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -524,7 +524,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_TypicalVideoSequence) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -595,7 +595,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_SingleVideoSequence) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -652,7 +652,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_SingleVideoSequence_LargePFrame) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -728,7 +728,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_AcceptableVideoSequence) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -792,7 +792,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_EmptyIDRBeforeNormalFrames) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -855,7 +855,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_EmptyIDRBeforeNormalFrames_FUA) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -917,7 +917,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_BaselinePackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -985,7 +985,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_NoSpsPpsPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1044,7 +1044,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_ReorderingIdrPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1113,7 +1113,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_PframeBeforeIdrPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1188,7 +1188,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_PframeReorderingPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1262,7 +1262,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_IdrPframeReorderingPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1341,7 +1341,7 @@ VOID TEST(Rtc2RtmpConvertTest, PacketVideo_PframeLostPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with AVC codec SrsUniquePtr req(new MockRtc2RtmpRequest()); @@ -1402,14 +1402,14 @@ VOID TEST(Rtc2RtmpConvertTest, PacketAudio_ThreeAudioPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with Opus codec (typical for WebRTC) SrsUniquePtr req(new MockRtc2RtmpRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdOpus, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock to avoid FFmpeg issues - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(1); // Each input packet produces 1 output packet // Access private member through friendship (utests have access to private members) @@ -1452,14 +1452,14 @@ VOID TEST(Rtc2RtmpConvertTest, PacketAudio_ReorderingAudioPackets) srs_error_t err; MockRtc2RtmpFrameTarget target; - SrsRtcFrameBuilder builder(&target); + SrsRtcFrameBuilder builder(_srs_app_factory, &target); // Initialize the builder with Opus codec (typical for WebRTC) SrsUniquePtr req(new MockRtc2RtmpRequest()); HELPER_EXPECT_SUCCESS(builder.initialize(req.get(), SrsAudioCodecIdOpus, SrsVideoCodecIdAVC)); // Replace the audio transcoder with our mock to avoid FFmpeg issues - MockAudioTranscoder *mock_transcoder = new MockAudioTranscoder(); + MockAudioTranscoderForUtest *mock_transcoder = new MockAudioTranscoderForUtest(); mock_transcoder->set_output_packets(1); // Each input packet produces 1 output packet // Access private member through friendship (utests have access to private members) diff --git a/trunk/src/utest/srs_utest_manual_mock.cpp b/trunk/src/utest/srs_utest_manual_mock.cpp index 858b21f88..efd8932a8 100644 --- a/trunk/src/utest/srs_utest_manual_mock.cpp +++ b/trunk/src/utest/srs_utest_manual_mock.cpp @@ -180,6 +180,10 @@ MockRtcTrackDescriptionFactory::MockRtcTrackDescriptionFactory() audio_ssrc_ = 12345; video_ssrc_ = 67890; screen_ssrc_ = 98765; + + audio_pt_ = 111; + video_pt_ = 96; + screen_pt_ = 97; } MockRtcTrackDescriptionFactory::~MockRtcTrackDescriptionFactory() @@ -227,12 +231,17 @@ SrsRtcTrackDescription *MockRtcTrackDescriptionFactory::create_audio_track(uint3 audio_desc->is_active_ = true; audio_desc->direction_ = "sendrecv"; audio_desc->mid_ = mid; - audio_desc->media_ = new SrsAudioPayload(111, "opus", 48000, 2); + audio_desc->media_ = new SrsAudioPayload(audio_pt_, "opus", 48000, 2); return audio_desc; } SrsRtcTrackDescription *MockRtcTrackDescriptionFactory::create_video_track(uint32_t ssrc, std::string id, std::string mid) { + uint8_t pt = video_pt_; + if (ssrc == screen_ssrc_) { + pt = screen_pt_; + } + SrsRtcTrackDescription *video_desc = new SrsRtcTrackDescription(); video_desc->type_ = "video"; video_desc->ssrc_ = ssrc; @@ -240,7 +249,7 @@ SrsRtcTrackDescription *MockRtcTrackDescriptionFactory::create_video_track(uint3 video_desc->is_active_ = true; video_desc->direction_ = "sendrecv"; video_desc->mid_ = mid; - video_desc->media_ = new SrsVideoPayload(96, "H264", 90000); + video_desc->media_ = new SrsVideoPayload(pt, "H264", 90000); return video_desc; } @@ -294,6 +303,21 @@ ISrsRequest *MockRtcAsyncCallRequest::as_http() return this; } +MockRtcSource::MockRtcSource() +{ + on_rtp_count_ = 0; +} + +MockRtcSource::~MockRtcSource() +{ +} + +srs_error_t MockRtcSource::on_rtp(SrsRtpPacket *pkt) +{ + on_rtp_count_++; + return SrsRtcSource::on_rtp(pkt); +} + // MockRtcSourceManager implementation MockRtcSourceManager::MockRtcSourceManager() { @@ -301,7 +325,7 @@ MockRtcSourceManager::MockRtcSourceManager() fetch_or_create_error_ = srs_success; initialize_count_ = 0; fetch_or_create_count_ = 0; - mock_source_ = SrsSharedPtr(new SrsRtcSource()); + mock_source_ = SrsSharedPtr(new MockRtcSource()); } MockRtcSourceManager::~MockRtcSourceManager() @@ -523,485 +547,6 @@ void MockRtcPacketSender::set_send_packet_error(srs_error_t err) send_packet_error_ = err; } -// MockAppConfig implementation -MockAppConfig::MockAppConfig() -{ - http_hooks_enabled_ = true; - on_stop_directive_ = NULL; - on_unpublish_directive_ = NULL; - rtc_nack_enabled_ = true; - rtc_nack_no_copy_ = false; - rtc_drop_for_pt_ = 0; - rtc_twcc_enabled_ = true; - srt_enabled_ = false; - rtc_to_rtmp_ = false; - dash_dispose_ = 0; - dash_enabled_ = false; - api_as_candidates_ = true; - resolve_api_domain_ = true; - keep_api_domain_ = false; - mw_msgs_ = 8; - mw_sleep_ = 350 * SRS_UTIME_MILLISECONDS; - rtc_dtls_role_ = "passive"; - default_vhost_ = NULL; - srt_to_rtmp_ = true; - rtc_from_rtmp_ = false; - forwards_directive_ = NULL; - backend_directive_ = NULL; -} - -MockAppConfig::~MockAppConfig() -{ - clear_on_stop_directive(); - clear_on_unpublish_directive(); - - srs_freep(default_vhost_); - srs_freep(forwards_directive_); - srs_freep(backend_directive_); -} - -void MockAppConfig::set_forward_destinations(const std::vector &destinations) -{ - srs_freep(forwards_directive_); - - if (!destinations.empty()) { - forwards_directive_ = new SrsConfDirective(); - forwards_directive_->name_ = "destination"; - forwards_directive_->args_ = destinations; - } -} - -void MockAppConfig::set_forward_backend(const std::string &backend_url) -{ - srs_freep(backend_directive_); - - if (!backend_url.empty()) { - backend_directive_ = new SrsConfDirective(); - backend_directive_->name_ = "backend"; - backend_directive_->args_.push_back(backend_url); - } -} - -srs_utime_t MockAppConfig::get_pithy_print() -{ - return 10 * SRS_UTIME_SECONDS; -} - -std::string MockAppConfig::get_default_app_name() -{ - return "live"; -} - -void MockAppConfig::subscribe(ISrsReloadHandler *handler) -{ - // Do nothing in mock -} - -void MockAppConfig::unsubscribe(ISrsReloadHandler *handler) -{ - // Do nothing in mock -} - -bool MockAppConfig::get_vhost_http_hooks_enabled(std::string vhost) -{ - return http_hooks_enabled_; -} - -SrsConfDirective *MockAppConfig::get_vhost_on_stop(std::string vhost) -{ - return on_stop_directive_; -} - -SrsConfDirective *MockAppConfig::get_vhost_on_unpublish(std::string vhost) -{ - return on_unpublish_directive_; -} - -SrsConfDirective *MockAppConfig::get_vhost_on_dvr(std::string vhost) -{ - return NULL; -} - -bool MockAppConfig::get_rtc_nack_enabled(std::string vhost) -{ - return rtc_nack_enabled_; -} - -bool MockAppConfig::get_rtc_nack_no_copy(std::string vhost) -{ - return rtc_nack_no_copy_; -} - -bool MockAppConfig::get_realtime_enabled(std::string vhost, bool is_rtc) -{ - return true; -} - -int MockAppConfig::get_mw_msgs(std::string vhost, bool is_realtime, bool is_rtc) -{ - return mw_msgs_; -} - -int MockAppConfig::get_rtc_drop_for_pt(std::string vhost) -{ - return rtc_drop_for_pt_; -} - -bool MockAppConfig::get_rtc_twcc_enabled(std::string vhost) -{ - return rtc_twcc_enabled_; -} - -bool MockAppConfig::get_srt_enabled() -{ - return srt_enabled_; -} - -bool MockAppConfig::get_srt_enabled(std::string vhost) -{ - return srt_enabled_; -} - -std::string MockAppConfig::get_srt_default_streamid() -{ - return "#!::r=live/livestream,m=request"; -} - -bool MockAppConfig::get_srt_to_rtmp(std::string vhost) -{ - return srt_to_rtmp_; -} - -bool MockAppConfig::get_rtc_to_rtmp(std::string vhost) -{ - return rtc_to_rtmp_; -} - -srs_utime_t MockAppConfig::get_rtc_stun_timeout(std::string vhost) -{ - return 30 * SRS_UTIME_SECONDS; -} - -bool MockAppConfig::get_rtc_stun_strict_check(std::string vhost) -{ - return false; -} - -std::string MockAppConfig::get_rtc_dtls_role(std::string vhost) -{ - return rtc_dtls_role_; -} - -std::string MockAppConfig::get_rtc_dtls_version(std::string vhost) -{ - return "auto"; -} - -SrsConfDirective *MockAppConfig::get_vhost_on_hls(std::string vhost) -{ - return NULL; -} - -SrsConfDirective *MockAppConfig::get_vhost_on_hls_notify(std::string vhost) -{ - return NULL; -} - -bool MockAppConfig::get_hls_enabled(std::string vhost) -{ - return false; -} - -bool MockAppConfig::get_hls_enabled(SrsConfDirective *vhost) -{ - return false; -} - -bool MockAppConfig::get_hls_use_fmp4(std::string vhost) -{ - return false; -} - -std::string MockAppConfig::get_hls_entry_prefix(std::string vhost) -{ - return ""; -} - -std::string MockAppConfig::get_hls_path(std::string vhost) -{ - return "./objs/nginx/html"; -} - -std::string MockAppConfig::get_hls_m3u8_file(std::string vhost) -{ - return "[app]/[stream].m3u8"; -} - -std::string MockAppConfig::get_hls_ts_file(std::string vhost) -{ - return "[app]/[stream]-[seq].ts"; -} - -std::string MockAppConfig::get_hls_fmp4_file(std::string vhost) -{ - return "[app]/[stream]-[seq].m4s"; -} - -std::string MockAppConfig::get_hls_init_file(std::string vhost) -{ - return "[app]/[stream]-init.mp4"; -} - -bool MockAppConfig::get_hls_ts_floor(std::string vhost) -{ - return false; -} - -srs_utime_t MockAppConfig::get_hls_fragment(std::string vhost) -{ - return 10 * SRS_UTIME_SECONDS; -} - -double MockAppConfig::get_hls_td_ratio(std::string vhost) -{ - return 1.5; -} - -double MockAppConfig::get_hls_aof_ratio(std::string vhost) -{ - return 2.0; -} - -srs_utime_t MockAppConfig::get_hls_window(std::string vhost) -{ - return 60 * SRS_UTIME_SECONDS; -} - -std::string MockAppConfig::get_hls_on_error(std::string vhost) -{ - return "continue"; -} - -bool MockAppConfig::get_hls_cleanup(std::string vhost) -{ - return true; -} - -srs_utime_t MockAppConfig::get_hls_dispose(std::string vhost) -{ - return 120 * SRS_UTIME_SECONDS; -} - -bool MockAppConfig::get_hls_wait_keyframe(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_hls_keys(std::string vhost) -{ - return false; -} - -int MockAppConfig::get_hls_fragments_per_key(std::string vhost) -{ - return 5; -} - -std::string MockAppConfig::get_hls_key_file(std::string vhost) -{ - return "[app]/[stream]-[seq].key"; -} - -std::string MockAppConfig::get_hls_key_file_path(std::string vhost) -{ - return "./objs/nginx/html"; -} - -std::string MockAppConfig::get_hls_key_url(std::string vhost) -{ - return ""; -} - -int MockAppConfig::get_vhost_hls_nb_notify(std::string vhost) -{ - return 64; -} - -bool MockAppConfig::get_vhost_hls_dts_directly(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_hls_ctx_enabled(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_hls_ts_ctx_enabled(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_hls_master_m3u8_path_relative(std::string vhost) -{ - return false; -} - -bool MockAppConfig::get_hls_recover(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_forward_enabled(std::string vhost) -{ - return forwards_directive_ != NULL || backend_directive_ != NULL; -} - -SrsConfDirective *MockAppConfig::get_forwards(std::string vhost) -{ - return forwards_directive_; -} - -srs_utime_t MockAppConfig::get_queue_length(std::string vhost) -{ - return 30 * SRS_UTIME_SECONDS; -} - -SrsConfDirective *MockAppConfig::get_forward_backend(std::string vhost) -{ - return backend_directive_; -} - -bool MockAppConfig::get_atc(std::string vhost) -{ - return false; -} - -int MockAppConfig::get_time_jitter(std::string vhost) -{ - return SrsRtmpJitterAlgorithmFULL; -} - -bool MockAppConfig::get_mix_correct(std::string vhost) -{ - return false; -} - -bool MockAppConfig::try_annexb_first(std::string vhost) -{ - return true; -} - -bool MockAppConfig::get_vhost_is_edge(std::string vhost) -{ - return false; -} - -bool MockAppConfig::get_atc_auto(std::string vhost) -{ - return false; -} - -bool MockAppConfig::get_reduce_sequence_header(std::string vhost) -{ - return false; -} - -bool MockAppConfig::get_parse_sps(std::string vhost) -{ - return true; -} - -void MockAppConfig::set_http_hooks_enabled(bool enabled) -{ - http_hooks_enabled_ = enabled; -} - -void MockAppConfig::set_on_stop_urls(const std::vector &urls) -{ - clear_on_stop_directive(); - if (!urls.empty()) { - on_stop_directive_ = new SrsConfDirective(); - on_stop_directive_->name_ = "on_stop"; - on_stop_directive_->args_ = urls; - } -} - -void MockAppConfig::clear_on_stop_directive() -{ - srs_freep(on_stop_directive_); -} - -void MockAppConfig::set_on_unpublish_urls(const std::vector &urls) -{ - clear_on_unpublish_directive(); - if (!urls.empty()) { - on_unpublish_directive_ = new SrsConfDirective(); - on_unpublish_directive_->name_ = "on_unpublish"; - on_unpublish_directive_->args_ = urls; - } -} - -void MockAppConfig::clear_on_unpublish_directive() -{ - srs_freep(on_unpublish_directive_); -} - -void MockAppConfig::set_rtc_nack_enabled(bool enabled) -{ - rtc_nack_enabled_ = enabled; -} - -void MockAppConfig::set_rtc_nack_no_copy(bool no_copy) -{ - rtc_nack_no_copy_ = no_copy; -} - -void MockAppConfig::set_rtc_drop_for_pt(int pt) -{ - rtc_drop_for_pt_ = pt; -} - -void MockAppConfig::set_rtc_twcc_enabled(bool enabled) -{ - rtc_twcc_enabled_ = enabled; -} - -void MockAppConfig::set_srt_enabled(bool enabled) -{ - srt_enabled_ = enabled; -} - -void MockAppConfig::set_rtc_to_rtmp(bool enabled) -{ - rtc_to_rtmp_ = enabled; -} - -void MockAppConfig::set_api_as_candidates(bool enabled) -{ - api_as_candidates_ = enabled; -} - -void MockAppConfig::set_resolve_api_domain(bool enabled) -{ - resolve_api_domain_ = enabled; -} - -void MockAppConfig::set_keep_api_domain(bool enabled) -{ - keep_api_domain_ = enabled; -} - -bool MockAppConfig::get_security_enabled(std::string vhost) -{ - return false; -} - -SrsConfDirective *MockAppConfig::get_security_rules(std::string vhost) -{ - return NULL; -} - // Mock RTC packet receiver implementation MockRtcPacketReceiver::MockRtcPacketReceiver() { @@ -1160,6 +705,7 @@ MockLiveSource::MockLiveSource() on_audio_count_ = 0; on_video_count_ = 0; on_dump_packets_count_ = 0; + on_frame_count_ = 0; } MockLiveSource::~MockLiveSource() @@ -1196,16 +742,25 @@ srs_error_t MockLiveSource::consumer_dumps(ISrsLiveConsumer *consumer, bool ds, srs_error_t MockLiveSource::on_audio(SrsRtmpCommonMessage *audio) { - on_audio_count_++; return SrsLiveSource::on_audio(audio); } srs_error_t MockLiveSource::on_video(SrsRtmpCommonMessage *video) { - on_video_count_++; return SrsLiveSource::on_video(video); } +srs_error_t MockLiveSource::on_frame(SrsMediaPacket *msg) +{ + on_frame_count_++; + if (msg->is_audio()) { + on_audio_count_++; + } else if (msg->is_video()) { + on_video_count_++; + } + return SrsLiveSource::on_frame(msg); +} + // Mock SRT source implementation MockSrtSource::MockSrtSource() { @@ -1360,6 +915,19 @@ MockRtmpServer::~MockRtmpServer() recv_msgs_.clear(); } +void MockRtmpServer::set_request(SrsRtmpConnType type, std::string ip, std::string vhost, std::string app, std::string stream, std::string tcUrl, std::string schema, int port, std::string host) +{ + type_ = type; + ip_ = ip; + vhost_ = vhost; + app_ = app; + stream_ = stream; + tcUrl_ = tcUrl; + schema_ = schema; + port_ = port; + host_ = host; +} + void MockRtmpServer::set_recv_timeout(srs_utime_t tm) { } @@ -2464,6 +2032,31 @@ void MockOriginHub::set_on_forwarder_start_error(srs_error_t err) on_forwarder_start_error_ = srs_error_copy(err); } +// MockAudioCache implementation +MockAudioCache::MockAudioCache() +{ + process_packet_count_ = 0; +} + +MockAudioCache::~MockAudioCache() +{ +} + +srs_error_t MockAudioCache::process_packet(SrsRtpPacket *src, std::vector &ready_packets) +{ + process_packet_count_++; + + // Copy the packet. + SrsRtpPacket *copy = src->copy(); + ready_packets.push_back(copy); + + return srs_success; +} + +void MockAudioCache::clear_all() +{ +} + // Mock ISrsBasicRtmpClient implementation MockRtmpClient::MockRtmpClient() { @@ -2625,3 +2218,51 @@ void MockRtmpClient::set_url(std::string url) { url_ = url; } + +MockAudioTranscoder::MockAudioTranscoder() +{ + transcode_count_ = 0; + // Set default AAC header for mock transcoder + aac_header_ = std::string("\xAF\x00\x12\x10", 4); +} + +MockAudioTranscoder::~MockAudioTranscoder() +{ +} + +srs_error_t MockAudioTranscoder::initialize(SrsAudioCodecId from, SrsAudioCodecId to, int channels, int sample_rate, int bit_rate) +{ + return srs_success; +} + +srs_error_t MockAudioTranscoder::transcode(SrsParsedAudioPacket *in, std::vector &outs) +{ + transcode_count_++; + + SrsParsedAudioPacket *out = in->copy(); + output_packets_.push_back(out); + outs.push_back(out); + + return srs_success; +} + +void MockAudioTranscoder::free_frames(std::vector &frames) +{ + for (std::vector::iterator it = frames.begin(); it != frames.end(); ++it) { + SrsParsedAudioPacket *p = *it; + srs_freep(p); + } +} + +void MockAudioTranscoder::aac_codec_header(uint8_t **data, int *len) +{ + int size = aac_header_.size(); + if (size <= 0) { + return; + } + + uint8_t *copy = new uint8_t[size]; + memcpy(copy, aac_header_.data(), size); + *data = copy; + *len = size; +} diff --git a/trunk/src/utest/srs_utest_manual_mock.hpp b/trunk/src/utest/srs_utest_manual_mock.hpp index 0fbd96d9a..f1c5564f8 100644 --- a/trunk/src/utest/srs_utest_manual_mock.hpp +++ b/trunk/src/utest/srs_utest_manual_mock.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,11 @@ public: uint32_t video_ssrc_; uint32_t screen_ssrc_; +public: + uint8_t audio_pt_; + uint8_t video_pt_; + uint8_t screen_pt_; + public: // Create a map of track descriptions with audio and video tracks (for play stream) std::map create_audio_video_tracks(); @@ -151,6 +157,20 @@ public: virtual ISrsRequest *as_http(); }; +// Mock RTC source for testing +class MockRtcSource : public SrsRtcSource +{ +public: + int on_rtp_count_; + +public: + MockRtcSource(); + virtual ~MockRtcSource(); + +public: + virtual srs_error_t on_rtp(SrsRtpPacket *pkt); +}; + // Mock RTC source manager for testing class MockRtcSourceManager : public ISrsRtcSourceManager { @@ -269,20 +289,74 @@ public: bool rtc_from_rtmp_; SrsConfDirective *forwards_directive_; SrsConfDirective *backend_directive_; + bool rtc_server_enabled_; + bool rtc_enabled_; + bool rtc_init_rate_from_sdp_; public: - MockAppConfig(); - virtual ~MockAppConfig(); + MockAppConfig() + { + http_hooks_enabled_ = true; + on_stop_directive_ = NULL; + on_unpublish_directive_ = NULL; + rtc_nack_enabled_ = true; + rtc_nack_no_copy_ = false; + rtc_drop_for_pt_ = 0; + rtc_twcc_enabled_ = true; + srt_enabled_ = false; + rtc_to_rtmp_ = false; + dash_dispose_ = 0; + dash_enabled_ = false; + api_as_candidates_ = true; + resolve_api_domain_ = true; + keep_api_domain_ = false; + mw_msgs_ = 8; + mw_sleep_ = 350 * SRS_UTIME_MILLISECONDS; + rtc_dtls_role_ = "passive"; + default_vhost_ = NULL; + srt_to_rtmp_ = true; + rtc_from_rtmp_ = false; + forwards_directive_ = NULL; + backend_directive_ = NULL; + rtc_server_enabled_ = false; + rtc_enabled_ = false; + rtc_init_rate_from_sdp_ = false; + } + virtual ~MockAppConfig() + { + clear_on_stop_directive(); + clear_on_unpublish_directive(); + + srs_freep(default_vhost_); + srs_freep(forwards_directive_); + srs_freep(backend_directive_); + } public: // Helper methods for setting forward configuration - void set_forward_destinations(const std::vector &destinations); - void set_forward_backend(const std::string &backend_url); + void set_forward_destinations(const std::vector &destinations) + { + srs_freep(forwards_directive_); + if (!destinations.empty()) { + forwards_directive_ = new SrsConfDirective(); + forwards_directive_->name_ = "destination"; + forwards_directive_->args_ = destinations; + } + } + void set_forward_backend(const std::string &backend_url) + { + srs_freep(backend_directive_); + if (!backend_url.empty()) { + backend_directive_ = new SrsConfDirective(); + backend_directive_->name_ = "backend"; + backend_directive_->args_.push_back(backend_url); + } + } // ISrsConfig methods - virtual srs_utime_t get_pithy_print(); - virtual std::string get_default_app_name(); - virtual void subscribe(ISrsReloadHandler *handler); - virtual void unsubscribe(ISrsReloadHandler *handler); + srs_utime_t get_pithy_print() { return 10 * SRS_UTIME_SECONDS; } + std::string get_default_app_name() { return "live"; } + void subscribe(ISrsReloadHandler *handler) {} + void unsubscribe(ISrsReloadHandler *handler) {} virtual srs_error_t reload(SrsReloadState *pstate) { return srs_success; } virtual srs_error_t persistence() { return srs_success; } virtual std::string config() { return ""; } @@ -322,7 +396,7 @@ public: virtual std::string get_https_stream_ssl_cert() { return ""; } virtual std::string get_http_stream_dir() { return ""; } virtual bool get_http_stream_crossdomain() { return false; } - virtual bool get_rtc_server_enabled() { return false; } + virtual bool get_rtc_server_enabled() { return rtc_server_enabled_; } virtual bool get_rtc_server_tcp_enabled() { return false; } virtual std::vector get_rtc_server_tcp_listens() { @@ -402,74 +476,75 @@ public: virtual SrsConfDirective *get_vhost_on_close(std::string vhost) { return NULL; } virtual SrsConfDirective *get_vhost_on_publish(std::string vhost) { return NULL; } virtual SrsConfDirective *get_vhost_on_play(std::string vhost) { return NULL; } - virtual bool get_rtc_enabled(std::string vhost) { return false; } + virtual bool get_rtc_enabled(std::string vhost) { return rtc_enabled_; } virtual bool get_rtsp_enabled(std::string vhost) { return false; } virtual bool get_rtc_from_rtmp(std::string vhost) { return rtc_from_rtmp_; } virtual bool get_rtsp_from_rtmp(std::string vhost) { return false; } // ISrsAppConfig methods - virtual bool get_vhost_http_hooks_enabled(std::string vhost); - virtual SrsConfDirective *get_vhost_on_stop(std::string vhost); - virtual SrsConfDirective *get_vhost_on_unpublish(std::string vhost); - virtual SrsConfDirective *get_vhost_on_dvr(std::string vhost); - virtual bool get_rtc_nack_enabled(std::string vhost); - virtual bool get_rtc_nack_no_copy(std::string vhost); - virtual bool get_realtime_enabled(std::string vhost, bool is_rtc); - virtual int get_mw_msgs(std::string vhost, bool is_realtime, bool is_rtc); - virtual int get_rtc_drop_for_pt(std::string vhost); - virtual bool get_rtc_twcc_enabled(std::string vhost); - virtual bool get_srt_enabled(); - virtual bool get_srt_enabled(std::string vhost); - virtual std::string get_srt_default_streamid(); - virtual bool get_srt_to_rtmp(std::string vhost); - virtual bool get_rtc_to_rtmp(std::string vhost); - virtual srs_utime_t get_rtc_stun_timeout(std::string vhost); - virtual bool get_rtc_stun_strict_check(std::string vhost); - virtual std::string get_rtc_dtls_role(std::string vhost); - virtual std::string get_rtc_dtls_version(std::string vhost); - virtual SrsConfDirective *get_vhost_on_hls(std::string vhost); - virtual SrsConfDirective *get_vhost_on_hls_notify(std::string vhost); + virtual bool get_vhost_http_hooks_enabled(std::string vhost) { return http_hooks_enabled_; } + virtual SrsConfDirective *get_vhost_on_stop(std::string vhost) { return on_stop_directive_; } + virtual SrsConfDirective *get_vhost_on_unpublish(std::string vhost) { return on_unpublish_directive_; } + virtual SrsConfDirective *get_vhost_on_dvr(std::string vhost) { return NULL; } + virtual bool get_rtc_nack_enabled(std::string vhost) { return rtc_nack_enabled_; } + virtual bool get_rtc_nack_no_copy(std::string vhost) { return rtc_nack_no_copy_; } + virtual bool get_realtime_enabled(std::string vhost, bool is_rtc) { return true; } + virtual int get_mw_msgs(std::string vhost, bool is_realtime, bool is_rtc) { return mw_msgs_; } + virtual int get_rtc_drop_for_pt(std::string vhost) { return rtc_drop_for_pt_; } + virtual bool get_rtc_twcc_enabled(std::string vhost) { return rtc_twcc_enabled_; } + virtual bool get_rtc_init_rate_from_sdp(std::string vhost) { return rtc_init_rate_from_sdp_; } + virtual bool get_srt_enabled() { return srt_enabled_; } + virtual bool get_srt_enabled(std::string vhost) { return srt_enabled_; } + virtual std::string get_srt_default_streamid() { return "#!::r=live/livestream,m=request"; } + virtual bool get_srt_to_rtmp(std::string vhost) { return srt_to_rtmp_; } + virtual bool get_rtc_to_rtmp(std::string vhost) { return rtc_to_rtmp_; } + virtual srs_utime_t get_rtc_stun_timeout(std::string vhost) { return 30 * SRS_UTIME_SECONDS; } + virtual bool get_rtc_stun_strict_check(std::string vhost) { return false; } + virtual std::string get_rtc_dtls_role(std::string vhost) { return rtc_dtls_role_; } + virtual std::string get_rtc_dtls_version(std::string vhost) { return "auto"; } + virtual SrsConfDirective *get_vhost_on_hls(std::string vhost) { return NULL; } + virtual SrsConfDirective *get_vhost_on_hls_notify(std::string vhost) { return NULL; } // HLS methods - virtual bool get_hls_enabled(std::string vhost); - virtual bool get_hls_enabled(SrsConfDirective *vhost); - virtual bool get_hls_use_fmp4(std::string vhost); - virtual std::string get_hls_entry_prefix(std::string vhost); - virtual std::string get_hls_path(std::string vhost); - virtual std::string get_hls_m3u8_file(std::string vhost); - virtual std::string get_hls_ts_file(std::string vhost); - virtual std::string get_hls_fmp4_file(std::string vhost); - virtual std::string get_hls_init_file(std::string vhost); - virtual bool get_hls_ts_floor(std::string vhost); - virtual srs_utime_t get_hls_fragment(std::string vhost); - virtual double get_hls_td_ratio(std::string vhost); - virtual double get_hls_aof_ratio(std::string vhost); - virtual srs_utime_t get_hls_window(std::string vhost); - virtual std::string get_hls_on_error(std::string vhost); - virtual bool get_hls_cleanup(std::string vhost); - virtual srs_utime_t get_hls_dispose(std::string vhost); - virtual bool get_hls_wait_keyframe(std::string vhost); - virtual bool get_hls_keys(std::string vhost); - virtual int get_hls_fragments_per_key(std::string vhost); - virtual std::string get_hls_key_file(std::string vhost); - virtual std::string get_hls_key_file_path(std::string vhost); - virtual std::string get_hls_key_url(std::string vhost); - virtual int get_vhost_hls_nb_notify(std::string vhost); - virtual bool get_vhost_hls_dts_directly(std::string vhost); - virtual bool get_hls_ctx_enabled(std::string vhost); - virtual bool get_hls_ts_ctx_enabled(std::string vhost); - virtual bool get_hls_master_m3u8_path_relative(std::string vhost); - virtual bool get_hls_recover(std::string vhost); - virtual bool get_forward_enabled(std::string vhost); - virtual SrsConfDirective *get_forwards(std::string vhost); - virtual srs_utime_t get_queue_length(std::string vhost); - virtual SrsConfDirective *get_forward_backend(std::string vhost); - virtual bool get_atc(std::string vhost); - virtual int get_time_jitter(std::string vhost); - virtual bool get_mix_correct(std::string vhost); - virtual bool try_annexb_first(std::string vhost); - virtual bool get_vhost_is_edge(std::string vhost); - virtual bool get_atc_auto(std::string vhost); - virtual bool get_reduce_sequence_header(std::string vhost); - virtual bool get_parse_sps(std::string vhost); + virtual bool get_hls_enabled(std::string vhost) { return false; } + virtual bool get_hls_enabled(SrsConfDirective *vhost) { return false; } + virtual bool get_hls_use_fmp4(std::string vhost) { return false; } + virtual std::string get_hls_entry_prefix(std::string vhost) { return ""; } + virtual std::string get_hls_path(std::string vhost) { return "./objs/nginx/html"; } + virtual std::string get_hls_m3u8_file(std::string vhost) { return "[app]/[stream].m3u8"; } + virtual std::string get_hls_ts_file(std::string vhost) { return "[app]/[stream]-[seq].ts"; } + virtual std::string get_hls_fmp4_file(std::string vhost) { return "[app]/[stream]-[seq].m4s"; } + virtual std::string get_hls_init_file(std::string vhost) { return "[app]/[stream]-init.mp4"; } + virtual bool get_hls_ts_floor(std::string vhost) { return false; } + virtual srs_utime_t get_hls_fragment(std::string vhost) { return 10 * SRS_UTIME_SECONDS; } + virtual double get_hls_td_ratio(std::string vhost) { return 1.5; } + virtual double get_hls_aof_ratio(std::string vhost) { return 2.0; } + virtual srs_utime_t get_hls_window(std::string vhost) { return 60 * SRS_UTIME_SECONDS; } + virtual std::string get_hls_on_error(std::string vhost) { return "continue"; } + virtual bool get_hls_cleanup(std::string vhost) { return true; } + virtual srs_utime_t get_hls_dispose(std::string vhost) { return 120 * SRS_UTIME_SECONDS; } + virtual bool get_hls_wait_keyframe(std::string vhost) { return true; } + virtual bool get_hls_keys(std::string vhost) { return false; } + virtual int get_hls_fragments_per_key(std::string vhost) { return 5; } + virtual std::string get_hls_key_file(std::string vhost) { return "[app]/[stream]-[seq].key"; } + virtual std::string get_hls_key_file_path(std::string vhost) { return "./objs/nginx/html"; } + virtual std::string get_hls_key_url(std::string vhost) { return ""; } + virtual int get_vhost_hls_nb_notify(std::string vhost) { return 64; } + virtual bool get_vhost_hls_dts_directly(std::string vhost) { return true; } + virtual bool get_hls_ctx_enabled(std::string vhost) { return true; } + virtual bool get_hls_ts_ctx_enabled(std::string vhost) { return true; } + virtual bool get_hls_master_m3u8_path_relative(std::string vhost) { return false; } + virtual bool get_hls_recover(std::string vhost) { return true; } + virtual bool get_forward_enabled(std::string vhost) { return forwards_directive_ != NULL || backend_directive_ != NULL; } + virtual SrsConfDirective *get_forwards(std::string vhost) { return forwards_directive_; } + virtual srs_utime_t get_queue_length(std::string vhost) { return 30 * SRS_UTIME_SECONDS; } + virtual SrsConfDirective *get_forward_backend(std::string vhost) { return backend_directive_; } + virtual bool get_atc(std::string vhost) { return false; } + virtual int get_time_jitter(std::string vhost) { return SrsRtmpJitterAlgorithmFULL; } + virtual bool get_mix_correct(std::string vhost) { return false; } + virtual bool try_annexb_first(std::string vhost) { return true; } + virtual bool get_vhost_is_edge(std::string vhost) { return false; } + virtual bool get_atc_auto(std::string vhost) { return false; } + virtual bool get_reduce_sequence_header(std::string vhost) { return false; } + virtual bool get_parse_sps(std::string vhost) { return true; } // DVR methods virtual std::string get_dvr_path(std::string vhost) { return "./[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv"; } virtual std::string get_dvr_plan(std::string vhost) { return "session"; } @@ -541,22 +616,38 @@ public: virtual std::vector get_engine_aparams(SrsConfDirective *conf) { return std::vector(); } virtual std::string get_engine_oformat(SrsConfDirective *conf) { return ""; } virtual std::string get_engine_output(SrsConfDirective *conf) { return ""; } - void set_http_hooks_enabled(bool enabled); - void set_on_stop_urls(const std::vector &urls); - void clear_on_stop_directive(); - void set_on_unpublish_urls(const std::vector &urls); - void clear_on_unpublish_directive(); - void set_rtc_nack_enabled(bool enabled); - void set_rtc_nack_no_copy(bool no_copy); - void set_rtc_drop_for_pt(int pt); - void set_rtc_twcc_enabled(bool enabled); - void set_srt_enabled(bool enabled); - void set_rtc_to_rtmp(bool enabled); - void set_api_as_candidates(bool enabled); - void set_resolve_api_domain(bool enabled); - void set_keep_api_domain(bool enabled); - virtual bool get_security_enabled(std::string vhost); - virtual SrsConfDirective *get_security_rules(std::string vhost); + void set_http_hooks_enabled(bool enabled) { http_hooks_enabled_ = enabled; } + void set_on_stop_urls(const std::vector &urls) + { + clear_on_stop_directive(); + if (!urls.empty()) { + on_stop_directive_ = new SrsConfDirective(); + on_stop_directive_->name_ = "on_stop"; + on_stop_directive_->args_ = urls; + } + } + void clear_on_stop_directive() { srs_freep(on_stop_directive_); } + void set_on_unpublish_urls(const std::vector &urls) + { + clear_on_unpublish_directive(); + if (!urls.empty()) { + on_unpublish_directive_ = new SrsConfDirective(); + on_unpublish_directive_->name_ = "on_unpublish"; + on_unpublish_directive_->args_ = urls; + } + } + void clear_on_unpublish_directive() { srs_freep(on_unpublish_directive_); } + void set_rtc_nack_enabled(bool enabled) { rtc_nack_enabled_ = enabled; } + void set_rtc_nack_no_copy(bool no_copy) { rtc_nack_no_copy_ = no_copy; } + void set_rtc_drop_for_pt(int pt) { rtc_drop_for_pt_ = pt; } + void set_rtc_twcc_enabled(bool enabled) { rtc_twcc_enabled_ = enabled; } + void set_srt_enabled(bool enabled) { srt_enabled_ = enabled; } + void set_rtc_to_rtmp(bool enabled) { rtc_to_rtmp_ = enabled; } + void set_api_as_candidates(bool enabled) { api_as_candidates_ = enabled; } + void set_resolve_api_domain(bool enabled) { resolve_api_domain_ = enabled; } + void set_keep_api_domain(bool enabled) { keep_api_domain_ = enabled; } + bool get_security_enabled(std::string vhost) { return false; } + SrsConfDirective *get_security_rules(std::string vhost) { return NULL; } }; // Mock RTC packet receiver for testing SrsRtcPublishStream @@ -634,6 +725,7 @@ public: int on_audio_count_; int on_video_count_; int on_dump_packets_count_; + int on_frame_count_; public: MockLiveSource(); @@ -647,6 +739,7 @@ public: public: virtual srs_error_t on_audio(SrsRtmpCommonMessage *audio); virtual srs_error_t on_video(SrsRtmpCommonMessage *video); + virtual srs_error_t on_frame(SrsMediaPacket *msg); }; // Mock SRT source for testing SrsRtcPublishStream @@ -743,6 +836,9 @@ public: MockRtmpServer(); virtual ~MockRtmpServer(); +public: + void set_request(SrsRtmpConnType type, std::string ip, std::string vhost, std::string app, std::string stream, std::string tcUrl, std::string schema, int port, std::string host); + public: virtual void set_recv_timeout(srs_utime_t tm); virtual void set_send_timeout(srs_utime_t tm); @@ -1104,6 +1200,21 @@ public: void set_on_dvr_request_sh_error(srs_error_t err); }; +// Mock audio cache for ISrsRtcFrameBuilderAudioPacketCache +class MockAudioCache : public ISrsRtcFrameBuilderAudioPacketCache +{ +public: + int process_packet_count_; + +public: + MockAudioCache(); + virtual ~MockAudioCache(); + +public: + virtual srs_error_t process_packet(SrsRtpPacket *src, std::vector &ready_packets); + virtual void clear_all(); +}; + // Mock ISrsBasicRtmpClient for testing SrsForwarder class MockRtmpClient : public ISrsBasicRtmpClient { @@ -1157,4 +1268,23 @@ public: virtual void set_url(std::string url); }; +// Mock the audio transcoder ISrsAudioTranscoder. +class MockAudioTranscoder : public ISrsAudioTranscoder +{ +public: + int transcode_count_; + std::vector output_packets_; + std::string aac_header_; + +public: + MockAudioTranscoder(); + virtual ~MockAudioTranscoder(); + +public: + virtual srs_error_t initialize(SrsAudioCodecId from, SrsAudioCodecId to, int channels, int sample_rate, int bit_rate); + virtual srs_error_t transcode(SrsParsedAudioPacket *in, std::vector &outs); + virtual void free_frames(std::vector &frames); + virtual void aac_codec_header(uint8_t **data, int *len); +}; + #endif diff --git a/trunk/src/utest/srs_utest_manual_rtc.cpp b/trunk/src/utest/srs_utest_manual_rtc.cpp index 0416512b1..393a6c321 100644 --- a/trunk/src/utest/srs_utest_manual_rtc.cpp +++ b/trunk/src/utest/srs_utest_manual_rtc.cpp @@ -1607,7 +1607,7 @@ VOID TEST(KernelRTCTest, DefaultTrackStatus) ds.type_ = "audio"; ds.id_ = "NSNWOn19NDn12o8nNeji2"; ds.ssrc_ = 100; - audio = new SrsRtcAudioRecvTrack(&mock_receiver, &ds); + audio = new SrsRtcAudioRecvTrack(&mock_receiver, &ds, false); publish->audio_tracks_.push_back(audio); } if (true) { @@ -1615,7 +1615,7 @@ VOID TEST(KernelRTCTest, DefaultTrackStatus) ds.type_ = "video"; ds.id_ = "VMo22nfLDn122nfnDNL2"; ds.ssrc_ = 200; - video = new SrsRtcVideoRecvTrack(&mock_receiver, &ds); + video = new SrsRtcVideoRecvTrack(&mock_receiver, &ds, false); publish->video_tracks_.push_back(video); } EXPECT_FALSE(audio->get_track_status()); @@ -1668,7 +1668,7 @@ VOID TEST(KernelRTCTest, SyncTimestampBySenderReportNormal) video_ds.id_ = "VMo22nfLDn122nfnDNL2"; video_ds.ssrc_ = 200; - SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds); + SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds, false); publish.video_tracks_.push_back(video); publish.set_all_tracks_status(true); @@ -1736,7 +1736,7 @@ VOID TEST(KernelRTCTest, SyncTimestampBySenderReportOutOfOrder) video_ds.id_ = "VMo22nfLDn122nfnDNL2"; video_ds.ssrc_ = 200; - SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds); + SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds, false); publish.video_tracks_.push_back(video); publish.set_all_tracks_status(true); @@ -1809,7 +1809,7 @@ VOID TEST(KernelRTCTest, SyncTimestampBySenderReportConsecutive) video_ds.id_ = "VMo22nfLDn122nfnDNL2"; video_ds.ssrc_ = 200; - SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds); + SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds, false); publish.video_tracks_.push_back(video); publish.set_all_tracks_status(true); @@ -1915,7 +1915,7 @@ VOID TEST(KernelRTCTest, SyncTimestampBySenderReportDuplicated) video_ds.id_ = "VMo22nfLDn122nfnDNL2"; video_ds.ssrc_ = 200; - SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds); + SrsRtcVideoRecvTrack *video = new SrsRtcVideoRecvTrack(&mock_receiver, &video_ds, false); publish.video_tracks_.push_back(video); publish.set_all_tracks_status(true); diff --git a/trunk/src/utest/srs_utest_manual_rtc_recv_track.cpp b/trunk/src/utest/srs_utest_manual_rtc_recv_track.cpp index e6e95b72e..0daeab9de 100644 --- a/trunk/src/utest/srs_utest_manual_rtc_recv_track.cpp +++ b/trunk/src/utest/srs_utest_manual_rtc_recv_track.cpp @@ -78,7 +78,7 @@ public: } MockSrsRtcRecvTrack() - : SrsRtcRecvTrack(nullptr, create_default_track_desc(), true) {} // true for is_audio + : SrsRtcRecvTrack(nullptr, create_default_track_desc(), true, false) {} // true for is_audio, false for init_rate_from_sdp }; VOID TEST(RtcRecvTrackTest, OnNackBasicTest) diff --git a/trunk/src/utest/srs_utest_manual_st.cpp b/trunk/src/utest/srs_utest_manual_st.cpp index ddd19c26b..c9715075b 100644 --- a/trunk/src/utest/srs_utest_manual_st.cpp +++ b/trunk/src/utest/srs_utest_manual_st.cpp @@ -43,9 +43,9 @@ VOID TEST(StTest, StUtimeInMicroseconds) EXPECT_GT(st_time_1, 0); EXPECT_GT(st_time_2, 0); EXPECT_GE(st_time_2, st_time_1); - // st_time_2 - st_time_1 should be in range of [1, 1000] microseconds + // st_time_2 - st_time_1 should be in range of [1, 3000] microseconds EXPECT_GE(st_time_2 - st_time_1, 0); - EXPECT_LE(st_time_2 - st_time_1, 1000); + EXPECT_LE(st_time_2 - st_time_1, 3000); } static inline st_utime_t time_gettimeofday() diff --git a/trunk/src/utest/srs_utest_workflow_rtc2rtmp.cpp b/trunk/src/utest/srs_utest_workflow_rtc2rtmp.cpp new file mode 100644 index 000000000..2a44a1beb --- /dev/null +++ b/trunk/src/utest/srs_utest_workflow_rtc2rtmp.cpp @@ -0,0 +1,190 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2025 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Mock app factory for RTC to RTMP workflow testing +class MockAppFactoryForRtc2Rtmp : public SrsAppFactory +{ +public: + MockAudioCache *last_created_audio_cache_; + MockAudioTranscoder *last_created_audio_transcoder_; + +public: + MockAppFactoryForRtc2Rtmp() + { + last_created_audio_cache_ = NULL; + last_created_audio_transcoder_ = NULL; + } + + virtual ~MockAppFactoryForRtc2Rtmp() + { + // Don't delete last_created_audio_cache_ or last_created_audio_transcoder_ here, + // they are managed by frame builder + } + +#ifdef SRS_FFMPEG_FIT + virtual ISrsRtcFrameBuilderAudioPacketCache *create_rtc_frame_builder_audio_packet_cache() + { + // Create a new mock audio cache each time + MockAudioCache *cache = new MockAudioCache(); + last_created_audio_cache_ = cache; + return cache; + } + + virtual ISrsAudioTranscoder *create_audio_transcoder() + { + // Create a new mock audio transcoder each time + MockAudioTranscoder *transcoder = new MockAudioTranscoder(); + last_created_audio_transcoder_ = transcoder; + return transcoder; + } +#endif +}; + +// This test is used to verify the basic workflow of the RTC connection. +// It's finished with the help of AI, but each step is manually designed +// and verified. So this is not dominated by AI, but by humanbeing. +VOID TEST(BasicWorkflowRtc2RtmpTest, ManuallyVerifyTypicalScenario) +{ + srs_error_t err; + + // Create mock objects for dependencies + SrsUniquePtr mock_config(new MockAppConfig()); + SrsUniquePtr mock_rtc_sources(new MockRtcSourceManager()); + SrsUniquePtr mock_stat(new MockAppStatistic()); + SrsUniquePtr mock_request(new MockRtcAsyncCallRequest("test.vhost", "live", "stream1")); + SrsUniquePtr mock_exec(new MockRtcAsyncTaskExecutor()); + SrsUniquePtr mock_expire(new MockExpire()); + SrsUniquePtr mock_receiver(new MockRtcPacketReceiver()); + SrsUniquePtr track_factory(new MockRtcTrackDescriptionFactory()); + SrsUniquePtr mock_sources(new MockLiveSourceManager()); + SrsUniquePtr mock_factory(new MockAppFactoryForRtc2Rtmp()); + + mock_config->rtc_to_rtmp_ = true; + mock_config->rtc_init_rate_from_sdp_ = true; + + // Create RTC publish stream - use real pli_worker_ + SrsContextId cid; + cid.set_value("test-rtc2rtmp-workflow-typical-scenario"); + SrsUniquePtr publish_stream(new SrsRtcPublishStream(mock_exec.get(), mock_expire.get(), mock_receiver.get(), cid)); + + // Mock the publish stream object + if (true) { + // Inject mock dependencies + publish_stream->config_ = mock_config.get(); + publish_stream->rtc_sources_ = mock_rtc_sources.get(); + publish_stream->live_sources_ = mock_sources.get(); + publish_stream->stat_ = mock_stat.get(); + publish_stream->app_factory_ = mock_factory.get(); + } + + // Initialize publish stream, rtc2rtmp bridge should be created + SrsRtcBridge *bridge = NULL; + SrsLiveSource *live_source = NULL; + if (true) { + SrsUniquePtr stream_desc(track_factory->create_stream_description()); + + // Initialize the publish stream (it will take ownership of track descriptions) + HELPER_EXPECT_SUCCESS(publish_stream->initialize(mock_request.get(), stream_desc.get())); + + // Check the tracks, should be one audio track + EXPECT_EQ(publish_stream->audio_tracks_.size(), 1); + // Check the tracks, should be one video track + EXPECT_EQ(publish_stream->video_tracks_.size(), 1); + + // source bridge should be created + bridge = dynamic_cast(publish_stream->source_->rtc_bridge_); + EXPECT_TRUE(bridge != NULL); + + live_source = bridge->rtmp_target_.get(); + EXPECT_TRUE(live_source != NULL); + } + + // Start the publish stream. + SrsRtcFrameBuilder *frame_builder = NULL; + if (true) { + // Test: First call to start() should succeed + HELPER_EXPECT_SUCCESS(publish_stream->start()); + + // Wait for coroutine to start. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Verify is_sender_started_ flag is set + EXPECT_TRUE(publish_stream->is_sender_started_); + + // When starting the publish stream, the frame builder should be recreated + frame_builder = bridge->frame_builder_; + EXPECT_TRUE(frame_builder != NULL); + + // Verify the audio cache was created by the factory + EXPECT_TRUE(mock_factory->last_created_audio_cache_ != NULL); + EXPECT_EQ(frame_builder->audio_cache_, mock_factory->last_created_audio_cache_); + + // Verify the audio transcoder was created by the factory + EXPECT_TRUE(mock_factory->last_created_audio_transcoder_ != NULL); + EXPECT_EQ(frame_builder->audio_transcoder_, mock_factory->last_created_audio_transcoder_); + } + + // Got a RTP audio packet. + MockLiveSource *mock_source = dynamic_cast(mock_sources->mock_source_.get()); + if (true) { + SrsRtpPacket pkt; + pkt.header_.set_ssrc(track_factory->audio_ssrc_); + pkt.header_.set_sequence(100); + pkt.header_.set_timestamp(1000); + pkt.header_.set_payload_type(track_factory->audio_pt_); + + // Create fake audio payload. + SrsRtpRawPayload *raw = new SrsRtpRawPayload(); + pkt.set_payload(raw, SrsRtpPacketPayloadTypeRaw); + raw->payload_ = pkt.wrap(100); + raw->nn_payload_ = 100; + + SrsUniquePtr data(new char[1500]); + SrsBuffer buf(data.get(), 1500); + HELPER_EXPECT_SUCCESS(pkt.encode(&buf)); + + HELPER_EXPECT_SUCCESS(publish_stream->on_rtp_plaintext(data.get(), buf.pos())); + + // The live source should got 2 audio packets, one is sequence header, another is audio data. + EXPECT_EQ(mock_source->on_audio_count_, 2); + EXPECT_EQ(mock_source->on_frame_count_, 2); + EXPECT_EQ(mock_source->on_video_count_, 0); + } + + publish_stream->stop(); +} diff --git a/trunk/src/utest/srs_utest_workflow_rtc2rtmp.hpp b/trunk/src/utest/srs_utest_workflow_rtc2rtmp.hpp new file mode 100644 index 000000000..b2b6cf65a --- /dev/null +++ b/trunk/src/utest/srs_utest_workflow_rtc2rtmp.hpp @@ -0,0 +1,32 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2025 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SRS_UTEST_WORKFLOW_RTC2RTMP_HPP +#define SRS_UTEST_WORKFLOW_RTC2RTMP_HPP + +/* +#include +*/ +#include + +#endif diff --git a/trunk/src/utest/srs_utest_workflow_rtc_conn.hpp b/trunk/src/utest/srs_utest_workflow_rtc_conn.hpp index 1b9dc4d39..6ee035a6e 100644 --- a/trunk/src/utest/srs_utest_workflow_rtc_conn.hpp +++ b/trunk/src/utest/srs_utest_workflow_rtc_conn.hpp @@ -21,11 +21,11 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef SRS_UTEST_RTC_CONN_HPP -#define SRS_UTEST_RTC_CONN_HPP +#ifndef SRS_UTEST_WORKFLOW_RTC_CONN_HPP +#define SRS_UTEST_WORKFLOW_RTC_CONN_HPP /* -#include +#include */ #include diff --git a/trunk/src/utest/srs_utest_workflow_rtc_playstream.cpp b/trunk/src/utest/srs_utest_workflow_rtc_playstream.cpp index 4f756d241..cf582ab8d 100644 --- a/trunk/src/utest/srs_utest_workflow_rtc_playstream.cpp +++ b/trunk/src/utest/srs_utest_workflow_rtc_playstream.cpp @@ -221,9 +221,4 @@ VOID TEST(BasicWorkflowRtcPlayStreamTest, ManuallyVerify) // Stop the play stream play_stream->stop(); - - // Clean up - set to NULL to avoid double-free - play_stream->config_ = NULL; - play_stream->rtc_sources_ = NULL; - play_stream->stat_ = NULL; } diff --git a/trunk/src/utest/srs_utest_workflow_rtc_publishstream.cpp b/trunk/src/utest/srs_utest_workflow_rtc_publishstream.cpp index 5a8f48e57..1d8060a97 100644 --- a/trunk/src/utest/srs_utest_workflow_rtc_publishstream.cpp +++ b/trunk/src/utest/srs_utest_workflow_rtc_publishstream.cpp @@ -96,9 +96,4 @@ VOID TEST(BasicWorkflowRtcPublishStreamTest, ManuallyVerify) // Stop the publish stream publish_stream->stop(); - - // Clean up - set injected fields to NULL to avoid double-free - publish_stream->config_ = NULL; - publish_stream->rtc_sources_ = NULL; - publish_stream->stat_ = NULL; } diff --git a/trunk/src/utest/srs_utest_workflow_rtmp2rtc.cpp b/trunk/src/utest/srs_utest_workflow_rtmp2rtc.cpp new file mode 100644 index 000000000..0176fcdd0 --- /dev/null +++ b/trunk/src/utest/srs_utest_workflow_rtmp2rtc.cpp @@ -0,0 +1,250 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2025 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Mock app factory for RTMP to RTC workflow testing +class MockAppFactoryForRtmp2Rtc : public SrsAppFactory +{ +public: + MockAudioTranscoder *last_created_audio_transcoder_; + +public: + MockAppFactoryForRtmp2Rtc() + { + last_created_audio_transcoder_ = NULL; + } + + virtual ~MockAppFactoryForRtmp2Rtc() + { + // Don't delete last_created_audio_transcoder_ here, + // it is managed by RTP builder + } + +#ifdef SRS_FFMPEG_FIT + virtual ISrsAudioTranscoder *create_audio_transcoder() + { + // Create a new mock audio transcoder each time + MockAudioTranscoder *transcoder = new MockAudioTranscoder(); + last_created_audio_transcoder_ = transcoder; + return transcoder; + } +#endif +}; + +// This test is used to verify the basic workflow of the RTMP connection. +// It's finished with the help of AI, but each step is manually designed +// and verified. So this is not dominated by AI, but by humanbeing. +VOID TEST(BasicWorkflowRtmp2RtcTest, ManuallyVerifyTypicalScenario) +{ + srs_error_t err; + + // Mock all interface dependencies + SrsUniquePtr mock_factory(new MockAppFactoryForRtmp2Rtc()); + SrsUniquePtr mock_config(new MockAppConfig()); + SrsUniquePtr mock_manager(new MockConnectionManager()); + SrsUniquePtr mock_sources(new MockLiveSourceManager()); + SrsUniquePtr mock_tokens(new MockStreamPublishTokenManager()); + SrsUniquePtr mock_stat(new MockAppStatistic()); + SrsUniquePtr mock_hooks(new MockHttpHooks()); + SrsUniquePtr mock_rtc_sources(new MockRtcSourceManager()); + SrsUniquePtr mock_srt_sources(new MockSrtSourceManager()); +#ifdef SRS_RTSP + SrsUniquePtr mock_rtsp_sources(new MockRtspSourceManager()); +#endif + MockRtmpServer *mock_rtmp_server = new MockRtmpServer(); + MockSecurity *mock_security = new MockSecurity(); + + mock_config->default_vhost_ = new SrsConfDirective(); + mock_config->default_vhost_->name_ = "vhost"; + mock_config->default_vhost_->args_.push_back("__defaultVhost__"); + + mock_config->mw_msgs_ = 0; // Handle each RTMP message, no merging write. + mock_config->mw_sleep_ = 0; // Handle each RTMP message, no merging write. + + mock_config->rtc_server_enabled_ = true; + mock_config->rtc_enabled_ = true; + mock_config->rtc_from_rtmp_ = true; + + mock_rtmp_server->set_request(SrsRtmpConnFMLEPublish, "192.168.1.100", "utest.ossrs.io", "utest", "livestream", "rtmp://127.0.0.1/utest", "rtmp", 1935, "127.0.0.1"); + + // Create SrsRtmpConn - it takes ownership of transport + ISrsRtmpTransport *transport = new MockRtmpTransport(); + SrsUniquePtr conn(new SrsRtmpConn(transport, "192.168.1.100", 1935)); + + conn->app_factory_ = mock_factory.get(); + conn->config_ = mock_config.get(); + conn->manager_ = mock_manager.get(); + conn->live_sources_ = mock_sources.get(); + conn->stream_publish_tokens_ = mock_tokens.get(); + conn->stat_ = mock_stat.get(); + conn->hooks_ = mock_hooks.get(); + conn->rtc_sources_ = mock_rtc_sources.get(); + conn->srt_sources_ = mock_srt_sources.get(); +#ifdef SRS_RTSP + conn->rtsp_sources_ = mock_rtsp_sources.get(); +#endif + srs_freep(conn->rtmp_); + conn->rtmp_ = mock_rtmp_server; + srs_freep(conn->security_); + conn->security_ = mock_security; + + // Start the RTMP connection. + MockLiveSource *mock_source = dynamic_cast(mock_sources->mock_source_.get()); + SrsRtmpBridge *bridge = NULL; + SrsRtcRtpBuilder *builder = NULL; + if (true) { + // Mock the client type to be a player + HELPER_EXPECT_SUCCESS(conn->start()); + + // Wait for coroutine to start. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Verify the req should be parsed. + ISrsRequest *req = conn->info_->req_; + EXPECT_STREQ("192.168.1.100", req->ip_.c_str()); + EXPECT_STREQ("rtmp://127.0.0.1/utest", req->tcUrl_.c_str()); + EXPECT_STREQ("rtmp", req->schema_.c_str()); + EXPECT_STREQ("__defaultVhost__", req->vhost_.c_str()); + EXPECT_STREQ("127.0.0.1", req->host_.c_str()); + EXPECT_EQ(1935, req->port_); + EXPECT_STREQ("utest", req->app_.c_str()); + EXPECT_STREQ("livestream", req->stream_.c_str()); + EXPECT_EQ(0, req->duration_); + EXPECT_TRUE(NULL == req->args_); + EXPECT_STREQ("rtmp", req->protocol_.c_str()); + EXPECT_FALSE(conn->info_->edge_); + + // Bridge must be created. + bridge = dynamic_cast(mock_source->rtmp_bridge_); + EXPECT_TRUE(bridge != NULL); + builder = bridge->rtp_builder_; + EXPECT_TRUE(builder != NULL); + +#ifdef SRS_FFMPEG_FIT + // Verify that the mock factory created the audio transcoder + EXPECT_TRUE(mock_factory->last_created_audio_transcoder_ != NULL); +#endif + } + + // Send AAC sequence header first (required before raw data). + MockRtcSource *mock_rtc_source = dynamic_cast(mock_rtc_sources->mock_source_.get()); + if (true) { + // Create AAC sequence header message. + // AAC audio format in RTMP/FLV: + // Byte 0: (SoundFormat << 4) | (SoundRate << 2) | (SoundSize << 1) | SoundType + // SoundFormat=10 (AAC), SoundRate=3 (44kHz), SoundSize=1 (16-bit), SoundType=1 (stereo) + // = 0xAF + // Byte 1: AACPacketType (0=sequence header, 1=raw data) + // Remaining bytes: AudioSpecificConfig (ASC) data + int payload_size = 4; + SrsRtmpCommonMessage *msg = new SrsRtmpCommonMessage(); + msg->header_.initialize_audio(payload_size, 0, 1); + msg->create_payload(payload_size); + + // Fill in AAC sequence header + SrsBuffer stream(msg->payload(), payload_size); + // Audio format byte: AAC(10), 44kHz(3), 16-bit(1), stereo(1) = 0xAF + stream.write_1bytes(0xAF); + // AAC packet type: 0 = AAC sequence header + stream.write_1bytes(0x00); + // AudioSpecificConfig (ASC) data: 0x12 0x10 + // This represents AAC-LC profile, 44.1kHz sample rate, 2 channels + stream.write_1bytes(0x12); + stream.write_1bytes(0x10); + + // Feed sequence header to rtmp server. + mock_rtmp_server->recv_msgs_.push_back(msg); + mock_rtmp_server->cond_->signal(); + + // Wait for consumer to process the message. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Verify that the sequence header is sent to the RTC source. + EXPECT_EQ(1, mock_source->on_audio_count_); + EXPECT_EQ(0, mock_rtc_source->on_rtp_count_); + } + + // Send AAC raw data frame. + if (true) { + // Create AAC raw data message. + // Byte 0: Audio format byte (0xAF) + // Byte 1: AACPacketType (1=raw data) + // Remaining bytes: AAC raw frame data + int payload_size = 10; + SrsRtmpCommonMessage *msg = new SrsRtmpCommonMessage(); + msg->header_.initialize_audio(payload_size, 23, 1); // 23ms timestamp for second frame + msg->create_payload(payload_size); + + // Fill in AAC raw data + SrsBuffer stream(msg->payload(), payload_size); + // Audio format byte: AAC(10), 44kHz(3), 16-bit(1), stereo(1) = 0xAF + stream.write_1bytes(0xAF); + // AAC packet type: 1 = AAC raw data + stream.write_1bytes(0x01); + // AAC raw frame data (8 bytes of dummy audio data) + for (int i = 0; i < 8; i++) { + stream.write_1bytes(0x00); + } + + // Feed raw data to rtmp server. + mock_rtmp_server->recv_msgs_.push_back(msg); + mock_rtmp_server->cond_->signal(); + + // Wait for consumer to process the message. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + + // Verify that the raw data is sent to the client. + EXPECT_EQ(2, mock_source->on_audio_count_); + EXPECT_EQ(1, mock_rtc_source->on_rtp_count_); + } + + // Simulate client quit event, the receive thread will get this error. + if (true) { + mock_rtmp_server->recv_err_ = srs_error_new(ERROR_SOCKET_READ, "mock client quit"); + mock_rtmp_server->cond_->signal(); + + // Wait for coroutine to stop. + srs_usleep(1 * SRS_UTIME_MILLISECONDS); + } + + // Stop the RTMP connection. + conn->stop(); +} diff --git a/trunk/src/utest/srs_utest_workflow_rtmp2rtc.hpp b/trunk/src/utest/srs_utest_workflow_rtmp2rtc.hpp new file mode 100644 index 000000000..ded38cc05 --- /dev/null +++ b/trunk/src/utest/srs_utest_workflow_rtmp2rtc.hpp @@ -0,0 +1,32 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2013-2025 Winlin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SRS_UTEST_WORKFLOW_RTMP2RTC_HPP +#define SRS_UTEST_WORKFLOW_RTMP2RTC_HPP + +/* +#include +*/ +#include + +#endif diff --git a/trunk/src/utest/srs_utest_workflow_rtmp_conn.cpp b/trunk/src/utest/srs_utest_workflow_rtmp_conn.cpp index 0b64ef910..002c4f3d1 100644 --- a/trunk/src/utest/srs_utest_workflow_rtmp_conn.cpp +++ b/trunk/src/utest/srs_utest_workflow_rtmp_conn.cpp @@ -67,16 +67,7 @@ VOID TEST(BasicWorkflowRtmpConnTest, ManuallyVerifyForPublisher) mock_config->mw_msgs_ = 0; // Handle each RTMP message, no merging write. mock_config->mw_sleep_ = 0; // Handle each RTMP message, no merging write. - mock_rtmp_server->type_ = SrsRtmpConnFMLEPublish; - mock_rtmp_server->stream_ = "livestream"; - mock_rtmp_server->ip_ = "192.168.1.100"; - mock_rtmp_server->vhost_ = "utest.ossrs.io"; - mock_rtmp_server->app_ = "utest"; - mock_rtmp_server->stream_ = "livestream"; - mock_rtmp_server->tcUrl_ = "rtmp://127.0.0.1/utest"; - mock_rtmp_server->schema_ = "rtmp"; - mock_rtmp_server->port_ = 1935; - mock_rtmp_server->host_ = "127.0.0.1"; + mock_rtmp_server->set_request(SrsRtmpConnFMLEPublish, "192.168.1.100", "utest.ossrs.io", "utest", "livestream", "rtmp://127.0.0.1/utest", "rtmp", 1935, "127.0.0.1"); // Create SrsRtmpConn - it takes ownership of transport ISrsRtmpTransport *transport = new MockRtmpTransport(); diff --git a/trunk/src/utest/srs_utest_workflow_srt_conn.cpp b/trunk/src/utest/srs_utest_workflow_srt_conn.cpp index 75e919e3c..f6176cb7b 100644 --- a/trunk/src/utest/srs_utest_workflow_srt_conn.cpp +++ b/trunk/src/utest/srs_utest_workflow_srt_conn.cpp @@ -239,6 +239,7 @@ VOID TEST(BasicWorkflowSrtConnTest, ManuallyVerifyForPlayer) // Simulate client quit event, the receive thread will get this error. if (true) { mock_srt_conn->read_error_ = srs_error_new(ERROR_SOCKET_READ, "mock client quit"); + mock_srt_conn->cond_->signal(); // Wait for coroutine to stop. srs_usleep(1 * SRS_UTIME_MILLISECONDS);