// // Copyright (c) 2013-2025 The SRS Authors // // SPDX-License-Identifier: MIT // #include #include #include #include #include #include #include #include #ifdef SRS_RTSP #include #endif #include using namespace std; ISrsStreamBridge::ISrsStreamBridge() { } ISrsStreamBridge::~ISrsStreamBridge() { } SrsFrameToRtmpBridge::SrsFrameToRtmpBridge(SrsSharedPtr source) { source_ = source; } SrsFrameToRtmpBridge::~SrsFrameToRtmpBridge() { } srs_error_t SrsFrameToRtmpBridge::initialize(ISrsRequest *r) { return srs_success; } srs_error_t SrsFrameToRtmpBridge::on_publish() { srs_error_t err = srs_success; // TODO: FIXME: Should sync with bridge? if ((err = source_->on_publish()) != srs_success) { return srs_error_wrap(err, "source publish"); } return err; } void SrsFrameToRtmpBridge::on_unpublish() { // TODO: FIXME: Should sync with bridge? source_->on_unpublish(); } srs_error_t SrsFrameToRtmpBridge::on_frame(SrsMediaPacket *frame) { return source_->on_frame(frame); } SrsFrameToRtcBridge::SrsFrameToRtcBridge(SrsSharedPtr source) { source_ = source; #if defined(SRS_FFMPEG_FIT) // Use lazy initialization - no need to determine codec/track parameters here rtp_builder_ = new SrsRtcRtpBuilder(this, source); #endif } SrsFrameToRtcBridge::~SrsFrameToRtcBridge() { #ifdef SRS_FFMPEG_FIT srs_freep(rtp_builder_); #endif } srs_error_t SrsFrameToRtcBridge::initialize(ISrsRequest *r) { #ifdef SRS_FFMPEG_FIT return rtp_builder_->initialize(r); #else return srs_success; #endif } srs_error_t SrsFrameToRtcBridge::on_publish() { srs_error_t err = srs_success; // TODO: FIXME: Should sync with bridge? if ((err = source_->on_publish()) != srs_success) { return srs_error_wrap(err, "source publish"); } #ifdef SRS_FFMPEG_FIT if ((err = rtp_builder_->on_publish()) != srs_success) { return srs_error_wrap(err, "rtp builder publish"); } #endif return err; } void SrsFrameToRtcBridge::on_unpublish() { #ifdef SRS_FFMPEG_FIT rtp_builder_->on_unpublish(); #endif // @remark This bridge might be disposed here, so never use it. // TODO: FIXME: Should sync with bridge? source_->on_unpublish(); } srs_error_t SrsFrameToRtcBridge::on_frame(SrsMediaPacket *frame) { #ifdef SRS_FFMPEG_FIT return rtp_builder_->on_frame(frame); #else return srs_success; #endif } srs_error_t SrsFrameToRtcBridge::on_rtp(SrsRtpPacket *pkt) { return source_->on_rtp(pkt); } #ifdef SRS_RTSP SrsFrameToRtspBridge::SrsFrameToRtspBridge(SrsSharedPtr source) { source_ = source; // Use lazy initialization - no need to determine codec/track parameters here rtp_builder_ = new SrsRtspRtpBuilder(this, source); } SrsFrameToRtspBridge::~SrsFrameToRtspBridge() { srs_freep(rtp_builder_); } srs_error_t SrsFrameToRtspBridge::initialize(ISrsRequest *r) { return rtp_builder_->initialize(r); } srs_error_t SrsFrameToRtspBridge::on_publish() { srs_error_t err = srs_success; // TODO: FIXME: Should sync with bridge? if ((err = source_->on_publish()) != srs_success) { return srs_error_wrap(err, "source publish"); } if ((err = rtp_builder_->on_publish()) != srs_success) { return srs_error_wrap(err, "rtp builder publish"); } return err; } void SrsFrameToRtspBridge::on_unpublish() { rtp_builder_->on_unpublish(); // @remark This bridge might be disposed here, so never use it. // TODO: FIXME: Should sync with bridge? source_->on_unpublish(); } srs_error_t SrsFrameToRtspBridge::on_frame(SrsMediaPacket *frame) { return rtp_builder_->on_frame(frame); } srs_error_t SrsFrameToRtspBridge::on_rtp(SrsRtpPacket *pkt) { return source_->on_rtp(pkt); } #endif SrsCompositeBridge::SrsCompositeBridge() { } SrsCompositeBridge::~SrsCompositeBridge() { for (vector::iterator it = bridges_.begin(); it != bridges_.end(); ++it) { ISrsStreamBridge *bridge = *it; srs_freep(bridge); } } srs_error_t SrsCompositeBridge::initialize(ISrsRequest *r) { srs_error_t err = srs_success; for (vector::iterator it = bridges_.begin(); it != bridges_.end(); ++it) { ISrsStreamBridge *bridge = *it; if ((err = bridge->initialize(r)) != srs_success) { return err; } } return err; } srs_error_t SrsCompositeBridge::on_publish() { srs_error_t err = srs_success; for (vector::iterator it = bridges_.begin(); it != bridges_.end(); ++it) { ISrsStreamBridge *bridge = *it; if ((err = bridge->on_publish()) != srs_success) { return err; } } return err; } void SrsCompositeBridge::on_unpublish() { for (vector::iterator it = bridges_.begin(); it != bridges_.end(); ++it) { ISrsStreamBridge *bridge = *it; bridge->on_unpublish(); } } srs_error_t SrsCompositeBridge::on_frame(SrsMediaPacket *frame) { srs_error_t err = srs_success; for (vector::iterator it = bridges_.begin(); it != bridges_.end(); ++it) { ISrsStreamBridge *bridge = *it; if ((err = bridge->on_frame(frame)) != srs_success) { return err; } } return err; } SrsCompositeBridge *SrsCompositeBridge::append(ISrsStreamBridge *bridge) { bridges_.push_back(bridge); return this; }