Return first and last RTP packet sequence number for completed frames.

Change-Id: Icab5c36489317ee2dd62bdda7340437abd07eb7e

Bug: webrtc:12579
Change-Id: Icab5c36489317ee2dd62bdda7340437abd07eb7e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/235041
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35216}
diff --git a/api/video/rtp_video_frame_assembler.cc b/api/video/rtp_video_frame_assembler.cc
index 2629040..271ac22 100644
--- a/api/video/rtp_video_frame_assembler.cc
+++ b/api/video/rtp_video_frame_assembler.cc
@@ -187,7 +187,10 @@
   for (auto& frame : frames) {
     auto complete_frames = reference_finder_.ManageFrame(std::move(frame));
     for (std::unique_ptr<RtpFrameObject>& complete_frame : complete_frames) {
-      res.push_back(std::move(complete_frame));
+      uint16_t rtp_seq_num_start = complete_frame->first_seq_num();
+      uint16_t rtp_seq_num_end = complete_frame->last_seq_num();
+      res.emplace_back(rtp_seq_num_start, rtp_seq_num_end,
+                       std::move(complete_frame));
     }
   }
   return res;
@@ -199,8 +202,12 @@
       FindReferences(AssembleFrames(packet_buffer_.InsertPadding(seq_num)));
   auto ref_finder_update = reference_finder_.PaddingReceived(seq_num);
 
-  res.insert(res.end(), std::make_move_iterator(ref_finder_update.begin()),
-             std::make_move_iterator(ref_finder_update.end()));
+  for (std::unique_ptr<RtpFrameObject>& complete_frame : ref_finder_update) {
+    uint16_t rtp_seq_num_start = complete_frame->first_seq_num();
+    uint16_t rtp_seq_num_end = complete_frame->last_seq_num();
+    res.emplace_back(rtp_seq_num_start, rtp_seq_num_end,
+                     std::move(complete_frame));
+  }
 
   return res;
 }
diff --git a/api/video/rtp_video_frame_assembler.h b/api/video/rtp_video_frame_assembler.h
index 353942b..83162cb 100644
--- a/api/video/rtp_video_frame_assembler.h
+++ b/api/video/rtp_video_frame_assembler.h
@@ -13,6 +13,7 @@
 
 #include <cstdint>
 #include <memory>
+#include <utility>
 
 #include "absl/container/inlined_vector.h"
 #include "api/video/encoded_frame.h"
@@ -26,9 +27,31 @@
 // monotonic in decode order, dependencies are expressed as frame IDs.
 class RtpVideoFrameAssembler {
  public:
+  // The RtpVideoFrameAssembler should return "RTP frames", but for now there
+  // is no good class for this purpose. For now return an EncodedFrame bundled
+  // with some minimal RTP information.
+  class AssembledFrame {
+   public:
+    AssembledFrame(uint16_t rtp_seq_num_start,
+                   uint16_t rtp_seq_num_end,
+                   std::unique_ptr<EncodedFrame> frame)
+        : rtp_seq_num_start_(rtp_seq_num_start),
+          rtp_seq_num_end_(rtp_seq_num_end),
+          frame_(std::move(frame)) {}
+
+    uint16_t RtpSeqNumStart() const { return rtp_seq_num_start_; }
+    uint16_t RtpSeqNumEnd() const { return rtp_seq_num_end_; }
+    std::unique_ptr<EncodedFrame> ExtractFrame() { return std::move(frame_); }
+
+   private:
+    uint16_t rtp_seq_num_start_;
+    uint16_t rtp_seq_num_end_;
+    std::unique_ptr<EncodedFrame> frame_;
+  };
+
   // FrameVector is just a vector-like type of std::unique_ptr<EncodedFrame>.
   // The vector type may change without notice.
-  using FrameVector = absl::InlinedVector<std::unique_ptr<EncodedFrame>, 3>;
+  using FrameVector = absl::InlinedVector<AssembledFrame, 3>;
   enum PayloadFormat { kRaw, kH264, kVp8, kVp9, kAv1, kGeneric };
 
   explicit RtpVideoFrameAssembler(PayloadFormat payload_format);
diff --git a/api/video/rtp_video_frame_assembler_unittests.cc b/api/video/rtp_video_frame_assembler_unittests.cc
index fd70f72..74e4906 100644
--- a/api/video/rtp_video_frame_assembler_unittests.cc
+++ b/api/video/rtp_video_frame_assembler_unittests.cc
@@ -162,13 +162,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(10));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kKeyframePayload));
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(10));
+  EXPECT_THAT(References(first_frame), IsEmpty());
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kKeyframePayload));
 
-  EXPECT_THAT(frames[1]->Id(), Eq(11));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(10));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kDeltaframePayload));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(11));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(10));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaframePayload));
 }
 
 TEST(RtpVideoFrameAssembler, Vp9Packetization) {
@@ -201,13 +203,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(10));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(10));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
-  EXPECT_THAT(frames[1]->Id(), Eq(11));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(10));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(11));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(10));
 }
 
 TEST(RtpVideoFrameAssembler, Av1Packetization) {
@@ -239,13 +243,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(20));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kKeyframePayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(20));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kKeyframePayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
-  EXPECT_THAT(frames[1]->Id(), Eq(21));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kDeltaframePayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(20));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(21));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaframePayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(20));
 }
 
 TEST(RtpVideoFrameAssembler, RawPacketizationDependencyDescriptorExtension) {
@@ -290,13 +296,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(10));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(10));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
-  EXPECT_THAT(frames[1]->Id(), Eq(20));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(10));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(20));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(10));
 }
 
 TEST(RtpVideoFrameAssembler, RawPacketizationGenericDescriptor00Extension) {
@@ -329,13 +337,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(100));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(100));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
-  EXPECT_THAT(frames[1]->Id(), Eq(102));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(100));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(102));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(100));
 }
 
 TEST(RtpVideoFrameAssembler, RawPacketizationGenericPayloadDescriptor) {
@@ -363,13 +373,15 @@
 
   ASSERT_THAT(frames, SizeIs(2));
 
-  EXPECT_THAT(frames[0]->Id(), Eq(123));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(123));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
-  EXPECT_THAT(frames[1]->Id(), Eq(124));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(123));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(124));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(123));
 }
 
 TEST(RtpVideoFrameAssembler, Padding) {
@@ -396,16 +408,18 @@
                frames);
 
   ASSERT_THAT(frames, SizeIs(1));
