1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

SmartPtr: Support load test for source by srs-bench. v6.0.130 (#4097)

1. Add live benchmark support in srs-bench, which only connects and
disconnects without any media transport, to test source creation and
disposal and verify source memory leaks.
2. SmartPtr: Support cleanup of HTTP-FLV stream. Unregister the HTTP-FLV
handler for the pattern and clean up the objects and resources.
3. Support benchmarking RTMP/SRT with srs-bench by integrating the gosrt
and oryx RTMP libraries.
4. Refine SRT and RTC sources by using a timer to clean up the sources,
following the same strategy as the Live source.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-06-21 07:13:12 +08:00 committed by GitHub
parent e3d74fb045
commit 1f9309ae25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
508 changed files with 6805 additions and 3299 deletions

View file

@ -71,6 +71,9 @@ using namespace std;
const int kRtpMaxPayloadSize = kRtpPacketSize - 300;
#endif
// the time to cleanup source.
#define SRS_RTC_SOURCE_CLEANUP (3 * SRS_UTIME_SECONDS)
// TODO: Add this function into SrsRtpMux class.
srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char** pbuf, int* pnn_buf)
{
@ -244,11 +247,56 @@ void SrsRtcConsumer::on_stream_change(SrsRtcSourceDescription* desc)
SrsRtcSourceManager::SrsRtcSourceManager()
{
lock = srs_mutex_new();
timer_ = new SrsHourGlass("sources", this, 1 * SRS_UTIME_SECONDS);
}
SrsRtcSourceManager::~SrsRtcSourceManager()
{
srs_mutex_destroy(lock);
srs_freep(timer_);
}
srs_error_t SrsRtcSourceManager::initialize()
{
return setup_ticks();
}
srs_error_t SrsRtcSourceManager::setup_ticks()
{
srs_error_t err = srs_success;
if ((err = timer_->tick(1, 3 * SRS_UTIME_SECONDS)) != srs_success) {
return srs_error_wrap(err, "tick");
}
if ((err = timer_->start()) != srs_success) {
return srs_error_wrap(err, "timer");
}
return err;
}
srs_error_t SrsRtcSourceManager::notify(int event, srs_utime_t interval, srs_utime_t tick)
{
srs_error_t err = srs_success;
std::map< std::string, SrsSharedPtr<SrsRtcSource> >::iterator it;
for (it = pool.begin(); it != pool.end();) {
SrsSharedPtr<SrsRtcSource>& source = it->second;
// When source expired, remove it.
// @see https://github.com/ossrs/srs/issues/713
if (source->stream_is_dead()) {
SrsContextId cid = source->source_id();
if (cid.empty()) cid = source->pre_source_id();
srs_trace("RTC: cleanup die source, id=[%s], total=%d", cid.c_str(), (int)pool.size());
pool.erase(it++);
} else {
++it;
}
}
return err;
}
srs_error_t SrsRtcSourceManager::fetch_or_create(SrsRequest* r, SrsSharedPtr<SrsRtcSource>& pps)
@ -305,19 +353,6 @@ SrsSharedPtr<SrsRtcSource> SrsRtcSourceManager::fetch(SrsRequest* r)
return source;
}
void SrsRtcSourceManager::eliminate(SrsRequest* r)
{
// Use lock to protect coroutine switch.
// @bug https://github.com/ossrs/srs/issues/1230
SrsLocker(lock);
string stream_url = r->get_stream_url();
std::map< std::string, SrsSharedPtr<SrsRtcSource> >::iterator it = pool.find(stream_url);
if (it != pool.end()) {
pool.erase(it);
}
}
SrsRtcSourceManager* _srs_rtc_sources = NULL;
ISrsRtcPublishStream::ISrsRtcPublishStream()
@ -351,6 +386,7 @@ SrsRtcSource::SrsRtcSource()
#endif
pli_for_rtmp_ = pli_elapsed_ = 0;
stream_die_at_ = 0;
}
SrsRtcSource::~SrsRtcSource()
@ -365,6 +401,10 @@ SrsRtcSource::~SrsRtcSource()
srs_freep(bridge_);
srs_freep(req);
srs_freep(stream_desc_);
SrsContextId cid = _source_id;
if (cid.empty()) cid = _pre_source_id;
srs_trace("free rtc source id=[%s]", cid.c_str());
}
srs_error_t SrsRtcSource::initialize(SrsRequest* r)
@ -380,6 +420,27 @@ srs_error_t SrsRtcSource::initialize(SrsRequest* r)
return err;
}
bool SrsRtcSource::stream_is_dead()
{
// still publishing?
if (is_created_) {
return false;
}
// has any consumers?
if (!consumers.empty()) {
return false;
}
// Delay cleanup source.
srs_utime_t now = srs_get_system_time();
if (now < stream_die_at_ + SRS_RTC_SOURCE_CLEANUP) {
return false;
}
return true;
}
void SrsRtcSource::init_for_play_before_publishing()
{
// If the stream description has already been setup by RTC publisher,
@ -493,6 +554,8 @@ srs_error_t SrsRtcSource::create_consumer(SrsRtcConsumer*& consumer)
consumer = new SrsRtcConsumer(this);
consumers.push_back(consumer);
stream_die_at_ = 0;
// TODO: FIXME: Implements edge cluster.
return err;
@ -526,7 +589,7 @@ void SrsRtcSource::on_consumer_destroy(SrsRtcConsumer* consumer)
// Destroy and cleanup source when no publishers and consumers.
if (!is_created_ && consumers.empty()) {
_srs_rtc_sources->eliminate(req);
stream_die_at_ = srs_get_system_time();
}
}
@ -629,8 +692,8 @@ void SrsRtcSource::on_unpublish()
stat->on_stream_close(req);
// Destroy and cleanup source when no publishers and consumers.
if (!is_created_ && consumers.empty()) {
_srs_rtc_sources->eliminate(req);
if (consumers.empty()) {
stream_die_at_ = srs_get_system_time();
}
}