diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-05-20 09:47:09 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-06-07 11:15:42 +0000 |
commit | 189d4fd8fad9e3c776873be51938cd31a42b6177 (patch) | |
tree | 6497caeff5e383937996768766ab3bb2081a40b2 /chromium/media/gpu/h265_decoder.cc | |
parent | 8bc75099d364490b22f43a7ce366b366c08f4164 (diff) | |
download | qtwebengine-chromium-189d4fd8fad9e3c776873be51938cd31a42b6177.tar.gz |
BASELINE: Update Chromium to 90.0.4430.221
Change-Id: Iff4d9d18d2fcf1a576f3b1f453010f744a232920
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/gpu/h265_decoder.cc')
-rw-r--r-- | chromium/media/gpu/h265_decoder.cc | 119 |
1 files changed, 87 insertions, 32 deletions
diff --git a/chromium/media/gpu/h265_decoder.cc b/chromium/media/gpu/h265_decoder.cc index 4c44016a0c6..64d5106de33 100644 --- a/chromium/media/gpu/h265_decoder.cc +++ b/chromium/media/gpu/h265_decoder.cc @@ -5,6 +5,7 @@ #include <algorithm> #include "base/logging.h" +#include "base/notreached.h" #include "media/base/limits.h" #include "media/gpu/h265_decoder.h" @@ -19,6 +20,35 @@ struct POCAscCompare { } }; +bool ParseBitDepth(const H265SPS& sps, uint8_t& bit_depth) { + // Spec 7.4.3.2.1 + if (sps.bit_depth_y != sps.bit_depth_c) { + DVLOG(1) << "Different bit depths among planes is not supported"; + return false; + } + bit_depth = base::checked_cast<uint8_t>(sps.bit_depth_y); + return true; +} + +bool IsValidBitDepth(uint8_t bit_depth, VideoCodecProfile profile) { + // Spec A.3. + switch (profile) { + case HEVCPROFILE_MAIN: + return bit_depth == 8u; + case HEVCPROFILE_MAIN10: + return bit_depth == 8u || bit_depth == 10u; + case HEVCPROFILE_MAIN_STILL_PICTURE: + return bit_depth == 8u; + default: + NOTREACHED(); + return false; + } +} + +bool IsYUV420Sequence(const H265SPS& sps) { + // Spec 6.2 + return sps.chroma_format_idc == 1; +} } // namespace H265Decoder::H265Accelerator::H265Accelerator() = default; @@ -185,16 +215,8 @@ H265Decoder::DecodeResult H265Decoder::Decode() { case H265NALU::CRA_NUT: if (!curr_slice_hdr_) { curr_slice_hdr_.reset(new H265SliceHeader()); - if (last_slice_hdr_) { - // This is a multi-slice picture, so we should copy all of the prior - // slice header data to the new slice and use those as the default - // values that don't have syntax elements present. - memcpy(curr_slice_hdr_.get(), last_slice_hdr_.get(), - sizeof(H265SliceHeader)); - last_slice_hdr_.reset(); - } - par_res = - parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get()); + par_res = parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get(), + last_slice_hdr_.get()); if (par_res == H265Parser::kMissingParameterSet) { // We may still be able to recover if we skip until we find the // SPS/PPS. @@ -318,6 +340,10 @@ VideoCodecProfile H265Decoder::GetProfile() const { return profile_; } +uint8_t H265Decoder::GetBitDepth() const { + return bit_depth_; +} + size_t H265Decoder::GetRequiredNumOfPictures() const { constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1; return GetNumReferenceFrames() + kPicsInPipeline; @@ -348,6 +374,10 @@ bool H265Decoder::ProcessPPS(int pps_id, bool* need_new_buffers) { DVLOG(2) << "New visible rect: " << new_visible_rect.ToString(); visible_rect_ = new_visible_rect; } + if (!IsYUV420Sequence(*sps)) { + DVLOG(1) << "Only YUV 4:2:0 is supported"; + return false; + } // Equation 7-8 max_pic_order_cnt_lsb_ = @@ -355,16 +385,25 @@ bool H265Decoder::ProcessPPS(int pps_id, bool* need_new_buffers) { VideoCodecProfile new_profile = H265Parser::ProfileIDCToVideoCodecProfile( sps->profile_tier_level.general_profile_idc); - + uint8_t new_bit_depth = 0; + if (!ParseBitDepth(*sps, new_bit_depth)) + return false; + if (!IsValidBitDepth(new_bit_depth, new_profile)) { + DVLOG(1) << "Invalid bit depth=" << base::strict_cast<int>(new_bit_depth) + << ", profile=" << GetProfileName(new_profile); + return false; + } if (pic_size_ != new_pic_size || dpb_.max_num_pics() != sps->max_dpb_size || - profile_ != new_profile) { + profile_ != new_profile || bit_depth_ != new_bit_depth) { if (!Flush()) return false; DVLOG(1) << "Codec profile: " << GetProfileName(new_profile) << ", level(x30): " << sps->profile_tier_level.general_level_idc << ", DPB size: " << sps->max_dpb_size - << ", Picture size: " << new_pic_size.ToString(); + << ", Picture size: " << new_pic_size.ToString() + << ", bit_depth: " << base::strict_cast<int>(new_bit_depth); profile_ = new_profile; + bit_depth_ = new_bit_depth; pic_size_ = new_pic_size; dpb_.set_max_num_pics(sps->max_dpb_size); if (need_new_buffers) @@ -486,41 +525,57 @@ bool H265Decoder::CalcRefPicPocs(const H265SPS* sps, // Equation 8-5. int i, j, k; for (i = 0, j = 0, k = 0; i < curr_st_ref_pic_set.num_negative_pics; ++i) { - if (curr_st_ref_pic_set.used_by_curr_pic_s0[i]) { - poc_st_curr_before_[j++] = - curr_pic_->pic_order_cnt_val_ + curr_st_ref_pic_set.delta_poc_s0[i]; - } else { - poc_st_foll_[k++] = - curr_pic_->pic_order_cnt_val_ + curr_st_ref_pic_set.delta_poc_s0[i]; + base::CheckedNumeric<int> poc = curr_pic_->pic_order_cnt_val_; + poc += curr_st_ref_pic_set.delta_poc_s0[i]; + if (!poc.IsValid()) { + DVLOG(1) << "Invalid POC"; + return false; } + if (curr_st_ref_pic_set.used_by_curr_pic_s0[i]) + poc_st_curr_before_[j++] = poc.ValueOrDefault(0); + else + poc_st_foll_[k++] = poc.ValueOrDefault(0); } num_poc_st_curr_before_ = j; for (i = 0, j = 0; i < curr_st_ref_pic_set.num_positive_pics; ++i) { - if (curr_st_ref_pic_set.used_by_curr_pic_s1[i]) { - poc_st_curr_after_[j++] = - curr_pic_->pic_order_cnt_val_ + curr_st_ref_pic_set.delta_poc_s1[i]; - } else { - poc_st_foll_[k++] = - curr_pic_->pic_order_cnt_val_ + curr_st_ref_pic_set.delta_poc_s1[i]; + base::CheckedNumeric<int> poc = curr_pic_->pic_order_cnt_val_; + poc += curr_st_ref_pic_set.delta_poc_s1[i]; + if (!poc.IsValid()) { + DVLOG(1) << "Invalid POC"; + return false; } + if (curr_st_ref_pic_set.used_by_curr_pic_s1[i]) + poc_st_curr_after_[j++] = poc.ValueOrDefault(0); + else + poc_st_foll_[k++] = poc.ValueOrDefault(0); } num_poc_st_curr_after_ = j; num_poc_st_foll_ = k; for (i = 0, j = 0, k = 0; i < slice_hdr->num_long_term_sps + slice_hdr->num_long_term_pics; ++i) { - int poc_lt = slice_hdr->poc_lsb_lt[i]; + base::CheckedNumeric<int> poc_lt = slice_hdr->poc_lsb_lt[i]; if (slice_hdr->delta_poc_msb_present_flag[i]) { - poc_lt += - curr_pic_->pic_order_cnt_val_ - - (slice_hdr->delta_poc_msb_cycle_lt[i] * max_pic_order_cnt_lsb_) - - (curr_pic_->pic_order_cnt_val_ & (max_pic_order_cnt_lsb_ - 1)); + poc_lt += curr_pic_->pic_order_cnt_val_; + base::CheckedNumeric<int> poc_delta = + slice_hdr->delta_poc_msb_cycle_lt[i]; + poc_delta *= max_pic_order_cnt_lsb_; + if (!poc_delta.IsValid()) { + DVLOG(1) << "Invalid POC"; + return false; + } + poc_lt -= poc_delta.ValueOrDefault(0); + poc_lt -= curr_pic_->pic_order_cnt_val_ & (max_pic_order_cnt_lsb_ - 1); + } + if (!poc_lt.IsValid()) { + DVLOG(1) << "Invalid POC"; + return false; } if (slice_hdr->used_by_curr_pic_lt[i]) { - poc_lt_curr_[j] = poc_lt; + poc_lt_curr_[j] = poc_lt.ValueOrDefault(0); curr_delta_poc_msb_present_flag_[j++] = slice_hdr->delta_poc_msb_present_flag[i]; } else { - poc_lt_foll_[k] = poc_lt; + poc_lt_foll_[k] = poc_lt.ValueOrDefault(0); foll_delta_poc_msb_present_flag_[k++] = slice_hdr->delta_poc_msb_present_flag[i]; } |