// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/d3d11_h265_accelerator.h"
#include <algorithm>
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/ranges/algorithm.h"
#include "base/trace_event/trace_event.h"
#include "media/base/win/mf_helpers.h"
#include "media/gpu/windows/d3d11_picture_buffer.h"
#include "media/media_buildflags.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"
namespace media {
namespace {
using H265DecoderStatus = H265Decoder::H265Accelerator::Status;
} // namespace
class D3D11H265Picture : public H265Picture {
public:
D3D11H265Picture(D3D11PictureBuffer* picture)
: picture(picture), picture_index_(picture->picture_index()) {
picture->set_in_picture_use(true);
}
raw_ptr<D3D11PictureBuffer> picture;
size_t picture_index_;
D3D11H265Picture* AsD3D11H265Picture() override { return this; }
protected:
~D3D11H265Picture() override;
};
D3D11H265Picture::~D3D11H265Picture() {
picture->set_in_picture_use(false);
}
D3D11H265Accelerator::D3D11H265Accelerator(D3D11VideoDecoderClient* client,
MediaLog* media_log)
: media_log_(media_log->Clone()), client_(client) {
DCHECK(client_);
}
D3D11H265Accelerator::~D3D11H265Accelerator() {}
scoped_refptr<H265Picture> D3D11H265Accelerator::CreateH265Picture() {
D3D11PictureBuffer* picture = client_->GetPicture();
if (!picture) {
return nullptr;
}
return base::MakeRefCounted<D3D11H265Picture>(picture);
}
bool D3D11H265Accelerator::IsChromaSamplingSupported(
VideoChromaSampling chroma_sampling) {
return chroma_sampling == VideoChromaSampling::k420 ||
chroma_sampling == VideoChromaSampling::k422 ||
chroma_sampling == VideoChromaSampling::k444;
}
H265DecoderStatus D3D11H265Accelerator::SubmitFrameMetadata(
const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr,
const H265Picture::Vector& ref_pic_list,
const H265Picture::Vector& ref_pic_set_lt_curr,
const H265Picture::Vector& ref_pic_set_st_curr_after,
const H265Picture::Vector& ref_pic_set_st_curr_before,
scoped_refptr<H265Picture> pic) {
D3D11H265Picture* d3d11_pic = pic->AsD3D11H265Picture();
if (!d3d11_pic) {
return H265DecoderStatus::kFail;
}
if (!client_->GetWrapper()->WaitForFrameBegins(d3d11_pic->picture.get())) {
return H265DecoderStatus::kFail;
}
use_scaling_lists_ = sps->scaling_list_enabled_flag;
poc_index_into_ref_pic_list_.clear();
for (size_t i = 0; i < media::kMaxRefPicListSize; i++) {
ref_frame_list_[i].bPicEntry = 0xFF;
ref_frame_pocs_[i] = 0;
}
// |ref_pic_list| contains the set of pictures as described
// in HEVC spec section 8.3.2, from the lists RefPicSetLtCurr,
// RefPicSetLtFoll, RefPicSetStCurrBefore, RefPicSetStCurrAfter
// and RefPicSetStFoll. When submitting a slice, will use information
// in ref_pic_list0 and ref_pic_list1 to fill POCs of corresponding
// list in picture param.
if (ref_pic_list.size() > kMaxRefPicListSize) {
DLOG(ERROR) << "Invalid fef pic list size.";
return H265DecoderStatus::kFail;
}
int i = 0;
for (auto& it : ref_pic_list) {
if (!it)
continue;
D3D11H265Picture* our_ref_pic = it->AsD3D11H265Picture();
if (!our_ref_pic)
continue;
ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_;
ref_frame_list_[i].AssociatedFlag = our_ref_pic->IsLongTermRef();
ref_frame_pocs_[i] = our_ref_pic->pic_order_cnt_val_;
poc_index_into_ref_pic_list_[our_ref_pic->pic_order_cnt_val_] = i;
i++;
}
return H265DecoderStatus::kOk;
}
void D3D11H265Accelerator::FillPicParamsWithConstants(
DXVA_PicParams_HEVC_Rext* pic) {
// According to DXVA spec section 2.2, this optional 1-bit flag
// has no meaning when used for CurrPic so always configure to 0.
pic->main.CurrPic.AssociatedFlag = 0;
// num_tile_columns_minus1 and num_tile_rows_minus1 will only
// be set if tiles are enabled. Set to 0 by default.
pic->main.num_tile_columns_minus1 = 0;
pic->main.num_tile_rows_minus1 = 0;
// Host decoder may set this to 1 if sps_max_num_reorder_pics is 0,
// but there is no requirement that NoPicReorderingFlag must be
// derived from it. So we always set it to 0 here.
pic->main.NoPicReorderingFlag = 0;
// Must be set to 0 in absence of indication whether B slices are used
// or not, and it does not affect the decoding process.
pic->main.NoBiPredFlag = 0;
// Shall be set to 0 and accelerators shall ignore its value.
pic->main.ReservedBits1 = 0;
// Bit field added to enable DWORD alignment and should be set to 0.
pic->main.ReservedBits2 = 0;
// Should always be set to 0.
pic->main.ReservedBits3 = 0;
// Should be set to 0 and ignored by accelerators
pic->main.ReservedBits4 = 0;
// Should always be set to 0.
pic->main.ReservedBits5 = 0;
// Should always be set to 0.
pic->main.ReservedBits6 = 0;
// Should always be set to 0.
pic->main.ReservedBits7 = 0;
}
#define ARG_SEL(_1, _2, NAME, ...) NAME
#define SPS_TO_PP1(a) (pic_param->main).a = sps->a;
#define SPS_TO_PPEXT(a) pic_param->a = sps->a;
#define SPS_TO_PP2(a, b) (pic_param->main).a = sps->b;
#define SPS_TO_PP(...) ARG_SEL(__VA_ARGS__, SPS_TO_PP2, SPS_TO_PP1)(__VA_ARGS__)
void D3D11H265Accelerator::PicParamsFromSPS(DXVA_PicParams_HEVC_Rext* pic_param,
const H265SPS* sps) {
// Refer to formula 7-14 and 7-16 of HEVC spec.
int min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3;
(pic_param->main).PicWidthInMinCbsY =
sps->pic_width_in_luma_samples >> min_cb_log2_size_y;
(pic_param->main).PicHeightInMinCbsY =
sps->pic_height_in_luma_samples >> min_cb_log2_size_y;
// wFormatAndSequenceInfoFlags from SPS
SPS_TO_PP(chroma_format_idc);
SPS_TO_PP(separate_colour_plane_flag);
SPS_TO_PP(bit_depth_luma_minus8);
SPS_TO_PP(bit_depth_chroma_minus8);
SPS_TO_PP(log2_max_pic_order_cnt_lsb_minus4);
if (sps->profile_tier_level.general_profile_idc == 4) {
is_rext_ = true;
}
// HEVC DXVA spec does not clearly state which slot
// in sps->sps_max_dec_pic_buffering_minus1 should
// be used here. However section A4.1 of HEVC spec
// requires the slot of highest tid to be used for
// indicating the maximum DPB size if level is not
// 8.5.
int highest_tid = sps->sps_max_sub_layers_minus1;
(pic_param->main).sps_max_dec_pic_buffering_minus1 =
sps->sps_max_dec_pic_buffering_minus1[highest_tid];
SPS_TO_PP(log2_min_luma_coding_block_size_minus3);
SPS_TO_PP(log2_diff_max_min_luma_coding_block_size);
// DXVA spec names them differently with HEVC spec.
SPS_TO_PP(log2_min_transform_block_size_minus2,
log2_min_luma_transform_block_size_minus2);
SPS_TO_PP(log2_diff_max_min_transform_block_size,
log2_diff_max_min_luma_transform_block_size);
SPS_TO_PP(max_transform_hierarchy_depth_inter);
SPS_TO_PP(max_transform_hierarchy_depth_intra);
SPS_TO_PP(num_short_term_ref_pic_sets);
SPS_TO_PP(num_long_term_ref_pics_sps);
// dwCodingParamToolFlags extracted from SPS
SPS_TO_PP(scaling_list_enabled_flag);
SPS_TO_PP(amp_enabled_flag);
SPS_TO_PP(sample_adaptive_offset_enabled_flag);
SPS_TO_PP(pcm_enabled_flag);
if (sps->pcm_enabled_flag) {
SPS_TO_PP(pcm_sample_bit_depth_luma_minus1);
SPS_TO_PP(pcm_sample_bit_depth_chroma_minus1);
SPS_TO_PP(log2_min_pcm_luma_coding_block_size_minus3);
SPS_TO_PP(log2_diff_max_min_pcm_luma_coding_block_size);
SPS_TO_PP(pcm_loop_filter_disabled_flag);
}
SPS_TO_PP(long_term_ref_pics_present_flag);
SPS_TO_PP(sps_temporal_mvp_enabled_flag);
SPS_TO_PP(strong_intra_smoothing_enabled_flag);
if (sps->sps_range_extension_flag) {
SPS_TO_PPEXT(transform_skip_rotation_enabled_flag);
SPS_TO_PPEXT(transform_skip_context_enabled_flag);
SPS_TO_PPEXT(implicit_rdpcm_enabled_flag);
SPS_TO_PPEXT(explicit_rdpcm_enabled_flag);
SPS_TO_PPEXT(extended_precision_processing_flag);
SPS_TO_PPEXT(intra_smoothing_disabled_flag);
SPS_TO_PPEXT(high_precision_offsets_enabled_flag);
SPS_TO_PPEXT(persistent_rice_adaptation_enabled_flag);
SPS_TO_PPEXT(cabac_bypass_alignment_enabled_flag);
}
}
#undef SPS_TO_PP
#undef SPS_TO_PPEXT
#undef SPS_TO_PP2
#undef SPS_TO_PP1
#define PPS_TO_PPEXT(a) pic_param->a = pps->a;
#define PPS_TO_PP1(a) (pic_param->main).a = pps->a;
#define PPS_TO_PP2(a, b) (pic_param->main).a = pps->b;
#define PPS_TO_PP(...) ARG_SEL(__VA_ARGS__, PPS_TO_PP2, PPS_TO_PP1)(__VA_ARGS__)
void D3D11H265Accelerator::PicParamsFromPPS(DXVA_PicParams_HEVC_Rext* pic_param,
const H265PPS* pps) {
PPS_TO_PP(num_ref_idx_l0_default_active_minus1);
PPS_TO_PP(num_ref_idx_l1_default_active_minus1);
PPS_TO_PP(init_qp_minus26);
// dwCodingParamToolFlags from PPS
PPS_TO_PP(dependent_slice_segments_enabled_flag);
PPS_TO_PP(output_flag_present_flag);
PPS_TO_PP(num_extra_slice_header_bits);
PPS_TO_PP(sign_data_hiding_enabled_flag);
PPS_TO_PP(cabac_init_present_flag);
// dwCodingSettingPicturePropertyFlags from PPS
PPS_TO_PP(constrained_intra_pred_flag);
PPS_TO_PP(transform_skip_enabled_flag);
PPS_TO_PP(cu_qp_delta_enabled_flag);
PPS_TO_PP(pps_slice_chroma_qp_offsets_present_flag);
PPS_TO_PP(weighted_pred_flag);
PPS_TO_PP(weighted_bipred_flag);
PPS_TO_PP(transquant_bypass_enabled_flag);
PPS_TO_PP(tiles_enabled_flag);
PPS_TO_PP(entropy_coding_sync_enabled_flag);
PPS_TO_PP(uniform_spacing_flag);
if (pps->tiles_enabled_flag)
PPS_TO_PP(loop_filter_across_tiles_enabled_flag);
PPS_TO_PP(pps_loop_filter_across_slices_enabled_flag);
PPS_TO_PP(deblocking_filter_override_enabled_flag);
PPS_TO_PP(pps_deblocking_filter_disabled_flag);
PPS_TO_PP(lists_modification_present_flag);
PPS_TO_PP(slice_segment_header_extension_present_flag);
PPS_TO_PP(pps_cb_qp_offset);
PPS_TO_PP(pps_cr_qp_offset);
if (pps->tiles_enabled_flag) {
PPS_TO_PP(num_tile_columns_minus1);
PPS_TO_PP(num_tile_rows_minus1);
if (!pps->uniform_spacing_flag) {
for (int i = 0; i <= pps->num_tile_columns_minus1; i++) {
PPS_TO_PP(column_width_minus1[i]);
}
for (int j = 0; j <= pps->num_tile_rows_minus1; j++) {
PPS_TO_PP(row_height_minus1[j]);
}
}
}
PPS_TO_PP(diff_cu_qp_delta_depth);
PPS_TO_PP(pps_beta_offset_div2);
PPS_TO_PP(pps_tc_offset_div2);
PPS_TO_PP(log2_parallel_merge_level_minus2);
if (pps->pps_range_extension_flag) {
PPS_TO_PPEXT(cross_component_prediction_enabled_flag);
PPS_TO_PPEXT(chroma_qp_offset_list_enabled_flag);
if (pps->chroma_qp_offset_list_enabled_flag) {
PPS_TO_PPEXT(diff_cu_chroma_qp_offset_depth);
PPS_TO_PPEXT(chroma_qp_offset_list_len_minus1);
for (int i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
PPS_TO_PPEXT(cb_qp_offset_list[i]);
PPS_TO_PPEXT(cr_qp_offset_list[i]);
}
}
PPS_TO_PPEXT(log2_sao_offset_scale_luma);
PPS_TO_PPEXT(log2_sao_offset_scale_chroma);
if (pps->transform_skip_enabled_flag) {
PPS_TO_PPEXT(log2_max_transform_skip_block_size_minus2);
}
}
return;
}
#undef PPS_TO_PPEXT
#undef PPS_TO_PP
#undef PPS_TO_PP2
#undef PPS_TO_PP1
#undef ARG_SEL
void D3D11H265Accelerator::PicParamsFromSliceHeader(
DXVA_PicParams_HEVC_Rext* pic_param,
const H265SPS* sps,
const H265SliceHeader* slice_hdr) {
// IDR_W_RADL and IDR_N_LP NALUs do not contain st_rps in slice header.
// Otherwise if short_term_ref_pic_set_sps_flag is 1, host decoder
// shall set ucNumDeltaPocsOfRefRpsIdx to 0.
if (slice_hdr->short_term_ref_pic_set_sps_flag) {
pic_param->main.ucNumDeltaPocsOfRefRpsIdx = 0;
pic_param->main.wNumBitsForShortTermRPSInSlice = 0;
} else {
pic_param->main.ucNumDeltaPocsOfRefRpsIdx =
slice_hdr->st_ref_pic_set.rps_idx_num_delta_pocs;
pic_param->main.wNumBitsForShortTermRPSInSlice = slice_hdr->st_rps_bits;
}
pic_param->main.IrapPicFlag = slice_hdr->irap_pic;
auto nal_unit_type = slice_hdr->nal_unit_type;
pic_param->main.IdrPicFlag = (nal_unit_type == H265NALU::IDR_W_RADL ||
nal_unit_type == H265NALU::IDR_N_LP);
pic_param->main.IntraPicFlag = slice_hdr->irap_pic;
}
void D3D11H265Accelerator::PicParamsFromPic(DXVA_PicParams_HEVC_Rext* pic_param,
D3D11H265Picture* pic) {
pic_param->main.CurrPicOrderCntVal = pic->pic_order_cnt_val_;
pic_param->main.CurrPic.Index7Bits = pic->picture_index_;
}
bool D3D11H265Accelerator::PicParamsFromRefLists(
DXVA_PicParams_HEVC_Rext* pic_param,
const H265Picture::Vector& ref_pic_set_lt_curr,
const H265Picture::Vector& ref_pic_set_st_curr_after,
const H265Picture::Vector& ref_pic_set_st_curr_before) {
constexpr int kDxvaInvalidRefPicIndex = 0xFF;
constexpr unsigned kStLtRpsSize = 8;
std::fill_n(pic_param->main.RefPicSetStCurrBefore, kStLtRpsSize,
kDxvaInvalidRefPicIndex);
std::fill_n(pic_param->main.RefPicSetStCurrAfter, kStLtRpsSize,
kDxvaInvalidRefPicIndex);
std::fill_n(pic_param->main.RefPicSetLtCurr, kStLtRpsSize,
kDxvaInvalidRefPicIndex);
std::copy(ref_frame_pocs_, ref_frame_pocs_ + kMaxRefPicListSize - 1,
pic_param->main.PicOrderCntValList);
size_t idx = 0;
for (auto& it : ref_pic_set_st_curr_before) {
if (!it)
continue;
auto poc = it->pic_order_cnt_val_;
auto poc_index = poc_index_into_ref_pic_list_[poc];
if (poc_index < 0) {
DLOG(ERROR) << "Invalid index of POC for RefPicSetStCurrBefore.";
return false;
}
if (idx > kStLtRpsSize - 1) {
DLOG(ERROR) << "Invalid RefPicSetStCurrBefore size.";
return false;
}
pic_param->main.RefPicSetStCurrBefore[idx++] = poc_index;
}
idx = 0;
for (auto& it : ref_pic_set_st_curr_after) {
if (!it)
continue;
auto poc = it->pic_order_cnt_val_;
auto poc_index = poc_index_into_ref_pic_list_[poc];
if (poc_index < 0) {
DLOG(ERROR) << "Invalid index of POC for RefPicSetStCurrAfter.";
return false;
}
if (idx > kStLtRpsSize - 1) {
DLOG(ERROR) << "Invalid RefPicSetStCurrAfter size.";
return false;
}
pic_param->main.RefPicSetStCurrAfter[idx++] = poc_index;
}
idx = 0;
for (auto& it : ref_pic_set_lt_curr) {
if (!it)
continue;
auto poc = it->pic_order_cnt_val_;
auto poc_index = poc_index_into_ref_pic_list_[poc];
if (poc_index < 0) {
DLOG(ERROR) << "Invalid index of POC for RefPicSetLtCurr.";
return false;
}
if (idx > kStLtRpsSize - 1) {
DLOG(ERROR) << "Invalid RefPicSetLtCurr size.";
return false;
}
pic_param->main.RefPicSetLtCurr[idx++] = poc_index;
}
return true;
}
H265DecoderStatus D3D11H265Accelerator::SubmitSlice(
const H265SPS* sps,
const H265PPS* pps,
const H265SliceHeader* slice_hdr,
const H265Picture::Vector& ref_pic_list0,
const H265Picture::Vector& ref_pic_list1,
const H265Picture::Vector& ref_pic_set_lt_curr,
const H265Picture::Vector& ref_pic_set_st_curr_after,
const H265Picture::Vector& ref_pic_set_st_curr_before,
scoped_refptr<H265Picture> pic,
const uint8_t* data,
size_t size,
const std::vector<SubsampleEntry>& subsamples) {
if (!client_->GetWrapper()->HasPendingBuffer(
D3DVideoDecoderWrapper::BufferType::kPictureParameters)) {
DXVA_PicParams_HEVC_Rext pic_param = {};
D3D11H265Picture* d3d11_pic = pic->AsD3D11H265Picture();
if (!d3d11_pic) {
return H265DecoderStatus::kFail;
}
FillPicParamsWithConstants(&pic_param);
PicParamsFromSPS(&pic_param, sps);
PicParamsFromPPS(&pic_param, pps);
PicParamsFromSliceHeader(&pic_param, sps, slice_hdr);
PicParamsFromPic(&pic_param, d3d11_pic);
memcpy(pic_param.main.RefPicList, ref_frame_list_,
sizeof pic_param.main.RefPicList);
if (!PicParamsFromRefLists(&pic_param, ref_pic_set_lt_curr,
ref_pic_set_st_curr_after,
ref_pic_set_st_curr_before)) {
return H265DecoderStatus::kFail;
}
pic_param.main.StatusReportFeedbackNumber =
current_status_report_feedback_num_++;
size_t pic_params_size = is_rext_ ? sizeof(DXVA_PicParams_HEVC_Rext)
: sizeof(DXVA_PicParams_HEVC);
auto params_buffer =
client_->GetWrapper()->GetPictureParametersBuffer(pic_params_size);
// For 420 content the driver may only allow main part picture parameters.
if (is_rext_ && params_buffer.size() < sizeof(DXVA_PicParams_HEVC_Rext)) {
pic_params_size = sizeof(DXVA_PicParams_HEVC);
}
if (params_buffer.size() < pic_params_size) {
MEDIA_LOG(ERROR, media_log_)
<< "Insufficient picture parameter buffer size";
return H265DecoderStatus::kFail;
}
memcpy(params_buffer.data(), &pic_param, pic_params_size);
if (!params_buffer.Commit()) {
return H265DecoderStatus::kFail;
}
}
// Fill up the quantitization matrix data structure when
// pps->scaling_list_enabled is true. See section 4.2
// of DXVA spec for HEVC.
if (use_scaling_lists_ &&
!client_->GetWrapper()->HasPendingBuffer(
D3DVideoDecoderWrapper::BufferType::kInverseQuantizationMatrix)) {
DXVA_Qmatrix_HEVC iq_matrix = {};
const H265ScalingListData* scaling_lists =
pps->pps_scaling_list_data_present_flag ? &pps->scaling_list_data
: &sps->scaling_list_data;
static_assert(std::is_same<decltype(iq_matrix.ucScalingLists0),
decltype(scaling_lists->scaling_list_4x4)>()
.value);
memcpy(iq_matrix.ucScalingLists0, scaling_lists->scaling_list_4x4,
sizeof iq_matrix.ucScalingLists0);
static_assert(std::is_same<decltype(iq_matrix.ucScalingLists1),
decltype(scaling_lists->scaling_list_8x8)>()
.value);
memcpy(iq_matrix.ucScalingLists1, scaling_lists->scaling_list_8x8,
sizeof iq_matrix.ucScalingLists1);
static_assert(std::is_same<decltype(iq_matrix.ucScalingLists2),
decltype(scaling_lists->scaling_list_16x16)>()
.value);
memcpy(iq_matrix.ucScalingLists2, scaling_lists->scaling_list_16x16,
sizeof iq_matrix.ucScalingLists2);
static_assert(
std::is_same<
std::remove_reference_t<decltype(iq_matrix.ucScalingLists3[0])>,
std::remove_const_t<std::remove_reference_t<
decltype(scaling_lists->scaling_list_32x32[0])>>>()
.value);
memcpy(iq_matrix.ucScalingLists3[0], scaling_lists->scaling_list_32x32[0],
sizeof(iq_matrix.ucScalingLists3[0]));
memcpy(iq_matrix.ucScalingLists3[1], scaling_lists->scaling_list_32x32[3],
sizeof(iq_matrix.ucScalingLists3[1]));
static_assert(
std::is_same<decltype(iq_matrix.ucScalingListDCCoefSizeID2),
decltype(scaling_lists->scaling_list_dc_coef_16x16)>()
.value);
memcpy(iq_matrix.ucScalingListDCCoefSizeID2,
scaling_lists->scaling_list_dc_coef_16x16,
sizeof(iq_matrix.ucScalingListDCCoefSizeID2));
iq_matrix.ucScalingListDCCoefSizeID3[0] =
scaling_lists->scaling_list_dc_coef_32x32[0];
iq_matrix.ucScalingListDCCoefSizeID3[1] =
scaling_lists->scaling_list_dc_coef_32x32[3];
auto iq_matrix_buffer =
client_->GetWrapper()->GetInverseQuantizationMatrixBuffer(
sizeof(iq_matrix));
if (iq_matrix_buffer.size() < sizeof(iq_matrix)) {
MEDIA_LOG(ERROR, media_log_) << "Insufficient quant buffer size";
return H265DecoderStatus::kFail;
}
memcpy(iq_matrix_buffer.data(), &iq_matrix, sizeof(iq_matrix));
if (!iq_matrix_buffer.Commit()) {
return H265DecoderStatus::kFail;
}
}
CHECK_GT(current_frame_size_, 0u);
client_->GetWrapper()->GetBitstreamBuffer(current_frame_size_);
constexpr uint8_t kStartCode[] = {0, 0, 1};
bool ok =
client_->GetWrapper()
->AppendBitstreamAndSliceDataWithStartCode<DXVA_Slice_HEVC_Short>(
{data, size}, kStartCode);
return ok ? H265DecoderStatus::kOk : H265DecoderStatus::kFail;
}
H265DecoderStatus D3D11H265Accelerator::SubmitDecode(
scoped_refptr<H265Picture> pic) {
return client_->GetWrapper()->SubmitSlice() &&
client_->GetWrapper()->SubmitDecode()
? H265DecoderStatus::kOk
: H265DecoderStatus::kFail;
}
void D3D11H265Accelerator::Reset() {
current_frame_size_ = 0;
if (client_->GetWrapper()) {
client_->GetWrapper()->Reset();
}
}
H265Decoder::H265Accelerator::Status D3D11H265Accelerator::SetStream(
base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config) {
current_frame_size_ = stream.size();
return H265Accelerator::SetStream(stream, decrypt_config);
}
bool D3D11H265Accelerator::OutputPicture(scoped_refptr<H265Picture> pic) {
D3D11H265Picture* our_pic = pic->AsD3D11H265Picture();
return our_pic && client_->OutputResult(our_pic, our_pic->picture);
}
} // namespace media