ViEFrameCallback::DeliverFrame: Make I420VideoFrame const ref.

This CL makes ViEFrameCallback::DeliverFrame const and removes the potential frame copy in ViEFrameProviderBase by moving it to ViEEncoder::DeliverFrame instead, for clients that use the FrameCallback functionality to modify the frame content.

BUG=1128
R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/43949004

Cr-Commit-Position: refs/heads/master@{#8934}
diff --git a/webrtc/video_engine/mock/mock_vie_frame_provider_base.h b/webrtc/video_engine/mock/mock_vie_frame_provider_base.h
index a59fdbf..9228515 100644
--- a/webrtc/video_engine/mock/mock_vie_frame_provider_base.h
+++ b/webrtc/video_engine/mock/mock_vie_frame_provider_base.h
@@ -19,7 +19,7 @@
  public:
   MOCK_METHOD3(DeliverFrame,
                void(int id,
-                    I420VideoFrame* video_frame,
+                    const I420VideoFrame& video_frame,
                     const std::vector<uint32_t>& csrcs));
   MOCK_METHOD2(DelayChanged, void(int id, int frame_delay));
   MOCK_METHOD3(GetPreferedFrameSettings,
diff --git a/webrtc/video_engine/vie_capturer.cc b/webrtc/video_engine/vie_capturer.cc
index 8a48804..d0456db 100644
--- a/webrtc/video_engine/vie_capturer.cc
+++ b/webrtc/video_engine/vie_capturer.cc
@@ -478,7 +478,7 @@
 
 void ViECapturer::DeliverI420Frame(I420VideoFrame* video_frame) {
   if (video_frame->native_handle() != NULL) {
-    ViEFrameProviderBase::DeliverFrame(video_frame, std::vector<uint32_t>());
+    ViEFrameProviderBase::DeliverFrame(*video_frame, std::vector<uint32_t>());
     return;
   }
 
@@ -528,7 +528,7 @@
     }
   }
   // Deliver the captured frame to all observers (channels, renderer or file).
-  ViEFrameProviderBase::DeliverFrame(video_frame, std::vector<uint32_t>());
+  ViEFrameProviderBase::DeliverFrame(*video_frame, std::vector<uint32_t>());
 }
 
 bool ViECapturer::CaptureCapabilityFixed() {
diff --git a/webrtc/video_engine/vie_capturer_unittest.cc b/webrtc/video_engine/vie_capturer_unittest.cc
index 389f0bb..e97a082 100644
--- a/webrtc/video_engine/vie_capturer_unittest.cc
+++ b/webrtc/video_engine/vie_capturer_unittest.cc
@@ -87,10 +87,10 @@
     data_callback_->OnIncomingCapturedFrame(0, *frame);
   }
 
-  void AddOutputFrame(const I420VideoFrame* frame) {
-    if (frame->native_handle() == NULL)
-      output_frame_ybuffers_.push_back(frame->buffer(kYPlane));
-    output_frames_.push_back(new I420VideoFrame(*frame));
+  void AddOutputFrame(const I420VideoFrame& frame) {
+    if (frame.native_handle() == NULL)
+      output_frame_ybuffers_.push_back(frame.buffer(kYPlane));
+    output_frames_.push_back(new I420VideoFrame(frame));
     output_frame_event_->Set();
   }
 
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 82555d7..48a6299 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -1674,7 +1674,7 @@
     no_of_csrcs = 1;
   }
   std::vector<uint32_t> csrcs(arr_ofCSRC, arr_ofCSRC + no_of_csrcs);
-  DeliverFrame(&video_frame, csrcs);
+  DeliverFrame(video_frame, csrcs);
 
   return 0;
 }
diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc
index a03d38e..391766c 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -510,7 +510,7 @@
 }
 
 void ViEEncoder::DeliverFrame(int id,
-                              I420VideoFrame* video_frame,
+                              const I420VideoFrame& video_frame,
                               const std::vector<uint32_t>& csrcs) {
   DCHECK(send_payload_router_ != NULL);
   DCHECK(csrcs.empty());
@@ -529,29 +529,29 @@
     TraceFrameDropEnd();
   }
 
