Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: cherry-pick 38781b86f0 from chromium #28050

Merged
merged 1 commit into from Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions patches/chromium/.patches
Expand Up @@ -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
@@ -0,0 +1,152 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Markus Handell <handellm@google.com>
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 <ccameron@chromium.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Reviewed-by: Miguel Casas <mcasas@chromium.org>
Commit-Queue: Markus Handell <handellm@google.com>
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<VideoFrame> ConvertToMemoryMappedFrame(
+ scoped_refptr<VideoFrame> 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<uint8_t*>(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<VideoFrame> frame) {
+ DCHECK(frame->HasGpuMemoryBuffer());
+ frame->GetGpuMemoryBuffer()->Unmap();
+ },
+ std::move(video_frame)));
+ return mapped_frame;
+}
+
scoped_refptr<VideoFrame> WrapAsI420VideoFrame(
scoped_refptr<VideoFrame> 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<VideoFrame> ConvertToMemoryMappedFrame(
+ scoped_refptr<VideoFrame> 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<media::VideoFrame>
VideoTrackRecorderImpl::Encoder::ConvertToI420ForSoftwareEncoder(
scoped_refptr<media::VideoFrame> 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<media::VideoFrame> 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<const uint8_t*>(gmb->memory(0)), gmb->stride(0),
- static_cast<const uint8_t*>(gmb->memory(1)), gmb->stride(1),
+ static_cast<const uint8_t*>(frame->data(0)), frame->stride(0),
+ static_cast<const uint8_t*>(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;