Changeset 288435 in webkit


Ignore:
Timestamp:
Jan 24, 2022 4:41:47 AM (6 months ago)
Author:
youenn@apple.com
Message:

MediaStream canvas.captureStream() playback to LocalSampleBufferDisplayLayer is flaky
https://bugs.webkit.org/show_bug.cgi?id=230623
<rdar://problem/83668578>

Reviewed by Kimmo Kinnunen.

There are a few issues when creating the video element, setting the srcObject and playing it right away.
The first thing is that we try to render the video element while thinking that it might be video accelerated
(it is always the case for MediaStreamTrack based tracks), but the video element is asynchronously updating whether it is accelerated.
Following what other MediaPlayerPrivate are doing, when MediaPlayerPrivateMediaStreamAVFObjC has set up its video layers,
we schedule a call to renderingModeChanged which will trigger a relayout.

We also ensure, when the layer is fully initialized to set all values (bounds, hide states) as otherwise, this might be lost on GPUProcess
which currently does not register a RemoteSampleBufferDisplayLayer at the time the corresponding IPC message is received.

The additional issue is in the case the MediaStreamTrack source only generates one frame for some time.
In that case, and if the frame is enqueueud while setting up the video layers, we were not rendering this frame.
To fix this, when the video layers are ready, we reenqueue the last video frame as neeeded.

Manually tested.

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r288434 r288435  
     12022-01-24  Youenn Fablet  <youenn@apple.com>
     2
     3        MediaStream canvas.captureStream() playback to LocalSampleBufferDisplayLayer is flaky
     4        https://bugs.webkit.org/show_bug.cgi?id=230623
     5        <rdar://problem/83668578>
     6
     7        Reviewed by Kimmo Kinnunen.
     8
     9        There are a few issues when creating the video element, setting the srcObject and playing it right away.
     10        The first thing is that we try to render the video element while thinking that it might be video accelerated
     11        (it is always the case for MediaStreamTrack based tracks), but the video element is asynchronously updating whether it is accelerated.
     12        Following what other MediaPlayerPrivate are doing, when MediaPlayerPrivateMediaStreamAVFObjC has set up its video layers,
     13        we schedule a call to renderingModeChanged which will trigger a relayout.
     14
     15        We also ensure, when the layer is fully initialized to set all values (bounds, hide states) as otherwise, this might be lost on GPUProcess
     16        which currently does not register a RemoteSampleBufferDisplayLayer at the time the corresponding IPC message is received.
     17
     18        The additional issue is in the case the MediaStreamTrack source only generates one frame for some time.
     19        In that case, and if the frame is enqueueud while setting up the video layers, we were not rendering this frame.
     20        To fix this, when the video layers are ready, we reenqueue the last video frame as neeeded.
     21
     22        Manually tested.
     23
     24        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
     25        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
     26
    1272022-01-24  Kimmo Kinnunen  <kkinnunen@apple.com>
    228
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h

    r288315 r288435  
    139139    void processNewVideoSample(MediaSample&, VideoSampleMetadata, Seconds);
    140140    void enqueueVideoSample(MediaSample&);
     141    void reenqueueCurrentVideoSampleIfNeeded();
    141142    void requestNotificationWhenReadyForVideoData();
    142143
     
    169170    void updateTracks();
    170171    void updateRenderingMode();
     172    void scheduleRenderingModeChanged();
    171173    void checkSelectedVideoTrack();
    172174    void updateDisplayLayer();
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm

    r288315 r288435  
    278278}
    279279
     280void MediaPlayerPrivateMediaStreamAVFObjC::reenqueueCurrentVideoSampleIfNeeded()
     281{
     282    if (!m_currentVideoSampleLock.tryLock())
     283        return;
     284    Locker locker { AdoptLock, m_currentVideoSampleLock };
     285
     286    if (!m_currentVideoSample && !m_imagePainter.mediaSample)
     287        return;
     288
     289    enqueueVideoSample(m_currentVideoSample ? *m_currentVideoSample : *m_imagePainter.mediaSample);
     290}
     291
    280292void MediaPlayerPrivateMediaStreamAVFObjC::processNewVideoSample(MediaSample& sample, VideoSampleMetadata metadata, Seconds presentationTime)
    281293{
     
    399411    }
    400412
    401     updateRenderingMode();
     413    scheduleRenderingModeChanged();
     414
     415    m_sampleBufferDisplayLayer->updateBoundsAndPosition(m_sampleBufferDisplayLayer->rootLayer().bounds, m_videoRotation);
     416    m_sampleBufferDisplayLayer->updateDisplayMode(m_displayMode < PausedImage, hideRootLayer());
    402417    m_shouldUpdateDisplayLayer = true;
    403418
     
    417432        m_sampleBufferDisplayLayer = nullptr;
    418433
    419     updateRenderingMode();
     434    scheduleRenderingModeChanged();
    420435   
    421436    m_videoLayerManager->didDestroyVideoLayer();
     
    552567        m_sampleBufferDisplayLayer->play();
    553568    updateDisplayMode();
     569    reenqueueCurrentVideoSampleIfNeeded();
    554570
    555571    scheduleDeferredTask([this] {
     
    623639    m_isPageVisible = isVisible;
    624640    flushRenderers();
     641    reenqueueCurrentVideoSampleIfNeeded();
    625642}
    626643
     
    712729void MediaPlayerPrivateMediaStreamAVFObjC::updateRenderingMode()
    713730{
    714     if (!updateDisplayMode())
    715         return;
    716 
     731    if (updateDisplayMode())
     732        scheduleRenderingModeChanged();
     733}
     734
     735void MediaPlayerPrivateMediaStreamAVFObjC::scheduleRenderingModeChanged()
     736{
    717737    scheduleDeferredTask([this] {
    718738        if (m_player)
    719739            m_player->renderingModeChanged();
     740        reenqueueCurrentVideoSampleIfNeeded();
    720741    });
    721 
    722742}
    723743
Note: See TracChangeset for help on using the changeset viewer.