Deliver I420VideoFrames from VideoRender module.

Performance issue and simplicity, this implementation skips conversion
to VideoEngine's frame format and then back again to I420VideoFrame.

BUG=2526
R=mflodman@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5140 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 26a760a..d889379 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -85,10 +85,10 @@
     }
   }
 
-  render_ = webrtc::ViERender::GetInterface(video_engine);
+  render_ = ViERender::GetInterface(video_engine);
   assert(render_ != NULL);
 
-  render_->AddRenderer(channel_, kVideoI420, this);
+  render_->AddRenderCallback(channel_, this);
 
   if (voice_engine) {
     video_engine_base_->SetVoiceEngine(voice_engine);
@@ -125,21 +125,17 @@
 }
 
 void VideoReceiveStream::StartReceiving() {
-  if (render_->StartRender(channel_)) {
+  if (render_->StartRender(channel_) != 0)
     abort();
-  }
-  if (video_engine_base_->StartReceive(channel_) != 0) {
+  if (video_engine_base_->StartReceive(channel_) != 0)
     abort();
-  }
 }
 
 void VideoReceiveStream::StopReceiving() {
-  if (render_->StopRender(channel_)) {
+  if (render_->StopRender(channel_) != 0)
     abort();
-  }
-  if (video_engine_base_->StopReceive(channel_) != 0) {
+  if (video_engine_base_->StopReceive(channel_) != 0)
     abort();
-  }
 }
 
 void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
@@ -156,44 +152,15 @@
              channel_, packet, static_cast<int>(length)) == 0;
 }
 
-int VideoReceiveStream::FrameSizeChange(unsigned int width,
-                                        unsigned int height,
-                                        unsigned int /*number_of_streams*/) {
-  width_ = width;
-  height_ = height;
-  return 0;
-}
-
-int VideoReceiveStream::DeliverFrame(uint8_t* frame,
-                                     int buffer_size,
-                                     uint32_t timestamp,
-                                     int64_t render_time,
-                                     void* /*handle*/) {
-  if (config_.renderer == NULL) {
+int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
+                                        I420VideoFrame& video_frame) {
+  if (config_.renderer == NULL)
     return 0;
-  }
 
-  I420VideoFrame video_frame;
-  video_frame.CreateEmptyFrame(width_, height_, width_, height_, height_);
-  ConvertToI420(kI420,
-                frame,
-                0,
-                0,
-                width_,
-                height_,
-                buffer_size,
-                webrtc::kRotateNone,
-                &video_frame);
-  video_frame.set_timestamp(timestamp);
-  video_frame.set_render_time_ms(render_time);
-
-  config_.renderer->RenderFrame(video_frame,
-                                render_time - clock_->TimeInMilliseconds());
-
+  config_.renderer->RenderFrame(
+      video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds());
   return 0;
 }
 
-bool VideoReceiveStream::IsTextureSupported() { return false; }
-
 }  // internal
 }  // webrtc
diff --git a/video/video_receive_stream.h b/video/video_receive_stream.h
index da4a9a6..bf6f9db 100644
--- a/video/video_receive_stream.h
+++ b/video/video_receive_stream.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
+#include "webrtc/modules/video_render/include/video_render_defines.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/video/transport_adapter.h"
 #include "webrtc/video_engine/include/vie_render.h"
@@ -34,7 +35,7 @@
 namespace internal {
 
 class VideoReceiveStream : public webrtc::VideoReceiveStream,
-                           public webrtc::ExternalRenderer {
+                           public VideoRenderCallback {
  public:
   VideoReceiveStream(webrtc::VideoEngine* video_engine,
                      const VideoReceiveStream::Config& config,
@@ -47,12 +48,8 @@
 
   virtual void GetCurrentReceiveCodec(VideoCodec* receive_codec) OVERRIDE;
 
-  virtual int FrameSizeChange(unsigned int width, unsigned int height,
-                              unsigned int /*number_of_streams*/) OVERRIDE;
-  virtual int DeliverFrame(uint8_t* frame, int buffer_size, uint32_t timestamp,
-                           int64_t render_time, void* /*handle*/) OVERRIDE;
-
-  virtual bool IsTextureSupported() OVERRIDE;
+  virtual int32_t RenderFrame(const uint32_t stream_id,
+                              I420VideoFrame& video_frame) OVERRIDE;
 
  public:
   virtual bool DeliverRtcp(const uint8_t* packet, size_t length);
@@ -72,10 +69,6 @@
   ViEImageProcess* image_process_;
 
   int channel_;
-
-  // TODO(pbos): Remove VideoReceiveStream can operate on I420 frames directly.
-  unsigned int height_;
-  unsigned int width_;
 };
 }  // internal
 }  // webrtc
diff --git a/video_engine/include/vie_render.h b/video_engine/include/vie_render.h
index 48afc1a..ab7cc6c 100644
--- a/video_engine/include/vie_render.h
+++ b/video_engine/include/vie_render.h
@@ -22,6 +22,7 @@
 
 class VideoEngine;
 class VideoRender;
+class VideoRenderCallback;
 
 // This class declares an abstract interface to be used for external renderers.
 // The user implemented derived class is registered using AddRenderer().
@@ -111,6 +112,13 @@
                           RawVideoType video_input_format,
                           ExternalRenderer* renderer) = 0;
 
