Allow Video Sender OnTransformedFrame() before TransformFrame()

Lazily initialize the RTPSenderVideoFrameTransformerDelegate's
encoder_queue_ on either OnTransformedFrame() or TransformFrame(), to
allow apps to write to an encoded insertable stream's writable before
reading from its readable.

Bug: chromium:1393373
Change-Id: I08f11682fa142884b575bb207d7d7044e80bbb9c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/284921
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tony Herre <herre@google.com>
Auto-Submit: Tony Herre <herre@google.com>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38728}
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
index 3d6931f..3e42781 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
@@ -112,14 +112,9 @@
       rtc::scoped_refptr<TransformedFrameCallback>(this), ssrc_);
 }
 
-bool RTPSenderVideoFrameTransformerDelegate::TransformFrame(
-    int payload_type,
-    absl::optional<VideoCodecType> codec_type,
-    uint32_t rtp_timestamp,
-    const EncodedImage& encoded_image,
-    RTPVideoHeader video_header,
-    absl::optional<int64_t> expected_retransmission_time_ms) {
+void RTPSenderVideoFrameTransformerDelegate::EnsureEncoderQueueCreated() {
   TaskQueueBase* current = TaskQueueBase::Current();
+
   if (!encoder_queue_) {
     // Save the current task queue to post the transformed frame for sending
     // once it is transformed. When there is no current task queue, i.e.
@@ -133,6 +128,18 @@
       encoder_queue_ = owned_encoder_queue_.get();
     }
   }
+}
+
+bool RTPSenderVideoFrameTransformerDelegate::TransformFrame(
+    int payload_type,
+    absl::optional<VideoCodecType> codec_type,
+    uint32_t rtp_timestamp,
+    const EncodedImage& encoded_image,
+    RTPVideoHeader video_header,
+    absl::optional<int64_t> expected_retransmission_time_ms) {
+  EnsureEncoderQueueCreated();
+
+  TaskQueueBase* current = TaskQueueBase::Current();
   // DCHECK that the current queue does not change, or if does then it was due
   // to a hardware encoder fallback and thus there is an owned queue.
   RTC_DCHECK(!current || current == encoder_queue_ || owned_encoder_queue_)
@@ -152,10 +159,9 @@
     std::unique_ptr<TransformableFrameInterface> frame) {
   MutexLock lock(&sender_lock_);
 
-  // The encoder queue normally gets destroyed after the sender;
-  // however, it might still be null by the time a previously queued frame
-  // arrives.
-  if (!sender_ || !encoder_queue_)
+  EnsureEncoderQueueCreated();
+
+  if (!sender_)
     return;
   rtc::scoped_refptr<RTPSenderVideoFrameTransformerDelegate> delegate(this);
   encoder_queue_->PostTask(
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h
index 65d6d3f..0c2a643 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h
@@ -74,6 +74,8 @@
   ~RTPSenderVideoFrameTransformerDelegate() override = default;
 
  private:
+  void EnsureEncoderQueueCreated();
+
   mutable Mutex sender_lock_;
   RTPSenderVideo* sender_ RTC_GUARDED_BY(sender_lock_);
   rtc::scoped_refptr<FrameTransformerInterface> frame_transformer_;