Skip to content

Commit

Permalink
[media] Implement HEVC support in VTVD
Browse files Browse the repository at this point in the history
This CL adds passthrough of raw VPS, SPS, and PPS NALU data from
H265Decoder, and then uses it exactly like VideoToolboxH264Accelerator
does to implement HEVC decoding.

Bug: 1331597
Change-Id: I2dde511769339dd0c66eef9a0992c21be776b3aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4785590
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1186846}
  • Loading branch information
Dan Sanders authored and Chromium LUCI CQ committed Aug 22, 2023
1 parent ccfd11e commit e8c8e69
Show file tree
Hide file tree
Showing 9 changed files with 764 additions and 14 deletions.
37 changes: 36 additions & 1 deletion media/gpu/h265_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ H265Decoder::H265Accelerator::H265Accelerator() = default;

H265Decoder::H265Accelerator::~H265Accelerator() = default;

void H265Decoder::H265Accelerator::ProcessVPS(
const H265VPS* vps,
base::span<const uint8_t> vps_nalu_data) {}

void H265Decoder::H265Accelerator::ProcessSPS(
const H265SPS* sps,
base::span<const uint8_t> sps_nalu_data) {}

void H265Decoder::H265Accelerator::ProcessPPS(
const H265PPS* pps,
base::span<const uint8_t> pps_nalu_data) {}

