⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 277424 in webkit


Ignore:
Timestamp:
May 12, 2021, 10:37:17 PM (5 years ago)
Author:
Peng Liu
Message:

[iPad] SourceBufferPrivateAVFObjC should not report an error to the web page when the video playback is interrupted
https://bugs.webkit.org/show_bug.cgi?id=225620

Reviewed by Jer Noble.

If SourceBufferPrivateAVFObjC reports an error to a web page when
AVSampleBufferDisplayLayer reports AVErrorOperationInterrupted (the playback
was interrupted), the web page will likely destroy the video player (and teardown
the video element). That behavior will lead to an empty picture-in-picture window
if the video was playing in picture-in-picture.

With this patch, SourceBufferPrivateAVFObjC will not report an error to the
web page in case of playback interruption. Instead, it takes a note that
the playback was interrupted, so that when we try to resume the playback later,
it will flush the AVSampleBufferDisplayLayer to recover the playback state.

In addition, we need to enqueue an IDR frame first before we enqueue more
samples after flushing the AVSampleBufferDisplayLayer. That is guaranteed
by SourceBufferPrivate::reenqueSamples().

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:

(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playInternal):

  • platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
  • platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:

(WebCore::MediaSourcePrivateAVFObjC::flushActiveSourceBuffersIfNeeded):

  • platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
  • platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:

(WebCore::SourceBufferPrivateAVFObjC::flushIfNeeded):
(WebCore::SourceBufferPrivateAVFObjC::layerDidReceiveError):
(WebCore::SourceBufferPrivateAVFObjC::isReadyForMoreSamples):

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r277420 r277424  
     12021-05-12  Peng Liu  <peng.liu6@apple.com>
     2
     3        [iPad] SourceBufferPrivateAVFObjC should not report an error to the web page when the video playback is interrupted
     4        https://bugs.webkit.org/show_bug.cgi?id=225620
     5
     6        Reviewed by Jer Noble.
     7
     8        If `SourceBufferPrivateAVFObjC` reports an error to a web page when
     9        `AVSampleBufferDisplayLayer` reports `AVErrorOperationInterrupted` (the playback
     10        was interrupted), the web page will likely destroy the video player (and teardown
     11        the video element). That behavior will lead to an empty picture-in-picture window
     12        if the video was playing in picture-in-picture.
     13
     14        With this patch, `SourceBufferPrivateAVFObjC` will not report an error to the
     15        web page in case of playback interruption. Instead, it takes a note that
     16        the playback was interrupted, so that when we try to resume the playback later,
     17        it will flush the `AVSampleBufferDisplayLayer` to recover the playback state.
     18
     19        In addition, we need to enqueue an IDR frame first before we enqueue more
     20        samples after flushing the `AVSampleBufferDisplayLayer`. That is guaranteed
     21        by `SourceBufferPrivate::reenqueSamples()`.
     22
     23        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
     24        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::playInternal):
     25        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
     26        * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
     27        (WebCore::MediaSourcePrivateAVFObjC::flushActiveSourceBuffersIfNeeded):
     28        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
     29        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
     30        (WebCore::SourceBufferPrivateAVFObjC::flushIfNeeded):
     31        (WebCore::SourceBufferPrivateAVFObjC::layerDidReceiveError):
     32        (WebCore::SourceBufferPrivateAVFObjC::isReadyForMoreSamples):
     33
    1342021-05-12  Chris Dumez  <cdumez@apple.com>
    235
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm

    r277365 r277424  
    323323
    324324    ALWAYS_LOG(LOGIDENTIFIER);
     325#if PLATFORM(IOS_FAMILY)
     326    m_mediaSourcePrivate->flushActiveSourceBuffersIfNeeded();
     327#endif
    325328    m_playing = true;
    326329    if (shouldBePlaying())
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h

    r272696 r277424  
    9494    void setDecompressionSession(WebCoreDecompressionSession*);
    9595
     96#if PLATFORM(IOS_FAMILY)
     97    void flushActiveSourceBuffersIfNeeded();
     98#endif
     99
    96100#if ENABLE(ENCRYPTED_MEDIA)
    97101    void cdmInstanceAttached(CDMInstance&);
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm

    r271530 r277424  
    283283}
    284284
     285#if PLATFORM(IOS_FAMILY)
     286void MediaSourcePrivateAVFObjC::flushActiveSourceBuffersIfNeeded()
     287{
     288    for (auto* sourceBuffer : m_activeSourceBuffers)
     289        sourceBuffer->flushIfNeeded();
     290}
     291#endif
     292
    285293#if ENABLE(ENCRYPTED_MEDIA)
    286294void MediaSourcePrivateAVFObjC::cdmInstanceAttached(CDMInstance& instance)
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h

    r276828 r277424  
    110110
    111111    void flush();
     112#if PLATFORM(IOS_FAMILY)
     113    void flushIfNeeded();
     114#endif
    112115
    113116    void registerForErrorNotifications(SourceBufferPrivateAVFObjCErrorClient*);
     
    198201    ALLOW_NEW_API_WITHOUT_GUARDS_END
    199202    RetainPtr<WebAVSampleBufferErrorListener> m_errorListener;
     203#if PLATFORM(IOS_FAMILY)
     204    bool m_displayLayerWasInterrupted { false };
     205#endif
    200206    RetainPtr<NSError> m_hdcpError;
    201207    Box<BinarySemaphore> m_hasSessionSemaphore;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm

    r277246 r277424  
    929929}
    930930
     931#if PLATFORM(IOS_FAMILY)
     932void SourceBufferPrivateAVFObjC::flushIfNeeded()
     933{
     934    if (!m_displayLayerWasInterrupted)
     935        return;
     936
     937    m_displayLayerWasInterrupted = false;
     938    if (m_videoTracks.size())
     939        flushVideo();
     940
     941    // We initiatively enqueue samples instead of waiting for the
     942    // media data requests from m_decompressionSession and m_displayLayer.
     943    // In addition, we need to enqueue a sync sample (IDR video frame) first.
     944    if (m_decompressionSession)
     945        m_decompressionSession->stopRequestingMediaData();
     946    [m_displayLayer stopRequestingMediaData];
     947
     948    reenqueSamples(AtomString::number(m_enabledVideoTrackID));
     949}
     950#endif
     951
    931952void SourceBufferPrivateAVFObjC::registerForErrorNotifications(SourceBufferPrivateAVFObjCErrorClient* client)
    932953{
     
    944965{
    945966    ERROR_LOG(LOGIDENTIFIER, [[error description] UTF8String]);
     967
     968#if PLATFORM(IOS_FAMILY)
     969    if ([layer status] == AVQueuedSampleBufferRenderingStatusFailed && [[error domain] isEqualToString:@"AVFoundationErrorDomain"] && [error code] == AVErrorOperationInterrupted) {
     970        m_displayLayerWasInterrupted = true;
     971        return;
     972    }
     973#endif
    946974
    947975    // FIXME(142246): Remove the following once <rdar://problem/20027434> is resolved.
     
    11751203    auto trackID = parseIntegerAllowingTrailingJunk<uint64_t>(trackIDString).valueOr(0);
    11761204    if (trackID == m_enabledVideoTrackID) {
     1205#if PLATFORM(IOS_FAMILY)
     1206        if (m_displayLayerWasInterrupted)
     1207            return false;
     1208#endif
     1209
    11771210        if (m_decompressionSession)
    11781211            return m_decompressionSession->isReadyForMoreMediaData();
Note: See TracChangeset for help on using the changeset viewer.