-  TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame->render_time_ms(),
+  TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
                           "Encode");
   I420VideoFrame* decimated_frame = NULL;
   // TODO(wuchengli): support texture frames.
-  if (video_frame->native_handle() == NULL) {
+  if (video_frame.native_handle() == NULL) {
     {
       CriticalSectionScoped cs(callback_cs_.get());
       if (effect_filter_) {
         size_t length =
-            CalcBufferSize(kI420, video_frame->width(), video_frame->height());
+            CalcBufferSize(kI420, video_frame.width(), video_frame.height());
         rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]);
-        ExtractBuffer(*video_frame, length, video_buffer.get());
+        ExtractBuffer(video_frame, length, video_buffer.get());
         effect_filter_->Transform(length,
                                   video_buffer.get(),
-                                  video_frame->ntp_time_ms(),
-                                  video_frame->timestamp(),
-                                  video_frame->width(),
-                                  video_frame->height());
+                                  video_frame.ntp_time_ms(),
+                                  video_frame.timestamp(),
+                                  video_frame.width(),
+                                  video_frame.height());
       }
     }
 
     // Pass frame via preprocessor.
-    const int ret = vpm_.PreprocessFrame(*video_frame, &decimated_frame);
+    const int ret = vpm_.PreprocessFrame(video_frame, &decimated_frame);
     if (ret == 1) {
       // Drop this frame.
       return;
@@ -560,18 +560,28 @@
       return;
     }
   }
-  // If the frame was not resampled or scaled => use original.
-  if (decimated_frame == NULL)  {
-    decimated_frame = video_frame;
-  }
 
+  // If we haven't resampled the frame and we have a FrameCallback, we need to
+  // make a deep copy of |video_frame|.
+  I420VideoFrame copied_frame;
   {
     CriticalSectionScoped cs(callback_cs_.get());
-    if (pre_encode_callback_)
+    if (pre_encode_callback_) {
+      // If the frame was not resampled or scaled => use copy of original.
+      if (decimated_frame == NULL) {
+        copied_frame.CopyFrame(video_frame);
+        decimated_frame = &copied_frame;
+      }
       pre_encode_callback_->FrameCallback(decimated_frame);
+    }
   }
 
-  if (video_frame->native_handle() != NULL) {
+  // If the frame was not resampled, scaled, or touched by FrameCallback => use
+  // original. The frame is const from here.
+  const I420VideoFrame* output_frame =
+      (decimated_frame != NULL) ? decimated_frame : &video_frame;
+
+  if (video_frame.native_handle() != NULL) {
     // TODO(wuchengli): add texture support. http://crbug.com/362437
     return;
   }
@@ -594,12 +604,12 @@
       has_received_rpsi_ = false;
     }
 
-    vcm_.AddVideoFrame(*decimated_frame, vpm_.ContentMetrics(),
+    vcm_.AddVideoFrame(*output_frame, vpm_.ContentMetrics(),
                        &codec_specific_info);
     return;
   }
 #endif
