Add extended header containing frame ID to the generic packetizer.

Also changes default value of frame ID in RTPVideoHeader to
kNoPictureId. Special care should be take so that picture ID will not
be set in RTPVideoHeader unless the client on the end supports
deserializing extended generic header.

Bug: webrtc:9582
Change-Id: Ib096373ed187f31e51d481193a2bda56de68f167
Reviewed-on: https://webrtc-review.googlesource.com/92084
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24250}
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index 53ff5d5..7ecec76 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -202,9 +202,10 @@
     uint32_t timestamp = 3000;
     uint16_t nack_list[kVideoNackListSize];
     for (int frame = 0; frame < kNumFrames; ++frame) {
+      RTPVideoHeader video_header;
       EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
           webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-          payload_data, payload_data_length, nullptr, nullptr, nullptr));
+          payload_data, payload_data_length, nullptr, &video_header, nullptr));
       // Min required delay until retransmit = 5 + RTT ms (RTT = 0).
       fake_clock.AdvanceTimeMilliseconds(5);
       int length = BuildNackList(nack_list);
@@ -250,9 +251,10 @@
   // Send 30 frames which at the default size is roughly what we need to get
   // enough packets.
   for (int frame = 0; frame < kNumFrames; ++frame) {
+    RTPVideoHeader video_header;
     EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
         webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-        payload_data, payload_data_length, nullptr, nullptr, nullptr));
+        payload_data, payload_data_length, nullptr, &video_header, nullptr));
     // Prepare next frame.
     timestamp += 3000;
     fake_clock.AdvanceTimeMilliseconds(33);
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index f13128f..ef03b99 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -41,7 +41,9 @@
                                   last_packet_reduction_len);
     }
     case kVideoCodecGeneric:
-      return new RtpPacketizerGeneric(frame_type, max_payload_len,
+      RTC_CHECK(rtp_video_header);
+      return new RtpPacketizerGeneric(*rtp_video_header, frame_type,
+                                      max_payload_len,
                                       last_packet_reduction_len);
     default:
       RTC_NOTREACHED();
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.cc b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
index a2a3ad1..1a8efc1 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
@@ -18,13 +18,21 @@
 namespace webrtc {
 
 static const size_t kGenericHeaderLength = 1;
+static const size_t kExtendedHeaderLength = 2;
 
-RtpPacketizerGeneric::RtpPacketizerGeneric(FrameType frame_type,
-                                           size_t max_payload_len,
-                                           size_t last_packet_reduction_len)
-    : payload_data_(NULL),
+RtpPacketizerGeneric::RtpPacketizerGeneric(
+    const RTPVideoHeader& rtp_video_header,
+    FrameType frame_type,
+    size_t max_payload_len,
+    size_t last_packet_reduction_len)
+    : picture_id_(
+          rtp_video_header.frame_id != kNoPictureId
+              ? absl::optional<uint16_t>(rtp_video_header.frame_id & 0x7FFF)
+              : absl::nullopt),
+      payload_data_(nullptr),
       payload_size_(0),
-      max_payload_len_(max_payload_len - kGenericHeaderLength),
+      max_payload_len_(max_payload_len - kGenericHeaderLength -
+                       (picture_id_.has_value() ? kExtendedHeaderLength : 0)),
       last_packet_reduction_len_(last_packet_reduction_len),
       frame_type_(frame_type),
       num_packets_left_(0),
@@ -62,6 +70,10 @@
   if (frame_type_ == kVideoFrameKey) {
     generic_header_ |= RtpFormatVideoGeneric::kKeyFrameBit;
   }
+  if (picture_id_.has_value()) {
+    generic_header_ |= RtpFormatVideoGeneric::kExtendedHeaderBit;
+  }
+
   return num_packets_left_;
 }
 
@@ -86,16 +98,24 @@
   }
   RTC_DCHECK_LE(next_packet_payload_len, max_payload_len_);
 
-  uint8_t* out_ptr =
-      packet->AllocatePayload(kGenericHeaderLength + next_packet_payload_len);
+  size_t total_length = next_packet_payload_len + kGenericHeaderLength +
+                        (picture_id_.has_value() ? kExtendedHeaderLength : 0);
+  uint8_t* out_ptr = packet->AllocatePayload(total_length);
+
   // Put generic header in packet.
   out_ptr[0] = generic_header_;
+  out_ptr += kGenericHeaderLength;
+
+  if (picture_id_.has_value()) {
+    WriteExtendedHeader(out_ptr);
+    out_ptr += kExtendedHeaderLength;
+  }
+
   // Remove first-packet bit, following packets are intermediate.
   generic_header_ &= ~RtpFormatVideoGeneric::kFirstPacketBit;
 
   // Put payload in packet.
-  memcpy(out_ptr + kGenericHeaderLength, payload_data_,
-         next_packet_payload_len);
+  memcpy(out_ptr, payload_data_, next_packet_payload_len);
   payload_data_ += next_packet_payload_len;
   payload_size_ -= next_packet_payload_len;
   --num_packets_left_;
