mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	browser(webkit): encode screencast frames on a dedicated thread (#2433)
This commit is contained in:
		
							parent
							
								
									454411062b
								
							
						
					
					
						commit
						0a34d05b3e
					
				@ -1 +1 @@
 | 
			
		||||
1250
 | 
			
		||||
1251
 | 
			
		||||
 | 
			
		||||
@ -8649,10 +8649,10 @@ index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..52fe7990b1c18b964ee3cfa9f324e3c2
 | 
			
		||||
     // The timeout we use when waiting for a DidUpdateGeometry message.
 | 
			
		||||
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..eac34bd46ae7b391d81fb0f21762024f2f97c8fa
 | 
			
		||||
index 0000000000000000000000000000000000000000..b58cea323c822ca6352e1cf907ab214e25345592
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
 | 
			
		||||
@@ -0,0 +1,252 @@
 | 
			
		||||
@@ -0,0 +1,253 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * Copyright (C) 2020 Microsoft Corporation.
 | 
			
		||||
+ *
 | 
			
		||||
@ -8815,9 +8815,10 @@ index 0000000000000000000000000000000000000000..eac34bd46ae7b391d81fb0f21762024f
 | 
			
		||||
+    if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(m_page.drawingArea()))
 | 
			
		||||
+        drawingArea->setPaintCallback(nullptr);
 | 
			
		||||
+
 | 
			
		||||
+    m_encoder->finish();
 | 
			
		||||
+    m_encoder = nullptr;
 | 
			
		||||
+    m_encoder->finish([protectRef = m_encoder.copyRef(), callback = WTFMove(callback)] {
 | 
			
		||||
+        callback->sendSuccess();
 | 
			
		||||
+    });
 | 
			
		||||
+    m_encoder = nullptr;
 | 
			
		||||
+#else
 | 
			
		||||
+    callback->sendFailure("Not implemented."_s);
 | 
			
		||||
+#endif
 | 
			
		||||
@ -8907,7 +8908,7 @@ index 0000000000000000000000000000000000000000..eac34bd46ae7b391d81fb0f21762024f
 | 
			
		||||
+} // namespace WebKit
 | 
			
		||||
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..a957c3b2586d67caa78b96bb8644bab8d8919e14
 | 
			
		||||
index 0000000000000000000000000000000000000000..77d4a06e4717629916241dc47cb057f4f6121743
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h
 | 
			
		||||
@@ -0,0 +1,85 @@
 | 
			
		||||
@ -8991,17 +8992,17 @@ index 0000000000000000000000000000000000000000..a957c3b2586d67caa78b96bb8644bab8
 | 
			
		||||
+    ImageFormat m_format { ImageFormat::Jpeg };
 | 
			
		||||
+    Optional<int> m_quality;
 | 
			
		||||
+#if PLATFORM(GTK)
 | 
			
		||||
+    std::unique_ptr<ScreencastEncoder> m_encoder;
 | 
			
		||||
+    RefPtr<ScreencastEncoder> m_encoder;
 | 
			
		||||
+#endif
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+} // namespace WebKit
 | 
			
		||||
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324ddd10d22
 | 
			
		||||
index 0000000000000000000000000000000000000000..46b324bf95e2d61fd4b9e67b7d646105fab943b1
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
 | 
			
		||||
@@ -0,0 +1,335 @@
 | 
			
		||||
@@ -0,0 +1,400 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * Copyright (c) 2010, The WebM Project authors. All rights reserved.
 | 
			
		||||
+ * Copyright (c) 2013 The Chromium Authors. All rights reserved.
 | 
			
		||||
@ -9038,6 +9039,9 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+#include <vpx/vp8.h>
 | 
			
		||||
+#include <vpx/vp8cx.h>
 | 
			
		||||
+#include <vpx/vpx_encoder.h>
 | 
			
		||||
+#include <wtf/MonotonicTime.h>
 | 
			
		||||
+#include <wtf/RunLoop.h>
 | 
			
		||||
+#include <wtf/WorkQueue.h>
 | 
			
		||||
