1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00

RTC: We should cache the sps/pps in source.

This commit is contained in:
winlin 2020-05-13 16:21:42 +08:00
parent 68de796f77
commit b8b52f28f5
3 changed files with 91 additions and 30 deletions

View file

@ -1423,8 +1423,7 @@ srs_error_t SrsRtcPlayer::package_stap_a(SrsRtcSource* source, SrsSharedPtrMessa
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
SrsRtcFromRtmpBridger* bridger = dynamic_cast<SrsRtcFromRtmpBridger*>(source->bridger()); SrsMetaCache* meta = source->cached_meta();
SrsMetaCache* meta = bridger->cached_meta();
if (!meta) { if (!meta) {
return err; return err;
} }

View file

@ -262,6 +262,8 @@ SrsRtcSource::SrsRtcSource()
req = NULL; req = NULL;
bridger_ = new SrsRtcFromRtmpBridger(this); bridger_ = new SrsRtcFromRtmpBridger(this);
format = new SrsRtmpFormat();
meta = new SrsMetaCache();
} }
SrsRtcSource::~SrsRtcSource() SrsRtcSource::~SrsRtcSource()
@ -272,6 +274,8 @@ SrsRtcSource::~SrsRtcSource()
srs_freep(req); srs_freep(req);
srs_freep(bridger_); srs_freep(bridger_);
srs_freep(format);
srs_freep(meta);
} }
srs_error_t SrsRtcSource::initialize(SrsRequest* r) 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"); return srs_error_wrap(err, "bridge initialize");
} }
if ((err = format->initialize()) != srs_success) {
return srs_error_wrap(err, "format initialize");
}
return err; return err;
} }
@ -333,6 +341,11 @@ ISrsSourceBridger* SrsRtcSource::bridger()
return bridger_; return bridger_;
} }
SrsMetaCache* SrsRtcSource::cached_meta()
{
return meta;
}
srs_error_t SrsRtcSource::create_consumer(SrsConnection* conn, SrsRtcConsumer*& consumer) srs_error_t SrsRtcSource::create_consumer(SrsConnection* conn, SrsRtcConsumer*& consumer)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -384,6 +397,10 @@ srs_error_t SrsRtcSource::on_publish()
return srs_error_wrap(err, "source id change"); 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. // TODO: FIXME: Handle by statistic.
return err; return err;
@ -396,6 +413,11 @@ void SrsRtcSource::on_unpublish()
return; 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"); srs_trace("cleanup when unpublish");
_can_publish = true; _can_publish = true;
@ -432,6 +454,25 @@ srs_error_t SrsRtcSource::on_video(SrsCommonMessage* shared_video)
return srs_error_wrap(err, "create message"); 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. // directly process the video message.
return on_video_imp(&msg); return on_video_imp(&msg);
} }
@ -466,11 +507,44 @@ srs_error_t SrsRtcSource::on_video_imp(SrsSharedPtrMessage* msg)
return err; 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) SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcSource* source)
{ {
req = NULL; req = NULL;
source_ = source; source_ = source;
meta = new SrsMetaCache();
format = new SrsRtmpFormat(); format = new SrsRtmpFormat();
codec = new SrsAudioRecode(kChannel, kSamplerate); codec = new SrsAudioRecode(kChannel, kSamplerate);
discard_aac = false; discard_aac = false;
@ -479,7 +553,6 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcSource* source)
SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger() SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger()
{ {
srs_freep(meta);
srs_freep(format); srs_freep(format);
srs_freep(codec); srs_freep(codec);
} }
@ -506,11 +579,6 @@ srs_error_t SrsRtcFromRtmpBridger::initialize(SrsRequest* r)
return err; return err;
} }
SrsMetaCache* SrsRtcFromRtmpBridger::cached_meta()
{
return meta;
}
srs_error_t SrsRtcFromRtmpBridger::on_publish() srs_error_t SrsRtcFromRtmpBridger::on_publish()
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -520,10 +588,6 @@ srs_error_t SrsRtcFromRtmpBridger::on_publish()
return srs_error_wrap(err, "source 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; return err;
} }
@ -531,11 +595,6 @@ void SrsRtcFromRtmpBridger::on_unpublish()
{ {
// TODO: FIXME: Should sync with bridger? // TODO: FIXME: Should sync with bridger?
source_->on_unpublish(); 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) 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; 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 // 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) { if (is_sequence_header && (err = meta->update_vsh(msg)) != srs_success) {
return srs_error_wrap(err, "meta update video"); 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"); 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); return source_->on_video_imp(msg);
} }

View file

@ -120,6 +120,8 @@ private:
SrsRtcPublisher* rtc_publisher_; SrsRtcPublisher* rtc_publisher_;
// Transmux RTMP to RTC. // Transmux RTMP to RTC.
SrsRtcFromRtmpBridger* bridger_; SrsRtcFromRtmpBridger* bridger_;
// The metadata cache.
SrsMetaCache* meta;
private: private:
// To delivery stream to clients. // To delivery stream to clients.
std::vector<SrsRtcConsumer*> consumers; std::vector<SrsRtcConsumer*> consumers;
@ -139,6 +141,8 @@ public:
virtual int pre_source_id(); virtual int pre_source_id();
// Get the bridger. // Get the bridger.
ISrsSourceBridger* bridger(); ISrsSourceBridger* bridger();
// For RTC, we need to package SPS/PPS(in cached meta) before each IDR.
SrsMetaCache* cached_meta();
public: public:
// Create consumer // Create consumer
// @param consumer, output the 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_video(SrsCommonMessage* video);
virtual srs_error_t on_audio_imp(SrsSharedPtrMessage* audio); virtual srs_error_t on_audio_imp(SrsSharedPtrMessage* audio);
virtual srs_error_t on_video_imp(SrsSharedPtrMessage* video); 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 class SrsRtcFromRtmpBridger : public ISrsSourceBridger
@ -172,8 +181,6 @@ class SrsRtcFromRtmpBridger : public ISrsSourceBridger
private: private:
SrsRequest* req; SrsRequest* req;
SrsRtcSource* source_; SrsRtcSource* source_;
// The metadata cache.
SrsMetaCache* meta;
// The format, codec information. // The format, codec information.
SrsRtmpFormat* format; SrsRtmpFormat* format;
private: private:
@ -185,8 +192,6 @@ public:
virtual ~SrsRtcFromRtmpBridger(); virtual ~SrsRtcFromRtmpBridger();
public: public:
virtual srs_error_t initialize(SrsRequest* r); 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 srs_error_t on_publish();
virtual void on_unpublish(); virtual void on_unpublish();
virtual srs_error_t on_audio(SrsSharedPtrMessage* audio); virtual srs_error_t on_audio(SrsSharedPtrMessage* audio);