@@ -111,6 +131,13 @@
   return "RtpPacketizerGeneric";
 }
 
+void RtpPacketizerGeneric::WriteExtendedHeader(uint8_t* out_ptr) {
+  // Store bottom 15 bits of the the sequence number. Only 15 bits are used for
+  // compatibility with other packetizer implemenetations that also use 15 bits.
+  out_ptr[0] = (*picture_id_ >> 8) & 0x7F;
+  out_ptr[1] = *picture_id_ & 0xFF;
+}
+
 RtpDepacketizerGeneric::~RtpDepacketizerGeneric() = default;
 
 bool RtpDepacketizerGeneric::Parse(ParsedPayload* parsed_payload,
@@ -118,7 +145,7 @@
                                    size_t payload_data_length) {
   assert(parsed_payload != NULL);
   if (payload_data_length == 0) {
-    RTC_LOG(LS_ERROR) << "Empty payload.";
+    RTC_LOG(LS_WARNING) << "Empty payload.";
     return false;
   }
 
@@ -135,6 +162,17 @@
   parsed_payload->video_header().width = 0;
   parsed_payload->video_header().height = 0;
 
+  if (generic_header & RtpFormatVideoGeneric::kExtendedHeaderBit) {
+    if (payload_data_length < kExtendedHeaderLength) {
+      RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
+      return false;
+    }
+    parsed_payload->video_header().frame_id =
+        ((payload_data[0] & 0x7F) << 8) | payload_data[1];
+    payload_data += kExtendedHeaderLength;
+    payload_data_length -= kExtendedHeaderLength;
+  }
+
   parsed_payload->payload = payload_data;
   parsed_payload->payload_length = payload_data_length;
   return true;
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.h b/modules/rtp_rtcp/source/rtp_format_video_generic.h
index 6031704..e608db5 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.h
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.h
@@ -20,13 +20,17 @@
 namespace RtpFormatVideoGeneric {
 static const uint8_t kKeyFrameBit = 0x01;
 static const uint8_t kFirstPacketBit = 0x02;
+// If this bit is set, there will be an extended header contained in this
+// packet. This was added later so old clients will not send this.
+static const uint8_t kExtendedHeaderBit = 0x04;
 }  // namespace RtpFormatVideoGeneric
 
 class RtpPacketizerGeneric : public RtpPacketizer {
  public:
   // Initialize with payload from encoder.
   // The payload_data must be exactly one encoded generic frame.
-  RtpPacketizerGeneric(FrameType frametype,
+  RtpPacketizerGeneric(const RTPVideoHeader& rtp_video_header,
+                       FrameType frametype,
                        size_t max_payload_len,
                        size_t last_packet_reduction_len);
 
@@ -45,6 +49,7 @@
   std::string ToString() override;
 
  private:
+  const absl::optional<uint16_t> picture_id_;
   const uint8_t* payload_data_;
   size_t payload_size_;
   const size_t max_payload_len_;
@@ -57,6 +62,8 @@
   // Number of packets, which will be 1 byte more than the rest.
   size_t num_larger_packets_;
 
+  void WriteExtendedHeader(uint8_t* out_ptr);
+
   RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerGeneric);
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
index 983bd8f..35ffa67 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
@@ -63,8 +63,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -78,8 +78,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -93,8 +93,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -114,8 +114,8 @@
   // generic header lengh for each packet minus last packet reduction).
   // 4 packets is enough for kPayloadSize.
   const size_t kMinNumPackets = 4;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -128,8 +128,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -143,8 +143,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -158,8 +158,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -179,8 +179,8 @@
   // generic header lengh for each packet minus last packet reduction).
   // 5 packets is enough for kPayloadSize.
   const size_t kMinNumPackets = 5;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -189,4 +189,84 @@
   EXPECT_EQ(num_packets, kMinNumPackets);
 }
 
+TEST(RtpPacketizerVideoGeneric, HasFrameIdWritesExtendedHeader) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.frame_id = 37;
+  RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_TRUE(payload[0] & 0x04);  // Extended header bit is set.
+  // Frame id is 37.
+  EXPECT_EQ(0u, payload[1]);
+  EXPECT_EQ(37u, payload[2]);
+}
+
+TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.frame_id = 0x8137;
+  RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_TRUE(payload[0] & 0x04);  // Extended header bit is set.
+  // Frame id is 0x137.
+  EXPECT_EQ(0x01u, payload[1]);
+  EXPECT_EQ(0x37u, payload[2]);
+}
+
+TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_FALSE(payload[0] & 0x04);
+}
+
+TEST(RtpDepacketizerVideoGeneric, NonExtendedHeaderNoFrameId) {
+  const size_t kPayloadLen = 1;
+  uint8_t payload[kPayloadLen] = {0x01};
+
+  RtpDepacketizerGeneric depacketizer;
+  RtpDepacketizer::ParsedPayload parsed_payload;
+  depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
+
+  EXPECT_EQ(kNoPictureId, parsed_payload.video_header().frame_id);
+}
+
+TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
+  const size_t kPayloadLen = 3;
+  uint8_t payload[kPayloadLen] = {0x05, 0x13, 0x37};
+
+  RtpDepacketizerGeneric depacketizer;
+  RtpDepacketizer::ParsedPayload parsed_payload;
+  depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
+
+  EXPECT_EQ(0x1337, parsed_payload.video_header().frame_id);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 9622680..d143c87 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -244,9 +244,10 @@
     EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType, 90000,
                                               0, 1500));
 
