Add a VideoFrameTrackingIdInjector based on the RTP header extension.

Bug: webrtc:12630
Change-Id: I74601cab31deff2978db0b8bfcbf562c975fa48b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/213352
Commit-Queue: Jeremy Leconte <jleconte@google.com>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33601}
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index 2d1288c..95b0a2a 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -18,6 +18,7 @@
       ":quality_analyzing_video_decoder",
       ":quality_analyzing_video_encoder",
       ":single_process_encoded_image_data_injector",
+      ":video_frame_tracking_id_injector",
     ]
     if (rtc_include_tests) {
       deps += [
@@ -37,6 +38,7 @@
         ":multi_head_queue_test",
         ":peer_connection_e2e_smoke_test",
         ":single_process_encoded_image_data_injector_unittest",
+        ":video_frame_tracking_id_injector_unittest",
       ]
     }
   }
@@ -88,6 +90,22 @@
     absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
   }
 
+  rtc_library("video_frame_tracking_id_injector") {
+    visibility = [ "*" ]
+    testonly = true
+    sources = [
+      "analyzer/video/video_frame_tracking_id_injector.cc",
+      "analyzer/video/video_frame_tracking_id_injector.h",
+    ]
+
+    deps = [
+      ":encoded_image_data_injector_api",
+      "../../../api/video:encoded_image",
+      "../../../rtc_base:checks",
+    ]
+    absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+  }
+
   rtc_library("simulcast_dummy_buffer_helper") {
     visibility = [ "*" ]
     testonly = true
@@ -394,6 +412,18 @@
       ]
     }
 
+    rtc_library("video_frame_tracking_id_injector_unittest") {
+      testonly = true
+      sources =
+          [ "analyzer/video/video_frame_tracking_id_injector_unittest.cc" ]
+      deps = [
+        ":video_frame_tracking_id_injector",
+        "../../../api/video:encoded_image",
+        "../../../rtc_base:rtc_base_approved",
+        "../../../test:test_support",
+      ]
+    }
+
     peer_connection_e2e_smoke_test_resources = [
       "../../../resources/pc_quality_smoke_test_alice_source.wav",
       "../../../resources/pc_quality_smoke_test_bob_source.wav",
diff --git a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
index 85e3a8ca..d7ee0f4 100644
--- a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
+++ b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
@@ -50,7 +50,6 @@
   buffer->data()[insertion_pos + 2] = info.sub_id;
 
   EncodedImage out = source;
-  out.SetVideoFrameTrackingId(id);
   out.SetEncodedData(buffer);
   return out;
 }
diff --git a/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.cc b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.cc
new file mode 100644
index 0000000..e149e3f
--- /dev/null
+++ b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.cc
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2021 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 "test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.h"
+
+#include "absl/memory/memory.h"
+#include "api/video/encoded_image.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace webrtc_pc_e2e {
+
+EncodedImage VideoFrameTrackingIdInjector::InjectData(
+    uint16_t id,
+    bool unused_discard,
+    const EncodedImage& source) {
+  RTC_CHECK(!unused_discard);
+  EncodedImage out = source;
+  out.SetVideoFrameTrackingId(id);
+  return out;
+}
+
+EncodedImageExtractionResult VideoFrameTrackingIdInjector::ExtractData(
+    const EncodedImage& source) {
+  return EncodedImageExtractionResult{source.VideoFrameTrackingId().value_or(0),
+                                      source, /*discard=*/false};
+}
+
+}  // namespace webrtc_pc_e2e
+}  // namespace webrtc
diff --git a/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.h b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.h
new file mode 100644
index 0000000..aac7c37
--- /dev/null
+++ b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.h
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2021 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 TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_FRAME_TRACKING_ID_INJECTOR_H_
+#define TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_FRAME_TRACKING_ID_INJECTOR_H_
+
+#include <cstdint>
+
+#include "api/video/encoded_image.h"
+#include "test/pc/e2e/analyzer/video/encoded_image_data_injector.h"
+
+namespace webrtc {
+namespace webrtc_pc_e2e {
+
+// This injector sets and retrieves the provided id in the EncodedImage
+// video_frame_tracking_id field. This is only possible with the RTP header
+// extension VideoFrameTrackingIdExtension that will propagate the input
+// tracking id to the received EncodedImage. This RTP header extension is
+// enabled with the field trial WebRTC-VideoFrameTrackingIdAdvertised
+// (http://www.webrtc.org/experiments/rtp-hdrext/video-frame-tracking-id).
+//
+// Note that this injector doesn't allow to discard frames.
+class VideoFrameTrackingIdInjector : public EncodedImageDataInjector,
+                                     public EncodedImageDataExtractor {
+ public:
+  EncodedImage InjectData(uint16_t id,
+                          bool unused_discard,
+                          const EncodedImage& source) override;
+
+  EncodedImageExtractionResult ExtractData(const EncodedImage& source) override;
+
+  void Start(int) override {}
+  void AddParticipantInCall() override {}
+};
+
+}  // namespace webrtc_pc_e2e
+}  // namespace webrtc
+
+#endif  // TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_FRAME_TRACKING_ID_INJECTOR_H_
diff --git a/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector_unittest.cc b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector_unittest.cc
new file mode 100644
index 0000000..af85b22
--- /dev/null
+++ b/test/pc/e2e/analyzer/video/video_frame_tracking_id_injector_unittest.cc
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2021 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 "test/pc/e2e/analyzer/video/video_frame_tracking_id_injector.h"
+
+#include "api/video/encoded_image.h"
+#include "rtc_base/buffer.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace webrtc_pc_e2e {
+namespace {
+
+EncodedImage CreateEncodedImageOfSizeN(size_t n) {
+  EncodedImage image;
+  rtc::scoped_refptr<EncodedImageBuffer> buffer = EncodedImageBuffer::Create(n);
+  for (size_t i = 0; i < n; ++i) {
+    buffer->data()[i] = static_cast<uint8_t>(i);
+  }
+  image.SetEncodedData(buffer);
+  return image;
+}
+
+TEST(VideoFrameTrackingIdInjectorTest, InjectExtractDiscardFalse) {
+  VideoFrameTrackingIdInjector injector;
+  EncodedImage source = CreateEncodedImageOfSizeN(10);
+  EncodedImageExtractionResult out =
+      injector.ExtractData(injector.InjectData(512, false, source));
+
+  EXPECT_EQ(out.id, 512);
+  EXPECT_FALSE(out.discard);
+  EXPECT_EQ(out.image.size(), 10ul);
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(source.data()[i], out.image.data()[i]);
+  }
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(VideoFrameTrackingIdInjectorTest, InjectExtractDiscardTrue) {
+  VideoFrameTrackingIdInjector injector;
+  EncodedImage source = CreateEncodedImageOfSizeN(10);
+
+  EXPECT_DEATH(injector.InjectData(512, true, source), "");
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace
+}  // namespace webrtc_pc_e2e
+}  // namespace webrtc