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

Refactor GetResolutionsForDecoders() to support AV1.

Does the following:
- Internalizes h264 and min resolution details.
- Sets the minimum resolution to 64,64 for both decoders.
- Only loops through the video device profiles once.
- Switches away from an std::pair to a named struct.
- Adds AV1 GUID values and uses them in DXVA decoder.
- Stops D3D11VideoDecoder for enumerating unsupported profiles.
- Stops using the DXVA2_Intel_ModeH264_E for enumeration.
- Gives all resolution tests a square resolution; e.g., 4k x 4k.
- Doesn't test or indicate support for a duplicate portrait resolution.

R=liberato, tmathmeyer

Bug: 1073252
Test: Updated unittests.
Change-Id: I8013e89104c96fad845fdbaecdb1d4b239f9a380
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2223261
Commit-Queue: Frank Liberato <liberato@chromium.org>
Reviewed-by: default avatarTed Meyer <tmathmeyer@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774317}
parent 13fdd6f9
......@@ -166,6 +166,7 @@ component("gpu") {
if (is_win) {
sources += [
"windows/av1_guids.h",
"windows/d3d11_com_defs.h",
"windows/d3d11_copying_texture_wrapper.cc",
"windows/d3d11_copying_texture_wrapper.h",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_WINDOWS_AV1_GUIDS_H_
#define MEDIA_GPU_WINDOWS_AV1_GUIDS_H_
#include <initguid.h>
#if WDK_NTDDI_VERSION <= NTDDI_WIN10_19H1
DEFINE_GUID(DXVA_ModeAV1_VLD_Profile0,
0xb8be4ccb,
0xcf53,
0x46ba,
0x8d,
0x59,
0xd6,
0xb8,
0xa6,
0xda,
0x5d,
0x2a);
DEFINE_GUID(DXVA_ModeAV1_VLD_Profile1,
0x6936ff0f,
0x45b1,
0x4163,
0x9c,
0xc1,
0x64,
0x6e,
0xf6,
0x94,
0x61,
0x08);
DEFINE_GUID(DXVA_ModeAV1_VLD_Profile2,
0x0c5f2aa1,
0xe541,
0x4089,
0xbb,
0x7b,
0x98,
0x11,
0x0a,
0x19,
0xd7,
0xc8);
#endif // WDK_NTDDI_VERSION <= NTDDI_WIN10_19H1
#endif // MEDIA_GPU_WINDOWS_AV1_GUIDS_H_
......@@ -908,97 +908,35 @@ D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
return {};
}
const auto supported_resolutions =
GetSupportedD3D11VideoDecoderResolutions(d3d11_device, gpu_workarounds);
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_vp8_resolutions,
&max_vp9_profile0_resolutions, &max_vp9_profile2_resolutions);
if (max_h264_resolutions.first.width() > 0) {
// Push H264 configs, except HIGH10.
// landscape
configs.push_back(SupportedVideoDecoderConfig(
H264PROFILE_MIN, // profile_min
static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE -
1), // profile_max
min_resolution, // coded_size_min
max_h264_resolutions.first, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
configs.push_back(SupportedVideoDecoderConfig(
static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE +
1), // profile_min
H264PROFILE_MAX, // profile_max
min_resolution, // coded_size_min
max_h264_resolutions.first, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
// portrait
configs.push_back(SupportedVideoDecoderConfig(
H264PROFILE_MIN, // profile_min
static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE -
1), // profile_max
min_resolution, // coded_size_min
max_h264_resolutions.second, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
configs.push_back(SupportedVideoDecoderConfig(
static_cast<VideoCodecProfile>(H264PROFILE_HIGH10PROFILE +
1), // profile_min
H264PROFILE_MAX, // profile_max
min_resolution, // coded_size_min
max_h264_resolutions.second, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
}
// TODO(liberato): Fill this in for VP8.
if (max_vp9_profile0_resolutions.first.width()) {
// landscape
configs.push_back(SupportedVideoDecoderConfig(
VP9PROFILE_PROFILE0, // profile_min
VP9PROFILE_PROFILE0, // profile_max
min_resolution, // coded_size_min
max_vp9_profile0_resolutions.first, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
// portrait
configs.push_back(SupportedVideoDecoderConfig(
VP9PROFILE_PROFILE0, // profile_min
VP9PROFILE_PROFILE0, // profile_max
min_resolution, // coded_size_min
max_vp9_profile0_resolutions.second, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
}
if (base::FeatureList::IsEnabled(kD3D11VideoDecoderVP9Profile2)) {
if (max_vp9_profile2_resolutions.first.width()) {
// landscape
configs.push_back(SupportedVideoDecoderConfig(
VP9PROFILE_PROFILE2, // profile_min
VP9PROFILE_PROFILE2, // profile_max
min_resolution, // coded_size_min
max_vp9_profile2_resolutions.first, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
// portrait
configs.push_back(SupportedVideoDecoderConfig(
VP9PROFILE_PROFILE2, // profile_min
VP9PROFILE_PROFILE2, // profile_max
min_resolution, // coded_size_min
max_vp9_profile2_resolutions.second, // coded_size_max
false, // allow_encrypted
false)); // require_encrypted
for (const auto& kv : supported_resolutions) {
const auto profile = kv.first;
if (profile == VP9PROFILE_PROFILE2 &&
!base::FeatureList::IsEnabled(kD3D11VideoDecoderVP9Profile2)) {
continue;
}
// TODO(liberato): Add VP8 and AV1 support to D3D11VideoDecoder.
if (profile == VP8PROFILE_ANY ||
(profile >= AV1PROFILE_MIN && profile <= AV1PROFILE_MAX)) {
continue;
}
const auto& resolution_range = kv.second;
configs.emplace_back(profile, profile, resolution_range.min_resolution,
resolution_range.max_landscape_resolution,
/*allow_encrypted=*/false,
/*require_encrypted=*/false);
if (!resolution_range.max_portrait_resolution.IsEmpty() &&
resolution_range.max_portrait_resolution !=
resolution_range.max_landscape_resolution) {
configs.emplace_back(profile, profile, resolution_range.min_resolution,
resolution_range.max_portrait_resolution,
/*allow_encrypted=*/false,
/*require_encrypted=*/false);
}
}
......
......@@ -7,10 +7,6 @@
#include <algorithm>
#include <memory>
#if !defined(OS_WIN)
#error This file should only be built on Windows.
#endif // !defined(OS_WIN)
#include <codecapi.h>
#include <dxgi1_2.h>
#include <ks.h>
......@@ -121,13 +117,6 @@ DEFINE_GUID(MF_XVP_PLAYBACK_MODE,
0xcc,
0xe9);
// Defines the GUID for the Intel H264 DXVA device.
static const GUID DXVA2_Intel_ModeH264_E = {
0x604F8E68,
0x4951,
0x4c54,
{0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6}};
static const CLSID CLSID_CAV1DecoderMFT = {
0xC843981A,
0x3359,
......@@ -184,7 +173,7 @@ HRESULT g_last_device_removed_reason;
namespace media {
static const VideoCodecProfile kSupportedProfiles[] = {
constexpr VideoCodecProfile kSupportedProfiles[] = {
H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH,
VP8PROFILE_ANY, VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE2,
AV1PROFILE_PROFILE_MAIN, AV1PROFILE_PROFILE_HIGH, AV1PROFILE_PROFILE_PRO};
......@@ -1347,84 +1336,28 @@ DXVAVideoDecodeAccelerator::GetSupportedProfiles(
}
}
// On Windows 7 the maximum resolution supported by media foundation is
// 1920 x 1088. We use 1088 to account for 16x16 macroblocks.
ResolutionPair max_h264_resolutions(gfx::Size(1920, 1088), gfx::Size());
// 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_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;
const bool is_vp8 = supported_profile == VP8PROFILE_ANY;
const bool is_av1 = supported_profile >= AV1PROFILE_MIN &&
supported_profile <= AV1PROFILE_MAX;
DCHECK(is_h264 || is_vp9 || is_vp8 || is_av1);
ResolutionPair max_resolutions;
if (is_h264) {
max_resolutions = max_h264_resolutions;
} else if (supported_profile == VP9PROFILE_PROFILE0) {
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;
} else if (is_av1) {
if (!base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding))
continue;
// TODO(dalecurtis): Update GetResolutionsForDecoders() to support AV1.
SupportedProfile profile;
profile.profile = supported_profile;
profile.min_resolution = gfx::Size();
profile.max_resolution = gfx::Size(8192, 8192);
profiles.push_back(profile);
continue;
}
// 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
// with any dimension smaller than 48 pixels:
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815
//
// TODO(dalecurtis): These values are too low. We should only be using
// hardware decode for videos above ~360p, see http://crbug.com/684792.
const gfx::Size min_resolution =
is_h264 ? gfx::Size(48, 48) : gfx::Size(16, 16);
const auto supported_resolutions = GetSupportedD3D11VideoDecoderResolutions(
gl::QueryD3D11DeviceObjectFromANGLE(), workarounds);
for (const auto& kv : supported_resolutions) {
const auto& resolution_range = kv.second;
{
SupportedProfile profile;
profile.profile = supported_profile;
profile.min_resolution = min_resolution;
profile.max_resolution = max_resolutions.first;
profile.profile = kv.first;
profile.min_resolution = resolution_range.min_resolution;
profile.max_resolution = resolution_range.max_landscape_resolution;
profiles.push_back(profile);
}
const gfx::Size portrait_max_resolution = max_resolutions.second;
if (!portrait_max_resolution.IsEmpty()) {
if (!resolution_range.max_portrait_resolution.IsEmpty() &&
resolution_range.max_portrait_resolution !=
resolution_range.max_landscape_resolution) {
SupportedProfile profile;
profile.profile = supported_profile;
profile.min_resolution = min_resolution;
profile.max_resolution = portrait_max_resolution;
profile.profile = kv.first;
profile.min_resolution = resolution_range.min_resolution;
profile.max_resolution = resolution_range.max_portrait_resolution;
profiles.push_back(profile);
}
}
return profiles;
}
......
......@@ -7,18 +7,12 @@
#include <d3d11_1.h>
#include <d3d9.h>
#include <dxva2api.h>
#include <initguid.h>
#include <mfidl.h>
#include <stdint.h>
#include <wrl/client.h>
// Work around bug in this header by disabling the relevant warning for it.
// https://connect.microsoft.com/VisualStudio/feedback/details/911260/dxva2api-h-in-win8-sdk-triggers-c4201-with-w4
#pragma warning(push)
#pragma warning(disable : 4201)
#include <dxva2api.h>
#pragma warning(pop)
#include <mfidl.h>
#include <list>
#include <map>
#include <memory>
......
......@@ -5,47 +5,35 @@
#ifndef MEDIA_GPU_WINDOWS_SUPPORTED_PROFILE_HELPERS_H_
#define MEDIA_GPU_WINDOWS_SUPPORTED_PROFILE_HELPERS_H_
#include <d3d11_1.h>
#include <wrl/client.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/base/video_codecs.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/windows/d3d11_com_defs.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace media {
using ResolutionPair = std::pair<gfx::Size, gfx::Size>;
bool IsLegacyGPU(ID3D11Device* device);
// Returns true if a ID3D11VideoDecoder can be created for |resolution_to_test|
// on the given |video_device|.
bool IsResolutionSupportedForDevice(const gfx::Size& resolution_to_test,
const GUID& decoder_guid,
ID3D11VideoDevice* video_device,
DXGI_FORMAT format);
ResolutionPair GetMaxResolutionsForGUIDs(
const gfx::Size& default_max,
ID3D11VideoDevice* video_device,
const std::vector<GUID>& valid_guids,
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.
struct SupportedResolutionRange {
gfx::Size min_resolution;
gfx::Size max_landscape_resolution;
gfx::Size max_portrait_resolution;
};
using SupportedResolutionRangeMap =
base::flat_map<VideoCodecProfile, SupportedResolutionRange>;
// Enumerates the extent of hardware decoding support for H.264, VP8, VP9, and
// AV1. If a codec is supported, its minimum and maximum supported resolutions
// are returned under the appropriate VideoCodecProfile entry.
//
// Notes:
// - VP8 and AV1 are only tested if their base::Feature entries are enabled.
// - Only baseline, main, and high H.264 profiles are supported.
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);
SupportedResolutionRangeMap GetSupportedD3D11VideoDecoderResolutions(
ComD3D11Device device,
const gpu::GpuDriverBugWorkarounds& workarounds);
} // namespace media
......
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