Skip to content

Commit 767f6bf

Browse files
authored
browser(webkit): report codec init errors to the client (#2410)
1 parent 1722dcb commit 767f6bf

File tree

2 files changed

+95
-91
lines changed

2 files changed

+95
-91
lines changed

browser_patches/webkit/BUILD_NUMBER

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1246
1+
1247

browser_patches/webkit/patches/bootstrap.diff

Lines changed: 94 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -8647,10 +8647,10 @@ index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..52fe7990b1c18b964ee3cfa9f324e3c2
86478647
// The timeout we use when waiting for a DidUpdateGeometry message.
86488648
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
86498649
new file mode 100644
8650-
index 0000000000000000000000000000000000000000..abc002273f8cd4a92b31f37c901227657d8e1c88
8650+
index 0000000000000000000000000000000000000000..eac34bd46ae7b391d81fb0f21762024f2f97c8fa
86518651
--- /dev/null
86528652
+++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp
8653-
@@ -0,0 +1,251 @@
8653+
@@ -0,0 +1,252 @@
86548654
+/*
86558655
+ * Copyright (C) 2020 Microsoft Corporation.
86568656
+ *
@@ -8785,14 +8785,15 @@ index 0000000000000000000000000000000000000000..abc002273f8cd4a92b31f37c90122765
87858785
+ return;
87868786
+ }
87878787
+
8788-
+ m_encoder = makeUnique<ScreencastEncoder>();
87898788
+ 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+
+
87918793
+ drawingArea->setPaintCallback([encoder = m_encoder.get()] (cairo_surface_t* surface) {
87928794
+ encoder->encodeFrame(surface);
87938795
+ });
87948796
+ } else {
8795-
+ m_encoder = nullptr;
87968797
+ errorString = "Cannot get drawing area."_s;
87978798
+ return;
87988799
+ }
@@ -8995,10 +8996,10 @@ index 0000000000000000000000000000000000000000..a957c3b2586d67caa78b96bb8644bab8
89958996
+} // namespace WebKit
89968997
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
89978998
new file mode 100644
8998-
index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636a15393ef
8999+
index 0000000000000000000000000000000000000000..05af437266cb8d561e848c63fdb4056e79c12ff0
89999000
--- /dev/null
90009001
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp
9001-
@@ -0,0 +1,341 @@
9002+
@@ -0,0 +1,344 @@
90029003
+/*
90039004
+ * Copyright (c) 2010, The WebM Project authors. All rights reserved.
90049005
+ * Copyright (c) 2013 The Chromium Authors. All rights reserved.
@@ -9159,50 +9160,74 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
91599160
+ fwrite(header, 1, 4, outfile);
91609161
+}
91619162
+
9163+
+} // namespace
91629164
+
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);
91729174
+ }
91739175
+
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+
+ }
91779186
+
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+
+ }
91869199
+
9187-
+ fprintf(stderr, " writtend frame (key=%d)\n", keyframe);
9200+
+ ++m_frameCount;
9201+
+ fprintf(stderr, " writtend frame (key=%d)\n", keyframe);
9202+
+ }
91889203
+ }
9189-
+ }
91909204
+
9191-
+ return got_pkts;
9192-
+}
9205+
+ return gotPkts;
9206+
+ }
91939207
+
9194-
+} // namespace
9208+
+ void finish()
9209+
+ {
9210+
+ // Flush encoder.
9211+
+ while (encodeFrame(nullptr))
9212+
+ ++m_frameCount;
91959213
+
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+
+ }
91969220
+
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;
92039227
+};
92049228
+
9205-
+ScreencastEncoder::ScreencastEncoder()
9229+
+ScreencastEncoder::ScreencastEncoder(std::unique_ptr<VPXCodec>&& vpxCodec)
9230+
+ : m_vpxCodec(WTFMove(vpxCodec))
92069231
+{
92079232
+}
92089233
+
@@ -9214,59 +9239,51 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
92149239
+#define VP8_FOURCC 0x30385056
92159240
+#define VP9_FOURCC 0x30395056
92169241
+
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)
92189243
+{
9219-
+ vpx_codec_ctx_t codec;
9220-
+ vpx_codec_enc_cfg_t cfg;
9221-
+ const int fps = 30;
9222-
+
92239244
+ const uint32_t fourcc = VP8_FOURCC;
92249245
+ vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
9225-
+
92269246
+ if (!codec_interface) {
9227-
+ fprintf(stderr, "Unsupported codec.\n");
9228-
+ return;
9247+
+ errorString = "Codec not found.";
9248+
+ return nullptr;
92299249
+ }
92309250
+
92319251
+ 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;
92349254
+ }
92359255
+
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;
92409262
+ }
92419263
+
92429264
+ cfg.g_w = w;
92439265
+ cfg.g_h = h;
9266+
+ const int fps = 30;
92449267
+ cfg.g_timebase.num = 1;
92459268
+ cfg.g_timebase.den = fps;
92469269
+ cfg.rc_target_bitrate = 200;
92479270
+ cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
92489271
+
9272+
+ vpx_codec_ctx_t codec;
92499273
+ 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;
92529276
+ }
92539277
+
92549278
+ FILE* file = fopen(filePath.utf8().data(), "wb");
92559279
+ 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;
92589282
+ }
92599283
+
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));
92709287
+}
92719288
+
92729289
+void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface)
@@ -9313,36 +9330,23 @@ index 0000000000000000000000000000000000000000..50a43d2bae34e04d3bdf96616e085636
93139330
+ u_data, uv_stride,
93149331
+ v_data, uv_stride,
93159332
+ 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());
93189334
+}
93199335
+
93209336
+void ScreencastEncoder::finish()
93219337
+{
9322-
+ if (!m_codecInfo)
9338+
+ if (!m_vpxCodec)
93239339
+ return;
93249340
+
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;
93399343
+}
93409344
+
93419345
+
93429346
+} // namespace WebKit
93439347
diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
93449348
new file mode 100644
9345-
index 0000000000000000000000000000000000000000..944d7166b9e6c74579eb43883c04042d2a7f86e3
9349+
index 0000000000000000000000000000000000000000..6ab23625bca03927ef060cc5be6919fe70b836bd
93469350
--- /dev/null
93479351
+++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h
93489352
@@ -0,0 +1,53 @@
@@ -9385,17 +9389,17 @@ index 0000000000000000000000000000000000000000..944d7166b9e6c74579eb43883c04042d
93859389
+ WTF_MAKE_NONCOPYABLE(ScreencastEncoder);
93869390
+ WTF_MAKE_FAST_ALLOCATED;
93879391
+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>&&);
93899396
+ ~ScreencastEncoder();
93909397
+
9391-
+ void init(const String& filePath, int width, int height);
93929398
+ void encodeFrame(cairo_surface_t*);
93939399
+ void finish();
93949400
+
93959401
+private:
9396-
+ struct CodecInfo;
9397-
+ std::unique_ptr<CodecInfo> m_codecInfo;
9398-
+ int m_frameCount { 0 };
9402+
+ std::unique_ptr<VPXCodec> m_vpxCodec;
93999403
+};
94009404
+
94019405
+} // namespace WebKit

0 commit comments

Comments
 (0)