Reset end-of-frame flag in non-VCL packet.

Bug: chromium:999807
Change-Id: I28309d2fda16842e620e499cb9e77ec771827b8c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157160
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29560}
diff --git a/modules/video_coding/h264_sps_pps_tracker.cc b/modules/video_coding/h264_sps_pps_tracker.cc
index 9c0e521..aa23617 100644
--- a/modules/video_coding/h264_sps_pps_tracker.cc
+++ b/modules/video_coding/h264_sps_pps_tracker.cc
@@ -27,6 +27,22 @@
 
 namespace {
 const uint8_t start_code_h264[] = {0, 0, 0, 1};
+
+bool HasVclData(const VCMPacket& packet) {
+  const auto* h264_header =
+      absl::get_if<RTPVideoHeaderH264>(&packet.video_header.video_type_header);
+  if (h264_header->nalus_length == 0) {
+    return h264_header->nalu_type == H264::NaluType::kIdr ||
+           h264_header->nalu_type == H264::NaluType::kSlice;
+  }
+  for (size_t i = 0; i < h264_header->nalus_length; ++i) {
+    if (h264_header->nalus[i].type == H264::NaluType::kIdr ||
+        h264_header->nalus[i].type == H264::NaluType::kSlice) {
+      return true;
+    }
+  }
+  return false;
+}
 }  // namespace
 
 H264SpsPpsTracker::H264SpsPpsTracker() = default;
@@ -212,6 +228,13 @@
 
   packet->dataPtr = buffer;
   packet->sizeBytes = required_size;
+
+  // If this packet does not contain any VCL NAL units then reset end-of-frame
+  // flag to prevent it from being interpreted as a frame by the packet buffer.
+  if (packet->is_last_packet_in_frame() && !HasVclData(*packet)) {
+    packet->video_header.is_last_packet_in_frame = false;
+  }
+
   return kInsert;
 }
 
diff --git a/modules/video_coding/h264_sps_pps_tracker_unittest.cc b/modules/video_coding/h264_sps_pps_tracker_unittest.cc
index 7857aa7..305b94b 100644
--- a/modules/video_coding/h264_sps_pps_tracker_unittest.cc
+++ b/modules/video_coding/h264_sps_pps_tracker_unittest.cc
@@ -388,5 +388,49 @@
   delete[] idr_packet.dataPtr;
 }
 
+TEST_F(TestH264SpsPpsTracker, ResetEndOfFrameFlagInNonVclPacket) {
+  // Insert SPS/PPS packet with end-of-frame flag set to true. The tracker
+  // should reset the flag since this packet doesn't contain VCL NALUs.
+  std::vector<uint8_t> data;
+  H264VcmPacket packet;
+  packet.video_header.is_last_packet_in_frame = true;
+
+  AddSps(&packet, 0, &data);
+  AddPps(&packet, 0, 1, &data);
+  packet.dataPtr = data.data();
+  packet.sizeBytes = data.size();
+
+  EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet));
+  EXPECT_FALSE(packet.is_last_packet_in_frame());
+  delete[] packet.dataPtr;
+  data.clear();
+}
+
+TEST_F(TestH264SpsPpsTracker, KeepEndOfFrameFlagInVclPacket) {
+  // Insert SPS/PPS/IDR packet with end-of-frame flag set to true. The tracker
+  // should keep the flag since this packet contains VCL NALUs.
+  std::vector<uint8_t> data;
+  H264VcmPacket packet;
+  packet.h264().packetization_type = kH264StapA;
+  packet.video_header.is_first_packet_in_frame =
+      true;  // Always true for STAP-A.
+  packet.video_header.is_last_packet_in_frame = true;
+
+  data.insert(data.end(), {0});     // First byte is ignored
+  data.insert(data.end(), {0, 2});  // Length of segment
+  AddSps(&packet, 13, &data);
+  data.insert(data.end(), {0, 2});  // Length of segment
+  AddPps(&packet, 13, 27, &data);
+  data.insert(data.end(), {0, 5});  // Length of segment
+  AddIdr(&packet, 27);
+  data.insert(data.end(), {1, 2, 3, 2, 1});
+  packet.dataPtr = data.data();
+  packet.sizeBytes = data.size();
+
+  EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet));
+  EXPECT_TRUE(packet.is_last_packet_in_frame());
+  delete[] packet.dataPtr;
+}
+
 }  // namespace video_coding
 }  // namespace webrtc