Skip to content

Commit

Permalink
Add feature for hardware vp8 decode on Windows. Query resolutions.
Browse files Browse the repository at this point in the history
Adds kMediaFoundationVP8Decoding as disabled by default. Updates our
supported profiles code to use it.

Bug: 1062849
Change-Id: I36b6c6b202411a7bd842a28727a7b67dd3f31882
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2110516
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Frank Liberato <liberato@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751875}
  • Loading branch information
dalecurtis authored and Commit Bot committed Mar 20, 2020
1 parent 658133b commit 6d03dcb
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 54 deletions.
4 changes: 4 additions & 0 deletions media/base/media_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,10 @@ const base::Feature kMediaFoundationH264Encoding{
const base::Feature kMediaFoundationVideoCapture{
"MediaFoundationVideoCapture", base::FEATURE_ENABLED_BY_DEFAULT};

// Enables VP8 decode acceleration for Windows.
const base::Feature MEDIA_EXPORT kMediaFoundationVP8Decoding{
"MediaFoundationVP8Decoding", base::FEATURE_DISABLED_BY_DEFAULT};

// Enables DirectShow GetPhotoState implementation
// Created to act as a kill switch by disabling it, in the case of the
// resurgence of https://crbug.com/722038
Expand Down
1 change: 1 addition & 0 deletions media/base/media_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ MEDIA_EXPORT extern const base::Feature kUsePooledSharedImageVideoProvider;
MEDIA_EXPORT extern const base::Feature kDelayCopyNV12Textures;
MEDIA_EXPORT extern const base::Feature kMediaFoundationH264Encoding;
MEDIA_EXPORT extern const base::Feature kMediaFoundationVideoCapture;
MEDIA_EXPORT extern const base::Feature kMediaFoundationVP8Decoding;
MEDIA_EXPORT extern const base::Feature kDirectShowGetPhotoState;
#endif // defined(OS_WIN)

Expand Down
7 changes: 5 additions & 2 deletions media/gpu/windows/d3d11_video_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -912,14 +912,15 @@ D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
std::vector<SupportedVideoDecoderConfig> configs;
// VP9 has no default resolutions since it may not even be supported.
ResolutionPair max_h264_resolutions(gfx::Size(1920, 1088), gfx::Size());
ResolutionPair max_vp8_resolutions;
ResolutionPair max_vp9_profile0_resolutions;
ResolutionPair max_vp9_profile2_resolutions;
const gfx::Size min_resolution(64, 64);

GetResolutionsForDecoders(
{D3D11_DECODER_PROFILE_H264_VLD_NOFGT}, d3d11_device, gpu_workarounds,
&max_h264_resolutions, &max_vp9_profile0_resolutions,
&max_vp9_profile2_resolutions);
&max_h264_resolutions, &max_vp8_resolutions,
&max_vp9_profile0_resolutions, &max_vp9_profile2_resolutions);

if (max_h264_resolutions.first.width() > 0) {
// Push H264 configs, except HIGH10.
Expand Down Expand Up @@ -960,6 +961,8 @@ D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
false)); // require_encrypted
}

// TODO(liberato): Fill this in for VP8.

