diff --git a/api/video/video_frame_metadata_unittest.cc b/api/video/video_frame_metadata_unittest.cc index 0f730f7410..4ebf7435dd 100644 --- a/api/video/video_frame_metadata_unittest.cc +++ b/api/video/video_frame_metadata_unittest.cc @@ -28,8 +28,7 @@ RTPVideoHeaderH264 ExampleHeaderH264() { RTPVideoHeaderH264 header; header.nalu_type = 4; header.packetization_type = H264PacketizationTypes::kH264StapA; - header.nalus[0] = nalu_info; - header.nalus_length = 1; + header.nalus = {nalu_info}; header.packetization_mode = H264PacketizationMode::SingleNalUnit; return header; } diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc index 4198c80106..e6b206cdd7 100644 --- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc +++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc @@ -220,13 +220,7 @@ absl::optional ProcessStapAOrSingleNalu( return absl::nullopt; } - if (h264_header.nalus_length == kMaxNalusPerPacket) { - RTC_LOG(LS_WARNING) - << "Received packet containing more than " << kMaxNalusPerPacket - << " NAL units. Will not keep track sps and pps ids for all of them."; - } else { - h264_header.nalus[h264_header.nalus_length++] = nalu; - } + h264_header.nalus.push_back(nalu); } return parsed_payload; @@ -284,8 +278,7 @@ absl::optional ParseFuaNalu( h264_header.packetization_type = kH264FuA; h264_header.nalu_type = original_nal_type; if (first_fragment) { - h264_header.nalus[h264_header.nalus_length] = nalu; - h264_header.nalus_length = 1; + h264_header.nalus = {nalu}; } return parsed_payload; } diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc index 7cc4108632..c4d524cbb3 100644 --- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc +++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc @@ -125,15 +125,7 @@ TEST(VideoRtpDepacketizerH264Test, StapAKey) { EXPECT_EQ(h264.packetization_type, kH264StapA); // NALU type for aggregated packets is the type of the first packet only. EXPECT_EQ(h264.nalu_type, kSps); - ASSERT_EQ(h264.nalus_length, 3u); - for (size_t i = 0; i < h264.nalus_length; ++i) { - EXPECT_EQ(h264.nalus[i].type, kExpectedNalus[i].type) - << "Failed parsing nalu " << i; - EXPECT_EQ(h264.nalus[i].sps_id, kExpectedNalus[i].sps_id) - << "Failed parsing nalu " << i; - EXPECT_EQ(h264.nalus[i].pps_id, kExpectedNalus[i].pps_id) - << "Failed parsing nalu " << i; - } + EXPECT_THAT(h264.nalus, ElementsAreArray(kExpectedNalus)); } TEST(VideoRtpDepacketizerH264Test, StapANaluSpsWithResolution) { @@ -327,7 +319,7 @@ TEST(VideoRtpDepacketizerH264Test, FuA) { absl::get(parsed1->video_header.video_type_header); EXPECT_EQ(h264.packetization_type, kH264FuA); EXPECT_EQ(h264.nalu_type, kIdr); - ASSERT_EQ(h264.nalus_length, 1u); + ASSERT_THAT(h264.nalus, SizeIs(1)); EXPECT_EQ(h264.nalus[0].type, static_cast(kIdr)); EXPECT_EQ(h264.nalus[0].sps_id, -1); EXPECT_EQ(h264.nalus[0].pps_id, 0); @@ -347,7 +339,7 @@ TEST(VideoRtpDepacketizerH264Test, FuA) { EXPECT_EQ(h264.packetization_type, kH264FuA); EXPECT_EQ(h264.nalu_type, kIdr); // NALU info is only expected for the first FU-A packet. - EXPECT_EQ(h264.nalus_length, 0u); + EXPECT_THAT(h264.nalus, IsEmpty()); } auto parsed3 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet3)); @@ -362,7 +354,7 @@ TEST(VideoRtpDepacketizerH264Test, FuA) { EXPECT_EQ(h264.packetization_type, kH264FuA); EXPECT_EQ(h264.nalu_type, kIdr); // NALU info is only expected for the first FU-A packet. - ASSERT_EQ(h264.nalus_length, 0u); + EXPECT_THAT(h264.nalus, IsEmpty()); } } @@ -409,7 +401,7 @@ TEST(VideoRtpDepacketizerH264Test, SeiPacket) { EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta); EXPECT_EQ(h264.packetization_type, kH264SingleNalu); EXPECT_EQ(h264.nalu_type, kSei); - ASSERT_EQ(h264.nalus_length, 1u); + ASSERT_THAT(h264.nalus, SizeIs(1)); EXPECT_EQ(h264.nalus[0].type, static_cast(kSei)); EXPECT_EQ(h264.nalus[0].sps_id, -1); EXPECT_EQ(h264.nalus[0].pps_id, -1); diff --git a/modules/video_coding/codecs/h264/include/h264_globals.h b/modules/video_coding/codecs/h264/include/h264_globals.h index 6a1de382dc..dac36dd734 100644 --- a/modules/video_coding/codecs/h264/include/h264_globals.h +++ b/modules/video_coding/codecs/h264/include/h264_globals.h @@ -16,6 +16,7 @@ #include #include +#include #include "modules/video_coding/codecs/interface/common_constants.h" #include "rtc_base/checks.h" @@ -72,8 +73,6 @@ struct NaluInfo { } }; -const size_t kMaxNalusPerPacket = 10; - struct RTPVideoHeaderH264 { // The NAL unit type. If this is a header for a // fragmented packet, it's the NAL unit type of @@ -83,8 +82,7 @@ struct RTPVideoHeaderH264 { uint8_t nalu_type; // The packetization type of this buffer - single, aggregated or fragmented. H264PacketizationTypes packetization_type; - NaluInfo nalus[kMaxNalusPerPacket]; - size_t nalus_length; + std::vector nalus; // The packetization mode of this transport. Packetization mode // determines which packetization types are allowed when packetizing. H264PacketizationMode packetization_mode; @@ -93,8 +91,7 @@ struct RTPVideoHeaderH264 { const RTPVideoHeaderH264& rhs) { return lhs.nalu_type == rhs.nalu_type && lhs.packetization_type == rhs.packetization_type && - std::equal(lhs.nalus, lhs.nalus + lhs.nalus_length, rhs.nalus, - rhs.nalus + rhs.nalus_length) && + lhs.nalus == rhs.nalus && lhs.packetization_mode == rhs.packetization_mode; } diff --git a/modules/video_coding/deprecated/BUILD.gn b/modules/video_coding/deprecated/BUILD.gn index 047541be4c..dacde525e5 100644 --- a/modules/video_coding/deprecated/BUILD.gn +++ b/modules/video_coding/deprecated/BUILD.gn @@ -134,6 +134,7 @@ rtc_library("deprecated_session_info") { "../../../modules:module_api_public", "../../../modules/video_coding:codec_globals_headers", "../../../rtc_base:logging", + "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/types:variant", ] sources = [ diff --git a/modules/video_coding/deprecated/jitter_buffer_unittest.cc b/modules/video_coding/deprecated/jitter_buffer_unittest.cc index ee88f9c9cb..cc504454c6 100644 --- a/modules/video_coding/deprecated/jitter_buffer_unittest.cc +++ b/modules/video_coding/deprecated/jitter_buffer_unittest.cc @@ -903,10 +903,8 @@ TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) { packet_->markerBit = true; packet_->video_header.codec = kVideoCodecH264; h264_header.nalu_type = H264::NaluType::kIdr; - h264_header.nalus[0].type = H264::NaluType::kIdr; - h264_header.nalus[0].sps_id = -1; - h264_header.nalus[0].pps_id = 0; - h264_header.nalus_length = 1; + h264_header.nalus = { + {.type = H264::NaluType::kIdr, .sps_id = -1, .pps_id = 0}}; bool retransmitted = false; EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); @@ -922,13 +920,9 @@ TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) { packet_->markerBit = false; packet_->video_header.codec = kVideoCodecH264; h264_header.nalu_type = H264::NaluType::kStapA; - h264_header.nalus[0].type = H264::NaluType::kSps; - h264_header.nalus[0].sps_id = 0; - h264_header.nalus[0].pps_id = -1; - h264_header.nalus[1].type = H264::NaluType::kPps; - h264_header.nalus[1].sps_id = 0; - h264_header.nalus[1].pps_id = 0; - h264_header.nalus_length = 2; + h264_header.nalus = { + {.type = H264::NaluType::kSps, .sps_id = 0, .pps_id = -1}, + {.type = H264::NaluType::kPps, .sps_id = 0, .pps_id = 0}}; // Not complete since the marker bit hasn't been received. EXPECT_EQ(kIncomplete, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); @@ -940,10 +934,8 @@ TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) { packet_->markerBit = true; packet_->video_header.codec = kVideoCodecH264; h264_header.nalu_type = H264::NaluType::kIdr; - h264_header.nalus[0].type = H264::NaluType::kIdr; - h264_header.nalus[0].sps_id = -1; - h264_header.nalus[0].pps_id = 0; - h264_header.nalus_length = 1; + h264_header.nalus = { + {.type = H264::NaluType::kIdr, .sps_id = -1, .pps_id = 0}}; // Complete and decodable since the pps and sps are received in the first // packet of this frame. EXPECT_EQ(kCompleteSession, @@ -961,10 +953,9 @@ TEST_F(TestBasicJitterBuffer, SpsAndPpsHandling) { packet_->markerBit = true; packet_->video_header.codec = kVideoCodecH264; h264_header.nalu_type = H264::NaluType::kSlice; - h264_header.nalus[0].type = H264::NaluType::kSlice; - h264_header.nalus[0].sps_id = -1; - h264_header.nalus[0].pps_id = 0; - h264_header.nalus_length = 1; + h264_header.nalus = { + {.type = H264::NaluType::kIdr, .sps_id = -1, .pps_id = 0}}; + // Complete and decodable since sps, pps and key frame has been received. EXPECT_EQ(kCompleteSession, jitter_buffer_->InsertPacket(*packet_, &retransmitted)); diff --git a/modules/video_coding/deprecated/session_info.cc b/modules/video_coding/deprecated/session_info.cc index b15dc0a9ff..ed0fc6496d 100644 --- a/modules/video_coding/deprecated/session_info.cc +++ b/modules/video_coding/deprecated/session_info.cc @@ -14,6 +14,7 @@ #include +#include "absl/algorithm/container.h" #include "absl/types/variant.h" #include "modules/include/module_common_types.h" #include "modules/include/module_common_types_public.h" @@ -139,9 +140,7 @@ std::vector VCMSessionInfo::GetNaluInfos() const { for (const VCMPacket& packet : packets_) { const auto& h264 = absl::get(packet.video_header.video_type_header); - for (size_t i = 0; i < h264.nalus_length; ++i) { - nalu_infos.push_back(h264.nalus[i]); - } + absl::c_copy(h264.nalus, std::back_inserter(nalu_infos)); } return nalu_infos; } diff --git a/modules/video_coding/h264_sps_pps_tracker.cc b/modules/video_coding/h264_sps_pps_tracker.cc index 5a7eae7b42..579279219f 100644 --- a/modules/video_coding/h264_sps_pps_tracker.cc +++ b/modules/video_coding/h264_sps_pps_tracker.cc @@ -58,8 +58,7 @@ H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( auto sps = sps_data_.end(); auto pps = pps_data_.end(); - for (size_t i = 0; i < h264_header.nalus_length; ++i) { - const NaluInfo& nalu = h264_header.nalus[i]; + for (const NaluInfo& nalu : h264_header.nalus) { switch (nalu.type) { case H264::NaluType::kSps: { SpsInfo& sps_info = sps_data_[nalu.sps_id]; @@ -140,7 +139,7 @@ H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( nalu_ptr += segment_length; } } else { - if (h264_header.nalus_length > 0) { + if (!h264_header.nalus.empty()) { required_size += sizeof(start_code_h264); } required_size += bitstream.size(); @@ -160,21 +159,11 @@ H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( fixed.bitstream.AppendData(pps->second.data.get(), pps->second.size); // Update codec header to reflect the newly added SPS and PPS. - NaluInfo sps_info; - sps_info.type = H264::NaluType::kSps; - sps_info.sps_id = sps->first; - sps_info.pps_id = -1; - NaluInfo pps_info; - pps_info.type = H264::NaluType::kPps; - pps_info.sps_id = sps->first; - pps_info.pps_id = pps->first; - if (h264_header.nalus_length + 2 <= kMaxNalusPerPacket) { - h264_header.nalus[h264_header.nalus_length++] = sps_info; - h264_header.nalus[h264_header.nalus_length++] = pps_info; - } else { - RTC_LOG(LS_WARNING) << "Not enough space in H.264 codec header to insert " - "SPS/PPS provided out-of-band."; - } + h264_header.nalus.push_back( + {.type = H264::NaluType::kSps, .sps_id = sps->first, .pps_id = -1}); + h264_header.nalus.push_back({.type = H264::NaluType::kPps, + .sps_id = sps->first, + .pps_id = pps->first}); } // Copy the rest of the bitstream and insert start codes. @@ -196,7 +185,7 @@ H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( nalu_ptr += segment_length; } } else { - if (h264_header.nalus_length > 0) { + if (!h264_header.nalus.empty()) { fixed.bitstream.AppendData(start_code_h264); } fixed.bitstream.AppendData(bitstream.data(), bitstream.size()); diff --git a/modules/video_coding/h264_sps_pps_tracker.h b/modules/video_coding/h264_sps_pps_tracker.h index 600e2ee397..3c0928d324 100644 --- a/modules/video_coding/h264_sps_pps_tracker.h +++ b/modules/video_coding/h264_sps_pps_tracker.h @@ -66,8 +66,8 @@ class H264SpsPpsTracker { std::unique_ptr data; }; - std::map pps_data_; - std::map sps_data_; + std::map pps_data_; + std::map sps_data_; }; } // namespace video_coding diff --git a/modules/video_coding/h264_sps_pps_tracker_unittest.cc b/modules/video_coding/h264_sps_pps_tracker_unittest.cc index 76591e9f5c..86c63a38a2 100644 --- a/modules/video_coding/h264_sps_pps_tracker_unittest.cc +++ b/modules/video_coding/h264_sps_pps_tracker_unittest.cc @@ -26,6 +26,7 @@ namespace video_coding { namespace { using ::testing::ElementsAreArray; +using ::testing::SizeIs; const uint8_t start_code[] = {0, 0, 0, 1}; @@ -64,7 +65,6 @@ class H264VideoHeader : public RTPVideoHeader { codec = kVideoCodecH264; is_first_packet_in_frame = false; auto& h264_header = video_type_header.emplace(); - h264_header.nalus_length = 0; h264_header.packetization_type = kH264SingleNalu; } @@ -87,7 +87,7 @@ class TestH264SpsPpsTracker : public ::testing::Test { data->push_back(H264::NaluType::kSps); data->push_back(sps_id); // The sps data, just a single byte. - header->h264().nalus[header->h264().nalus_length++] = info; + header->h264().nalus.push_back(info); } void AddPps(H264VideoHeader* header, @@ -101,7 +101,7 @@ class TestH264SpsPpsTracker : public ::testing::Test { data->push_back(H264::NaluType::kPps); data->push_back(pps_id); // The pps data, just a single byte. - header->h264().nalus[header->h264().nalus_length++] = info; + header->h264().nalus.push_back(info); } void AddIdr(H264VideoHeader* header, int pps_id) { @@ -110,7 +110,7 @@ class TestH264SpsPpsTracker : public ::testing::Test { info.sps_id = -1; info.pps_id = pps_id; - header->h264().nalus[header->h264().nalus_length++] = info; + header->h264().nalus.push_back(info); } protected: @@ -133,7 +133,7 @@ TEST_F(TestH264SpsPpsTracker, FuAFirstPacket) { uint8_t data[] = {1, 2, 3}; H264VideoHeader header; header.h264().packetization_type = kH264FuA; - header.h264().nalus_length = 1; + header.h264().nalus.resize(1); header.is_first_packet_in_frame = true; H264SpsPpsTracker::FixedBitstream fixed = @@ -201,7 +201,7 @@ TEST_F(TestH264SpsPpsTracker, ConsecutiveStapA) { TEST_F(TestH264SpsPpsTracker, SingleNaluInsertStartCode) { uint8_t data[] = {1, 2, 3}; H264VideoHeader header; - header.h264().nalus_length = 1; + header.h264().nalus.resize(1); H264SpsPpsTracker::FixedBitstream fixed = tracker_.CopyAndFixBitstream(data, &header); @@ -217,8 +217,8 @@ TEST_F(TestH264SpsPpsTracker, NoStartCodeInsertedForSubsequentFuAPacket) { std::vector data = {1, 2, 3}; H264VideoHeader header; header.h264().packetization_type = kH264FuA; - // Since no NALU begin in this packet the nalus_length is zero. - header.h264().nalus_length = 0; + // Since no NALU begin in this packet the nalus are empty. + header.h264().nalus.clear(); H264SpsPpsTracker::FixedBitstream fixed = tracker_.CopyAndFixBitstream(data, &header); @@ -330,12 +330,12 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBand) { H264VideoHeader idr_header; idr_header.is_first_packet_in_frame = true; AddIdr(&idr_header, 0); - EXPECT_EQ(idr_header.h264().nalus_length, 1u); + EXPECT_THAT(idr_header.h264().nalus, SizeIs(1)); H264SpsPpsTracker::FixedBitstream fixed = tracker_.CopyAndFixBitstream(kData, &idr_header); - EXPECT_EQ(idr_header.h264().nalus_length, 3u); + EXPECT_THAT(idr_header.h264().nalus, SizeIs(3)); EXPECT_EQ(idr_header.width, 320u); EXPECT_EQ(idr_header.height, 240u); ExpectSpsPpsIdr(idr_header.h264(), 0, 0); diff --git a/modules/video_coding/h26x_packet_buffer.cc b/modules/video_coding/h26x_packet_buffer.cc index 133ab4708a..3770edbf67 100644 --- a/modules/video_coding/h26x_packet_buffer.cc +++ b/modules/video_coding/h26x_packet_buffer.cc @@ -42,24 +42,15 @@ int64_t EuclideanMod(int64_t n, int64_t div) { return (n %= div) < 0 ? n + div : n; } -rtc::ArrayView GetNaluInfos( - const RTPVideoHeaderH264& h264_header) { - if (h264_header.nalus_length > kMaxNalusPerPacket) { - return {}; - } - - return rtc::MakeArrayView(h264_header.nalus, h264_header.nalus_length); -} - bool IsFirstPacketOfFragment(const RTPVideoHeaderH264& h264_header) { - return h264_header.nalus_length > 0; + return !h264_header.nalus.empty(); } bool BeginningOfIdr(const H26xPacketBuffer::Packet& packet) { const auto& h264_header = absl::get(packet.video_header.video_type_header); const bool contains_idr_nalu = - absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) { + absl::c_any_of(h264_header.nalus, [](const auto& nalu_info) { return nalu_info.type == H264::NaluType::kIdr; }); switch (h264_header.packetization_type) { @@ -76,7 +67,7 @@ bool BeginningOfIdr(const H26xPacketBuffer::Packet& packet) { bool HasSps(const H26xPacketBuffer::Packet& packet) { auto& h264_header = absl::get(packet.video_header.video_type_header); - return absl::c_any_of(GetNaluInfos(h264_header), [](const auto& nalu_info) { + return absl::c_any_of(h264_header.nalus, [](const auto& nalu_info) { return nalu_info.type == H264::NaluType::kSps; }); } @@ -219,7 +210,7 @@ bool H26xPacketBuffer::MaybeAssembleFrame(int64_t start_seq_num_unwrapped, if (packet->codec() == kVideoCodecH264) { const auto& h264_header = absl::get(packet->video_header.video_type_header); - for (const auto& nalu : GetNaluInfos(h264_header)) { + for (const auto& nalu : h264_header.nalus) { has_idr |= nalu.type == H264::NaluType::kIdr; has_sps |= nalu.type == H264::NaluType::kSps; has_pps |= nalu.type == H264::NaluType::kPps; @@ -383,8 +374,7 @@ bool H26xPacketBuffer::FixH264Packet(Packet& packet) { auto sps = sps_data_.end(); auto pps = pps_data_.end(); - for (size_t i = 0; i < h264_header.nalus_length; ++i) { - const NaluInfo& nalu = h264_header.nalus[i]; + for (const NaluInfo& nalu : h264_header.nalus) { switch (nalu.type) { case H264::NaluType::kSps: { SpsInfo& sps_info = sps_data_[nalu.sps_id]; @@ -456,22 +446,11 @@ bool H26xPacketBuffer::FixH264Packet(Packet& packet) { result.AppendData(pps->second.payload.get(), pps->second.size); // Update codec header to reflect the newly added SPS and PPS. - NaluInfo sps_info; - sps_info.type = H264::NaluType::kSps; - sps_info.sps_id = sps->first; - sps_info.pps_id = -1; - NaluInfo pps_info; - pps_info.type = H264::NaluType::kPps; - pps_info.sps_id = sps->first; - pps_info.pps_id = pps->first; - if (h264_header.nalus_length + 2 <= kMaxNalusPerPacket) { - h264_header.nalus[h264_header.nalus_length++] = sps_info; - h264_header.nalus[h264_header.nalus_length++] = pps_info; - } else { - RTC_LOG(LS_WARNING) - << "Not enough space in H.264 codec header to insert " - "SPS/PPS provided out-of-band."; - } + h264_header.nalus.push_back( + {.type = H264::NaluType::kSps, .sps_id = sps->first, .pps_id = -1}); + h264_header.nalus.push_back({.type = H264::NaluType::kPps, + .sps_id = sps->first, + .pps_id = pps->first}); } } diff --git a/modules/video_coding/h26x_packet_buffer.h b/modules/video_coding/h26x_packet_buffer.h index 8bfae71f7b..ef6d0db373 100644 --- a/modules/video_coding/h26x_packet_buffer.h +++ b/modules/video_coding/h26x_packet_buffer.h @@ -96,10 +96,10 @@ class H26xPacketBuffer { // Map from pps_pic_parameter_set_id to the PPS payload associated with this // ID. - std::map pps_data_; + std::map pps_data_; // Map from sps_video_parameter_set_id to the SPS payload associated with this // ID. - std::map sps_data_; + std::map sps_data_; }; } // namespace webrtc diff --git a/modules/video_coding/h26x_packet_buffer_unittest.cc b/modules/video_coding/h26x_packet_buffer_unittest.cc index 8d6d69136d..50f35f3643 100644 --- a/modules/video_coding/h26x_packet_buffer_unittest.cc +++ b/modules/video_coding/h26x_packet_buffer_unittest.cc @@ -109,14 +109,14 @@ H264Packet& H264Packet::Idr(std::vector payload, int pps_id) { auto& h264_header = H264Header(); auto nalu_info = MakeNaluInfo(kIdr); nalu_info.pps_id = pps_id; - h264_header.nalus[h264_header.nalus_length++] = nalu_info; + h264_header.nalus.push_back(nalu_info); nalu_payloads_.push_back(std::move(payload)); return *this; } H264Packet& H264Packet::Slice(std::vector payload) { auto& h264_header = H264Header(); - h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSlice); + h264_header.nalus.push_back(MakeNaluInfo(kSlice)); nalu_payloads_.push_back(std::move(payload)); return *this; } @@ -125,7 +125,7 @@ H264Packet& H264Packet::Sps(std::vector payload, int sps_id) { auto& h264_header = H264Header(); auto nalu_info = MakeNaluInfo(kSps); nalu_info.pps_id = sps_id; - h264_header.nalus[h264_header.nalus_length++] = nalu_info; + h264_header.nalus.push_back(nalu_info); nalu_payloads_.push_back(std::move(payload)); return *this; } @@ -133,7 +133,7 @@ H264Packet& H264Packet::Sps(std::vector payload, int sps_id) { H264Packet& H264Packet::SpsWithResolution(RenderResolution resolution, std::vector payload) { auto& h264_header = H264Header(); - h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kSps); + h264_header.nalus.push_back(MakeNaluInfo(kSps)); video_header_.width = resolution.Width(); video_header_.height = resolution.Height(); nalu_payloads_.push_back(std::move(payload)); @@ -147,14 +147,14 @@ H264Packet& H264Packet::Pps(std::vector payload, auto nalu_info = MakeNaluInfo(kPps); nalu_info.pps_id = pps_id; nalu_info.sps_id = sps_id; - h264_header.nalus[h264_header.nalus_length++] = nalu_info; + h264_header.nalus.push_back(nalu_info); nalu_payloads_.push_back(std::move(payload)); return *this; } H264Packet& H264Packet::Aud() { auto& h264_header = H264Header(); - h264_header.nalus[h264_header.nalus_length++] = MakeNaluInfo(kAud); + h264_header.nalus.push_back(MakeNaluInfo(kAud)); nalu_payloads_.push_back({}); return *this; } @@ -185,25 +185,24 @@ std::unique_ptr H264Packet::Build() { auto& h264_header = H264Header(); switch (type_) { case kH264FuA: { - RTC_CHECK_EQ(h264_header.nalus_length, 1); + RTC_CHECK_EQ(h264_header.nalus.size(), 1); res->video_payload = BuildFuaPayload(); break; } case kH264SingleNalu: { - RTC_CHECK_EQ(h264_header.nalus_length, 1); + RTC_CHECK_EQ(h264_header.nalus.size(), 1); res->video_payload = BuildSingleNaluPayload(); break; } case kH264StapA: { - RTC_CHECK_GT(h264_header.nalus_length, 1); - RTC_CHECK_LE(h264_header.nalus_length, kMaxNalusPerPacket); + RTC_CHECK_GT(h264_header.nalus.size(), 1); res->video_payload = BuildStapAPayload(); break; } } if (type_ == kH264FuA && !first_fragment_) { - h264_header.nalus_length = 0; + h264_header.nalus.clear(); } h264_header.packetization_type = type_; @@ -235,7 +234,7 @@ rtc::CopyOnWriteBuffer H264Packet::BuildStapAPayload() const { res.AppendData(&indicator, 1); auto& h264_header = H264Header(); - for (size_t i = 0; i < h264_header.nalus_length; ++i) { + for (size_t i = 0; i < h264_header.nalus.size(); ++i) { // The two first bytes indicates the nalu segment size. uint8_t length_as_array[2] = { 0, static_cast(nalu_payloads_[i].size() + 1)}; @@ -1044,24 +1043,6 @@ TEST(H26xPacketBufferTest, FullPacketBufferDoesNotBlockKeyframe) { SizeIs(1)); } -TEST(H26xPacketBufferTest, TooManyNalusInPacket) { - H26xPacketBuffer packet_buffer(/*h264_allow_idr_only_keyframes=*/false); - - std::unique_ptr packet(H264Packet(kH264StapA) - .Sps() - .Pps() - .Idr() - .SeqNum(1) - .Time(1) - .Marker() - .Build()); - auto& h264_header = - absl::get(packet->video_header.video_type_header); - h264_header.nalus_length = kMaxNalusPerPacket + 1; - - EXPECT_THAT(packet_buffer.InsertPacket(std::move(packet)).packets, IsEmpty()); -} - #ifdef RTC_ENABLE_H265 TEST(H26xPacketBufferTest, H265VpsSpsPpsIdrIsKeyframe) { H26xPacketBuffer packet_buffer(/*allow_idr_only_keyframes=*/false); diff --git a/modules/video_coding/packet_buffer.cc b/modules/video_coding/packet_buffer.cc index 420a200ba9..e1e572ea2f 100644 --- a/modules/video_coding/packet_buffer.cc +++ b/modules/video_coding/packet_buffer.cc @@ -287,15 +287,15 @@ std::vector> PacketBuffer::FindFrames( if (is_h264_descriptor) { const auto* h264_header = absl::get_if( &buffer_[start_index]->video_header.video_type_header); - if (!h264_header || h264_header->nalus_length >= kMaxNalusPerPacket) + if (!h264_header) return found_frames; - for (size_t j = 0; j < h264_header->nalus_length; ++j) { - if (h264_header->nalus[j].type == H264::NaluType::kSps) { + for (const NaluInfo& nalu : h264_header->nalus) { + if (nalu.type == H264::NaluType::kSps) { has_h264_sps = true; - } else if (h264_header->nalus[j].type == H264::NaluType::kPps) { + } else if (nalu.type == H264::NaluType::kPps) { has_h264_pps = true; - } else if (h264_header->nalus[j].type == H264::NaluType::kIdr) { + } else if (nalu.type == H264::NaluType::kIdr) { has_h264_idr = true; } } diff --git a/modules/video_coding/packet_buffer_unittest.cc b/modules/video_coding/packet_buffer_unittest.cc index 607ec47dc4..093ef0d935 100644 --- a/modules/video_coding/packet_buffer_unittest.cc +++ b/modules/video_coding/packet_buffer_unittest.cc @@ -416,13 +416,11 @@ class PacketBufferH264Test : public PacketBufferTest { packet->timestamp = timestamp; if (keyframe == kKeyFrame) { if (sps_pps_idr_is_keyframe_) { - h264_header.nalus[0].type = H264::NaluType::kSps; - h264_header.nalus[1].type = H264::NaluType::kPps; - h264_header.nalus[2].type = H264::NaluType::kIdr; - h264_header.nalus_length = 3; + h264_header.nalus = {{H264::NaluType::kSps}, + {H264::NaluType::kPps}, + {H264::NaluType::kIdr}}; } else { - h264_header.nalus[0].type = H264::NaluType::kIdr; - h264_header.nalus_length = 1; + h264_header.nalus = {{H264::NaluType::kIdr}}; } } packet->video_header.width = width; @@ -458,8 +456,7 @@ class PacketBufferH264Test : public PacketBufferTest { RTC_CHECK(first == kFirst); // Insert a AUD NALU / packet without width/height. - h264_header.nalus[0].type = H264::NaluType::kAud; - h264_header.nalus_length = 1; + h264_header.nalus = {{H264::NaluType::kAud}}; packet->video_header.is_first_packet_in_frame = true; packet->video_header.is_last_packet_in_frame = false; IgnoreResult(packet_buffer_.InsertPacket(std::move(packet))); @@ -524,8 +521,7 @@ TEST_P(PacketBufferH264ParameterizedTest, GetBitstreamBufferPadding) { auto packet = std::make_unique(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus_length = 1; - h264_header.nalus[0].type = H264::NaluType::kIdr; + h264_header.nalus = {{H264::NaluType::kIdr}}; h264_header.packetization_type = kH264SingleNalu; packet->seq_num = seq_num; packet->video_header.codec = kVideoCodecH264; @@ -641,7 +637,7 @@ TEST_F(PacketBufferTest, IncomingCodecChange) { packet->video_header.codec = kVideoCodecH264; auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus_length = 1; + h264_header.nalus.resize(1); packet->timestamp = 3; packet->seq_num = 3; packet->video_header.frame_type = VideoFrameType::kVideoFrameKey; @@ -660,21 +656,6 @@ TEST_F(PacketBufferTest, IncomingCodecChange) { SizeIs(2)); } -TEST_F(PacketBufferTest, TooManyNalusInPacket) { - auto packet = std::make_unique(); - packet->video_header.codec = kVideoCodecH264; - packet->timestamp = 1; - packet->seq_num = 1; - packet->video_header.frame_type = VideoFrameType::kVideoFrameKey; - packet->video_header.is_first_packet_in_frame = true; - packet->video_header.is_last_packet_in_frame = true; - auto& h264_header = - packet->video_header.video_type_header.emplace(); - h264_header.nalus_length = kMaxNalusPerPacket; - EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, - IsEmpty()); -} - TEST_P(PacketBufferH264ParameterizedTest, OneFrameFillBuffer) { InsertH264(0, kKeyFrame, kFirst, kNotLast, 1000); for (int i = 1; i < kStartSize - 1; ++i) @@ -771,8 +752,7 @@ TEST_F(PacketBufferH264IdrIsKeyframeTest, IdrIsKeyframe) { auto packet = CreatePacket(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus[0].type = H264::NaluType::kIdr; - h264_header.nalus_length = 1; + h264_header.nalus = {{H264::NaluType::kIdr}}; EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, ElementsAre(KeyFrame())); } @@ -781,10 +761,8 @@ TEST_F(PacketBufferH264IdrIsKeyframeTest, SpsPpsIdrIsKeyframe) { auto packet = CreatePacket(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus[0].type = H264::NaluType::kSps; - h264_header.nalus[1].type = H264::NaluType::kPps; - h264_header.nalus[2].type = H264::NaluType::kIdr; - h264_header.nalus_length = 3; + h264_header.nalus = { + {H264::NaluType::kSps}, {H264::NaluType::kPps}, {H264::NaluType::kIdr}}; EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, ElementsAre(KeyFrame())); @@ -801,8 +779,7 @@ TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, IdrIsNotKeyframe) { auto packet = CreatePacket(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus[0].type = H264::NaluType::kIdr; - h264_header.nalus_length = 1; + h264_header.nalus = {{H264::NaluType::kIdr}}; EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, ElementsAre(DeltaFrame())); @@ -812,9 +789,7 @@ TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIsNotKeyframe) { auto packet = CreatePacket(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus[0].type = H264::NaluType::kSps; - h264_header.nalus[1].type = H264::NaluType::kPps; - h264_header.nalus_length = 2; + h264_header.nalus = {{H264::NaluType::kSps}, {H264::NaluType::kPps}}; EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, ElementsAre(DeltaFrame())); @@ -824,10 +799,8 @@ TEST_F(PacketBufferH264SpsPpsIdrIsKeyframeTest, SpsPpsIdrIsKeyframe) { auto packet = CreatePacket(); auto& h264_header = packet->video_header.video_type_header.emplace(); - h264_header.nalus[0].type = H264::NaluType::kSps; - h264_header.nalus[1].type = H264::NaluType::kPps; - h264_header.nalus[2].type = H264::NaluType::kIdr; - h264_header.nalus_length = 3; + h264_header.nalus = { + {H264::NaluType::kSps}, {H264::NaluType::kPps}, {H264::NaluType::kIdr}}; EXPECT_THAT(packet_buffer_.InsertPacket(std::move(packet)).packets, ElementsAre(KeyFrame())); diff --git a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc index 93673f0b8e..f1c49046e6 100644 --- a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc +++ b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc @@ -56,6 +56,18 @@ class DataReader { size_t offset_ = 0; }; +RTPVideoHeaderH264 GenerateRTPVideoHeaderH264(DataReader* reader) { + RTPVideoHeaderH264 result; + result.nalu_type = reader->GetNum(); + result.packetization_type = reader->GetNum(); + int nalus_length = reader->GetNum(); + for (int i = 0; i < nalus_length; ++i) { + reader->CopyTo(&result.nalus.emplace_back()); + } + result.packetization_mode = reader->GetNum(); + return result; +} + absl::optional GenerateGenericFrameDependencies(DataReader* reader) { absl::optional result; @@ -117,8 +129,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { &video_header.video_type_header.emplace()); break; case kVideoCodecH264: - reader.CopyTo( - &video_header.video_type_header.emplace()); + video_header.video_type_header = GenerateRTPVideoHeaderH264(&reader); break; case kVideoCodecH265: // TODO(bugs.webrtc.org/13485) diff --git a/video/rtp_video_stream_receiver2_unittest.cc b/video/rtp_video_stream_receiver2_unittest.cc index 2d5956abd3..d87dc2626e 100644 --- a/video/rtp_video_stream_receiver2_unittest.cc +++ b/video/rtp_video_stream_receiver2_unittest.cc @@ -188,7 +188,7 @@ class RtpVideoStreamReceiver2Test : public ::testing::Test, info.pps_id = -1; data->AppendData({H264::NaluType::kSps, sps_id}); auto& h264 = absl::get(video_header->video_type_header); - h264.nalus[h264.nalus_length++] = info; + h264.nalus.push_back(info); } void AddPps(RTPVideoHeader* video_header, @@ -201,7 +201,7 @@ class RtpVideoStreamReceiver2Test : public ::testing::Test, info.pps_id = pps_id; data->AppendData({H264::NaluType::kPps, pps_id}); auto& h264 = absl::get(video_header->video_type_header); - h264.nalus[h264.nalus_length++] = info; + h264.nalus.push_back(info); } void AddIdr(RTPVideoHeader* video_header, int pps_id) { @@ -210,7 +210,7 @@ class RtpVideoStreamReceiver2Test : public ::testing::Test, info.sps_id = -1; info.pps_id = pps_id; auto& h264 = absl::get(video_header->video_type_header); - h264.nalus[h264.nalus_length++] = info; + h264.nalus.push_back(info); } void OnRtpPacket(const RtpPacketReceived& packet) override {