Diff
Modified: trunk/LayoutTests/ChangeLog (213971 => 213972)
--- trunk/LayoutTests/ChangeLog 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/LayoutTests/ChangeLog 2017-03-15 05:21:06 UTC (rev 213972)
@@ -1,3 +1,13 @@
+2017-03-14 Youenn Fablet <[email protected]>
+
+ CanvasCapture should not generate a frame per each canvas draw command
+ https://bugs.webkit.org/show_bug.cgi?id=169498
+
+ Reviewed by Simon Fraser & Eric Carlson.
+
+ * fast/mediastream/captureStream/canvas2d-heavy-drawing-expected.txt: Added.
+ * fast/mediastream/captureStream/canvas2d-heavy-drawing.html: Added.
+
2017-03-14 Wenson Hsieh <[email protected]>
Unreviewed, skip fast/media/video-element-in-details-collapse.html on iOS
Added: trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing-expected.txt (0 => 213972)
--- trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing-expected.txt 2017-03-15 05:21:06 UTC (rev 213972)
@@ -0,0 +1,4 @@
+
+
+PASS captureStream with 2d context drawing
+
Added: trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing.html (0 => 213972)
--- trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing.html (rev 0)
+++ trunk/LayoutTests/fast/mediastream/captureStream/canvas2d-heavy-drawing.html 2017-03-15 05:21:06 UTC (rev 213972)
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <body>
+ <canvas id="canvas1" width=100px height=100px></canvas>
+ <video id="video" autoplay width=100px height=100px></video>
+ <canvas id="canvas2" width=100px height=100px></canvas>
+ <script src=""
+ <script src=""
+ <script>
+
+var canvas1 = document.getElementById("canvas1");
+var canvas2 = document.getElementById("canvas2");
+var video = document.getElementById("video");
+
+var previousTrackSampleCount = 0
+function validateCanvas(resolve, reject)
+{
+ try {
+ if (window.internals) {
+ assert_true((internals.trackVideoSampleCount - previousTrackSampleCount) <= 1, "got too much internals.trackVideoSampleCount");
+ previousTrackSampleCount = internals.trackVideoSampleCount;
+ }
+ canvas2.getContext("2d").drawImage(video, 0 ,0);
+ assert_array_equals(canvas2.getContext("2d").getImageData(0 ,0, 100, 100), canvas2.getContext("2d").getImageData(0, 0, 100, 100));
+ } catch(e) {
+ reject(e);
+ return;
+ }
+ setTimeout(() => { validateCanvas(reject, resolve); }, 5);
+}
+
+function checkCanvas(canvas, stream)
+{
+ return new Promise((resolve, reject) => {
+ video.srcObject = stream;
+ video._onplay_ = () => {
+ if (window.internals)
+ previousTrackSampleCount = internals.trackVideoSampleCount;
+ validateCanvas(resolve, reject);
+ setTimeout(resolve, 500);
+ }
+ });
+}
+
+var cptr = 0;
+function printLine()
+{
+ var context = canvas1.getContext("2d");
+ context.fillStyle = "red";
+ for (var i = 0 ; i < 100; ++i)
+ context.fillRect(0, 0, 100, 100);
+
+ cptr += 5;
+ if (cptr > 255)
+ cptr = 0;
+ context.fillStyle="rgb(0, " + cptr + ", 0)";
+ context.fillRect(0, 0, 100, 100);
+ setTimeout(printLine, 100);
+}
+
+promise_test((test) => {
+ var stream = canvas1.captureStream();
+
+ assert_false(!!stream.getAudioTracks().length);
+ assert_true(stream.getVideoTracks().length == 1);
+
+ if (window.internals)
+ internals.observeMediaStreamTrack(stream.getVideoTracks()[0]);
+
+ promise = checkCanvas(canvas1, stream);
+
+ printLine();
+
+ return promise;
+}, "captureStream with 2d context drawing");
+ </script>
+ </body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (213971 => 213972)
--- trunk/Source/WebCore/ChangeLog 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/ChangeLog 2017-03-15 05:21:06 UTC (rev 213972)
@@ -1,3 +1,29 @@
+2017-03-14 Youenn Fablet <[email protected]>
+
+ CanvasCapture should not generate a frame per each canvas draw command
+ https://bugs.webkit.org/show_bug.cgi?id=169498
+
+ Reviewed by Simon Fraser & Eric Carlson.
+
+ Test: fast/mediastream/captureStream/canvas2d-heavy-drawing.html
+
+ Making Canvas capture be asynchronous.
+ This ensures that one frame will be created for a set of synchronous draw commands.
+ In the future, we should find a better approach, like aligning with requestAnimationFrame.
+ Adding internals observer API for media stream tracks.
+
+ * Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp:
+ (WebCore::CanvasCaptureMediaStreamTrack::Source::Source):
+ (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasChanged):
+ * Modules/mediastream/CanvasCaptureMediaStreamTrack.h:
+ * Modules/mediastream/MediaStreamTrack.idl:
+ * platform/mediastream/RealtimeMediaSource.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::~Internals):
+ (WebCore::Internals::observeMediaStreamTrack):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2017-03-14 Wenson Hsieh <[email protected]>
RenderElements should unregister for viewport visibility callbacks when they are destroyed
Modified: trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp (213971 => 213972)
--- trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp 2017-03-15 05:21:06 UTC (rev 213972)
@@ -62,6 +62,7 @@
: RealtimeMediaSource(String(), Type::Video, String())
, m_frameRequestRate(WTFMove(frameRequestRate))
, m_requestFrameTimer(*this, &Source::requestFrameTimerFired)
+ , m_canvasChangedTimer(*this, &Source::captureCanvas)
, m_canvas(&canvas)
{
m_settings.setWidth(canvas.width());
@@ -123,7 +124,10 @@
{
ASSERT_UNUSED(canvas, m_canvas == &canvas);
- captureCanvas();
+ // FIXME: We should try to generate the frame at the time the screen is being updated.
+ if (m_canvasChangedTimer.isActive())
+ return;
+ m_canvasChangedTimer.startOneShot(0);
}
void CanvasCaptureMediaStreamTrack::Source::captureCanvas()
Modified: trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h (213971 => 213972)
--- trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h 2017-03-15 05:21:06 UTC (rev 213972)
@@ -28,6 +28,7 @@
#include "HTMLCanvasElement.h"
#include "MediaStreamTrack.h"
+#include "Timer.h"
#include <wtf/TypeCasts.h>
namespace WebCore {
@@ -73,6 +74,7 @@
bool m_shouldEmitFrame { true };
std::optional<double> m_frameRequestRate;
Timer m_requestFrameTimer;
+ Timer m_canvasChangedTimer;
RealtimeMediaSourceSettings m_settings;
HTMLCanvasElement* m_canvas;
RefPtr<Image> m_currentImage;
Modified: trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl (213971 => 213972)
--- trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/Modules/mediastream/MediaStreamTrack.idl 2017-03-15 05:21:06 UTC (rev 213972)
@@ -29,6 +29,7 @@
ActiveDOMObject,
Conditional=MEDIA_STREAM,
CustomToJSObject,
+ ExportToWrappedFunction,
PrivateIdentifier,
PublicIdentifier,
] interface MediaStreamTrack : EventTarget {
Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h (213971 => 213972)
--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSource.h 2017-03-15 05:21:06 UTC (rev 213972)
@@ -137,8 +137,8 @@
virtual bool remote() const { return m_remote; }
virtual void setRemote(bool remote) { m_remote = remote; }
- void addObserver(Observer&);
- void removeObserver(Observer&);
+ WEBCORE_EXPORT void addObserver(Observer&);
+ WEBCORE_EXPORT void removeObserver(Observer&);
virtual void startProducingData() { }
virtual void stopProducingData() { }
Modified: trunk/Source/WebCore/testing/Internals.cpp (213971 => 213972)
--- trunk/Source/WebCore/testing/Internals.cpp 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/testing/Internals.cpp 2017-03-15 05:21:06 UTC (rev 213972)
@@ -90,6 +90,7 @@
#include "MallocStatistics.h"
#include "MediaPlayer.h"
#include "MediaProducer.h"
+#include "MediaStreamTrack.h"
#include "MemoryCache.h"
#include "MemoryInfo.h"
#include "MockLibWebRTCPeerConnection.h"
@@ -376,6 +377,8 @@
Internals::~Internals()
{
+ if (m_track)
+ m_track->source().removeObserver(*this);
}
void Internals::resetToConsistentState(Page& page)
@@ -3825,4 +3828,10 @@
#endif
+void Internals::observeMediaStreamTrack(MediaStreamTrack& track)
+{
+ m_track = &track;
+ m_track->source().addObserver(*this);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/Internals.h (213971 => 213972)
--- trunk/Source/WebCore/testing/Internals.h 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/testing/Internals.h 2017-03-15 05:21:06 UTC (rev 213972)
@@ -30,6 +30,7 @@
#include "ContextDestructionObserver.h"
#include "ExceptionOr.h"
#include "PageConsoleClient.h"
+#include "RealtimeMediaSource.h"
#include <runtime/Float32Array.h>
#if ENABLE(MEDIA_SESSION)
@@ -57,6 +58,7 @@
class InternalSettings;
class MallocStatistics;
class MediaSession;
+class MediaStreamTrack;
class MemoryInfo;
class MockCDMFactory;
class MockContentFilterSettings;
@@ -75,7 +77,7 @@
class WebGLRenderingContextBase;
class XMLHttpRequest;
-class Internals final : public RefCounted<Internals>, private ContextDestructionObserver {
+class Internals final : public RefCounted<Internals>, private ContextDestructionObserver, private RealtimeMediaSource::Observer {
public:
static Ref<Internals> create(Document&);
virtual ~Internals();
@@ -544,6 +546,10 @@
void simulateWebGLContextChanged(WebGLRenderingContextBase&);
#endif
+ unsigned long trackAudioSampleCount() const { return m_trackAudioSampleCount; }
+ unsigned long trackVideoSampleCount() const { return m_trackVideoSampleCount; }
+ void observeMediaStreamTrack(MediaStreamTrack&);
+
private:
explicit Internals(Document&);
Document* contextDocument() const;
@@ -551,7 +557,15 @@
ExceptionOr<RenderedDocumentMarker*> markerAt(Node&, const String& markerType, unsigned index);
+ // RealtimeMediaSource::Observer API
+ void videoSampleAvailable(MediaSample&) final { m_trackVideoSampleCount++; }
+ void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final { m_trackAudioSampleCount++; }
+
std::unique_ptr<InspectorStubFrontend> m_inspectorFrontend;
+
+ unsigned long m_trackVideoSampleCount { 0 };
+ unsigned long m_trackAudioSampleCount { 0 };
+ RefPtr<MediaStreamTrack> m_track;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/Internals.idl (213971 => 213972)
--- trunk/Source/WebCore/testing/Internals.idl 2017-03-15 03:28:08 UTC (rev 213971)
+++ trunk/Source/WebCore/testing/Internals.idl 2017-03-15 05:21:06 UTC (rev 213972)
@@ -516,4 +516,8 @@
void disableTileSizeUpdateDelay();
[Conditional=WEBGL] void simulateWebGLContextChanged(WebGLRenderingContextBase context);
+
+ void observeMediaStreamTrack(MediaStreamTrack track);
+ readonly attribute unsigned long trackAudioSampleCount;
+ readonly attribute unsigned long trackVideoSampleCount;
};