Support receiving cloned encoded audio frames

Bug: chromium:1464860
Change-Id: I01b2d768fcf5aef09b32304a8f9fe0b00ca32357
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/316320
Reviewed-by: Tony Herre <herre@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Palak Agarwal <agpalak@google.com>
Cr-Commit-Position: refs/heads/main@{#40583}
diff --git a/audio/channel_receive_frame_transformer_delegate.cc b/audio/channel_receive_frame_transformer_delegate.cc
index 54e08f7..2d2893b 100644
--- a/audio/channel_receive_frame_transformer_delegate.cc
+++ b/audio/channel_receive_frame_transformer_delegate.cc
@@ -112,11 +112,30 @@
   RTC_DCHECK_RUN_ON(&sequence_checker_);
   if (!receive_frame_callback_)
     return;
-  RTC_CHECK_EQ(frame->GetDirection(),
-               TransformableFrameInterface::Direction::kReceiver);
-  auto* transformed_frame =
-      static_cast<TransformableIncomingAudioFrame*>(frame.get());
-  receive_frame_callback_(transformed_frame->GetData(),
-                          transformed_frame->Header());
+
+  RTPHeader header;
+  if (frame->GetDirection() ==
+      TransformableFrameInterface::Direction::kSender) {
+    auto* transformed_frame =
+        static_cast<TransformableAudioFrameInterface*>(frame.get());
+    header.payloadType = transformed_frame->GetPayloadType();
+    header.timestamp = transformed_frame->GetTimestamp();
+    header.ssrc = transformed_frame->GetSsrc();
+    if (transformed_frame->AbsoluteCaptureTimestamp().has_value()) {
+      header.extension.absolute_capture_time = AbsoluteCaptureTime();
+      header.extension.absolute_capture_time->absolute_capture_timestamp =
+          transformed_frame->AbsoluteCaptureTimestamp().value();
+    }
+  } else {
+    auto* transformed_frame =
+        static_cast<TransformableIncomingAudioFrame*>(frame.get());
+    header = transformed_frame->Header();
+  }
+
+  // TODO(crbug.com/1464860): Take an explicit struct with the required
+  // information rather than the RTPHeader to make it easier to
+  // construct the required information when injecting transformed frames not
+  // originally from this receiver.
+  receive_frame_callback_(frame->GetData(), header);
 }
 }  // namespace webrtc
diff --git a/audio/channel_receive_frame_transformer_delegate_unittest.cc b/audio/channel_receive_frame_transformer_delegate_unittest.cc
index e31dd9f..b08dcff 100644
--- a/audio/channel_receive_frame_transformer_delegate_unittest.cc
+++ b/audio/channel_receive_frame_transformer_delegate_unittest.cc
@@ -13,6 +13,7 @@
 #include <memory>
 #include <utility>
 
+#include "audio/channel_send_frame_transformer_delegate.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_frame_transformer.h"
@@ -21,6 +22,8 @@
 namespace webrtc {
 namespace {
 
+using ::testing::_;
+using ::testing::ElementsAre;
 using ::testing::NiceMock;
 using ::testing::SaveArg;
 
@@ -94,6 +97,39 @@
   rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
 }
 
+// Test that when the delegate receives a Outgoing frame from the frame
+// transformer, it passes it to the channel using the ReceiveFrameCallback.
+TEST(ChannelReceiveFrameTransformerDelegateTest,
+     TransformRunsChannelReceiveCallbackForSenderFrame) {
+  rtc::AutoThread main_thread;
+  rtc::scoped_refptr<MockFrameTransformer> mock_frame_transformer =
+      rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
+  MockChannelReceive mock_channel;
+  rtc::scoped_refptr<ChannelReceiveFrameTransformerDelegate> delegate =
+      rtc::make_ref_counted<ChannelReceiveFrameTransformerDelegate>(
+          mock_channel.callback(), mock_frame_transformer,
+          rtc::Thread::Current());
+  rtc::scoped_refptr<TransformedFrameCallback> callback;
+  EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameCallback)
+      .WillOnce(SaveArg<0>(&callback));
+  delegate->Init();
+  ASSERT_TRUE(callback);
+
+  const uint8_t data[] = {1, 2, 3, 4};
+  rtc::ArrayView<const uint8_t> packet(data, sizeof(data));
+  RTPHeader header;
+  EXPECT_CALL(mock_channel, ReceiveFrame(ElementsAre(1, 2, 3, 4), _));
+  ON_CALL(*mock_frame_transformer, Transform)
+      .WillByDefault([&callback](
+                         std::unique_ptr<TransformableFrameInterface> frame) {
+        auto* transformed_frame =
+            static_cast<TransformableAudioFrameInterface*>(frame.get());
+        callback->OnTransformedFrame(CloneSenderAudioFrame(transformed_frame));
+      });
+  delegate->Transform(packet, header, 1111 /*ssrc*/);
+  rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
+}
+
 // Test that if the delegate receives a transformed frame after it has been
 // reset, it does not run the ReceiveFrameCallback, as the channel is destroyed
 // after resetting the delegate.