From 9a45e897d5fc86661b8e7f1143595c774cf0e971 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Mon, 13 Sep 2021 15:55:03 +0200 Subject: [PATCH] Update h264_bitstream and pps parsers to use BitstreamReader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new version is subjectivly cleaner and objectively generates smaller binary size Bug: None Change-Id: I6639b4a1455e745e0047339115b3d02ef81ce731 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231238 Reviewed-by: Sergey Silkin Reviewed-by: Stefan Holmer Reviewed-by: Erik Språng Commit-Queue: Danil Chapovalov Cr-Commit-Position: refs/heads/main@{#35000} --- common_video/BUILD.gn | 7 +- common_video/h264/h264_bitstream_parser.cc | 142 ++++++++---------- common_video/h264/pps_parser.cc | 158 +++++++-------------- common_video/h264/pps_parser.h | 16 +-- common_video/h264/pps_parser_unittest.cc | 2 +- 5 files changed, 128 insertions(+), 197 deletions(-) diff --git a/common_video/BUILD.gn b/common_video/BUILD.gn index 081b1c8104..30eddc6bf6 100644 --- a/common_video/BUILD.gn +++ b/common_video/BUILD.gn @@ -42,6 +42,7 @@ rtc_library("common_video") { ] deps = [ + "../api:array_view", "../api:scoped_refptr", "../api:sequence_checker", "../api/task_queue", @@ -55,6 +56,7 @@ rtc_library("common_video") { "../api/video_codecs:bitstream_parser_api", "../api/video_codecs:video_codecs_api", "../rtc_base", + "../rtc_base:bitstream_reader", "../rtc_base:checks", "../rtc_base:rtc_task_queue", "../rtc_base:safe_minmax", @@ -63,7 +65,10 @@ rtc_library("common_video") { "../system_wrappers:metrics", "//third_party/libyuv", ] - absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/numeric:bits", + "//third_party/abseil-cpp/absl/types:optional", + ] } rtc_source_set("frame_counts") { diff --git a/common_video/h264/h264_bitstream_parser.cc b/common_video/h264/h264_bitstream_parser.cc index bc2104c9ef..2311d0d2ee 100644 --- a/common_video/h264/h264_bitstream_parser.cc +++ b/common_video/h264/h264_bitstream_parser.cc @@ -15,31 +15,20 @@ #include #include "common_video/h264/h264_common.h" -#include "rtc_base/bit_buffer.h" +#include "rtc_base/bitstream_reader.h" #include "rtc_base/logging.h" +namespace webrtc { namespace { -const int kMaxAbsQpDeltaValue = 51; -const int kMinQpValue = 0; -const int kMaxQpValue = 51; +constexpr int kMaxAbsQpDeltaValue = 51; +constexpr int kMinQpValue = 0; +constexpr int kMaxQpValue = 51; } // namespace -namespace webrtc { - -#define RETURN_ON_FAIL(x, res) \ - do { \ - if (!(x)) { \ - RTC_LOG_F(LS_ERROR) << "FAILED: " #x; \ - return res; \ - } \ - } while (0) - -#define RETURN_INV_ON_FAIL(x) RETURN_ON_FAIL(x, kInvalidStream) - -H264BitstreamParser::H264BitstreamParser() {} -H264BitstreamParser::~H264BitstreamParser() {} +H264BitstreamParser::H264BitstreamParser() = default; +H264BitstreamParser::~H264BitstreamParser() = default; H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( const uint8_t* source, @@ -54,94 +43,90 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( if (slice_rbsp.size() < H264::kNaluTypeSize) return kInvalidStream; - rtc::BitBuffer slice_reader(slice_rbsp.data() + H264::kNaluTypeSize, - slice_rbsp.size() - H264::kNaluTypeSize); + BitstreamReader slice_reader(slice_rbsp); + slice_reader.ConsumeBits(H264::kNaluTypeSize * 8); + // Check to see if this is an IDR slice, which has an extra field to parse // out. bool is_idr = (source[0] & 0x0F) == H264::NaluType::kIdr; uint8_t nal_ref_idc = (source[0] & 0x60) >> 5; - uint32_t golomb_tmp; - uint32_t bits_tmp; // first_mb_in_slice: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); // slice_type: ue(v) - uint32_t slice_type; - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(slice_type)); + uint32_t slice_type = slice_reader.ReadExponentialGolomb(); // slice_type's 5..9 range is used to indicate that all slices of a picture // have the same value of slice_type % 5, we don't care about that, so we map // to the corresponding 0..4 range. slice_type %= 5; // pic_parameter_set_id: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); if (sps_->separate_colour_plane_flag == 1) { // colour_plane_id - RETURN_INV_ON_FAIL(slice_reader.ReadBits(2, bits_tmp)); + slice_reader.ConsumeBits(2); } // frame_num: u(v) // Represented by log2_max_frame_num bits. - RETURN_INV_ON_FAIL(slice_reader.ReadBits(sps_->log2_max_frame_num, bits_tmp)); - uint32_t field_pic_flag = 0; + slice_reader.ConsumeBits(sps_->log2_max_frame_num); + bool field_pic_flag = false; if (sps_->frame_mbs_only_flag == 0) { // field_pic_flag: u(1) - RETURN_INV_ON_FAIL(slice_reader.ReadBits(1, field_pic_flag)); - if (field_pic_flag != 0) { + field_pic_flag = slice_reader.Read(); + if (field_pic_flag) { // bottom_field_flag: u(1) - RETURN_INV_ON_FAIL(slice_reader.ReadBits(1, bits_tmp)); + slice_reader.ConsumeBits(1); } } if (is_idr) { // idr_pic_id: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } // pic_order_cnt_lsb: u(v) // Represented by sps_.log2_max_pic_order_cnt_lsb bits. if (sps_->pic_order_cnt_type == 0) { - RETURN_INV_ON_FAIL( - slice_reader.ReadBits(sps_->log2_max_pic_order_cnt_lsb, bits_tmp)); - if (pps_->bottom_field_pic_order_in_frame_present_flag && - field_pic_flag == 0) { + slice_reader.ConsumeBits(sps_->log2_max_pic_order_cnt_lsb); + if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) { // delta_pic_order_cnt_bottom: se(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } } if (sps_->pic_order_cnt_type == 1 && !sps_->delta_pic_order_always_zero_flag) { // delta_pic_order_cnt[0]: se(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); if (pps_->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) { // delta_pic_order_cnt[1]: se(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } } if (pps_->redundant_pic_cnt_present_flag) { // redundant_pic_cnt: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } if (slice_type == H264::SliceType::kB) { // direct_spatial_mv_pred_flag: u(1) - RETURN_INV_ON_FAIL(slice_reader.ReadBits(1, bits_tmp)); + slice_reader.ConsumeBits(1); } switch (slice_type) { case H264::SliceType::kP: case H264::SliceType::kB: case H264::SliceType::kSp: - uint32_t num_ref_idx_active_override_flag; // num_ref_idx_active_override_flag: u(1) - RETURN_INV_ON_FAIL( - slice_reader.ReadBits(1, num_ref_idx_active_override_flag)); - if (num_ref_idx_active_override_flag != 0) { + if (slice_reader.Read()) { // num_ref_idx_l0_active_minus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); if (slice_type == H264::SliceType::kB) { // num_ref_idx_l1_active_minus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } } break; default: break; } + if (!slice_reader.Ok()) { + return kInvalidStream; + } // assume nal_unit_type != 20 && nal_unit_type != 21: if (nalu_type == 20 || nalu_type == 21) { RTC_LOG(LS_ERROR) << "Unsupported nal unit type."; @@ -157,49 +142,44 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( // verify that they are both the same. if (slice_type % 5 != 2 && slice_type % 5 != 4) { // ref_pic_list_modification_flag_l0: u(1) - uint32_t ref_pic_list_modification_flag_l0; - RETURN_INV_ON_FAIL( - slice_reader.ReadBits(1, ref_pic_list_modification_flag_l0)); - if (ref_pic_list_modification_flag_l0) { + if (slice_reader.Read()) { uint32_t modification_of_pic_nums_idc; do { // modification_of_pic_nums_idc: ue(v) - RETURN_INV_ON_FAIL( - slice_reader.ReadExponentialGolomb(modification_of_pic_nums_idc)); + modification_of_pic_nums_idc = slice_reader.ReadExponentialGolomb(); if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { // abs_diff_pic_num_minus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } else if (modification_of_pic_nums_idc == 2) { // long_term_pic_num: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } - } while (modification_of_pic_nums_idc != 3); + } while (modification_of_pic_nums_idc != 3 && slice_reader.Ok()); } } if (slice_type % 5 == 1) { // ref_pic_list_modification_flag_l1: u(1) - uint32_t ref_pic_list_modification_flag_l1; - RETURN_INV_ON_FAIL( - slice_reader.ReadBits(1, ref_pic_list_modification_flag_l1)); - if (ref_pic_list_modification_flag_l1) { + if (slice_reader.Read()) { uint32_t modification_of_pic_nums_idc; do { // modification_of_pic_nums_idc: ue(v) - RETURN_INV_ON_FAIL( - slice_reader.ReadExponentialGolomb(modification_of_pic_nums_idc)); + modification_of_pic_nums_idc = slice_reader.ReadExponentialGolomb(); if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { // abs_diff_pic_num_minus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } else if (modification_of_pic_nums_idc == 2) { // long_term_pic_num: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } - } while (modification_of_pic_nums_idc != 3); + } while (modification_of_pic_nums_idc != 3 && slice_reader.Ok()); } } } + if (!slice_reader.Ok()) { + return kInvalidStream; + } // TODO(pbos): Do we need support for pred_weight_table()? if ((pps_->weighted_pred_flag && (slice_type == H264::SliceType::kP || slice_type == H264::SliceType::kSp)) || @@ -216,49 +196,47 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( if (is_idr) { // no_output_of_prior_pics_flag: u(1) // long_term_reference_flag: u(1) - RETURN_INV_ON_FAIL(slice_reader.ReadBits(2, bits_tmp)); + slice_reader.ConsumeBits(2); } else { // adaptive_ref_pic_marking_mode_flag: u(1) - uint32_t adaptive_ref_pic_marking_mode_flag; - RETURN_INV_ON_FAIL( - slice_reader.ReadBits(1, adaptive_ref_pic_marking_mode_flag)); - if (adaptive_ref_pic_marking_mode_flag) { + if (slice_reader.Read()) { uint32_t memory_management_control_operation; do { // memory_management_control_operation: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb( - memory_management_control_operation)); + memory_management_control_operation = + slice_reader.ReadExponentialGolomb(); if (memory_management_control_operation == 1 || memory_management_control_operation == 3) { // difference_of_pic_nums_minus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } if (memory_management_control_operation == 2) { // long_term_pic_num: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } if (memory_management_control_operation == 3 || memory_management_control_operation == 6) { // long_term_frame_idx: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } if (memory_management_control_operation == 4) { // max_long_term_frame_idx_plus1: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } - } while (memory_management_control_operation != 0); + } while (memory_management_control_operation != 0 && slice_reader.Ok()); } } } if (pps_->entropy_coding_mode_flag && slice_type != H264::SliceType::kI && slice_type != H264::SliceType::kSi) { // cabac_init_idc: ue(v) - RETURN_INV_ON_FAIL(slice_reader.ReadExponentialGolomb(golomb_tmp)); + slice_reader.ReadExponentialGolomb(); } - int32_t last_slice_qp_delta; - RETURN_INV_ON_FAIL( - slice_reader.ReadSignedExponentialGolomb(last_slice_qp_delta)); + int last_slice_qp_delta = slice_reader.ReadSignedExponentialGolomb(); + if (!slice_reader.Ok()) { + return kInvalidStream; + } if (abs(last_slice_qp_delta) > kMaxAbsQpDeltaValue) { // Something has gone wrong, and the parsed value is invalid. RTC_LOG(LS_WARNING) << "Parsed QP value out of range."; diff --git a/common_video/h264/pps_parser.cc b/common_video/h264/pps_parser.cc index 3d3725f95a..8e52ec19cf 100644 --- a/common_video/h264/pps_parser.cc +++ b/common_video/h264/pps_parser.cc @@ -13,23 +13,16 @@ #include #include +#include "absl/numeric/bits.h" #include "common_video/h264/h264_common.h" -#include "rtc_base/bit_buffer.h" +#include "rtc_base/bitstream_reader.h" #include "rtc_base/checks.h" -#define RETURN_EMPTY_ON_FAIL(x) \ - do { \ - if (!(x)) { \ - return absl::nullopt; \ - } \ - } while (0) - -namespace { -const int kMaxPicInitQpDeltaValue = 25; -const int kMinPicInitQpDeltaValue = -26; -} // namespace - namespace webrtc { +namespace { +constexpr int kMaxPicInitQpDeltaValue = 25; +constexpr int kMinPicInitQpDeltaValue = -26; +} // namespace // General note: this is based off the 02/2014 version of the H.264 standard. // You can find it on this page: @@ -40,9 +33,7 @@ absl::optional PpsParser::ParsePps(const uint8_t* data, // First, parse out rbsp, which is basically the source buffer minus emulation // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in // section 7.3.1 of the H.264 standard. - std::vector unpacked_buffer = H264::ParseRbsp(data, length); - rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); - return ParseInternal(&bit_buffer); + return ParseInternal(H264::ParseRbsp(data, length)); } bool PpsParser::ParsePpsIds(const uint8_t* data, @@ -55,150 +46,109 @@ bool PpsParser::ParsePpsIds(const uint8_t* data, // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in // section 7.3.1 of the H.264 standard. std::vector unpacked_buffer = H264::ParseRbsp(data, length); - rtc::BitBuffer bit_buffer(unpacked_buffer.data(), unpacked_buffer.size()); - return ParsePpsIdsInternal(&bit_buffer, pps_id, sps_id); + BitstreamReader reader(unpacked_buffer); + *pps_id = reader.ReadExponentialGolomb(); + *sps_id = reader.ReadExponentialGolomb(); + return reader.Ok(); } absl::optional PpsParser::ParsePpsIdFromSlice(const uint8_t* data, size_t length) { std::vector unpacked_buffer = H264::ParseRbsp(data, length); - rtc::BitBuffer slice_reader(unpacked_buffer.data(), unpacked_buffer.size()); + BitstreamReader slice_reader(unpacked_buffer); - uint32_t golomb_tmp; // first_mb_in_slice: ue(v) - if (!slice_reader.ReadExponentialGolomb(golomb_tmp)) - return absl::nullopt; + slice_reader.ReadExponentialGolomb(); // slice_type: ue(v) - if (!slice_reader.ReadExponentialGolomb(golomb_tmp)) - return absl::nullopt; + slice_reader.ReadExponentialGolomb(); // pic_parameter_set_id: ue(v) - uint32_t slice_pps_id; - if (!slice_reader.ReadExponentialGolomb(slice_pps_id)) + uint32_t slice_pps_id = slice_reader.ReadExponentialGolomb(); + if (!slice_reader.Ok()) { return absl::nullopt; + } return slice_pps_id; } absl::optional PpsParser::ParseInternal( - rtc::BitBuffer* bit_buffer) { + rtc::ArrayView buffer) { + BitstreamReader reader(buffer); PpsState pps; + pps.id = reader.ReadExponentialGolomb(); + pps.sps_id = reader.ReadExponentialGolomb(); - RETURN_EMPTY_ON_FAIL(ParsePpsIdsInternal(bit_buffer, &pps.id, &pps.sps_id)); - - uint32_t bits_tmp; - uint32_t golomb_ignored; // entropy_coding_mode_flag: u(1) - uint32_t entropy_coding_mode_flag; - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(1, entropy_coding_mode_flag)); - pps.entropy_coding_mode_flag = entropy_coding_mode_flag != 0; + pps.entropy_coding_mode_flag = reader.Read(); // bottom_field_pic_order_in_frame_present_flag: u(1) - uint32_t bottom_field_pic_order_in_frame_present_flag; - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadBits(1, bottom_field_pic_order_in_frame_present_flag)); - pps.bottom_field_pic_order_in_frame_present_flag = - bottom_field_pic_order_in_frame_present_flag != 0; + pps.bottom_field_pic_order_in_frame_present_flag = reader.Read(); // num_slice_groups_minus1: ue(v) - uint32_t num_slice_groups_minus1; - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadExponentialGolomb(num_slice_groups_minus1)); + uint32_t num_slice_groups_minus1 = reader.ReadExponentialGolomb(); if (num_slice_groups_minus1 > 0) { - uint32_t slice_group_map_type; // slice_group_map_type: ue(v) - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadExponentialGolomb(slice_group_map_type)); + uint32_t slice_group_map_type = reader.ReadExponentialGolomb(); if (slice_group_map_type == 0) { - for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1; - ++i_group) { + for (uint32_t i_group = 0; + i_group <= num_slice_groups_minus1 && reader.Ok(); ++i_group) { // run_length_minus1[iGroup]: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); } } else if (slice_group_map_type == 1) { // TODO(sprang): Implement support for dispersed slice group map type. // See 8.2.2.2 Specification for dispersed slice group map type. } else if (slice_group_map_type == 2) { - for (uint32_t i_group = 0; i_group <= num_slice_groups_minus1; - ++i_group) { + for (uint32_t i_group = 0; + i_group <= num_slice_groups_minus1 && reader.Ok(); ++i_group) { // top_left[iGroup]: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); // bottom_right[iGroup]: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); } } else if (slice_group_map_type == 3 || slice_group_map_type == 4 || slice_group_map_type == 5) { // slice_group_change_direction_flag: u(1) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(1, bits_tmp)); + reader.ConsumeBits(1); // slice_group_change_rate_minus1: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); } else if (slice_group_map_type == 6) { // pic_size_in_map_units_minus1: ue(v) - uint32_t pic_size_in_map_units_minus1; - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadExponentialGolomb(pic_size_in_map_units_minus1)); - uint32_t slice_group_id_bits = 0; - uint32_t num_slice_groups = num_slice_groups_minus1 + 1; - // If num_slice_groups is not a power of two an additional bit is required - // to account for the ceil() of log2() below. - if ((num_slice_groups & (num_slice_groups - 1)) != 0) - ++slice_group_id_bits; - while (num_slice_groups > 0) { - num_slice_groups >>= 1; - ++slice_group_id_bits; - } - for (uint32_t i = 0; i <= pic_size_in_map_units_minus1; i++) { - // slice_group_id[i]: u(v) - // Represented by ceil(log2(num_slice_groups_minus1 + 1)) bits. - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadBits(slice_group_id_bits, bits_tmp)); - } + uint32_t pic_size_in_map_units = reader.ReadExponentialGolomb() + 1; + int slice_group_id_bits = 1 + absl::bit_width(num_slice_groups_minus1); + + // slice_group_id: array of size pic_size_in_map_units, each element + // is represented by ceil(log2(num_slice_groups_minus1 + 1)) bits. + reader.ConsumeBits(slice_group_id_bits * pic_size_in_map_units); } } // num_ref_idx_l0_default_active_minus1: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); // num_ref_idx_l1_default_active_minus1: ue(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); // weighted_pred_flag: u(1) - uint32_t weighted_pred_flag; - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(1, weighted_pred_flag)); - pps.weighted_pred_flag = weighted_pred_flag != 0; + pps.weighted_pred_flag = reader.Read(); // weighted_bipred_idc: u(2) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(2, pps.weighted_bipred_idc)); + pps.weighted_bipred_idc = reader.ReadBits(2); // pic_init_qp_minus26: se(v) - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadSignedExponentialGolomb(pps.pic_init_qp_minus26)); + pps.pic_init_qp_minus26 = reader.ReadSignedExponentialGolomb(); // Sanity-check parsed value - if (pps.pic_init_qp_minus26 > kMaxPicInitQpDeltaValue || + if (!reader.Ok() || pps.pic_init_qp_minus26 > kMaxPicInitQpDeltaValue || pps.pic_init_qp_minus26 < kMinPicInitQpDeltaValue) { - RETURN_EMPTY_ON_FAIL(false); + return absl::nullopt; } // pic_init_qs_minus26: se(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); // chroma_qp_index_offset: se(v) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(golomb_ignored)); + reader.ReadExponentialGolomb(); // deblocking_filter_control_present_flag: u(1) // constrained_intra_pred_flag: u(1) - RETURN_EMPTY_ON_FAIL(bit_buffer->ReadBits(2, bits_tmp)); + reader.ConsumeBits(2); // redundant_pic_cnt_present_flag: u(1) - RETURN_EMPTY_ON_FAIL( - bit_buffer->ReadBits(1, pps.redundant_pic_cnt_present_flag)); + pps.redundant_pic_cnt_present_flag = reader.ReadBit(); + if (!reader.Ok()) { + return absl::nullopt; + } return pps; } -bool PpsParser::ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, - uint32_t* pps_id, - uint32_t* sps_id) { - if (pps_id == nullptr) - return false; - // pic_parameter_set_id: ue(v) - if (!bit_buffer->ReadExponentialGolomb(*pps_id)) - return false; - if (sps_id == nullptr) - return false; - // seq_parameter_set_id: ue(v) - if (!bit_buffer->ReadExponentialGolomb(*sps_id)) - return false; - return true; -} - } // namespace webrtc diff --git a/common_video/h264/pps_parser.h b/common_video/h264/pps_parser.h index d6c31b0688..52717dcc26 100644 --- a/common_video/h264/pps_parser.h +++ b/common_video/h264/pps_parser.h @@ -11,11 +11,11 @@ #ifndef COMMON_VIDEO_H264_PPS_PARSER_H_ #define COMMON_VIDEO_H264_PPS_PARSER_H_ -#include "absl/types/optional.h" +#include +#include -namespace rtc { -class BitBuffer; -} +#include "absl/types/optional.h" +#include "api/array_view.h" namespace webrtc { @@ -49,12 +49,10 @@ class PpsParser { size_t length); protected: - // Parse the PPS state, for a bit buffer where RBSP decoding has already been + // Parse the PPS state, for a buffer where RBSP decoding has already been // performed. - static absl::optional ParseInternal(rtc::BitBuffer* bit_buffer); - static bool ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, - uint32_t* pps_id, - uint32_t* sps_id); + static absl::optional ParseInternal( + rtc::ArrayView buffer); }; } // namespace webrtc diff --git a/common_video/h264/pps_parser_unittest.cc b/common_video/h264/pps_parser_unittest.cc index a279563f85..f5b03dccfd 100644 --- a/common_video/h264/pps_parser_unittest.cc +++ b/common_video/h264/pps_parser_unittest.cc @@ -174,7 +174,7 @@ class PpsParserTest : public ::testing::Test { WritePps(pps, slice_group_map_type, num_slice_groups, pic_size_in_map_units, &buffer_); parsed_pps_ = PpsParser::ParsePps(buffer_.data(), buffer_.size()); - EXPECT_TRUE(static_cast(parsed_pps_)); + ASSERT_TRUE(parsed_pps_); EXPECT_EQ(pps.bottom_field_pic_order_in_frame_present_flag, parsed_pps_->bottom_field_pic_order_in_frame_present_flag); EXPECT_EQ(pps.weighted_pred_flag, parsed_pps_->weighted_pred_flag);