AI: Add config init_rate_from_sdp that defaults to off

This commit is contained in:
OSSRS-AI 2025-10-28 08:06:10 -04:00 committed by winlin
parent 2604d0a239
commit e600afae1e
16 changed files with 254 additions and 632 deletions

View File

@ -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.

View File

@ -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_);

View File

@ -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:

View File

@ -1291,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;

View File

@ -3128,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();
@ -3150,7 +3150,7 @@ SrsRtcRecvTrack::SrsRtcRecvTrack(ISrsRtcPacketReceiver *receiver, SrsRtcTrackDes
// 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 (track_desc_->media_) {
if (init_rate_from_sdp && track_desc_->media_) {
rate_ = static_cast<double>(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_);
@ -3337,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)
{
}
@ -3385,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)
{
}

View File

@ -883,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:
@ -917,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:
@ -931,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:

View File

@ -111,7 +111,7 @@ public:
virtual srs_error_t add_sample(char *bytes, int size);
// clang-format off
SRS_DECLARE_PRIVATE: // clang-format on
SRS_DECLARE_PROTECTED: // clang-format on
// Copy the packet.
virtual SrsParsedPacket *copy();
virtual void do_copy(SrsParsedPacket *p);
@ -131,7 +131,7 @@ public:
virtual SrsAudioCodecConfig *acodec();
// clang-format off
SRS_DECLARE_PRIVATE: // clang-format on
SRS_DECLARE_PROTECTED: // clang-format on
virtual SrsParsedAudioPacket *copy();
};
@ -162,7 +162,7 @@ public:
virtual srs_error_t add_sample(char *bytes, int size);
// clang-format off
SRS_DECLARE_PRIVATE: // clang-format on
SRS_DECLARE_PROTECTED: // clang-format on
virtual SrsParsedVideoPacket *copy();
public:

View File

@ -2253,7 +2253,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadEmptyBuffer)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2276,7 +2276,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264RawNALU)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2307,7 +2307,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264STAP)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2342,7 +2342,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264FUA)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2376,7 +2376,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCRawNALU)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H265", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2407,7 +2407,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCSTAP)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H265", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2444,7 +2444,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCFUA)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H265", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2479,7 +2479,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadUnknownCodec)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("VP8", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> 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<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2529,7 +2529,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadH264IDR)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2560,7 +2560,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadHEVCIDR)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H265", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> pkt(create_test_rtp_packet(100, 1000, 12345));
@ -2591,7 +2591,7 @@ VOID TEST(SrsRtcVideoRecvTrackTest, OnBeforeDecodePayloadSingleByte)
{
MockRtcPacketReceiver mock_receiver;
SrsUniquePtr<SrsRtcTrackDescription> desc(create_video_track_description("H264", 12345));
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get());
SrsRtcVideoRecvTrack track(&mock_receiver, desc.get(), false);
SrsUniquePtr<SrsRtpPacket> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> track_desc1(create_test_track_description("audio", 55555));
SrsUniquePtr<SrsRtcTrackDescription> 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;

View File

@ -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);

View File

@ -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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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<SrsRtcTrackDescription> 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

View File

@ -33,7 +33,7 @@ class MockSrsRtcRecvTrackForAVSync : public SrsRtcRecvTrack
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)
: SrsRtcRecvTrack(NULL, create_track_desc(type, ssrc, sample_rate), is_audio, true)
{
}

View File

@ -547,487 +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;
rtc_server_enabled_ = false;
rtc_enabled_ = false;
}
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<std::string> &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<std::string> &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<std::string> &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()
{

View File

@ -291,20 +291,72 @@ public:
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<std::string> &destinations);
void set_forward_backend(const std::string &backend_url);
void set_forward_destinations(const std::vector<std::string> &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 ""; }
@ -429,69 +481,70 @@ public:
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"; }
@ -563,22 +616,38 @@ public:
virtual std::vector<std::string> get_engine_aparams(SrsConfDirective *conf) { return std::vector<std::string>(); }
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<std::string> &urls);
void clear_on_stop_directive();
void set_on_unpublish_urls(const std::vector<std::string> &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<std::string> &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<std::string> &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

View File

@ -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);

View File

@ -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)

View File

@ -95,6 +95,7 @@ VOID TEST(BasicWorkflowRtc2RtmpTest, ManuallyVerifyTypicalScenario)
SrsUniquePtr<MockAppFactoryForRtc2Rtmp> 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;