Do not propagate generic descriptor on receiving frame

It was used only for the frame decryptor.
Decryptor needs only raw representation that it can recreate
in a way compatible with the new version of the descriptor.

This relands commit abf73de8eae90e9ac7e88ce1d52728e8102e824f.
with adjustments.

Change-Id: I935977179bef31d8e1023964b967658e9a7db92d
Bug: webrtc:10342
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168489
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30532}
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index 9005548..f7ce1ab 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -165,6 +165,8 @@
     "source/rtcp_receiver.h",
     "source/rtcp_sender.cc",
     "source/rtcp_sender.h",
+    "source/rtp_descriptor_authentication.cc",
+    "source/rtp_descriptor_authentication.h",
     "source/rtp_format.cc",
     "source/rtp_format.h",
     "source/rtp_format_h264.cc",
diff --git a/modules/rtp_rtcp/source/rtp_descriptor_authentication.cc b/modules/rtp_rtcp/source/rtp_descriptor_authentication.cc
new file mode 100644
index 0000000..f4525f0
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtp_descriptor_authentication.cc
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
+
+#include <cstdint>
+#include <vector>
+
+#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
+#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
+#include "modules/rtp_rtcp/source/rtp_video_header.h"
+
+namespace webrtc {
+
+std::vector<uint8_t> RtpDescriptorAuthentication(
+    const RTPVideoHeader& rtp_video_header) {
+  if (!rtp_video_header.generic) {
+    return {};
+  }
+  const RTPVideoHeader::GenericDescriptorInfo& descriptor =
+      *rtp_video_header.generic;
+  // Default way of creating additional data for an encrypted frame.
+  if (descriptor.spatial_index < 0 || descriptor.temporal_index < 0 ||
+      descriptor.spatial_index >=
+          RtpGenericFrameDescriptor::kMaxSpatialLayers ||
+      descriptor.temporal_index >=
+          RtpGenericFrameDescriptor::kMaxTemporalLayers ||
+      descriptor.dependencies.size() >
+          RtpGenericFrameDescriptor::kMaxNumFrameDependencies) {
+    return {};
+  }
+  RtpGenericFrameDescriptor frame_descriptor;
+  frame_descriptor.SetFirstPacketInSubFrame(true);
+  frame_descriptor.SetLastPacketInSubFrame(false);
+  frame_descriptor.SetTemporalLayer(descriptor.temporal_index);
+  frame_descriptor.SetSpatialLayersBitmask(1 << descriptor.spatial_index);
+  frame_descriptor.SetFrameId(descriptor.frame_id & 0xFFFF);
+  for (int64_t dependency : descriptor.dependencies) {
+    frame_descriptor.AddFrameDependencyDiff(descriptor.frame_id - dependency);
+  }
+  if (descriptor.dependencies.empty()) {
+    frame_descriptor.SetResolution(rtp_video_header.width,
+                                   rtp_video_header.height);
+  }
+  std::vector<uint8_t> result(
+      RtpGenericFrameDescriptorExtension00::ValueSize(frame_descriptor));
+  RtpGenericFrameDescriptorExtension00::Write(result, frame_descriptor);
+  return result;
+}
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_descriptor_authentication.h b/modules/rtp_rtcp/source/rtp_descriptor_authentication.h
new file mode 100644
index 0000000..1791abe
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtp_descriptor_authentication.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_RTP_RTCP_SOURCE_RTP_DESCRIPTOR_AUTHENTICATION_H_
+#define MODULES_RTP_RTCP_SOURCE_RTP_DESCRIPTOR_AUTHENTICATION_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "modules/rtp_rtcp/source/rtp_video_header.h"
+
+namespace webrtc {
+
+// Converts frame dependencies into array of bytes for authentication.
+std::vector<uint8_t> RtpDescriptorAuthentication(
+    const RTPVideoHeader& rtp_video_header);
+
+}  // namespace webrtc
+
+#endif  // MODULES_RTP_RTCP_SOURCE_RTP_DESCRIPTOR_AUTHENTICATION_H_
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
index 7a8af09..465308e 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
@@ -97,22 +97,4 @@
   return true;
 }
 
