AI: Add utest to cover rtsp module.

This commit is contained in:
OSSRS-AI 2025-10-06 23:45:52 -04:00 committed by winlin
parent 809d77b662
commit 94dde8e370
7 changed files with 2101 additions and 50 deletions

View File

@ -347,6 +347,14 @@ void SrsRtspPlayStream::set_all_tracks_status(bool status)
srs_trace("RTSP: Init tracks %s ok", merged_log.str().c_str());
}
ISrsRtspConnection::ISrsRtspConnection()
{
}
ISrsRtspConnection::~ISrsRtspConnection()
{
}
SrsRtspConnection::SrsRtspConnection(ISrsResourceManager *cm, ISrsProtocolReadWriter *skt, std::string cip, int port)
{
manager_ = cm;

View File

@ -88,7 +88,24 @@ public:
void set_all_tracks_status(bool status);
};
class SrsRtspConnection : public ISrsResource, public ISrsDisposingHandler, public ISrsExpire, public ISrsCoroutineHandler, public ISrsStartable
// The handler for RTSP connection send packet.
class ISrsRtspConnection
{
public:
ISrsRtspConnection();
virtual ~ISrsRtspConnection();
public:
virtual srs_error_t do_send_packet(SrsRtpPacket *pkt) = 0;
};
// A RTSP session, client request and response with RTSP.
class SrsRtspConnection : public ISrsResource, // It's a resource.
public ISrsDisposingHandler,
public ISrsExpire,
public ISrsCoroutineHandler,
public ISrsStartable,
public ISrsRtspConnection
{
private:
bool disposing_;

View File

@ -250,6 +250,9 @@ SrsRtspSource::SrsRtspSource()
req_ = NULL;
stream_die_at_ = 0;
stat_ = _srs_stat;
circuit_breaker_ = _srs_circuit_breaker;
}
SrsRtspSource::~SrsRtspSource()
@ -266,6 +269,9 @@ SrsRtspSource::~SrsRtspSource()
if (cid.empty())
cid = _pre_source_id;
srs_trace("free rtc source id=[%s]", cid.c_str());
stat_ = NULL;
circuit_breaker_ = NULL;
}
// CRITICAL: This method is called AFTER the source has been added to the source pool
@ -437,8 +443,7 @@ srs_error_t SrsRtspSource::on_publish()
return srs_error_wrap(err, "source id change");
}
SrsStatistic *stat = _srs_stat;
stat->on_stream_publish(req_, _source_id.c_str());
stat_->on_stream_publish(req_, _source_id.c_str());
return err;
}
@ -457,8 +462,7 @@ void SrsRtspSource::on_unpublish()
}
_source_id = SrsContextId();
SrsStatistic *stat = _srs_stat;
stat->on_stream_close(req_);
stat_->on_stream_close(req_);
// Destroy and cleanup source when no publishers and consumers.
if (consumers_.empty()) {
@ -475,7 +479,7 @@ srs_error_t SrsRtspSource::on_rtp(SrsRtpPacket *pkt)
srs_error_t err = srs_success;
// If circuit-breaker is dying, drop packet.
if (_srs_circuit_breaker->hybrid_dying_water_level()) {
if (circuit_breaker_->hybrid_dying_water_level()) {
_srs_pps_aloss2->sugar_ += (int64_t)consumers_.size();
return err;
}
@ -531,6 +535,8 @@ SrsRtspRtpBuilder::SrsRtspRtpBuilder(ISrsRtpTarget *target, SrsSharedPtr<SrsRtsp
// Lazy initialization flags
audio_initialized_ = false;
video_initialized_ = false;
config_ = _srs_config;
}
SrsRtspRtpBuilder::~SrsRtspRtpBuilder()
@ -538,6 +544,8 @@ SrsRtspRtpBuilder::~SrsRtspRtpBuilder()
srs_freep(format_);
srs_freep(meta_);
srs_freep(video_builder_);
config_ = NULL;
}
srs_error_t SrsRtspRtpBuilder::initialize_audio_track(SrsAudioCodecId codec)
@ -679,7 +687,7 @@ srs_error_t SrsRtspRtpBuilder::initialize(ISrsRequest *r)
}
// Setup the SPS/PPS parsing strategy.
format_->try_annexb_first_ = _srs_config->try_annexb_first(r->vhost_);
format_->try_annexb_first_ = config_->try_annexb_first(r->vhost_);
srs_trace("RTSP bridge from RTMP, try_annexb_first=%d", format_->try_annexb_first_);
@ -997,7 +1005,7 @@ srs_error_t SrsRtspRtpBuilder::consume_packets(vector<SrsRtpPacket *> &pkts)
return err;
}
SrsRtspSendTrack::SrsRtspSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio)
SrsRtspSendTrack::SrsRtspSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio)
{
session_ = session;
track_desc_ = track_desc->copy();
@ -1031,7 +1039,7 @@ std::string SrsRtspSendTrack::get_track_id()
return track_desc_->id_;
}
SrsRtspAudioSendTrack::SrsRtspAudioSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
SrsRtspAudioSendTrack::SrsRtspAudioSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
: SrsRtspSendTrack(session, track_desc, true)
{
}
@ -1071,7 +1079,7 @@ srs_error_t SrsRtspAudioSendTrack::on_rtp(SrsRtpPacket *pkt)
return err;
}
SrsRtspVideoSendTrack::SrsRtspVideoSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
SrsRtspVideoSendTrack::SrsRtspVideoSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
: SrsRtspSendTrack(session, track_desc, false)
{
}