if (max_vp9_profile0_resolutions.first.width()) {
// landscape
configs.push_back(SupportedVideoDecoderConfig(
Expand Down
21 changes: 13 additions & 8 deletions media/gpu/windows/dxva_video_decode_accelerator_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1260,21 +1260,24 @@ DXVAVideoDecodeAccelerator::GetSupportedProfiles(
// 1920 x 1088. We use 1088 to account for 16x16 macroblocks.
ResolutionPair max_h264_resolutions(gfx::Size(1920, 1088), gfx::Size());

// VP9 has no default resolutions since it may not even be supported.
// VP8/VP9 has no default resolutions since it may not even be supported.
ResolutionPair max_vp8_resolutions;
ResolutionPair max_vp9_profile0_resolutions;
ResolutionPair max_vp9_profile2_resolutions;

GetResolutionsForDecoders(
{DXVA2_ModeH264_E, DXVA2_Intel_ModeH264_E},
gl::QueryD3D11DeviceObjectFromANGLE(), workarounds, &max_h264_resolutions,
&max_vp9_profile0_resolutions, &max_vp9_profile2_resolutions);
GetResolutionsForDecoders({DXVA2_ModeH264_E, DXVA2_Intel_ModeH264_E},
gl::QueryD3D11DeviceObjectFromANGLE(), workarounds,
&max_h264_resolutions, &max_vp8_resolutions,
&max_vp9_profile0_resolutions,
&max_vp9_profile2_resolutions);

for (const auto& supported_profile : kSupportedProfiles) {
const bool is_h264 = supported_profile >= H264PROFILE_MIN &&
supported_profile <= H264PROFILE_MAX;
const bool is_vp9 = supported_profile >= VP9PROFILE_MIN &&
supported_profile <= VP9PROFILE_MAX;
DCHECK(is_h264 || is_vp9);
const bool is_vp8 = supported_profile == VP8PROFILE_ANY;
DCHECK(is_h264 || is_vp9 || is_vp8);

ResolutionPair max_resolutions;
if (is_h264) {
Expand All @@ -1283,10 +1286,12 @@ DXVAVideoDecodeAccelerator::GetSupportedProfiles(
max_resolutions = max_vp9_profile0_resolutions;
} else if (supported_profile == VP9PROFILE_PROFILE2) {
max_resolutions = max_vp9_profile2_resolutions;
} else if (is_vp8) {
max_resolutions = max_vp8_resolutions;
}

// Skip adding VP9 profiles if it's not supported or disabled.
if (is_vp9 && max_resolutions.first.IsEmpty())
// Skip adding VPx profiles if it's not supported or disabled.
if ((is_vp9 || is_vp8) && max_resolutions.first.IsEmpty())
continue;

// Windows Media Foundation H.264 decoding does not support decoding videos
Expand Down
91 changes: 52 additions & 39 deletions media/gpu/windows/supported_profile_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
#include <memory>
#include <utility>

#include "base/feature_list.h"
#include "base/trace_event/trace_event.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/base/media_switches.h"

#if !defined(OS_WIN)
#error This file should only be built on Windows.
Expand Down Expand Up @@ -189,8 +191,8 @@ ResolutionPair GetMaxResolutionsForGUIDs(
}));

for (const auto& res : resolutions_to_test) {
if (!media::IsResolutionSupportedForDevice(res, decoder_guid, video_device,
format)) {
if (!IsResolutionSupportedForDevice(res, decoder_guid, video_device,
format)) {
break;
}
result.first = res;
Expand All @@ -199,8 +201,8 @@ ResolutionPair GetMaxResolutionsForGUIDs(
// The max supported portrait resolution should be just be a w/h flip of the
// max supported landscape resolution.
gfx::Size flipped(result.first.height(), result.first.width());
if (media::IsResolutionSupportedForDevice(flipped, decoder_guid, video_device,
format)) {
if (IsResolutionSupportedForDevice(flipped, decoder_guid, video_device,
format)) {
result.second = flipped;
}

Expand All @@ -213,45 +215,56 @@ void GetResolutionsForDecoders(std::vector<GUID> h264_guids,
ComD3D11Device device,
const gpu::GpuDriverBugWorkarounds& workarounds,
ResolutionPair* h264_resolutions,
ResolutionPair* vp8_resolutions,
ResolutionPair* vp9_0_resolutions,
ResolutionPair* vp9_2_resolutions) {
TRACE_EVENT0("gpu,startup", "GetResolutionsForDecoders");
if (base::win::GetVersion() > base::win::Version::WIN7) {
// To detect if a driver supports the desired resolutions, we try and create
// a DXVA decoder instance for that resolution and profile. If that succeeds
// we assume that the driver supports decoding for that resolution.
// Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while
// creating surfaces larger than 1920 x 1088.
if (device && !IsLegacyGPU(device.Get())) {
ComD3D11VideoDevice video_device;
if (SUCCEEDED(device.As(&video_device))) {
*h264_resolutions = GetMaxResolutionsForGUIDs(
h264_resolutions->first, video_device.Get(), h264_guids,
{gfx::Size(2560, 1440), gfx::Size(3840, 2160),
gfx::Size(4096, 2160), gfx::Size(4096, 2304)});

if (!workarounds.disable_accelerated_vpx_decode) {
*vp9_0_resolutions = GetMaxResolutionsForGUIDs(
vp9_0_resolutions->first, video_device.Get(),
{D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0},
{gfx::Size(4096, 2160), gfx::Size(4096, 2304),
gfx::Size(7680, 4320), gfx::Size(8192, 4320),
gfx::Size(8192, 8192)});

// RS3 has issues with VP9.2 decoding. See https://crbug.com/937108.
if (base::win::GetVersion() != base::win::Version::WIN10_RS3) {
*vp9_2_resolutions = GetMaxResolutionsForGUIDs(
vp9_2_resolutions->first, video_device.Get(),
{D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2},
{gfx::Size(4096, 2160), gfx::Size(4096, 2304),
gfx::Size(7680, 4320), gfx::Size(8192, 4320),
gfx::Size(8192, 8192)},
DXGI_FORMAT_P010);
}
}
}
}
if (base::win::GetVersion() <= base::win::Version::WIN7)
return;

// To detect if a driver supports the desired resolutions, we try and create
// a DXVA decoder instance for that resolution and profile. If that succeeds
// we assume that the driver supports decoding for that resolution.
// Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while
// creating surfaces larger than 1920 x 1088.
if (!device || IsLegacyGPU(device.Get()))
return;

ComD3D11VideoDevice video_device;
if (FAILED(device.As(&video_device)))
return;

*h264_resolutions = GetMaxResolutionsForGUIDs(
h264_resolutions->first, video_device.Get(), h264_guids,
{gfx::Size(2560, 1440), gfx::Size(3840, 2160), gfx::Size(4096, 2160),
gfx::Size(4096, 2304)});

if (workarounds.disable_accelerated_vpx_decode)
return;

if (base::FeatureList::IsEnabled(kMediaFoundationVP8Decoding)) {
*vp8_resolutions = GetMaxResolutionsForGUIDs(
vp8_resolutions->first, video_device.Get(),
{D3D11_DECODER_PROFILE_VP8_VLD},
{gfx::Size(4096, 2160), gfx::Size(4096, 2304)});
}

*vp9_0_resolutions = GetMaxResolutionsForGUIDs(
vp9_0_resolutions->first, video_device.Get(),
{D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0},
{gfx::Size(4096, 2160), gfx::Size(4096, 2304), gfx::Size(7680, 4320),
gfx::Size(8192, 4320), gfx::Size(8192, 8192)});

// RS3 has issues with VP9.2 decoding. See https://crbug.com/937108.
if (base::win::GetVersion() == base::win::Version::WIN10_RS3)
return;

*vp9_2_resolutions = GetMaxResolutionsForGUIDs(
vp9_2_resolutions->first, video_device.Get(),
{D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2},
{gfx::Size(4096, 2160), gfx::Size(4096, 2304), gfx::Size(7680, 4320),
gfx::Size(8192, 4320), gfx::Size(8192, 8192)},
DXGI_FORMAT_P010);
}

} // namespace media
2 changes: 2 additions & 0 deletions media/gpu/windows/supported_profile_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ ResolutionPair GetMaxResolutionsForGUIDs(
const std::vector<gfx::Size>& resolutions_to_test,
DXGI_FORMAT format = DXGI_FORMAT_NV12);

// TODO(dalecurtis): This function should be changed to use return values.
MEDIA_GPU_EXPORT
void GetResolutionsForDecoders(std::vector<GUID> h264_guids,
ComD3D11Device device,
const gpu::GpuDriverBugWorkarounds& workarounds,
ResolutionPair* h264_resolutions,
ResolutionPair* vp8_resolutions,
ResolutionPair* vp9_0_resolutions,
ResolutionPair* vp9_2_resolutions);

Expand Down
50 changes: 45 additions & 5 deletions media/gpu/windows/supported_profile_helpers_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include <map>
#include <utility>

#include "base/test/scoped_feature_list.h"
#include "base/win/windows_version.h"
#include "media/base/media_switches.h"
#include "media/base/test_helpers.h"
#include "media/base/win/d3d11_mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
Expand Down Expand Up @@ -137,13 +139,15 @@ TEST_F(SupportedResolutionResolverTest, NoDeviceAllDefault) {

ResolutionPair h264_res_expected = {{1, 2}, {3, 4}};
ResolutionPair h264_res = {{1, 2}, {3, 4}};
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT}, nullptr,
gpu_workarounds_, &h264_res, &vp9_0_res,
gpu_workarounds_, &h264_res, &vp8_res, &vp9_0_res,
&vp9_2_res);

ASSERT_EQ(h264_res, h264_res_expected);
ASSERT_EQ(vp8_res, zero);
ASSERT_EQ(vp9_0_res, zero);
ASSERT_EQ(vp9_0_res, zero);
}
Expand All @@ -155,13 +159,15 @@ TEST_F(SupportedResolutionResolverTest, LegacyGPUAllDefault) {

ResolutionPair h264_res_expected = {{1, 2}, {3, 4}};
ResolutionPair h264_res = {{1, 2}, {3, 4}};
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT},
mock_d3d11_device_, gpu_workarounds_, &h264_res,
&vp9_0_res, &vp9_2_res);
&vp8_res, &vp9_0_res, &vp9_2_res);

ASSERT_EQ(h264_res, h264_res_expected);
ASSERT_EQ(vp8_res, zero);
ASSERT_EQ(vp9_2_res, zero);
ASSERT_EQ(vp9_0_res, zero);
}
Expand All @@ -173,14 +179,42 @@ TEST_F(SupportedResolutionResolverTest, WorkaroundsDisableVpx) {
EnableDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT});

ResolutionPair h264_res;
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT},
mock_d3d11_device_, gpu_workarounds_, &h264_res,
&vp9_0_res, &vp9_2_res);
&vp8_res, &vp9_0_res, &vp9_2_res);