H265Decoder::H265Accelerator::Status H265Decoder::H265Accelerator::SetStream(
base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config) {
Expand Down Expand Up @@ -216,6 +228,7 @@ H265Decoder::DecodeResult H265Decoder::Decode() {
}

// 8.1.2 We only want nuh_layer_id of zero.
// TODO(crbug.com/1331597): Support alpha on macOS.
if (curr_nalu_->nuh_layer_id) {
DVLOG(4) << "Skipping NALU with nuh_layer_id="
<< curr_nalu_->nuh_layer_id;
Expand Down Expand Up @@ -317,20 +330,42 @@ H265Decoder::DecodeResult H265Decoder::Decode() {
last_slice_hdr_.swap(curr_slice_hdr_);
curr_slice_hdr_.reset();
break;
case H265NALU::VPS_NUT:
CHECK_ACCELERATOR_RESULT(FinishPrevFrameIfPresent());
int vps_id;
par_res = parser_.ParseVPS(&vps_id);
if (par_res != H265Parser::kOk) {
SET_ERROR_AND_RETURN();
}
accelerator_->ProcessVPS(
parser_.GetVPS(vps_id),
base::span<const uint8_t>(
curr_nalu_->data,
base::checked_cast<size_t>(curr_nalu_->size)));
break;
case H265NALU::SPS_NUT:
CHECK_ACCELERATOR_RESULT(FinishPrevFrameIfPresent());
int sps_id;
par_res = parser_.ParseSPS(&sps_id);
if (par_res != H265Parser::kOk)
SET_ERROR_AND_RETURN();

accelerator_->ProcessSPS(
parser_.GetSPS(sps_id),
base::span<const uint8_t>(
curr_nalu_->data,
base::checked_cast<size_t>(curr_nalu_->size)));
break;
case H265NALU::PPS_NUT:
CHECK_ACCELERATOR_RESULT(FinishPrevFrameIfPresent());
int pps_id;
par_res = parser_.ParsePPS(*curr_nalu_, &pps_id);
if (par_res != H265Parser::kOk)
SET_ERROR_AND_RETURN();
accelerator_->ProcessPPS(
parser_.GetPPS(pps_id),
base::span<const uint8_t>(
curr_nalu_->data,
base::checked_cast<size_t>(curr_nalu_->size)));

// For ARC CTS tests they expect us to request the buffers after only
// processing the SPS/PPS, we can't wait until we get the first IDR. To
Expand Down
18 changes: 18 additions & 0 deletions media/gpu/h265_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ class MEDIA_GPU_EXPORT H265Decoder final : public AcceleratedVideoDecoder {
// this situation as normal and return from Decode() with kRanOutOfSurfaces.
virtual scoped_refptr<H265Picture> CreateH265Picture() = 0;

// Provides the raw NALU data for a VPS. The |vps| passed to
// SubmitFrameMetadata() is always the most recent VPS passed to
// ProcessVPS() with the same |vps_video_parameter_set_id|.
virtual void ProcessVPS(const H265VPS* vps,
base::span<const uint8_t> vps_nalu_data);

// Provides the raw NALU data for an SPS. The |sps| passed to
// SubmitFrameMetadata() is always the most recent SPS passed to
// ProcessSPS() with the same |sps_video_parameter_set_id|.
virtual void ProcessSPS(const H265SPS* sps,
base::span<const uint8_t> sps_nalu_data);

// Provides the raw NALU data for a PPS. The |pps| passed to
// SubmitFrameMetadata() is always the most recent PPS passed to
// ProcessPPS() with the same |pps_pic_parameter_set_id|.
virtual void ProcessPPS(const H265PPS* pps,
base::span<const uint8_t> pps_nalu_data);

// Submit metadata for the current frame, providing the current |sps|, |pps|
// and |slice_hdr| for it. |ref_pic_list| contains the set of pictures as
// described in 8.3.2 from the lists RefPicSetLtCurr, RefPicSetLtFoll,
Expand Down
9 changes: 9 additions & 0 deletions media/gpu/mac/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ source_set("mac") {
"vt_video_encode_accelerator_mac.cc",
"vt_video_encode_accelerator_mac.h",
]
if (enable_hevc_parser_and_hw_decoder) {
sources += [
"video_toolbox_h265_accelerator.cc",
"video_toolbox_h265_accelerator.h",
]
}
public_deps = [ "//third_party/webrtc_overrides:webrtc_component" ]
frameworks = [
"CoreFoundation.framework",
Expand Down Expand Up @@ -91,4 +97,7 @@ source_set("unit_tests") {
"vp9_super_frame_bitstream_filter_unittest.cc",
"vt_config_util_unittest.cc",
]
if (enable_hevc_parser_and_hw_decoder) {
sources += [ "video_toolbox_h265_accelerator_unittest.cc" ]
}
}
9 changes: 8 additions & 1 deletion media/gpu/mac/video_toolbox_decompression_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,17 @@ bool VideoToolboxDecompressionInterface::CreateSession(
decoder_config,
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
kCFBooleanTrue);

// We don't have software HEVC decoders to fall back to.
// TODO(crbug.com/1331597): Plumb hardware requirement from the accelerator.
FourCharCode codec_type = CMFormatDescriptionGetMediaSubType(format);
bool require_hardware = (codec_type != kCMVideoCodecType_HEVC) &&
(codec_type != kCMVideoCodecType_HEVCWithAlpha);

CFDictionarySetValue(
decoder_config,
kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder,
kCFBooleanTrue);
require_hardware ? kCFBooleanTrue : kCFBooleanFalse);
#endif

if (!decompression_session_->Create(format, decoder_config)) {
Expand Down
4 changes: 2 additions & 2 deletions media/gpu/mac/video_toolbox_h264_accelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class MEDIA_GPU_EXPORT VideoToolboxH264Accelerator
OutputCB output_cb_;

// Raw parameter set bytes that have been observed.
base::flat_map<int, std::vector<uint8_t>> seen_sps_data_;
base::flat_map<int, std::vector<uint8_t>> seen_pps_data_;
base::flat_map<int, std::vector<uint8_t>> seen_sps_data_; // IDs can be 0-31
base::flat_map<int, std::vector<uint8_t>> seen_pps_data_; // IDs can be 0-255

// Raw parameter set bytes used to produce |active_format_|, so that they
// can be checked for changes.
Expand Down

0 comments on commit e8c8e69

Please sign in to comment.