+    RTPVideoHeader video_header;
     EXPECT_TRUE(rtp_sender_->SendOutgoingData(
         kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData,
-        sizeof(kPayloadData), nullptr, nullptr, nullptr,
+        sizeof(kPayloadData), nullptr, &video_header, nullptr,
         kDefaultExpectedRetransmissionTimeMs));
   }
 };
@@ -968,9 +969,10 @@
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
   // Send keyframe
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   uint8_t generic_header = sent_payload[0];
@@ -985,7 +987,7 @@
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   sent_payload = transport_.last_sent_packet().payload();
   generic_header = sent_payload[0];
@@ -1299,9 +1301,10 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, _, _, _, _, _))
       .Times(::testing::AtLeast(2));
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_EQ(1U, callback.num_calls_);
   EXPECT_EQ(ssrc, callback.ssrc_);
@@ -1310,7 +1313,7 @@
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_EQ(2U, callback.num_calls_);
   EXPECT_EQ(ssrc, callback.ssrc_);
@@ -1373,10 +1376,11 @@
   rtp_sender_->ProcessBitrate();
 
   // Send a few frames.
+  RTPVideoHeader video_header;
   for (uint32_t i = 0; i < kNumPackets; ++i) {
     ASSERT_TRUE(rtp_sender_->SendOutgoingData(
         kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-        nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+        nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
     fake_clock_.AdvanceTimeMilliseconds(kPacketInterval);
   }
 
@@ -1457,9 +1461,10 @@
   rtp_sender_->RegisterRtpStatisticsCallback(&callback);
 
   // Send a frame.
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   StreamDataCounters expected;
   expected.transmitted.payload_bytes = 6;
   expected.transmitted.header_bytes = 12;
@@ -1501,7 +1506,7 @@
   rtp_sender_->SetFecParameters(fec_params, fec_params);
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   expected.transmitted.payload_bytes = 40;
   expected.transmitted.header_bytes = 60;
   expected.transmitted.packets = 5;
@@ -1518,9 +1523,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   EXPECT_THAT(sent_payload, ElementsAreArray(payload));
@@ -1537,9 +1543,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   EXPECT_THAT(sent_payload, ElementsAreArray(payload));
@@ -1576,22 +1583,23 @@
   // During start, it takes the starting timestamp as last sent timestamp.
   // The duration is calculated as the difference of current and last sent
   // timestamp. So for first call it will skip since the duration is zero.
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   // DTMF Sample Length is (Frequency/1000) * Duration.
   // So in this case, it is (8000/1000) * 500 = 4000.
   // Sending it as two packets.
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms + 2000, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   // Marker Bit should be set to 1 for first packet.
   EXPECT_TRUE(transport_.last_sent_packet().Marker());
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms + 4000, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   // Marker Bit should be set to 0 for rest of the packets.
   EXPECT_FALSE(transport_.last_sent_packet().Marker());
 }
@@ -1608,9 +1616,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, kPayloadType, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   // Will send 2 full-size padding packets.
   rtp_sender_->TimeToSendPadding(1, PacedPacketInfo());
diff --git a/modules/rtp_rtcp/source/rtp_video_header.h b/modules/rtp_rtcp/source/rtp_video_header.h
index ec3dbd2..edeb48d 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.h
+++ b/modules/rtp_rtcp/source/rtp_video_header.h
@@ -46,7 +46,7 @@
   }
 
   // Information for generic codec descriptor.
-  int64_t frame_id = 0;
+  int64_t frame_id = kNoPictureId;
   int spatial_index = 0;
   int temporal_index = 0;
   absl::InlinedVector<int64_t, 5> dependencies;
diff --git a/modules/rtp_rtcp/test/testAPI/test_api_video.cc b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
index 91d1bfd..2cfc94e 100644
--- a/modules/rtp_rtcp/test/testAPI/test_api_video.cc
+++ b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
@@ -140,9 +140,10 @@
 
 TEST_F(RtpRtcpVideoTest, BasicVideo) {
   uint32_t timestamp = 3000;
+  RTPVideoHeader video_header;
   EXPECT_TRUE(video_module_->SendOutgoingData(
       kVideoFrameDelta, 123, timestamp, timestamp / 90, video_frame_,
-      payload_data_length_, nullptr, nullptr, nullptr));
+      payload_data_length_, nullptr, &video_header, nullptr));
 }
 
 TEST_F(RtpRtcpVideoTest, PaddingOnlyFrames) {