diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 127647d89..d019896ce 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1423,8 +1423,7 @@ srs_error_t SrsRtcPlayer::package_stap_a(SrsRtcSource* source, SrsSharedPtrMessa { srs_error_t err = srs_success; - SrsRtcFromRtmpBridger* bridger = dynamic_cast(source->bridger()); - SrsMetaCache* meta = bridger->cached_meta(); + SrsMetaCache* meta = source->cached_meta(); if (!meta) { return err; } diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 71c9e5c9a..59b4db139 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -262,6 +262,8 @@ SrsRtcSource::SrsRtcSource() req = NULL; bridger_ = new SrsRtcFromRtmpBridger(this); + format = new SrsRtmpFormat(); + meta = new SrsMetaCache(); } SrsRtcSource::~SrsRtcSource() @@ -272,6 +274,8 @@ SrsRtcSource::~SrsRtcSource() srs_freep(req); srs_freep(bridger_); + srs_freep(format); + srs_freep(meta); } srs_error_t SrsRtcSource::initialize(SrsRequest* r) @@ -284,6 +288,10 @@ srs_error_t SrsRtcSource::initialize(SrsRequest* r) return srs_error_wrap(err, "bridge initialize"); } + if ((err = format->initialize()) != srs_success) { + return srs_error_wrap(err, "format initialize"); + } + return err; } @@ -333,6 +341,11 @@ ISrsSourceBridger* SrsRtcSource::bridger() return bridger_; } +SrsMetaCache* SrsRtcSource::cached_meta() +{ + return meta; +} + srs_error_t SrsRtcSource::create_consumer(SrsConnection* conn, SrsRtcConsumer*& consumer) { srs_error_t err = srs_success; @@ -384,6 +397,10 @@ srs_error_t SrsRtcSource::on_publish() return srs_error_wrap(err, "source id change"); } + // Reset the metadata cache, to make VLC happy when disable/enable stream. + // @see https://github.com/ossrs/srs/issues/1630#issuecomment-597979448 + meta->clear(); + // TODO: FIXME: Handle by statistic. return err; @@ -396,6 +413,11 @@ void SrsRtcSource::on_unpublish() return; } + // Reset the metadata cache, to make VLC happy when disable/enable stream. + // @see https://github.com/ossrs/srs/issues/1630#issuecomment-597979448 + meta->update_previous_vsh(); + meta->update_previous_ash(); + srs_trace("cleanup when unpublish"); _can_publish = true; @@ -432,6 +454,25 @@ srs_error_t SrsRtcSource::on_video(SrsCommonMessage* shared_video) return srs_error_wrap(err, "create message"); } + bool is_sequence_header = SrsFlvVideo::sh(msg.payload, msg.size); + if (is_sequence_header && (err = meta->update_vsh(&msg)) != srs_success) { + return srs_error_wrap(err, "meta update video"); + } + + // user can disable the sps parse to workaround when parse sps failed. + // @see https://github.com/ossrs/srs/issues/474 + if (is_sequence_header) { + format->avc_parse_sps = _srs_config->get_parse_sps(req->vhost); + } + + if ((err = format->on_video(&msg)) != srs_success) { + return srs_error_wrap(err, "format consume video"); + } + + if ((err = filter(&msg, format)) != srs_success) { + return srs_error_wrap(err, "filter video"); + } + // directly process the video message. return on_video_imp(&msg); } @@ -466,11 +507,44 @@ srs_error_t SrsRtcSource::on_video_imp(SrsSharedPtrMessage* msg) return err; } +srs_error_t SrsRtcSource::filter(SrsSharedPtrMessage* shared_frame, SrsFormat* format) +{ + srs_error_t err = srs_success; + + // If IDR, we will insert SPS/PPS before IDR frame. + if (format->video && format->video->has_idr) { + shared_frame->set_has_idr(true); + } + + // Update samples to shared frame. + for (int i = 0; i < format->video->nb_samples; ++i) { + SrsSample* sample = &format->video->samples[i]; + + // Because RTC does not support B-frame, so we will drop them. + // TODO: Drop B-frame in better way, which not cause picture corruption. + if (true) { + if ((err = sample->parse_bframe()) != srs_success) { + return srs_error_wrap(err, "parse bframe"); + } + if (sample->bframe) { + continue; + } + } + } + + if (format->video->nb_samples <= 0) { + return err; + } + + shared_frame->set_samples(format->video->samples, format->video->nb_samples); + + return err; +} + SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcSource* source) { req = NULL; source_ = source; - meta = new SrsMetaCache(); format = new SrsRtmpFormat(); codec = new SrsAudioRecode(kChannel, kSamplerate); discard_aac = false; @@ -479,7 +553,6 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcSource* source) SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger() { - srs_freep(meta); srs_freep(format); srs_freep(codec); } @@ -506,11 +579,6 @@ srs_error_t SrsRtcFromRtmpBridger::initialize(SrsRequest* r) return err; } -SrsMetaCache* SrsRtcFromRtmpBridger::cached_meta() -{ - return meta; -} - srs_error_t SrsRtcFromRtmpBridger::on_publish() { srs_error_t err = srs_success; @@ -520,10 +588,6 @@ srs_error_t SrsRtcFromRtmpBridger::on_publish() return srs_error_wrap(err, "source publish"); } - // Reset the metadata cache, to make VLC happy when disable/enable stream. - // @see https://github.com/ossrs/srs/issues/1630#issuecomment-597979448 - meta->clear(); - return err; } @@ -531,11 +595,6 @@ void SrsRtcFromRtmpBridger::on_unpublish() { // TODO: FIXME: Should sync with bridger? source_->on_unpublish(); - - // Reset the metadata cache, to make VLC happy when disable/enable stream. - // @see https://github.com/ossrs/srs/issues/1630#issuecomment-597979448 - meta->update_previous_vsh(); - meta->update_previous_ash(); } srs_error_t SrsRtcFromRtmpBridger::on_audio(SrsSharedPtrMessage* msg) @@ -637,15 +696,9 @@ srs_error_t SrsRtcFromRtmpBridger::on_video(SrsSharedPtrMessage* msg) { srs_error_t err = srs_success; - bool is_sequence_header = SrsFlvVideo::sh(msg->payload, msg->size); - - // user can disable the sps parse to workaround when parse sps failed. - // @see https://github.com/ossrs/srs/issues/474 - if (is_sequence_header) { - format->avc_parse_sps = _srs_config->get_parse_sps(req->vhost); - } - // cache the sequence header if h264 + bool is_sequence_header = SrsFlvVideo::sh(msg->payload, msg->size); + SrsMetaCache* meta = source_->cached_meta(); if (is_sequence_header && (err = meta->update_vsh(msg)) != srs_success) { return srs_error_wrap(err, "meta update video"); } @@ -654,6 +707,10 @@ srs_error_t SrsRtcFromRtmpBridger::on_video(SrsSharedPtrMessage* msg) return srs_error_wrap(err, "format consume video"); } + if ((err = filter(msg, format)) != srs_success) { + return srs_error_wrap(err, "filter video"); + } + return source_->on_video_imp(msg); } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 08a9093a4..8711a3269 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -120,6 +120,8 @@ private: SrsRtcPublisher* rtc_publisher_; // Transmux RTMP to RTC. SrsRtcFromRtmpBridger* bridger_; + // The metadata cache. + SrsMetaCache* meta; private: // To delivery stream to clients. std::vector consumers; @@ -139,6 +141,8 @@ public: virtual int pre_source_id(); // Get the bridger. ISrsSourceBridger* bridger(); + // For RTC, we need to package SPS/PPS(in cached meta) before each IDR. + SrsMetaCache* cached_meta(); public: // Create consumer // @param consumer, output the create consumer. @@ -165,6 +169,11 @@ public: virtual srs_error_t on_video(SrsCommonMessage* video); virtual srs_error_t on_audio_imp(SrsSharedPtrMessage* audio); virtual srs_error_t on_video_imp(SrsSharedPtrMessage* video); +private: + // The format, codec information. + // TODO: FIXME: Remove it. + SrsRtmpFormat* format; + srs_error_t filter(SrsSharedPtrMessage* shared_video, SrsFormat* format); }; class SrsRtcFromRtmpBridger : public ISrsSourceBridger @@ -172,8 +181,6 @@ class SrsRtcFromRtmpBridger : public ISrsSourceBridger private: SrsRequest* req; SrsRtcSource* source_; - // The metadata cache. - SrsMetaCache* meta; // The format, codec information. SrsRtmpFormat* format; private: @@ -185,8 +192,6 @@ public: virtual ~SrsRtcFromRtmpBridger(); public: virtual srs_error_t initialize(SrsRequest* r); - // For RTC, we need to package SPS/PPS(in cached meta) before each IDR. - SrsMetaCache* cached_meta(); virtual srs_error_t on_publish(); virtual void on_unpublish(); virtual srs_error_t on_audio(SrsSharedPtrMessage* audio);