Changeset 248721 in webkit


Ignore:
Timestamp:
Aug 15, 2019 10:17:52 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

[GStreamer] Deal with slow buffer consumption in GStreamerMediaStreamSource
https://bugs.webkit.org/show_bug.cgi?id=200633

Refactoring the GStreamerMediaStreamSource factoring out streams specific
data in a dedicated structure.

Patch by Thibault Saunier <tsaunier@igalia.com> on 2019-08-15
Reviewed by Philippe Normand.

No new tests, since I do not see how to reproduce that in a test in a simple way,
this aims at enhancing user experience when running under high load.

  • platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:

(WebCore::_WebKitMediaStreamSrc::SourceData::reset):
(WebCore::_WebKitMediaStreamSrc::SourceData::src):
(WebCore::_WebKitMediaStreamSrc::SourceData::setSrc):
(WebCore::_WebKitMediaStreamSrc::SourceData::isUsed):
(WebCore::_WebKitMediaStreamSrc::SourceData::pushSample):
(WebCore::webkitMediaStreamSrcDispose):
(WebCore::webkit_media_stream_src_init):
(WebCore::webkitMediaStreamSrcNeedDataCb):
(WebCore::webkitMediaStreamSrcEnoughDataCb):
(WebCore::webkitMediaStreamSrcSetupAppSrc):
(WebCore::webkitMediaStreamSrcRemoveTrackByType):
(WebCore::webkitMediaStreamSrcPushVideoSample):
(WebCore::webkitMediaStreamSrcPushAudioSample):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r248718 r248721  
     12019-08-15  Thibault Saunier  <tsaunier@igalia.com>
     2
     3        [GStreamer] Deal with slow buffer consumption in GStreamerMediaStreamSource
     4        https://bugs.webkit.org/show_bug.cgi?id=200633
     5
     6        Refactoring the GStreamerMediaStreamSource factoring out streams specific
     7        data in a dedicated structure.
     8
     9        Reviewed by Philippe Normand.
     10
     11        No new tests, since I do not see how to reproduce that in a test in a simple way,
     12        this aims at enhancing user experience when running under high load.
     13
     14        * platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
     15        (WebCore::_WebKitMediaStreamSrc::SourceData::reset):
     16        (WebCore::_WebKitMediaStreamSrc::SourceData::src):
     17        (WebCore::_WebKitMediaStreamSrc::SourceData::setSrc):
     18        (WebCore::_WebKitMediaStreamSrc::SourceData::isUsed):
     19        (WebCore::_WebKitMediaStreamSrc::SourceData::pushSample):
     20        (WebCore::webkitMediaStreamSrcDispose):
     21        (WebCore::webkit_media_stream_src_init):
     22        (WebCore::webkitMediaStreamSrcNeedDataCb):
     23        (WebCore::webkitMediaStreamSrcEnoughDataCb):
     24        (WebCore::webkitMediaStreamSrcSetupAppSrc):
     25        (WebCore::webkitMediaStreamSrcRemoveTrackByType):
     26        (WebCore::webkitMediaStreamSrcPushVideoSample):
     27        (WebCore::webkitMediaStreamSrcPushAudioSample):
     28
    1292019-08-15  Youenn Fablet  <youenn@apple.com>
    230
  • trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp

    r246677 r248721  
    172172    gchar* uri;
    173173
    174     GstElement* audioSrc;
    175     GstClockTime firstAudioBufferPts;
    176     GstElement* videoSrc;
    177     GstClockTime firstFramePts;
     174    struct SourceData {
     175        GRefPtr<GstElement> m_src;
     176        void reset(bool isVideo)
     177        {
     178            m_firstBufferPts = GST_CLOCK_TIME_NONE;
     179            m_isVideo = isVideo;
     180            m_src = nullptr;
     181        }
     182
     183        GstElement* src()
     184        {
     185            return m_src.get();
     186        }
     187
     188        static void needDataCb(GstElement*, guint, WebKitMediaStreamSrc::SourceData *self)
     189        {
     190            self->setEnoughData(false);
     191        }
     192
     193        static void enoughDataCb(GstElement*, WebKitMediaStreamSrc::SourceData *self)
     194        {
     195            self->setEnoughData(true);
     196        }
     197
     198
     199        void setSrc(GstElement *src)
     200        {
     201            m_src = adoptGRef(GST_ELEMENT(g_object_ref_sink(src)));
     202            if (GST_IS_APP_SRC(src)) {
     203                g_object_set(src, "is-live", true, "format", GST_FORMAT_TIME, "emit-signals", TRUE, "min-percent", 100, nullptr);
     204                g_signal_connect(src, "enough-data", G_CALLBACK(enoughDataCb), this);
     205                g_signal_connect(src, "need-data", G_CALLBACK(needDataCb), this);
     206            }
     207        }
     208
     209        bool isUsed()
     210        {
     211            return !!m_src;
     212        }
     213
     214        void setEnoughData(bool enough)
     215        {
     216            m_enoughData = enough;
     217        }
     218
     219        void pushSample(GstSample *sample)
     220        {
     221            if (!m_src)
     222                return;
     223
     224            bool drop = m_enoughData;
     225            auto buffer = gst_sample_get_buffer(sample);
     226            auto caps = gst_sample_get_caps(sample);
     227            if (!GST_CLOCK_TIME_IS_VALID(m_firstBufferPts)) {
     228                m_firstBufferPts = GST_BUFFER_PTS(buffer);
     229                auto pad = adoptGRef(gst_element_get_static_pad(m_src.get(), "src"));
     230                gst_pad_set_offset(pad.get(), -m_firstBufferPts);
     231            }
     232
     233            if (m_isVideo && drop) {
     234                drop = (gst_structure_has_name(gst_caps_get_structure(caps, 0), "video/x-raw")
     235                    || GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT));
     236            }
     237
     238            if (drop) {
     239                m_needsDiscont = true;
     240                GST_INFO_OBJECT(m_src.get(), "%s queue full already... not pushing", m_isVideo ? "Video" : "Audio");
     241                return;
     242            }
     243
     244            if (m_needsDiscont) {
     245                GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DISCONT);
     246                m_needsDiscont = false;
     247            }
     248
     249            gst_app_src_push_sample(GST_APP_SRC(m_src.get()), sample);
     250        }
     251    private:
     252        GstClockTime m_firstBufferPts;
     253        bool m_enoughData;
     254        bool m_needsDiscont;
     255        bool m_isVideo;
     256    };
     257
     258    SourceData audioSrc;
     259    SourceData videoSrc;
    178260
    179261    std::unique_ptr<WebKitMediaStreamTrackObserver> mediaStreamTrackObserver;
     
    275357    WebKitMediaStreamSrc* self = WEBKIT_MEDIA_STREAM_SRC(object);
    276358
    277     if (self->audioSrc) {
    278         gst_bin_remove(GST_BIN(self), self->audioSrc);
    279         self->audioSrc = nullptr;
    280     }
    281 
    282     if (self->videoSrc) {
    283         gst_bin_remove(GST_BIN(self), self->videoSrc);
    284         self->videoSrc = nullptr;
     359    if (self->audioSrc.isUsed()) {
     360        gst_bin_remove(GST_BIN(self), self->audioSrc.src());
     361        self->audioSrc.reset(false);
     362    }
     363
     364    if (self->videoSrc.isUsed()) {
     365        gst_bin_remove(GST_BIN(self), self->videoSrc.src());
     366        self->videoSrc.reset(true);
    285367    }
    286368}
     
    355437    self->mediaStreamObserver = std::make_unique<WebKitMediaStreamObserver>(self);
    356438    self->flowCombiner = gst_flow_combiner_new();
    357     self->firstAudioBufferPts = GST_CLOCK_TIME_NONE;
    358     self->firstFramePts = GST_CLOCK_TIME_NONE;
     439    self->videoSrc.reset(true);
     440    self->audioSrc.reset(false);
    359441}
    360442
     
    468550
    469551static gboolean webkitMediaStreamSrcSetupAppSrc(WebKitMediaStreamSrc* self,
    470     MediaStreamTrackPrivate* track, GstElement** element,
     552    MediaStreamTrackPrivate* track, WebKitMediaStreamSrc::SourceData* data,
    471553    GstStaticPadTemplate* pad_template, bool onlyTrack)
    472554{
    473     *element = gst_element_factory_make("appsrc", nullptr);
    474     g_object_set(*element, "is-live", true, "format", GST_FORMAT_TIME, nullptr);
    475 
    476     return webkitMediaStreamSrcSetupSrc(self, track, *element, pad_template, TRUE, onlyTrack);
     555    data->setSrc(gst_element_factory_make("appsrc", nullptr));
     556    if (track->isCaptureTrack())
     557        g_object_set(data->src(), "do-timestamp", true, nullptr);
     558
     559    return webkitMediaStreamSrcSetupSrc(self, track, data->src(), pad_template, TRUE, onlyTrack);
    477560}
    478561
     
    511594{
    512595    if (trackType == RealtimeMediaSource::Type::Audio) {
    513         if (self->audioSrc) {
    514             gst_element_set_state(self->audioSrc, GST_STATE_NULL);
    515             gst_bin_remove(GST_BIN(self), self->audioSrc);
    516             self->audioSrc = nullptr;
     596        if (self->audioSrc.isUsed()) {
     597            gst_element_set_state(self->audioSrc.src(), GST_STATE_NULL);
     598            gst_bin_remove(GST_BIN(self), self->audioSrc.src());
     599            self->audioSrc.reset(false);
    517600        }
    518601    } else if (trackType == RealtimeMediaSource::Type::Video) {
    519         if (self->videoSrc) {
    520             gst_element_set_state(self->videoSrc, GST_STATE_NULL);
    521             gst_bin_remove(GST_BIN(self), self->videoSrc);
    522             self->videoSrc = nullptr;
     602        if (self->videoSrc.isUsed()) {
     603            gst_element_set_state(self->videoSrc.src(), GST_STATE_NULL);
     604            gst_bin_remove(GST_BIN(self), self->videoSrc.src());
     605            self->videoSrc.reset(true);
    523606        }
    524607    } else
     
    545628static void webkitMediaStreamSrcPushVideoSample(WebKitMediaStreamSrc* self, GstSample* gstsample)
    546629{
    547     if (self->videoSrc) {
    548         if (!GST_CLOCK_TIME_IS_VALID(self->firstFramePts)) {
    549             auto buffer = gst_sample_get_buffer(gstsample);
    550 
    551             self->firstFramePts = GST_BUFFER_PTS(buffer);
    552             auto pad = adoptGRef(gst_element_get_static_pad(self->videoSrc, "src"));
    553             gst_pad_set_offset(pad.get(), -self->firstFramePts);
    554         }
    555 
    556         gst_app_src_push_sample(GST_APP_SRC(self->videoSrc), gstsample);
    557     }
     630    self->videoSrc.pushSample(gstsample);
    558631}
    559632
    560633static void webkitMediaStreamSrcPushAudioSample(WebKitMediaStreamSrc* self, GstSample* gstsample)
    561634{
    562     if (self->audioSrc) {
    563         if (!GST_CLOCK_TIME_IS_VALID(self->firstAudioBufferPts)) {
    564             auto buffer = gst_sample_get_buffer(gstsample);
    565 
    566             self->firstAudioBufferPts = GST_BUFFER_PTS(buffer);
    567             auto pad = adoptGRef(gst_element_get_static_pad(self->audioSrc, "src"));
    568             gst_pad_set_offset(pad.get(), -self->firstAudioBufferPts);
    569         }
    570         gst_app_src_push_sample(GST_APP_SRC(self->audioSrc), gstsample);
    571     }
     635    self->audioSrc.pushSample(gstsample);
    572636}
    573637
Note: See TracChangeset for help on using the changeset viewer.