Fix WHIP with transcoding bug. v7.0.92 (#4495)

This commit is contained in:
winlin 2025-09-21 08:52:18 -04:00
parent ca261fe955
commit 10c0b66c0f
12 changed files with 71 additions and 48 deletions

View File

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v7-changes"></a>
## SRS 7.0 Changelog
* v7.0, 2025-09-21, Fix WHIP with transcoding bug. v7.0.92 (#4495)
* v7.0, 2025-09-20, Merge [#4504](https://github.com/ossrs/srs/pull/4504): fix rtsp compiling warning. v7.0.91 (#4504)
* v7.0, 2025-09-19, Merge [#4503](https://github.com/ossrs/srs/pull/4503): AI: Refine RTMP/SRT/RTC bridge. v7.0.90 (#4503)
* v7.0, 2025-09-15, RTC2RTMP: Fix sequence number wraparound assertion crashes. v7.0.89 (#4491)
@ -105,6 +106,7 @@ The changelog for SRS.
<a name="v6-changes"></a>
## SRS 6.0 Changelog
* v6.0, 2025-09-21, Fix WHIP with transcoding bug. v6.0.179 (#4495)
* v6.0, 2025-09-15, RTC2RTMP: Fix sequence number wraparound assertion crashes. v6.0.177 (#4491)
* v6.0, 2025-09-05, RTX: Fix race condition for timer. v6.0.176 (#4470) (#4474)
* v6.0, 2025-08-26, Merge [#4451](https://github.com/ossrs/srs/pull/4451): RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v6.0.175 (#4451)

View File

@ -1869,6 +1869,9 @@ SrsRtcConnection::~SrsRtcConnection()
srs_freep(req_);
srs_freep(pli_epp_);
// Optional to release the publisher token.
publish_token_ = NULL;
}
void SrsRtcConnection::on_before_dispose(ISrsResource *c)
@ -1931,6 +1934,11 @@ string SrsRtcConnection::token()
return token_;
}
void SrsRtcConnection::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token)
{
publish_token_ = publish_token;
}
ISrsKbpsDelta *SrsRtcConnection::delta()
{
return networks_->delta();

View File

@ -55,6 +55,7 @@ class SrsRtcNetworks;
class SrsRtcUdpNetwork;
class ISrsRtcNetwork;
class SrsRtcTcpNetwork;
class SrsStreamPublishToken;
const uint8_t kSR = 200;
const uint8_t kRR = 201;
@ -529,6 +530,7 @@ private:
ISrsRequest *req_;
SrsSdp remote_sdp_;
SrsSdp local_sdp_;
SrsSharedPtr<SrsStreamPublishToken> publish_token_;
private:
// twcc handler
@ -561,6 +563,8 @@ public:
std::string username();
// Get the token for verify this session, for example, when delete session by WHIP API.
std::string token();
// Set the publish token for this session if publisher.
void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
public:
virtual ISrsKbpsDelta *delta();

View File

@ -348,7 +348,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
if (ruc->publish_ && (err = _srs_stream_publish_tokens->acquire_token(req, publish_token_raw)) != srs_success) {
return srs_error_wrap(err, "acquire stream publish token");
}
SrsUniquePtr<SrsStreamPublishToken> publish_token(publish_token_raw);
SrsSharedPtr<SrsStreamPublishToken> publish_token(publish_token_raw);
if (publish_token.get()) {
srs_trace("stream publish token acquired, type=rtc, url=%s", req->get_stream_url().c_str());
}
@ -370,6 +370,11 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
return srs_error_wrap(err, "create session");
}
// Update publish token for publisher.
if (ruc->publish_) {
session->set_publish_token(publish_token);
}
*psession = session;
return err;

View File

@ -715,9 +715,6 @@ void SrsRtcSource::on_unpublish()
srs_trace("cleanup when unpublish, created=%u, deliver=%u", is_created_, is_delivering_packets_);
is_created_ = false;
is_delivering_packets_ = false;
if (!_source_id.empty()) {
_pre_source_id = _source_id;
}
@ -744,16 +741,20 @@ void SrsRtcSource::on_unpublish()
if (consumers_.empty()) {
stream_die_at_ = srs_time_now_cached();
}
// Should never change the final state before all cleanup is done.
is_created_ = false;
is_delivering_packets_ = false;
}
void SrsRtcSource::subscribe(ISrsRtcSourceEventHandler *h)
void SrsRtcSource::rtc_source_subscribe(ISrsRtcSourceEventHandler *h)
{
if (std::find(event_handlers_.begin(), event_handlers_.end(), h) == event_handlers_.end()) {
event_handlers_.push_back(h);
}
}
void SrsRtcSource::unsubscribe(ISrsRtcSourceEventHandler *h)
void SrsRtcSource::rtc_source_unsubscribe(ISrsRtcSourceEventHandler *h)
{
std::vector<ISrsRtcSourceEventHandler *>::iterator it;
it = std::find(event_handlers_.begin(), event_handlers_.end(), h);

View File

@ -310,8 +310,8 @@ public:
public:
// For event handler
virtual void subscribe(ISrsRtcSourceEventHandler *h);
virtual void unsubscribe(ISrsRtcSourceEventHandler *h);
virtual void rtc_source_subscribe(ISrsRtcSourceEventHandler *h);
virtual void rtc_source_unsubscribe(ISrsRtcSourceEventHandler *h);
public:
// Get and set the publisher, passed to consumer to process requests such as PLI.

View File

@ -444,9 +444,6 @@ void SrsRtspSource::on_unpublish()
srs_trace("cleanup when unpublish, created=%u, deliver=%u", is_created_, is_delivering_packets_);
is_created_ = false;
is_delivering_packets_ = false;
if (!_source_id.empty()) {
_pre_source_id = _source_id;
}
@ -459,6 +456,10 @@ void SrsRtspSource::on_unpublish()
if (consumers_.empty()) {
stream_die_at_ = srs_time_now_cached();
}
// Should never change the final state before all cleanup is done.
is_created_ = false;
is_delivering_packets_ = false;
}
srs_error_t SrsRtspSource::on_rtp(SrsRtpPacket *pkt)

View File

@ -1085,8 +1085,6 @@ void SrsSrtSource::on_unpublish()
return;
}
can_publish_ = true;
SrsStatistic *stat = SrsStatistic::instance();
stat->on_stream_close(req_);
@ -1099,6 +1097,9 @@ void SrsSrtSource::on_unpublish()
if (consumers_.empty()) {
stream_die_at_ = srs_time_now_cached();
}
// Should never change the final state before all cleanup is done.
can_publish_ = true;
}
srs_error_t SrsSrtSource::on_packet(SrsSrtPacket *packet)

View File

@ -185,6 +185,7 @@ void SrsFastCoroutine::stop()
}
disposed_ = true;
stopping_ = true;
stopping_cid_ = _srs_context->get_id();
interrupt();

View File

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define VERSION_REVISION 177
#define VERSION_REVISION 179
#endif

View File

@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
#define VERSION_REVISION 91
#define VERSION_REVISION 92
#endif

View File

@ -1575,8 +1575,8 @@ VOID TEST(AppTest2, RtcSourceOnConsumerDestroyNotifyEventHandlers)
// Set up source with publish stream and event handlers
source->set_publish_stream(publish_stream);
source->subscribe(handler1);
source->subscribe(handler2);
source->rtc_source_subscribe(handler1);
source->rtc_source_subscribe(handler2);
// Create mock consumers
MockRtcConsumer *consumer1 = new MockRtcConsumer();
@ -1625,7 +1625,7 @@ VOID TEST(AppTest2, RtcSourceOnConsumerDestroyNoPublishStream)
// Create mock event handler
MockRtcSourceEventHandler *handler = new MockRtcSourceEventHandler();
source->subscribe(handler);
source->rtc_source_subscribe(handler);
// Create mock consumer
MockRtcConsumer *consumer = new MockRtcConsumer();
@ -1961,12 +1961,12 @@ VOID TEST(AppTest2, RtcSourceSubscribeBasic)
EXPECT_EQ(0, (int)source->event_handlers_.size());
// Subscribe first handler
source->subscribe(handler1.get());
source->rtc_source_subscribe(handler1.get());
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(handler1.get(), source->event_handlers_[0]);
// Subscribe second handler
source->subscribe(handler2.get());
source->rtc_source_subscribe(handler2.get());
EXPECT_EQ(2, (int)source->event_handlers_.size());
EXPECT_EQ(handler1.get(), source->event_handlers_[0]);
EXPECT_EQ(handler2.get(), source->event_handlers_[1]);
@ -1991,18 +1991,18 @@ VOID TEST(AppTest2, RtcSourceSubscribeDuplicateHandler)
SrsUniquePtr<MockRtcSourceEventHandler> handler(new MockRtcSourceEventHandler());
// Subscribe handler first time
source->subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(handler.get(), source->event_handlers_[0]);
// Subscribe same handler again - should not add duplicate
source->subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(handler.get(), source->event_handlers_[0]);
// Subscribe same handler multiple times - should still be only one
source->subscribe(handler.get());
source->subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(handler.get(), source->event_handlers_[0]);
}
@ -2026,12 +2026,12 @@ VOID TEST(AppTest2, RtcSourceSubscribeNullHandler)
EXPECT_EQ(0, (int)source->event_handlers_.size());
// Subscribe null handler - should add it (implementation allows null)
source->subscribe(NULL);
source->rtc_source_subscribe(NULL);
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(NULL, source->event_handlers_[0]);
// Subscribe null handler again - should not add duplicate
source->subscribe(NULL);
source->rtc_source_subscribe(NULL);
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(NULL, source->event_handlers_[0]);
}
@ -2060,9 +2060,9 @@ VOID TEST(AppTest2, RtcSourceSubscribeMultipleHandlers)
EXPECT_EQ(0, (int)source->event_handlers_.size());
// Subscribe handlers in order
source->subscribe(handler1.get());
source->subscribe(handler2.get());
source->subscribe(handler3.get());
source->rtc_source_subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
source->rtc_source_subscribe(handler3.get());
// Verify all handlers are subscribed in correct order
EXPECT_EQ(3, (int)source->event_handlers_.size());
@ -2071,8 +2071,8 @@ VOID TEST(AppTest2, RtcSourceSubscribeMultipleHandlers)
EXPECT_EQ(handler3.get(), source->event_handlers_[2]);
// Try to subscribe duplicates - should not change the list
source->subscribe(handler2.get());
source->subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
source->rtc_source_subscribe(handler1.get());
EXPECT_EQ(3, (int)source->event_handlers_.size());
EXPECT_EQ(handler1.get(), source->event_handlers_[0]);
EXPECT_EQ(handler2.get(), source->event_handlers_[1]);
@ -2099,29 +2099,29 @@ VOID TEST(AppTest2, RtcSourceSubscribeUnsubscribeInteraction)
SrsUniquePtr<MockRtcSourceEventHandler> handler2(new MockRtcSourceEventHandler());
// Subscribe both handlers
source->subscribe(handler1.get());
source->subscribe(handler2.get());
source->rtc_source_subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
EXPECT_EQ(2, (int)source->event_handlers_.size());
// Unsubscribe first handler
source->unsubscribe(handler1.get());
source->rtc_source_unsubscribe(handler1.get());
EXPECT_EQ(1, (int)source->event_handlers_.size());
EXPECT_EQ(handler2.get(), source->event_handlers_[0]);
// Re-subscribe first handler - should be added back
source->subscribe(handler1.get());
source->rtc_source_subscribe(handler1.get());
EXPECT_EQ(2, (int)source->event_handlers_.size());
EXPECT_EQ(handler2.get(), source->event_handlers_[0]);
EXPECT_EQ(handler1.get(), source->event_handlers_[1]);
// Unsubscribe all handlers
source->unsubscribe(handler1.get());
source->unsubscribe(handler2.get());
source->rtc_source_unsubscribe(handler1.get());
source->rtc_source_unsubscribe(handler2.get());
EXPECT_EQ(0, (int)source->event_handlers_.size());
// Re-subscribe in different order
source->subscribe(handler2.get());
source->subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
source->rtc_source_subscribe(handler1.get());
EXPECT_EQ(2, (int)source->event_handlers_.size());
EXPECT_EQ(handler2.get(), source->event_handlers_[0]);
EXPECT_EQ(handler1.get(), source->event_handlers_[1]);
@ -2147,8 +2147,8 @@ VOID TEST(AppTest2, RtcSourceSubscribeEventNotification)
SrsUniquePtr<MockRtcSourceEventHandler> handler2(new MockRtcSourceEventHandler());
// Subscribe handlers
source->subscribe(handler1.get());
source->subscribe(handler2.get());
source->rtc_source_subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
// Verify initial state
EXPECT_EQ(0, handler1->on_unpublish_count_);
@ -2174,11 +2174,11 @@ VOID TEST(AppTest2, RtcSourceSubscribeEventNotification)
handler2->on_unpublish_count_ = 0;
// Subscribe both handlers to the new source
source2->subscribe(handler1.get());
source2->subscribe(handler2.get());
source2->rtc_source_subscribe(handler1.get());
source2->rtc_source_subscribe(handler2.get());
// Unsubscribe handler1
source2->unsubscribe(handler1.get());
source2->rtc_source_unsubscribe(handler1.get());
// Verify only handler2 is subscribed now
EXPECT_EQ(1, (int)source2->event_handlers_.size());
@ -2255,7 +2255,7 @@ VOID TEST(AppTest2, RtcSourcePublishStreamWithConsumerDestroy)
// Create a mock event handler
SrsUniquePtr<MockRtcSourceEventHandler> handler(new MockRtcSourceEventHandler());
source->subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
// Create consumers
ISrsRtcConsumer *consumer1 = NULL;
@ -3204,8 +3204,8 @@ VOID TEST(AppTest2, RtcSourceSetStreamCreatedWithEventHandlers)
// Create and subscribe event handlers
SrsUniquePtr<MockRtcSourceEventHandler> handler1(new MockRtcSourceEventHandler());
SrsUniquePtr<MockRtcSourceEventHandler> handler2(new MockRtcSourceEventHandler());
source->subscribe(handler1.get());
source->subscribe(handler2.get());
source->rtc_source_subscribe(handler1.get());
source->rtc_source_subscribe(handler2.get());
// Verify initial state
EXPECT_FALSE(source->is_created_);
@ -3242,7 +3242,7 @@ VOID TEST(AppTest2, RtcSourcePublishStreamWithoutConsumerDestroy)
// Create a mock event handler
SrsUniquePtr<MockRtcSourceEventHandler> handler(new MockRtcSourceEventHandler());
source->subscribe(handler.get());
source->rtc_source_subscribe(handler.get());
// Create and destroy consumer
ISrsRtcConsumer *consumer = NULL;