+  // Propagating VideoRenderCallback down to the VideoRender module for new API.
+  // Contains default-implementation not to break code mocking this interface.
+  // (Ugly, but temporary.)
+  virtual int AddRenderCallback(int render_id, VideoRenderCallback* callback) {
+    return 0;
+  }
+
  protected:
   ViERender() {}
   virtual ~ViERender() {}
diff --git a/video_engine/vie_render_impl.cc b/video_engine/vie_render_impl.cc
index 507e05a..b7b7c94 100644
--- a/video_engine/vie_render_impl.cc
+++ b/video_engine/vie_render_impl.cc
@@ -394,4 +394,35 @@
   }
 }
 
+int ViERenderImpl::AddRenderCallback(int render_id,
+                                     VideoRenderCallback* callback) {
+  if (render_id < kViEChannelIdBase || render_id > kViEChannelIdMax)
+    return -1;
+  // This is a channel.
+  ViEChannelManagerScoped cm(*(shared_data_->channel_manager()));
+  ViEFrameProviderBase* frame_provider = cm.Channel(render_id);
+  if (!frame_provider) {
+    WEBRTC_TRACE(kTraceError,
+                 kTraceVideo,
+                 ViEId(shared_data_->instance_id()),
+                 "%s: FrameProvider id %d doesn't exist",
+                 __FUNCTION__,
+                 render_id);
+    shared_data_->SetLastError(kViERenderInvalidRenderId);
+    return -1;
+  }
+  ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream(
+      render_id, NULL, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+  if (!renderer) {
+    shared_data_->SetLastError(kViERenderUnknownError);
+    return -1;
+  }
+  if (renderer->SetVideoRenderCallback(render_id, callback) != 0) {
+    shared_data_->SetLastError(kViERenderUnknownError);
+    return -1;
+  }
+
+  return frame_provider->RegisterFrameCallback(render_id, renderer);
+}
+
 }  // namespace webrtc
diff --git a/video_engine/vie_render_impl.h b/video_engine/vie_render_impl.h
index c419794..e8f1587 100644
--- a/video_engine/vie_render_impl.h
+++ b/video_engine/vie_render_impl.h
@@ -46,6 +46,9 @@
   virtual int AddRenderer(const int render_id, RawVideoType video_input_format,
                           ExternalRenderer* renderer);
 
+  virtual int AddRenderCallback(int render_id,
+                                VideoRenderCallback* callback) OVERRIDE;
+
  protected:
   explicit ViERenderImpl(ViESharedData* shared_data);
   virtual ~ViERenderImpl();
diff --git a/video_engine/vie_renderer.cc b/video_engine/vie_renderer.cc
index 35c68aa..e18ebe9 100644
--- a/video_engine/vie_renderer.cc
+++ b/video_engine/vie_renderer.cc
@@ -104,6 +104,11 @@
                                                   incoming_external_callback_);
 }
 
+int32_t ViERenderer::SetVideoRenderCallback(int32_t render_id,
+                                            VideoRenderCallback* callback) {
+  return render_module_.AddExternalRenderCallback(render_id, callback);
+}
+
 ViERenderer::ViERenderer(const int32_t render_id,
                          const int32_t engine_id,
                          VideoRender& render_module,
diff --git a/video_engine/vie_renderer.h b/video_engine/vie_renderer.h
index 4f73e51..907735c 100644
--- a/video_engine/vie_renderer.h
+++ b/video_engine/vie_renderer.h
@@ -86,6 +86,9 @@
                               RawVideoType video_input_format,
                               ExternalRenderer* external_renderer);
 
+  int32_t SetVideoRenderCallback(const int32_t render_id,
+                                 VideoRenderCallback* callback);
+
  private:
   ViERenderer(const int32_t render_id, const int32_t engine_id,
                 VideoRender& render_module,