diff --git a/patches/chromium/.patches b/patches/chromium/.patches index cf07a626659e8..f9114298d6a7a 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -130,3 +130,4 @@ websocket_don_t_clear_event_queue_on_destruction.patch cherry-pick-7e0e52df283c.patch cherry-pick-6ed1c0c425e0.patch cherry-pick-aeb6bc551b60.patch +mediarecorder_tolerate_non-gmb_nv12_frames_for_h264.patch diff --git a/patches/chromium/mediarecorder_tolerate_non-gmb_nv12_frames_for_h264.patch b/patches/chromium/mediarecorder_tolerate_non-gmb_nv12_frames_for_h264.patch new file mode 100644 index 0000000000000..b5c3e09078dae --- /dev/null +++ b/patches/chromium/mediarecorder_tolerate_non-gmb_nv12_frames_for_h264.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Markus Handell +Date: Tue, 23 Feb 2021 18:45:55 +0000 +Subject: MediaRecorder: tolerate non-GMB NV12 frames for H264. + +The VPX video track recorders were updated to tolerate non-GMB NV12 +input in crrev/c/2425748, but the H264 encoder was left neglected, +which hurts Mac users that have disabled hardware acceleration. This +change adds that support to it. + +[TBR landing because mcasas@chromium.org is OOO] + +TBR=mcasas@chromium.org +(cherry picked from commit de865890bf6a12c74ae9943ede6132d25c7a33dd) + +Bug: 1177593 +Change-Id: I608c76b1de8261dcc44463fe896e3b63d5fd329e +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2694407 +Reviewed-by: ccameron +Reviewed-by: Evan Shrubsole +Reviewed-by: Miguel Casas +Commit-Queue: Markus Handell +Cr-Original-Commit-Position: refs/heads/master@{#854709} +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2715222 +Cr-Commit-Position: refs/branch-heads/4389@{#1320} +Cr-Branched-From: 9251c5db2b6d5a59fe4eac7aafa5fed37c139bb7-refs/heads/master@{#843830} + +diff --git a/media/base/video_util.cc b/media/base/video_util.cc +index 3daa1cb27d5705d56d0075e82a9ecd0bfb86c366..d5a0f1b578e22822089d704fcd7b98cbb26bb405 100644 +--- a/media/base/video_util.cc ++++ b/media/base/video_util.cc +@@ -13,6 +13,7 @@ + #include "base/numerics/safe_math.h" + #include "media/base/video_frame.h" + #include "third_party/libyuv/include/libyuv.h" ++#include "ui/gfx/gpu_memory_buffer.h" + + namespace media { + +@@ -424,6 +425,38 @@ void CopyRGBToVideoFrame(const uint8_t* source, + region_in_frame.width(), region_in_frame.height()); + } + ++scoped_refptr ConvertToMemoryMappedFrame( ++ scoped_refptr video_frame) { ++ DCHECK(video_frame); ++ DCHECK(video_frame->HasGpuMemoryBuffer()); ++ auto* gmb = video_frame->GetGpuMemoryBuffer(); ++ if (!gmb->Map()) ++ return nullptr; ++ const size_t num_planes = VideoFrame::NumPlanes(video_frame->format()); ++ uint8_t* plane_addrs[VideoFrame::kMaxPlanes] = {}; ++ for (size_t i = 0; i < num_planes; i++) ++ plane_addrs[i] = static_cast(gmb->memory(i)); ++ auto mapped_frame = VideoFrame::WrapExternalYuvDataWithLayout( ++ video_frame->layout(), video_frame->visible_rect(), ++ video_frame->natural_size(), plane_addrs[0], plane_addrs[1], ++ plane_addrs[2], video_frame->timestamp()); ++ if (!mapped_frame) { ++ gmb->Unmap(); ++ return nullptr; ++ } ++ mapped_frame->set_color_space(video_frame->ColorSpace()); ++ mapped_frame->metadata()->MergeMetadataFrom(video_frame->metadata()); ++ // Pass |video_frame| so that it outlives |mapped_frame| and the mapped buffer ++ // is unmapped on destruction. ++ mapped_frame->AddDestructionObserver(base::BindOnce( ++ [](scoped_refptr frame) { ++ DCHECK(frame->HasGpuMemoryBuffer()); ++ frame->GetGpuMemoryBuffer()->Unmap(); ++ }, ++ std::move(video_frame))); ++ return mapped_frame; ++} ++ + scoped_refptr WrapAsI420VideoFrame( + scoped_refptr frame) { + DCHECK_EQ(VideoFrame::STORAGE_OWNED_MEMORY, frame->storage_type()); +diff --git a/media/base/video_util.h b/media/base/video_util.h +index 42e060a25b711fca8bba3cef8ade9bbaa2092c55..2681163c55618ae8738d91987bb46a4e8bcc541b 100644 +--- a/media/base/video_util.h ++++ b/media/base/video_util.h +@@ -134,6 +134,12 @@ MEDIA_EXPORT gfx::Size GetRectSizeFromOrigin(const gfx::Rect& rect); + MEDIA_EXPORT gfx::Size PadToMatchAspectRatio(const gfx::Size& size, + const gfx::Size& target); + ++// A helper function to map GpuMemoryBuffer-based VideoFrame. This function ++// maps the given GpuMemoryBuffer of |frame| as-is without converting pixel ++// format. The returned VideoFrame owns the |frame|. ++MEDIA_EXPORT scoped_refptr ConvertToMemoryMappedFrame( ++ scoped_refptr frame); ++ + // Copy an RGB bitmap into the specified |region_in_frame| of a YUV video frame. + // Fills the regions outside |region_in_frame| with black. + MEDIA_EXPORT void CopyRGBToVideoFrame(const uint8_t* source, +diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc +index 401e696e886f68fc4a9bb9ac0614959f0a8673a8..c323faab804ad421b1c8f8d7789222304c4d44e6 100644 +--- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc ++++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc +@@ -54,9 +54,13 @@ void H264Encoder::EncodeOnEncodingTaskRunner( + base::TimeTicks capture_timestamp) { + TRACE_EVENT0("media", "H264Encoder::EncodeOnEncodingTaskRunner"); + DCHECK(encoding_task_runner_->BelongsToCurrentThread()); ++ DCHECK(frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_NV12 || ++ frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420 || ++ frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420A); + +- if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) ++ if (frame->format() == media::PIXEL_FORMAT_NV12) + frame = ConvertToI420ForSoftwareEncoder(frame); ++ DCHECK(frame->IsMappable()); + + const gfx::Size frame_size = frame->visible_rect().size(); + if (!openh264_encoder_ || configured_size_ != frame_size) { +diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc +index 8f69cc61257cbe2c4c349912cfb4647ceaf771f7..1ace9b3f6ed14a96af7b8e8779a3929675be9a0a 100644 +--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc ++++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc +@@ -415,20 +415,17 @@ bool VideoTrackRecorderImpl::Encoder::CanEncodeAlphaChannel() { + scoped_refptr + VideoTrackRecorderImpl::Encoder::ConvertToI420ForSoftwareEncoder( + scoped_refptr frame) { +- DCHECK_EQ(frame->storage_type(), +- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER); +- // NV12 is currently the only supported pixel format for GpuMemoryBuffer. + DCHECK_EQ(frame->format(), media::VideoPixelFormat::PIXEL_FORMAT_NV12); + +- auto* gmb = frame->GetGpuMemoryBuffer(); +- if (!gmb->Map()) +- return frame; ++ if (frame->GetGpuMemoryBuffer()) ++ frame = media::ConvertToMemoryMappedFrame(frame); ++ + scoped_refptr i420_frame = media::VideoFrame::CreateFrame( + media::VideoPixelFormat::PIXEL_FORMAT_I420, frame->coded_size(), + frame->visible_rect(), frame->natural_size(), frame->timestamp()); + auto ret = libyuv::NV12ToI420( +- static_cast(gmb->memory(0)), gmb->stride(0), +- static_cast(gmb->memory(1)), gmb->stride(1), ++ static_cast(frame->data(0)), frame->stride(0), ++ static_cast(frame->data(1)), frame->stride(1), + i420_frame->data(media::VideoFrame::kYPlane), + i420_frame->stride(media::VideoFrame::kYPlane), + i420_frame->data(media::VideoFrame::kUPlane), +@@ -436,7 +433,6 @@ VideoTrackRecorderImpl::Encoder::ConvertToI420ForSoftwareEncoder( + i420_frame->data(media::VideoFrame::kVPlane), + i420_frame->stride(media::VideoFrame::kVPlane), + frame->coded_size().width(), frame->coded_size().height()); +- gmb->Unmap(); + if (ret) + return frame; + return i420_frame;