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

Changeset 268398 in webkit


Ignore:
Timestamp:
Oct 13, 2020, 10:06:16 AM (6 years ago)
Author:
youenn@apple.com
Message:

Webcam video from navigator.mediaDevices.getUserMedia() to 2D canvas fails on Safari on iPhone
https://bugs.webkit.org/show_bug.cgi?id=217578
<rdar://problem/70183875>

Reviewed by Eric Carlson.

It is unneeded for MediaStream video backends to enqueue samples to the display layer if the video element is hidden.
In iOS, the samples may never be flushed which might cause capture failing after enqueuing too many camera samples.
To avoid that, we no longer enqueue samples to the display layer when the player is not visible.
In case of canvas painting, other backends need to be made visible for canvas painting to work.
For MediaStream backend, we do not need that since we always keep the last sample.
For that reason, we keep the backend as not visible even if canvas happens.
We do so by introducing a setVisibleForCanvas that is a no-op for MediaStream backend and similar to setVisible for other backends.
For good measure, we now flush the MediaStream display layer whenever visibility changed.

Manually tested.

  • html/HTMLVideoElement.cpp:

(WebCore::HTMLVideoElement::paintCurrentFrameInContext):

  • platform/graphics/MediaPlayer.cpp:

(WebCore::MediaPlayer::setVisibleForCanvas):

  • platform/graphics/MediaPlayer.h:
  • platform/graphics/MediaPlayerPrivate.h:

(WebCore::MediaPlayerPrivateInterface::setVisibleForCanvas):

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

(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVisible):
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVisibleForCanvas):

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r268396 r268398  
     12020-10-13  Youenn Fablet  <youenn@apple.com>
     2
     3        Webcam video from navigator.mediaDevices.getUserMedia() to 2D canvas fails on Safari on iPhone
     4        https://bugs.webkit.org/show_bug.cgi?id=217578
     5        <rdar://problem/70183875>
     6
     7        Reviewed by Eric Carlson.
     8
     9        It is unneeded for MediaStream video backends to enqueue samples to the display layer if the video element is hidden.
     10        In iOS, the samples may never be flushed which might cause capture failing after enqueuing too many camera samples.
     11        To avoid that, we no longer enqueue samples to the display layer when the player is not visible.
     12        In case of canvas painting, other backends need to be made visible for canvas painting to work.
     13        For MediaStream backend, we do not need that since we always keep the last sample.
     14        For that reason, we keep the backend as not visible even if canvas happens.
     15        We do so by introducing a setVisibleForCanvas that is a no-op for MediaStream backend and similar to setVisible for other backends.
     16        For good measure, we now flush the MediaStream display layer whenever visibility changed.
     17 
     18        Manually tested.
     19
     20        * html/HTMLVideoElement.cpp:
     21        (WebCore::HTMLVideoElement::paintCurrentFrameInContext):
     22        * platform/graphics/MediaPlayer.cpp:
     23        (WebCore::MediaPlayer::setVisibleForCanvas):
     24        * platform/graphics/MediaPlayer.h:
     25        * platform/graphics/MediaPlayerPrivate.h:
     26        (WebCore::MediaPlayerPrivateInterface::setVisibleForCanvas):
     27        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
     28        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
     29        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample):
     30        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVisible):
     31        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVisibleForCanvas):
     32
    1332020-10-13  Youenn Fablet  <youenn@apple.com>
    234
  • trunk/Source/WebCore/html/HTMLVideoElement.cpp

    r268299 r268398  
    305305        return;
    306306   
    307     player->setVisible(true); // Make player visible or it won't draw.
     307    player->setVisibleForCanvas(true); // Make player visible or it won't draw.
    308308    context.paintFrameForMedia(*player, destRect);
    309309}
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp

    r268145 r268398  
    963963}
    964964
     965void MediaPlayer::setVisibleForCanvas(bool visible)
     966{
     967    m_visible = visible;
     968    m_private->setVisibleForCanvas(visible);
     969}
     970
    965971MediaPlayer::Preload MediaPlayer::preload() const
    966972{
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.h

    r268145 r268398  
    349349    bool visible() const;
    350350    void setVisible(bool);
     351    void setVisibleForCanvas(bool);
    351352
    352353    void prepareToPlay();
  • trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h

    r268070 r268398  
    9797
    9898    virtual void setVisible(bool) = 0;
     99    virtual void setVisibleForCanvas(bool visible) { setVisible(visible); }
    99100
    100101    virtual float duration() const { return 0; }
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h

    r267472 r268398  
    125125
    126126    void setVisible(bool) final;
     127    void setVisibleForCanvas(bool) final;
    127128
    128129    MediaTime durationMediaTime() const override;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm

    r267472 r268398  
    253253void MediaPlayerPrivateMediaStreamAVFObjC::enqueueVideoSample(MediaSample& sample)
    254254{
     255    if (!m_visible)
     256        return;
     257
    255258    auto locker = tryHoldLock(m_sampleBufferDisplayLayerLock);
    256259    if (!locker)
     
    594597
    595598    m_visible = visible;
    596     if (m_visible)
    597         flushRenderers();
     599    flushRenderers();
     600}
     601
     602void MediaPlayerPrivateMediaStreamAVFObjC::setVisibleForCanvas(bool)
     603{
    598604}
    599605
Note: See TracChangeset for help on using the changeset viewer.