diff --git a/common_video/h264/h264_bitstream_parser.cc b/common_video/h264/h264_bitstream_parser.cc index 9f02a96d12..38cf0ff6e6 100644 --- a/common_video/h264/h264_bitstream_parser.cc +++ b/common_video/h264/h264_bitstream_parser.cc @@ -31,15 +31,13 @@ H264BitstreamParser::H264BitstreamParser() = default; H264BitstreamParser::~H264BitstreamParser() = default; H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( - const uint8_t* source, - size_t source_length, + rtc::ArrayView source, uint8_t nalu_type) { if (!sps_ || !pps_) return kInvalidStream; last_slice_qp_delta_ = absl::nullopt; - const std::vector slice_rbsp = - H264::ParseRbsp(source, source_length); + const std::vector slice_rbsp = H264::ParseRbsp(source); if (slice_rbsp.size() < H264::kNaluTypeSize) return kInvalidStream; @@ -308,19 +306,17 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu( return kOk; } -void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { +void H264BitstreamParser::ParseSlice(rtc::ArrayView slice) { H264::NaluType nalu_type = H264::ParseNaluType(slice[0]); switch (nalu_type) { case H264::NaluType::kSps: { - sps_ = SpsParser::ParseSps(slice + H264::kNaluTypeSize, - length - H264::kNaluTypeSize); + sps_ = SpsParser::ParseSps(slice.subview(H264::kNaluTypeSize)); if (!sps_) RTC_DLOG(LS_WARNING) << "Unable to parse SPS from H264 bitstream."; break; } case H264::NaluType::kPps: { - pps_ = PpsParser::ParsePps(slice + H264::kNaluTypeSize, - length - H264::kNaluTypeSize); + pps_ = PpsParser::ParsePps(slice.subview(H264::kNaluTypeSize)); if (!pps_) RTC_DLOG(LS_WARNING) << "Unable to parse PPS from H264 bitstream."; break; @@ -330,7 +326,7 @@ void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { case H264::NaluType::kPrefix: break; // Ignore these nalus, as we don't care about their contents. default: - Result res = ParseNonParameterSetNalu(slice, length, nalu_type); + Result res = ParseNonParameterSetNalu(slice, nalu_type); if (res != kOk) RTC_DLOG(LS_INFO) << "Failed to parse bitstream. Error: " << res; break; @@ -339,11 +335,10 @@ void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { void H264BitstreamParser::ParseBitstream( rtc::ArrayView bitstream) { - std::vector nalu_indices = - H264::FindNaluIndices(bitstream.data(), bitstream.size()); + std::vector nalu_indices = H264::FindNaluIndices(bitstream); for (const H264::NaluIndex& index : nalu_indices) - ParseSlice(bitstream.data() + index.payload_start_offset, - index.payload_size); + ParseSlice( + bitstream.subview(index.payload_start_offset, index.payload_size)); } absl::optional H264BitstreamParser::GetLastSliceQp() const { diff --git a/common_video/h264/h264_bitstream_parser.h b/common_video/h264/h264_bitstream_parser.h index 05427825ac..1fad9895f9 100644 --- a/common_video/h264/h264_bitstream_parser.h +++ b/common_video/h264/h264_bitstream_parser.h @@ -40,9 +40,8 @@ class H264BitstreamParser : public BitstreamParser { kInvalidStream, kUnsupportedStream, }; - void ParseSlice(const uint8_t* slice, size_t length); - Result ParseNonParameterSetNalu(const uint8_t* source, - size_t source_length, + void ParseSlice(rtc::ArrayView slice); + Result ParseNonParameterSetNalu(rtc::ArrayView source, uint8_t nalu_type); // SPS/PPS state, updated when parsing new SPS/PPS, used to parse slices. diff --git a/common_video/h264/h264_common.cc b/common_video/h264/h264_common.cc index 06d94e0305..b9316421a5 100644 --- a/common_video/h264/h264_common.cc +++ b/common_video/h264/h264_common.cc @@ -17,19 +17,18 @@ namespace H264 { const uint8_t kNaluTypeMask = 0x1F; -std::vector FindNaluIndices(const uint8_t* buffer, - size_t buffer_size) { +std::vector FindNaluIndices(rtc::ArrayView buffer) { // This is sorta like Boyer-Moore, but with only the first optimization step: // given a 3-byte sequence we're looking at, if the 3rd byte isn't 1 or 0, // skip ahead to the next 3-byte sequence. 0s and 1s are relatively rare, so // this will skip the majority of reads/checks. std::vector sequences; - if (buffer_size < kNaluShortStartSequenceSize) + if (buffer.size() < kNaluShortStartSequenceSize) return sequences; static_assert(kNaluShortStartSequenceSize >= 2, "kNaluShortStartSequenceSize must be larger or equals to 2"); - const size_t end = buffer_size - kNaluShortStartSequenceSize; + const size_t end = buffer.size() - kNaluShortStartSequenceSize; for (size_t i = 0; i < end;) { if (buffer[i + 2] > 1) { i += 3; @@ -57,7 +56,7 @@ std::vector FindNaluIndices(const uint8_t* buffer, // Update length of last entry, if any. auto it = sequences.rbegin(); if (it != sequences.rend()) - it->payload_size = buffer_size - it->payload_start_offset; + it->payload_size = buffer.size() - it->payload_start_offset; return sequences; } @@ -66,16 +65,16 @@ NaluType ParseNaluType(uint8_t data) { return static_cast(data & kNaluTypeMask); } -std::vector ParseRbsp(const uint8_t* data, size_t length) { +std::vector ParseRbsp(rtc::ArrayView data) { std::vector out; - out.reserve(length); + out.reserve(data.size()); - for (size_t i = 0; i < length;) { + for (size_t i = 0; i < data.size();) { // Be careful about over/underflow here. byte_length_ - 3 can underflow, and // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_ // above, and that expression will produce the number of bytes left in // the stream including the byte at i. - if (length - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) { + if (data.size() - i >= 3 && !data[i] && !data[i + 1] && data[i + 2] == 3) { // Two rbsp bytes. out.push_back(data[i++]); out.push_back(data[i++]); @@ -89,14 +88,13 @@ std::vector ParseRbsp(const uint8_t* data, size_t length) { return out; } -void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination) { +void WriteRbsp(rtc::ArrayView bytes, rtc::Buffer* destination) { static const uint8_t kZerosInStartSequence = 2; static const uint8_t kEmulationByte = 0x03u; size_t num_consecutive_zeros = 0; - destination->EnsureCapacity(destination->size() + length); + destination->EnsureCapacity(destination->size() + bytes.size()); - for (size_t i = 0; i < length; ++i) { - uint8_t byte = bytes[i]; + for (uint8_t byte : bytes) { if (byte <= kEmulationByte && num_consecutive_zeros >= kZerosInStartSequence) { // Need to escape. diff --git a/common_video/h264/h264_common.h b/common_video/h264/h264_common.h index a55d6470e8..e7df02ae0d 100644 --- a/common_video/h264/h264_common.h +++ b/common_video/h264/h264_common.h @@ -63,8 +63,14 @@ struct NaluIndex { }; // Returns a vector of the NALU indices in the given buffer. -RTC_EXPORT std::vector FindNaluIndices(const uint8_t* buffer, - size_t buffer_size); +RTC_EXPORT std::vector FindNaluIndices( + rtc::ArrayView buffer); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline std::vector FindNaluIndices(const uint8_t* buffer, + size_t buffer_size) { + return FindNaluIndices(rtc::MakeArrayView(buffer, buffer_size)); +} // Get the NAL type from the header byte immediately following start sequence. RTC_EXPORT NaluType ParseNaluType(uint8_t data); @@ -83,12 +89,24 @@ RTC_EXPORT NaluType ParseNaluType(uint8_t data); // the 03 emulation byte. // Parse the given data and remove any emulation byte escaping. -std::vector ParseRbsp(const uint8_t* data, size_t length); +std::vector ParseRbsp(rtc::ArrayView data); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline std::vector ParseRbsp(const uint8_t* data, size_t length) { + return ParseRbsp(rtc::MakeArrayView(data, length)); +} // Write the given data to the destination buffer, inserting and emulation // bytes in order to escape any data the could be interpreted as a start // sequence. -void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination); +void WriteRbsp(rtc::ArrayView bytes, rtc::Buffer* destination); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline void WriteRbsp(const uint8_t* bytes, + size_t length, + rtc::Buffer* destination) { + WriteRbsp(rtc::MakeArrayView(bytes, length), destination); +} } // namespace H264 } // namespace webrtc diff --git a/common_video/h264/pps_parser.cc b/common_video/h264/pps_parser.cc index 46105d5b9f..f12ab9b0af 100644 --- a/common_video/h264/pps_parser.cc +++ b/common_video/h264/pps_parser.cc @@ -29,16 +29,15 @@ constexpr int kMinPicInitQpDeltaValue = -26; // You can find it on this page: // http://www.itu.int/rec/T-REC-H.264 -absl::optional PpsParser::ParsePps(const uint8_t* data, - size_t length) { +absl::optional PpsParser::ParsePps( + rtc::ArrayView 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. - return ParseInternal(H264::ParseRbsp(data, length)); + return ParseInternal(H264::ParseRbsp(data)); } -bool PpsParser::ParsePpsIds(const uint8_t* data, - size_t length, +bool PpsParser::ParsePpsIds(rtc::ArrayView data, uint32_t* pps_id, uint32_t* sps_id) { RTC_DCHECK(pps_id); @@ -46,7 +45,7 @@ bool PpsParser::ParsePpsIds(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); + std::vector unpacked_buffer = H264::ParseRbsp(data); BitstreamReader reader(unpacked_buffer); *pps_id = reader.ReadExponentialGolomb(); *sps_id = reader.ReadExponentialGolomb(); @@ -54,9 +53,8 @@ bool PpsParser::ParsePpsIds(const uint8_t* data, } absl::optional PpsParser::ParseSliceHeader( - const uint8_t* data, - size_t length) { - std::vector unpacked_buffer = H264::ParseRbsp(data, length); + rtc::ArrayView data) { + std::vector unpacked_buffer = H264::ParseRbsp(data); BitstreamReader slice_reader(unpacked_buffer); PpsParser::SliceHeader slice_header; diff --git a/common_video/h264/pps_parser.h b/common_video/h264/pps_parser.h index 298c55e8d9..d2d0609ab9 100644 --- a/common_video/h264/pps_parser.h +++ b/common_video/h264/pps_parser.h @@ -47,15 +47,19 @@ class PpsParser { }; // Unpack RBSP and parse PPS state from the supplied buffer. - static absl::optional ParsePps(const uint8_t* data, size_t length); + static absl::optional ParsePps(rtc::ArrayView data); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline absl::optional ParsePps(const uint8_t* data, + size_t length) { + return ParsePps(rtc::MakeArrayView(data, length)); + } - static bool ParsePpsIds(const uint8_t* data, - size_t length, + static bool ParsePpsIds(rtc::ArrayView data, uint32_t* pps_id, uint32_t* sps_id); - static absl::optional ParseSliceHeader(const uint8_t* data, - size_t length); + static absl::optional ParseSliceHeader( + rtc::ArrayView data); protected: // Parse the PPS state, for a buffer where RBSP decoding has already been diff --git a/common_video/h264/pps_parser_unittest.cc b/common_video/h264/pps_parser_unittest.cc index 833a39c8f7..a325e8ccf4 100644 --- a/common_video/h264/pps_parser_unittest.cc +++ b/common_video/h264/pps_parser_unittest.cc @@ -134,7 +134,7 @@ void WritePps(const PpsParser::PpsState& pps, bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset); } - H264::WriteRbsp(data, byte_offset, out_buffer); + H264::WriteRbsp(rtc::MakeArrayView(data, byte_offset), out_buffer); } class PpsParserTest : public ::testing::Test { @@ -175,7 +175,7 @@ class PpsParserTest : public ::testing::Test { buffer_.Clear(); WritePps(pps, slice_group_map_type, num_slice_groups, pic_size_in_map_units, &buffer_); - parsed_pps_ = PpsParser::ParsePps(buffer_.data(), buffer_.size()); + parsed_pps_ = PpsParser::ParsePps(buffer_); 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); @@ -219,18 +219,17 @@ TEST_F(PpsParserTest, MaxPps) { } TEST_F(PpsParserTest, ParseSliceHeader) { - std::vector nalu_indices = - H264::FindNaluIndices(kH264BitstreamChunk, sizeof(kH264BitstreamChunk)); + rtc::ArrayView chunk(kH264BitstreamChunk); + std::vector nalu_indices = H264::FindNaluIndices(chunk); EXPECT_EQ(nalu_indices.size(), 3ull); for (const auto& index : nalu_indices) { H264::NaluType nalu_type = - H264::ParseNaluType(kH264BitstreamChunk[index.payload_start_offset]); + H264::ParseNaluType(chunk[index.payload_start_offset]); if (nalu_type == H264::NaluType::kIdr) { // Skip NAL type header and parse slice header. absl::optional slice_header = - PpsParser::ParseSliceHeader( - kH264BitstreamChunk + index.payload_start_offset + 1, - index.payload_size - 1); + PpsParser::ParseSliceHeader(chunk.subview( + index.payload_start_offset + 1, index.payload_size - 1)); ASSERT_TRUE(slice_header.has_value()); EXPECT_EQ(slice_header->first_mb_in_slice, 0u); EXPECT_EQ(slice_header->pic_parameter_set_id, 0u); diff --git a/common_video/h264/sps_parser.cc b/common_video/h264/sps_parser.cc index 6206c39f5f..000e028a32 100644 --- a/common_video/h264/sps_parser.cc +++ b/common_video/h264/sps_parser.cc @@ -32,9 +32,9 @@ SpsParser::SpsState::~SpsState() = default; // http://www.itu.int/rec/T-REC-H.264 // Unpack RBSP and parse SPS state from the supplied buffer. -absl::optional SpsParser::ParseSps(const uint8_t* data, - size_t length) { - std::vector unpacked_buffer = H264::ParseRbsp(data, length); +absl::optional SpsParser::ParseSps( + rtc::ArrayView data) { + std::vector unpacked_buffer = H264::ParseRbsp(data); BitstreamReader reader(unpacked_buffer); return ParseSpsUpToVui(reader); } diff --git a/common_video/h264/sps_parser.h b/common_video/h264/sps_parser.h index d0d7371e61..ae8df60792 100644 --- a/common_video/h264/sps_parser.h +++ b/common_video/h264/sps_parser.h @@ -42,7 +42,12 @@ class RTC_EXPORT SpsParser { }; // Unpack RBSP and parse SPS state from the supplied buffer. - static absl::optional ParseSps(const uint8_t* data, size_t length); + static absl::optional ParseSps(rtc::ArrayView data); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline absl::optional ParseSps(const uint8_t* data, + size_t length) { + return ParseSps(rtc::MakeArrayView(data, length)); + } protected: // Parse the SPS state, up till the VUI part, for a buffer where RBSP diff --git a/common_video/h264/sps_parser_unittest.cc b/common_video/h264/sps_parser_unittest.cc index c9326e4b28..721aa3f051 100644 --- a/common_video/h264/sps_parser_unittest.cc +++ b/common_video/h264/sps_parser_unittest.cc @@ -107,7 +107,7 @@ void GenerateFakeSps(uint16_t width, } out_buffer->Clear(); - H264::WriteRbsp(rbsp, byte_count, out_buffer); + H264::WriteRbsp(rtc::MakeArrayView(rbsp, byte_count), out_buffer); } TEST(H264SpsParserTest, TestSampleSPSHdLandscape) { @@ -116,8 +116,7 @@ TEST(H264SpsParserTest, TestSampleSPSHdLandscape) { const uint8_t buffer[] = {0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50, 0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x2A, 0xE0, 0xF1, 0x83, 0x19, 0x60}; - absl::optional sps = - SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(1280u, sps->width); EXPECT_EQ(720u, sps->height); @@ -129,8 +128,7 @@ TEST(H264SpsParserTest, TestSampleSPSVgaLandscape) { const uint8_t buffer[] = {0x7A, 0x00, 0x1E, 0xBC, 0xD9, 0x40, 0xA0, 0x2F, 0xF8, 0x98, 0x40, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x56, 0x83, 0xC5, 0x8B, 0x65, 0x80}; - absl::optional sps = - SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(640u, sps->width); EXPECT_EQ(360u, sps->height); @@ -142,8 +140,7 @@ TEST(H264SpsParserTest, TestSampleSPSWeirdResolution) { const uint8_t buffer[] = {0x7A, 0x00, 0x0D, 0xBC, 0xD9, 0x43, 0x43, 0x3E, 0x5E, 0x10, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x15, 0xA0, 0xF1, 0x42, 0x99, 0x60}; - absl::optional sps = - SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(200u, sps->width); EXPECT_EQ(400u, sps->height); @@ -152,8 +149,7 @@ TEST(H264SpsParserTest, TestSampleSPSWeirdResolution) { TEST(H264SpsParserTest, TestSyntheticSPSQvgaLandscape) { rtc::Buffer buffer; GenerateFakeSps(320u, 180u, 1, 0, 0, &buffer); - absl::optional sps = - SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -163,8 +159,7 @@ TEST(H264SpsParserTest, TestSyntheticSPSQvgaLandscape) { TEST(H264SpsParserTest, TestSyntheticSPSWeirdResolution) { rtc::Buffer buffer; GenerateFakeSps(156u, 122u, 2, 0, 0, &buffer); - absl::optional sps = - SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(156u, sps->width); EXPECT_EQ(122u, sps->height); @@ -178,8 +173,7 @@ TEST(H264SpsParserTest, TestSampleSPSWithScalingLists) { 0x10, 0xc2, 0x00, 0x84, 0x3b, 0x50, 0x3c, 0x01, 0x13, 0xf2, 0xcd, 0xc0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0xe8, 0x40}; - absl::optional sps = - SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(1920u, sps->width); EXPECT_EQ(1080u, sps->height); @@ -188,8 +182,7 @@ TEST(H264SpsParserTest, TestSampleSPSWithScalingLists) { TEST(H264SpsParserTest, TestLog2MaxFrameNumMinus4) { rtc::Buffer buffer; GenerateFakeSps(320u, 180u, 1, 0, 0, &buffer); - absl::optional sps = - SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -197,7 +190,7 @@ TEST(H264SpsParserTest, TestLog2MaxFrameNumMinus4) { EXPECT_EQ(4u, sps->log2_max_frame_num); GenerateFakeSps(320u, 180u, 1, 12, 0, &buffer); - sps = SpsParser::ParseSps(buffer.data(), buffer.size()); + sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -205,14 +198,13 @@ TEST(H264SpsParserTest, TestLog2MaxFrameNumMinus4) { EXPECT_EQ(16u, sps->log2_max_frame_num); GenerateFakeSps(320u, 180u, 1, 13, 0, &buffer); - EXPECT_FALSE(SpsParser::ParseSps(buffer.data(), buffer.size())); + EXPECT_FALSE(SpsParser::ParseSps(buffer)); } TEST(H264SpsParserTest, TestLog2MaxPicOrderCntMinus4) { rtc::Buffer buffer; GenerateFakeSps(320u, 180u, 1, 0, 0, &buffer); - absl::optional sps = - SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -220,15 +212,14 @@ TEST(H264SpsParserTest, TestLog2MaxPicOrderCntMinus4) { EXPECT_EQ(4u, sps->log2_max_pic_order_cnt_lsb); GenerateFakeSps(320u, 180u, 1, 0, 12, &buffer); - EXPECT_TRUE(static_cast( - sps = SpsParser::ParseSps(buffer.data(), buffer.size()))); + EXPECT_TRUE(static_cast(sps = SpsParser::ParseSps(buffer))); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); EXPECT_EQ(1u, sps->id); EXPECT_EQ(16u, sps->log2_max_pic_order_cnt_lsb); GenerateFakeSps(320u, 180u, 1, 0, 13, &buffer); - EXPECT_FALSE(SpsParser::ParseSps(buffer.data(), buffer.size())); + EXPECT_FALSE(SpsParser::ParseSps(buffer)); } } // namespace webrtc diff --git a/common_video/h264/sps_vui_rewriter.cc b/common_video/h264/sps_vui_rewriter.cc index 117e92a1e5..07b5805148 100644 --- a/common_video/h264/sps_vui_rewriter.cc +++ b/common_video/h264/sps_vui_rewriter.cc @@ -135,14 +135,13 @@ void SpsVuiRewriter::UpdateStats(ParseResult result, Direction direction) { } SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( - const uint8_t* buffer, - size_t length, + rtc::ArrayView buffer, absl::optional* sps, const webrtc::ColorSpace* color_space, rtc::Buffer* destination) { // Create temporary RBSP decoded buffer of the payload (exlcuding the // leading nalu type header byte (the SpsParser uses only the payload). - std::vector rbsp_buffer = H264::ParseRbsp(buffer, length); + std::vector rbsp_buffer = H264::ParseRbsp(buffer); BitstreamReader source_buffer(rbsp_buffer); absl::optional sps_state = SpsParser::ParseSpsUpToVui(source_buffer); @@ -153,7 +152,7 @@ SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( // We're going to completely muck up alignment, so we need a BitBufferWriter // to write with. - rtc::Buffer out_buffer(length + kMaxVuiSpsIncrease); + rtc::Buffer out_buffer(buffer.size() + kMaxVuiSpsIncrease); rtc::BitBufferWriter sps_writer(out_buffer.data(), out_buffer.size()); // Check how far the SpsParser has read, and copy that data in bulk. @@ -200,26 +199,25 @@ SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( bit_offset = 0; } - RTC_DCHECK(byte_offset <= length + kMaxVuiSpsIncrease); + RTC_DCHECK(byte_offset <= buffer.size() + kMaxVuiSpsIncrease); RTC_CHECK(destination != nullptr); out_buffer.SetSize(byte_offset); // Write updates SPS to destination with added RBSP - H264::WriteRbsp(out_buffer.data(), out_buffer.size(), destination); + H264::WriteRbsp(out_buffer, destination); return ParseResult::kVuiRewritten; } SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( - const uint8_t* buffer, - size_t length, + rtc::ArrayView buffer, absl::optional* sps, const webrtc::ColorSpace* color_space, rtc::Buffer* destination, Direction direction) { ParseResult result = - ParseAndRewriteSps(buffer, length, sps, color_space, destination); + ParseAndRewriteSps(buffer, sps, color_space, destination); UpdateStats(result, direction); return result; } @@ -227,22 +225,21 @@ SpsVuiRewriter::ParseResult SpsVuiRewriter::ParseAndRewriteSps( rtc::Buffer SpsVuiRewriter::ParseOutgoingBitstreamAndRewrite( rtc::ArrayView buffer, const webrtc::ColorSpace* color_space) { - std::vector nalus = - H264::FindNaluIndices(buffer.data(), buffer.size()); + std::vector nalus = H264::FindNaluIndices(buffer); // Allocate some extra space for potentially adding a missing VUI. rtc::Buffer output_buffer(/*size=*/0, /*capacity=*/buffer.size() + nalus.size() * kMaxVuiSpsIncrease); - for (const H264::NaluIndex& nalu : nalus) { + for (const H264::NaluIndex& nalu_index : nalus) { // Copy NAL unit start code. - const uint8_t* start_code_ptr = buffer.data() + nalu.start_offset; - const size_t start_code_length = - nalu.payload_start_offset - nalu.start_offset; - const uint8_t* nalu_ptr = buffer.data() + nalu.payload_start_offset; - const size_t nalu_length = nalu.payload_size; + rtc::ArrayView start_code = buffer.subview( + nalu_index.start_offset, + nalu_index.payload_start_offset - nalu_index.start_offset); + rtc::ArrayView nalu = buffer.subview( + nalu_index.payload_start_offset, nalu_index.payload_size); - if (H264::ParseNaluType(nalu_ptr[0]) == H264::NaluType::kSps) { + if (H264::ParseNaluType(nalu[0]) == H264::NaluType::kSps) { // Check if stream uses picture order count type 0, and if so rewrite it // to enable faster decoding. Streams in that format incur additional // delay because it allows decode order to differ from render order. @@ -259,24 +256,24 @@ rtc::Buffer SpsVuiRewriter::ParseOutgoingBitstreamAndRewrite( // Add the type header to the output buffer first, so that the rewriter // can append modified payload on top of that. - output_nalu.AppendData(nalu_ptr[0]); + output_nalu.AppendData(nalu[0]); - ParseResult result = ParseAndRewriteSps( - nalu_ptr + H264::kNaluTypeSize, nalu_length - H264::kNaluTypeSize, - &sps, color_space, &output_nalu, Direction::kOutgoing); + ParseResult result = + ParseAndRewriteSps(nalu.subview(H264::kNaluTypeSize), &sps, + color_space, &output_nalu, Direction::kOutgoing); if (result == ParseResult::kVuiRewritten) { - output_buffer.AppendData(start_code_ptr, start_code_length); + output_buffer.AppendData(start_code); output_buffer.AppendData(output_nalu.data(), output_nalu.size()); continue; } - } else if (H264::ParseNaluType(nalu_ptr[0]) == H264::NaluType::kAud) { + } else if (H264::ParseNaluType(nalu[0]) == H264::NaluType::kAud) { // Skip the access unit delimiter copy. continue; } // vui wasn't rewritten and it is not aud, copy the nal unit as is. - output_buffer.AppendData(start_code_ptr, start_code_length); - output_buffer.AppendData(nalu_ptr, nalu_length); + output_buffer.AppendData(start_code); + output_buffer.AppendData(nalu); } return output_buffer; } diff --git a/common_video/h264/sps_vui_rewriter.h b/common_video/h264/sps_vui_rewriter.h index ef80d5b60e..66f7e1a702 100644 --- a/common_video/h264/sps_vui_rewriter.h +++ b/common_video/h264/sps_vui_rewriter.h @@ -43,8 +43,7 @@ class SpsVuiRewriter : private SpsParser { // (NALU start, type, Stap-A, etc) have already been parsed and that RBSP // decoding has been performed. static ParseResult ParseAndRewriteSps( - const uint8_t* buffer, - size_t length, + rtc::ArrayView buffer, absl::optional* sps, const ColorSpace* color_space, rtc::Buffer* destination, @@ -58,8 +57,7 @@ class SpsVuiRewriter : private SpsParser { private: static ParseResult ParseAndRewriteSps( - const uint8_t* buffer, - size_t length, + rtc::ArrayView buffer, absl::optional* sps, const ColorSpace* color_space, rtc::Buffer* destination); diff --git a/common_video/h264/sps_vui_rewriter_unittest.cc b/common_video/h264/sps_vui_rewriter_unittest.cc index 2907949e6c..d440905375 100644 --- a/common_video/h264/sps_vui_rewriter_unittest.cc +++ b/common_video/h264/sps_vui_rewriter_unittest.cc @@ -297,7 +297,7 @@ void GenerateFakeSps(const VuiHeader& vui, rtc::Buffer* out_buffer) { byte_count++; } - H264::WriteRbsp(rbsp, byte_count, out_buffer); + H264::WriteRbsp(rtc::MakeArrayView(rbsp, byte_count), out_buffer); } void TestSps(const VuiHeader& vui, @@ -310,8 +310,8 @@ void TestSps(const VuiHeader& vui, absl::optional sps; rtc::Buffer rewritten_sps; SpsVuiRewriter::ParseResult result = SpsVuiRewriter::ParseAndRewriteSps( - original_sps.data(), original_sps.size(), &sps, color_space, - &rewritten_sps, SpsVuiRewriter::Direction::kIncoming); + original_sps, &sps, color_space, &rewritten_sps, + SpsVuiRewriter::Direction::kIncoming); EXPECT_EQ(expected_parse_result, result); ASSERT_TRUE(sps); EXPECT_EQ(sps->width, kWidth); @@ -324,7 +324,7 @@ void TestSps(const VuiHeader& vui, // Ensure that added/rewritten SPS is parsable. rtc::Buffer tmp; result = SpsVuiRewriter::ParseAndRewriteSps( - rewritten_sps.data(), rewritten_sps.size(), &sps, nullptr, &tmp, + rewritten_sps, &sps, nullptr, &tmp, SpsVuiRewriter::Direction::kIncoming); EXPECT_EQ(SpsVuiRewriter::ParseResult::kVuiOk, result); ASSERT_TRUE(sps); diff --git a/common_video/h265/h265_bitstream_parser.cc b/common_video/h265/h265_bitstream_parser.cc index 3287d78e6b..c9d17b0628 100644 --- a/common_video/h265/h265_bitstream_parser.cc +++ b/common_video/h265/h265_bitstream_parser.cc @@ -80,13 +80,11 @@ H265BitstreamParser::~H265BitstreamParser() = default; // section 7.3.6.1. You can find it on this page: // http://www.itu.int/rec/T-REC-H.265 H265BitstreamParser::Result H265BitstreamParser::ParseNonParameterSetNalu( - const uint8_t* source, - size_t source_length, + rtc::ArrayView source, uint8_t nalu_type) { last_slice_qp_delta_ = absl::nullopt; last_slice_pps_id_ = absl::nullopt; - const std::vector slice_rbsp = - H265::ParseRbsp(source, source_length); + const std::vector slice_rbsp = H265::ParseRbsp(source); if (slice_rbsp.size() < H265::kNaluHeaderSize) return kInvalidStream; @@ -420,14 +418,14 @@ const H265SpsParser::SpsState* H265BitstreamParser::GetSPS(uint32_t id) const { return &it->second; } -void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { +void H265BitstreamParser::ParseSlice(rtc::ArrayView slice) { H265::NaluType nalu_type = H265::ParseNaluType(slice[0]); switch (nalu_type) { case H265::NaluType::kVps: { absl::optional vps_state; - if (length >= H265::kNaluHeaderSize) { - vps_state = H265VpsParser::ParseVps(slice + H265::kNaluHeaderSize, - length - H265::kNaluHeaderSize); + if (slice.size() >= H265::kNaluHeaderSize) { + vps_state = + H265VpsParser::ParseVps(slice.subview(H265::kNaluHeaderSize)); } if (!vps_state) { @@ -439,9 +437,9 @@ void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { } case H265::NaluType::kSps: { absl::optional sps_state; - if (length >= H265::kNaluHeaderSize) { - sps_state = H265SpsParser::ParseSps(slice + H265::kNaluHeaderSize, - length - H265::kNaluHeaderSize); + if (slice.size() >= H265::kNaluHeaderSize) { + sps_state = + H265SpsParser::ParseSps(slice.subview(H265::kNaluHeaderSize)); } if (!sps_state) { RTC_LOG(LS_WARNING) << "Unable to parse SPS from H265 bitstream."; @@ -452,9 +450,9 @@ void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { } case H265::NaluType::kPps: { absl::optional pps_state; - if (length >= H265::kNaluHeaderSize) { - std::vector unpacked_buffer = H265::ParseRbsp( - slice + H265::kNaluHeaderSize, length - H265::kNaluHeaderSize); + if (slice.size() >= H265::kNaluHeaderSize) { + std::vector unpacked_buffer = + H265::ParseRbsp(slice.subview(H265::kNaluHeaderSize)); BitstreamReader slice_reader(unpacked_buffer); // pic_parameter_set_id: ue(v) uint32_t pps_id = slice_reader.ReadExponentialGolomb(); @@ -463,8 +461,8 @@ void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { uint32_t sps_id = slice_reader.ReadExponentialGolomb(); IN_RANGE_OR_RETURN_VOID(sps_id, 0, 15); const H265SpsParser::SpsState* sps = GetSPS(sps_id); - pps_state = H265PpsParser::ParsePps( - slice + H265::kNaluHeaderSize, length - H265::kNaluHeaderSize, sps); + pps_state = + H265PpsParser::ParsePps(slice.subview(H265::kNaluHeaderSize), sps); } if (!pps_state) { RTC_LOG(LS_WARNING) << "Unable to parse PPS from H265 bitstream."; @@ -480,7 +478,7 @@ void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { case H265::NaluType::kFu: break; default: - Result res = ParseNonParameterSetNalu(slice, length, nalu_type); + Result res = ParseNonParameterSetNalu(slice, nalu_type); if (res != kOk) { RTC_LOG(LS_INFO) << "Failed to parse bitstream. Error: " << res; } @@ -489,10 +487,10 @@ void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { } absl::optional -H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp(const uint8_t* data, - size_t length, - uint8_t nalu_type) { - std::vector unpacked_buffer = H265::ParseRbsp(data, length); +H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp( + rtc::ArrayView data, + uint8_t nalu_type) { + std::vector unpacked_buffer = H265::ParseRbsp(data); BitstreamReader slice_reader(unpacked_buffer); // first_slice_segment_in_pic_flag: u(1) @@ -519,10 +517,10 @@ H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp(const uint8_t* data, void H265BitstreamParser::ParseBitstream( rtc::ArrayView bitstream) { - std::vector nalu_indices = - H265::FindNaluIndices(bitstream.data(), bitstream.size()); + std::vector nalu_indices = H265::FindNaluIndices(bitstream); for (const H265::NaluIndex& index : nalu_indices) - ParseSlice(&bitstream[index.payload_start_offset], index.payload_size); + ParseSlice( + bitstream.subview(index.payload_start_offset, index.payload_size)); } absl::optional H265BitstreamParser::GetLastSliceQp() const { diff --git a/common_video/h265/h265_bitstream_parser.h b/common_video/h265/h265_bitstream_parser.h index 48f27ef2e7..cf18ccb686 100644 --- a/common_video/h265/h265_bitstream_parser.h +++ b/common_video/h265/h265_bitstream_parser.h @@ -40,8 +40,7 @@ class RTC_EXPORT H265BitstreamParser : public BitstreamParser { absl::optional GetLastSlicePpsId() const; static absl::optional ParsePpsIdFromSliceSegmentLayerRbsp( - const uint8_t* data, - size_t length, + rtc::ArrayView data, uint8_t nalu_type); protected: @@ -50,9 +49,8 @@ class RTC_EXPORT H265BitstreamParser : public BitstreamParser { kInvalidStream, kUnsupportedStream, }; - void ParseSlice(const uint8_t* slice, size_t length); - Result ParseNonParameterSetNalu(const uint8_t* source, - size_t source_length, + void ParseSlice(rtc::ArrayView slice); + Result ParseNonParameterSetNalu(rtc::ArrayView source, uint8_t nalu_type); const H265PpsParser::PpsState* GetPPS(uint32_t id) const; diff --git a/common_video/h265/h265_bitstream_parser_unittest.cc b/common_video/h265/h265_bitstream_parser_unittest.cc index 7ca979433a..5889c70589 100644 --- a/common_video/h265/h265_bitstream_parser_unittest.cc +++ b/common_video/h265/h265_bitstream_parser_unittest.cc @@ -127,8 +127,8 @@ TEST(H265BitstreamParserTest, ReportsLastSliceQpFromShortTermReferenceSlices) { TEST(H265BitstreamParserTest, PpsIdFromSlice) { H265BitstreamParser h265_parser; absl::optional pps_id = - h265_parser.ParsePpsIdFromSliceSegmentLayerRbsp( - kH265SliceChunk, sizeof(kH265SliceChunk), H265::NaluType::kTrailR); + h265_parser.ParsePpsIdFromSliceSegmentLayerRbsp(kH265SliceChunk, + H265::NaluType::kTrailR); ASSERT_TRUE(pps_id); EXPECT_EQ(1u, *pps_id); } diff --git a/common_video/h265/h265_common.cc b/common_video/h265/h265_common.cc index 70864495bc..28b29e98a7 100644 --- a/common_video/h265/h265_common.cc +++ b/common_video/h265/h265_common.cc @@ -17,10 +17,8 @@ namespace H265 { constexpr uint8_t kNaluTypeMask = 0x7E; -std::vector FindNaluIndices(const uint8_t* buffer, - size_t buffer_size) { - std::vector indices = - H264::FindNaluIndices(buffer, buffer_size); +std::vector FindNaluIndices(rtc::ArrayView buffer) { + std::vector indices = H264::FindNaluIndices(buffer); std::vector results; for (auto& index : indices) { results.push_back( @@ -33,12 +31,12 @@ NaluType ParseNaluType(uint8_t data) { return static_cast((data & kNaluTypeMask) >> 1); } -std::vector ParseRbsp(const uint8_t* data, size_t length) { - return H264::ParseRbsp(data, length); +std::vector ParseRbsp(rtc::ArrayView data) { + return H264::ParseRbsp(data); } -void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination) { - H264::WriteRbsp(bytes, length, destination); +void WriteRbsp(rtc::ArrayView bytes, rtc::Buffer* destination) { + H264::WriteRbsp(bytes, destination); } uint32_t Log2Ceiling(uint32_t value) { diff --git a/common_video/h265/h265_common.h b/common_video/h265/h265_common.h index b9186dcd2e..50ca1b3073 100644 --- a/common_video/h265/h265_common.h +++ b/common_video/h265/h265_common.h @@ -77,8 +77,14 @@ struct NaluIndex { }; // Returns a vector of the NALU indices in the given buffer. -RTC_EXPORT std::vector FindNaluIndices(const uint8_t* buffer, - size_t buffer_size); +RTC_EXPORT std::vector FindNaluIndices( + rtc::ArrayView buffer); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline std::vector FindNaluIndices(const uint8_t* buffer, + size_t buffer_size) { + return FindNaluIndices(rtc::MakeArrayView(buffer, buffer_size)); +} // Get the NAL type from the header byte immediately following start sequence. RTC_EXPORT NaluType ParseNaluType(uint8_t data); @@ -97,12 +103,24 @@ RTC_EXPORT NaluType ParseNaluType(uint8_t data); // the 03 emulation byte. // Parse the given data and remove any emulation byte escaping. -std::vector ParseRbsp(const uint8_t* data, size_t length); +std::vector ParseRbsp(rtc::ArrayView data); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline std::vector ParseRbsp(const uint8_t* data, size_t length) { + return ParseRbsp(rtc::MakeArrayView(data, length)); +} // Write the given data to the destination buffer, inserting and emulation // bytes in order to escape any data the could be interpreted as a start // sequence. -void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination); +void WriteRbsp(rtc::ArrayView bytes, rtc::Buffer* destination); + +// TODO: bugs.webrtc.org/42225170 - Deprecate. +inline void WriteRbsp(const uint8_t* bytes, + size_t length, + rtc::Buffer* destination) { + WriteRbsp(rtc::MakeArrayView(bytes, length), destination); +} uint32_t Log2Ceiling(uint32_t value); diff --git a/common_video/h265/h265_pps_parser.cc b/common_video/h265/h265_pps_parser.cc index 1cc9abd794..3339f652fd 100644 --- a/common_video/h265/h265_pps_parser.cc +++ b/common_video/h265/h265_pps_parser.cc @@ -63,17 +63,15 @@ namespace webrtc { // http://www.itu.int/rec/T-REC-H.265 absl::optional H265PpsParser::ParsePps( - const uint8_t* data, - size_t length, + rtc::ArrayView data, const H265SpsParser::SpsState* sps) { // 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.1 of the H.265 standard. - return ParseInternal(H265::ParseRbsp(data, length), sps); + return ParseInternal(H265::ParseRbsp(data), sps); } -bool H265PpsParser::ParsePpsIds(const uint8_t* data, - size_t length, +bool H265PpsParser::ParsePpsIds(rtc::ArrayView data, uint32_t* pps_id, uint32_t* sps_id) { RTC_DCHECK(pps_id); @@ -81,7 +79,7 @@ bool H265PpsParser::ParsePpsIds(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.1 of the H.265 standard. - std::vector unpacked_buffer = H265::ParseRbsp(data, length); + std::vector unpacked_buffer = H265::ParseRbsp(data); BitstreamReader reader(unpacked_buffer); *pps_id = reader.ReadExponentialGolomb(); IN_RANGE_OR_RETURN_FALSE(*pps_id, 0, 63); diff --git a/common_video/h265/h265_pps_parser.h b/common_video/h265/h265_pps_parser.h index 62bc18fe6b..1bd0eadb7e 100644 --- a/common_video/h265/h265_pps_parser.h +++ b/common_video/h265/h265_pps_parser.h @@ -43,14 +43,26 @@ class RTC_EXPORT H265PpsParser { }; // Unpack RBSP and parse PPS state from the supplied buffer. - static absl::optional ParsePps(const uint8_t* data, - size_t length, + static absl::optional ParsePps(rtc::ArrayView data, const H265SpsParser::SpsState* sps); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline absl::optional ParsePps( + const uint8_t* data, + size_t length, + const H265SpsParser::SpsState* sps) { + return ParsePps(rtc::MakeArrayView(data, length), sps); + } - static bool ParsePpsIds(const uint8_t* data, - size_t length, + static bool ParsePpsIds(rtc::ArrayView data, uint32_t* pps_id, uint32_t* sps_id); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline bool ParsePpsIds(const uint8_t* data, + size_t length, + uint32_t* pps_id, + uint32_t* sps_id) { + return ParsePpsIds(rtc::MakeArrayView(data, length), pps_id, sps_id); + } protected: // Parse the PPS state, for a bit buffer where RBSP decoding has already been diff --git a/common_video/h265/h265_pps_parser_unittest.cc b/common_video/h265/h265_pps_parser_unittest.cc index d91fc1a55c..c683a43008 100644 --- a/common_video/h265/h265_pps_parser_unittest.cc +++ b/common_video/h265/h265_pps_parser_unittest.cc @@ -161,7 +161,7 @@ void WritePps(const H265PpsParser::PpsState& pps, bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset); } - H265::WriteRbsp(data, byte_offset, out_buffer); + H265::WriteRbsp(rtc::MakeArrayView(data, byte_offset), out_buffer); } class H265PpsParserTest : public ::testing::Test { @@ -196,9 +196,8 @@ class H265PpsParserTest : public ::testing::Test { 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82}; H265SpsParser::SpsState parsed_sps = - H265SpsParser::ParseSps(sps_buffer, arraysize(sps_buffer)).value(); - parsed_pps_ = - H265PpsParser::ParsePps(buffer_.data(), buffer_.size(), &parsed_sps); + H265SpsParser::ParseSps(sps_buffer).value(); + parsed_pps_ = H265PpsParser::ParsePps(buffer_, &parsed_sps); ASSERT_TRUE(parsed_pps_); EXPECT_EQ(pps.dependent_slice_segments_enabled_flag, parsed_pps_->dependent_slice_segments_enabled_flag); diff --git a/common_video/h265/h265_sps_parser.cc b/common_video/h265/h265_sps_parser.cc index a2da4b9b7b..cb59d6094f 100644 --- a/common_video/h265/h265_sps_parser.cc +++ b/common_video/h265/h265_sps_parser.cc @@ -104,10 +104,8 @@ size_t H265SpsParser::GetDpbMaxPicBuf(int general_profile_idc) { // Unpack RBSP and parse SPS state from the supplied buffer. absl::optional H265SpsParser::ParseSps( - const uint8_t* data, - size_t length) { - RTC_DCHECK(data); - return ParseSpsInternal(H265::ParseRbsp(data, length)); + rtc::ArrayView data) { + return ParseSpsInternal(H265::ParseRbsp(data)); } bool H265SpsParser::ParseScalingListData(BitstreamReader& reader) { diff --git a/common_video/h265/h265_sps_parser.h b/common_video/h265/h265_sps_parser.h index 7ec170671d..072e2e9791 100644 --- a/common_video/h265/h265_sps_parser.h +++ b/common_video/h265/h265_sps_parser.h @@ -104,7 +104,12 @@ class RTC_EXPORT H265SpsParser { }; // Unpack RBSP and parse SPS state from the supplied buffer. - static absl::optional ParseSps(const uint8_t* data, size_t length); + static absl::optional ParseSps(rtc::ArrayView data); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline absl::optional ParseSps(const uint8_t* data, + size_t length) { + return ParseSps(rtc::MakeArrayView(data, length)); + } static bool ParseScalingListData(BitstreamReader& reader); diff --git a/common_video/h265/h265_sps_parser_unittest.cc b/common_video/h265/h265_sps_parser_unittest.cc index 26af4b1170..46d8d2d53a 100644 --- a/common_video/h265/h265_sps_parser_unittest.cc +++ b/common_video/h265/h265_sps_parser_unittest.cc @@ -365,7 +365,7 @@ void WriteSps(uint16_t width, } out_buffer->Clear(); - H265::WriteRbsp(rbsp, byte_count, out_buffer); + H265::WriteRbsp(rtc::MakeArrayView(rbsp, byte_count), out_buffer); } class H265SpsParserTest : public ::testing::Test { @@ -389,8 +389,7 @@ TEST_F(H265SpsParserTest, TestSampleSPSHdLandscape) { 0x02, 0x80, 0x80, 0x2d, 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82}; - absl::optional sps = - H265SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(1280u, sps->width); EXPECT_EQ(720u, sps->height); @@ -418,8 +417,7 @@ TEST_F(H265SpsParserTest, TestSampleSPSVerticalCropLandscape) { 0x05, 0x02, 0x01, 0x09, 0xf2, 0xe5, 0x95, 0x9a, 0x49, 0x32, 0xb8, 0x04, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x78, 0x20}; - absl::optional sps = - H265SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(640u, sps->width); EXPECT_EQ(260u, sps->height); @@ -446,8 +444,7 @@ TEST_F(H265SpsParserTest, TestSampleSPSHorizontalAndVerticalCrop) { 0x08, 0x48, 0x04, 0x27, 0x72, 0xe5, 0x95, 0x9a, 0x49, 0x32, 0xb8, 0x04, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x78, 0x20}; - absl::optional sps = - H265SpsParser::ParseSps(buffer, arraysize(buffer)); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(260u, sps->width); EXPECT_EQ(260u, sps->height); @@ -456,8 +453,7 @@ TEST_F(H265SpsParserTest, TestSampleSPSHorizontalAndVerticalCrop) { TEST_F(H265SpsParserTest, TestSyntheticSPSQvgaLandscape) { rtc::Buffer buffer; WriteSps(320u, 180u, 1, 0, 1, 0, &buffer); - absl::optional sps = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -467,8 +463,7 @@ TEST_F(H265SpsParserTest, TestSyntheticSPSQvgaLandscape) { TEST_F(H265SpsParserTest, TestSyntheticSPSWeirdResolution) { rtc::Buffer buffer; WriteSps(156u, 122u, 2, 0, 1, 0, &buffer); - absl::optional sps = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(156u, sps->width); EXPECT_EQ(122u, sps->height); @@ -478,8 +473,7 @@ TEST_F(H265SpsParserTest, TestSyntheticSPSWeirdResolution) { TEST_F(H265SpsParserTest, TestLog2MaxSubLayersMinus1) { rtc::Buffer buffer; WriteSps(320u, 180u, 1, 0, 1, 0, &buffer); - absl::optional sps = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -488,7 +482,7 @@ TEST_F(H265SpsParserTest, TestLog2MaxSubLayersMinus1) { WriteSps(320u, 180u, 1, 6, 1, 0, &buffer); absl::optional sps1 = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps1.has_value()); EXPECT_EQ(320u, sps1->width); EXPECT_EQ(180u, sps1->height); @@ -497,15 +491,14 @@ TEST_F(H265SpsParserTest, TestLog2MaxSubLayersMinus1) { WriteSps(320u, 180u, 1, 7, 1, 0, &buffer); absl::optional result = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + H265SpsParser::ParseSps(buffer); EXPECT_FALSE(result.has_value()); } TEST_F(H265SpsParserTest, TestSubLayerOrderingInfoPresentFlag) { rtc::Buffer buffer; WriteSps(320u, 180u, 1, 6, 1, 0, &buffer); - absl::optional sps = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -514,7 +507,7 @@ TEST_F(H265SpsParserTest, TestSubLayerOrderingInfoPresentFlag) { WriteSps(320u, 180u, 1, 6, 1, 0, &buffer); absl::optional sps1 = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps1.has_value()); EXPECT_EQ(320u, sps1->width); EXPECT_EQ(180u, sps1->height); @@ -525,8 +518,7 @@ TEST_F(H265SpsParserTest, TestSubLayerOrderingInfoPresentFlag) { TEST_F(H265SpsParserTest, TestLongTermRefPicsPresentFlag) { rtc::Buffer buffer; WriteSps(320u, 180u, 1, 0, 1, 0, &buffer); - absl::optional sps = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + absl::optional sps = H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps.has_value()); EXPECT_EQ(320u, sps->width); EXPECT_EQ(180u, sps->height); @@ -535,7 +527,7 @@ TEST_F(H265SpsParserTest, TestLongTermRefPicsPresentFlag) { WriteSps(320u, 180u, 1, 6, 1, 1, &buffer); absl::optional sps1 = - H265SpsParser::ParseSps(buffer.data(), buffer.size()); + H265SpsParser::ParseSps(buffer); ASSERT_TRUE(sps1.has_value()); EXPECT_EQ(320u, sps1->width); EXPECT_EQ(180u, sps1->height); diff --git a/common_video/h265/h265_vps_parser.cc b/common_video/h265/h265_vps_parser.cc index 16b967dad4..0a00370163 100644 --- a/common_video/h265/h265_vps_parser.cc +++ b/common_video/h265/h265_vps_parser.cc @@ -25,10 +25,8 @@ H265VpsParser::VpsState::VpsState() = default; // Unpack RBSP and parse VPS state from the supplied buffer. absl::optional H265VpsParser::ParseVps( - const uint8_t* data, - size_t length) { - RTC_DCHECK(data); - return ParseInternal(H265::ParseRbsp(data, length)); + rtc::ArrayView data) { + return ParseInternal(H265::ParseRbsp(data)); } absl::optional H265VpsParser::ParseInternal( diff --git a/common_video/h265/h265_vps_parser.h b/common_video/h265/h265_vps_parser.h index c793996bc1..e8ca1a07de 100644 --- a/common_video/h265/h265_vps_parser.h +++ b/common_video/h265/h265_vps_parser.h @@ -29,7 +29,12 @@ class RTC_EXPORT H265VpsParser { }; // Unpack RBSP and parse VPS state from the supplied buffer. - static absl::optional ParseVps(const uint8_t* data, size_t length); + static absl::optional ParseVps(rtc::ArrayView data); + // TODO: bugs.webrtc.org/42225170 - Deprecate. + static inline absl::optional ParseVps(const uint8_t* data, + size_t length) { + return ParseVps(rtc::MakeArrayView(data, length)); + } protected: // Parse the VPS state, for a bit buffer where RBSP decoding has already been diff --git a/common_video/h265/h265_vps_parser_unittest.cc b/common_video/h265/h265_vps_parser_unittest.cc index 24e8a77154..87e1f58634 100644 --- a/common_video/h265/h265_vps_parser_unittest.cc +++ b/common_video/h265/h265_vps_parser_unittest.cc @@ -41,8 +41,7 @@ TEST_F(H265VpsParserTest, TestSampleVPSId) { 0x1c, 0x01, 0xff, 0xff, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x78, 0x95, 0x98, 0x09, }; - EXPECT_TRUE(static_cast( - vps_ = H265VpsParser::ParseVps(buffer, arraysize(buffer)))); + EXPECT_TRUE(static_cast(vps_ = H265VpsParser::ParseVps(buffer))); EXPECT_EQ(1u, vps_->id); } diff --git a/modules/rtp_rtcp/source/rtp_format_h264.cc b/modules/rtp_rtcp/source/rtp_format_h264.cc index 9c1dc4edb8..7e11add85b 100644 --- a/modules/rtp_rtcp/source/rtp_format_h264.cc +++ b/modules/rtp_rtcp/source/rtp_format_h264.cc @@ -48,8 +48,7 @@ RtpPacketizerH264::RtpPacketizerH264(rtc::ArrayView payload, RTC_CHECK(packetization_mode == H264PacketizationMode::NonInterleaved || packetization_mode == H264PacketizationMode::SingleNalUnit); - for (const auto& nalu : - H264::FindNaluIndices(payload.data(), payload.size())) { + for (const auto& nalu : H264::FindNaluIndices(payload)) { input_fragments_.push_back( payload.subview(nalu.payload_start_offset, nalu.payload_size)); } diff --git a/modules/rtp_rtcp/source/rtp_packetizer_h265.cc b/modules/rtp_rtcp/source/rtp_packetizer_h265.cc index 775c50c38e..901b68bfa3 100644 --- a/modules/rtp_rtcp/source/rtp_packetizer_h265.cc +++ b/modules/rtp_rtcp/source/rtp_packetizer_h265.cc @@ -24,8 +24,7 @@ namespace webrtc { RtpPacketizerH265::RtpPacketizerH265(rtc::ArrayView payload, PayloadSizeLimits limits) : limits_(limits), num_packets_left_(0) { - for (const auto& nalu : - H264::FindNaluIndices(payload.data(), payload.size())) { + for (const auto& nalu : H264::FindNaluIndices(payload)) { if (!nalu.payload_size) { input_fragments_.clear(); return; diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc index 60fc545d53..fa48b7fcc0 100644 --- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc +++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc @@ -116,7 +116,8 @@ absl::optional ProcessStapAOrSingleNalu( nalu.sps_id = -1; nalu.pps_id = -1; start_offset += H264::kNaluTypeSize; - + rtc::ArrayView nalu_data(&payload_data[start_offset], + end_offset - start_offset); switch (nalu.type) { case H264::NaluType::kSps: { // Check if VUI is present in SPS and if it needs to be modified to @@ -131,8 +132,8 @@ absl::optional ProcessStapAOrSingleNalu( absl::optional sps; SpsVuiRewriter::ParseResult result = SpsVuiRewriter::ParseAndRewriteSps( - &payload_data[start_offset], end_offset - start_offset, &sps, - nullptr, &output_buffer, SpsVuiRewriter::Direction::kIncoming); + nalu_data, &sps, nullptr, &output_buffer, + SpsVuiRewriter::Direction::kIncoming); switch (result) { case SpsVuiRewriter::ParseResult::kFailure: RTC_LOG(LS_WARNING) << "Failed to parse SPS NAL unit."; @@ -179,9 +180,7 @@ absl::optional ProcessStapAOrSingleNalu( case H264::NaluType::kPps: { uint32_t pps_id; uint32_t sps_id; - if (PpsParser::ParsePpsIds(&payload_data[start_offset], - end_offset - start_offset, &pps_id, - &sps_id)) { + if (PpsParser::ParsePpsIds(nalu_data, &pps_id, &sps_id)) { nalu.pps_id = pps_id; nalu.sps_id = sps_id; } else { @@ -197,8 +196,7 @@ absl::optional ProcessStapAOrSingleNalu( [[fallthrough]]; case H264::NaluType::kSlice: { absl::optional slice_header = - PpsParser::ParseSliceHeader(&payload_data[start_offset], - end_offset - start_offset); + PpsParser::ParseSliceHeader(nalu_data); if (slice_header) { nalu.pps_id = slice_header->pic_parameter_set_id; parsed_payload->video_header.is_first_packet_in_frame &= @@ -249,8 +247,8 @@ absl::optional ParseFuaNalu( if (original_nal_type == H264::NaluType::kIdr || original_nal_type == H264::NaluType::kSlice) { absl::optional slice_header = - PpsParser::ParseSliceHeader(rtp_payload.cdata() + 2 * kNalHeaderSize, - rtp_payload.size() - 2 * kNalHeaderSize); + PpsParser::ParseSliceHeader(rtc::ArrayView(rtp_payload) + .subview(2 * kNalHeaderSize)); if (slice_header) { nalu.pps_id = slice_header->pic_parameter_set_id; is_first_packet_in_frame = slice_header->first_mb_in_slice == 0; diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc index fdb5680a96..b415ae7b7f 100644 --- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc +++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h265.cc @@ -120,6 +120,8 @@ absl::optional ProcessApOrSingleNalu( uint8_t nalu_type = (payload_data[start_offset] & kH265TypeMask) >> 1; start_offset += kH265NalHeaderSizeBytes; + rtc::ArrayView nalu_data(&payload_data[start_offset], + end_offset - start_offset); switch (nalu_type) { case H265::NaluType::kBlaWLp: case H265::NaluType::kBlaWRadl: @@ -141,8 +143,8 @@ absl::optional ProcessApOrSingleNalu( if (start_offset) output_buffer->AppendData(payload_data, start_offset); - absl::optional sps = H265SpsParser::ParseSps( - &payload_data[start_offset], end_offset - start_offset); + absl::optional sps = + H265SpsParser::ParseSps(nalu_data); if (sps) { // TODO(bugs.webrtc.org/13485): Implement the size calculation taking diff --git a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc index 535640e780..03a8beca23 100644 --- a/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc +++ b/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc @@ -381,7 +381,7 @@ void VideoCodecTestFixtureImpl::H264KeyframeChecker::CheckEncodedFrame( bool contains_pps = false; bool contains_idr = false; const std::vector nalu_indices = - webrtc::H264::FindNaluIndices(encoded_frame.data(), encoded_frame.size()); + webrtc::H264::FindNaluIndices(encoded_frame); for (const webrtc::H264::NaluIndex& index : nalu_indices) { webrtc::H264::NaluType nalu_type = webrtc::H264::ParseNaluType( encoded_frame.data()[index.payload_start_offset]); diff --git a/modules/video_coding/codecs/test/videoprocessor.cc b/modules/video_coding/codecs/test/videoprocessor.cc index c5e7ed0ebb..2133a94ab4 100644 --- a/modules/video_coding/codecs/test/videoprocessor.cc +++ b/modules/video_coding/codecs/test/videoprocessor.cc @@ -52,7 +52,7 @@ size_t GetMaxNaluSizeBytes(const EncodedImage& encoded_frame, return 0; std::vector nalu_indices = - webrtc::H264::FindNaluIndices(encoded_frame.data(), encoded_frame.size()); + webrtc::H264::FindNaluIndices(encoded_frame); RTC_CHECK(!nalu_indices.empty()); diff --git a/modules/video_coding/h264_sps_pps_tracker.cc b/modules/video_coding/h264_sps_pps_tracker.cc index 579279219f..834a36d53e 100644 --- a/modules/video_coding/h264_sps_pps_tracker.cc +++ b/modules/video_coding/h264_sps_pps_tracker.cc @@ -217,9 +217,9 @@ void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector& sps, return; } absl::optional parsed_sps = SpsParser::ParseSps( - sps.data() + kNaluHeaderOffset, sps.size() - kNaluHeaderOffset); + rtc::ArrayView(sps).subview(kNaluHeaderOffset)); absl::optional parsed_pps = PpsParser::ParsePps( - pps.data() + kNaluHeaderOffset, pps.size() - kNaluHeaderOffset); + rtc::ArrayView(pps).subview(kNaluHeaderOffset)); if (!parsed_sps) { RTC_LOG(LS_WARNING) << "Failed to parse SPS."; diff --git a/modules/video_coding/h26x_packet_buffer.cc b/modules/video_coding/h26x_packet_buffer.cc index e6e74413c0..c1f6426b4c 100644 --- a/modules/video_coding/h26x_packet_buffer.cc +++ b/modules/video_coding/h26x_packet_buffer.cc @@ -85,8 +85,8 @@ int64_t* GetContinuousSequence(rtc::ArrayView last_continuous, #ifdef RTC_ENABLE_H265 bool HasVps(const H26xPacketBuffer::Packet& packet) { - std::vector nalu_indices = H265::FindNaluIndices( - packet.video_payload.cdata(), packet.video_payload.size()); + std::vector nalu_indices = + H265::FindNaluIndices(packet.video_payload); return absl::c_any_of((nalu_indices), [&packet]( const H265::NaluIndex& nalu_index) { return H265::ParseNaluType( @@ -242,8 +242,8 @@ bool H26xPacketBuffer::MaybeAssembleFrame(int64_t start_seq_num_unwrapped, } #ifdef RTC_ENABLE_H265 } else if (packet->codec() == kVideoCodecH265) { - std::vector nalu_indices = H265::FindNaluIndices( - packet->video_payload.cdata(), packet->video_payload.size()); + std::vector nalu_indices = + H265::FindNaluIndices(packet->video_payload); for (const auto& nalu_index : nalu_indices) { uint8_t nalu_type = H265::ParseNaluType( packet->video_payload.cdata()[nalu_index.payload_start_offset]); @@ -339,9 +339,9 @@ void H26xPacketBuffer::InsertSpsPpsNalus(const std::vector& sps, return; } absl::optional parsed_sps = SpsParser::ParseSps( - sps.data() + kNaluHeaderOffset, sps.size() - kNaluHeaderOffset); + rtc::ArrayView(sps).subview(kNaluHeaderOffset)); absl::optional parsed_pps = PpsParser::ParsePps( - pps.data() + kNaluHeaderOffset, pps.size() - kNaluHeaderOffset); + rtc::ArrayView(pps).subview(kNaluHeaderOffset)); if (!parsed_sps) { RTC_LOG(LS_WARNING) << "Failed to parse SPS."; diff --git a/sdk/objc/components/video_codec/nalu_rewriter.cc b/sdk/objc/components/video_codec/nalu_rewriter.cc index 73c0ed0abd..054d6f9284 100644 --- a/sdk/objc/components/video_codec/nalu_rewriter.cc +++ b/sdk/objc/components/video_codec/nalu_rewriter.cc @@ -259,7 +259,7 @@ AnnexBBufferReader::AnnexBBufferReader(const uint8_t* annexb_buffer, size_t length) : start_(annexb_buffer), length_(length) { RTC_DCHECK(annexb_buffer); - offsets_ = H264::FindNaluIndices(annexb_buffer, length); + offsets_ = H264::FindNaluIndices(rtc::MakeArrayView(annexb_buffer, length)); offset_ = offsets_.begin(); }