Commit 07ed5f6e authored by Dale Curtis's avatar Dale Curtis Committed by Chromium LUCI CQ

Implement support for uploading RGB VideoFrame resources.

Now that we allow RGB VideoFrames through WebCodecs, we need to add
support in VideoResourceUpdater since BreakoutBox allows them to
reach our normal compositing path.

R=sandersd

Bug: 1167206,1167412
Test: Updated unittests.
Change-Id: Ie7a72128ab4bf65c72a5a8a41014700b9db7d677
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2634049
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844918}
parent d4781d14
......@@ -233,6 +233,9 @@ static base::Optional<VideoFrameLayout> GetDefaultLayout(
break;
case PIXEL_FORMAT_ARGB:
case PIXEL_FORMAT_XRGB:
case PIXEL_FORMAT_ABGR:
case PIXEL_FORMAT_XBGR:
planes = std::vector<ColorPlaneLayout>{ColorPlaneLayout(
coded_size.width() * 4, 0, coded_size.GetArea() * 4)};
break;
......@@ -252,10 +255,8 @@ static base::Optional<VideoFrameLayout> GetDefaultLayout(
default:
// TODO(miu): This function should support any pixel format.
// http://crbug.com/555909 .
DLOG(ERROR)
<< "Only PIXEL_FORMAT_I420, PIXEL_FORMAT_Y16, PIXEL_FORMAT_NV12, "
"and PIXEL_FORMAT_ARGB formats are supported: "
<< VideoPixelFormatToString(format);
DLOG(ERROR) << "Unsupported pixel format"
<< VideoPixelFormatToString(format);
return base::nullopt;
}
......
......@@ -49,6 +49,7 @@
// shown here to indicate where ideal conversions are currently missing.
#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
SK_A32_SHIFT == 24
#define OUTPUT_ARGB 1
#define LIBYUV_I400_TO_ARGB libyuv::I400ToARGB
#define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
#define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
......@@ -86,8 +87,11 @@
// #define LIBYUV_U410_TO_ARGB libyuv::U410ToARGB
#define LIBYUV_NV12_TO_ARGB libyuv::NV12ToARGB
#define LIBYUV_ABGR_TO_ARGB libyuv::ABGRToARGB
#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
SK_A32_SHIFT == 24
#define OUTPUT_ARGB 0
#define LIBYUV_I400_TO_ARGB libyuv::I400ToARGB
#define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR
#define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR
......@@ -125,6 +129,8 @@
// #define LIBYUV_U410_TO_ARGB libyuv::U410ToABGR
#define LIBYUV_NV12_TO_ARGB libyuv::NV12ToABGR
#define LIBYUV_ABGR_TO_ARGB libyuv::ARGBToABGR
#else
#error Unexpected Skia ARGB_8888 layout!
#endif
......@@ -390,10 +396,20 @@ void ConvertVideoFrameToRGBPixelsTask(const VideoFrame* video_frame,
format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_XBGR) {
DCHECK_LE(width, static_cast<int>(row_bytes));
const uint8_t* data = plane_meta[VideoFrame::kARGBPlane].data;
for (size_t i = 0; i < rows; i++) {
memcpy(pixels, data, width * 4);
pixels += row_bytes;
data += plane_meta[VideoFrame::kARGBPlane].stride;
if ((OUTPUT_ARGB &&
(format == PIXEL_FORMAT_ARGB || format == PIXEL_FORMAT_XRGB)) ||
(!OUTPUT_ARGB &&
(format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_XBGR))) {
for (size_t i = 0; i < rows; i++) {
memcpy(pixels, data, width * 4);
pixels += row_bytes;
data += plane_meta[VideoFrame::kARGBPlane].stride;
}
} else {
LIBYUV_ABGR_TO_ARGB(plane_meta[VideoFrame::kARGBPlane].data,
plane_meta[VideoFrame::kARGBPlane].stride, pixels,
row_bytes, width, rows);
}
done->Run();
return;
......
......@@ -943,13 +943,25 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
size_t bits_per_channel = video_frame->BitDepth();
// Only YUV and Y16 software video frames are supported.
const bool is_rgb = input_frame_format == PIXEL_FORMAT_XBGR ||
input_frame_format == PIXEL_FORMAT_XRGB ||
input_frame_format == PIXEL_FORMAT_ABGR ||
input_frame_format == PIXEL_FORMAT_ARGB;
DCHECK(IsYuvPlanar(input_frame_format) ||
input_frame_format == PIXEL_FORMAT_Y16);
input_frame_format == PIXEL_FORMAT_Y16 || is_rgb);
viz::ResourceFormat output_resource_format;
gfx::ColorSpace output_color_space = video_frame->ColorSpace();
if (input_frame_format == PIXEL_FORMAT_Y16) {
if (input_frame_format == PIXEL_FORMAT_XBGR) {
output_resource_format = viz::RGBX_8888;
} else if (input_frame_format == PIXEL_FORMAT_XRGB) {
output_resource_format = viz::BGRX_8888;
} else if (input_frame_format == PIXEL_FORMAT_ABGR) {
output_resource_format = viz::RGBA_8888;
} else if (input_frame_format == PIXEL_FORMAT_ARGB) {
output_resource_format = viz::BGRA_8888;
} else if (input_frame_format == PIXEL_FORMAT_Y16) {
// Unable to display directly as yuv planes so convert it to RGBA for
// compositing.
output_resource_format = viz::RGBA_8888;
......@@ -963,9 +975,10 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
// returned by the resource provider is viz::RGBA_8888, then a GPU driver
// bug workaround requires that YUV frames must be converted to RGB
// before texture upload.
bool texture_needs_rgb_conversion =
!software_compositor() &&
output_resource_format == viz::ResourceFormat::RGBA_8888;
const bool texture_needs_rgb_conversion =
input_frame_format == PIXEL_FORMAT_Y16 ||
(!software_compositor() && IsYuvPlanar(input_frame_format) &&
output_resource_format == viz::ResourceFormat::RGBA_8888);
size_t output_plane_count = VideoFrame::NumPlanes(input_frame_format);
......@@ -1026,14 +1039,15 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
external_resources.bits_per_channel = bits_per_channel;
if (software_compositor() || texture_needs_rgb_conversion) {
if (software_compositor() || texture_needs_rgb_conversion || is_rgb) {
DCHECK_EQ(plane_resources.size(), 1u);
PlaneResource* plane_resource = plane_resources[0];
DCHECK_EQ(plane_resource->resource_format(), viz::RGBA_8888);
if (!plane_resource->Matches(video_frame->unique_id(), 0)) {
// We need to transfer data from |video_frame| to the plane resource.
if (software_compositor()) {
DCHECK_EQ(plane_resource->resource_format(), viz::RGBA_8888);
if (!video_renderer_)
video_renderer_ = std::make_unique<PaintCanvasVideoRenderer>();
......@@ -1062,7 +1076,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
} else {
HardwarePlaneResource* hardware_resource = plane_resource->AsHardware();
size_t bytes_per_row = viz::ResourceSizes::CheckedWidthInBytes<size_t>(
video_frame->coded_size().width(), viz::ResourceFormat::RGBA_8888);
video_frame->coded_size().width(), output_resource_format);
size_t needed_size = bytes_per_row * video_frame->coded_size().height();
if (upload_pixels_size_ < needed_size) {
// Free the existing data first so that the memory can be reused,
......@@ -1084,8 +1098,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
scope.texture_id());
gl->TexSubImage2D(
hardware_resource->texture_target(), 0, 0, 0, plane_size.width(),
plane_size.height(), GLDataFormat(viz::ResourceFormat::RGBA_8888),
GLDataType(viz::ResourceFormat::RGBA_8888), upload_pixels_.get());
plane_size.height(), GLDataFormat(output_resource_format),
GLDataType(output_resource_format), upload_pixels_.get());
}
}
plane_resource->SetUniqueId(video_frame->unique_id(), 0);
......@@ -1113,7 +1127,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
}
transferable_resource.color_space = output_color_space;
transferable_resource.format = viz::ResourceFormat::RGBA_8888;
transferable_resource.format = output_resource_format;
external_resources.resources.push_back(std::move(transferable_resource));
external_resources.release_callbacks.push_back(base::BindOnce(
&VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment