Commit dacf14c4 authored by Miguel Casas-Sanchez's avatar Miguel Casas-Sanchez Committed by Commit Bot

Mac: teach GpuMemoryBufferVideoFramePool to handle XR30

This CL teaches GpuMemoryBufferVideoFramePool to handle XR30
formats, when context capabilities' image_xr30 is enabled
and the incoming data is of 10 bit per component type.

This CL also enables the necessary checks in the gles2 and
GpuMemoryBuffer support to recongnise this format in Mac only
(other platforms coming soon).

Test with high bit depth videos e.g.:
'http://crosvideo.appspot.com?codec=vp9.2&loop=true'
and media/test/data/...
- bear-320x180-hi10p-vp9.webm
- bear-320x180-hi10p.mp4 (this is an H.264 part 10, 10bpc)
- blackwhite_yuv420p_hi10p.mp4
- bear-320x180-hi12p-vp9.webm

Also covered in e.g. content_browsertests'
 MediaColorTest.Yuv420pHighBitDepth
which would fail if the colors were inverted.

Bug: 797347
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I8e73a7558d5506875d1547983d4e5e796a543aeb
Reviewed-on: https://chromium-review.googlesource.com/862326Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531293}
parent 531fac6a
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/context_provider.h"
#include "content/child/child_thread_impl.h" #include "content/child/child_thread_impl.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
...@@ -296,14 +297,25 @@ GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(size_t bit_depth) { ...@@ -296,14 +297,25 @@ GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(size_t bit_depth) {
viz::ContextProvider::ScopedContextLock lock(context_provider_); viz::ContextProvider::ScopedContextLock lock(context_provider_);
auto capabilities = context_provider_->ContextCapabilities(); auto capabilities = context_provider_->ContextCapabilities();
if (bit_depth > 8) { if (bit_depth > 8) {
// If high bit depth rendering is not enabled and we support RG textures, // If high bit depth rendering is enabled, bail here, otherwise try and use
// use those, albeit at a reduced bit depth of 8 bits per component. // XR30 storage, and if not and we support RG textures, use those, albeit at
// a reduced bit depth of 8 bits per component.
// TODO(mcasas): continue working on this, avoiding dropping information as // TODO(mcasas): continue working on this, avoiding dropping information as
// long as the hardware may support it https://crbug.com/798485. // long as the hardware may support it https://crbug.com/798485.
if (!rendering_color_space_.IsHDR() && capabilities.texture_rg) if (rendering_color_space_.IsHDR())
return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
else
return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED; return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
#if defined(OS_MACOSX)
// TODO(mcasas): enable other platforms https://crbug.com/776093
// https://crbug.com/803451, https://crbug.com/803975.
// TODO(mcasas): remove the |bit_depth| check when libyuv supports more than
// just x010ToAR30 conversions, https://crbug.com/libyuv/751.
if (capabilities.image_xr30 && bit_depth == 10)
return media::GpuVideoAcceleratorFactories::OutputFormat::XR30;
#endif
if (capabilities.texture_rg)
return media::GpuVideoAcceleratorFactories::OutputFormat::I420;
return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
} }
if (capabilities.image_ycbcr_420v && if (capabilities.image_ycbcr_420v &&
!capabilities.image_ycbcr_420v_disabled_for_video_frames) { !capabilities.image_ycbcr_420v_disabled_for_video_frames) {
......
...@@ -6304,6 +6304,8 @@ bool CreateImageValidInternalFormat(GLenum internalformat, ...@@ -6304,6 +6304,8 @@ bool CreateImageValidInternalFormat(GLenum internalformat,
return capabilities.texture_format_etc1; return capabilities.texture_format_etc1;
case GL_R16_EXT: case GL_R16_EXT:
return capabilities.texture_norm16; return capabilities.texture_norm16;
case GL_RGB10_A2_EXT:
return capabilities.image_xr30;
case GL_RED: case GL_RED:
case GL_RG_EXT: case GL_RG_EXT:
case GL_RGB: case GL_RGB:
......
...@@ -56,6 +56,7 @@ bool IsNativeGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format, ...@@ -56,6 +56,7 @@ bool IsNativeGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
return format == gfx::BufferFormat::R_8 || return format == gfx::BufferFormat::R_8 ||
format == gfx::BufferFormat::BGRA_8888 || format == gfx::BufferFormat::BGRA_8888 ||
format == gfx::BufferFormat::RGBA_F16 || format == gfx::BufferFormat::RGBA_F16 ||
format == gfx::BufferFormat::BGRX_1010102 ||
format == gfx::BufferFormat::UYVY_422 || format == gfx::BufferFormat::UYVY_422 ||
format == gfx::BufferFormat::YUV_420_BIPLANAR; format == gfx::BufferFormat::YUV_420_BIPLANAR;
case gfx::BufferUsage::SCANOUT_VDA_WRITE: case gfx::BufferUsage::SCANOUT_VDA_WRITE:
......
...@@ -208,6 +208,9 @@ gfx::BufferFormat GpuMemoryBufferFormat( ...@@ -208,6 +208,9 @@ gfx::BufferFormat GpuMemoryBufferFormat(
case GpuVideoAcceleratorFactories::OutputFormat::UYVY: case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
DCHECK_EQ(0u, plane); DCHECK_EQ(0u, plane);
return gfx::BufferFormat::UYVY_422; return gfx::BufferFormat::UYVY_422;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
DCHECK_EQ(0u, plane);
return gfx::BufferFormat::BGRX_1010102;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
break; break;
...@@ -230,6 +233,11 @@ unsigned ImageInternalFormat(GpuVideoAcceleratorFactories::OutputFormat format, ...@@ -230,6 +233,11 @@ unsigned ImageInternalFormat(GpuVideoAcceleratorFactories::OutputFormat format,
case GpuVideoAcceleratorFactories::OutputFormat::UYVY: case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
DCHECK_EQ(0u, plane); DCHECK_EQ(0u, plane);
return GL_RGB_YCBCR_422_CHROMIUM; return GL_RGB_YCBCR_422_CHROMIUM;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
DCHECK_EQ(0u, plane);
// Technically speaking we should say GL_RGB10_EXT, but that format is not
// supported in OpenGLES.
return GL_RGB10_A2_EXT;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
break; break;
...@@ -246,6 +254,8 @@ size_t PlanesPerCopy(GpuVideoAcceleratorFactories::OutputFormat format) { ...@@ -246,6 +254,8 @@ size_t PlanesPerCopy(GpuVideoAcceleratorFactories::OutputFormat format) {
case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB:
case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB:
return 2; return 2;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
return 3;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
break; break;
...@@ -263,6 +273,8 @@ VideoPixelFormat VideoFormat( ...@@ -263,6 +273,8 @@ VideoPixelFormat VideoFormat(
return PIXEL_FORMAT_NV12; return PIXEL_FORMAT_NV12;
case GpuVideoAcceleratorFactories::OutputFormat::UYVY: case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
return PIXEL_FORMAT_UYVY; return PIXEL_FORMAT_UYVY;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
return PIXEL_FORMAT_ARGB;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
break; break;
...@@ -281,6 +293,8 @@ size_t NumGpuMemoryBuffers(GpuVideoAcceleratorFactories::OutputFormat format) { ...@@ -281,6 +293,8 @@ size_t NumGpuMemoryBuffers(GpuVideoAcceleratorFactories::OutputFormat format) {
return 2; return 2;
case GpuVideoAcceleratorFactories::OutputFormat::UYVY: case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
return 1; return 1;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
return 1;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
break; break;
...@@ -395,6 +409,66 @@ void CopyRowsToUYVYBuffer(int first_row, ...@@ -395,6 +409,66 @@ void CopyRowsToUYVYBuffer(int first_row,
done.Run(); done.Run();
} }
void CopyRowsToXR30Buffer(int first_row,
int rows,
int width,
const scoped_refptr<VideoFrame>& source_frame,
uint8_t* output,
int dest_stride,
const base::Closure& done) {
TRACE_EVENT2("media", "CopyRowsToXR30Buffer", "bytes_per_row", width * 2,
"rows", rows);
if (output) {
DCHECK_NE(dest_stride, 0);
DCHECK_LE(width, std::abs(dest_stride / 2));
DCHECK_EQ(0, first_row % 2);
int color_space;
if (source_frame->metadata()->GetInteger(VideoFrameMetadata::COLOR_SPACE,
&color_space)) {
color_space = COLOR_SPACE_UNSPECIFIED;
}
const uint16_t* y_plane = reinterpret_cast<const uint16_t*>(
source_frame->visible_data(VideoFrame::kYPlane) +
first_row * source_frame->stride(VideoFrame::kYPlane));
const size_t y_plane_stride = source_frame->stride(VideoFrame::kYPlane) / 2;
const uint16_t* v_plane = reinterpret_cast<const uint16_t*>(
source_frame->visible_data(VideoFrame::kVPlane) +
first_row / 2 * source_frame->stride(VideoFrame::kVPlane));
const size_t v_plane_stride = source_frame->stride(VideoFrame::kVPlane) / 2;
const uint16_t* u_plane = reinterpret_cast<const uint16_t*>(
source_frame->visible_data(VideoFrame::kUPlane) +
first_row / 2 * source_frame->stride(VideoFrame::kUPlane));
const size_t u_plane_stride = source_frame->stride(VideoFrame::kUPlane) / 2;
uint8_t* dest_ar30 = output + first_row * dest_stride;
// RGB textures need RGB as MatrixID.
switch (color_space) {
case COLOR_SPACE_HD_REC709:
libyuv::H010ToAR30(y_plane, y_plane_stride, v_plane, v_plane_stride,
u_plane, u_plane_stride, dest_ar30, dest_stride,
width, rows);
source_frame->set_color_space(gfx::ColorSpace(
gfx::ColorSpace::PrimaryID::BT709,
gfx::ColorSpace::TransferID::BT709, gfx::ColorSpace::MatrixID::RGB,
gfx::ColorSpace::RangeID::LIMITED));
break;
case COLOR_SPACE_UNSPECIFIED:
case COLOR_SPACE_JPEG:
case COLOR_SPACE_SD_REC601:
libyuv::I010ToAR30(y_plane, y_plane_stride, v_plane, v_plane_stride,
u_plane, u_plane_stride, dest_ar30, dest_stride,
width, rows);
source_frame->set_color_space(gfx::ColorSpace(
gfx::ColorSpace::PrimaryID::SMPTE170M,
gfx::ColorSpace::TransferID::SMPTE170M,
gfx::ColorSpace::MatrixID::RGB, gfx::ColorSpace::RangeID::LIMITED));
break;
}
}
done.Run();
}
gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame, gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame,
GpuVideoAcceleratorFactories::OutputFormat output_format) { GpuVideoAcceleratorFactories::OutputFormat output_format) {
DCHECK(gfx::Rect(video_frame->coded_size()) DCHECK(gfx::Rect(video_frame->coded_size())
...@@ -410,6 +484,7 @@ gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame, ...@@ -410,6 +484,7 @@ gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame,
(video_frame->visible_rect().height() + 1) & ~1); (video_frame->visible_rect().height() + 1) & ~1);
break; break;
case GpuVideoAcceleratorFactories::OutputFormat::UYVY: case GpuVideoAcceleratorFactories::OutputFormat::UYVY:
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1,
video_frame->visible_rect().height()); video_frame->visible_rect().height());
break; break;
...@@ -642,6 +717,15 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers( ...@@ -642,6 +717,15 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffers(
static_cast<uint8_t*>(buffer->memory(0)), static_cast<uint8_t*>(buffer->memory(0)),
buffer->stride(0), barrier)); buffer->stride(0), barrier));
break; break;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
worker_task_runner_->PostTask(
FROM_HERE, base::Bind(&CopyRowsToXR30Buffer, row, rows_to_copy,
coded_size.width(), video_frame,
static_cast<uint8_t*>(buffer->memory(0)),
buffer->stride(0), barrier));
break;
case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED:
NOTREACHED(); NOTREACHED();
} }
...@@ -734,6 +818,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: ...@@ -734,6 +818,9 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::
allow_overlay = true; allow_overlay = true;
#endif #endif
break; break;
case GpuVideoAcceleratorFactories::OutputFormat::XR30:
allow_overlay = true;
break;
default: default:
break; break;
} }
......
...@@ -289,6 +289,24 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareNV12Frame2) { ...@@ -289,6 +289,24 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareNV12Frame2) {
media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)); media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED));
} }
TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30Frame) {
scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10, 10);
scoped_refptr<VideoFrame> frame;
mock_gpu_factories_->SetVideoFrameOutputFormat(
media::GpuVideoAcceleratorFactories::OutputFormat::XR30);
gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame));
RunUntilIdle();
EXPECT_NE(software_frame.get(), frame.get());
EXPECT_EQ(PIXEL_FORMAT_ARGB, frame->format());
EXPECT_EQ(1u, frame->NumTextures());
EXPECT_EQ(1u, gles2_->gen_textures_count());
EXPECT_TRUE(frame->metadata()->IsTrue(
media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED));
}
// CreateGpuMemoryBuffer can return null (e.g: when the GPU process is down). // CreateGpuMemoryBuffer can return null (e.g: when the GPU process is down).
// This test checks that in that case we don't crash and still create the // This test checks that in that case we don't crash and still create the
// textures. // textures.
......
...@@ -69,6 +69,7 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories { ...@@ -69,6 +69,7 @@ class MEDIA_EXPORT GpuVideoAcceleratorFactories {
UYVY, // One 422 GMB UYVY, // One 422 GMB
NV12_SINGLE_GMB, // One NV12 GMB NV12_SINGLE_GMB, // One NV12 GMB
NV12_DUAL_GMB, // One R8, one RG88 GMB NV12_DUAL_GMB, // One R8, one RG88 GMB
XR30, // 10:10:10:2 BGRX in one GMB
}; };
// Return whether GPU encoding/decoding is enabled. // Return whether GPU encoding/decoding is enabled.
......
...@@ -27,7 +27,8 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer { ...@@ -27,7 +27,8 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
DCHECK(gfx::BufferFormat::R_8 == format_ || DCHECK(gfx::BufferFormat::R_8 == format_ ||
gfx::BufferFormat::RG_88 == format_ || gfx::BufferFormat::RG_88 == format_ ||
gfx::BufferFormat::YUV_420_BIPLANAR == format_ || gfx::BufferFormat::YUV_420_BIPLANAR == format_ ||
gfx::BufferFormat::UYVY_422 == format_); gfx::BufferFormat::UYVY_422 == format_ ||
gfx::BufferFormat::BGRX_1010102 == format_);
DCHECK(num_planes_ <= kMaxPlanes); DCHECK(num_planes_ <= kMaxPlanes);
for (int i = 0; i < static_cast<int>(num_planes_); ++i) { for (int i = 0; i < static_cast<int>(num_planes_); ++i) {
bytes_[i].resize(gfx::RowSizeForBufferFormat(size_.width(), format_, i) * bytes_[i].resize(gfx::RowSizeForBufferFormat(size_.width(), format_, i) *
......
...@@ -39,6 +39,7 @@ bool ValidInternalFormat(unsigned internalformat) { ...@@ -39,6 +39,7 @@ bool ValidInternalFormat(unsigned internalformat) {
case GL_RG: case GL_RG:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_RGB: case GL_RGB:
case GL_RGB10_A2_EXT:
case GL_RGB_YCBCR_420V_CHROMIUM: case GL_RGB_YCBCR_420V_CHROMIUM:
case GL_RGB_YCBCR_422_CHROMIUM: case GL_RGB_YCBCR_422_CHROMIUM:
case GL_RGBA: case GL_RGBA:
......
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