-void RtpGenericFrameDescriptor::SetByteRepresentation(
-    rtc::ArrayView<const uint8_t> byte_representation) {
-  RTC_CHECK(!byte_representation.empty());
-  byte_representation_.assign(byte_representation.begin(),
-                              byte_representation.end());
-  // Clear end_of_subframe bit.
-  // Because ByteRepresentation is used for frame authentication, bit describing
-  // position of the packet in the frame shouldn't be part of it.
-  // This match RtpVideoSender where descriptor is passed for authentication
-  // before end_of_subframe bit is decided and set, i.e. it is always 0.
-  byte_representation_[0] &= ~0x40;
-}
-
-rtc::ArrayView<const uint8_t>
-RtpGenericFrameDescriptor::GetByteRepresentation() {
-  return byte_representation_;
-}
-
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
index 9e79455..1b83307 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
@@ -70,9 +70,6 @@
   // Returns false on failure, i.e. number of dependencies is too large.
   bool AddFrameDependencyDiff(uint16_t fdiff);
 
-  void SetByteRepresentation(rtc::ArrayView<const uint8_t> representation);
-  rtc::ArrayView<const uint8_t> GetByteRepresentation();
-
  private:
   bool beginning_of_subframe_ = false;
   bool end_of_subframe_ = false;
@@ -86,8 +83,6 @@
   uint16_t frame_deps_id_diffs_[kMaxNumFrameDependencies];
   int width_ = 0;
   int height_ = 0;
-
-  std::vector<uint8_t> byte_representation_;
 };
 
 }  // namespace webrtc
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 77f6186..935151f 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -84,6 +84,7 @@
     "../../api/video:encoded_image",
     "../../api/video:video_bitrate_allocation",
     "../../api/video:video_bitrate_allocator_factory",
+    "../../rtc_base:deprecation",
     "../../system_wrappers:field_trial",
     "../../system_wrappers:metrics",
     "../rtp_rtcp:rtp_video_header",
diff --git a/modules/video_coding/frame_object.cc b/modules/video_coding/frame_object.cc
index 682ce17..7152c3b 100644
--- a/modules/video_coding/frame_object.cc
+++ b/modules/video_coding/frame_object.cc
@@ -37,7 +37,6 @@
     VideoContentType content_type,
     const RTPVideoHeader& video_header,
     const absl::optional<webrtc::ColorSpace>& color_space,
-    const absl::optional<RtpGenericFrameDescriptor>& generic_descriptor,
     RtpPacketInfos packet_infos,
     rtc::scoped_refptr<EncodedImageBuffer> image_buffer)
     : first_seq_num_(first_seq_num),
@@ -45,7 +44,6 @@
       last_packet_received_time_(last_packet_received_time),
       times_nacked_(times_nacked) {
   rtp_video_header_ = video_header;
-  rtp_generic_frame_descriptor_ = generic_descriptor;
 
   // EncodedFrame members
   codec_type_ = codec;
@@ -92,6 +90,43 @@
   is_last_spatial_layer = markerBit;
 }
 
+RtpFrameObject::RtpFrameObject(
+    uint16_t first_seq_num,
+    uint16_t last_seq_num,
+    bool markerBit,
+    int times_nacked,
+    int64_t first_packet_received_time,
+    int64_t last_packet_received_time,
+    uint32_t rtp_timestamp,
+    int64_t ntp_time_ms,
+    const VideoSendTiming& timing,
+    uint8_t payload_type,
+    VideoCodecType codec,
+    VideoRotation rotation,
+    VideoContentType content_type,
+    const RTPVideoHeader& video_header,
+    const absl::optional<webrtc::ColorSpace>& color_space,
+    const absl::optional<RtpGenericFrameDescriptor>& /*generic_descriptor*/,
+    RtpPacketInfos packet_infos,
+    rtc::scoped_refptr<EncodedImageBuffer> image_buffer)
+    : RtpFrameObject(first_seq_num,
+                     last_seq_num,
+                     markerBit,
+                     times_nacked,
+                     first_packet_received_time,
+                     last_packet_received_time,
+                     rtp_timestamp,
+                     ntp_time_ms,
+                     timing,
+                     payload_type,
+                     codec,
+                     rotation,
+                     content_type,
+                     video_header,
+                     color_space,
+                     std::move(packet_infos),
+                     std::move(image_buffer)) {}
+
 RtpFrameObject::~RtpFrameObject() {
 }
 
