diff --git a/modules/video_coding/h264_sps_pps_tracker.cc b/modules/video_coding/h264_sps_pps_tracker.cc index 0741a261e0..5a7eae7b42 100644 --- a/modules/video_coding/h264_sps_pps_tracker.cc +++ b/modules/video_coding/h264_sps_pps_tracker.cc @@ -130,7 +130,6 @@ H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( if (h264_header.packetization_type == kH264StapA) { const uint8_t* nalu_ptr = bitstream.data() + 1; while (nalu_ptr < bitstream.data() + bitstream.size() - 1) { - RTC_DCHECK(video_header->is_first_packet_in_frame); required_size += sizeof(start_code_h264); // The first two bytes describe the length of a segment. diff --git a/modules/video_coding/h264_sps_pps_tracker_unittest.cc b/modules/video_coding/h264_sps_pps_tracker_unittest.cc index 3f07c6ef60..76591e9f5c 100644 --- a/modules/video_coding/h264_sps_pps_tracker_unittest.cc +++ b/modules/video_coding/h264_sps_pps_tracker_unittest.cc @@ -156,6 +156,48 @@ TEST_F(TestH264SpsPpsTracker, StapAIncorrectSegmentLength) { H264SpsPpsTracker::kDrop); } +TEST_F(TestH264SpsPpsTracker, ConsecutiveStapA) { + // When the GenericFrameDescriptor or DependencyDescriptor RTP header + // extensions are used, we may receive a series of StapA packets where only + // the first packet has is_first_packet_in_frame = true set. + std::vector data; + H264VideoHeader first_header; + first_header.h264().packetization_type = kH264StapA; + first_header.is_first_packet_in_frame = true; + + // SPS in first packet. + data.insert(data.end(), {0}); // First byte is ignored + data.insert(data.end(), {0, 2}); // Length of segment + AddSps(&first_header, 13, &data); + H264SpsPpsTracker::FixedBitstream first_fixed = + tracker_.CopyAndFixBitstream(data, &first_header); + EXPECT_THAT(first_fixed.action, H264SpsPpsTracker::kInsert); + + H264VideoHeader second_header; + second_header.h264().packetization_type = kH264StapA; + second_header.is_first_packet_in_frame = false; + + // PPS and IDR in second packet. + data.insert(data.end(), {0, 2}); // Length of segment + AddPps(&second_header, 13, 27, &data); + data.insert(data.end(), {0, 5}); // Length of segment + AddIdr(&second_header, 27); + data.insert(data.end(), {1, 2, 3, 2, 1}); + + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &second_header); + + EXPECT_THAT(fixed.action, H264SpsPpsTracker::kInsert); + std::vector expected; + expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); + expected.insert(expected.end(), {H264::NaluType::kSps, 13}); + expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); + expected.insert(expected.end(), {H264::NaluType::kPps, 27}); + expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); + expected.insert(expected.end(), {1, 2, 3, 2, 1}); + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(expected)); +} + TEST_F(TestH264SpsPpsTracker, SingleNaluInsertStartCode) { uint8_t data[] = {1, 2, 3}; H264VideoHeader header;