Commit 6d03dcbb authored by Dale Curtis's avatar Dale Curtis Committed by Commit Bot

Add feature for hardware vp8 decode on Windows. Query resolutions.

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: default avatarFrank Liberato <liberato@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751875}
parent 658133b6
......@@ -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
......
......@@ -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)
......
......@@ -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.
......@@ -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(
......
......@@ -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) {
......@@ -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
......
......@@ -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.
......@@ -189,7 +191,7 @@ ResolutionPair GetMaxResolutionsForGUIDs(
}));
for (const auto& res : resolutions_to_test) {
if (!media::IsResolutionSupportedForDevice(res, decoder_guid, video_device,
if (!IsResolutionSupportedForDevice(res, decoder_guid, video_device,
format)) {
break;
}
......@@ -199,7 +201,7 @@ 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,
if (IsResolutionSupportedForDevice(flipped, decoder_guid, video_device,
format)) {
result.second = flipped;
}
......@@ -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) {
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())) {
if (!device || IsLegacyGPU(device.Get()))
return;
ComD3D11VideoDevice video_device;
if (SUCCEEDED(device.As(&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)});
{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)});
}
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)});
{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) {
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)},
{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
......@@ -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);
......
......@@ -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"
......@@ -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);
}
......@@ -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);
}
......@@ -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);
......@@ -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);
......@@ -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);
......
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