-  vcm_.AddVideoFrame(*decimated_frame);
+  vcm_.AddVideoFrame(*output_frame);
 }
 
 void ViEEncoder::DelayChanged(int id, int frame_delay) {
diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h
index 8683b07..50d1c93 100644
--- a/webrtc/video_engine/vie_encoder.h
+++ b/webrtc/video_engine/vie_encoder.h
@@ -105,7 +105,7 @@
 
   // Implementing ViEFrameCallback.
   void DeliverFrame(int id,
-                    I420VideoFrame* video_frame,
+                    const I420VideoFrame& video_frame,
                     const std::vector<uint32_t>& csrcs) override;
   void DelayChanged(int id, int frame_delay) override;
   int GetPreferedFrameSettings(int* width,
diff --git a/webrtc/video_engine/vie_frame_provider_base.cc b/webrtc/video_engine/vie_frame_provider_base.cc
index c7493a4..a9ee1a8 100644
--- a/webrtc/video_engine/vie_frame_provider_base.cc
+++ b/webrtc/video_engine/vie_frame_provider_base.cc
@@ -45,7 +45,7 @@
   return id_;
 }
 
-void ViEFrameProviderBase::DeliverFrame(I420VideoFrame* video_frame,
+void ViEFrameProviderBase::DeliverFrame(const I420VideoFrame& video_frame,
                                         const std::vector<uint32_t>& csrcs) {
   DCHECK(frame_delivery_thread_checker_.CalledOnValidThread());
 #ifdef DEBUG_
@@ -54,24 +54,9 @@
   CriticalSectionScoped cs(provider_cs_.get());
 
   // Deliver the frame to all registered callbacks.
-  if (frame_callbacks_.size() == 1) {
-    // We don't have to copy the frame.
-    frame_callbacks_.front()->DeliverFrame(id_, video_frame, csrcs);
-  } else {
-    for (ViEFrameCallback* callback : frame_callbacks_) {
-      if (video_frame->native_handle() != NULL) {
-        callback->DeliverFrame(id_, video_frame, csrcs);
-      } else {
-        // Make a copy of the frame for all callbacks.
-        if (!extra_frame_.get()) {
-          extra_frame_.reset(new I420VideoFrame());
-        }
-        // TODO(mflodman): We can get rid of this frame copy.
-        extra_frame_->CopyFrame(*video_frame);
-        callback->DeliverFrame(id_, extra_frame_.get(), csrcs);
-      }
-    }
-  }
+  for (ViEFrameCallback* callback : frame_callbacks_)
+    callback->DeliverFrame(id_, video_frame, csrcs);
+
 #ifdef DEBUG_
   const int process_time =
       static_cast<int>((TickTime::Now() - start_process_time).Milliseconds());
diff --git a/webrtc/video_engine/vie_frame_provider_base.h b/webrtc/video_engine/vie_frame_provider_base.h
index b3ace3b..8ec2f4b 100644
--- a/webrtc/video_engine/vie_frame_provider_base.h
+++ b/webrtc/video_engine/vie_frame_provider_base.h
@@ -29,7 +29,7 @@
 class ViEFrameCallback {
  public:
   virtual void DeliverFrame(int id,
-                            I420VideoFrame* video_frame,
+                            const I420VideoFrame& video_frame,
                             const std::vector<uint32_t>& csrcs) = 0;
 
   // The capture delay has changed from the provider. |frame_delay| is given in
@@ -77,7 +77,7 @@
   virtual int FrameCallbackChanged() = 0;
 
  protected:
-  void DeliverFrame(I420VideoFrame* video_frame,
+  void DeliverFrame(const I420VideoFrame& video_frame,
                     const std::vector<uint32_t>& csrcs);
   void SetFrameDelay(int frame_delay);
   int FrameDelay();
diff --git a/webrtc/video_engine/vie_renderer.cc b/webrtc/video_engine/vie_renderer.cc
index bfeeba2..0deaf2f 100644
--- a/webrtc/video_engine/vie_renderer.cc
+++ b/webrtc/video_engine/vie_renderer.cc
@@ -122,9 +122,9 @@
 }
 
 void ViERenderer::DeliverFrame(int id,
-                               I420VideoFrame* video_frame,
+                               const I420VideoFrame& video_frame,
                                const std::vector<uint32_t>& csrcs) {
-  render_callback_->RenderFrame(render_id_, *video_frame);
+  render_callback_->RenderFrame(render_id_, video_frame);
 }
 
 void ViERenderer::DelayChanged(int id, int frame_delay) {}
diff --git a/webrtc/video_engine/vie_renderer.h b/webrtc/video_engine/vie_renderer.h
index 5a7fdc1..55765a7 100644
--- a/webrtc/video_engine/vie_renderer.h
+++ b/webrtc/video_engine/vie_renderer.h
@@ -97,7 +97,7 @@
 
   // Implement ViEFrameCallback
   virtual void DeliverFrame(int id,
-                            I420VideoFrame* video_frame,
+                            const I420VideoFrame& video_frame,
                             const std::vector<uint32_t>& csrcs);
   virtual void DelayChanged(int id, int frame_delay);
   virtual int GetPreferedFrameSettings(int* width,