Changeset 270106 in webkit


Ignore:
Timestamp:
Nov 20, 2020 4:19:20 AM (3 years ago)
Author:
Philippe Normand
Message:

[MSE] Infinite loop in sample eviction when duration is NaN
https://bugs.webkit.org/show_bug.cgi?id=218228

Reviewed by Darin Adler.

Source/WebCore:

Avoid infinite loop in evictCodedFrames for live streams

When playing live streams the MediaSource DOM duration attribute has no meaning
and would thus be set as +inf. When seeks are triggered to positions prior to
the current playback position the SourceBuffer might attempt to free some space
in order to keep the amount of memory used under control. It proceeds in 2
steps:

  1. Attempt to free space represented by buffered range from media start up until current playback position - 30 seconds.
  2. If step 1 didn't free enough memory, attempt to release memory represented by buffered ranges starting from current playback position + 30 seconds until media duration.

Step 2 here wasn't taking into account the case where MediaSource.duration is
actually invalid, and thus was entering an infinite loop.

Test: media/media-source/live-rewind-seek-and-evict.html

  • Modules/mediasource/SourceBuffer.cpp:

(WebCore::SourceBuffer::evictCodedFrames):

Source/WTF:

  • wtf/MediaTime.h: New isFinite() method, to check if the MediaTime is valid and represents

a finite value, eg not NaN or Infinite.

LayoutTests:

  • media/media-source/live-rewind-seek-and-evict-expected.txt: Renamed from LayoutTests/platform/glib/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt.
  • media/media-source/live-rewind-seek-and-evict.html: Added.
  • media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt:
  • media/media-source/mock-media-source.js:

(makeAInit):

  • platform/mac/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt: Copied from LayoutTests/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt.
