STR: <html><head></head><body><canvas></canvas><script> navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then((stream) => { var video = document.createElement('video'); video.srcObject = stream; video.play(); var canvas = document.querySelector('canvas'); var c2d = canvas.getContext('2d'); function draw() { canvas.width = video.videoWidth; canvas.height = video.videoHeight; c2d.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); requestAnimationFrame(draw); } requestAnimationFrame(draw); }); </script></body></html> Works on desktop Firefox, Chrome and Edge, and on mobile Android Firefox and Chrome, but produces a black canvas on Safari.
<rdar://problem/70183875>
I reproed the issue. This does not repro if the video element is rendering.
Here is a fiddle that reproduces the issue: https://jsfiddle.net/kw8fbcma/4/ Capture probably fails as the samples are queued in the local sample buffer display layer which is not actually rendering.
Created attachment 411209 [details] Patch
Comment on attachment 411209 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=411209&action=review > Source/WebCore/platform/graphics/MediaPlayer.cpp:968 > +void MediaPlayer::setVisibleForCanvas(bool b) > +{ > + m_visible = b; > + m_private->setVisibleForCanvas(b); s/b/visible/ > Source/WebCore/platform/graphics/MediaPlayerPrivate.h:99 > + virtual void setVisibleForCanvas(bool b) { setVisible(b); } Ditto
Created attachment 411223 [details] Patch for landing
Committed r268398: <https://trac.webkit.org/changeset/268398> All reviewed patches have been landed. Closing bug and clearing flags on attachment 411223 [details].
Why no layout test?
(In reply to Simon Fraser (smfr) from comment #8) > Why no layout test? It would be nice but I found it hard to test. Ideas welcome. We would basically need to verify that AVSampleBufferDisplayLayer is not keeping references too much video samples in its queue but I do not see APIs to get that info. Ideally, we would want to validate that the mock device CVPixelBufferPool is able to recycle its pixel buffers at some reasonable point in time. That would make the mock very close to the real camera. Not sure how we can do that though. Maybe we can observe the CVPixelBuffer pointers.
What happens if you do this: setVisibleForCanvas(true); setVisible(true); ? I think you do not become visible, because of the early return in MediaPlayerPrivateMediaStreamAVFObjC::setVisible. And maybe there are other early returns like this?
(In reply to Geoffrey Garen from comment #10) > What happens if you do this: > setVisibleForCanvas(true); > setVisible(true); > ? > > I think you do not become visible, because of the early return in > MediaPlayerPrivateMediaStreamAVFObjC::setVisible. And maybe there are other > early returns like this? For MediaPlayerPrivateMediaStreamAVFObjC, the MediaPlayer::setVisibleForCanvas(true) call is a no-op: - MediaPlayerPrivateMediaStreamAVFObjC::setVisibleForCanvas is a no-op. - MediaPlayer::m_visible is not used by MediaPlayerPrivateMediaStreamAVFObjC. The MediaPlayer::setVisible(true) call would end up setting MediaPlayerPrivateMediaStreamAVFObjC::m_visible to true. For other MediaPlayerPrivateXX, this patch is hopefully a no-op as MediaPlayer::setVisibleForCanvas is the same as MediaPlayer::setVisible. I'll double check this tomorrow but I think we can remove MediaPlayer::m_visible.
> I'll double check this tomorrow but I think we can remove > MediaPlayer::m_visible. Filed https://bugs.webkit.org/show_bug.cgi?id=217810