+
 | 
			
		||||
+using namespace WebCore;
 | 
			
		||||
+
 | 
			
		||||
@ -9157,10 +9161,60 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+
 | 
			
		||||
+} // namespace
 | 
			
		||||
+
 | 
			
		||||
+class ScreencastEncoder::VPXFrame {
 | 
			
		||||
+    WTF_MAKE_NONCOPYABLE(VPXFrame);
 | 
			
		||||
+    WTF_MAKE_FAST_ALLOCATED;
 | 
			
		||||
+public:
 | 
			
		||||
+    VPXFrame(RefPtr<cairo_surface_t>&& surface, IntSize size)
 | 
			
		||||
+        : m_surface(WTFMove(surface))
 | 
			
		||||
+        , m_size(size)
 | 
			
		||||
+    { }
 | 
			
		||||
+
 | 
			
		||||
+    void setDuration(int duration) { m_duration = duration; }
 | 
			
		||||
+    int duration() const { return m_duration; }
 | 
			
		||||
+
 | 
			
		||||
+    vpx_image_t* convertToVpxImage()
 | 
			
		||||
+    {
 | 
			
		||||
+        if (m_image)
 | 
			
		||||
+            return m_image.get();
 | 
			
		||||
+
 | 
			
		||||
+        createImage(m_size, m_image, m_imageBuffer);
 | 
			
		||||
+
 | 
			
		||||
+        // Convert the updated region to YUV ready for encoding.
 | 
			
		||||
+        const uint8_t* rgba_data = cairo_image_surface_get_data(m_surface.get());
 | 
			
		||||
+        int rgba_stride = cairo_image_surface_get_stride(m_surface.get());
 | 
			
		||||
+
 | 
			
		||||
+        const int y_stride = m_image->stride[0];
 | 
			
		||||
+        ASSERT(m_image->stride[1] == m_image->stride[2]);
 | 
			
		||||
+        const int uv_stride = m_image->stride[1];
 | 
			
		||||
+        uint8_t* y_data = m_image->planes[0];
 | 
			
		||||
+        uint8_t* u_data = m_image->planes[1];
 | 
			
		||||
+        uint8_t* v_data = m_image->planes[2];
 | 
			
		||||
+
 | 
			
		||||
+        // TODO: redraw only damaged regions?
 | 
			
		||||
+        libyuv::ARGBToI420(rgba_data, rgba_stride,
 | 
			
		||||
+                            y_data, y_stride,
 | 
			
		||||
+                            u_data, uv_stride,
 | 
			
		||||
+                            v_data, uv_stride,
 | 
			
		||||
+                            m_size.width(), m_size.height());
 | 
			
		||||
+
 | 
			
		||||
+        return m_image.get();
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+private:
 | 
			
		||||
+    RefPtr<cairo_surface_t> m_surface;
 | 
			
		||||
+    IntSize m_size;
 | 
			
		||||
+    int m_duration = 0;
 | 
			
		||||
+    std::unique_ptr<uint8_t[]> m_imageBuffer;
 | 
			
		||||
+    std::unique_ptr<vpx_image_t> m_image;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+class ScreencastEncoder::VPXCodec {
 | 
			
		||||
+public:
 | 
			
		||||
+    VPXCodec(uint32_t fourcc, vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
 | 
			
		||||
+        : m_fourcc(fourcc)
 | 
			
		||||
+        : m_encoderQueue(WorkQueue::create("Screencast encoder"))
 | 
			
		||||
+        , m_fourcc(fourcc)
 | 
			
		||||
+        , m_codec(codec)
 | 
			
		||||
+        , m_cfg(cfg)
 | 
			
		||||
+        , m_file(file)
 | 
			
		||||
@ -9168,12 +9222,27 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+        ivf_write_file_header(m_file, &m_cfg, m_fourcc, 0);
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    bool encodeFrame(vpx_image_t *img)
 | 
			
		||||
+    void encodeFrameAsync(std::unique_ptr<VPXFrame>&& frame)
 | 
			
		||||
+    {
 | 
			
		||||
+        m_encoderQueue->dispatch([this, frame = WTFMove(frame)] {
 | 
			
		||||
+            encodeFrame(frame->convertToVpxImage(), frame->duration());
 | 
			
		||||
+        });
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    void finishAsync(Function<void()>&& callback)
 | 
			
		||||
+    {
 | 
			
		||||
+        m_encoderQueue->dispatch([this, callback = WTFMove(callback)] {
 | 
			
		||||
+            finish();
 | 
			
		||||
+            callback();
 | 
			
		||||
+        });
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+private:
 | 
			
		||||
+    bool encodeFrame(vpx_image_t *img, int duration)
 | 
			
		||||
+    {
 | 
			
		||||
+        vpx_codec_iter_t iter = nullptr;
 | 
			
		||||
+        const vpx_codec_cx_pkt_t *pkt = nullptr;
 | 
			
		||||
+        int flags = 0;
 | 
			
		||||
+        unsigned long duration =  1;
 | 
			
		||||
+        const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME);
 | 
			
		||||
+        if (res != VPX_CODEC_OK) {
 | 
			
		||||
+            fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
 | 
			
		||||
@ -9191,9 +9260,9 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+                    return 0;
 | 
			
		||||
+                }
 | 
			
		||||
+                bool keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
 | 
			
		||||
+                fprintf(stderr, "  %spts=%ld sz=%ld\n", keyframe ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz);
 | 
			
		||||
+                m_pts += pkt->data.frame.duration;
 | 
			
		||||
+                ++m_frameCount;
 | 
			
		||||
+                fprintf(stderr, "  #%03d %spts=%ld sz=%ld\n", m_frameCount, keyframe ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz);
 | 
			
		||||
+                m_pts += pkt->data.frame.duration;
 | 
			
		||||
+            }
 | 
			
		||||
+        }
 | 
			
		||||
+
 | 
			
		||||
@ -9203,7 +9272,7 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+    void finish()
 | 
			
		||||
+    {
 | 
			
		||||
+        // Flush encoder.
 | 
			
		||||
+        while (encodeFrame(nullptr))
 | 
			
		||||
+        while (encodeFrame(nullptr, 1))
 | 
			
		||||
+            ++m_frameCount;
 | 
			
		||||
+
 | 
			
		||||
+        rewind(m_file);
 | 
			
		||||
@ -9213,13 +9282,13 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+        fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+private:
 | 
			
		||||
+    uint32_t m_fourcc = 0;
 | 
			
		||||
+    Ref<WorkQueue> m_encoderQueue;
 | 
			
		||||
+    uint32_t m_fourcc { 0 };
 | 
			
		||||
+    vpx_codec_ctx_t m_codec;
 | 
			
		||||
+    vpx_codec_enc_cfg_t m_cfg;
 | 
			
		||||
+    FILE* m_file = nullptr;
 | 
			
		||||
+    int m_frameCount = 0;
 | 
			
		||||
+    int64_t m_pts;
 | 
			
		||||
+    FILE* m_file { nullptr };
 | 
			
		||||
+    int m_frameCount { 0 };
 | 
			
		||||
+    int64_t m_pts { 0 };
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec)
 | 
			
		||||
@ -9229,13 +9298,15 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+
 | 
			
		||||
+ScreencastEncoder::~ScreencastEncoder()
 | 
			
		||||
+{
 | 
			
		||||
+    finish();
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+#define VP8_FOURCC 0x30385056
 | 
			
		||||
+#define VP9_FOURCC 0x30395056
 | 
			
		||||
+
 | 
			
		||||
+std::unique_ptr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, int w, int h)
 | 
			
		||||
+static const int fps = 30;
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+RefPtr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, int w, int h)
 | 
			
		||||
+{
 | 
			
		||||
+    const uint32_t fourcc = VP8_FOURCC;
 | 
			
		||||
+    vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
 | 
			
		||||
@ -9259,7 +9330,6 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+
 | 
			
		||||
+    cfg.g_w = w;
 | 
			
		||||
+    cfg.g_h = h;
 | 
			
		||||
+    const int fps = 30;
 | 
			
		||||
+    cfg.g_timebase.num = 1;
 | 
			
		||||
+    cfg.g_timebase.den = fps;
 | 
			
		||||
+    cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
 | 
			
		||||
@ -9278,13 +9348,25 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+
 | 
			
		||||
+    std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(fourcc, codec, cfg, file));
 | 
			
		||||
+    fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
 | 
			
		||||
+    return makeUnique<ScreencastEncoder>(WTFMove(vpxCodec));
 | 
			
		||||
+    return adoptRef(new ScreencastEncoder(WTFMove(vpxCodec)));
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+void ScreencastEncoder::flushLastFrame()
 | 
			
		||||
+{
 | 
			
		||||
+    MonotonicTime now = MonotonicTime::now();
 | 
			
		||||
+    if (m_lastFrameTimestamp) {
 | 
			
		||||
+        Seconds seconds = now - m_lastFrameTimestamp;
 | 
			
		||||
+        int duration = 1 + seconds.seconds() * fps; // Duration in timebase units
 | 
			
		||||
+        m_lastFrame->setDuration(duration);
 | 
			
		||||
+        m_vpxCodec->encodeFrameAsync(WTFMove(m_lastFrame));
 | 
			
		||||
+    }
 | 
			
		||||
+    m_lastFrameTimestamp = now;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface)
 | 
			
		||||
+{
 | 
			
		||||
+    fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
 | 
			
		||||
+
 | 
			
		||||
+    flushLastFrame();
 | 
			
		||||
+    IntSize size = cairoSurfaceSize(drawingAreaSurface);
 | 
			
		||||
+    if (size.isZero()) {
 | 
			
		||||
+        fprintf(stderr, "Cairo surface size is 0\n");
 | 
			
		||||
@ -9293,56 +9375,40 @@ index 0000000000000000000000000000000000000000..6e0c7ffce5201430c04c95247e812324
 | 
			
		||||
+
 | 
			
		||||
+    // TODO: scale image if the size has changed.
 | 
			
		||||
+    // TODO: adjust device scale factor?
 | 
			
		||||
+    RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()));
 | 
			
		||||
+    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()));
 | 
			
		||||
+    {
 | 
			
		||||
+        RefPtr<cairo_t> cr = adoptRef(cairo_create(newSurface.get()));
 | 
			
		||||
+        RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
 | 
			
		||||
+        cairo_set_source_surface(cr.get(), drawingAreaSurface, 0, 0);
 | 
			
		||||
+        cairo_paint(cr.get());
 | 
			
		||||
+    }
 | 
			
		||||
+    cairo_surface_flush(newSurface.get());
 | 
			
		||||
+    cairo_surface_flush(surface.get());
 | 
			
		||||
+
 | 
			
		||||
+    std::unique_ptr<vpx_image_t> image;
 | 
			
		||||
+    std::unique_ptr<uint8_t[]> image_buffer;
 | 
			
		||||
+    createImage(size, image, image_buffer);
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+    // Convert the updated region to YUV ready for encoding.
 | 
			
		||||
+    const uint8_t* rgba_data = cairo_image_surface_get_data(newSurface.get());
 | 
			
		||||
+    int rgba_stride = cairo_image_surface_get_stride(newSurface.get());
 | 
			
		||||
+
 | 
			
		||||
+    const int y_stride = image->stride[0];
 | 
			
		||||
+    ASSERT(image->stride[1] == image->stride[2]);
 | 
			
		||||
+    const int uv_stride = image->stride[1];
 | 
			
		||||
+    uint8_t* y_data = image->planes[0];
 | 
			
		||||
+    uint8_t* u_data = image->planes[1];
 | 
			
		||||
+    uint8_t* v_data = image->planes[2];
 | 
			
		||||
+
 | 
			
		||||
+    // TODO: redraw only damaged regions?
 | 
			
		||||
+    libyuv::ARGBToI420(rgba_data, rgba_stride,
 | 
			
		||||
+                        y_data, y_stride,
 | 
			
		||||
+                        u_data, uv_stride,
 | 
			
		||||
+                        v_data, uv_stride,
 | 
			
		||||
+                        size.width(), size.height());
 | 
			
		||||
+    m_vpxCodec->encodeFrame(image.get());
 | 
			
		||||
+    m_lastFrame = makeUnique<VPXFrame>(WTFMove(surface), size);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+void ScreencastEncoder::finish()
 | 
			
		||||
+void ScreencastEncoder::finish(Function<void()>&& callback)
 | 
			
		||||
+{
 | 
			
		||||
+    if (!m_vpxCodec)
 | 
			
		||||
+    if (!m_vpxCodec) {
 | 
			
		||||
+        callback();
 | 
			
		||||
+        return;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+    m_vpxCodec->finish();
 | 
			
		||||
+    m_vpxCodec = nullptr;
 | 
			
		||||
+    flushLastFrame();
 | 
			
		||||
+    m_vpxCodec->finishAsync([callback = WTFMove(callback)] () mutable {
 | 
			
		||||
+        RunLoop::main().dispatch([callback = WTFMove(callback)] {
 | 
			
		||||
+            callback();
 | 
			
		||||
+        });
 | 
			
		||||
+    });
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+} // namespace WebKit
 | 
			
		||||
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..6ab23625bca03927ef060cc5be6919fe70b836bd
 | 
			
		||||
index 0000000000000000000000000000000000000000..b0c8e5aadcdc44e741fe1b2df5f28eee20f7be3f
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
@@ -0,0 +1,59 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * Copyright (C) 2020 Microsoft Corporation.
 | 
			
		||||
+ *
 | 
			
		||||
@ -9372,27 +9438,33 @@ index 0000000000000000000000000000000000000000..6ab23625bca03927ef060cc5be6919fe
 | 
			
		||||
+
 | 
			
		||||
+#include <wtf/Forward.h>
 | 
			
		||||
+#include <wtf/Noncopyable.h>
 | 
			
		||||
+#include <wtf/ThreadSafeRefCounted.h>
 | 
			
		||||
+#include <wtf/WeakPtr.h>
 | 
			
		||||
+
 | 
			
		||||
+namespace WebKit {
 | 
			
		||||
+
 | 
			
		||||
+class WebPageProxy;
 | 
			
		||||
+
 | 
			
		||||
+class ScreencastEncoder {
 | 
			
		||||
+class ScreencastEncoder : public ThreadSafeRefCounted<ScreencastEncoder> {
 | 
			
		||||
+    WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
 | 
			
		||||
+    WTF_MAKE_FAST_ALLOCATED;
 | 
			
		||||
+public:
 | 
			
		||||
+    static std::unique_ptr<ScreencastEncoder> create(String& errorString, const String& filePath, int width, int height);
 | 
			
		||||
+    static RefPtr<ScreencastEncoder> create(String& errorString, const String& filePath, int width, int height);
 | 
			
		||||
+
 | 
			
		||||
+    class VPXCodec;
 | 
			
		||||
+    explicit ScreencastEncoder(std::unique_ptr<VPXCodec>&&);
 | 
			
		||||
+    ~ScreencastEncoder();
 | 
			
		||||
+
 | 
			
		||||
+    void encodeFrame(cairo_surface_t*);
 | 
			
		||||
+    void finish();
 | 
			
		||||
+    void finish(Function<void()>&& callback);
 | 
			
		||||
+
 | 
			
		||||
+private:
 | 
			
		||||
+    void flushLastFrame();
 | 
			
		||||
+
 | 
			
		||||
+    std::unique_ptr<VPXCodec> m_vpxCodec;
 | 
			
		||||
+    MonotonicTime m_lastFrameTimestamp;
 | 
			
		||||
+    class VPXFrame;
 | 
			
		||||
+    std::unique_ptr<VPXFrame> m_lastFrame;
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+} // namespace WebKit
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user