Location:
trunk
Files:
1 added
7 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r270103 r270106  
     12020-11-20  Philippe Normand  <pnormand@igalia.com>
     2
     3        [MSE] Infinite loop in sample eviction when duration is NaN
     4        https://bugs.webkit.org/show_bug.cgi?id=218228
     5
     6        Reviewed by Darin Adler.
     7
     8        * media/media-source/live-rewind-seek-and-evict-expected.txt: Renamed from LayoutTests/platform/glib/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt.
     9        * media/media-source/live-rewind-seek-and-evict.html: Added.
     10        * media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt:
     11        * media/media-source/mock-media-source.js:
     12        (makeAInit):
     13        * platform/mac/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt: Copied from LayoutTests/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt.
     14
    1152020-11-20  Fujii Hironori  <Hironori.Fujii@sony.com>
    216
  • trunk/LayoutTests/media/media-source/live-rewind-seek-and-evict-expected.txt

    r270103 r270106  
    1 
     1This tests rewind seeks in a live stream. The sample eviction algorithm should attempt to remove some samples without going into an infinite loop.
    22EVENT(sourceopen)
    33EVENT(updateend)
    4 EXPECTED (video.currentTime == '120') OK
     4EXPECTED (isNaN(source.duration) == 'true') OK
    55Appending PTS=120
    66EVENT(updateend)
     
    116116EVENT(updateend)
    117117Appending PTS=176
    118 EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.') OK
    119 EXPECTED (bufferedRanges() == '[ 120...176 ]') OK
     118EVENT(updateend)
     119EXPECTED (video.currentTime == '175') OK
     120EXPECTED (bufferedRanges() == '[ 120...132, 162...177 ]') OK
    120121EXPECTED (video.currentTime == '115') OK
     122Appending PTS=109
     123EVENT(updateend)
     124Appending PTS=110
     125EVENT(updateend)
     126Appending PTS=111
     127EVENT(updateend)
     128Appending PTS=112
     129EVENT(updateend)
     130Appending PTS=113
     131EVENT(updateend)
     132Appending PTS=114
     133EVENT(updateend)
    121134Appending PTS=115
    122135EVENT(updateend)
     
    127140Appending PTS=118
    128141EVENT(updateend)
    129 EXPECTED (exception != 'QuotaExceededError: The quota has been exceeded.') OK
    130 EXPECTED (bufferedRanges() == '[ 115...119, 120...170 ]') OK
     142Appending PTS=119
     143EVENT(updateend)
     144EXPECTED (bufferedRanges() == '[ 109...132, 162...177 ]') OK
    131145END OF TEST
    132146
  • trunk/LayoutTests/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt

    r246195 r270106  
    116116EVENT(updateend)
    117117Appending PTS=176
    118 EVENT(updateend)
    119 EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.'), OBSERVED 'null' FAIL
    120 EXPECTED (bufferedRanges() == '[ 120...176 ]'), OBSERVED '[ 120...177 ]' FAIL
     118EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.') OK
     119EXPECTED (bufferedRanges() == '[ 120...176 ]') OK
    121120EXPECTED (video.currentTime == '115') OK
    122121Appending PTS=115
  • trunk/LayoutTests/media/media-source/mock-media-source.js

    r237651 r270106  
    7676    array.set(stringToArray('init'));
    7777
    78     var view = new DataView(buffer);
    79     var timeScale = 1000;
    80     view.setUint32(4, byteLength, true);
    81     view.setInt32(8, duration * timeScale, true);
    82     view.setInt32(12, timeScale, true);
     78    if (!isNaN(duration)) {
     79        var view = new DataView(buffer);
     80        var timeScale = 1000;
     81        view.setUint32(4, byteLength, true);
     82        view.setInt32(8, duration * timeScale, true);
     83        view.setInt32(12, timeScale, true);
     84    }
    8385
    8486    var offset = 16;
  • trunk/Source/WTF/ChangeLog

    r270067 r270106  
     12020-11-20  Philippe Normand  <pnormand@igalia.com>
     2
     3        [MSE] Infinite loop in sample eviction when duration is NaN
     4        https://bugs.webkit.org/show_bug.cgi?id=218228
     5
     6        Reviewed by Darin Adler.
     7
     8        * wtf/MediaTime.h: New isFinite() method, to check if the MediaTime is valid and represents
     9        a finite value, eg not NaN or Infinite.
     10
    1112020-11-19  Ada Chan  <adachan@apple.com>
    212
  • trunk/Source/WTF/wtf/MediaTime.h

    r259917 r270106  
    9797    bool isNegativeInfinite() const { return m_timeFlags & NegativeInfinite; }
    9898    bool isIndefinite() const { return m_timeFlags & Indefinite; }
     99    bool isFinite() const { return !isInvalid() && !isIndefinite() && !isPositiveInfinite() && !isNegativeInfinite(); }
    99100    bool hasDoubleValue() const { return m_timeFlags & DoubleValue; }
    100101    uint8_t timeFlags() const { return m_timeFlags; }
  • trunk/Source/WebCore/ChangeLog

    r270103 r270106  
     12020-11-20  Philippe Normand  <pnormand@igalia.com>
     2
     3        [MSE] Infinite loop in sample eviction when duration is NaN
     4        https://bugs.webkit.org/show_bug.cgi?id=218228
     5
     6        Reviewed by Darin Adler.
     7
     8        Avoid infinite loop in evictCodedFrames for live streams
     9
     10        When playing live streams the MediaSource DOM duration attribute has no meaning
     11        and would thus be set as +inf. When seeks are triggered to positions prior to
     12        the current playback position the SourceBuffer might attempt to free some space
     13        in order to keep the amount of memory used under control. It proceeds in 2
     14        steps:
     15
     16        1. Attempt to free space represented by buffered range from media start up until
     17           current playback position - 30 seconds.
     18        2. If step 1 didn't free enough memory, attempt to release memory represented by
     19           buffered ranges starting from current playback position + 30 seconds until media
     20           duration.
     21
     22        Step 2 here wasn't taking into account the case where MediaSource.duration is
     23        actually invalid, and thus was entering an infinite loop.
     24
     25        Test: media/media-source/live-rewind-seek-and-evict.html
     26
     27        * Modules/mediasource/SourceBuffer.cpp:
     28        (WebCore::SourceBuffer::evictCodedFrames):
     29
    1302020-11-20  Fujii Hironori  <Hironori.Fujii@sony.com>
    231
  • trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp

    r269907 r270106  
    997997
    998998    rangeEnd = m_source->duration();
     999    if (!rangeEnd.isFinite()) {
     1000        rangeEnd = buffered.maximumBufferedTime();
     1001        DEBUG_LOG(LOGIDENTIFIER, "MediaSource duration is not a finite value, using maximum buffered time: ", rangeEnd);
     1002    }
     1003
    9991004    rangeStart = rangeEnd - thirtySeconds;
    10001005    while (rangeStart > minimumRangeStart) {
Note: See TracChangeset for help on using the changeset viewer.