View File

@ -26,6 +26,10 @@ class SrsRtcSourceDescription;
class SrsResourceManager;
class SrsRtspConnection;
class SrsRtpVideoBuilder;
class ISrsStatistic;
class ISrsCircuitBreaker;
class ISrsAppConfig;
class ISrsRtspConnection;
// The RTSP stream consumer, consume packets from RTSP stream source.
class SrsRtspConsumer
@ -118,6 +122,10 @@ extern SrsResourceManager *_srs_rtsp_manager;
// A Source is a stream, to publish and to play with, binding to SrsRtspPlayStream.
class SrsRtspSource : public ISrsRtpTarget
{
private:
ISrsStatistic *stat_;
ISrsCircuitBreaker *circuit_breaker_;
private:
// For publish, it's the publish client id.
// For edge, it's the edge ingest id.
@ -201,6 +209,9 @@ public:
// Convert AV frame to RTSP RTP packets.
class SrsRtspRtpBuilder
{
private:
ISrsAppConfig *config_;
private:
ISrsRequest *req_;
ISrsRtpTarget *rtp_target_;
@ -264,10 +275,10 @@ public:
protected:
// The owner connection for this track.
SrsRtspConnection *session_;
ISrsRtspConnection *session_;
public:
SrsRtspSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio);
SrsRtspSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc, bool is_audio);
virtual ~SrsRtspSendTrack();
public:
@ -284,7 +295,7 @@ public:
class SrsRtspAudioSendTrack : public SrsRtspSendTrack
{
public:
SrsRtspAudioSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
SrsRtspAudioSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
virtual ~SrsRtspAudioSendTrack();
public:
@ -294,7 +305,7 @@ public:
class SrsRtspVideoSendTrack : public SrsRtspSendTrack
{
public:
SrsRtspVideoSendTrack(SrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
SrsRtspVideoSendTrack(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
virtual ~SrsRtspVideoSendTrack();
public:

View File

@ -531,7 +531,6 @@ srs_error_t SrsMpegtsSrtConn::do_playing()
srs_assert(consumer_raw);
SrsUniquePtr<ISrsSrtConsumer> consumer(consumer_raw);
SrsSrtConsumer *consumer_impl = dynamic_cast<SrsSrtConsumer *>(consumer_raw);
// TODO: FIXME: Dumps the SPS/PPS from gop cache, without other frames.
if ((err = srt_source_->consumer_dumps(consumer.get())) != srs_success) {

File diff suppressed because it is too large Load Diff

View File

@ -12,9 +12,10 @@
*/
#include <srs_utest.hpp>
#include <srs_utest_app6.hpp>
#include <srs_app_rtsp_conn.hpp>
#include <srs_app_stream_bridge.hpp>
#include <srs_protocol_rtmp_stack.hpp>
#include <srs_utest_app6.hpp>
// Mock frame target for testing SrsSrtFrameBuilder
class MockSrtFrameTarget : public ISrsFrameTarget
@ -107,5 +108,52 @@ public:
void reset();
};
#endif
// Forward declaration
class SrsRtspConsumer;
// Mock RTSP source for testing SrsRtspConsumer
class MockRtspSource
{
public:
int on_consumer_destroy_count_;
public:
MockRtspSource();
virtual ~MockRtspSource();
void on_consumer_destroy(SrsRtspConsumer *consumer);
void reset();
};
// Mock RTP target for testing SrsRtspRtpBuilder
class MockRtspRtpTarget : public ISrsRtpTarget
{
public:
int on_rtp_count_;
SrsRtpPacket *last_rtp_;
srs_error_t rtp_error_;
public:
MockRtspRtpTarget();
virtual ~MockRtspRtpTarget();
virtual srs_error_t on_rtp(SrsRtpPacket *pkt);
void set_rtp_error(srs_error_t err);
void reset();
};
// Mock RTSP connection for testing SrsRtspSendTrack
class MockRtspConnection : public ISrsRtspConnection
{
public:
int do_send_packet_count_;
SrsRtpPacket *last_packet_;
srs_error_t send_error_;
public:
MockRtspConnection();
virtual ~MockRtspConnection();
virtual srs_error_t do_send_packet(SrsRtpPacket *pkt);
void set_send_error(srs_error_t err);
void reset();
};
#endif