Commit 6c0a7baf authored by Frank Liberato's avatar Frank Liberato Committed by Commit Bot

Send stream / display HDR metatadata to the video processor.

If we have an HDR video, send along any stream mastering metadata or
display metadata to the VideoProcessor.  This allows proper tone
mapping on some devices, such as the Radeon 5700.

Change-Id: I7b625fec44693c1abf85656c09342b1faae44ca4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107492
Commit-Queue: Frank Liberato <liberato@chromium.org>
Reviewed-by: default avatarTed Meyer <tmathmeyer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756887}
parent 3de82d7c
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h"
#include "media/gpu/windows/d3d11_com_defs.h" #include "media/gpu/windows/d3d11_com_defs.h"
#include "media/gpu/windows/display_helper.h"
namespace media { namespace media {
...@@ -88,4 +89,15 @@ bool CopyingTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb) { ...@@ -88,4 +89,15 @@ bool CopyingTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb) {
return output_texture_wrapper_->Init(std::move(get_helper_cb)); return output_texture_wrapper_->Init(std::move(get_helper_cb));
} }
void CopyingTexture2DWrapper::SetStreamHDRMetadata(
const HDRMetadata& stream_metadata) {
auto dxgi_stream_metadata = DisplayHelper::HdrMetadataToDXGI(stream_metadata);
video_processor_->SetStreamHDRMetadata(dxgi_stream_metadata);
}
void CopyingTexture2DWrapper::SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata) {
video_processor_->SetDisplayHDRMetadata(dxgi_display_metadata);
}
} // namespace media } // namespace media
...@@ -39,6 +39,10 @@ class MEDIA_GPU_EXPORT CopyingTexture2DWrapper : public Texture2DWrapper { ...@@ -39,6 +39,10 @@ class MEDIA_GPU_EXPORT CopyingTexture2DWrapper : public Texture2DWrapper {
bool Init(GetCommandBufferHelperCB get_helper_cb) override; bool Init(GetCommandBufferHelperCB get_helper_cb) override;
void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) override;
void SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata) override;
private: private:
gfx::Size size_; gfx::Size size_;
std::unique_ptr<VideoProcessorProxy> video_processor_; std::unique_ptr<VideoProcessorProxy> video_processor_;
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <string.h>
#include <utility> #include <utility>
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "media/gpu/windows/d3d11_copying_texture_wrapper.h" #include "media/gpu/windows/d3d11_copying_texture_wrapper.h"
#include "media/gpu/windows/d3d11_texture_wrapper.h" #include "media/gpu/windows/d3d11_texture_wrapper.h"
#include "media/gpu/windows/d3d11_video_processor_proxy.h" #include "media/gpu/windows/d3d11_video_processor_proxy.h"
#include "media/gpu/windows/display_helper.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -49,6 +52,16 @@ class MockVideoProcessorProxy : public VideoProcessorProxy { ...@@ -49,6 +52,16 @@ class MockVideoProcessorProxy : public VideoProcessorProxy {
last_output_color_space_ = color_space; last_output_color_space_ = color_space;
} }
void SetStreamHDRMetadata(
const DXGI_HDR_METADATA_HDR10& stream_metadata) override {
last_stream_metadata_ = stream_metadata;
}
void SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& display_metadata) override {
last_display_metadata_ = display_metadata;
}
HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view, HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view,
UINT output_frameno, UINT output_frameno,
UINT stream_count, UINT stream_count,
...@@ -61,9 +74,11 @@ class MockVideoProcessorProxy : public VideoProcessorProxy { ...@@ -61,9 +74,11 @@ class MockVideoProcessorProxy : public VideoProcessorProxy {
MOCK_METHOD0(MockCreateVideoProcessorInputView, HRESULT()); MOCK_METHOD0(MockCreateVideoProcessorInputView, HRESULT());
MOCK_METHOD0(MockVideoProcessorBlt, HRESULT()); MOCK_METHOD0(MockVideoProcessorBlt, HRESULT());
// Most recent arguments to SetStream/OutputColorSpace(). // Most recent arguments to SetStream/OutputColorSpace()/etc.
base::Optional<gfx::ColorSpace> last_stream_color_space_; base::Optional<gfx::ColorSpace> last_stream_color_space_;
base::Optional<gfx::ColorSpace> last_output_color_space_; base::Optional<gfx::ColorSpace> last_output_color_space_;
base::Optional<DXGI_HDR_METADATA_HDR10> last_stream_metadata_;
base::Optional<DXGI_HDR_METADATA_HDR10> last_display_metadata_;
}; };
class MockTexture2DWrapper : public Texture2DWrapper { class MockTexture2DWrapper : public Texture2DWrapper {
...@@ -87,6 +102,9 @@ class MockTexture2DWrapper : public Texture2DWrapper { ...@@ -87,6 +102,9 @@ class MockTexture2DWrapper : public Texture2DWrapper {
MOCK_METHOD0(MockInit, bool()); MOCK_METHOD0(MockInit, bool());
MOCK_METHOD0(MockProcessTexture, bool()); MOCK_METHOD0(MockProcessTexture, bool());
MOCK_METHOD1(SetStreamHDRMetadata, void(const HDRMetadata& stream_metadata));
MOCK_METHOD1(SetDisplayHDRMetadata,
void(const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata));
}; };
CommandBufferHelperPtr UselessHelper() { CommandBufferHelperPtr UselessHelper() {
...@@ -205,4 +223,44 @@ TEST_P(D3D11CopyingTexture2DWrapperTest, ...@@ -205,4 +223,44 @@ TEST_P(D3D11CopyingTexture2DWrapperTest,
// TODO: verify that these aren't sent multiple times, unless they change. // TODO: verify that these aren't sent multiple times, unless they change.
} }
TEST_P(D3D11CopyingTexture2DWrapperTest, HDRMetadataIsSentToVideoProcessor) {
HDRMetadata metadata;
metadata.mastering_metadata.primary_r =
MasteringMetadata::Chromaticity(0.1, 0.2);
metadata.mastering_metadata.primary_g =
MasteringMetadata::Chromaticity(0.3, 0.4);
metadata.mastering_metadata.primary_b =
MasteringMetadata::Chromaticity(0.5, 0.6);
metadata.mastering_metadata.white_point =
MasteringMetadata::Chromaticity(0.7, 0.8);
metadata.mastering_metadata.luminance_max = 0.9;
metadata.mastering_metadata.luminance_min = 0.05;
metadata.max_content_light_level = 1000;
metadata.max_frame_average_light_level = 10000;
auto processor = ExpectProcessorProxy();
MockVideoProcessorProxy* processor_raw = processor.get();
auto wrapper = std::make_unique<CopyingTexture2DWrapper>(
gfx::Size(100, 200), ExpectTextureWrapper(), std::move(processor),
nullptr, gfx::ColorSpace::CreateSCRGBLinear());
const DXGI_HDR_METADATA_HDR10 dxgi_metadata =
DisplayHelper::HdrMetadataToDXGI(metadata);
wrapper->SetStreamHDRMetadata(metadata);
EXPECT_TRUE(processor_raw->last_stream_metadata_);
EXPECT_FALSE(processor_raw->last_display_metadata_);
EXPECT_EQ(memcmp(&dxgi_metadata, &(*processor_raw->last_stream_metadata_),
sizeof(dxgi_metadata)),
0);
processor_raw->last_stream_metadata_.reset();
wrapper->SetDisplayHDRMetadata(dxgi_metadata);
EXPECT_FALSE(processor_raw->last_stream_metadata_);
EXPECT_TRUE(processor_raw->last_display_metadata_);
EXPECT_EQ(memcmp(&dxgi_metadata, &(*processor_raw->last_display_metadata_),
sizeof(dxgi_metadata)),
0);
}
} // namespace media } // namespace media
...@@ -84,6 +84,8 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer ...@@ -84,6 +84,8 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
return output_view_; return output_view_;
} }
Texture2DWrapper* texture_wrapper() const { return texture_wrapper_.get(); }
// Shouldn't be here, but simpler for now. // Shouldn't be here, but simpler for now.
base::TimeDelta timestamp_; base::TimeDelta timestamp_;
......
...@@ -127,6 +127,12 @@ bool DefaultTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb) { ...@@ -127,6 +127,12 @@ bool DefaultTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb) {
textures_per_picture); textures_per_picture);
} }
void DefaultTexture2DWrapper::SetStreamHDRMetadata(
const HDRMetadata& stream_metadata) {}
void DefaultTexture2DWrapper::SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata) {}
DefaultTexture2DWrapper::GpuResources::GpuResources() {} DefaultTexture2DWrapper::GpuResources::GpuResources() {}
DefaultTexture2DWrapper::GpuResources::~GpuResources() { DefaultTexture2DWrapper::GpuResources::~GpuResources() {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "media/base/hdr_metadata.h"
#include "media/base/status.h" #include "media/base/status.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/gpu/command_buffer_helper.h" #include "media/gpu/command_buffer_helper.h"
...@@ -50,6 +51,10 @@ class MEDIA_GPU_EXPORT Texture2DWrapper { ...@@ -50,6 +51,10 @@ class MEDIA_GPU_EXPORT Texture2DWrapper {
const gfx::ColorSpace& input_color_space, const gfx::ColorSpace& input_color_space,
MailboxHolderArray* mailbox_dest_out, MailboxHolderArray* mailbox_dest_out,
gfx::ColorSpace* output_color_space) = 0; gfx::ColorSpace* output_color_space) = 0;
virtual void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) = 0;
virtual void SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata) = 0;
}; };
// The default texture wrapper that uses GPUResources to talk to hardware // The default texture wrapper that uses GPUResources to talk to hardware
...@@ -71,6 +76,10 @@ class MEDIA_GPU_EXPORT DefaultTexture2DWrapper : public Texture2DWrapper { ...@@ -71,6 +76,10 @@ class MEDIA_GPU_EXPORT DefaultTexture2DWrapper : public Texture2DWrapper {
MailboxHolderArray* mailbox_dest, MailboxHolderArray* mailbox_dest,
gfx::ColorSpace* output_color_space) override; gfx::ColorSpace* output_color_space) override;
void SetStreamHDRMetadata(const HDRMetadata& stream_metadata) override;
void SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& dxgi_display_metadata) override;
private: private:
// Things that are to be accessed / freed only on the main thread. In // Things that are to be accessed / freed only on the main thread. In
// addition to setting up the textures to render from a D3D11 texture, // addition to setting up the textures to render from a D3D11 texture,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "media/gpu/windows/d3d11_video_context_wrapper.h" #include "media/gpu/windows/d3d11_video_context_wrapper.h"
#include "media/gpu/windows/d3d11_video_decoder_impl.h" #include "media/gpu/windows/d3d11_video_decoder_impl.h"
#include "media/gpu/windows/d3d11_video_device_format_support.h" #include "media/gpu/windows/d3d11_video_device_format_support.h"
#include "media/gpu/windows/display_helper.h"
#include "media/gpu/windows/supported_profile_helpers.h" #include "media/gpu/windows/supported_profile_helpers.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "ui/gl/direct_composition_surface_win.h" #include "ui/gl/direct_composition_surface_win.h"
...@@ -682,6 +683,19 @@ void D3D11VideoDecoder::CreatePictureBuffers() { ...@@ -682,6 +683,19 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
return; return;
} }
HDRMetadata stream_metadata;
if (config_.hdr_metadata())
stream_metadata = *config_.hdr_metadata();
// else leave |stream_metadata| default-initialized. We might use it anyway.
base::Optional<DXGI_HDR_METADATA_HDR10> display_metadata;
if (decoder_configurator_->TextureFormat() == DXGI_FORMAT_P010) {
// For HDR formats, try to get the display metadata. This may fail, which
// is okay. We'll just skip sending the metadata.
DisplayHelper display_helper(device_);
display_metadata = display_helper.GetDisplayMetadata();
}
// Drop any old pictures. // Drop any old pictures.
for (auto& buffer : picture_buffers_) for (auto& buffer : picture_buffers_)
DCHECK(!buffer->in_picture_use()); DCHECK(!buffer->in_picture_use());
...@@ -704,6 +718,20 @@ void D3D11VideoDecoder::CreatePictureBuffers() { ...@@ -704,6 +718,20 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
NotifyError("Unable to allocate PictureBuffer"); NotifyError("Unable to allocate PictureBuffer");
return; return;
} }
// If we have display metadata, then tell the processor. Note that the
// order of these calls is important, and we must set the display metadata
// if we set the stream metadata, else it can crash on some AMD cards.
if (display_metadata) {
if (config_.hdr_metadata() ||
gpu_workarounds_.use_empty_video_hdr_metadata) {
// It's okay if this has an empty-initialized metadata.
picture_buffers_[i]->texture_wrapper()->SetStreamHDRMetadata(
stream_metadata);
}
picture_buffers_[i]->texture_wrapper()->SetDisplayHDRMetadata(
*display_metadata);
}
} }
} }
......
...@@ -98,6 +98,29 @@ void VideoProcessorProxy::SetOutputColorSpace( ...@@ -98,6 +98,29 @@ void VideoProcessorProxy::SetOutputColorSpace(
} }
} }
void VideoProcessorProxy::SetStreamHDRMetadata(
const DXGI_HDR_METADATA_HDR10& stream_metadata) {
ComD3D11VideoContext2 video_context2;
if (FAILED(video_context_.As(&video_context2)))
return;
// TODO: we shouldn't do this unless we also set the display metadata.
video_context2->VideoProcessorSetOutputHDRMetaData(
video_processor_.Get(), DXGI_HDR_METADATA_TYPE_HDR10,
sizeof(stream_metadata), &stream_metadata);
}
void VideoProcessorProxy::SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& display_metadata) {
ComD3D11VideoContext2 video_context2;
if (FAILED(video_context_.As(&video_context2)))
return;
video_context2->VideoProcessorSetOutputHDRMetaData(
video_processor_.Get(), DXGI_HDR_METADATA_TYPE_HDR10,
sizeof(display_metadata), &display_metadata);
}
HRESULT VideoProcessorProxy::VideoProcessorBlt( HRESULT VideoProcessorProxy::VideoProcessorBlt(
ID3D11VideoProcessorOutputView* output_view, ID3D11VideoProcessorOutputView* output_view,
UINT output_frameno, UINT output_frameno,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <wrl/client.h> #include <wrl/client.h>
#include <cstdint> #include <cstdint>
#include "media/base/hdr_metadata.h"
#include "media/gpu/media_gpu_export.h" #include "media/gpu/media_gpu_export.h"
#include "media/gpu/windows/d3d11_com_defs.h" #include "media/gpu/windows/d3d11_com_defs.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
...@@ -43,6 +44,13 @@ class MEDIA_GPU_EXPORT VideoProcessorProxy { ...@@ -43,6 +44,13 @@ class MEDIA_GPU_EXPORT VideoProcessorProxy {
// Configure the output color space on the video context. // Configure the output color space on the video context.
virtual void SetOutputColorSpace(const gfx::ColorSpace& color_space); virtual void SetOutputColorSpace(const gfx::ColorSpace& color_space);
// Set the stream / display metadata. Optional, and may silently do nothing
// if it's not supported.
virtual void SetStreamHDRMetadata(
const DXGI_HDR_METADATA_HDR10& stream_metadata);
virtual void SetDisplayHDRMetadata(
const DXGI_HDR_METADATA_HDR10& display_metadata);
virtual HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view, virtual HRESULT VideoProcessorBlt(ID3D11VideoProcessorOutputView* output_view,
UINT output_frameno, UINT output_frameno,
UINT stream_count, UINT stream_count,
......
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