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

SmartPtr: Use shared ptr to manage GB objects. v6.0.126 (#4080)

The object relations: 

![gb](266e8a4e-3f1e-4805-8406-9008d6a63aa0)

Session manages SIP and Media object using shared resource or shared
ptr. Note that I actually use SrsExecutorCoroutine to delete the object
when each coroutine is done, because there is always a dedicate
coroutine for each object.

For SIP and Media object, they directly use the session by raw pointer,
it's safe because session always live longer than session and media
object.

---

Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-06-12 22:40:20 +08:00 committed by GitHub
parent 1656391c67
commit 6834ec208d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 989 additions and 464 deletions

View file

@ -26,11 +26,11 @@ class SrsCoroutine;
class SrsPackContext;
class SrsBuffer;
class SrsSipMessage;
class SrsLazyGbSession;
class SrsLazyGbSipTcpConn;
class SrsLazyGbMediaTcpConn;
class SrsLazyGbSipTcpReceiver;
class SrsLazyGbSipTcpSender;
class SrsGbSession;
class SrsGbSipTcpConn;
class SrsGbMediaTcpConn;
class SrsGbSipTcpReceiver;
class SrsGbSipTcpSender;
class SrsAlonePithyPrint;
class SrsGbMuxer;
class SrsSimpleRtmpClient;
@ -51,7 +51,7 @@ class SrsRawAacStream;
// established:
// init: media is not connected.
// dispose session: sip is bye.
// Please see SrsLazyGbSession::drive_state for detail.
// Please see SrsGbSession::drive_state for detail.
enum SrsGbSessionState
{
SrsGbSessionStateInit = 0,
@ -76,7 +76,7 @@ std::string srs_gb_session_state(SrsGbSessionState state);
// to bye: Got bye SIP message from device.
// re-inviting:
// to inviting: Got bye OK response from deivce.
// Please see SrsLazyGbSipTcpConn::drive_state for detail.
// Please see SrsGbSipTcpConn::drive_state for detail.
enum SrsGbSipState
{
SrsGbSipStateInit = 0,
@ -90,16 +90,23 @@ enum SrsGbSipState
std::string srs_gb_sip_state(SrsGbSipState state);
// The main logic object for GB, the session.
class SrsLazyGbSession : public SrsLazyObject, public ISrsResource, public ISrsStartable, public ISrsCoroutineHandler
// Each session contains a SIP object and a media object, that are managed by session. This means session always
// lives longer than SIP and media, and session will dispose SIP and media when session disposed. In another word,
// SIP and media objects use directly pointer to session, while session use shared ptr.
class SrsGbSession : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler
{
private:
SrsCoroutine* trd_;
SrsContextId cid_;
private:
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
SrsSharedResource<SrsGbSession>* wrapper_;
// The owner coroutine, allow user to interrupt the loop.
ISrsInterruptable* owner_coroutine_;
ISrsContextIdSetter* owner_cid_;
private:
SrsGbSessionState state_;
SrsLazyObjectWrapper<SrsLazyGbSession>* wrapper_root_;
SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>* sip_;
SrsLazyObjectWrapper<SrsLazyGbMediaTcpConn>* media_;
SrsSharedResource<SrsGbSipTcpConn> sip_;
SrsSharedResource<SrsGbMediaTcpConn> media_;
SrsGbMuxer* muxer_;
private:
// The candidate for SDP in configuration.
@ -132,26 +139,27 @@ private:
uint64_t media_recovered_;
uint64_t media_msgs_dropped_;
uint64_t media_reserved_;
private:
friend class SrsLazyObjectWrapper<SrsLazyGbSession>;
SrsLazyGbSession(SrsLazyObjectWrapper<SrsLazyGbSession>* wrapper_root);
public:
virtual ~SrsLazyGbSession();
SrsGbSession();
virtual ~SrsGbSession();
public:
// Initialize the GB session.
srs_error_t initialize(SrsConfDirective* conf);
void setup(SrsConfDirective* conf);
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
void setup_owner(SrsSharedResource<SrsGbSession>* wrapper, ISrsInterruptable* owner_coroutine, ISrsContextIdSetter* owner_cid);
// Interface ISrsExecutorHandler
public:
virtual void on_executor_done(ISrsInterruptable* executor);
public:
// When got a pack of messages.
void on_ps_pack(SrsPackContext* ctx, SrsPsPacket* ps, const std::vector<SrsTsMessage*>& msgs);
// When got available SIP transport.
void on_sip_transport(SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>* sip);
SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>* sip_transport();
void on_sip_transport(SrsSharedResource<SrsGbSipTcpConn> sip);
SrsSharedResource<SrsGbSipTcpConn> sip_transport();
// When got available media transport.
void on_media_transport(SrsLazyObjectWrapper<SrsLazyGbMediaTcpConn>* media);
void on_media_transport(SrsSharedResource<SrsGbMediaTcpConn> media);
// Get the candidate for SDP generation, the public IP address for device to connect to.
std::string pip();
// Interface ISrsStartable
public:
virtual srs_error_t start();
// Interface ISrsOneCycleThreadHandler
public:
virtual srs_error_t cycle();
@ -186,12 +194,12 @@ public:
};
// A GB28181 TCP SIP connection.
class SrsLazyGbSipTcpConn : public SrsLazyObject, public ISrsResource, public ISrsStartable, public ISrsCoroutineHandler
class SrsGbSipTcpConn : public ISrsResource, public ISrsCoroutineHandler, public ISrsExecutorHandler
{
private:
SrsGbSipState state_;
SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>* wrapper_root_;
SrsLazyObjectWrapper<SrsLazyGbSession>* session_;
// The owner session object, note that we use the raw pointer and should never free it.
SrsGbSession* session_;
SrsSipMessage* register_;
SrsSipMessage* invite_ok_;
private:
@ -202,18 +210,28 @@ private:
SrsTcpListener* sip_listener_;
SrsTcpListener* media_listener_;
private:
SrsTcpConnection* conn_;
SrsLazyGbSipTcpReceiver* receiver_;
SrsLazyGbSipTcpSender* sender_;
SrsCoroutine* trd_;
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
SrsSharedResource<SrsGbSipTcpConn>* wrapper_;
// The owner coroutine, allow user to interrupt the loop.
ISrsInterruptable* owner_coroutine_;
ISrsContextIdSetter* owner_cid_;
SrsContextId cid_;
private:
friend class SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>;
SrsLazyGbSipTcpConn(SrsLazyObjectWrapper<SrsLazyGbSipTcpConn>* wrapper_root);
SrsTcpConnection* conn_;
SrsGbSipTcpReceiver* receiver_;
SrsGbSipTcpSender* sender_;
public:
virtual ~SrsLazyGbSipTcpConn();
SrsGbSipTcpConn();
virtual ~SrsGbSipTcpConn();
public:
// Setup object, to keep empty constructor.
void setup(SrsConfDirective* conf, SrsTcpListener* sip, SrsTcpListener* media, srs_netfd_t stfd);
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
void setup_owner(SrsSharedResource<SrsGbSipTcpConn>* wrapper, ISrsInterruptable* owner_coroutine, ISrsContextIdSetter* owner_cid);
// Interface ISrsExecutorHandler
public:
virtual void on_executor_done(ISrsInterruptable* executor);
public:
// Get the SIP device id.
std::string device_id();
// Set the cid of all coroutines.
@ -253,29 +271,26 @@ private:
public:
virtual const SrsContextId& get_id();
virtual std::string desc();
// Interface ISrsStartable
public:
virtual srs_error_t start();
// Interface ISrsOneCycleThreadHandler
public:
virtual srs_error_t cycle();
private:
virtual srs_error_t do_cycle();
srs_error_t do_cycle();
private:
// Create session if no one, or bind to an existed session.
srs_error_t bind_session(SrsSipMessage* msg, SrsLazyObjectWrapper<SrsLazyGbSession>** psession);
srs_error_t bind_session(SrsSipMessage* msg, SrsGbSession** psession);
};
// Start a coroutine to receive SIP messages.
class SrsLazyGbSipTcpReceiver : public ISrsStartable, public ISrsCoroutineHandler
class SrsGbSipTcpReceiver : public ISrsStartable, public ISrsCoroutineHandler
{
private:
SrsCoroutine* trd_;
SrsTcpConnection* conn_;
SrsLazyGbSipTcpConn* sip_;
SrsGbSipTcpConn* sip_;
public:
SrsLazyGbSipTcpReceiver(SrsLazyGbSipTcpConn* sip, SrsTcpConnection* conn);
virtual ~SrsLazyGbSipTcpReceiver();
SrsGbSipTcpReceiver(SrsGbSipTcpConn* sip, SrsTcpConnection* conn);
virtual ~SrsGbSipTcpReceiver();
public:
// Interrupt the receiver coroutine.
void interrupt();
@ -292,7 +307,7 @@ private:
};
// Start a coroutine to send out SIP messages.
class SrsLazyGbSipTcpSender : public ISrsStartable, public ISrsCoroutineHandler
class SrsGbSipTcpSender : public ISrsStartable, public ISrsCoroutineHandler
{
private:
SrsCoroutine* trd_;
@ -301,8 +316,8 @@ private:
std::vector<SrsSipMessage*> msgs_;
srs_cond_t wait_;
public:
SrsLazyGbSipTcpSender(SrsTcpConnection* conn);
virtual ~SrsLazyGbSipTcpSender();
SrsGbSipTcpSender(SrsTcpConnection* conn);
virtual ~SrsGbSipTcpSender();
public:
// Push message to queue, and sender will send out in dedicate coroutine.
void enqueue(SrsSipMessage* msg);
@ -333,27 +348,36 @@ public:
};
// A GB28181 TCP media connection, for PS stream.
class SrsLazyGbMediaTcpConn : public SrsLazyObject, public ISrsResource, public ISrsStartable, public ISrsCoroutineHandler
, public ISrsPsPackHandler
class SrsGbMediaTcpConn : public ISrsResource, public ISrsCoroutineHandler, public ISrsPsPackHandler, public ISrsExecutorHandler
{
private:
bool connected_;
SrsLazyObjectWrapper<SrsLazyGbMediaTcpConn>* wrapper_root_;
SrsLazyObjectWrapper<SrsLazyGbSession>* session_;
// The owner session object, note that we use the raw pointer and should never free it.
SrsGbSession* session_;
uint32_t nn_rtcp_;
private:
// The shared resource which own this object, we should never free it because it's managed by shared ptr.
SrsSharedResource<SrsGbMediaTcpConn>* wrapper_;
// The owner coroutine, allow user to interrupt the loop.
ISrsInterruptable* owner_coroutine_;
ISrsContextIdSetter* owner_cid_;
SrsContextId cid_;
private:
SrsPackContext* pack_;
SrsTcpConnection* conn_;
SrsCoroutine* trd_;
uint8_t* buffer_;
private:
friend class SrsLazyObjectWrapper<SrsLazyGbMediaTcpConn>;
SrsLazyGbMediaTcpConn(SrsLazyObjectWrapper<SrsLazyGbMediaTcpConn>* wrapper_root);
public:
virtual ~SrsLazyGbMediaTcpConn();
SrsGbMediaTcpConn();
virtual ~SrsGbMediaTcpConn();
public:
// Setup object, to keep empty constructor.
void setup(srs_netfd_t stfd);
// Setup the owner, the wrapper is the shared ptr, the interruptable object is the coroutine, and the cid is the context id.
void setup_owner(SrsSharedResource<SrsGbMediaTcpConn>* wrapper, ISrsInterruptable* owner_coroutine, ISrsContextIdSetter* owner_cid);
// Interface ISrsExecutorHandler
public:
virtual void on_executor_done(ISrsInterruptable* executor);
public:
// Whether media is connected.
bool is_connected();
// Interrupt transport by session.
@ -364,9 +388,6 @@ public:
public:
virtual const SrsContextId& get_id();
virtual std::string desc();
// Interface ISrsStartable
public:
virtual srs_error_t start();
// Interface ISrsOneCycleThreadHandler
public:
virtual srs_error_t cycle();
@ -377,7 +398,7 @@ public:
virtual srs_error_t on_ps_pack(SrsPsPacket* ps, const std::vector<SrsTsMessage*>& msgs);
private:
// Create session if no one, or bind to an existed session.
srs_error_t bind_session(uint32_t ssrc, SrsLazyObjectWrapper<SrsLazyGbSession>** psession);
srs_error_t bind_session(uint32_t ssrc, SrsGbSession** psession);
};
// The queue for mpegts over udp to send packets.
@ -402,7 +423,8 @@ public:
class SrsGbMuxer
{
private:
SrsLazyGbSession* session_;
// The owner session object, note that we use the raw pointer and should never free it.
SrsGbSession* session_;
std::string output_;
SrsSimpleRtmpClient* sdk_;
private:
@ -428,10 +450,10 @@ private:
SrsMpegpsQueue* queue_;
SrsPithyPrint* pprint_;
public:
SrsGbMuxer(SrsLazyGbSession* session);
SrsGbMuxer(SrsGbSession* session);
virtual ~SrsGbMuxer();
public:
srs_error_t initialize(std::string output);
void setup(std::string output);
srs_error_t on_ts_message(SrsTsMessage* msg);
private:
virtual srs_error_t on_ts_video(SrsTsMessage* msg, SrsBuffer* avs);