In Av1 packetizer set marker bit with respect of end_of_picture flag

Bug: webrtc:12167
Change-Id: If14fdd7144951c7aa7e48efd390637dd66201bf7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/192791
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32612}
diff --git a/call/rtp_payload_params.cc b/call/rtp_payload_params.cc
index e0b831e..f8d6776 100644
--- a/call/rtp_payload_params.cc
+++ b/call/rtp_payload_params.cc
@@ -36,6 +36,7 @@
                                    absl::optional<int> spatial_index,
                                    RTPVideoHeader* rtp) {
   rtp->codec = info.codecType;
+  rtp->is_last_frame_in_picture = info.end_of_picture;
   switch (info.codecType) {
     case kVideoCodecVP8: {
       auto& vp8_header = rtp->video_type_header.emplace<RTPVideoHeaderVP8>();
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 7703a6b..7550b70 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -54,8 +54,9 @@
       return std::make_unique<RtpPacketizerVp9>(payload, limits, vp9);
     }
     case kVideoCodecAV1:
-      return std::make_unique<RtpPacketizerAv1>(payload, limits,
-                                                rtp_video_header.frame_type);
+      return std::make_unique<RtpPacketizerAv1>(
+          payload, limits, rtp_video_header.frame_type,
+          rtp_video_header.is_last_frame_in_picture);
     default: {
       return std::make_unique<RtpPacketizerGeneric>(payload, limits,
                                                     rtp_video_header);
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1.cc b/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
index 909b128..4408bee 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
@@ -88,10 +88,12 @@
 
 RtpPacketizerAv1::RtpPacketizerAv1(rtc::ArrayView<const uint8_t> payload,
                                    RtpPacketizer::PayloadSizeLimits limits,
-                                   VideoFrameType frame_type)
+                                   VideoFrameType frame_type,
+                                   bool is_last_frame_in_picture)
     : frame_type_(frame_type),
       obus_(ParseObus(payload)),
-      packets_(Packetize(obus_, limits)) {}
+      packets_(Packetize(obus_, limits)),
+      is_last_frame_in_picture_(is_last_frame_in_picture) {}
 
 std::vector<RtpPacketizerAv1::Obu> RtpPacketizerAv1::ParseObus(
     rtc::ArrayView<const uint8_t> payload) {
@@ -414,11 +416,8 @@
                 kAggregationHeaderSize + next_packet.packet_size);
 
   ++packet_index_;
-  if (packet_index_ == packets_.size()) {
-    // TODO(danilchap): To support spatial scalability pass and use information
-    // if this frame is the last in the temporal unit.
-    packet->SetMarker(true);
-  }
+  bool is_last_packet_in_frame = packet_index_ == packets_.size();
+  packet->SetMarker(is_last_packet_in_frame && is_last_frame_in_picture_);
   return true;
 }
 
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1.h b/modules/rtp_rtcp/source/rtp_packetizer_av1.h
index 79fa6e0..520e746 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1.h
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1.h
@@ -26,7 +26,8 @@
  public:
   RtpPacketizerAv1(rtc::ArrayView<const uint8_t> payload,
                    PayloadSizeLimits limits,
-                   VideoFrameType frame_type);
+                   VideoFrameType frame_type,
+                   bool is_last_frame_in_picture);
   ~RtpPacketizerAv1() override = default;
 
   size_t NumPackets() const override { return packets_.size() - packet_index_; }
@@ -63,6 +64,7 @@
   const VideoFrameType frame_type_;
   const std::vector<Obu> obus_;
   const std::vector<Packet> packets_;
+  const bool is_last_frame_in_picture_;
   size_t packet_index_ = 0;
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc b/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
index 0529e98..84d2b35 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
@@ -88,9 +88,11 @@
 std::vector<RtpPayload> Packetize(
     rtc::ArrayView<const uint8_t> payload,
     RtpPacketizer::PayloadSizeLimits limits,
-    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta) {
+    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta,
+    bool is_last_frame_in_picture = true) {
   // Run code under test.
-  RtpPacketizerAv1 packetizer(payload, limits, frame_type);
+  RtpPacketizerAv1 packetizer(payload, limits, frame_type,
+                              is_last_frame_in_picture);
   // Convert result into structure that is easier to run expectation against.
   std::vector<RtpPayload> result(packetizer.NumPackets());
   for (RtpPayload& rtp_payload : result) {
@@ -332,6 +334,34 @@
   EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
 }
 
+TEST(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
+  auto kFrame = BuildAv1Frame(
+      {Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
+
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 100;
+  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
+                            /*is_last_frame_in_picture=*/true);
+  ASSERT_THAT(payloads, SizeIs(3u));
+  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
+  EXPECT_TRUE(payloads[2].rtp_packet.Marker());
+}
+
+TEST(RtpPacketizerAv1Test, DoesntSetMarkerBitForPacketsNotInEndOfPictureFrame) {
+  auto kFrame = BuildAv1Frame(
+      {Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
+
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 100;
+  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
+                            /*is_last_frame_in_picture=*/false);
+  ASSERT_THAT(payloads, SizeIs(3u));
+  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[2].rtp_packet.Marker());
+}
+
 TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
   // 2nd OBU is too large to fit into one packet, so its head would be in the
   // same packet as the 1st OBU.
diff --git a/modules/rtp_rtcp/source/rtp_video_header.h b/modules/rtp_rtcp/source/rtp_video_header.h
index ca34155..8a2fcba 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.h
+++ b/modules/rtp_rtcp/source/rtp_video_header.h
@@ -70,6 +70,7 @@
   VideoContentType content_type = VideoContentType::UNSPECIFIED;
   bool is_first_packet_in_frame = false;
   bool is_last_packet_in_frame = false;
+  bool is_last_frame_in_picture = true;
   uint8_t simulcastIdx = 0;
   VideoCodecType codec = VideoCodecType::kVideoCodecGeneric;
 
diff --git a/test/fuzzers/rtp_packetizer_av1_fuzzer.cc b/test/fuzzers/rtp_packetizer_av1_fuzzer.cc
index 5277c10f..e5550c1 100644
--- a/test/fuzzers/rtp_packetizer_av1_fuzzer.cc
+++ b/test/fuzzers/rtp_packetizer_av1_fuzzer.cc
@@ -35,7 +35,8 @@
 
   // Main function under test: RtpPacketizerAv1's constructor.
   RtpPacketizerAv1 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
-                              limits, frame_type);
+                              limits, frame_type,
+                              /*is_last_frame_in_picture=*/true);
 
   size_t num_packets = packetizer.NumPackets();
   if (num_packets == 0) {