Changeset 243489 in webkit


Ignore:
Timestamp:
Mar 26, 2019 2:34:07 AM (5 years ago)
Author:
Philippe Normand
Message:

[GStreamer] Sound loop with Google Hangouts and WhatsApp notifications
https://bugs.webkit.org/show_bug.cgi?id=189471

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

The media duration is now cached (again). The loop issue was
triggered by the previous version of the code returning positive
infinite duration in didEnd(), followed by the timeupdate event
propagation that would trick the HTMLMediaElement into a new call
to play(). Now the cached duration is updated to current position
at EOS (for forward playback direction only), so the media element
no longer triggers a new play call for those cases.

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:

(WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::loadFull):
(WebCore::MediaPlayerPrivateGStreamer::playbackPosition const):
(WebCore::MediaPlayerPrivateGStreamer::platformDuration const):
(WebCore::MediaPlayerPrivateGStreamer::durationMediaTime const):
(WebCore::MediaPlayerPrivateGStreamer::currentMediaTime const):
(WebCore::MediaPlayerPrivateGStreamer::didEnd):
(WebCore::MediaPlayerPrivateGStreamer::durationChanged):

  • platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
  • platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:

(WebCore::MediaPlayerPrivateGStreamerMSE::currentMediaTime const):

LayoutTests:

  • platform/gtk/TestExpectations:
  • platform/gtk/media/video-playing-and-pause-expected.txt:
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243488 r243489  
     12019-03-26  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GStreamer] Sound loop with Google Hangouts and WhatsApp notifications
     4        https://bugs.webkit.org/show_bug.cgi?id=189471
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        * platform/gtk/TestExpectations:
     9        * platform/gtk/media/video-playing-and-pause-expected.txt:
     10
    1112019-03-26  Antti Koivisto  <antti@apple.com>
    212
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r243437 r243489  
    14611461webkit.org/b/116976 media/video-played-collapse.html [ Failure Pass Crash ]
    14621462
    1463 webkit.org/b/116977 media/event-attributes.html [ Crash Failure Timeout Pass ]
    1464 
    14651463webkit.org/b/103443 fast/parser/parser-yield-timing.html [ Failure Pass ]
    1466 
    1467 webkit.org/b/105191 media/video-playing-and-pause.html [ Failure Pass ]
    1468 
    1469 webkit.org/b/118460 media/media-element-play-after-eos.html [ Timeout Pass ]
    14701464
    14711465webkit.org/b/119009 http/tests/cache/subresource-failover-to-network.html [ Failure Pass ]
     
    16781672
    16791673webkit.org/b/134981 fast/parser/document-write-during-load.html [ Timeout Pass Crash ]
    1680 
    1681 webkit.org/b/81604 media/video-loop.html [ Timeout Pass ]
    16821674
    16831675webkit.org/b/134998 plugins/change-widget-and-click-crash.html [ Timeout Pass Crash ]
     
    38183810webkit.org/b/196201 fast/text/ja-sans-serif.html [ ImageOnlyFailure ]
    38193811
     3812webkit.org/b/116977 media/event-attributes.html [ Failure ]
     3813
    38203814#////////////////////////////////////////////////////////////////////////////////////////
    38213815# End of non-crashing, non-flaky tests failing
  • trunk/LayoutTests/platform/gtk/media/video-playing-and-pause-expected.txt

    r148815 r243489  
    11layer at (0,0) size 800x600
    22  RenderView at (0,0) size 800x600
    3 layer at (0,0) size 800x317
    4   RenderBlock {HTML} at (0,0) size 800x317
    5     RenderBody {BODY} at (8,16) size 784x293
    6       RenderBlock {P} at (0,0) size 784x34
    7         RenderText {#text} at (0,0) size 766x34
    8           text run at (0,0) width 766: "Test that pausing the media element in \"playing\" event handler pauses the media immediately. The video should show the"
    9           text run at (0,17) width 68: "first frame."
    10       RenderBlock (anonymous) at (0,50) size 784x243
     3layer at (0,0) size 800x320
     4  RenderBlock {HTML} at (0,0) size 800x320
     5    RenderBody {BODY} at (8,16) size 784x296
     6      RenderBlock {P} at (0,0) size 784x36
     7        RenderText {#text} at (0,0) size 764x35
     8          text run at (0,0) width 764: "Test that pausing the media element in \"playing\" event handler pauses the media immediately. The video should show the"
     9          text run at (0,18) width 68: "first frame."
     10      RenderBlock (anonymous) at (0,52) size 784x244
    1111        RenderText {#text} at (0,0) size 0x0
    12 layer at (8,66) size 320x240
     12layer at (8,68) size 320x240
    1313  RenderVideo {VIDEO} at (0,0) size 320x240
    14 layer at (8,66) size 320x240
     14layer at (8,68) size 320x240
    1515  RenderFlexibleBox {DIV} at (0,0) size 320x240
    1616    RenderBlock {DIV} at (0,200) size 320x40
    17 layer at (13,271) size 310x30
     17layer at (13,273) size 310x30
    1818  RenderFlexibleBox {DIV} at (5,5) size 310x30 [bgcolor=#141414CC]
    19     RenderButton {INPUT} at (9,0) size 30x30
     19    RenderButton {BUTTON} at (9,0) size 30x30
    2020    RenderSlider {INPUT} at (49,11) size 93x8 [color=#E6E6E659]
    2121      RenderFlexibleBox {DIV} at (0,0) size 93x8 [border: (1px solid #E6E6E659)]
    2222        RenderBlock {DIV} at (1,-2) size 105x12
    23           RenderBlock {DIV} at (-7,0) size 13x12 [color=#FFFFFF]
     23          RenderBlock {DIV} at (-7,0) size 12x12 [color=#FFFFFF]
    2424    RenderBlock {DIV} at (157,0) size 74x30 [color=#FFFFFF]
    2525      RenderText {#text} at (0,7) size 74x15
    2626        text run at (0,7) width 74: "00:00 / 00:06"
    27     RenderButton {INPUT} at (239,0) size 30x30
    28     RenderButton {INPUT} at (271,0) size 30x30
     27    RenderButton {BUTTON} at (239,0) size 30x30
     28    RenderFlexibleBox {DIV} at (271,0) size 30x30
     29      RenderButton {BUTTON} at (0,0) size 30x30
  • trunk/Source/WebCore/ChangeLog

    r243488 r243489  
     12019-03-26  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GStreamer] Sound loop with Google Hangouts and WhatsApp notifications
     4        https://bugs.webkit.org/show_bug.cgi?id=189471
     5
     6        Reviewed by Xabier Rodriguez-Calvar.
     7
     8        The media duration is now cached (again). The loop issue was
     9        triggered by the previous version of the code returning positive
     10        infinite duration in didEnd(), followed by the timeupdate event
     11        propagation that would trick the HTMLMediaElement into a new call
     12        to play(). Now the cached duration is updated to current position
     13        at EOS (for forward playback direction only), so the media element
     14        no longer triggers a new play call for those cases.
     15
     16        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
     17        (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
     18        (WebCore::MediaPlayerPrivateGStreamer::loadFull):
     19        (WebCore::MediaPlayerPrivateGStreamer::playbackPosition const):
     20        (WebCore::MediaPlayerPrivateGStreamer::platformDuration const):
     21        (WebCore::MediaPlayerPrivateGStreamer::durationMediaTime const):
     22        (WebCore::MediaPlayerPrivateGStreamer::currentMediaTime const):
     23        (WebCore::MediaPlayerPrivateGStreamer::didEnd):
     24        (WebCore::MediaPlayerPrivateGStreamer::durationChanged):
     25        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
     26        * platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp:
     27        (WebCore::MediaPlayerPrivateGStreamerMSE::currentMediaTime const):
     28
    1292019-03-26  Antti Koivisto  <antti@apple.com>
    230
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp

    r243197 r243489  
    137137    , m_bufferingPercentage(0)
    138138    , m_cachedPosition(MediaTime::invalidTime())
     139    , m_cachedDuration(MediaTime::invalidTime())
    139140    , m_canFallBackToLastFinishedSeekPosition(false)
    140141    , m_changingRate(false)
     
    143144    , m_isEndReached(false)
    144145    , m_isStreaming(false)
    145     , m_durationAtEOS(MediaTime::invalidTime())
    146146    , m_paused(true)
    147147    , m_playbackRate(1)
     
    303303    m_player->readyStateChanged();
    304304    m_volumeAndMuteInitialized = false;
    305     m_durationAtEOS = MediaTime::invalidTime();
    306305
    307306    if (!m_delayingLoad)
     
    358357MediaTime MediaPlayerPrivateGStreamer::playbackPosition() const
    359358{
     359    GST_TRACE_OBJECT(pipeline(), "isEndReached: %s, seeking: %s, seekTime: %s", boolForPrinting(m_isEndReached), boolForPrinting(m_seeking), m_seekTime.toString().utf8().data());
    360360    if (m_isEndReached && m_seeking)
    361361        return m_seekTime;
     
    364364    static const Seconds positionCacheThreshold = 200_ms;
    365365    Seconds now = WTF::WallTime::now().secondsSinceEpoch();
    366     if (m_lastQueryTime && (now - m_lastQueryTime.value()) < positionCacheThreshold && m_cachedPosition.isValid())
     366    if (m_lastQueryTime && (now - m_lastQueryTime.value()) < positionCacheThreshold && m_cachedPosition.isValid()) {
     367        GST_TRACE_OBJECT(pipeline(), "Returning cached position: %s", m_cachedPosition.toString().utf8().data());
    367368        return m_cachedPosition;
     369    }
    368370
    369371    m_lastQueryTime = now;
     
    376378    gst_query_unref(query);
    377379
    378     GST_TRACE_OBJECT(pipeline(), "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
     380    GST_TRACE_OBJECT(pipeline(), "Position %" GST_TIME_FORMAT ", canFallBackToLastFinishedSeekPosition: %s", GST_TIME_ARGS(position), boolForPrinting(m_canFallBackToLastFinishedSeekPosition));
    379381
    380382    MediaTime playbackPosition = MediaTime::zeroTime();
     
    478480}
    479481
     482MediaTime MediaPlayerPrivateGStreamer::platformDuration() const
     483{
     484    GST_TRACE_OBJECT(pipeline(), "errorOccured: %s, pipeline state: %s", boolForPrinting(m_errorOccured), gst_element_state_get_name(GST_STATE(m_pipeline.get())));
     485    if (m_errorOccured)
     486        return MediaTime::invalidTime();
     487
     488    // The duration query would fail on a not-prerolled pipeline.
     489    if (GST_STATE(m_pipeline.get()) < GST_STATE_PAUSED)
     490        return MediaTime::invalidTime();
     491
     492    int64_t duration = 0;
     493    if (!gst_element_query_duration(m_pipeline.get(), GST_FORMAT_TIME, &duration) || !GST_CLOCK_TIME_IS_VALID(duration)) {
     494        GST_DEBUG_OBJECT(pipeline(), "Time duration query failed for %s", m_url.string().utf8().data());
     495        return MediaTime::positiveInfiniteTime();
     496    }
     497
     498    GST_LOG_OBJECT(pipeline(), "Duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(duration));
     499    return MediaTime(duration, GST_SECOND);
     500}
     501
    480502MediaTime MediaPlayerPrivateGStreamer::durationMediaTime() const
     503{
     504    GST_TRACE_OBJECT(pipeline(), "Cached duration: %s", m_cachedDuration.toString().utf8().data());
     505    if (m_cachedDuration.isValid())
     506        return m_cachedDuration;
     507
     508    MediaTime duration = platformDuration();
     509    if (!duration || duration.isInvalid())
     510        return MediaTime::zeroTime();
     511
     512    m_cachedDuration = duration;
     513
     514    return m_cachedDuration;
     515}
     516
     517MediaTime MediaPlayerPrivateGStreamer::currentMediaTime() const
    481518{
    482519    if (!m_pipeline || m_errorOccured)
    483520        return MediaTime::invalidTime();
    484521
    485     if (m_durationAtEOS.isValid())
    486         return m_durationAtEOS;
    487 
    488     // The duration query would fail on a not-prerolled pipeline.
    489     if (GST_STATE(m_pipeline.get()) < GST_STATE_PAUSED)
    490         return MediaTime::positiveInfiniteTime();
    491 
    492     gint64 timeLength = 0;
    493 
    494     if (!gst_element_query_duration(m_pipeline.get(), GST_FORMAT_TIME, &timeLength) || !GST_CLOCK_TIME_IS_VALID(timeLength)) {
    495         GST_DEBUG_OBJECT(pipeline(), "Time duration query failed for %s", m_url.string().utf8().data());
    496         return MediaTime::positiveInfiniteTime();
    497     }
    498 
    499     GST_LOG("Duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(timeLength));
    500 
    501     return MediaTime(timeLength, GST_SECOND);
    502     // FIXME: handle 3.14.9.5 properly
    503 }
    504 
    505 MediaTime MediaPlayerPrivateGStreamer::currentMediaTime() const
    506 {
    507     if (!m_pipeline || m_errorOccured)
    508         return MediaTime::invalidTime();
    509 
     522    GST_TRACE_OBJECT(pipeline(), "seeking: %s, seekTime: %s", boolForPrinting(m_seeking), m_seekTime.toString().utf8().data());
    510523    if (m_seeking)
    511524        return m_seekTime;
     
    22012214    m_cachedPosition = MediaTime::invalidTime();
    22022215    MediaTime now = currentMediaTime();
    2203     if (now > MediaTime { } && now <= durationMediaTime())
     2216    if (now > MediaTime::zeroTime() && !m_seeking) {
     2217        m_cachedDuration = now;
    22042218        m_player->durationChanged();
     2219    }
    22052220
    22062221    m_isEndReached = true;
    2207     timeChanged();
    22082222
    22092223    if (!m_player->client().mediaPlayerIsLooping()) {
    22102224        m_paused = true;
    2211         m_durationAtEOS = durationMediaTime();
    22122225        changePipelineState(GST_STATE_READY);
    22132226        m_downloadFinished = false;
    22142227    }
     2228    timeChanged();
    22152229}
    22162230
     
    22182232{
    22192233    MediaTime previousDuration = durationMediaTime();
    2220 
    2221     // FIXME: Check if this method is still useful, because it's not doing its work at all
    2222     // since bug #159458 removed a cacheDuration() call here.
     2234    m_cachedDuration = MediaTime::invalidTime();
    22232235
    22242236    // Avoid emiting durationchanged in the case where the previous
  • trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h

    r243197 r243489  
    9292    bool seeking() const override;
    9393
     94    MediaTime platformDuration() const;
    9495    MediaTime durationMediaTime() const override;
    9596    MediaTime currentMediaTime() const override;
     
    188189
    189190protected:
    190     void cacheDuration();
    191 
    192191    bool m_buffering;
    193192    int m_bufferingPercentage;
    194193    mutable MediaTime m_cachedPosition;
     194    mutable MediaTime m_cachedDuration;
    195195    bool m_canFallBackToLastFinishedSeekPosition;
    196196    bool m_changingRate;
     
    199199    mutable bool m_isEndReached;
    200200    mutable bool m_isStreaming;
    201     mutable MediaTime m_durationAtEOS;
    202201    bool m_paused;
    203202    float m_playbackRate;
  • trunk/Source/WebCore/platform/graphics/gstreamer/mse/MediaPlayerPrivateGStreamerMSE.cpp

    r242034 r243489  
    783783        m_isEndReached = true;
    784784        m_cachedPosition = m_mediaTimeDuration;
    785         m_durationAtEOS = m_mediaTimeDuration;
    786785        m_player->timeChanged();
    787786    }
Note: See TracChangeset for help on using the changeset viewer.