Changeset 285993 in webkit
- Timestamp:
- Nov 18, 2021, 2:34:22 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 37 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/ChangeLog (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html (modified) (2 diffs)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html (modified) (4 diffs)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating-expected.txt (modified) (1 diff)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html (modified) (5 diffs)
-
LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback.html (modified) (6 diffs)
-
LayoutTests/platform/ios-wk2/TestExpectations (modified) (1 diff)
-
LayoutTests/platform/mac-wk1/TestExpectations (modified) (1 diff)
-
LayoutTests/platform/mac-wk2/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/html/HTMLMediaElement.h (modified) (2 diffs)
-
Source/WebCore/html/HTMLVideoElement.cpp (modified) (4 diffs)
-
Source/WebCore/html/HTMLVideoElement.h (modified) (1 diff)
-
Source/WebCore/platform/VideoFrameMetadata.h (modified) (1 diff)
-
Source/WebCore/platform/graphics/MediaPlayer.cpp (modified) (2 diffs)
-
Source/WebCore/platform/graphics/MediaPlayer.h (modified) (4 diffs)
-
Source/WebCore/platform/graphics/MediaPlayerPrivate.h (modified) (1 diff)
-
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (modified) (3 diffs)
-
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (modified) (5 diffs)
-
Source/WebCore/platform/graphics/cv/PixelBufferConformerCV.h (modified) (1 diff)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp (modified) (1 diff)
-
Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h (modified) (1 diff)
-
Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in (modified) (1 diff)
-
Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm (modified) (2 diffs)
-
Source/WebKit/Scripts/webkit/messages.py (modified) (2 diffs)
-
Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp (modified) (2 diffs)
-
Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.h (modified) (4 diffs)
-
Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.messages.in (modified) (1 diff)
-
Source/WebKit/WebProcess/GPU/media/cocoa/MediaPlayerPrivateRemoteCocoa.mm (modified) (2 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/DumpRenderTree/mac/DumpRenderTree.mm (modified) (1 diff)
-
Tools/WebKitTestRunner/TestController.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r285989 r285993 1 2021-11-18 Youenn Fablet <youenn@apple.com> 2 3 MediaPlayerAVFoundation should support rvfc 4 https://bugs.webkit.org/show_bug.cgi?id=231945 5 6 Reviewed by Eric Carlson. 7 8 Unskipped some tests. 9 10 * platform/ios-wk2/TestExpectations: 11 * platform/mac-wk1/TestExpectations: 12 * platform/mac-wk2/TestExpectations: 13 1 14 2021-11-18 Sergio Villar Senin <svillar@igalia.com> 2 15 -
trunk/LayoutTests/imported/w3c/ChangeLog
r285989 r285993 1 2021-11-18 Youenn Fablet <youenn@apple.com> 2 3 MediaPlayerAVFoundation should support rvfc 4 https://bugs.webkit.org/show_bug.cgi?id=231945 5 <rdar://problem/84657372> 6 7 Reviewed by Eric Carlson. 8 9 Transforming tests from async to promise based so that there is only one video playing at a time, to make it work smoothly in iOS. 10 11 * web-platform-tests/video-rvfc/request-video-frame-callback-dom-expected.txt: 12 * web-platform-tests/video-rvfc/request-video-frame-callback-dom.html: 13 * web-platform-tests/video-rvfc/request-video-frame-callback-parallel-expected.txt: 14 * web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html: 15 * web-platform-tests/video-rvfc/request-video-frame-callback-repeating-expected.txt: 16 * web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html: 17 * web-platform-tests/video-rvfc/request-video-frame-callback-expected.txt: 18 * web-platform-tests/video-rvfc/request-video-frame-callback.html: 19 1 20 2021-11-18 Sergio Villar Senin <svillar@igalia.com> 2 21 -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom-expected.txt
r284528 r285993 1 1 2 Harness Error (TIMEOUT), message = null 2 PASS Test a video outside of the DOM can still use video.rVFC. 3 PASS Test video.rVFC works with "display:none". 4 PASS Test video.rVFC works with "visibility:hidden". 3 5 4 TIMEOUT Test a video outside of the DOM can still use video.rVFC. Test timed out5 TIMEOUT Test video.rVFC works with "display:none". Test timed out6 TIMEOUT Test video.rVFC works with "visibility:hidden". Test timed out7 -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html
r284528 r285993 14 14 } 15 15 16 async_test(function(t) { 16 promise_test(async function(t) { 17 let done; 18 const promise = new Promise(resolve => done = resolve); 19 17 20 let video = document.createElement('video'); 18 21 19 video.requestVideoFrameCallback( t.step_func_done());22 video.requestVideoFrameCallback(done); 20 23 video.src = testVideo.url; 21 video.play();24 await video.play(); 22 25 26 return promise; 23 27 }, 'Test a video outside of the DOM can still use video.rVFC.'); 24 28 25 29 function rvfcStyleTest(applyStyle, description) { 26 async_test(function(t) { 30 promise_test(async function(t) { 31 let done; 32 const promise = new Promise(resolve => done = resolve); 33 27 34 let video = document.createElement('video'); 28 35 document.body.appendChild(video); … … 32 39 t.step_func( _ => { 33 40 // Make sure we can receive more than one callback. 34 video.requestVideoFrameCallback( t.step_func_done());41 video.requestVideoFrameCallback(done); 35 42 }) 36 43 ); 37 44 38 45 video.src = testVideo.url; 39 video.play(); 46 await video.play(); 47 48 return promise; 40 49 }, description); 41 50 } -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-expected.txt
r284528 r285993 1 1 2 2 3 Harness Error (TIMEOUT), message = null 3 PASS Test we can register a video.rVFC callback. 4 PASS Test video.rVFC callbacks run before window.rAF callbacks. 5 PASS Test we can cancel a video.rVFC request. 6 PASS Test invalid calls to the video.rVFC API. 7 PASS Test video.rVFC does not stop when switching sources. 4 8 5 TIMEOUT Test we can register a video.rVFC callback. Test timed out6 TIMEOUT Test video.rVFC callbacks run before window.rAF callbacks. Test timed out7 TIMEOUT Test we can cancel a video.rVFC request. Test timed out8 PASS Test invalid calls to the video.rVFC API.9 TIMEOUT Test video.rVFC does not stop when switching sources. Test timed out10 -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel-expected.txt
r284528 r285993 1 1 2 2 3 Harness Error (TIMEOUT), message = null 3 PASS Test callbacks get the same information. 4 PASS Test we can cancel callbacks from callbacks. 4 5 5 TIMEOUT Test callbacks get the same information. Test timed out6 TIMEOUT Test we can cancel callbacks from callbacks. Test timed out7 -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html
r284528 r285993 8 8 <script> 9 9 10 async_test(function(t) { 10 promise_test(async function(t) { 11 let done; 12 const promise = new Promise(resolve => done = resolve); 13 11 14 let video = document.createElement('video'); 12 15 document.body.appendChild(video); … … 20 23 })); 21 24 22 video.requestVideoFrameCallback(t.step_func _done((time, metadata) => {25 video.requestVideoFrameCallback(t.step_func((time, metadata) => { 23 26 assert_equals(firstTime, time); 24 27 assert_object_equals(firstMetadata, metadata); 28 done(); 25 29 })); 26 30 … … 28 32 video.play(); 29 33 34 return promise; 30 35 }, 'Test callbacks get the same information.'); 31 36 32 async_test(function(t) { 37 promise_test(async function(t) { 38 let done; 39 const promise = new Promise(resolve => done = resolve); 40 33 41 let video = document.createElement('video'); 34 42 document.body.appendChild(video); … … 47 55 48 56 // NOTE: This callback should be executed last. 49 video.requestVideoFrameCallback( 50 t.step_func_done() 51 ); 57 video.requestVideoFrameCallback(done); 52 58 53 59 video.src = getVideoURI('/media/movie_5'); 54 60 video.play(); 61 62 return promise; 55 63 }, 'Test we can cancel callbacks from callbacks.'); 56 64 </script> -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating-expected.txt
r284528 r285993 1 1 2 2 3 Harness Error (TIMEOUT), message = null 3 PASS Test new callbacks are only called on the next frame. 4 PASS Test chaining calls to video.rVFC, and verify the required parameters. 4 5 5 TIMEOUT Test new callbacks are only called on the next frame. Test timed out6 TIMEOUT Test chaining calls to video.rVFC, and verify the required parameters. Test timed out7 -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html
r284528 r285993 8 8 <script> 9 9 10 async_test(function(t) { 10 promise_test(async function(t) { 11 let done; 12 const promise = new Promise(resolve => done = resolve); 13 11 14 let video = document.createElement('video'); 12 15 document.body.appendChild(video); … … 25 28 // Queue up a second callback, and make sure it's called at the same time 26 29 // as the one we just queued up. 27 video.requestVideoFrameCallback(t.step_func _done((time) => {30 video.requestVideoFrameCallback(t.step_func((time) => { 28 31 assert_equals(time, secondTime, "Callbacks queued together should be called at the same time"); 32 done(); 29 33 })) 30 34 … … 32 36 33 37 video.src = getVideoURI('/media/movie_5'); 34 video.play();38 await video.play(); 35 39 40 return promise; 36 41 }, 'Test new callbacks are only called on the next frame.'); 37 42 38 async_test(function(t) { 43 promise_test(async function(t) { 44 let done; 45 const promise = new Promise(resolve => done = resolve); 46 39 47 let video = document.createElement('video'); 40 48 document.body.appendChild(video); … … 65 73 66 74 if (++currentCallNumber > maxNumberOfCalls) { 67 t.done()75 done() 68 76 } else { 69 77 video.requestVideoFrameCallback(t.step_func(repeatingCallback)); … … 74 82 75 83 video.src = getVideoURI('/media/movie_5'); 76 video.play();84 await video.play(); 77 85 86 return promise; 78 87 }, 'Test chaining calls to video.rVFC, and verify the required parameters.'); 79 88 </script> -
trunk/LayoutTests/imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback.html
r284528 r285993 19 19 } 20 20 21 async_test(function(t) { 21 promise_test(async function(t) { 22 let done; 23 const promise = new Promise(resolve => done = resolve); 24 22 25 let video = document.createElement('video'); 23 26 document.body.appendChild(video); 24 27 25 28 let id = video.requestVideoFrameCallback( 26 t.step_func _done((time, metadata) => {29 t.step_func((time, metadata) => { 27 30 assert_true(time > 0); 28 31 assert_equals(metadata.height, testVideo.height); 29 32 assert_equals(metadata.width, testVideo.width); 33 done(); 30 34 }) 31 35 ); … … 34 38 35 39 video.src = testVideo.url; 36 video.play();40 await video.play(); 37 41 42 return promise; 38 43 }, 'Test we can register a video.rVFC callback.'); 39 44 40 async_test(function(t) { 45 promise_test(async function(t) { 46 let done; 47 const promise = new Promise(resolve => done = resolve); 48 41 49 let video = document.createElement('video'); 42 50 document.body.appendChild(video); … … 46 54 // Queue a call to window.rAF, and make sure it is executed within the 47 55 // same turn of the event loop (with the same 'time' parameter). 48 window.requestAnimationFrame( t.step_func _done( window_now => {56 window.requestAnimationFrame( t.step_func( window_now => { 49 57 assert_equals(video_now, window_now); 58 done(); 50 59 })); 51 60 }) … … 53 62 54 63 video.src = testVideo.url; 55 video.play();64 await video.play(); 56 65 66 return promise; 57 67 }, 'Test video.rVFC callbacks run before window.rAF callbacks.'); 58 68 59 69 60 async_test(function(t) { 70 promise_test(async function(t) { 71 let done; 72 const promise = new Promise(resolve => done = resolve); 73 61 74 let video = document.createElement('video'); 62 75 document.body.appendChild(video); … … 75 88 // give it some more time and really make sure it doesn't, by going 76 89 // throught the event loop once more. 77 t.step_timeout(() => { t.done(); }, 0);90 t.step_timeout(() => { done(); }, 0); 78 91 }) 79 92 ); 80 93 81 94 video.src = testVideo.url; 82 video.play(); 95 await video.play(); 96 97 return promise; 83 98 }, 'Test we can cancel a video.rVFC request.'); 84 99 … … 106 121 promise_test(async function(t) { 107 122 let video = document.createElement('video'); 123 video.autoplay = true; 108 124 document.body.appendChild(video); 109 125 -
trunk/LayoutTests/platform/ios-wk2/TestExpectations
r285565 r285993 144 144 fast/mediastream/getUserMedia-rvfc.html [ Pass ] 145 145 webrtc/peerConnection-rvfc.html [ Pass ] 146 # Timing out tests until we add regular video streaming backend support.146 # Timing out tests until we add XR session. 147 147 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-before-xr-session.https.html [ Skip ] 148 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html [ Skip ]149 148 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Skip ] 150 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html [ Skip ]151 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html [ Skip ]152 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback.html [ Skip ]153 149 154 150 #////////////////////////////////////////////////////////////////////////////////////////// -
trunk/LayoutTests/platform/mac-wk1/TestExpectations
r285936 r285993 33 33 # rdar://problem/61793884 : Enabling this test for WK1 only. 34 34 fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html [ Pass ] 35 36 imported/w3c/web-platform-tests/video-rvfc [ Pass ] 37 # Timing out tests until we add XR session. 38 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-before-xr-session.https.html [ Skip ] 39 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Skip ] 35 40 36 41 #////////////////////////////////////////////////////////////////////////////////////////// -
trunk/LayoutTests/platform/mac-wk2/TestExpectations
r285928 r285993 123 123 fast/mediastream/getUserMedia-rvfc.html [ Pass ] 124 124 webrtc/peerConnection-rvfc.html [ Pass ] 125 # Timing out tests until we add regular video streaming backend support.125 # Timing out tests until we add XR session. 126 126 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-before-xr-session.https.html [ Skip ] 127 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-dom.html [ Skip ]128 127 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Skip ] 129 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-parallel.html [ Skip ]130 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html [ Skip ]131 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback.html [ Skip ]132 128 133 129 #////////////////////////////////////////////////////////////////////////////////////////// -
trunk/Source/WebCore/ChangeLog
r285992 r285993 1 2021-11-18 Youenn Fablet <youenn@apple.com> 2 3 MediaPlayerAVFoundation should support rvfc 4 https://bugs.webkit.org/show_bug.cgi?id=231945 5 <rdar://problem/84657372> 6 7 Reviewed by Eric Carlson. 8 9 Add API to start/stop gathering metadata. 10 This goes from video element down to media player private. 11 Conversely, add a callback to get the metadata, including the pixel buffer. 12 13 Implement support in MediaPlayerPrivateAVFoundationObjC by adding a specific timeline observer. 14 We reuse the same video output and the same pixel buffer as when painting the video element in the canvas. 15 To make sure painting in a canvas does not have side effects with gathering video metadata, we do not update the pixel buffer 16 when painting on a canvas in case video metadata is gathered. 17 Instead, we consider that pixel buffer is as up to date as possible in that case. 18 To make it work in WK1, we implement the synchronous video frame callback getter. 19 20 Round the millisecond now time given to the callback, like done for RAF. 21 22 Covered by enabled tests. 23 24 * WebCore.xcodeproj/project.pbxproj: 25 * html/HTMLMediaElement.h: 26 * html/HTMLVideoElement.cpp: 27 * html/HTMLVideoElement.h: 28 * platform/VideoFrameMetadata.h: 29 * platform/cocoa/CVPixelBufferRef.h: Added. 30 * platform/graphics/MediaPlayer.cpp: 31 * platform/graphics/MediaPlayer.h: 32 * platform/graphics/MediaPlayerPrivate.h: 33 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h: 34 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm: 35 * platform/graphics/cv/PixelBufferConformerCV.h: 36 1 37 2021-11-18 Chris Lord <clord@igalia.com> 2 38 -
trunk/Source/WebCore/html/HTMLMediaElement.h
r285571 r285993 642 642 bool isChangingVideoFullscreenMode() const { return m_changingVideoFullscreenMode; } 643 643 644 protected: 645 void mediaPlayerEngineUpdated() override; 646 644 647 private: 645 648 friend class Internals; … … 693 696 void mediaPlayerRenderingModeChanged() final; 694 697 bool mediaPlayerAcceleratedCompositingEnabled() final; 695 void mediaPlayerEngineUpdated() final;696 698 void mediaPlayerWillInitializeMediaEngine() final; 697 699 void mediaPlayerDidInitializeMediaEngine() final; -
trunk/Source/WebCore/html/HTMLVideoElement.cpp
r285984 r285993 590 590 unsigned HTMLVideoElement::requestVideoFrameCallback(Ref<VideoFrameRequestCallback>&& callback) 591 591 { 592 if (m_videoFrameRequests.isEmpty() && player()) 593 player()->startVideoFrameMetadataGathering(); 594 592 595 auto identifier = ++m_nextVideoFrameRequestIndex; 593 596 m_videoFrameRequests.append(makeUniqueRef<VideoFrameRequest>(identifier, WTFMove(callback))); … … 609 612 } 610 613 m_videoFrameRequests.remove(index); 614 615 if (m_videoFrameRequests.isEmpty() && player()) 616 player()->stopVideoFrameMetadataGathering(); 611 617 } 612 618 … … 641 647 auto& request = m_videoFrameRequests[index]; 642 648 if (!request->cancelled) { 643 request->callback->handleEvent( now.value(), *videoFrameMetadata);649 request->callback->handleEvent(std::round(now.milliseconds()), *videoFrameMetadata); 644 650 request->cancelled = true; 645 651 } … … 648 654 649 655 m_videoFrameRequests.removeAllMatching([](auto& callback) { return callback->cancelled; }); 650 } 651 652 } 653 654 #endif 656 657 if (m_videoFrameRequests.isEmpty() && player()) 658 player()->stopVideoFrameMetadataGathering(); 659 } 660 661 void HTMLVideoElement::mediaPlayerEngineUpdated() 662 { 663 HTMLMediaElement::mediaPlayerEngineUpdated(); 664 if (!m_videoFrameRequests.isEmpty() && player()) 665 player()->startVideoFrameMetadataGathering(); 666 } 667 668 } 669 670 #endif -
trunk/Source/WebCore/html/HTMLVideoElement.h
r284528 r285993 142 142 PlatformMediaSession::MediaType presentationType() const final { return PlatformMediaSession::MediaType::Video; } 143 143 144 void mediaPlayerEngineUpdated() final; 145 144 146 std::unique_ptr<HTMLImageLoader> m_imageLoader; 145 147 -
trunk/Source/WebCore/platform/VideoFrameMetadata.h
r284528 r285993 44 44 std::optional<double> receiveTime; 45 45 std::optional<unsigned> rtpTimestamp; 46 47 template<class Encoder> void encode(Encoder&) const; 48 template<class Decoder> static std::optional<VideoFrameMetadata> decode(Decoder&); 46 49 }; 50 51 template<class Encoder> 52 inline void VideoFrameMetadata::encode(Encoder& encoder) const 53 { 54 encoder << presentationTime << expectedDisplayTime << width << height << mediaTime << presentedFrames << processingDuration << captureTime << receiveTime << rtpTimestamp; 55 } 56 57 template<class Decoder> 58 inline std::optional<VideoFrameMetadata> VideoFrameMetadata::decode(Decoder& decoder) 59 { 60 std::optional<double> presentationTime; 61 decoder >> presentationTime; 62 if (!presentationTime) 63 return std::nullopt; 64 65 std::optional<double> expectedDisplayTime; 66 decoder >> expectedDisplayTime; 67 if (!expectedDisplayTime) 68 return std::nullopt; 69 70 std::optional<unsigned> width; 71 decoder >> width; 72 if (!width) 73 return std::nullopt; 74 75 std::optional<unsigned> height; 76 decoder >> height; 77 if (!height) 78 return std::nullopt; 79 80 std::optional<double> mediaTime; 81 decoder >> mediaTime; 82 if (!mediaTime) 83 return std::nullopt; 84 85 std::optional<unsigned> presentedFrames; 86 decoder >> presentedFrames; 87 if (!presentedFrames) 88 return std::nullopt; 89 90 std::optional<std::optional<double>> processingDuration; 91 decoder >> processingDuration; 92 if (!processingDuration) 93 return std::nullopt; 94 95 std::optional<std::optional<double>> captureTime; 96 decoder >> captureTime; 97 if (!captureTime) 98 return std::nullopt; 99 100 std::optional<std::optional<double>> receiveTime; 101 decoder >> receiveTime; 102 if (!receiveTime) 103 return std::nullopt; 104 105 std::optional<std::optional<unsigned>> rtpTimestamp; 106 decoder >> rtpTimestamp; 107 if (!rtpTimestamp) 108 return std::nullopt; 109 110 return VideoFrameMetadata { *presentationTime, *expectedDisplayTime, *width, *height, *mediaTime, *presentedFrames, *processingDuration, *captureTime, *receiveTime, *rtpTimestamp }; 111 } 47 112 48 113 } -
trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp
r284857 r285993 591 591 if (m_visibleInViewport) 592 592 m_private->setVisibleInViewport(m_visibleInViewport); 593 if (m_isGatheringVideoFrameMetadata) 594 m_private->startVideoFrameMetadataGathering(); 593 595 m_private->prepareForPlayback(m_privateBrowsing, m_preload, m_preservesPitch, m_shouldPrepareToRender); 594 596 } … … 1721 1723 return m_private->videoFrameMetadata(); 1722 1724 } 1725 1726 void MediaPlayer::startVideoFrameMetadataGathering() 1727 { 1728 m_isGatheringVideoFrameMetadata = true; 1729 m_private->startVideoFrameMetadataGathering(); 1730 } 1731 1732 void MediaPlayer::stopVideoFrameMetadataGathering() 1733 { 1734 m_isGatheringVideoFrameMetadata = false; 1735 m_private->stopVideoFrameMetadataGathering(); 1736 } 1737 1738 #if PLATFORM(COCOA) 1739 void MediaPlayer::onNewVideoFrameMetadata(VideoFrameMetadata&& metadata, RetainPtr<CVPixelBufferRef>&& buffer) 1740 { 1741 client().mediaPlayerOnNewVideoFrameMetadata(WTFMove(metadata), WTFMove(buffer)); 1742 } 1743 #endif 1723 1744 1724 1745 String MediaPlayer::elementId() const -
trunk/Source/WebCore/platform/graphics/MediaPlayer.h
r284857 r285993 287 287 virtual void mediaPlayerQueueTaskOnEventLoop(Function<void()>&& task) { callOnMainThread(WTFMove(task)); } 288 288 289 #if PLATFORM(COCOA) 290 virtual void mediaPlayerOnNewVideoFrameMetadata(VideoFrameMetadata&&, RetainPtr<CVPixelBufferRef>&&) { } 291 #endif 292 289 293 #if !RELEASE_LOG_DISABLED 290 294 virtual const void* mediaPlayerLogIdentifier() { return nullptr; } … … 584 588 void removeTextTrack(InbandTextTrackPrivate&); 585 589 void removeVideoTrack(VideoTrackPrivate&); 590 591 #if PLATFORM(COCOA) 592 void onNewVideoFrameMetadata(VideoFrameMetadata&&, RetainPtr<CVPixelBufferRef>&&); 593 #endif 586 594 587 595 bool requiresTextTrackRepresentation() const; … … 682 690 683 691 std::optional<VideoFrameMetadata> videoFrameMetadata(); 692 void startVideoFrameMetadataGathering(); 693 void stopVideoFrameMetadataGathering(); 684 694 685 695 private: … … 726 736 bool m_shouldContinueAfterKeyNeeded { false }; 727 737 #endif 738 bool m_isGatheringVideoFrameMetadata { false }; 728 739 }; 729 740 -
trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h
r284857 r285993 324 324 325 325 virtual std::optional<VideoFrameMetadata> videoFrameMetadata() { return { }; } 326 virtual void startVideoFrameMetadataGathering() { } 327 virtual void stopVideoFrameMetadataGathering() { } 326 328 }; 327 329 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
r285330 r285993 29 29 30 30 #include "MediaPlayerPrivateAVFoundation.h" 31 #include <CoreMedia/CMTime.h> 31 32 #include <wtf/Function.h> 32 33 #include <wtf/HashMap.h> … … 342 343 bool pauseAtHostTime(const MonotonicTime&) final; 343 344 bool haveBeenAskedToPaint() const { return m_haveBeenAskedToPaint; } 345 346 void startVideoFrameMetadataGathering() final; 347 void stopVideoFrameMetadataGathering() final; 348 std::optional<VideoFrameMetadata> videoFrameMetadata() final { return std::exchange(m_videoFrameMetadata, { }); } 349 void checkNewVideoFrameMetadata(CMTime); 344 350 345 351 RetainPtr<AVURLAsset> m_avAsset; … … 452 458 bool m_waitForVideoOutputMediaDataWillChangeTimedOut { false }; 453 459 bool m_haveBeenAskedToPaint { false }; 460 uint64_t m_sampleCount { 0 }; 461 RetainPtr<id> m_videoFrameMetadataGatheringObserver; 462 bool m_isGatheringVideoFrameMetadata { false }; 463 std::optional<VideoFrameMetadata> m_videoFrameMetadata; 454 464 }; 455 465 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
r285330 r285993 537 537 m_currentTimeObserver = nil; 538 538 539 if (m_videoFrameMetadataGatheringObserver) { 540 [m_avPlayer removeTimeObserver:m_videoFrameMetadataGatheringObserver.get()]; 541 m_videoFrameMetadataGatheringObserver = nil; 542 } 543 539 544 m_avPlayer = nil; 540 545 } … … 1109 1114 }]; 1110 1115 1116 if (m_isGatheringVideoFrameMetadata) 1117 startVideoFrameMetadataGathering(); 1111 1118 setDelayCallbacks(false); 1112 1119 } … … 1432 1439 { 1433 1440 return m_cachedTimeControlStatus == AVPlayerTimeControlStatusPaused; 1441 } 1442 1443 void MediaPlayerPrivateAVFoundationObjC::startVideoFrameMetadataGathering() 1444 { 1445 ASSERT(!m_videoFrameMetadataGatheringObserver || m_avPlayer); 1446 m_isGatheringVideoFrameMetadata = true; 1447 1448 // FIXME: We should use a CADisplayLink to get updates on rendering, for now we emulate with addPeriodicTimeObserverForInterval. 1449 m_videoFrameMetadataGatheringObserver = [m_avPlayer addPeriodicTimeObserverForInterval:PAL::CMTimeMake(1, 60) queue:dispatch_get_main_queue() usingBlock:[weakThis = WeakPtr { *this }](CMTime currentTime) { 1450 ensureOnMainThread([weakThis, currentTime] { 1451 if (weakThis) 1452 weakThis->checkNewVideoFrameMetadata(currentTime); 1453 }); 1454 }]; 1455 } 1456 1457 void MediaPlayerPrivateAVFoundationObjC::checkNewVideoFrameMetadata(CMTime currentTime) 1458 { 1459 if (!updateLastPixelBuffer()) 1460 return; 1461 1462 VideoFrameMetadata metadata; 1463 metadata.width = m_cachedPresentationSize.width(); 1464 metadata.height = m_cachedPresentationSize.height(); 1465 metadata.presentedFrames = ++m_sampleCount; 1466 metadata.mediaTime = PAL::CMTimeGetSeconds(currentTime); 1467 // FIXME: presentationTime and expectedDisplayTime might not always have the same value, we should try getting more precise values. 1468 metadata.presentationTime = MonotonicTime::now().secondsSinceEpoch().seconds(); 1469 metadata.expectedDisplayTime = metadata.presentationTime; 1470 1471 m_videoFrameMetadata = metadata; 1472 player()->onNewVideoFrameMetadata(WTFMove(metadata), m_lastPixelBuffer.get()); 1473 } 1474 1475 void MediaPlayerPrivateAVFoundationObjC::stopVideoFrameMetadataGathering() 1476 { 1477 m_isGatheringVideoFrameMetadata = false; 1478 m_videoFrameMetadata = { }; 1479 1480 if (m_videoFrameMetadataGatheringObserver) { 1481 [m_avPlayer removeTimeObserver:m_videoFrameMetadataGatheringObserver.get()]; 1482 m_videoFrameMetadataGatheringObserver = nil; 1483 } 1434 1484 } 1435 1485 … … 2549 2599 // for the requested time has already been retrieved. In this case, the last valid image (if any) 2550 2600 // should be displayed. 2551 if ( !updateLastPixelBuffer() && (m_lastImage || !m_lastPixelBuffer))2601 if ((m_isGatheringVideoFrameMetadata || !updateLastPixelBuffer()) && (m_lastImage || !m_lastPixelBuffer)) 2552 2602 return; 2553 2603 … … 2584 2634 RetainPtr<CVPixelBufferRef> MediaPlayerPrivateAVFoundationObjC::pixelBufferForCurrentTime() 2585 2635 { 2586 updateLastPixelBuffer(); 2587 if (!m_lastPixelBuffer) 2588 return nullptr; 2636 if (!m_isGatheringVideoFrameMetadata) 2637 updateLastPixelBuffer(); 2589 2638 2590 2639 return m_lastPixelBuffer; -
trunk/Source/WebCore/platform/graphics/cv/PixelBufferConformerCV.h
r269371 r285993 39 39 WEBCORE_EXPORT PixelBufferConformerCV(CFDictionaryRef attributes); 40 40 WEBCORE_EXPORT RetainPtr<CVPixelBufferRef> convert(CVPixelBufferRef); 41 RetainPtr<CGImageRef> createImageFromPixelBuffer(CVPixelBufferRef);41 WEBCORE_EXPORT RetainPtr<CGImageRef> createImageFromPixelBuffer(CVPixelBufferRef); 42 42 43 43 private: -
trunk/Source/WebKit/ChangeLog
r285992 r285993 1 2021-11-18 Youenn Fablet <youenn@apple.com> 2 3 MediaPlayerAVFoundation should support rvfc 4 https://bugs.webkit.org/show_bug.cgi?id=231945 5 <rdar://problem/84657372> 6 7 Reviewed by Eric Carlson. 8 9 Add IPC messaging to start/stop metadata gathering from WebProcess to GPUProcess. 10 Add IPC messaging to push metadata to WebProcess, including sending the corresponding CVPixelBuffer for the current metadata. 11 MediaPlayerPrivateRemote will then serve that buffer when being requested the current image. 12 This ensures that painting on a canvas does not mark the current buffer as acquired, which would then skip the video frame metadata gathering. 13 This also ensures the same buffer is used if a video element is painted several times during the same rvfc callback. 14 This has the side benefit of removing the synchronous IPC to paint the video element in a canvas. 15 16 * GPUProcess/media/RemoteMediaPlayerProxy.cpp: 17 * GPUProcess/media/RemoteMediaPlayerProxy.h: 18 * GPUProcess/media/RemoteMediaPlayerProxy.messages.in: 19 * GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm: 20 * Scripts/webkit/messages.py: 21 * WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp: 22 * WebProcess/GPU/media/MediaPlayerPrivateRemote.h: 23 * WebProcess/GPU/media/MediaPlayerPrivateRemote.messages.in: 24 * WebProcess/GPU/media/cocoa/MediaPlayerPrivateRemoteCocoa.mm: 25 1 26 2021-11-18 Chris Lord <clord@igalia.com> 2 27 -
trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp
r284294 r285993 1099 1099 } 1100 1100 1101 void RemoteMediaPlayerProxy::startVideoFrameMetadataGathering() 1102 { 1103 if (m_player) 1104 m_player->startVideoFrameMetadataGathering(); 1105 } 1106 1107 void RemoteMediaPlayerProxy::stopVideoFrameMetadataGathering() 1108 { 1109 if (m_player) 1110 m_player->startVideoFrameMetadataGathering(); 1111 } 1112 1101 1113 #if !RELEASE_LOG_DISABLED 1102 1114 WTFLogChannel& RemoteMediaPlayerProxy::logChannel() const -
trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h
r284439 r285993 308 308 void pauseAtHostTime(MonotonicTime); 309 309 310 void startVideoFrameMetadataGathering(); 311 void stopVideoFrameMetadataGathering(); 312 #if PLATFORM(COCOA) 313 void mediaPlayerOnNewVideoFrameMetadata(WebCore::VideoFrameMetadata&&, RetainPtr<CVPixelBufferRef>&&); 314 #endif 315 310 316 bool mediaPlayerPausedOrStalled() const; 311 317 void currentTimeChanged(const MediaTime&); -
trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.messages.in
r284439 r285993 133 133 PlayAtHostTime(MonotonicTime time) 134 134 PauseAtHostTime(MonotonicTime time) 135 136 StartVideoFrameMetadataGathering() 137 StopVideoFrameMetadataGathering() 135 138 } 136 139 -
trunk/Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm
r284439 r285993 31 31 #import "LayerHostingContext.h" 32 32 #import "MediaPlayerPrivateRemoteMessages.h" 33 #import "WebCoreArgumentCoders.h" 33 34 #import <QuartzCore/QuartzCore.h> 34 35 #import <WebCore/FloatSize.h> … … 82 83 m_videoInlineSize = size; 83 84 setVideoInlineSizeIfPossible(*m_inlineLayerHostingContext, size); 85 } 86 87 void RemoteMediaPlayerProxy::mediaPlayerOnNewVideoFrameMetadata(VideoFrameMetadata&& metadata, RetainPtr<CVPixelBufferRef>&& buffer) 88 { 89 m_webProcessConnection->send(Messages::MediaPlayerPrivateRemote::PushVideoFrameMetadata(metadata, buffer), m_id); 84 90 } 85 91 -
trunk/Source/WebKit/Scripts/webkit/messages.py
r285981 r285993 372 372 '"GestureTypes.h"': ["PLATFORM(IOS_FAMILY)"], 373 373 '"WCLayerTreeHostIdentifier.h"': ["USE(GRAPHICS_LAYER_WC)"], 374 '<WebCore/CVUtilities.h>': ["PLATFORM(COCOA)", ], 375 '<WebCore/DataDetectorType.h>': ["ENABLE(DATA_DETECTION)"], 374 376 '<WebCore/MediaPlaybackTargetContext.h>': ["ENABLE(WIRELESS_PLAYBACK_TARGET)"], 375 '<WebCore/DataDetectorType.h>': ["ENABLE(DATA_DETECTION)"],376 377 } 377 378 if not header in conditions: … … 680 681 681 682 special_cases = { 683 'CVPixelBufferRef': ['<WebCore/CVUtilities.h>'], 682 684 'IPC::Semaphore': ['"IPCSemaphore.h"'], 683 685 'Inspector::ExtensionError': ['"InspectorExtensionTypes.h"'], -
trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp
r284741 r285993 81 81 82 82 #if PLATFORM(COCOA) 83 #import <WebCore/PixelBufferConformerCV.h> 83 84 #import <WebCore/VideoLayerManagerObjC.h> 84 85 #endif … … 1378 1379 } 1379 1380 1381 std::optional<VideoFrameMetadata> MediaPlayerPrivateRemote::videoFrameMetadata() 1382 { 1383 auto videoFrameMetadata = std::exchange(m_videoFrameMetadata, { }); 1384 return videoFrameMetadata; 1385 } 1386 1387 void MediaPlayerPrivateRemote::startVideoFrameMetadataGathering() 1388 { 1389 m_isGatheringVideoFrameMetadata = true; 1390 connection().send(Messages::RemoteMediaPlayerProxy::StartVideoFrameMetadataGathering(), m_id); 1391 } 1392 1393 void MediaPlayerPrivateRemote::stopVideoFrameMetadataGathering() 1394 { 1395 m_isGatheringVideoFrameMetadata = false; 1396 #if PLATFORM(COCOA) 1397 m_pixelBufferGatheredWithVideoFrameMetadata = nullptr; 1398 #endif 1399 connection().send(Messages::RemoteMediaPlayerProxy::StopVideoFrameMetadataGathering(), m_id); 1400 } 1401 1380 1402 void MediaPlayerPrivateRemote::requestResource(RemoteMediaResourceIdentifier remoteMediaResourceIdentifier, WebCore::ResourceRequest&& request, WebCore::PlatformMediaResourceLoader::LoadOptions options, CompletionHandler<void()>&& completionHandler) 1381 1403 { -
trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.h
r284741 r285993 40 40 #include <WebCore/MediaPlayerPrivate.h> 41 41 #include <WebCore/SecurityOriginData.h> 42 #include <WebCore/VideoFrameMetadata.h> 42 43 #include <wtf/LoggerHelper.h> 43 44 #include <wtf/MediaTime.h> … … 57 58 class SerializedPlatformDataCueValue; 58 59 class VideoLayerManager; 60 61 #if PLATFORM(COCOA) 62 class PixelBufferConformerCV; 63 #endif 59 64 } 60 65 … … 400 405 bool pauseAtHostTime(const MonotonicTime&) final; 401 406 void updateConfiguration(RemoteMediaPlayerConfiguration&&); 407 408 std::optional<WebCore::VideoFrameMetadata> videoFrameMetadata() final; 409 void startVideoFrameMetadataGathering() final; 410 void stopVideoFrameMetadataGathering() final; 411 412 #if PLATFORM(COCOA) 413 void pushVideoFrameMetadata(WebCore::VideoFrameMetadata&&, RetainPtr<CVPixelBufferRef>&&); 414 #endif 402 415 403 416 WeakPtr<WebCore::MediaPlayer> m_player; … … 451 464 RetainPtr<CVPixelBufferRef> m_pixelBufferForCurrentTime; 452 465 #endif 466 #if PLATFORM(COCOA) 467 RetainPtr<CVPixelBufferRef> m_pixelBufferGatheredWithVideoFrameMetadata; 468 std::unique_ptr<WebCore::PixelBufferConformerCV> m_pixelBufferConformer; 469 #endif 470 std::optional<WebCore::VideoFrameMetadata> m_videoFrameMetadata; 471 bool m_isGatheringVideoFrameMetadata { false }; 453 472 }; 454 473 -
trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.messages.in
r278917 r285993 92 92 GetRawCookies(URL url) -> (Vector<WebCore::Cookie> result) Async 93 93 #endif 94 95 #if PLATFORM(COCOA) 96 PushVideoFrameMetadata(struct WebCore::VideoFrameMetadata metadata, RetainPtr<CVPixelBufferRef> buffer); 97 #endif 94 98 } 95 99 -
trunk/Source/WebKit/WebProcess/GPU/media/cocoa/MediaPlayerPrivateRemoteCocoa.mm
r284439 r285993 34 34 #import <WebCore/ColorSpaceCG.h> 35 35 #import <WebCore/IOSurface.h> 36 #import <WebCore/PixelBufferConformerCV.h> 36 37 #import <pal/spi/cocoa/QuartzCoreSPI.h> 37 38 #import <wtf/MachSendRight.h> 39 40 #import <WebCore/CoreVideoSoftLink.h> 38 41 39 42 namespace WebKit { … … 47 50 #endif 48 51 52 void MediaPlayerPrivateRemote::pushVideoFrameMetadata(WebCore::VideoFrameMetadata&& videoFrameMetadata, RetainPtr<CVPixelBufferRef>&& buffer) 53 { 54 if (!m_isGatheringVideoFrameMetadata) 55 return; 56 m_videoFrameMetadata = WTFMove(videoFrameMetadata); 57 m_pixelBufferGatheredWithVideoFrameMetadata = WTFMove(buffer); 58 } 59 49 60 RefPtr<NativeImage> MediaPlayerPrivateRemote::nativeImageForCurrentTime() 50 61 { 62 if (m_pixelBufferGatheredWithVideoFrameMetadata) { 63 if (!m_pixelBufferConformer) 64 m_pixelBufferConformer = makeUnique<PixelBufferConformerCV>((__bridge CFDictionaryRef)@{ (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA) }); 65 ASSERT(m_pixelBufferConformer); 66 if (!m_pixelBufferConformer) 67 return nullptr; 68 return NativeImage::create(m_pixelBufferConformer->createImageFromPixelBuffer(m_pixelBufferGatheredWithVideoFrameMetadata.get())); 69 } 70 51 71 std::optional<MachSendRight> sendRight; 52 72 auto colorSpace = DestinationColorSpace::SRGB(); -
trunk/Tools/ChangeLog
r285988 r285993 1 2021-11-18 Youenn Fablet <youenn@apple.com> 2 3 MediaPlayerAVFoundation should support rvfc 4 https://bugs.webkit.org/show_bug.cgi?id=231945 5 6 Reviewed by Eric Carlson. 7 8 Enable rvfc by default in test runner. 9 10 * DumpRenderTree/mac/DumpRenderTree.mm: 11 * WebKitTestRunner/TestController.cpp: 12 1 13 2021-11-18 Carlos Garcia Campos <cgarcia@igalia.com> 2 14 -
trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm
r284528 r285993 864 864 865 865 if (enableAllExperimentalFeatures) { 866 for (WebFeature *feature in [WebPreferences _experimentalFeatures]) { 867 // FIXME: We disable rvfc by default. Enable it when the video backend support is good enough. 868 auto enabled = [feature.name isEqual:@"RequestVideoFrameCallback"] ? NO : YES; 869 [preferences _setEnabled:enabled forFeature:feature]; 870 } 866 for (WebFeature *feature in [WebPreferences _experimentalFeatures]) 867 [preferences _setEnabled:YES forFeature:feature]; 871 868 } 872 869 -
trunk/Tools/WebKitTestRunner/TestController.cpp
r285168 r285993 906 906 WKPreferencesEnableAllExperimentalFeatures(preferences); 907 907 908 // FIXME: We disable rvfc by default. Enable it when the video backend support is good enough.909 WKPreferencesSetRequestVideoFrameCallbackEnabled(preferences, false);910 911 908 WKPreferencesResetAllInternalDebugFeatures(preferences); 912 909
Note:
See TracChangeset
for help on using the changeset viewer.