@@ -8647,10 +8647,10 @@ index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..52fe7990b1c18b964ee3cfa9f324e3c2
8647
8647
// The timeout we use when waiting for a DidUpdateGeometry message.
8648
8648
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
8649
8649
new file mode 100644
8650
- index 0000000000000000000000000000000000000000..abc002273f8cd4a92b31f37c901227657d8e1c88
8650
+ index 0000000000000000000000000000000000000000..eac34bd46ae7b391d81fb0f21762024f2f97c8fa
8651
8651
--- /dev/null
8652
8652
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
8653
- @@ -0,0 +1,251 @@
8653
+ @@ -0,0 +1,252 @@
8654
8654
+/*
8655
8655
+ * Copyright (C) 2020 Microsoft Corporation.
8656
8656
+ *
@@ -8785,14 +8785,15 @@ index 0000000000000000000000000000000000000000..abc002273f8cd4a92b31f37c90122765
8785
8785
+ return;
8786
8786
+ }
8787
8787
+
8788
- + m_encoder = makeUnique<ScreencastEncoder>();
8789
8788
+ if (auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(m_page.drawingArea())) {
8790
- + m_encoder->init(file, drawingArea->size().width(), drawingArea->size().height());
8789
+ + m_encoder = ScreencastEncoder::create(errorString, file, drawingArea->size().width(), drawingArea->size().height());
8790
+ + if (!m_encoder)
8791
+ + return;
8792
+ +
8791
8793
+ drawingArea->setPaintCallback([encoder = m_encoder.get()] (cairo_surface_t* surface) {
8792
8794
+ encoder->encodeFrame(surface);
8793
8795
+ });
8794
8796
+ } else {
8795
- + m_encoder = nullptr;
8796
8797
+ errorString = "Cannot get drawing area."_s;
8797
8798
+ return;
8798
8799
+ }
@@ -8995,10 +8996,10 @@ index 0000000000000000000000000000000000000000..a957c3b2586d67caa78b96bb8644bab8
8995
8996
+} // namespace WebKit
8996
8997
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
8997
8998
new file mode 100644
8998
- index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636a15393ef
8999
+ index 0000000000000000000000000000000000000000..05af437266cb8d561e848c63fdb4056e79c12ff0
8999
9000
--- /dev/null
9000
9001
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
9001
- @@ -0,0 +1,341 @@
9002
+ @@ -0,0 +1,344 @@
9002
9003
+/*
9003
9004
+ * Copyright (c) 2010, The WebM Project authors. All rights reserved.
9004
9005
+ * Copyright (c) 2013 The Chromium Authors. All rights reserved.
@@ -9159,50 +9160,74 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
9159
9160
+ fwrite(header, 1, 4, outfile);
9160
9161
+}
9161
9162
+
9163
+ +} // namespace
9162
9164
+
9163
- +int encode_frame(vpx_codec_ctx_t *codec, vpx_image_t *img,
9164
- + int frame_index, FILE* file) {
9165
- + vpx_codec_iter_t iter = nullptr;
9166
- + const vpx_codec_cx_pkt_t *pkt = nullptr;
9167
- + int flags = 0;
9168
- + const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, flags, VPX_DL_REALTIME);
9169
- + if (res != VPX_CODEC_OK) {
9170
- + fprintf(stderr, "Failed to encode frame: %d\n", res);
9171
- + return 0 ;
9165
+ +class ScreencastEncoder::VPXCodec {
9166
+ +public:
9167
+ + VPXCodec(uint32_t fourcc, vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file)
9168
+ + : m_fourcc(fourcc)
9169
+ + , m_codec(codec)
9170
+ + , m_cfg(cfg)
9171
+ + , m_file(file)
9172
+ + {
9173
+ + ivf_write_file_header(m_file, &m_cfg, m_fourcc, 0) ;
9172
9174
+ }
9173
9175
+
9174
- + int got_pkts = 0;
9175
- + while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != nullptr) {
9176
- + got_pkts = 1;
9176
+ + bool encodeFrame(vpx_image_t *img)
9177
+ + {
9178
+ + vpx_codec_iter_t iter = nullptr;
9179
+ + const vpx_codec_cx_pkt_t *pkt = nullptr;
9180
+ + int flags = 0;
9181
+ + const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_frameCount, 1, flags, VPX_DL_REALTIME);
9182
+ + if (res != VPX_CODEC_OK) {
9183
+ + fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec));
9184
+ + return false;
9185
+ + }
9177
9186
+
9178
- + fprintf(stderr, " pkt->kind=%d\n", pkt->kind);
9179
- + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
9180
- + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
9181
- + ivf_write_frame_header(file, pkt->data.frame.pts, pkt->data.frame.sz);
9182
- + if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, file) != pkt->data.frame.sz) {
9183
- + fprintf(stderr, "Failed to write compressed frame\n");
9184
- + return 0;
9185
- + }
9187
+ + bool gotPkts = false;
9188
+ + while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) {
9189
+ + gotPkts = true;
9190
+ +
9191
+ + fprintf(stderr, " pkt->kind=%d\n", pkt->kind);
9192
+ + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
9193
+ + const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
9194
+ + ivf_write_frame_header(m_file, pkt->data.frame.pts, pkt->data.frame.sz);
9195
+ + if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, m_file) != pkt->data.frame.sz) {
9196
+ + fprintf(stderr, "Failed to write compressed frame\n");
9197
+ + return 0;
9198
+ + }
9186
9199
+
9187
- + fprintf(stderr, " writtend frame (key=%d)\n", keyframe);
9200
+ + ++m_frameCount;
9201
+ + fprintf(stderr, " writtend frame (key=%d)\n", keyframe);
9202
+ + }
9188
9203
+ }
9189
- + }
9190
9204
+
9191
- + return got_pkts ;
9192
- +}
9205
+ + return gotPkts ;
9206
+ + }
9193
9207
+
9194
- +} // namespace
9208
+ + void finish()
9209
+ + {
9210
+ + // Flush encoder.
9211
+ + while (encodeFrame(nullptr))
9212
+ + ++m_frameCount;
9195
9213
+
9214
+ + rewind(m_file);
9215
+ + // Update total frame count.
9216
+ + ivf_write_file_header(m_file, &m_cfg, m_fourcc, m_frameCount);
9217
+ + fclose(m_file);
9218
+ + fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
9219
+ + }
9196
9220
+
9197
- +struct ScreencastEncoder::CodecInfo {
9198
- + uint32_t fourcc = 0;
9199
- + vpx_codec_ctx_t codec ;
9200
- + vpx_codec_enc_cfg_t cfg ;
9201
- + vpx_codec_iface_t* codec_interface = nullptr;
9202
- + FILE* file = nullptr ;
9221
+ +private:
9222
+ + uint32_t m_fourcc = 0;
9223
+ + vpx_codec_ctx_t m_codec ;
9224
+ + vpx_codec_enc_cfg_t m_cfg ;
9225
+ + FILE* m_file = nullptr;
9226
+ + int m_frameCount = 0 ;
9203
9227
+};
9204
9228
+
9205
- +ScreencastEncoder::ScreencastEncoder()
9229
+ +ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec)
9230
+ + : m_vpxCodec(WTFMove(vpxCodec))
9206
9231
+{
9207
9232
+}
9208
9233
+
@@ -9214,59 +9239,51 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
9214
9239
+#define VP8_FOURCC 0x30385056
9215
9240
+#define VP9_FOURCC 0x30395056
9216
9241
+
9217
- +void ScreencastEncoder::init( const String& filePath, int w, int h)
9242
+ +std::unique_ptr<ScreencastEncoder> ScreencastEncoder::create(String& errorString, const String& filePath, int w, int h)
9218
9243
+{
9219
- + vpx_codec_ctx_t codec;
9220
- + vpx_codec_enc_cfg_t cfg;
9221
- + const int fps = 30;
9222
- +
9223
9244
+ const uint32_t fourcc = VP8_FOURCC;
9224
9245
+ vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
9225
- +
9226
9246
+ if (!codec_interface) {
9227
- + fprintf(stderr, "Unsupported codec.\n") ;
9228
- + return;
9247
+ + errorString = "Codec not found." ;
9248
+ + return nullptr ;
9229
9249
+ }
9230
9250
+
9231
9251
+ if (w <= 0 || h <= 0 || (w % 2) != 0 || (h % 2) != 0) {
9232
- + fprintf(stderr, "Invalid frame size: %dx%d\n" , w, h);
9233
- + return;
9252
+ + errorString = makeString( "Invalid frame size: "_s , w, "x"_s , h);
9253
+ + return nullptr ;
9234
9254
+ }
9235
9255
+
9236
- + vpx_codec_err_t res = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
9237
- + if (res) {
9238
- + fprintf(stderr, "Failed to get default codec config.\n");
9239
- + return;
9256
+ + vpx_codec_enc_cfg_t cfg;
9257
+ + memset(&cfg, 0, sizeof(cfg));
9258
+ + vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
9259
+ + if (error) {
9260
+ + errorString = makeString("Failed to get default codec config: "_s, vpx_codec_err_to_string(error));
9261
+ + return nullptr;
9240
9262
+ }
9241
9263
+
9242
9264
+ cfg.g_w = w;
9243
9265
+ cfg.g_h = h;
9266
+ + const int fps = 30;
9244
9267
+ cfg.g_timebase.num = 1;
9245
9268
+ cfg.g_timebase.den = fps;
9246
9269
+ cfg.rc_target_bitrate = 200;
9247
9270
+ cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
9248
9271
+
9272
+ + vpx_codec_ctx_t codec;
9249
9273
+ if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) {
9250
- + fprintf(stderr, "Failed to initialize encoder\n" );
9251
- + return;
9274
+ + errorString = makeString( "Failed to initialize encoder: "_s, vpx_codec_error(&codec) );
9275
+ + return nullptr ;
9252
9276
+ }
9253
9277
+
9254
9278
+ FILE* file = fopen(filePath.utf8().data(), "wb");
9255
9279
+ if (!file) {
9256
- + fprintf(stderr, "%s can't be written to.\n ", filePath.utf8().data( ));
9257
- + return;
9280
+ + errorString = makeString("Failed to open file '", filePath, "' for writing: ", strerror(errno ));
9281
+ + return nullptr ;
9258
9282
+ }
9259
9283
+
9260
- + ivf_write_file_header(file, &cfg, fourcc, 0);
9261
- +
9262
- + m_codecInfo.reset(new CodecInfo());
9263
- + m_codecInfo->fourcc = fourcc;
9264
- + m_codecInfo->codec = codec;
9265
- + m_codecInfo->cfg = cfg;
9266
- + m_codecInfo->codec_interface = codec_interface;
9267
- + m_codecInfo->file = file;
9268
- +
9269
- + fprintf(stderr, "ScreencastEncoder initialized: %s\n", vpx_codec_iface_name(codec_interface));
9284
+ + std::unique_ptr<VPXCodec> vpxCodec(new VPXCodec(fourcc, codec, cfg, file));
9285
+ + fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
9286
+ + return makeUnique<ScreencastEncoder>(WTFMove(vpxCodec));
9270
9287
+}
9271
9288
+
9272
9289
+void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface)
@@ -9313,36 +9330,23 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
9313
9330
+ u_data, uv_stride,
9314
9331
+ v_data, uv_stride,
9315
9332
+ size.width(), size.height());
9316
- + if (encode_frame(&m_codecInfo->codec, image.get(), m_frameCount, m_codecInfo->file))
9317
- + ++m_frameCount;
9333
+ + m_vpxCodec->encodeFrame(image.get());
9318
9334
+}
9319
9335
+
9320
9336
+void ScreencastEncoder::finish()
9321
9337
+{
9322
- + if (!m_codecInfo )
9338
+ + if (!m_vpxCodec )
9323
9339
+ return;
9324
9340
+
9325
- + // Flush encoder.
9326
- + while (encode_frame(&m_codecInfo->codec, NULL, -1, m_codecInfo->file)) {
9327
- + fprintf(stderr, "flushed frame\n");
9328
- + ++m_frameCount;
9329
- + }
9330
- +
9331
- +
9332
- + fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
9333
- + rewind(m_codecInfo->file);
9334
- + ivf_write_file_header(m_codecInfo->file, &m_codecInfo->cfg, m_codecInfo->fourcc, m_frameCount);
9335
- + fclose(m_codecInfo->file);
9336
- +
9337
- + m_codecInfo = nullptr;
9338
- + m_frameCount = 0;
9341
+ + m_vpxCodec->finish();
9342
+ + m_vpxCodec = nullptr;
9339
9343
+}
9340
9344
+
9341
9345
+
9342
9346
+} // namespace WebKit
9343
9347
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
9344
9348
new file mode 100644
9345
- index 0000000000000000000000000000000000000000..944d7166b9e6c74579eb43883c04042d2a7f86e3
9349
+ index 0000000000000000000000000000000000000000..6ab23625bca03927ef060cc5be6919fe70b836bd
9346
9350
--- /dev/null
9347
9351
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
9348
9352
@@ -0,0 +1,53 @@
@@ -9385,17 +9389,17 @@ index 0000000000000000000000000000000000000000..944d7166b9e6c74579eb43883c04042d
9385
9389
+ WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
9386
9390
+ WTF_MAKE_FAST_ALLOCATED;
9387
9391
+public:
9388
- + ScreencastEncoder();
9392
+ + static std::unique_ptr<ScreencastEncoder> create(String& errorString, const String& filePath, int width, int height);
9393
+ +
9394
+ + class VPXCodec;
9395
+ + explicit ScreencastEncoder(std::unique_ptr<VPXCodec>&&);
9389
9396
+ ~ScreencastEncoder();
9390
9397
+
9391
- + void init(const String& filePath, int width, int height);
9392
9398
+ void encodeFrame(cairo_surface_t*);
9393
9399
+ void finish();
9394
9400
+
9395
9401
+private:
9396
- + struct CodecInfo;
9397
- + std::unique_ptr<CodecInfo> m_codecInfo;
9398
- + int m_frameCount { 0 };
9402
+ + std::unique_ptr<VPXCodec> m_vpxCodec;
9399
9403
+};
9400
9404
+
9401
9405
+} // namespace WebKit
0 commit comments