Commit f2d7b53c authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Commit Bot

H265 VAAPI Accelerator

This adds the VAAPI accelerator delegate for H265 decoding. This is not
actually enabled yet because there are other pieces higher up in the
decoding pipeline that still need to be turned on.

BUG=chromium:1141237,b:153111783
TEST=HEVC playback works w/ full set of changes, vaapi_unittest

Change-Id: Ic0a2dbe774267d4852e0d4d47aa378c6602ad41f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530798Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarSergey Volk <servolk@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Cr-Commit-Position: refs/heads/master@{#827050}
parent ca6c8879
...@@ -16,6 +16,10 @@ H265Picture::~H265Picture() = default; ...@@ -16,6 +16,10 @@ H265Picture::~H265Picture() = default;
H265DPB::H265DPB() = default; H265DPB::H265DPB() = default;
H265DPB::~H265DPB() = default; H265DPB::~H265DPB() = default;
VaapiH265Picture* H265Picture::AsVaapiH265Picture() {
return nullptr;
}
void H265DPB::set_max_num_pics(size_t max_num_pics) { void H265DPB::set_max_num_pics(size_t max_num_pics) {
DCHECK_LE(max_num_pics, static_cast<size_t>(kMaxDpbSize)); DCHECK_LE(max_num_pics, static_cast<size_t>(kMaxDpbSize));
max_num_pics_ = max_num_pics; max_num_pics_ = max_num_pics;
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
namespace media { namespace media {
class VaapiH265Picture;
// A picture (a frame or a field) in the H.265 spec sense. // A picture (a frame or a field) in the H.265 spec sense.
// See spec at http://www.itu.int/rec/T-REC-H.265 // See spec at http://www.itu.int/rec/T-REC-H.265
class MEDIA_GPU_EXPORT H265Picture : public CodecPicture { class MEDIA_GPU_EXPORT H265Picture : public CodecPicture {
...@@ -25,6 +27,8 @@ class MEDIA_GPU_EXPORT H265Picture : public CodecPicture { ...@@ -25,6 +27,8 @@ class MEDIA_GPU_EXPORT H265Picture : public CodecPicture {
H265Picture(const H265Picture&) = delete; H265Picture(const H265Picture&) = delete;
H265Picture& operator=(const H265Picture&) = delete; H265Picture& operator=(const H265Picture&) = delete;
virtual VaapiH265Picture* AsVaapiH265Picture();
enum ReferenceType { enum ReferenceType {
kUnused = 0, kUnused = 0,
kShortTermCurrBefore = 1, kShortTermCurrBefore = 1,
......
...@@ -6,6 +6,7 @@ import("//build/config/chromeos/ui_mode.gni") ...@@ -6,6 +6,7 @@ import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni") import("//build/config/features.gni")
import("//build/config/ui.gni") import("//build/config/ui.gni")
import("//media/gpu/args.gni") import("//media/gpu/args.gni")
import("//media/media_options.gni")
import("//testing/test.gni") import("//testing/test.gni")
import("//tools/generate_stubs/rules.gni") import("//tools/generate_stubs/rules.gni")
import("//ui/gl/features.gni") import("//ui/gl/features.gni")
...@@ -71,6 +72,12 @@ source_set("vaapi") { ...@@ -71,6 +72,12 @@ source_set("vaapi") {
"vp9_vaapi_video_decoder_delegate.cc", "vp9_vaapi_video_decoder_delegate.cc",
"vp9_vaapi_video_decoder_delegate.h", "vp9_vaapi_video_decoder_delegate.h",
] ]
if (proprietary_codecs && enable_platform_hevc) {
sources += [
"h265_vaapi_video_decoder_delegate.cc",
"h265_vaapi_video_decoder_delegate.h",
]
}
configs += [ configs += [
"//build/config/linux/libva", "//build/config/linux/libva",
...@@ -80,6 +87,7 @@ source_set("vaapi") { ...@@ -80,6 +87,7 @@ source_set("vaapi") {
deps = [ deps = [
":common", ":common",
"//base", "//base",
"//build:chromeos_buildflags",
"//gpu/config", "//gpu/config",
"//gpu/ipc/common", "//gpu/ipc/common",
"//gpu/ipc/service", "//gpu/ipc/service",
......
This diff is collapsed.
// 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_VAAPI_H265_VAAPI_VIDEO_DECODER_DELEGATE_H_
#define MEDIA_GPU_VAAPI_H265_VAAPI_VIDEO_DECODER_DELEGATE_H_
#include <va/va.h>
#include "base/memory/scoped_refptr.h"
#include "media/gpu/h265_decoder.h"
#include "media/gpu/h265_dpb.h"
#include "media/gpu/vaapi/vaapi_video_decoder_delegate.h"
#include "media/video/h265_parser.h"
// Verbatim from va/va.h, where typedef is used.
typedef struct _VAPictureHEVC VAPictureHEVC;
namespace media {
class H265Picture;
class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
public VaapiVideoDecoderDelegate {
public:
H265VaapiVideoDecoderDelegate(DecodeSurfaceHandler<VASurface>* vaapi_dec,
scoped_refptr<VaapiWrapper> vaapi_wrapper);
H265VaapiVideoDecoderDelegate(const H265VaapiVideoDecoderDelegate&) = delete;
H265VaapiVideoDecoderDelegate& operator=(
const H265VaapiVideoDecoderDelegate&) = delete;
~H265VaapiVideoDecoderDelegate() override;
// H265Decoder::H265Accelerator implementation.
scoped_refptr<H265Picture> CreateH265Picture() override;
Status SubmitFrameMetadata(const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr,
const H265Picture::Vector& ref_pic_list,
scoped_refptr<H265Picture> pic) override;
Status SubmitSlice(const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr,
const H265Picture::Vector& ref_pic_list0,
const H265Picture::Vector& ref_pic_list1,
scoped_refptr<H265Picture> pic,
const uint8_t* data,
size_t size,
const std::vector<SubsampleEntry>& subsamples) override;
Status SubmitDecode(scoped_refptr<H265Picture> pic) override;
bool OutputPicture(scoped_refptr<H265Picture> pic) override;
void Reset() override;
private:
void FillVAPicture(VAPictureHEVC* va_pic, scoped_refptr<H265Picture> pic);
void FillVARefFramesFromRefList(const H265Picture::Vector& ref_pic_list,
VAPictureHEVC* va_pics);
// Returns |kInvalidRefPicIndex| if it cannot find a picture.
int GetRefPicIndex(int poc);
// Submits the slice data to the decoder for the prior slice that was just
// submitted to us. This allows us to handle multi-slice pictures properly.
// |last_slice| is set to true when submitting the last slice, false
// otherwise.
bool SubmitPriorSliceDataIfPresent(bool last_slice);
// Stores the POCs (picture order counts) in the ReferenceFrames submitted as
// the frame metadata so we can determine the indices for the reference frames
// in the slice metadata.
std::vector<int> ref_pic_list_pocs_;
// Data from the prior/current slice for handling multi slice so we can
// properly set the flag for the last slice.
VASliceParameterBufferHEVC slice_param_;
// We can hold onto the slice data pointer because we process all frames as
// one DecoderBuffer, so the memory will still be accessible until the frame
// is done. |last_slice_data_| being non-null indicates we have a valid
// |slice_param_| filled.
const uint8_t* last_slice_data_{nullptr};
size_t last_slice_size_{0};
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_H265_VAAPI_VIDEO_DECODER_DELEGATE_H_
...@@ -9,16 +9,27 @@ namespace media { ...@@ -9,16 +9,27 @@ namespace media {
VaapiH264Picture::VaapiH264Picture(scoped_refptr<VASurface> va_surface) VaapiH264Picture::VaapiH264Picture(scoped_refptr<VASurface> va_surface)
: va_surface_(va_surface) {} : va_surface_(va_surface) {}
VaapiH264Picture::~VaapiH264Picture() {} VaapiH264Picture::~VaapiH264Picture() = default;
VaapiH264Picture* VaapiH264Picture::AsVaapiH264Picture() { VaapiH264Picture* VaapiH264Picture::AsVaapiH264Picture() {
return this; return this;
} }
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
VaapiH265Picture::VaapiH265Picture(scoped_refptr<VASurface> va_surface)
: va_surface_(va_surface) {}
VaapiH265Picture::~VaapiH265Picture() = default;
VaapiH265Picture* VaapiH265Picture::AsVaapiH265Picture() {
return this;
}
#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
VaapiVP8Picture::VaapiVP8Picture(scoped_refptr<VASurface> va_surface) VaapiVP8Picture::VaapiVP8Picture(scoped_refptr<VASurface> va_surface)
: va_surface_(va_surface) {} : va_surface_(va_surface) {}
VaapiVP8Picture::~VaapiVP8Picture() {} VaapiVP8Picture::~VaapiVP8Picture() = default;
VaapiVP8Picture* VaapiVP8Picture::AsVaapiVP8Picture() { VaapiVP8Picture* VaapiVP8Picture::AsVaapiVP8Picture() {
return this; return this;
...@@ -27,7 +38,7 @@ VaapiVP8Picture* VaapiVP8Picture::AsVaapiVP8Picture() { ...@@ -27,7 +38,7 @@ VaapiVP8Picture* VaapiVP8Picture::AsVaapiVP8Picture() {
VaapiVP9Picture::VaapiVP9Picture(scoped_refptr<VASurface> va_surface) VaapiVP9Picture::VaapiVP9Picture(scoped_refptr<VASurface> va_surface)
: va_surface_(va_surface) {} : va_surface_(va_surface) {}
VaapiVP9Picture::~VaapiVP9Picture() {} VaapiVP9Picture::~VaapiVP9Picture() = default;
VaapiVP9Picture* VaapiVP9Picture::AsVaapiVP9Picture() { VaapiVP9Picture* VaapiVP9Picture::AsVaapiVP9Picture() {
return this; return this;
......
...@@ -8,6 +8,11 @@ ...@@ -8,6 +8,11 @@
#include "media/gpu/vaapi/va_surface.h" #include "media/gpu/vaapi/va_surface.h"
#include "media/gpu/vp8_picture.h" #include "media/gpu/vp8_picture.h"
#include "media/gpu/vp9_picture.h" #include "media/gpu/vp9_picture.h"
#include "media/media_buildflags.h"
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
#include "media/gpu/h265_dpb.h"
#endif
namespace media { namespace media {
...@@ -33,6 +38,27 @@ class VaapiH264Picture : public H264Picture { ...@@ -33,6 +38,27 @@ class VaapiH264Picture : public H264Picture {
DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture); DISALLOW_COPY_AND_ASSIGN(VaapiH264Picture);
}; };
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
class VaapiH265Picture : public H265Picture {
public:
explicit VaapiH265Picture(scoped_refptr<VASurface> va_surface);
VaapiH265Picture(const VaapiH265Picture&) = delete;
VaapiH265Picture& operator=(const VaapiH265Picture&) = delete;
VaapiH265Picture* AsVaapiH265Picture() override;
scoped_refptr<VASurface> va_surface() const { return va_surface_; }
VASurfaceID GetVASurfaceID() const { return va_surface_->id(); }
protected:
~VaapiH265Picture() override;
private:
scoped_refptr<VASurface> va_surface_;
};
#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
class VaapiVP8Picture : public VP8Picture { class VaapiVP8Picture : public VP8Picture {
public: public:
explicit VaapiVP8Picture(scoped_refptr<VASurface> va_surface); explicit VaapiVP8Picture(scoped_refptr<VASurface> va_surface);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "build/chromeos_buildflags.h" #include "build/chromeos_buildflags.h"
#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/gpu/vaapi/vaapi_wrapper.h" #include "media/gpu/vaapi/vaapi_wrapper.h"
#include "media/media_buildflags.h"
namespace media { namespace media {
namespace { namespace {
...@@ -44,6 +45,9 @@ base::Optional<VAProfile> ConvertToVAProfile(VideoCodecProfile profile) { ...@@ -44,6 +45,9 @@ base::Optional<VAProfile> ConvertToVAProfile(VideoCodecProfile profile) {
// 2.9.0 or newer. // 2.9.0 or newer.
// https://source.chromium.org/chromium/chromium/src/+/master:build/linux/sysroot_scripts/generated_package_lists/sid.amd64 // https://source.chromium.org/chromium/chromium/src/+/master:build/linux/sysroot_scripts/generated_package_lists/sid.amd64
{AV1PROFILE_PROFILE_MAIN, VAProfileAV1Profile0}, {AV1PROFILE_PROFILE_MAIN, VAProfileAV1Profile0},
#endif
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
{HEVCPROFILE_MAIN, VAProfileHEVCMain},
#endif #endif
}; };
auto it = kProfileMap.find(profile); auto it = kProfileMap.find(profile);
...@@ -70,6 +74,9 @@ base::Optional<VAProfile> StringToVAProfile(const std::string& va_profile) { ...@@ -70,6 +74,9 @@ base::Optional<VAProfile> StringToVAProfile(const std::string& va_profile) {
// 2.9.0 or newer. // 2.9.0 or newer.
// https://source.chromium.org/chromium/chromium/src/+/master:build/linux/sysroot_scripts/generated_package_lists/sid.amd64 // https://source.chromium.org/chromium/chromium/src/+/master:build/linux/sysroot_scripts/generated_package_lists/sid.amd64
{"VAProfileAV1Profile0", VAProfileAV1Profile0}, {"VAProfileAV1Profile0", VAProfileAV1Profile0},
#endif
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
{"VAProfileHEVCMain", VAProfileHEVCMain},
#endif #endif
}; };
......
...@@ -28,6 +28,10 @@ ...@@ -28,6 +28,10 @@
#include "media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.h" #include "media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
#include "media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h"
#endif
namespace media { namespace media {
namespace { namespace {
...@@ -639,6 +643,15 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() { ...@@ -639,6 +643,15 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
decoder_.reset( decoder_.reset(
new VP9Decoder(std::move(accelerator), profile_, color_space_)); new VP9Decoder(std::move(accelerator), profile_, color_space_));
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
} else if (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX) {
auto accelerator =
std::make_unique<H265VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
decoder_delegate_ = accelerator.get();
decoder_.reset(
new H265Decoder(std::move(accelerator), profile_, color_space_));
#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC)
} else { } else {
return Status(StatusCode::kDecoderUnsupportedProfile) return Status(StatusCode::kDecoderUnsupportedProfile)
.WithData("profile", profile_); .WithData("profile", profile_);
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/base/video_types.h" #include "media/base/video_types.h"
#include "media/gpu/macros.h" #include "media/gpu/macros.h"
#include "media/media_buildflags.h"
// Auto-generated for dlopen libva libraries // Auto-generated for dlopen libva libraries
#include "media/gpu/vaapi/va_stubs.h" #include "media/gpu/vaapi/va_stubs.h"
...@@ -362,6 +363,9 @@ const ProfileCodecMap& GetProfileCodecMap() { ...@@ -362,6 +363,9 @@ const ProfileCodecMap& GetProfileCodecMap() {
#endif // BUILDFLAG(IS_ASH) #endif // BUILDFLAG(IS_ASH)
// VaapiWrapper does not support AV1 Profile 1. // VaapiWrapper does not support AV1 Profile 1.
// {AV1PROFILE_PROFILE_HIGH, VAProfileAV1Profile1}, // {AV1PROFILE_PROFILE_HIGH, VAProfileAV1Profile1},
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
{HEVCPROFILE_MAIN, VAProfileHEVCMain},
#endif
}); });
return *kMediaToVAProfileMap; return *kMediaToVAProfileMap;
} }
......
...@@ -147,18 +147,19 @@ struct MEDIA_EXPORT H265ScalingListData { ...@@ -147,18 +147,19 @@ struct MEDIA_EXPORT H265ScalingListData {
kDefaultScalingListSize0Values = 16, // Table 7-5, all values are 16 kDefaultScalingListSize0Values = 16, // Table 7-5, all values are 16
kScalingListSizeId0Count = 16, // 7.4.5 kScalingListSizeId0Count = 16, // 7.4.5
kScalingListSizeId1To3Count = 64, // 7.4.5 kScalingListSizeId1To3Count = 64, // 7.4.5
kNumScalingListMatrices = 6,
}; };
// TODO(jkardatzke): Optimize storage of the 32x32 since only indices 0 and 3 // TODO(jkardatzke): Optimize storage of the 32x32 since only indices 0 and 3
// are actually used. Also change it in the accelerator delegate if that is // are actually used. Also change it in the accelerator delegate if that is
// done. // done.
// Syntax elements. // Syntax elements.
int scaling_list_dc_coef_16x16[6]; int scaling_list_dc_coef_16x16[kNumScalingListMatrices];
int scaling_list_dc_coef_32x32[6]; int scaling_list_dc_coef_32x32[kNumScalingListMatrices];
int scaling_list_4x4[6][kScalingListSizeId0Count]; int scaling_list_4x4[kNumScalingListMatrices][kScalingListSizeId0Count];
int scaling_list_8x8[6][kScalingListSizeId1To3Count]; int scaling_list_8x8[kNumScalingListMatrices][kScalingListSizeId1To3Count];
int scaling_list_16x16[6][kScalingListSizeId1To3Count]; int scaling_list_16x16[kNumScalingListMatrices][kScalingListSizeId1To3Count];
int scaling_list_32x32[6][kScalingListSizeId1To3Count]; int scaling_list_32x32[kNumScalingListMatrices][kScalingListSizeId1To3Count];
}; };
struct MEDIA_EXPORT H265StRefPicSet { struct MEDIA_EXPORT H265StRefPicSet {
......
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