mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	RTC: We should cache the sps/pps in source.
This commit is contained in:
		
							parent
							
								
									68de796f77
								
							
						
					
					
						commit
						b8b52f28f5
					
				
					 3 changed files with 91 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -1423,8 +1423,7 @@ srs_error_t SrsRtcPlayer::package_stap_a(SrsRtcSource* source, SrsSharedPtrMessa
 | 
			
		|||
{
 | 
			
		||||
    srs_error_t err = srs_success;
 | 
			
		||||
 | 
			
		||||
    SrsRtcFromRtmpBridger* bridger = dynamic_cast<SrsRtcFromRtmpBridger*>(source->bridger());
 | 
			
		||||
    SrsMetaCache* meta = bridger->cached_meta();
 | 
			
		||||
    SrsMetaCache* meta = source->cached_meta();
 | 
			
		||||
    if (!meta) {
 | 
			
		||||
        return err;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<SrsRtcConsumer*> 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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue