summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/windows
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/gpu/windows')
-rw-r--r--chromium/media/gpu/windows/av1_guids.h52
-rw-r--r--chromium/media/gpu/windows/d3d11_decoder_configurator.cc5
-rw-r--r--chromium/media/gpu/windows/d3d11_decoder_configurator.h4
-rw-r--r--chromium/media/gpu/windows/d3d11_h264_accelerator.cc16
-rw-r--r--chromium/media/gpu/windows/d3d11_h264_accelerator.h3
-rw-r--r--chromium/media/gpu/windows/d3d11_picture_buffer.cc13
-rw-r--r--chromium/media/gpu/windows/d3d11_picture_buffer.h15
-rw-r--r--chromium/media/gpu/windows/d3d11_texture_selector.cc2
-rw-r--r--chromium/media/gpu/windows/d3d11_texture_wrapper.cc19
-rw-r--r--chromium/media/gpu/windows/d3d11_video_decoder.cc418
-rw-r--r--chromium/media/gpu/windows/d3d11_video_decoder.h21
-rw-r--r--chromium/media/gpu/windows/d3d11_video_decoder_client.h10
-rw-r--r--chromium/media/gpu/windows/d3d11_video_decoder_unittest.cc2
-rw-r--r--chromium/media/gpu/windows/d3d11_vp9_accelerator.cc25
-rw-r--r--chromium/media/gpu/windows/d3d11_vp9_accelerator.h3
-rw-r--r--chromium/media/gpu/windows/d3d11_vp9_picture.cc3
-rw-r--r--chromium/media/gpu/windows/d3d11_vp9_picture.h4
-rw-r--r--chromium/media/gpu/windows/dxva_video_decode_accelerator_win.cc140
-rw-r--r--chromium/media/gpu/windows/dxva_video_decode_accelerator_win.h18
-rw-r--r--chromium/media/gpu/windows/supported_profile_helpers.cc218
-rw-r--r--chromium/media/gpu/windows/supported_profile_helpers.h56
-rw-r--r--chromium/media/gpu/windows/supported_profile_helpers_unittest.cc261
22 files changed, 723 insertions, 585 deletions
diff --git a/chromium/media/gpu/windows/av1_guids.h b/chromium/media/gpu/windows/av1_guids.h
new file mode 100644
index 00000000000..c5e4e5d314c
--- /dev/null
+++ b/chromium/media/gpu/windows/av1_guids.h
@@ -0,0 +1,52 @@
+// 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 <dxva.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_
diff --git a/chromium/media/gpu/windows/d3d11_decoder_configurator.cc b/chromium/media/gpu/windows/d3d11_decoder_configurator.cc
index a4a42eabf51..869106f87e9 100644
--- a/chromium/media/gpu/windows/d3d11_decoder_configurator.cc
+++ b/chromium/media/gpu/windows/d3d11_decoder_configurator.cc
@@ -73,9 +73,11 @@ bool D3D11DecoderConfigurator::SupportsDevice(
ComD3D11Texture2D D3D11DecoderConfigurator::CreateOutputTexture(
ComD3D11Device device,
- gfx::Size size) {
+ gfx::Size size,
+ uint32_t array_size) {
output_texture_desc_.Width = size.width();
output_texture_desc_.Height = size.height();
+ output_texture_desc_.ArraySize = array_size;
ComD3D11Texture2D result;
if (!SUCCEEDED(
@@ -100,7 +102,6 @@ void D3D11DecoderConfigurator::SetUpTextureDescriptor(bool supports_swap_chain,
bool is_encrypted) {
output_texture_desc_ = {};
output_texture_desc_.MipLevels = 1;
- output_texture_desc_.ArraySize = D3D11DecoderConfigurator::BUFFER_COUNT;
output_texture_desc_.Format = dxgi_format_;
output_texture_desc_.SampleDesc.Count = 1;
output_texture_desc_.Usage = D3D11_USAGE_DEFAULT;
diff --git a/chromium/media/gpu/windows/d3d11_decoder_configurator.h b/chromium/media/gpu/windows/d3d11_decoder_configurator.h
index a23535bc615..3d6cd49e90c 100644
--- a/chromium/media/gpu/windows/d3d11_decoder_configurator.h
+++ b/chromium/media/gpu/windows/d3d11_decoder_configurator.h
@@ -40,7 +40,9 @@ class MEDIA_GPU_EXPORT D3D11DecoderConfigurator {
bool SupportsDevice(ComD3D11VideoDevice video_device);
// Create the decoder's output texture.
- ComD3D11Texture2D CreateOutputTexture(ComD3D11Device device, gfx::Size size);
+ ComD3D11Texture2D CreateOutputTexture(ComD3D11Device device,
+ gfx::Size size,
+ uint32_t array_size);
const D3D11_VIDEO_DECODER_DESC* DecoderDescriptor() const {
return &decoder_desc_;
diff --git a/chromium/media/gpu/windows/d3d11_h264_accelerator.cc b/chromium/media/gpu/windows/d3d11_h264_accelerator.cc
index df549d3a380..e87c1ece44f 100644
--- a/chromium/media/gpu/windows/d3d11_h264_accelerator.cc
+++ b/chromium/media/gpu/windows/d3d11_h264_accelerator.cc
@@ -45,12 +45,12 @@ void AppendSubsamples(
class D3D11H264Picture : public H264Picture {
public:
D3D11H264Picture(D3D11PictureBuffer* picture)
- : picture(picture), level_(picture->level()) {
+ : picture(picture), picture_index_(picture->picture_index()) {
picture->set_in_picture_use(true);
}
D3D11PictureBuffer* picture;
- size_t level_;
+ size_t picture_index_;
protected:
~D3D11H264Picture() override;
@@ -63,16 +63,16 @@ D3D11H264Picture::~D3D11H264Picture() {
D3D11H264Accelerator::D3D11H264Accelerator(
D3D11VideoDecoderClient* client,
MediaLog* media_log,
- ComD3D11VideoDecoder video_decoder,
ComD3D11VideoDevice video_device,
std::unique_ptr<VideoContextWrapper> video_context)
: client_(client),
media_log_(media_log),
- video_decoder_(video_decoder),
video_device_(video_device),
video_context_(std::move(video_context)) {
DCHECK(client);
DCHECK(media_log_);
+ client->SetDecoderCB(base::BindRepeating(
+ &D3D11H264Accelerator::SetVideoDecoder, base::Unretained(this)));
}
D3D11H264Accelerator::~D3D11H264Accelerator() {}
@@ -135,7 +135,7 @@ DecoderStatus D3D11H264Accelerator::SubmitFrameMetadata(
D3D11H264Picture* our_ref_pic = static_cast<D3D11H264Picture*>(it->get());
if (!our_ref_pic->ref)
continue;
- ref_frame_list_[i].Index7Bits = our_ref_pic->level_;
+ ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_;
ref_frame_list_[i].AssociatedFlag = our_ref_pic->long_term;
field_order_cnt_list_[i][0] = our_ref_pic->top_field_order_cnt;
field_order_cnt_list_[i][1] = our_ref_pic->bottom_field_order_cnt;
@@ -281,7 +281,7 @@ void D3D11H264Accelerator::PicParamsFromSliceHeader(
void D3D11H264Accelerator::PicParamsFromPic(DXVA_PicParams_H264* pic_param,
scoped_refptr<H264Picture> pic) {
pic_param->CurrPic.Index7Bits =
- static_cast<D3D11H264Picture*>(pic.get())->level_;
+ static_cast<D3D11H264Picture*>(pic.get())->picture_index_;
pic_param->RefPicFlag = pic->ref;
pic_param->frame_num = pic->frame_num;
@@ -588,4 +588,8 @@ void D3D11H264Accelerator::RecordFailure(const std::string& reason,
MEDIA_LOG(ERROR, media_log_) << hr_string << ": " << reason;
}
+void D3D11H264Accelerator::SetVideoDecoder(ComD3D11VideoDecoder video_decoder) {
+ video_decoder_ = std::move(video_decoder);
+}
+
} // namespace media
diff --git a/chromium/media/gpu/windows/d3d11_h264_accelerator.h b/chromium/media/gpu/windows/d3d11_h264_accelerator.h
index cd9dd468755..00e2bd5cecd 100644
--- a/chromium/media/gpu/windows/d3d11_h264_accelerator.h
+++ b/chromium/media/gpu/windows/d3d11_h264_accelerator.h
@@ -34,7 +34,6 @@ class D3D11H264Accelerator : public H264Decoder::H264Accelerator {
public:
D3D11H264Accelerator(D3D11VideoDecoderClient* client,
MediaLog* media_log,
- ComD3D11VideoDecoder video_decoder,
ComD3D11VideoDevice video_device,
std::unique_ptr<VideoContextWrapper> video_context);
~D3D11H264Accelerator() override;
@@ -78,6 +77,8 @@ class D3D11H264Accelerator : public H264Decoder::H264Accelerator {
void PicParamsFromPic(DXVA_PicParams_H264* pic_param,
scoped_refptr<H264Picture> pic);
+ void SetVideoDecoder(ComD3D11VideoDecoder video_decoder);
+
private:
bool SubmitSliceData();
bool RetrieveBitstreamBuffer();
diff --git a/chromium/media/gpu/windows/d3d11_picture_buffer.cc b/chromium/media/gpu/windows/d3d11_picture_buffer.cc
index 7c0278b690e..60d1720e92f 100644
--- a/chromium/media/gpu/windows/d3d11_picture_buffer.cc
+++ b/chromium/media/gpu/windows/d3d11_picture_buffer.cc
@@ -24,15 +24,17 @@ namespace media {
D3D11PictureBuffer::D3D11PictureBuffer(
scoped_refptr<base::SequencedTaskRunner> delete_task_runner,
ComD3D11Texture2D texture,
+ size_t array_slice,
std::unique_ptr<Texture2DWrapper> texture_wrapper,
gfx::Size size,
- size_t level)
+ size_t picture_index)
: RefCountedDeleteOnSequence<D3D11PictureBuffer>(
std::move(delete_task_runner)),
texture_(std::move(texture)),
+ array_slice_(array_slice),
texture_wrapper_(std::move(texture_wrapper)),
size_(size),
- level_(level) {}
+ picture_index_(picture_index) {}
D3D11PictureBuffer::~D3D11PictureBuffer() {
}
@@ -46,7 +48,7 @@ bool D3D11PictureBuffer::Init(
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = {};
view_desc.DecodeProfile = decoder_guid;
view_desc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D;
- view_desc.Texture2D.ArraySlice = (UINT)level_;
+ view_desc.Texture2D.ArraySlice = array_slice_;
if (!texture_wrapper_->Init(std::move(gpu_task_runner),
std::move(get_helper_cb))) {
@@ -69,8 +71,9 @@ bool D3D11PictureBuffer::ProcessTexture(
const gfx::ColorSpace& input_color_space,
MailboxHolderArray* mailbox_dest,
gfx::ColorSpace* output_color_space) {
- return texture_wrapper_->ProcessTexture(Texture(), level_, input_color_space,
- mailbox_dest, output_color_space);
+ return texture_wrapper_->ProcessTexture(Texture(), array_slice_,
+ input_color_space, mailbox_dest,
+ output_color_space);
}
ComD3D11Texture2D D3D11PictureBuffer::Texture() const {
diff --git a/chromium/media/gpu/windows/d3d11_picture_buffer.h b/chromium/media/gpu/windows/d3d11_picture_buffer.h
index d605772d147..08e2c307725 100644
--- a/chromium/media/gpu/windows/d3d11_picture_buffer.h
+++ b/chromium/media/gpu/windows/d3d11_picture_buffer.h
@@ -47,13 +47,18 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
public:
// |texture_wrapper| is responsible for controlling mailbox access to
// the ID3D11Texture2D,
- // |level| is the picturebuffer index inside the Array-type ID3D11Texture2D.
+ // |array_slice| is the picturebuffer index inside the Array-type
+ // ID3D11Texture2D. |picture_index| is a unique id used to identify this
+ // picture to the decoder. If a texture array is used, then it might as well
+ // be equal to the texture array index. Otherwise, any 0-based index is
+ // probably okay, though sequential makes sense.
D3D11PictureBuffer(
scoped_refptr<base::SequencedTaskRunner> delete_task_runner,
ComD3D11Texture2D texture,
+ size_t array_slice,
std::unique_ptr<Texture2DWrapper> texture_wrapper,
gfx::Size size,
- size_t level);
+ size_t picture_index);
bool Init(scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
GetCommandBufferHelperCB get_helper_cb,
@@ -71,7 +76,7 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
ComD3D11Texture2D Texture() const;
const gfx::Size& size() const { return size_; }
- size_t level() const { return level_; }
+ size_t picture_index() const { return picture_index_; }
// Is this PictureBuffer backing a VideoFrame right now?
bool in_client_use() const { return in_client_use_; }
@@ -97,11 +102,13 @@ class MEDIA_GPU_EXPORT D3D11PictureBuffer
friend class base::DeleteHelper<D3D11PictureBuffer>;
ComD3D11Texture2D texture_;
+ uint32_t array_slice_;
+
std::unique_ptr<Texture2DWrapper> texture_wrapper_;
gfx::Size size_;
bool in_picture_use_ = false;
bool in_client_use_ = false;
- size_t level_;
+ size_t picture_index_;
ComD3D11VideoDecoderOutputView output_view_;
diff --git a/chromium/media/gpu/windows/d3d11_texture_selector.cc b/chromium/media/gpu/windows/d3d11_texture_selector.cc
index b3f0c78377d..dd3b88544ac 100644
--- a/chromium/media/gpu/windows/d3d11_texture_selector.cc
+++ b/chromium/media/gpu/windows/d3d11_texture_selector.cc
@@ -152,7 +152,7 @@ std::unique_ptr<TextureSelector> TextureSelector::Create(
// If we're trying to produce an output texture that's different from what
// the decoder is providing, then we need to copy it.
- needs_texture_copy = (decoder_output_format != output_dxgi_format);
+ needs_texture_copy |= (decoder_output_format != output_dxgi_format);
// Force texture copy on if requested for debugging.
if (base::FeatureList::IsEnabled(kD3D11VideoDecoderAlwaysCopy))
diff --git a/chromium/media/gpu/windows/d3d11_texture_wrapper.cc b/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
index ab7ea22a87f..58f36986b9b 100644
--- a/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
+++ b/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -74,6 +74,9 @@ bool DefaultTexture2DWrapper::ProcessTexture(
if (received_error_)
return false;
+ // Temporary check to track down https://crbug.com/1077645
+ CHECK(texture);
+
// It's okay to post and forget this call, since it'll be ordered correctly
// with respect to any access on the gpu main thread.
gpu_resources_.Post(FROM_HERE, &GpuResources::PushNewTexture,
@@ -259,14 +262,24 @@ void DefaultTexture2DWrapper::GpuResources::Init(
void DefaultTexture2DWrapper::GpuResources::PushNewTexture(
ComD3D11Texture2D texture,
size_t array_slice) {
- if (!helper_ || !helper_->MakeContextCurrent()) {
- NotifyError(StatusCode::kCantMakeContextCurrent);
+ // If init didn't complete, then signal (another) error that will probably be
+ // ignored in favor of whatever we signalled earlier.
+ if (!gl_image_ || !stream_) {
+ NotifyError(StatusCode::kDecoderInitializeNeverCompleted);
return;
}
- // Notify |gl_image_| that it has a new texture.
+ // Notify |gl_image_| that it has a new texture. Do this unconditionally, so
+ // hat we can guarantee that the image isn't null. Nobody expects it to be,
+ // and failures will be noticed only asynchronously.
+ // https://crbug.com/1077645
gl_image_->SetTexture(texture, array_slice);
+ if (!helper_ || !helper_->MakeContextCurrent()) {
+ NotifyError(StatusCode::kCantMakeContextCurrent);
+ return;
+ }
+
// Notify angle that it has a new texture.
EGLAttrib frame_attributes[] = {
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
diff --git a/chromium/media/gpu/windows/d3d11_video_decoder.cc b/chromium/media/gpu/windows/d3d11_video_decoder.cc
index 3ba6d9b3225..a98753cb255 100644
--- a/chromium/media/gpu/windows/d3d11_video_decoder.cc
+++ b/chromium/media/gpu/windows/d3d11_video_decoder.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
@@ -26,6 +27,7 @@
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
+#include "media/base/win/hresult_status_helper.h"
#include "media/gpu/windows/d3d11_picture_buffer.h"
#include "media/gpu/windows/d3d11_video_context_wrapper.h"
#include "media/gpu/windows/d3d11_video_decoder_impl.h"
@@ -166,23 +168,125 @@ HRESULT D3D11VideoDecoder::InitializeAcceleratedDecoder(
profile_ = config.profile();
if (config.codec() == kCodecVP9) {
accelerated_video_decoder_ = std::make_unique<VP9Decoder>(
- std::make_unique<D3D11VP9Accelerator>(this, media_log_.get(),
- video_decoder, video_device_,
- std::move(video_context)),
+ std::make_unique<D3D11VP9Accelerator>(
+ this, media_log_.get(), video_device_, std::move(video_context)),
profile_, config.color_space_info());
- return hr;
- }
-
- if (config.codec() == kCodecH264) {
+ } else if (config.codec() == kCodecH264) {
accelerated_video_decoder_ = std::make_unique<H264Decoder>(
- std::make_unique<D3D11H264Accelerator>(this, media_log_.get(),
- video_decoder, video_device_,
- std::move(video_context)),
+ std::make_unique<D3D11H264Accelerator>(
+ this, media_log_.get(), video_device_, std::move(video_context)),
profile_, config.color_space_info());
- return hr;
+ } else {
+ return E_FAIL;
}
- return E_FAIL;
+ // Provide the initial video decoder object.
+ DCHECK(set_accelerator_decoder_cb_);
+ set_accelerator_decoder_cb_.Run(std::move(video_decoder));
+
+ return hr;
+}
+
+ErrorOr<std::tuple<ComD3D11VideoDecoder>>
+D3D11VideoDecoder::CreateD3D11Decoder() {
+ HRESULT hr;
+
+ // TODO: supported check?
+
+ decoder_configurator_ = D3D11DecoderConfigurator::Create(
+ gpu_preferences_, gpu_workarounds_, config_, media_log_.get());
+ if (!decoder_configurator_)
+ return StatusCode::kDecoderUnsupportedProfile;
+
+ if (!decoder_configurator_->SupportsDevice(video_device_))
+ return StatusCode::kDecoderUnsupportedCodec;
+
+ FormatSupportChecker format_checker(device_);
+ if (!format_checker.Initialize()) {
+ // Don't fail; it'll just return no support a lot.
+ MEDIA_LOG(WARNING, media_log_)
+ << "Could not create format checker, continuing";
+ }
+
+ // Use IsHDRSupported to guess whether the compositor can output HDR textures.
+ // See TextureSelector for notes about why the decoder should not care.
+ texture_selector_ = TextureSelector::Create(
+ gpu_preferences_, gpu_workarounds_,
+ decoder_configurator_->TextureFormat(),
+ is_hdr_supported_ ? TextureSelector::HDRMode::kSDROrHDR
+ : TextureSelector::HDRMode::kSDROnly,
+ &format_checker, media_log_.get());
+ if (!texture_selector_)
+ return StatusCode::kCannotCreateTextureSelector;
+
+ UINT config_count = 0;
+ hr = video_device_->GetVideoDecoderConfigCount(
+ decoder_configurator_->DecoderDescriptor(), &config_count);
+
+ if (FAILED(hr)) {
+ return Status(StatusCode::kCannotGetDecoderConfigCount)
+ .AddCause(HresultToStatus(hr));
+ }
+
+ if (config_count == 0)
+ return Status(StatusCode::kCannotGetDecoderConfigCount);
+
+ D3D11_VIDEO_DECODER_CONFIG dec_config = {};
+ bool found = false;
+
+ for (UINT i = 0; i < config_count; i++) {
+ hr = video_device_->GetVideoDecoderConfig(
+ decoder_configurator_->DecoderDescriptor(), i, &dec_config);
+ if (FAILED(hr)) {
+ return Status(StatusCode::kCannotGetDecoderConfig)
+ .AddCause(HresultToStatus(hr));
+ }
+
+ if (config_.codec() == kCodecVP9 && dec_config.ConfigBitstreamRaw == 1) {
+ // DXVA VP9 specification mentions ConfigBitstreamRaw "shall be 1".
+ found = true;
+ break;
+ }
+
+ if (config_.codec() == kCodecH264 && dec_config.ConfigBitstreamRaw == 2) {
+ // ConfigBitstreamRaw == 2 means the decoder uses DXVA_Slice_H264_Short.
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return StatusCode::kDecoderUnsupportedConfig;
+
+ // Prefer whatever the config tells us about whether to use one Texture2D with
+ // multiple array slices, or multiple Texture2Ds with one slice each. If bit
+ // 14 is clear, then it's the former, else it's the latter.
+ //
+ // Let the workaround override array texture mode, if enabled.
+ //
+ // For more information, please see:
+ // https://download.microsoft.com/download/9/2/A/92A4E198-67E0-4ABD-9DB7-635D711C2752/DXVA_VPx.pdf
+ // https://download.microsoft.com/download/5/f/c/5fc4ec5c-bd8c-4624-8034-319c1bab7671/DXVA_H264.pdf
+ use_single_video_decoder_texture_ =
+ !!(dec_config.ConfigDecoderSpecific & (1 << 14)) ||
+ gpu_workarounds_.use_single_video_decoder_texture;
+ if (use_single_video_decoder_texture_)
+ MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using single textures";
+ else
+ MEDIA_LOG(INFO, media_log_) << "D3D11VideoDecoder is using array texture";
+
+ Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
+ hr = video_device_->CreateVideoDecoder(
+ decoder_configurator_->DecoderDescriptor(), &dec_config, &video_decoder);
+
+ if (!video_decoder.Get())
+ return Status(StatusCode::kDecoderFailedCreation);
+
+ if (FAILED(hr)) {
+ return Status(StatusCode::kDecoderFailedCreation)
+ .AddCause(HresultToStatus(hr));
+ }
+
+ return {std::move(video_decoder)};
}
void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
@@ -257,57 +361,20 @@ void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
return;
}
- device_->GetImmediateContext(device_context_.ReleaseAndGetAddressOf());
+ device_->GetImmediateContext(&device_context_);
HRESULT hr;
// TODO(liberato): Handle cleanup better. Also consider being less chatty in
// the logs, since this will fall back.
- hr = device_.CopyTo(video_device_.ReleaseAndGetAddressOf());
- if (!SUCCEEDED(hr)) {
- NotifyError("Failed to get video device");
- return;
- }
-
- decoder_configurator_ = D3D11DecoderConfigurator::Create(
- gpu_preferences_, gpu_workarounds_, config, media_log_.get());
- if (!decoder_configurator_) {
- NotifyError("D3DD11: Config provided unsupported profile");
- return;
- }
-
- if (!decoder_configurator_->SupportsDevice(video_device_)) {
- NotifyError("D3D11: Device does not support decoder GUID");
- return;
- }
-
- FormatSupportChecker format_checker(device_);
- if (!format_checker.Initialize()) {
- // Don't fail; it'll just return no support a lot.
- MEDIA_LOG(WARNING, media_log_)
- << "Could not create format checker, continuing";
- }
-
- // Use IsHDRSupported to guess whether the compositor can output HDR textures.
- // See TextureSelector for notes about why the decoder should not care.
- texture_selector_ = TextureSelector::Create(
- gpu_preferences_, gpu_workarounds_,
- decoder_configurator_->TextureFormat(),
- is_hdr_supported_ ? TextureSelector::HDRMode::kSDROrHDR
- : TextureSelector::HDRMode::kSDROnly,
- &format_checker, media_log_.get());
- if (!texture_selector_) {
- NotifyError("D3DD11: Cannot get TextureSelector for format");
- return;
- }
-
// TODO(liberato): dxva does this. don't know if we need to.
if (!base::FeatureList::IsEnabled(kD3D11VideoDecoderSkipMultithreaded)) {
ComD3D11Multithread multi_threaded;
hr = device_->QueryInterface(IID_PPV_ARGS(&multi_threaded));
if (!SUCCEEDED(hr)) {
- NotifyError("Failed to query ID3D11Multithread");
+ NotifyError(Status(StatusCode::kCannotQueryID3D11Multithread)
+ .AddCause(HresultToStatus(hr)));
return;
}
// TODO(liberato): This is a hack, since the unittest returns
@@ -316,51 +383,20 @@ void D3D11VideoDecoder::Initialize(const VideoDecoderConfig& config,
multi_threaded->SetMultithreadProtected(TRUE);
}
- UINT config_count = 0;
- hr = video_device_->GetVideoDecoderConfigCount(
- decoder_configurator_->DecoderDescriptor(), &config_count);
- if (FAILED(hr) || config_count == 0) {
- NotifyError("Failed to get video decoder config count");
- return;
- }
-
- D3D11_VIDEO_DECODER_CONFIG dec_config = {};
- bool found = false;
-
- for (UINT i = 0; i < config_count; i++) {
- hr = video_device_->GetVideoDecoderConfig(
- decoder_configurator_->DecoderDescriptor(), i, &dec_config);
- if (FAILED(hr)) {
- NotifyError("Failed to get decoder config");
- return;
- }
-
- if (config.codec() == kCodecVP9 && dec_config.ConfigBitstreamRaw == 1) {
- // DXVA VP9 specification mentions ConfigBitstreamRaw "shall be 1".
- found = true;
- break;
- }
-
- if (config.codec() == kCodecH264 && dec_config.ConfigBitstreamRaw == 2) {
- // ConfigBitstreamRaw == 2 means the decoder uses DXVA_Slice_H264_Short.
- found = true;
- break;
- }
- }
- if (!found) {
- NotifyError("Failed to find decoder config");
+ hr = device_.As(&video_device_);
+ if (!SUCCEEDED(hr)) {
+ NotifyError("Failed to get video device");
return;
}
- Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder;
- hr = video_device_->CreateVideoDecoder(
- decoder_configurator_->DecoderDescriptor(), &dec_config, &video_decoder);
- if (!video_decoder.Get()) {
- NotifyError("Failed to create a video decoder");
+ auto video_decoder_or_error = CreateD3D11Decoder();
+ if (video_decoder_or_error.has_error()) {
+ NotifyError(video_decoder_or_error.error());
return;
}
- hr = InitializeAcceleratedDecoder(config, video_decoder);
+ hr = InitializeAcceleratedDecoder(
+ config, std::move(std::get<0>(video_decoder_or_error.value())));
if (!SUCCEEDED(hr)) {
NotifyError("Failed to get device context");
@@ -556,13 +592,35 @@ void D3D11VideoDecoder::DoDecode() {
return;
CreatePictureBuffers();
} else if (result == media::AcceleratedVideoDecoder::kConfigChange) {
+ // TODO(liberato): I think we support this now, as long as it's the same
+ // decoder. Should update |config_| though.
if (profile_ != accelerated_video_decoder_->GetProfile()) {
// TODO(crbug.com/1022246): Handle profile change.
LOG(ERROR) << "Profile change is not supported";
NotifyError("Profile change is not supported");
return;
}
- CreatePictureBuffers();
+ // Before the first frame, we get a config change that we should ignore.
+ // We only want to take action if this is a mid-stream config change. We
+ // could wait until now to allocate the first D3D11VideoDecoder, but we
+ // don't, so that init can fail rather than decoding if there's a problem
+ // creating it. If there's a config change at the start of the stream,
+ // then this might not work.
+ if (!picture_buffers_.size())
+ continue;
+
+ // Update the config.
+ const auto new_coded_size = accelerated_video_decoder_->GetPicSize();
+ config_.set_coded_size(new_coded_size);
+ auto video_decoder_or_error = CreateD3D11Decoder();
+ if (video_decoder_or_error.has_error()) {
+ NotifyError(video_decoder_or_error.error());
+ return;
+ }
+ DCHECK(set_accelerator_decoder_cb_);
+ set_accelerator_decoder_cb_.Run(
+ std::move(std::get<0>(video_decoder_or_error.value())));
+ picture_buffers_.clear();
} else if (result == media::AcceleratedVideoDecoder::kTryAgain) {
LOG(ERROR) << "Try again is not supported";
NotifyError("Try again is not supported");
@@ -627,14 +685,6 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
DCHECK(texture_selector_);
gfx::Size size = accelerated_video_decoder_->GetPicSize();
- // Create an input texture array.
- ComD3D11Texture2D in_texture =
- decoder_configurator_->CreateOutputTexture(device_, size);
- if (!in_texture) {
- NotifyError("Failed to create a Texture2D for PictureBuffers");
- return;
- }
-
HDRMetadata stream_metadata;
if (config_.hdr_metadata())
stream_metadata = *config_.hdr_metadata();
@@ -653,8 +703,24 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
DCHECK(!buffer->in_picture_use());
picture_buffers_.clear();
+ ComD3D11Texture2D in_texture;
+
// Create each picture buffer.
for (size_t i = 0; i < D3D11DecoderConfigurator::BUFFER_COUNT; i++) {
+ // Create an input texture / texture array if we haven't already.
+ if (!in_texture) {
+ in_texture = decoder_configurator_->CreateOutputTexture(
+ device_, size,
+ use_single_video_decoder_texture_
+ ? 1
+ : D3D11DecoderConfigurator::BUFFER_COUNT);
+ }
+
+ if (!in_texture) {
+ NotifyError("Failed to create a Texture2D for PictureBuffers");
+ return;
+ }
+
auto tex_wrapper = texture_selector_->CreateTextureWrapper(
device_, video_device_, device_context_, size);
if (!tex_wrapper) {
@@ -662,8 +728,10 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
return;
}
- picture_buffers_.push_back(new D3D11PictureBuffer(
- decoder_task_runner_, in_texture, std::move(tex_wrapper), size, i));
+ const size_t array_slice = use_single_video_decoder_texture_ ? 0 : i;
+ picture_buffers_.push_back(
+ new D3D11PictureBuffer(decoder_task_runner_, in_texture, array_slice,
+ std::move(tex_wrapper), size, i /* level */));
if (!picture_buffers_[i]->Init(
gpu_task_runner_, get_helper_cb_, video_device_,
decoder_configurator_->DecoderGuid(), media_log_->Clone())) {
@@ -671,6 +739,11 @@ void D3D11VideoDecoder::CreatePictureBuffers() {
return;
}
+ // If we're using one texture per buffer, rather than an array, then clear
+ // the ref to it so that we allocate a new one above.
+ if (use_single_video_decoder_texture_)
+ in_texture = nullptr;
+
// 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.
@@ -750,7 +823,7 @@ bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
frame->SetReleaseMailboxCB(
base::BindOnce(release_mailbox_cb_, std::move(wait_complete_cb)));
- frame->metadata()->SetBoolean(VideoFrameMetadata::POWER_EFFICIENT, true);
+ frame->metadata()->power_efficient = true;
// For NV12, overlay is allowed by default. If the decoder is going to support
// non-NV12 textures, then this may have to be conditionally set. Also note
// that ALLOW_OVERLAY is required for encrypted video path.
@@ -765,28 +838,33 @@ bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
// presenter decide if it wants to.
const bool allow_overlay =
base::FeatureList::IsEnabled(kD3D11VideoDecoderAllowOverlay);
- frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY,
- allow_overlay);
+ frame->metadata()->allow_overlay = allow_overlay;
frame->set_color_space(output_color_space);
output_cb_.Run(frame);
return true;
}
-// TODO(tmathmeyer) eventually have this take a Status and pass it through
-// to each of the callbacks.
+void D3D11VideoDecoder::SetDecoderCB(const SetAcceleratorDecoderCB& cb) {
+ set_accelerator_decoder_cb_ = cb;
+}
+
+// TODO(tmathmeyer): Please don't add new uses of this overload.
void D3D11VideoDecoder::NotifyError(const char* reason) {
+ NotifyError(Status(StatusCode::kDecoderInitializeNeverCompleted, reason));
+}
+
+void D3D11VideoDecoder::NotifyError(const Status& reason) {
TRACE_EVENT0("gpu", "D3D11VideoDecoder::NotifyError");
state_ = State::kError;
- DLOG(ERROR) << reason;
// TODO(tmathmeyer) - Remove this after plumbing Status through the
// decode_cb and input_buffer_queue cb's.
- MEDIA_LOG(ERROR, media_log_) << reason;
+ MEDIA_LOG(ERROR, media_log_)
+ << "D3D11VideoDecoder error: " << std::hex << reason.code();
if (init_cb_)
- std::move(init_cb_).Run(
- Status(StatusCode::kDecoderInitializeNeverCompleted, reason));
+ std::move(init_cb_).Run(reason);
current_buffer_ = nullptr;
if (current_decode_cb_)
@@ -876,97 +954,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);
}
}
diff --git a/chromium/media/gpu/windows/d3d11_video_decoder.h b/chromium/media/gpu/windows/d3d11_video_decoder.h
index d9ba26ab254..70e07b81300 100644
--- a/chromium/media/gpu/windows/d3d11_video_decoder.h
+++ b/chromium/media/gpu/windows/d3d11_video_decoder.h
@@ -85,6 +85,7 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder,
D3D11PictureBuffer* GetPicture() override;
bool OutputResult(const CodecPicture* picture,
D3D11PictureBuffer* picture_buffer) override;
+ void SetDecoderCB(const SetAcceleratorDecoderCB&) override;
static bool GetD3D11FeatureLevel(
ComD3D11Device dev,
@@ -142,6 +143,12 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder,
// gpu main thread.
void CreatePictureBuffers();
+ // Create a D3D11VideoDecoder, if possible, based on the current config.
+ // TODO(liberato): we use a tuple only because ErrorOr<ComD3D111VideoDecoder>
+ // doesn't work. Something about base::Optional trying to convert to void*,
+ // but the conversion is ambiguous.
+ ErrorOr<std::tuple<ComD3D11VideoDecoder>> CreateD3D11Decoder();
+
enum class NotSupportedReason {
kVideoIsSupported = 0,
@@ -205,8 +212,10 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder,
};
// Enter the kError state. This will fail any pending |init_cb_| and / or
- // pending decode as well.
+ // pending decode as well. Do not add new uses of the char* overload; send a
+ // Status instead.
void NotifyError(const char* reason);
+ void NotifyError(const Status& reason);
// The implementation, which lives on the GPU main thread.
base::SequenceBound<D3D11VideoDecoderImpl> impl_;
@@ -281,7 +290,15 @@ class MEDIA_GPU_EXPORT D3D11VideoDecoder : public VideoDecoder,
SupportedConfigs supported_configs_;
// Should we assume that we're outputting to an HDR display?
- bool is_hdr_supported_;
+ bool is_hdr_supported_ = false;
+
+ // Should we use multiple single textures for the decoder output (true) or one
+ // texture with multiple array slices (false)?
+ bool use_single_video_decoder_texture_ = false;
+
+ // Word-salad callback to set / update D3D11 Video callback to the
+ // accelerator. Needed for config changes.
+ SetAcceleratorDecoderCB set_accelerator_decoder_cb_;
base::WeakPtrFactory<D3D11VideoDecoder> weak_factory_{this};
diff --git a/chromium/media/gpu/windows/d3d11_video_decoder_client.h b/chromium/media/gpu/windows/d3d11_video_decoder_client.h
index a80e8430c7f..0286ad41ade 100644
--- a/chromium/media/gpu/windows/d3d11_video_decoder_client.h
+++ b/chromium/media/gpu/windows/d3d11_video_decoder_client.h
@@ -5,7 +5,9 @@
#ifndef MEDIA_GPU_WINDOWS_D3D11_VIDEO_DECODER_CLIENT_H_
#define MEDIA_GPU_WINDOWS_D3D11_VIDEO_DECODER_CLIENT_H_
+#include "base/callback.h"
#include "media/base/video_color_space.h"
+#include "media/gpu/windows/d3d11_com_defs.h"
namespace media {
@@ -16,10 +18,18 @@ class D3D11PictureBuffer;
// required methods to D3D11VideoAccelerators.
class D3D11VideoDecoderClient {
public:
+ using SetAcceleratorDecoderCB =
+ base::RepeatingCallback<void(ComD3D11VideoDecoder)>;
+
virtual D3D11PictureBuffer* GetPicture() = 0;
virtual bool OutputResult(const CodecPicture* picture,
D3D11PictureBuffer* picture_buffer) = 0;
+ // Called by the accelerator to provide a callback that can be used to give
+ // the accelerator a D3D11VideoDecoder object. Must be called during
+ // construction of the accelerator.
+ virtual void SetDecoderCB(const SetAcceleratorDecoderCB&) = 0;
+
protected:
virtual ~D3D11VideoDecoderClient() = default;
};
diff --git a/chromium/media/gpu/windows/d3d11_video_decoder_unittest.cc b/chromium/media/gpu/windows/d3d11_video_decoder_unittest.cc
index 91908445262..bb950b7717c 100644
--- a/chromium/media/gpu/windows/d3d11_video_decoder_unittest.cc
+++ b/chromium/media/gpu/windows/d3d11_video_decoder_unittest.cc
@@ -283,7 +283,7 @@ TEST_F(D3D11VideoDecoderTest, DoesNotSupportVP9WithLegacyGPU) {
}
TEST_F(D3D11VideoDecoderTest, DoesNotSupportVP9WithGPUWorkaroundDisableVPX) {
- gpu_workarounds_.disable_accelerated_vpx_decode = true;
+ gpu_workarounds_.disable_accelerated_vp9_decode = true;
VideoDecoderConfig configuration =
TestVideoConfig::NormalCodecProfile(kCodecVP9, VP9PROFILE_PROFILE0);
diff --git a/chromium/media/gpu/windows/d3d11_vp9_accelerator.cc b/chromium/media/gpu/windows/d3d11_vp9_accelerator.cc
index eeec7896bde..7fe0f7f7eca 100644
--- a/chromium/media/gpu/windows/d3d11_vp9_accelerator.cc
+++ b/chromium/media/gpu/windows/d3d11_vp9_accelerator.cc
@@ -36,17 +36,17 @@ CreateSubsampleMappingBlock(const std::vector<SubsampleEntry>& from) {
D3D11VP9Accelerator::D3D11VP9Accelerator(
D3D11VideoDecoderClient* client,
MediaLog* media_log,
- ComD3D11VideoDecoder video_decoder,
ComD3D11VideoDevice video_device,
std::unique_ptr<VideoContextWrapper> video_context)
: client_(client),
media_log_(media_log),
status_feedback_(0),
- video_decoder_(std::move(video_decoder)),
video_device_(std::move(video_device)),
video_context_(std::move(video_context)) {
DCHECK(client);
DCHECK(media_log_);
+ client->SetDecoderCB(base::BindRepeating(
+ &D3D11VP9Accelerator::SetVideoDecoder, base::Unretained(this)));
}
D3D11VP9Accelerator::~D3D11VP9Accelerator() {}
@@ -111,7 +111,7 @@ void D3D11VP9Accelerator::CopyFrameParams(const D3D11VP9Picture& pic,
pic_params->BitDepthMinus8Luma = pic_params->BitDepthMinus8Chroma =
pic.frame_hdr->bit_depth - 8;
- pic_params->CurrPic.Index7Bits = pic.level();
+ pic_params->CurrPic.Index7Bits = pic.picture_index();
pic_params->frame_type = !pic.frame_hdr->IsKeyframe();
COPY_PARAM(subsampling_x);
@@ -150,7 +150,7 @@ void D3D11VP9Accelerator::CopyReferenceFrames(
if (ref_pic) {
scoped_refptr<D3D11VP9Picture> our_ref_pic(
static_cast<D3D11VP9Picture*>(ref_pic.get()));
- pic_params->ref_frame_map[i].Index7Bits = our_ref_pic->level();
+ pic_params->ref_frame_map[i].Index7Bits = our_ref_pic->picture_index();
pic_params->ref_frame_coded_width[i] = texture_descriptor.Width;
pic_params->ref_frame_coded_height[i] = texture_descriptor.Height;
} else {
@@ -185,19 +185,16 @@ void D3D11VP9Accelerator::CopyLoopFilterParams(
// base::size(...) doesn't work well in an array initializer.
DCHECK_EQ(4lu, base::size(pic_params->ref_deltas));
- int ref_deltas[4] = {0};
for (size_t i = 0; i < base::size(pic_params->ref_deltas); i++) {
- if (loop_filter_params.update_ref_deltas[i])
- ref_deltas[i] = loop_filter_params.ref_deltas[i];
- pic_params->ref_deltas[i] = ref_deltas[i];
+ // The update_ref_deltas[i] is _only_ for parsing! it allows omission of the
+ // 6 bytes that would otherwise be needed for a new value to overwrite the
+ // global one. It has nothing to do with setting the ref_deltas here.
+ pic_params->ref_deltas[i] = loop_filter_params.ref_deltas[i];
}
- int mode_deltas[2] = {0};
DCHECK_EQ(2lu, base::size(pic_params->mode_deltas));
for (size_t i = 0; i < base::size(pic_params->mode_deltas); i++) {
- if (loop_filter_params.update_mode_deltas[i])
- mode_deltas[i] = loop_filter_params.mode_deltas[i];
- pic_params->mode_deltas[i] = mode_deltas[i];
+ pic_params->mode_deltas[i] = loop_filter_params.mode_deltas[i];
}
}
@@ -381,4 +378,8 @@ bool D3D11VP9Accelerator::GetFrameContext(scoped_refptr<VP9Picture> picture,
return false;
}
+void D3D11VP9Accelerator::SetVideoDecoder(ComD3D11VideoDecoder video_decoder) {
+ video_decoder_ = std::move(video_decoder);
+}
+
} // namespace media
diff --git a/chromium/media/gpu/windows/d3d11_vp9_accelerator.h b/chromium/media/gpu/windows/d3d11_vp9_accelerator.h
index dc262d68d26..43c2c26e595 100644
--- a/chromium/media/gpu/windows/d3d11_vp9_accelerator.h
+++ b/chromium/media/gpu/windows/d3d11_vp9_accelerator.h
@@ -24,7 +24,6 @@ class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
public:
D3D11VP9Accelerator(D3D11VideoDecoderClient* client,
MediaLog* media_log,
- ComD3D11VideoDecoder video_decoder,
ComD3D11VideoDevice video_device,
std::unique_ptr<VideoContextWrapper> video_context);
~D3D11VP9Accelerator() override;
@@ -69,6 +68,8 @@ class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
void RecordFailure(const std::string& fail_type, const std::string& reason);
+ void SetVideoDecoder(ComD3D11VideoDecoder video_decoder);
+
D3D11VideoDecoderClient* client_;
MediaLog* const media_log_;
UINT status_feedback_;
diff --git a/chromium/media/gpu/windows/d3d11_vp9_picture.cc b/chromium/media/gpu/windows/d3d11_vp9_picture.cc
index 24ae6033294..5efa82b5be0 100644
--- a/chromium/media/gpu/windows/d3d11_vp9_picture.cc
+++ b/chromium/media/gpu/windows/d3d11_vp9_picture.cc
@@ -7,7 +7,8 @@
namespace media {
D3D11VP9Picture::D3D11VP9Picture(D3D11PictureBuffer* picture_buffer)
- : picture_buffer_(picture_buffer), level_(picture_buffer_->level()) {
+ : picture_buffer_(picture_buffer),
+ picture_index_(picture_buffer_->picture_index()) {
picture_buffer_->set_in_picture_use(true);
}
diff --git a/chromium/media/gpu/windows/d3d11_vp9_picture.h b/chromium/media/gpu/windows/d3d11_vp9_picture.h
index 3d3bcbbb3f9..27b144402cc 100644
--- a/chromium/media/gpu/windows/d3d11_vp9_picture.h
+++ b/chromium/media/gpu/windows/d3d11_vp9_picture.h
@@ -19,14 +19,14 @@ class D3D11VP9Picture : public VP9Picture {
D3D11PictureBuffer* picture_buffer() const { return picture_buffer_; }
- size_t level() const { return level_; }
+ size_t picture_index() const { return picture_index_; }
protected:
~D3D11VP9Picture() override;
private:
D3D11PictureBuffer* picture_buffer_;
- size_t level_;
+ size_t picture_index_;
};
} // namespace media
diff --git a/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index ff451f0bb17..350458a8598 100644
--- a/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -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};
@@ -606,7 +595,11 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
enable_low_latency_(gpu_preferences.enable_low_latency_dxva),
support_share_nv12_textures_(
gpu_preferences.enable_zero_copy_dxgi_video &&
- !workarounds.disable_dxgi_zero_copy_video),
+ !workarounds.disable_dxgi_zero_copy_video &&
+ /* Sharing will use an array texture, so avoid it if arrays are being
+ * worked around. https://crbug.com/971952 .
+ */
+ !workarounds.use_single_video_decoder_texture),
num_picture_buffers_requested_(support_share_nv12_textures_
? kNumPictureBuffersForZeroCopy
: kNumPictureBuffers),
@@ -619,8 +612,12 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
use_keyed_mutex_(false),
using_angle_device_(false),
using_debug_device_(false),
- enable_accelerated_vpx_decode_(
- !workarounds.disable_accelerated_vpx_decode),
+ enable_accelerated_av1_decode_(
+ !workarounds.disable_accelerated_av1_decode),
+ enable_accelerated_vp8_decode_(
+ !workarounds.disable_accelerated_vp8_decode),
+ enable_accelerated_vp9_decode_(
+ !workarounds.disable_accelerated_vp9_decode),
processing_config_changed_(false),
use_empty_video_hdr_metadata_(workarounds.use_empty_video_hdr_metadata) {
weak_ptr_ = weak_this_factory_.GetWeakPtr();
@@ -1343,84 +1340,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;
}
@@ -1475,18 +1416,21 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(VideoCodecProfile profile) {
"blacklisted version of msmpeg2vdec.dll 6.1.7140", false);
codec_ = kCodecH264;
clsid = __uuidof(CMSH264DecoderMFT);
- } else if (enable_accelerated_vpx_decode_ &&
- ((profile >= VP9PROFILE_PROFILE0 &&
- profile <= VP9PROFILE_PROFILE3) ||
- profile == VP8PROFILE_ANY)) {
+ } else if ((profile >= VP9PROFILE_PROFILE0 &&
+ profile <= VP9PROFILE_PROFILE3) ||
+ profile == VP8PROFILE_ANY) {
codec_ = profile == VP8PROFILE_ANY ? kCodecVP8 : kCodecVP9;
- clsid = CLSID_MSVPxDecoder;
- decoder_dll = ::LoadLibrary(kMSVPxDecoderDLLName);
- if (decoder_dll)
- using_ms_vpx_mft_ = true;
+ if ((codec_ == kCodecVP8 && enable_accelerated_vp8_decode_) ||
+ (codec_ == kCodecVP9 && enable_accelerated_vp9_decode_)) {
+ clsid = CLSID_MSVPxDecoder;
+ decoder_dll = ::LoadLibrary(kMSVPxDecoderDLLName);
+ if (decoder_dll)
+ using_ms_vpx_mft_ = true;
+ }
}
- if (base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
+ if (enable_accelerated_av1_decode_ &&
+ base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
(profile >= AV1PROFILE_MIN && profile <= AV1PROFILE_MAX)) {
codec_ = kCodecAV1;
clsid = CLSID_CAV1DecoderMFT;
@@ -1512,17 +1456,15 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(VideoCodecProfile profile) {
CHECK(create_dxgi_device_manager_);
if (media_log_)
MEDIA_LOG(INFO, media_log_) << "Using D3D11 device for DXVA";
- RETURN_AND_NOTIFY_ON_FAILURE(CreateDX11DevManager(),
- "Failed to initialize DX11 device and manager",
- PLATFORM_FAILURE, false);
+ RETURN_ON_FAILURE(CreateDX11DevManager(),
+ "Failed to initialize DX11 device and manager", false);
device_manager_to_use =
reinterpret_cast<ULONG_PTR>(d3d11_device_manager_.Get());
} else {
if (media_log_)
MEDIA_LOG(INFO, media_log_) << "Using D3D9 device for DXVA";
- RETURN_AND_NOTIFY_ON_FAILURE(CreateD3DDevManager(),
- "Failed to initialize D3D device and manager",
- PLATFORM_FAILURE, false);
+ RETURN_ON_FAILURE(CreateD3DDevManager(),
+ "Failed to initialize D3D device and manager", false);
device_manager_to_use = reinterpret_cast<ULONG_PTR>(device_manager_.Get());
}
diff --git a/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.h b/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.h
index 4377744a8fd..21d3ec0d3fb 100644
--- a/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.h
+++ b/chromium/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -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>
@@ -588,8 +582,12 @@ class MEDIA_GPU_EXPORT DXVAVideoDecodeAccelerator
bool using_angle_device_;
bool using_debug_device_;
- // Enables hardware acceleration for VP9 video decoding.
- const bool enable_accelerated_vpx_decode_;
+ // Enables hardware acceleration for AV1 video decoding.
+ const bool enable_accelerated_av1_decode_;
+
+ // Enables hardware acceleration for VP8/VP9 video decoding.
+ const bool enable_accelerated_vp8_decode_;
+ const bool enable_accelerated_vp9_decode_;
// The media foundation H.264 decoder has problems handling changes like
// resolution change, bitrate change etc. If we reinitialize the decoder
diff --git a/chromium/media/gpu/windows/supported_profile_helpers.cc b/chromium/media/gpu/windows/supported_profile_helpers.cc
index 5004c5799b7..7d8622286f1 100644
--- a/chromium/media/gpu/windows/supported_profile_helpers.cc
+++ b/chromium/media/gpu/windows/supported_profile_helpers.cc
@@ -9,16 +9,14 @@
#include <memory>
#include <utility>
+#include <d3d9.h>
+#include <dxva2api.h>
+
#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.
-#endif // !defined(OS_WIN)
+#include "media/gpu/windows/av1_guids.h"
namespace {
@@ -26,7 +24,7 @@ namespace {
// or earlier, and don't handle resolutions higher than 1920 x 1088 well.
//
// NOTE: This list must be kept in sorted order.
-static const uint16_t kLegacyAmdGpuList[] = {
+constexpr uint16_t kLegacyAmdGpuList[] = {
0x130f, 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707,
0x6708, 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x6720, 0x6721,
0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728, 0x6729, 0x6738,
@@ -67,14 +65,18 @@ static const uint16_t kLegacyAmdGpuList[] = {
// 1920 x 1088 are supported. Updated based on crash reports.
//
// NOTE: This list must be kept in sorted order.
-static const uint16_t kLegacyIntelGpuList[] = {
+constexpr uint16_t kLegacyIntelGpuList[] = {
0x102, 0x106, 0x116, 0x126, 0x152, 0x156, 0x166,
0x402, 0x406, 0x416, 0x41e, 0xa06, 0xa16, 0xf31,
};
-} // namespace
-
-namespace media {
+// 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.
+constexpr gfx::Size kMinResolution(64, 64);
// Certain AMD GPU drivers like R600, R700, Evergreen and Cayman and some second
// generation Intel GPU drivers crash if we create a video device with a
@@ -157,32 +159,12 @@ bool IsResolutionSupportedForDevice(const gfx::Size& resolution_to_test,
config_count > 0;
}
-// Returns a tuple of (LandscapeMax, PortraitMax). If landscape maximum can not
-// be computed, the value of |default_max| is returned for the landscape maximum
-// and a zero size value is returned for portrait max (erring conservatively).
-ResolutionPair GetMaxResolutionsForGUIDs(
- const gfx::Size& default_max,
+media::SupportedResolutionRange GetResolutionsForGUID(
ID3D11VideoDevice* video_device,
- const std::vector<GUID>& valid_guids,
+ const GUID& decoder_guid,
const std::vector<gfx::Size>& resolutions_to_test,
- DXGI_FORMAT format) {
- ResolutionPair result(default_max, gfx::Size());
-
- // Enumerate supported video profiles and look for the profile.
- GUID decoder_guid = GUID_NULL;
- UINT profile_count = video_device->GetVideoDecoderProfileCount();
- for (UINT profile_idx = 0; profile_idx < profile_count; profile_idx++) {
- GUID profile_id = {};
- if (SUCCEEDED(
- video_device->GetVideoDecoderProfile(profile_idx, &profile_id)) &&
- std::find(valid_guids.begin(), valid_guids.end(), profile_id) !=
- valid_guids.end()) {
- decoder_guid = profile_id;
- break;
- }
- }
- if (decoder_guid == GUID_NULL)
- return result;
+ DXGI_FORMAT format = DXGI_FORMAT_NV12) {
+ media::SupportedResolutionRange result;
// Verify input is in ascending order by height.
DCHECK(std::is_sorted(resolutions_to_test.begin(), resolutions_to_test.end(),
@@ -195,32 +177,54 @@ ResolutionPair GetMaxResolutionsForGUIDs(
format)) {
break;
}
- result.first = res;
+ result.max_landscape_resolution = res;
}
// 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 (IsResolutionSupportedForDevice(flipped, decoder_guid, video_device,
+ const gfx::Size flipped(result.max_landscape_resolution.height(),
+ result.max_landscape_resolution.width());
+ if (flipped == result.max_landscape_resolution ||
+ IsResolutionSupportedForDevice(flipped, decoder_guid, video_device,
format)) {
- result.second = flipped;
+ result.max_portrait_resolution = flipped;
}
+ if (!result.max_landscape_resolution.IsEmpty())
+ result.min_resolution = kMinResolution;
+
return result;
}
-// TODO(tmathmeyer) refactor this so that we don'ty call
-// GetMaxResolutionsForGUIDS so many times.
-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");
+} // namespace
+
+namespace media {
+
+SupportedResolutionRangeMap GetSupportedD3D11VideoDecoderResolutions(
+ ComD3D11Device device,
+ const gpu::GpuDriverBugWorkarounds& workarounds) {
+ TRACE_EVENT0("gpu,startup", "GetSupportedD3D11VideoDecoderResolutions");
+ SupportedResolutionRangeMap supported_resolutions;
+
+ // We always insert support for H.264 regardless of the tests below. It's old
+ // enough to be ubiquitous.
+ //
+ // On Windows 7 the maximum resolution supported by media foundation is
+ // 1920 x 1088. We use 1088 to account for 16x16 macro-blocks.
+ constexpr gfx::Size kDefaultMaxH264Resolution(1920, 1088);
+ SupportedResolutionRange h264_profile;
+ h264_profile.min_resolution = kMinResolution;
+ h264_profile.max_landscape_resolution = kDefaultMaxH264Resolution;
+
+ // We don't have a way to map DXVA support to specific H.264 profiles, so just
+ // mark all the common ones with the same level of support.
+ constexpr VideoCodecProfile kSupportedH264Profiles[] = {
+ H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH};
+ for (const auto profile : kSupportedH264Profiles)
+ supported_resolutions[profile] = h264_profile;
+
if (base::win::GetVersion() <= base::win::Version::WIN7)
- return;
+ return supported_resolutions;
// 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
@@ -228,43 +232,99 @@ void GetResolutionsForDecoders(std::vector<GUID> h264_guids,
// 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;
+ return supported_resolutions;
ComD3D11VideoDevice video_device;
if (FAILED(device.As(&video_device)))
- return;
+ return supported_resolutions;
- *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)});
+ const std::vector<gfx::Size> kModernResolutions = {
+ gfx::Size(4096, 2160), gfx::Size(4096, 2304), gfx::Size(7680, 4320),
+ gfx::Size(8192, 4320), gfx::Size(8192, 8192)};
- if (workarounds.disable_accelerated_vpx_decode)
- return;
+ const bool should_test_for_av1_support =
+ base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
+ !workarounds.disable_accelerated_av1_decode;
- 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)});
+ // Enumerate supported video profiles and look for the known profile for each
+ // codec. We first look through the the decoder profiles so we don't run N
+ // resolution tests for a profile that's unsupported.
+ UINT profile_count = video_device->GetVideoDecoderProfileCount();
+ for (UINT i = 0; i < profile_count; i++) {
+ GUID profile_id;
+ if (FAILED(video_device->GetVideoDecoderProfile(i, &profile_id)))
+ continue;
+
+ if (profile_id == D3D11_DECODER_PROFILE_H264_VLD_NOFGT) {
+ const auto result = GetResolutionsForGUID(
+ video_device.Get(), profile_id,
+ {gfx::Size(2560, 1440), gfx::Size(3840, 2160), gfx::Size(4096, 2160),
+ gfx::Size(4096, 2304), gfx::Size(4096, 4096)});
+
+ // Unlike the other codecs, H.264 support is assumed up to 1080p, even if
+ // our initial queries fail. If they fail, we use the defaults set above.
+ if (!result.max_landscape_resolution.IsEmpty()) {
+ for (const auto profile : kSupportedH264Profiles)
+ supported_resolutions[profile] = result;
+ }
+ continue;
+ }
+
+ // Note: Each bit depth of AV1 uses a different DXGI_FORMAT, here we only
+ // test for the 8-bit one (NV12).
+ if (should_test_for_av1_support) {
+ if (profile_id == DXVA_ModeAV1_VLD_Profile0) {
+ supported_resolutions[AV1PROFILE_PROFILE_MAIN] = GetResolutionsForGUID(
+ video_device.Get(), profile_id, kModernResolutions);
+ continue;
+ }
+ if (profile_id == DXVA_ModeAV1_VLD_Profile1) {
+ supported_resolutions[AV1PROFILE_PROFILE_HIGH] = GetResolutionsForGUID(
+ video_device.Get(), profile_id, kModernResolutions);
+ continue;
+ }
+ if (profile_id == DXVA_ModeAV1_VLD_Profile2) {
+ // TODO(dalecurtis): 12-bit profile 2 support is complicated. Ideally,
+ // we should test DXVA_ModeAV1_VLD_12bit_Profile2 and
+ // DXVA_ModeAV1_VLD_12bit_Profile2_420 when the bit depth of the content
+ // is 12-bit. However we don't know the bit depth or pixel format until
+ // too late. In these cases we'll end up initializing the decoder and
+ // failing on the first decode (which will trigger software fallback).
+ supported_resolutions[AV1PROFILE_PROFILE_PRO] = GetResolutionsForGUID(
+ video_device.Get(), profile_id, kModernResolutions);
+ continue;
+ }
+ }
+
+ if (!workarounds.disable_accelerated_vp8_decode &&
+ profile_id == D3D11_DECODER_PROFILE_VP8_VLD &&
+ base::FeatureList::IsEnabled(kMediaFoundationVP8Decoding)) {
+ supported_resolutions[VP8PROFILE_ANY] =
+ GetResolutionsForGUID(video_device.Get(), profile_id,
+ {gfx::Size(4096, 2160), gfx::Size(4096, 2304),
+ gfx::Size(4096, 4096)});
+ continue;
+ }
+
+ if (workarounds.disable_accelerated_vp9_decode)
+ continue;
+
+ if (profile_id == D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0) {
+ supported_resolutions[VP9PROFILE_PROFILE0] = GetResolutionsForGUID(
+ video_device.Get(), profile_id, kModernResolutions);
+ continue;
+ }
+
+ // RS3 has issues with VP9.2 decoding. See https://crbug.com/937108.
+ if (profile_id == D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2 &&
+ base::win::GetVersion() != base::win::Version::WIN10_RS3) {
+ supported_resolutions[VP9PROFILE_PROFILE2] = GetResolutionsForGUID(
+ video_device.Get(), profile_id, kModernResolutions, DXGI_FORMAT_P010);
+ continue;
+ }
}
- *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);
+ return supported_resolutions;
}
} // namespace media
diff --git a/chromium/media/gpu/windows/supported_profile_helpers.h b/chromium/media/gpu/windows/supported_profile_helpers.h
index 1834f0ba62a..6e521d08ff6 100644
--- a/chromium/media/gpu/windows/supported_profile_helpers.h
+++ b/chromium/media/gpu/windows/supported_profile_helpers.h
@@ -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
diff --git a/chromium/media/gpu/windows/supported_profile_helpers_unittest.cc b/chromium/media/gpu/windows/supported_profile_helpers_unittest.cc
index 67aeb7d45b8..0d5da5b6e47 100644
--- a/chromium/media/gpu/windows/supported_profile_helpers_unittest.cc
+++ b/chromium/media/gpu/windows/supported_profile_helpers_unittest.cc
@@ -15,6 +15,7 @@
#include "media/base/media_switches.h"
#include "media/base/test_helpers.h"
#include "media/base/win/d3d11_mocks.h"
+#include "media/gpu/windows/av1_guids.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
@@ -31,25 +32,28 @@ using ::testing::WithArgs;
return; \
} while (0)
-HRESULT SetIfSizeLessThan(D3D11_VIDEO_DECODER_DESC* desc, UINT* count) {
- *count = 1;
- return S_OK;
-}
+namespace {
+
+using PciId = std::pair<uint16_t, uint16_t>;
+constexpr PciId kLegacyIntelGpu = {0x8086, 0x102};
+constexpr PciId kRecentIntelGpu = {0x8086, 0x100};
+constexpr PciId kLegacyAmdGpu = {0x1022, 0x130f};
+constexpr PciId kRecentAmdGpu = {0x1022, 0x130e};
+
+constexpr gfx::Size kMinResolution(64, 64);
+constexpr gfx::Size kFullHd(1920, 1088);
+constexpr gfx::Size kSquare4k(4096, 4096);
+constexpr gfx::Size kSquare8k(8192, 8192);
+
+} // namespace
namespace media {
+constexpr VideoCodecProfile kSupportedH264Profiles[] = {
+ H264PROFILE_BASELINE, H264PROFILE_MAIN, H264PROFILE_HIGH};
+
class SupportedResolutionResolverTest : public ::testing::Test {
public:
- const std::pair<uint16_t, uint16_t> LegacyIntelGPU = {0x8086, 0x102};
- const std::pair<uint16_t, uint16_t> RecentIntelGPU = {0x8086, 0x100};
- const std::pair<uint16_t, uint16_t> LegacyAMDGPU = {0x1022, 0x130f};
- const std::pair<uint16_t, uint16_t> RecentAMDGPU = {0x1022, 0x130e};
-
- const ResolutionPair ten_eighty = {{1920, 1080}, {1080, 1920}};
- const ResolutionPair zero = {{0, 0}, {0, 0}};
- const ResolutionPair tall4k = {{4096, 2304}, {2304, 4096}};
- const ResolutionPair eightKsquare = {{8192, 8192}, {8192, 8192}};
-
void SetUp() override {
gpu_workarounds_.disable_dxgi_zero_copy_video = false;
mock_d3d11_device_ = CreateD3D11Mock<NiceMock<D3D11DeviceMock>>();
@@ -68,11 +72,11 @@ class SupportedResolutionResolverTest : public ::testing::Test {
ON_CALL(*mock_dxgi_device_.Get(), GetAdapter(_))
.WillByDefault(SetComPointeeAndReturnOk<0>(mock_dxgi_adapter_.Get()));
- SetGPUProfile(RecentIntelGPU);
- SetMaxResolutionForGUID(D3D11_DECODER_PROFILE_H264_VLD_NOFGT, {4096, 4096});
+ SetGpuProfile(kRecentIntelGpu);
+ SetMaxResolution(D3D11_DECODER_PROFILE_H264_VLD_NOFGT, kSquare4k);
}
- void SetMaxResolutionForGUID(const GUID& g, const gfx::Size& max_res) {
+ void SetMaxResolution(const GUID& g, const gfx::Size& max_res) {
max_size_for_guids_[g] = max_res;
ON_CALL(*mock_d3d11_video_device_.Get(), GetVideoDecoderConfigCount(_, _))
.WillByDefault(
@@ -110,7 +114,7 @@ class SupportedResolutionResolverTest : public ::testing::Test {
})));
}
- void SetGPUProfile(std::pair<uint16_t, uint16_t> vendor_and_gpu) {
+ void SetGpuProfile(std::pair<uint16_t, uint16_t> vendor_and_gpu) {
mock_adapter_desc_.DeviceId = static_cast<UINT>(vendor_and_gpu.second);
mock_adapter_desc_.VendorId = static_cast<UINT>(vendor_and_gpu.first);
@@ -119,6 +123,39 @@ class SupportedResolutionResolverTest : public ::testing::Test {
DoAll(SetArgPointee<0>(mock_adapter_desc_), Return(S_OK)));
}
+ void AssertDefaultSupport(
+ const SupportedResolutionRangeMap& supported_resolutions,
+ size_t expected_size = 3u) {
+ ASSERT_EQ(expected_size, supported_resolutions.size());
+ for (const auto profile : kSupportedH264Profiles) {
+ auto it = supported_resolutions.find(profile);
+ ASSERT_NE(it, supported_resolutions.end());
+ EXPECT_EQ(kMinResolution, it->second.min_resolution);
+ EXPECT_EQ(kFullHd, it->second.max_landscape_resolution);
+ EXPECT_EQ(gfx::Size(), it->second.max_portrait_resolution);
+ }
+ }
+
+ void TestDecoderSupport(const GUID& decoder,
+ VideoCodecProfile profile,
+ const gfx::Size& max_res = kSquare4k,
+ const gfx::Size& max_landscape_res = kSquare4k,
+ const gfx::Size& max_portrait_res = kSquare4k) {
+ EnableDecoders({decoder});
+ SetMaxResolution(decoder, max_res);
+
+ const auto supported_resolutions = GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_);
+ AssertDefaultSupport(supported_resolutions,
+ base::size(kSupportedH264Profiles) + 1);
+
+ auto it = supported_resolutions.find(profile);
+ ASSERT_NE(it, supported_resolutions.end());
+ EXPECT_EQ(kMinResolution, it->second.min_resolution);
+ EXPECT_EQ(max_landscape_res, it->second.max_landscape_resolution);
+ EXPECT_EQ(max_portrait_res, it->second.max_portrait_resolution);
+ }
+
Microsoft::WRL::ComPtr<D3D11DeviceMock> mock_d3d11_device_;
Microsoft::WRL::ComPtr<DXGIAdapterMock> mock_dxgi_adapter_;
Microsoft::WRL::ComPtr<DXGIDeviceMock> mock_dxgi_device_;
@@ -131,144 +168,128 @@ class SupportedResolutionResolverTest : public ::testing::Test {
return memcmp(&a, &b, sizeof(GUID)) < 0;
}
};
- std::map<GUID, gfx::Size, GUIDComparison> max_size_for_guids_;
+ base::flat_map<GUID, gfx::Size, GUIDComparison> max_size_for_guids_;
};
-TEST_F(SupportedResolutionResolverTest, NoDeviceAllDefault) {
+TEST_F(SupportedResolutionResolverTest, HasH264SupportByDefault) {
DONT_RUN_ON_WIN_7();
+ AssertDefaultSupport(
+ GetSupportedD3D11VideoDecoderResolutions(nullptr, gpu_workarounds_));
- 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, &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);
-}
-
-TEST_F(SupportedResolutionResolverTest, LegacyGPUAllDefault) {
- DONT_RUN_ON_WIN_7();
+ SetGpuProfile(kLegacyIntelGpu);
+ AssertDefaultSupport(GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_));
- SetGPUProfile(LegacyIntelGPU);
-
- 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,
- &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);
+ SetGpuProfile(kLegacyAmdGpu);
+ AssertDefaultSupport(GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_));
}
TEST_F(SupportedResolutionResolverTest, WorkaroundsDisableVpx) {
DONT_RUN_ON_WIN_7();
- gpu_workarounds_.disable_dxgi_zero_copy_video = true;
- EnableDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT});
+ gpu_workarounds_.disable_accelerated_vp8_decode = true;
+ gpu_workarounds_.disable_accelerated_vp9_decode = true;
+ EnableDecoders({D3D11_DECODER_PROFILE_VP8_VLD,
+ D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0,
+ D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2});
- 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);
+ AssertDefaultSupport(GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_));
+}
- ASSERT_EQ(h264_res, tall4k);
+TEST_F(SupportedResolutionResolverTest, H264Supports4k) {
+ DONT_RUN_ON_WIN_7();
- ASSERT_EQ(vp8_res, zero);
- ASSERT_EQ(vp9_0_res, zero);
- ASSERT_EQ(vp9_2_res, zero);
+ EnableDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT});
+ const auto supported_resolutions = GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_);
+
+ ASSERT_EQ(3u, supported_resolutions.size());
+ for (const auto profile : kSupportedH264Profiles) {
+ auto it = supported_resolutions.find(profile);
+ ASSERT_NE(it, supported_resolutions.end());
+ EXPECT_EQ(kMinResolution, it->second.min_resolution);
+ EXPECT_EQ(kSquare4k, it->second.max_landscape_resolution);
+ EXPECT_EQ(kSquare4k, it->second.max_portrait_resolution);
+ }
}
-TEST_F(SupportedResolutionResolverTest, VP8_Supports4k) {
+TEST_F(SupportedResolutionResolverTest, VP8Supports4k) {
DONT_RUN_ON_WIN_7();
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(kMediaFoundationVP8Decoding);
+ TestDecoderSupport(D3D11_DECODER_PROFILE_VP8_VLD, VP8PROFILE_ANY);
+}
- 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);
+TEST_F(SupportedResolutionResolverTest, VP9Profile0Supports8k) {
+ DONT_RUN_ON_WIN_7();
+ TestDecoderSupport(D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0,
+ VP9PROFILE_PROFILE0, kSquare8k, kSquare8k, kSquare8k);
+}
- ASSERT_EQ(vp9_2_res, zero);
+TEST_F(SupportedResolutionResolverTest, VP9Profile2Supports8k) {
+ DONT_RUN_ON_WIN_7();
+ TestDecoderSupport(D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2,
+ VP9PROFILE_PROFILE2, kSquare8k, kSquare8k, kSquare8k);
}
-TEST_F(SupportedResolutionResolverTest, VP9_0Supports8k) {
+TEST_F(SupportedResolutionResolverTest, MultipleCodecs) {
DONT_RUN_ON_WIN_7();
+ SetGpuProfile(kRecentAmdGpu);
+
+ // H.264 and VP9.0 are the most common supported codecs.
EnableDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT,
D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0});
- 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,
- &vp8_res, &vp9_0_res, &vp9_2_res);
-
- ASSERT_EQ(h264_res, tall4k);
-
- ASSERT_EQ(vp8_res, zero);
-
- ASSERT_EQ(vp9_0_res, eightKsquare);
+ SetMaxResolution(D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, kSquare8k);
+
+ const auto supported_resolutions = GetSupportedD3D11VideoDecoderResolutions(
+ mock_d3d11_device_, gpu_workarounds_);
+
+ ASSERT_EQ(base::size(kSupportedH264Profiles) + 1,
+ supported_resolutions.size());
+ for (const auto profile : kSupportedH264Profiles) {
+ auto it = supported_resolutions.find(profile);
+ ASSERT_NE(it, supported_resolutions.end());
+ EXPECT_EQ(kMinResolution, it->second.min_resolution);
+ EXPECT_EQ(kSquare4k, it->second.max_landscape_resolution);
+ EXPECT_EQ(kSquare4k, it->second.max_portrait_resolution);
+ }
- ASSERT_EQ(vp9_2_res, zero);
+ auto it = supported_resolutions.find(VP9PROFILE_PROFILE0);
+ ASSERT_NE(it, supported_resolutions.end());
+ EXPECT_EQ(kMinResolution, it->second.min_resolution);
+ EXPECT_EQ(kSquare8k, it->second.max_landscape_resolution);
+ EXPECT_EQ(kSquare8k, it->second.max_portrait_resolution);
}
-TEST_F(SupportedResolutionResolverTest, BothVP9ProfilesSupported) {
+TEST_F(SupportedResolutionResolverTest, AV1ProfileMainSupports8k) {
DONT_RUN_ON_WIN_7();
- EnableDecoders({D3D11_DECODER_PROFILE_H264_VLD_NOFGT,
- D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0,
- D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2});
- SetMaxResolutionForGUID(D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, {8192, 8192});
- SetMaxResolutionForGUID(D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2,
- {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,
- &vp8_res, &vp9_0_res, &vp9_2_res);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(kMediaFoundationAV1Decoding);
+ TestDecoderSupport(DXVA_ModeAV1_VLD_Profile0, AV1PROFILE_PROFILE_MAIN,
+ kSquare8k, kSquare8k, kSquare8k);
+}
- ASSERT_EQ(h264_res, tall4k);
+TEST_F(SupportedResolutionResolverTest, AV1ProfileHighSupports8k) {
+ DONT_RUN_ON_WIN_7();
- ASSERT_EQ(vp8_res, zero);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(kMediaFoundationAV1Decoding);
+ TestDecoderSupport(DXVA_ModeAV1_VLD_Profile1, AV1PROFILE_PROFILE_HIGH,
+ kSquare8k, kSquare8k, kSquare8k);
+}
- ASSERT_EQ(vp9_0_res, eightKsquare);
+TEST_F(SupportedResolutionResolverTest, AV1ProfileProSupports8k) {
+ DONT_RUN_ON_WIN_7();
- ASSERT_EQ(vp9_2_res, eightKsquare);
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(kMediaFoundationAV1Decoding);
+ TestDecoderSupport(DXVA_ModeAV1_VLD_Profile2, AV1PROFILE_PROFILE_PRO,
+ kSquare8k, kSquare8k, kSquare8k);
}
} // namespace media