RESOLVED FIXED 227559
SourceBuffer.abort() doesn't go back to state WAITING_FOR_SEGMENT properly
https://bugs.webkit.org/show_bug.cgi?id=227559
Summary SourceBuffer.abort() doesn't go back to state WAITING_FOR_SEGMENT properly
Jean-Yves Avenard [:jya]
Reported 2021-06-30 18:18:54 PDT
Consider the following test: consoleWrite('Append the two partial media segments in reverse order. Separated with an abort'); run('sourceBuffer.appendBuffer(loader.mediaSegment(1).slice(0, 65677))'); await waitFor(sourceBuffer, 'update'); run('sourceBuffer.abort()'); testExpected('sourceBuffer.buffered.length', '1'); testExpected('sourceBuffer.buffered.end(0)', '82.981', '=='); run('sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, 65677))'); await waitFor(sourceBuffer, 'update'); testExpected('sourceBuffer.buffered.length', '2'); testExpected('sourceBuffer.buffered.end(0)', '6.041', '=='); testExpected('sourceBuffer.buffered.end(1)', '82.981', '=='); While we should get: Append the two partial media segments in reverse order. Separated with an abort RUN(sourceBuffer.appendBuffer(loader.mediaSegment(1).slice(0, 65677))) EVENT(update) RUN(sourceBuffer.abort()) EXPECTED (sourceBuffer.buffered.length == '1') OK EXPECTED (sourceBuffer.buffered.end(0) == '82.981') OK RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, 65677))) EVENT(update) EXPECTED (sourceBuffer.buffered.length == '2') OK EXPECTED (sourceBuffer.buffered.end(0) == '6.041') OK EXPECTED (sourceBuffer.buffered.end(1) == '82.981') OK END OF TEST We get: Append the two partial media segments in reverse order. Separated with an abort RUN(sourceBuffer.appendBuffer(loader.mediaSegment(1).slice(0, 65677))) EVENT(update) RUN(sourceBuffer.abort()) EXPECTED (sourceBuffer.buffered.length == '1') OK EXPECTED (sourceBuffer.buffered.end(0) == '82.981') OK RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, 65677))) EVENT(update) EXPECTED (sourceBuffer.buffered.length == '2'), OBSERVED '1' FAIL EXPECTED (sourceBuffer.buffered.end(0) == '6.041'), OBSERVED '82.981' FAIL IndexSizeError: The index is not in the allowed range. END OF TEST The reason for this is that when calling SourceBuffer.abort() we call into: void SourceBufferPrivateAVFObjC::abort() (https://webkit-search.igalia.com/webkit/rev/a76db2def990ef700e79d59e175d0c6c5eaf8472/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm#659) which does: m_initializationSegmentIsHandled = false; for webm we call into: void SourceBufferParserWebM::resetParserState() https://webkit-search.igalia.com/webkit/rev/a76db2def990ef700e79d59e175d0c6c5eaf8472/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp#679 Which will call into: m_tracks.clear(); m_initializationSegment = nullptr; m_initializationSegmentEncountered = false; So we effectively move back to SourceBuffer into append state = WAITING_FOR_SEGMENT and "first initialization segment received flag is false" (https://w3c.github.io/media-source/#first-init-segment-received-flag) This prevents appending any more data into the source buffer until a new init segment is received. This is an incorrect behaviour. I'm not seeing YouTube being impacted much when constantly seeking in the video ; even though the above JS is a pattern they use. I'm guessing they work around this bug by always sending a new init segment after calling abort, when they don't have it. Firefox had a similar bug a while back, and this used to cause stalls.
Attachments
Patch (736.44 KB, patch)
2021-07-01 20:33 PDT, Jean-Yves Avenard [:jya]
ews-feeder: commit-queue-
Patch (736.49 KB, patch)
2021-07-01 20:44 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (737.94 KB, patch)
2021-07-02 01:35 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (737.93 KB, patch)
2021-07-02 23:04 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (737.93 KB, patch)
2021-07-02 23:23 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (742.09 KB, patch)
2021-07-09 01:43 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (738.45 KB, patch)
2021-07-12 17:07 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (738.44 KB, patch)
2021-07-12 17:25 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (741.26 KB, patch)
2021-07-13 00:04 PDT, Jean-Yves Avenard [:jya]
no flags
Patch (742.10 KB, patch)
2021-07-13 20:21 PDT, Jean-Yves Avenard [:jya]
no flags
Radar WebKit Bug Importer
Comment 1 2021-06-30 18:19:22 PDT
Jean-Yves Avenard [:jya]
Comment 2 2021-07-01 20:10:30 PDT
*** Bug 222495 has been marked as a duplicate of this bug. ***
Jean-Yves Avenard [:jya]
Comment 3 2021-07-01 20:33:50 PDT
Jean-Yves Avenard [:jya]
Comment 4 2021-07-01 20:44:22 PDT
Created attachment 432767 [details] Patch Fix compilation on machine with no VP9
Jean-Yves Avenard [:jya]
Comment 5 2021-07-02 01:35:21 PDT
Created attachment 432770 [details] Patch Handle case where sourceBuffer.remove is called immediately after abort
Eric Carlson
Comment 6 2021-07-02 13:43:39 PDT
Comment on attachment 432770 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=432770&action=review > Source/WebCore/ChangeLog:34 > + - The SourceBufferParser handle two type of parser: SourceBufferParser and the s/two type/two types/ > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:417 > + callOnMainThread([this, weakThis = WTFMove(weakThis)] { I believe we are trying to get away from using `callOnMainThread` as a way to queue tasks in favor of using the event queue. SourceBuffer is an ActiveDOMObject, so you could add a method that calls `queueCancellableTaskKeepingObjectAlive` and use it instead. This would presumably allow you to get rid of the WeakPtr, because SourceBuffer would cancel the pending task when it clears the client pointer. > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:575 > + callOnMainThread([weakThis = makeWeakPtr(*this), data = WTFMove(data), this]() mutable { > + if (!weakThis) > + return; Ditto > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:588 > + callOnMainThread([weakThis = WTFMove(weakThis), trackID, respondedSemaphore]() { Ditto. > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:591 > + respondedSemaphore->signal(); Is it safe to signaling the semaphore if `weakThis` is null (the object has been destroyed)? > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:608 > + callOnMainThread([weakThis = WTFMove(weakThis), initData = WTFMove(initData), trackID, hasSessionSemaphore]() mutable { Ditto > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:629 > + callOnMainThread([weakThis = WTFMove(weakThis)] { Ditto > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:672 > + callOnMainThread([weakThis = makeWeakPtr(*this), start, end, currentMediaTime, isEnded, completionHandler = WTFMove(completionHandler)]() mutable { Ditto > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:696 > + callOnMainThread([weakThis = makeWeakPtr(*this), this]() { Ditto > Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:727 > + callOnMainThread([weakThis = makeWeakPtr(*this), parser = m_parser, this]() { Ditto. > Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp:812 > + // partial init segment is encountered after a call to sourceBuffer.abort(). s/segment is encountered/segment be encountered/
Jean-Yves Avenard [:jya]
Comment 7 2021-07-02 22:44:39 PDT
Comment on attachment 432770 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=432770&action=review >> Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:417 >> + callOnMainThread([this, weakThis = WTFMove(weakThis)] { > > I believe we are trying to get away from using `callOnMainThread` as a way to queue tasks in favor of using the event queue. SourceBuffer is an ActiveDOMObject, so you could add a method that calls `queueCancellableTaskKeepingObjectAlive` and use it instead. This would presumably allow you to get rid of the WeakPtr, because SourceBuffer would cancel the pending task when it clears the client pointer. As discussed on slack, as callOnMainThread is used thoroughly in this file and related once, I will keep this as-is so we don't have to worry on the impact in the use (or no-longer used) semaphores.
Jean-Yves Avenard [:jya]
Comment 8 2021-07-02 23:04:05 PDT
Created attachment 432843 [details] Patch Apply comments
EWS
Comment 9 2021-07-02 23:12:16 PDT
Eric Carlon found in /Volumes/Data/worker/Commit-Queue/build/LayoutTests/ChangeLog does not appear to be a valid reviewer according to contributors.json. /Volumes/Data/worker/Commit-Queue/build/LayoutTests/ChangeLog neither lists a valid reviewer nor contains the string "Unreviewed" or "Rubber stamp" (case insensitive).
Jean-Yves Avenard [:jya]
Comment 10 2021-07-02 23:23:10 PDT
Created attachment 432844 [details] Patch Fix Eric's name
EWS
Comment 11 2021-07-03 00:01:58 PDT
Committed r279542 (239378@main): <https://commits.webkit.org/239378@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 432844 [details].
ayumi_kojima
Comment 12 2021-07-06 14:34:12 PDT
It looks like the changes in https://trac.webkit.org/changeset/279542/webkit caused these 4 tests to crash with the assert imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-implicit.html imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-without-codecs-parameter.html imported/w3c/web-platform-tests/media-source/mediasource-changetype-play-negative.html History: https://results.webkit.org/?suite=layout-tests&suite=layout-tests&suite=layout-tests&suite=layout-tests&test=imported%2Fw3c%2Fweb-platform-tests%2Fmedia-source%2Fmediasource-changetype-play-implicit.html&test=imported%2Fw3c%2Fweb-platform-tests%2Fmedia-source%2Fmediasource-changetype-play-negative.html&test=imported%2Fw3c%2Fweb-platform-tests%2Fmedia-source%2Fmediasource-changetype-play-without-codecs-parameter.html&test=imported%2Fw3c%2Fweb-platform-tests%2Fmedia-source%2Fmediasource-changetype-play.html https://build.webkit.org/results/Apple-BigSur-Debug-AppleSilicon-WK2-Tests/r279586%20(2011)/results.html
Truitt Savell
Comment 13 2021-07-06 14:36:03 PDT
Reverted r279542 for reason: Casued 4 test crashes Committed r279622 (239440@main): <https://commits.webkit.org/239440@main>
Jean-Yves Avenard [:jya]
Comment 14 2021-07-09 01:43:07 PDT
Created attachment 433203 [details] Patch Clear m_mediaSamples array on reset, re-schedule some methods
Jean-Yves Avenard [:jya]
Comment 15 2021-07-12 17:07:50 PDT
Created attachment 433375 [details] Patch Redesign
Jean-Yves Avenard [:jya]
Comment 16 2021-07-12 17:25:41 PDT
Created attachment 433378 [details] Patch Fix grammar
Jean-Yves Avenard [:jya]
Comment 17 2021-07-13 00:04:09 PDT
Created attachment 433391 [details] Patch Prevent each sample received after a call to ChangeType to fire an error
Jean-Yves Avenard [:jya]
Comment 18 2021-07-13 06:39:39 PDT
Comment on attachment 433391 [details] Patch unrelated failures.
EWS
Comment 19 2021-07-13 09:18:14 PDT
Found 2 new test failures: fast/canvas/webgl/texImage2D-mse-flipY-false.html, fast/canvas/webgl/texImage2D-mse-flipY-true.html
Jean-Yves Avenard [:jya]
Comment 20 2021-07-13 20:21:55 PDT
Created attachment 433472 [details] Patch Fix logic where queued samples wouldn't be processed once the init segment was processed in the content process
EWS
Comment 21 2021-07-13 22:12:34 PDT
Committed r279904 (239653@main): <https://commits.webkit.org/239653@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 433472 [details].
Note You need to log in before you can comment on or make changes to this bug.