Commit 210f7ed9 authored by Fredrik Hubinette's avatar Fredrik Hubinette Committed by Commit Bot

convert CopyRowsToRGB10Buffer to use gfx::ColorSpace

Also fixes the logic. Before it the code would default
to rec601, and because of a bug it would *always* use
the default.

Now it defaults to rec709, unless rec601 is specified.

Bug: 754986
Change-Id: I94773a3bf0dfeae18e6a2ee8bc36ca884ba590b5
Reviewed-on: https://chromium-review.googlesource.com/998842
Commit-Queue: Fredrik Hubinette <hubbe@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555606}
parent 6027daff
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "media/video/gpu_video_accelerator_factories.h" #include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/libyuv/include/libyuv.h" #include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/buffer_format_util.h" #include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/trace_util.h" #include "ui/gl/trace_util.h"
namespace media { namespace media {
...@@ -464,7 +465,6 @@ void CopyRowsToRGB10Buffer(bool is_argb, ...@@ -464,7 +465,6 @@ void CopyRowsToRGB10Buffer(bool is_argb,
base::ScopedClosureRunner done_runner(std::move(done)); base::ScopedClosureRunner done_runner(std::move(done));
TRACE_EVENT2("media", "CopyRowsToXR30Buffer", "bytes_per_row", width * 2, TRACE_EVENT2("media", "CopyRowsToXR30Buffer", "bytes_per_row", width * 2,
"rows", rows); "rows", rows);
if (!output) if (!output)
return; return;
...@@ -472,11 +472,6 @@ void CopyRowsToRGB10Buffer(bool is_argb, ...@@ -472,11 +472,6 @@ void CopyRowsToRGB10Buffer(bool is_argb,
DCHECK_LE(width, std::abs(dest_stride / 2)); DCHECK_LE(width, std::abs(dest_stride / 2));
DCHECK_EQ(0, first_row % 2); DCHECK_EQ(0, first_row % 2);
int color_space = COLOR_SPACE_UNSPECIFIED;
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*>( const uint16_t* y_plane = reinterpret_cast<const uint16_t*>(
source_frame->visible_data(VideoFrame::kYPlane) + source_frame->visible_data(VideoFrame::kYPlane) +
first_row * source_frame->stride(VideoFrame::kYPlane)); first_row * source_frame->stride(VideoFrame::kYPlane));
...@@ -489,33 +484,31 @@ void CopyRowsToRGB10Buffer(bool is_argb, ...@@ -489,33 +484,31 @@ void CopyRowsToRGB10Buffer(bool is_argb,
source_frame->visible_data(VideoFrame::kUPlane) + source_frame->visible_data(VideoFrame::kUPlane) +
first_row / 2 * source_frame->stride(VideoFrame::kUPlane)); first_row / 2 * source_frame->stride(VideoFrame::kUPlane));
const size_t u_plane_stride = source_frame->stride(VideoFrame::kUPlane) / 2; const size_t u_plane_stride = source_frame->stride(VideoFrame::kUPlane) / 2;
uint8_t* dest_ar30 = output + first_row * dest_stride; uint8_t* dest_rgb10 = output + first_row * dest_stride;
switch (color_space) { SkYUVColorSpace skyuv = kRec709_SkYUVColorSpace;
case COLOR_SPACE_HD_REC709: source_frame->ColorSpace().ToSkYUVColorSpace(&skyuv);
if (is_argb) {
libyuv::H010ToAR30(y_plane, y_plane_stride, u_plane, u_plane_stride, if (skyuv == kRec601_SkYUVColorSpace) {
v_plane, v_plane_stride, dest_ar30, dest_stride, if (is_argb) {
width, rows); libyuv::I010ToAR30(y_plane, y_plane_stride, u_plane, u_plane_stride,
} else { v_plane, v_plane_stride, dest_rgb10, dest_stride,
libyuv::H010ToAB30(y_plane, y_plane_stride, u_plane, u_plane_stride, width, rows);
v_plane, v_plane_stride, dest_ar30, dest_stride, } else {
width, rows); libyuv::I010ToAB30(y_plane, y_plane_stride, u_plane, u_plane_stride,
} v_plane, v_plane_stride, dest_rgb10, dest_stride,
break; width, rows);
case COLOR_SPACE_UNSPECIFIED: }
case COLOR_SPACE_JPEG: } else {
case COLOR_SPACE_SD_REC601: if (is_argb) {
if (is_argb) { libyuv::H010ToAR30(y_plane, y_plane_stride, u_plane, u_plane_stride,
libyuv::I010ToAR30(y_plane, y_plane_stride, u_plane, u_plane_stride, v_plane, v_plane_stride, dest_rgb10, dest_stride,
v_plane, v_plane_stride, dest_ar30, dest_stride, width, rows);
width, rows); } else {
} else { libyuv::H010ToAB30(y_plane, y_plane_stride, u_plane, u_plane_stride,
libyuv::I010ToAB30(y_plane, y_plane_stride, u_plane, u_plane_stride, v_plane, v_plane_stride, dest_rgb10, dest_stride,
v_plane, v_plane_stride, dest_ar30, dest_stride, width, rows);
width, rows); }
}
break;
} }
} }
...@@ -910,7 +903,13 @@ void GpuMemoryBufferVideoFramePool::PoolImpl:: ...@@ -910,7 +903,13 @@ void GpuMemoryBufferVideoFramePool::PoolImpl::
#endif #endif
break; break;
case GpuVideoAcceleratorFactories::OutputFormat::XR30: case GpuVideoAcceleratorFactories::OutputFormat::XR30:
case GpuVideoAcceleratorFactories::OutputFormat::XB30:
allow_overlay = true; allow_overlay = true;
// We've converted the YUV to RGB, fix the color space.
// TODO(hubbe): The libyuv YUV to RGB conversion may not have
// honored the color space conversion 100%. We should either fix
// libyuv or find a way for later passes to make up the difference.
frame->set_color_space(video_frame->ColorSpace().GetAsRGB());
break; break;
default: default:
break; break;
......
...@@ -128,6 +128,15 @@ class GpuMemoryBufferVideoFramePoolTest : public ::testing::Test { ...@@ -128,6 +128,15 @@ class GpuMemoryBufferVideoFramePoolTest : public ::testing::Test {
return video_frame; return video_frame;
} }
// Note, the X portion is set to 1 since it may use ARGB instead of
// XRGB on some platforms.
uint32_t as_xr30(uint32_t r, uint32_t g, uint32_t b) {
return (3 << 30) | (r << 20) | (g << 10) | b;
}
uint32_t as_xb30(uint32_t r, uint32_t g, uint32_t b) {
return (3 << 30) | (b << 20) | (g << 10) | r;
}
protected: protected:
base::SimpleTestTickClock test_clock_; base::SimpleTestTickClock test_clock_;
std::unique_ptr<MockGpuVideoAcceleratorFactories> mock_gpu_factories_; std::unique_ptr<MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
...@@ -331,6 +340,62 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30Frame) { ...@@ -331,6 +340,62 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30Frame) {
EXPECT_EQ(1u, gles2_->gen_textures_count()); EXPECT_EQ(1u, gles2_->gen_textures_count());
EXPECT_TRUE(frame->metadata()->IsTrue( EXPECT_TRUE(frame->metadata()->IsTrue(
media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)); media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED));
EXPECT_EQ(1u, mock_gpu_factories_->created_memory_buffers().size());
mock_gpu_factories_->created_memory_buffers()[0]->Map();
void* memory = mock_gpu_factories_->created_memory_buffers()[0]->memory(0);
EXPECT_EQ(as_xr30(0, 311, 0), *static_cast<uint32_t*>(memory));
}
TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30FrameBT709) {
scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10, 10);
software_frame->set_color_space(gfx::ColorSpace::CreateREC709());
scoped_refptr<VideoFrame> frame;
mock_gpu_factories_->SetVideoFrameOutputFormat(
media::GpuVideoAcceleratorFactories::OutputFormat::XR30);
gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
software_frame, base::BindOnce(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));
EXPECT_EQ(1u, mock_gpu_factories_->created_memory_buffers().size());
mock_gpu_factories_->created_memory_buffers()[0]->Map();
void* memory = mock_gpu_factories_->created_memory_buffers()[0]->memory(0);
EXPECT_EQ(as_xr30(0, 311, 0), *static_cast<uint32_t*>(memory));
}
TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXR30FrameBT601) {
scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10, 10);
software_frame->set_color_space(gfx::ColorSpace::CreateREC601());
scoped_refptr<VideoFrame> frame;
mock_gpu_factories_->SetVideoFrameOutputFormat(
media::GpuVideoAcceleratorFactories::OutputFormat::XR30);
gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
software_frame, base::BindOnce(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));
EXPECT_EQ(1u, mock_gpu_factories_->created_memory_buffers().size());
mock_gpu_factories_->created_memory_buffers()[0]->Map();
void* memory = mock_gpu_factories_->created_memory_buffers()[0]->memory(0);
EXPECT_EQ(as_xr30(0, 543, 0), *static_cast<uint32_t*>(memory));
} }
TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXB30Frame) { TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareXB30Frame) {
......
...@@ -99,7 +99,10 @@ MockGpuVideoAcceleratorFactories::CreateGpuMemoryBuffer( ...@@ -99,7 +99,10 @@ MockGpuVideoAcceleratorFactories::CreateGpuMemoryBuffer(
gfx::BufferUsage /* usage */) { gfx::BufferUsage /* usage */) {
if (fail_to_allocate_gpu_memory_buffer_) if (fail_to_allocate_gpu_memory_buffer_)
return nullptr; return nullptr;
return std::make_unique<GpuMemoryBufferImpl>(size, format); std::unique_ptr<gfx::GpuMemoryBuffer> ret(
new GpuMemoryBufferImpl(size, format));
created_memory_buffers_.push_back(ret.get());
return ret;
} }
std::unique_ptr<base::SharedMemory> std::unique_ptr<base::SharedMemory>
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -91,6 +92,10 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories { ...@@ -91,6 +92,10 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
gpu::gles2::GLES2Interface* GetGLES2Interface() { return gles2_; } gpu::gles2::GLES2Interface* GetGLES2Interface() { return gles2_; }
const std::vector<gfx::GpuMemoryBuffer*>& created_memory_buffers() {
return created_memory_buffers_;
}
private: private:
DISALLOW_COPY_AND_ASSIGN(MockGpuVideoAcceleratorFactories); DISALLOW_COPY_AND_ASSIGN(MockGpuVideoAcceleratorFactories);
...@@ -100,6 +105,8 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories { ...@@ -100,6 +105,8 @@ class MockGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
bool fail_to_allocate_gpu_memory_buffer_ = false; bool fail_to_allocate_gpu_memory_buffer_ = false;
gpu::gles2::GLES2Interface* gles2_; gpu::gles2::GLES2Interface* gles2_;
std::vector<gfx::GpuMemoryBuffer*> created_memory_buffers_;
}; };
} // namespace media } // namespace media
......
...@@ -423,6 +423,13 @@ ColorSpace ColorSpace::GetAsFullRangeRGB() const { ...@@ -423,6 +423,13 @@ ColorSpace ColorSpace::GetAsFullRangeRGB() const {
return result; return result;
} }
ColorSpace ColorSpace::GetAsRGB() const {
ColorSpace result(*this);
if (IsValid())
result.matrix_ = MatrixID::RGB;
return result;
}
ColorSpace ColorSpace::GetRasterColorSpace() const { ColorSpace ColorSpace::GetRasterColorSpace() const {
// Rasterization can only be done into parametric color spaces. // Rasterization can only be done into parametric color spaces.
if (icc_profile_id_) if (icc_profile_id_)
......
...@@ -179,6 +179,9 @@ class COLOR_SPACE_EXPORT ColorSpace { ...@@ -179,6 +179,9 @@ class COLOR_SPACE_EXPORT ColorSpace {
// parametric). // parametric).
ColorSpace GetParametricApproximation() const; ColorSpace GetParametricApproximation() const;
// Return this color space with any YUV to RGB conversion stripped off.
ColorSpace GetAsRGB() const;
// Return this color space with any range adjust or YUV to RGB conversion // Return this color space with any range adjust or YUV to RGB conversion
// stripped off. // stripped off.
ColorSpace GetAsFullRangeRGB() const; ColorSpace GetAsFullRangeRGB() const;
......
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