ASSERT_EQ(h264_res, tall4k);

ASSERT_EQ(vp8_res, zero);
ASSERT_EQ(vp9_0_res, zero);
ASSERT_EQ(vp9_2_res, zero);
}

TEST_F(SupportedResolutionResolverTest, VP8_Supports4k) {
DONT_RUN_ON_WIN_7();

base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(kMediaFoundationVP8Decoding);

EnableDecoders(
{D3D11_DECODER_PROFILE_H264_VLD_NOFGT, D3D11_DECODER_PROFILE_VP8_VLD});
SetMaxResolutionForGUID(D3D11_DECODER_PROFILE_VP8_VLD, {4096, 4096});

ResolutionPair h264_res;
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT},
mock_d3d11_device_, gpu_workarounds_, &h264_res,
&vp8_res, &vp9_0_res, &vp9_2_res);

ASSERT_EQ(h264_res, tall4k);

ASSERT_EQ(vp8_res, tall4k);

ASSERT_EQ(vp9_0_res, zero);

ASSERT_EQ(vp9_2_res, zero);
Expand All @@ -194,14 +228,17 @@ TEST_F(SupportedResolutionResolverTest, VP9_0Supports8k) {
SetMaxResolutionForGUID(D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, {8192, 8192});

ResolutionPair h264_res;
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT},
mock_d3d11_device_, gpu_workarounds_, &h264_res,
&vp9_0_res, &vp9_2_res);
&vp8_res, &vp9_0_res, &vp9_2_res);

ASSERT_EQ(h264_res, tall4k);

ASSERT_EQ(vp8_res, zero);

ASSERT_EQ(vp9_0_res, eightKsquare);

ASSERT_EQ(vp9_2_res, zero);
Expand All @@ -218,14 +255,17 @@ TEST_F(SupportedResolutionResolverTest, BothVP9ProfilesSupported) {
{8192, 8192});

ResolutionPair h264_res;
ResolutionPair vp8_res;
ResolutionPair vp9_0_res;
ResolutionPair vp9_2_res;
GetResolutionsForDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT},
mock_d3d11_device_, gpu_workarounds_, &h264_res,
&vp9_0_res, &vp9_2_res);
&vp8_res, &vp9_0_res, &vp9_2_res);

ASSERT_EQ(h264_res, tall4k);

ASSERT_EQ(vp8_res, zero);

ASSERT_EQ(vp9_0_res, eightKsquare);

ASSERT_EQ(vp9_2_res, eightKsquare);
Expand Down

0 comments on commit 6d03dcb

Please sign in to comment.