@@ -131,11 +166,6 @@
   return rtp_video_header_;
 }
 
-const absl::optional<RtpGenericFrameDescriptor>&
-RtpFrameObject::GetGenericFrameDescriptor() const {
-  return rtp_generic_frame_descriptor_;
-}
-
 const FrameMarking& RtpFrameObject::GetFrameMarking() const {
   return rtp_video_header_.frame_marking;
 }
diff --git a/modules/video_coding/frame_object.h b/modules/video_coding/frame_object.h
index b3cee20..f43fafd 100644
--- a/modules/video_coding/frame_object.h
+++ b/modules/video_coding/frame_object.h
@@ -14,12 +14,32 @@
 #include "absl/types/optional.h"
 #include "api/video/encoded_frame.h"
 #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
+#include "rtc_base/deprecation.h"
 
 namespace webrtc {
 namespace video_coding {
 
 class RtpFrameObject : public EncodedFrame {
  public:
+  RtpFrameObject(uint16_t first_seq_num,
+                 uint16_t last_seq_num,
+                 bool markerBit,
+                 int times_nacked,
+                 int64_t first_packet_received_time,
+                 int64_t last_packet_received_time,
+                 uint32_t rtp_timestamp,
+                 int64_t ntp_time_ms,
+                 const VideoSendTiming& timing,
+                 uint8_t payload_type,
+                 VideoCodecType codec,
+                 VideoRotation rotation,
+                 VideoContentType content_type,
+                 const RTPVideoHeader& video_header,
+                 const absl::optional<webrtc::ColorSpace>& color_space,
+                 RtpPacketInfos packet_infos,
+                 rtc::scoped_refptr<EncodedImageBuffer> image_buffer);
+
+  RTC_DEPRECATED
   RtpFrameObject(
       uint16_t first_seq_num,
       uint16_t last_seq_num,
@@ -50,13 +70,10 @@
   int64_t RenderTime() const override;
   bool delayed_by_retransmission() const override;
   const RTPVideoHeader& GetRtpVideoHeader() const;
-  const absl::optional<RtpGenericFrameDescriptor>& GetGenericFrameDescriptor()
-      const;
   const FrameMarking& GetFrameMarking() const;
 
  private:
   RTPVideoHeader rtp_video_header_;
-  absl::optional<RtpGenericFrameDescriptor> rtp_generic_frame_descriptor_;
   VideoCodecType codec_type_;
   uint16_t first_seq_num_;
   uint16_t last_seq_num_;
diff --git a/modules/video_coding/packet_buffer.cc b/modules/video_coding/packet_buffer.cc
index 6ebb9c4..73abbbe 100644
--- a/modules/video_coding/packet_buffer.cc
+++ b/modules/video_coding/packet_buffer.cc
@@ -473,7 +473,6 @@
       last_packet.video_header.content_type,    //
       first_packet.video_header,                //
       last_packet.video_header.color_space,     //
-      first_packet.generic_descriptor,          //
       RtpPacketInfos(std::move(packet_infos)),  //
       std::move(bitstream));
 }
diff --git a/modules/video_coding/packet_buffer.h b/modules/video_coding/packet_buffer.h
index f78147c..5ce67ba 100644
--- a/modules/video_coding/packet_buffer.h
+++ b/modules/video_coding/packet_buffer.h
@@ -19,7 +19,6 @@
 #include "absl/base/attributes.h"
 #include "api/rtp_packet_info.h"
 #include "api/video/encoded_image.h"
-#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "modules/rtp_rtcp/source/rtp_video_header.h"
 #include "modules/video_coding/frame_object.h"
@@ -67,7 +66,6 @@
 
     rtc::CopyOnWriteBuffer video_payload;
     RTPVideoHeader video_header;
-    absl::optional<RtpGenericFrameDescriptor> generic_descriptor;
 
     RtpPacketInfo packet_info;
   };
diff --git a/modules/video_coding/rtp_frame_reference_finder_unittest.cc b/modules/video_coding/rtp_frame_reference_finder_unittest.cc
index 29fdba5..e103023 100644
--- a/modules/video_coding/rtp_frame_reference_finder_unittest.cc
+++ b/modules/video_coding/rtp_frame_reference_finder_unittest.cc
@@ -57,7 +57,6 @@
       VideoContentType::UNSPECIFIED,
       video_header,
       /*color_space=*/absl::nullopt,
-      /*generic_descriptor=*/absl::nullopt,
       RtpPacketInfos(),
       EncodedImageBuffer::Create(/*size=*/0));
   // clang-format on