-  EXPECT_THAT(frames[0]->Id(), Eq(123));
-  EXPECT_THAT(Payload(frames[0]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[0]), IsEmpty());
+  auto first_frame = frames[0].ExtractFrame();
+  EXPECT_THAT(first_frame->Id(), Eq(123));
+  EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(first_frame), IsEmpty());
 
   AppendFrames(assembler.InsertPacket(PaddingPacket(/*seq_num=*/124)), frames);
 
   ASSERT_THAT(frames, SizeIs(2));
-  EXPECT_THAT(frames[1]->Id(), Eq(125));
-  EXPECT_THAT(Payload(frames[1]), ElementsAreArray(kPayload));
-  EXPECT_THAT(References(frames[1]), UnorderedElementsAre(123));
+  auto second_frame = frames[1].ExtractFrame();
+  EXPECT_THAT(second_frame->Id(), Eq(125));
+  EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload));
+  EXPECT_THAT(References(second_frame), UnorderedElementsAre(123));
 }
 
 TEST(RtpVideoFrameAssembler, ClearOldPackets) {
@@ -476,5 +490,94 @@
               SizeIs(1));
 }
 
+TEST(RtpVideoFrameAssembler, SeqNumStartAndSeqNumEndSet) {
+  RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric);
+  RtpVideoFrameAssembler::FrameVector frames;
+  uint8_t kPayload[] =
+      "Some payload that will get split into two when packetized.";
+
+  RTPVideoHeader video_header;
+  video_header.frame_type = VideoFrameType::kVideoFrameKey;
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = sizeof(kPayload) - 1;
+
+  auto packetizer =
+      RtpPacketizer::Create(kVideoCodecGeneric, kPayload, limits, video_header);
+  ASSERT_THAT(packetizer->NumPackets(), Eq(2U));
+
+  RtpPacketReceived::ExtensionManager extension_manager;
+  {
+    RtpPacketToSend send_packet(&extension_manager);
+    packetizer->NextPacket(&send_packet);
+    send_packet.SetSequenceNumber(123);
+    RtpPacketReceived received_packet(&extension_manager);
+    received_packet.Parse(send_packet.Buffer());
+    assembler.InsertPacket(received_packet);
+  }
+
+  {
+    RtpPacketToSend send_packet(&extension_manager);
+    packetizer->NextPacket(&send_packet);
+    send_packet.SetSequenceNumber(124);
+    RtpPacketReceived received_packet(&extension_manager);
+    received_packet.Parse(send_packet.Buffer());
+    AppendFrames(assembler.InsertPacket(received_packet), frames);
+  }
+
+  ASSERT_THAT(frames, SizeIs(1));
+  EXPECT_THAT(frames[0].RtpSeqNumStart(), Eq(123));
+  EXPECT_THAT(frames[0].RtpSeqNumEnd(), Eq(124));
+}
+
+TEST(RtpVideoFrameAssembler, SeqNumStartAndSeqNumEndSetWhenPaddingReceived) {
+  RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric);
+  RtpVideoFrameAssembler::FrameVector frames;
+  uint8_t kPayload[] =
+      "Some payload that will get split into two when packetized.";
+
+  RTPVideoHeader video_header;
+  video_header.frame_type = VideoFrameType::kVideoFrameKey;
+
+  EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric)
+                                         .WithPayload(kPayload)
+                                         .WithVideoHeader(video_header)
+                                         .WithSeqNum(121)
+                                         .Build()),
+              SizeIs(1));
+
+  video_header.frame_type = VideoFrameType::kVideoFrameDelta;
+  RtpPacketReceived::ExtensionManager extension_manager;
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = sizeof(kPayload) - 1;
+
+  auto packetizer =
+      RtpPacketizer::Create(kVideoCodecGeneric, kPayload, limits, video_header);
+  ASSERT_THAT(packetizer->NumPackets(), Eq(2U));
+
+  {
+    RtpPacketToSend send_packet(&extension_manager);
+    packetizer->NextPacket(&send_packet);
+    send_packet.SetSequenceNumber(123);
+    RtpPacketReceived received_packet(&extension_manager);
+    received_packet.Parse(send_packet.Buffer());
+    assembler.InsertPacket(received_packet);
+  }
+
+  {
+    RtpPacketToSend send_packet(&extension_manager);
+    packetizer->NextPacket(&send_packet);
+    send_packet.SetSequenceNumber(124);
+    RtpPacketReceived received_packet(&extension_manager);
+    received_packet.Parse(send_packet.Buffer());
+    assembler.InsertPacket(received_packet);
+  }
+
+  AppendFrames(assembler.InsertPacket(PaddingPacket(/*seq_num=*/122)), frames);
+
+  ASSERT_THAT(frames, SizeIs(1));
+  EXPECT_THAT(frames[0].RtpSeqNumStart(), Eq(123));
+  EXPECT_THAT(frames[0].RtpSeqNumEnd(), Eq(124));
+}
+
 }  // namespace
 }  // namespace webrtc