diff --git a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
index 0aa8e75..96eca94 100644
--- a/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
+++ b/test/fuzzers/rtp_frame_reference_finder_fuzzer.cc
@@ -63,25 +63,31 @@
       std::unique_ptr<video_coding::EncodedFrame> frame) override {}
 };
 
-RtpGenericFrameDescriptor GenerateRtpGenericFrameDescriptor(
-    DataReader* reader) {
-  RtpGenericFrameDescriptor res;
-  res.SetFirstPacketInSubFrame(true);
-  res.SetFrameId(reader->GetNum<uint16_t>());
-
-  int spatial_layer =
-      reader->GetNum<uint8_t>() % RtpGenericFrameDescriptor::kMaxSpatialLayers;
-  res.SetSpatialLayersBitmask(1 << spatial_layer);
-  res.SetTemporalLayer(reader->GetNum<uint8_t>() %
-                       RtpGenericFrameDescriptor::kMaxTemporalLayers);
-
-  int num_diffs = (reader->GetNum<uint8_t>() %
-                   RtpGenericFrameDescriptor::kMaxNumFrameDependencies);
-  for (int i = 0; i < num_diffs; ++i) {
-    res.AddFrameDependencyDiff(reader->GetNum<uint16_t>() % (1 << 14));
+absl::optional<RTPVideoHeader::GenericDescriptorInfo>
+GenerateGenericFrameDependencies(DataReader* reader) {
+  absl::optional<RTPVideoHeader::GenericDescriptorInfo> result;
+  uint8_t flags = reader->GetNum<uint8_t>();
+  if (flags & 0b1000'0000) {
+    // i.e. with 50% chance there are no generic dependencies.
+    // in such case codec-specfic code path of the RtpFrameReferenceFinder will
+    // be validated.
+    return result;
   }
 
-  return res;
+  result.emplace();
+  result->frame_id = reader->GetNum<int64_t>();
+  result->spatial_index = (flags & 0b0111'0000) >> 4;
+  result->temporal_index = (flags & 0b0000'1110) >> 1;
+  result->discardable = (flags & 0b0000'0001);
+
+  // Larger than supported by the RtpFrameReferenceFinder.
+  int num_diffs = (reader->GetNum<uint8_t>() % 16);
+  for (int i = 0; i < num_diffs; ++i) {
+    result->dependencies.push_back(result->frame_id -
+                                   (reader->GetNum<uint16_t>() % (1 << 14)));
+  }
+
+  return result;
 }
 }  // namespace
 
@@ -90,7 +96,7 @@
   NullCallback cb;
   video_coding::RtpFrameReferenceFinder reference_finder(&cb);
 
-  auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 4);
+  auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 5);
 
   while (reader.MoreToRead()) {
     uint16_t first_seq_num = reader.GetNum<uint16_t>();
@@ -128,6 +134,7 @@
     }
 
     reader.CopyTo(&video_header.frame_marking);
+    video_header.generic = GenerateGenericFrameDependencies(&reader);
 
     // clang-format off
     auto frame = std::make_unique<video_coding::RtpFrameObject>(
@@ -146,7 +153,6 @@
         VideoContentType::UNSPECIFIED,
         video_header,
         /*color_space=*/absl::nullopt,
-        GenerateRtpGenericFrameDescriptor(&reader),
         RtpPacketInfos(),
         EncodedImageBuffer::Create(/*size=*/0));
     // clang-format on
diff --git a/video/buffered_frame_decryptor.cc b/video/buffered_frame_decryptor.cc
index 90d14d3..ae83da9 100644
--- a/video/buffered_frame_decryptor.cc
+++ b/video/buffered_frame_decryptor.cc
@@ -11,7 +11,10 @@
 #include "video/buffered_frame_decryptor.h"
 
 #include <utility>
+#include <vector>
 
+#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
+#include "modules/video_coding/frame_object.h"
 #include "rtc_base/logging.h"
 #include "system_wrappers/include/field_trial.h"
 
@@ -60,9 +63,7 @@
     return FrameDecision::kStash;
   }
   // When using encryption we expect the frame to have the generic descriptor.
-  absl::optional<RtpGenericFrameDescriptor> descriptor =
-      frame->GetGenericFrameDescriptor();
-  if (!descriptor) {
+  if (frame->GetRtpVideoHeader().generic == absl::nullopt) {
     RTC_LOG(LS_ERROR) << "No generic frame descriptor found dropping frame.";
     return FrameDecision::kDrop;
   }
@@ -76,9 +77,9 @@
                                                      max_plaintext_byte_size);
 
   // Only enable authenticating the header if the field trial is enabled.
-  rtc::ArrayView<const uint8_t> additional_data;
+  std::vector<uint8_t> additional_data;
   if (generic_descriptor_auth_experiment_) {
-    additional_data = descriptor->GetByteRepresentation();
+    additional_data = RtpDescriptorAuthentication(frame->GetRtpVideoHeader());
   }
 
   // Attempt to decrypt the video frame.
diff --git a/video/buffered_frame_decryptor_unittest.cc b/video/buffered_frame_decryptor_unittest.cc
index 1b21acf..bbc08b0 100644
--- a/video/buffered_frame_decryptor_unittest.cc
+++ b/video/buffered_frame_decryptor_unittest.cc
@@ -57,6 +57,8 @@
   std::unique_ptr<video_coding::RtpFrameObject> CreateRtpFrameObject(
       bool key_frame) {
     seq_num_++;
+    RTPVideoHeader rtp_video_header;
+    rtp_video_header.generic.emplace();
 
     // clang-format off
     return std::make_unique<video_coding::RtpFrameObject>(
@@ -73,9 +75,8 @@
         kVideoCodecGeneric,
         kVideoRotation_0,
         VideoContentType::UNSPECIFIED,
-        RTPVideoHeader(),
+        rtp_video_header,
         /*color_space=*/absl::nullopt,
-        RtpGenericFrameDescriptor(),
         RtpPacketInfos(),
         EncodedImageBuffer::Create(/*size=*/0));
     // clang-format on
diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc
index 9f5fe02..cce557a 100644
--- a/video/rtp_video_stream_receiver.cc
+++ b/video/rtp_video_stream_receiver.cc
@@ -28,6 +28,7 @@
 #include "modules/rtp_rtcp/include/ulpfec_receiver.h"
 #include "modules/rtp_rtcp/source/create_video_rtp_depacketizer.h"
 #include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
 #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
@@ -367,51 +368,43 @@
   rtp_packet.GetExtension<PlayoutDelayLimits>(&video_header.playout_delay);
   rtp_packet.GetExtension<FrameMarkingExtension>(&video_header.frame_marking);
 
-  RtpGenericFrameDescriptor& generic_descriptor =
-      packet->generic_descriptor.emplace();
-  if (rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension01>(
-          &generic_descriptor)) {
-    if (rtp_packet.HasExtension<RtpGenericFrameDescriptorExtension00>()) {
-      RTC_LOG(LS_WARNING) << "RTP packet had two different GFD versions.";
-      return;
-    }
-    generic_descriptor.SetByteRepresentation(
-        rtp_packet.GetRawExtension<RtpGenericFrameDescriptorExtension01>());
-  } else if ((rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension00>(
-                 &generic_descriptor))) {
-    generic_descriptor.SetByteRepresentation(
-        rtp_packet.GetRawExtension<RtpGenericFrameDescriptorExtension00>());
-  } else {
-    packet->generic_descriptor = absl::nullopt;
+  if (rtp_packet.HasExtension<RtpGenericFrameDescriptorExtension00>() &&
+      rtp_packet.HasExtension<RtpGenericFrameDescriptorExtension01>()) {
+    RTC_LOG(LS_WARNING) << "RTP packet had two different GFD versions.";
+    return;
   }
-  if (packet->generic_descriptor != absl::nullopt) {
-    video_header.is_first_packet_in_frame =
-        packet->generic_descriptor->FirstPacketInSubFrame();
-    video_header.is_last_packet_in_frame =
-        packet->generic_descriptor->LastPacketInSubFrame();
 
-    if (packet->generic_descriptor->FirstPacketInSubFrame()) {
+  RtpGenericFrameDescriptor generic_descriptor;
+  bool has_generic_descriptor =
+      rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension01>(
+          &generic_descriptor) ||
+      rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension00>(
+          &generic_descriptor);
+  if (has_generic_descriptor) {
+    video_header.is_first_packet_in_frame =
+        generic_descriptor.FirstPacketInSubFrame();
+    video_header.is_last_packet_in_frame =
+        generic_descriptor.LastPacketInSubFrame();
+
+    if (generic_descriptor.FirstPacketInSubFrame()) {
       video_header.frame_type =
-          packet->generic_descriptor->FrameDependenciesDiffs().empty()
+          generic_descriptor.FrameDependenciesDiffs().empty()
               ? VideoFrameType::kVideoFrameKey
               : VideoFrameType::kVideoFrameDelta;
 
       auto& descriptor = video_header.generic.emplace();
       int64_t frame_id =
-          frame_id_unwrapper_.Unwrap(packet->generic_descriptor->FrameId());
+          frame_id_unwrapper_.Unwrap(generic_descriptor.FrameId());
       descriptor.frame_id = frame_id;
-      descriptor.spatial_index = packet->generic_descriptor->SpatialLayer();
-      descriptor.temporal_index = packet->generic_descriptor->TemporalLayer();
-      descriptor.discardable =
-          packet->generic_descriptor->Discardable().value_or(false);
-      for (uint16_t fdiff :
-           packet->generic_descriptor->FrameDependenciesDiffs()) {
+      descriptor.spatial_index = generic_descriptor.SpatialLayer();
+      descriptor.temporal_index = generic_descriptor.TemporalLayer();
+      descriptor.discardable = generic_descriptor.Discardable().value_or(false);
+      for (uint16_t fdiff : generic_descriptor.FrameDependenciesDiffs()) {
         descriptor.dependencies.push_back(frame_id - fdiff);
       }
     }
-
-    video_header.width = packet->generic_descriptor->Width();
-    video_header.height = packet->generic_descriptor->Height();
+    video_header.width = generic_descriptor.Width();
+    video_header.height = generic_descriptor.Height();
   }
 
   // Color space should only be transmitted in the last packet of a frame,
@@ -435,7 +428,7 @@
       // TODO(bugs.webrtc.org/10336): Implement support for reordering.
       RTC_LOG(LS_INFO)
           << "LossNotificationController does not support reordering.";
-    } else if (!packet->generic_descriptor) {
+    } else if (!has_generic_descriptor) {
       RTC_LOG(LS_WARNING) << "LossNotificationController requires generic "
                              "frame descriptor, but it is missing.";
     } else {