Add concept of whether video renderer supports rotation.

Rotation is best done when rendered in GPU, added the shader code which rotates the frame. For renderers which don't support rotation, the rotation will be done before sending down the frame to render. By default, assume renderer can't do rotation.

BUG=4145
R=glaznev@webrtc.org, pthatcher@webrtc.org

Committed: https://code.google.com/p/webrtc/source/detail?r=8660

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

Cr-Commit-Position: refs/heads/master@{#8661}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8661 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/media/base/videoframe.cc b/talk/media/base/videoframe.cc
index 990552e..83790d2 100644
--- a/talk/media/base/videoframe.cc
+++ b/talk/media/base/videoframe.cc
@@ -122,51 +122,6 @@
                dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch());
 }
 
-const VideoFrame* VideoFrame::GetCopyWithRotationApplied() const {
-  // If the frame is not rotated, the caller should reuse this frame instead of
-  // making a redundant copy.
-  if (GetVideoRotation() == webrtc::kVideoRotation_0) {
-    return this;
-  }
-
-  // If the video frame is backed up by a native handle, it resides in the GPU
-  // memory which we can't rotate here. The assumption is that the renderers
-  // which uses GPU to render should be able to rotate themselves.
-  DCHECK(!GetNativeHandle());
-
-  if (rotated_frame_) {
-    return rotated_frame_.get();
-  }
-
-  int width = static_cast<int>(GetWidth());
-  int height = static_cast<int>(GetHeight());
-
-  int rotated_width = width;
-  int rotated_height = height;
-  if (GetVideoRotation() == webrtc::kVideoRotation_90 ||
-      GetVideoRotation() == webrtc::kVideoRotation_270) {
-    rotated_width = height;
-    rotated_height = width;
-  }
-
-  rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height,
-                                        GetPixelWidth(), GetPixelHeight(),
-                                        GetElapsedTime(), GetTimeStamp()));
-
-  // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from
-  // VideoRotation to libyuv::RotationMode.
-  int ret = libyuv::I420Rotate(
-      GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(),
-      GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(),
-      rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(),
-      rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), width, height,
-      static_cast<libyuv::RotationMode>(GetVideoRotation()));
-  if (ret == 0) {
-    return rotated_frame_.get();
-  }
-  return nullptr;
-}
-
 size_t VideoFrame::ConvertToRgbBuffer(uint32 to_fourcc,
                                       uint8* buffer,
                                       size_t size,
diff --git a/talk/media/base/videoframe.h b/talk/media/base/videoframe.h
index ce3cd28..371dd9b 100644
--- a/talk/media/base/videoframe.h
+++ b/talk/media/base/videoframe.h
@@ -29,7 +29,6 @@
 #define TALK_MEDIA_BASE_VIDEOFRAME_H_
 
 #include "webrtc/base/basictypes.h"
-#include "webrtc/base/scoped_ptr.h"
 #include "webrtc/base/stream.h"
 #include "webrtc/common_video/rotation.h"
 
@@ -162,7 +161,9 @@
 
   // Return a copy of frame which has its pending rotation applied. The
   // ownership of the returned frame is held by this frame.
-  virtual const VideoFrame* GetCopyWithRotationApplied() const;
+  virtual const VideoFrame* GetCopyWithRotationApplied() const {
+    return nullptr;
+  }
 
   // Writes the frame into the given stream and returns the StreamResult.
   // See webrtc/base/stream.h for a description of StreamResult and error.
@@ -228,11 +229,6 @@
                                        size_t pixel_height,
                                        int64_t elapsed_time,
                                        int64_t time_stamp) const = 0;
-
- private:
-  // This is mutable as the calculation is expensive but once calculated, it
-  // remains const.
-  mutable rtc::scoped_ptr<VideoFrame> rotated_frame_;
 };
 
 }  // namespace cricket
diff --git a/talk/media/webrtc/webrtcvideoframe.cc b/talk/media/webrtc/webrtcvideoframe.cc
index 052e6f2..8d702c9 100644
--- a/talk/media/webrtc/webrtcvideoframe.cc
+++ b/talk/media/webrtc/webrtcvideoframe.cc
@@ -288,4 +288,49 @@
   rotation_ = webrtc::kVideoRotation_0;
 }
 
+const VideoFrame* WebRtcVideoFrame::GetCopyWithRotationApplied() const {
+  // If the frame is not rotated, the caller should reuse this frame instead of
+  // making a redundant copy.
+  if (GetVideoRotation() == webrtc::kVideoRotation_0) {
+    return this;
+  }
+
+  // If the video frame is backed up by a native handle, it resides in the GPU
+  // memory which we can't rotate here. The assumption is that the renderers
+  // which uses GPU to render should be able to rotate themselves.
+  DCHECK(!GetNativeHandle());
+
+  if (rotated_frame_) {
+    return rotated_frame_.get();
+  }
+
+  int width = static_cast<int>(GetWidth());
+  int height = static_cast<int>(GetHeight());
+
+  int rotated_width = width;
+  int rotated_height = height;
+  if (GetVideoRotation() == webrtc::kVideoRotation_90 ||
+      GetVideoRotation() == webrtc::kVideoRotation_270) {
+    rotated_width = height;
+    rotated_height = width;
+  }
+
+  rotated_frame_.reset(CreateEmptyFrame(rotated_width, rotated_height,
+                                        GetPixelWidth(), GetPixelHeight(),
+                                        GetElapsedTime(), GetTimeStamp()));
+
+  // TODO(guoweis): Add a function in webrtc_libyuv.cc to convert from
+  // VideoRotation to libyuv::RotationMode.
+  int ret = libyuv::I420Rotate(
+      GetYPlane(), GetYPitch(), GetUPlane(), GetUPitch(), GetVPlane(),
+      GetVPitch(), rotated_frame_->GetYPlane(), rotated_frame_->GetYPitch(),
+      rotated_frame_->GetUPlane(), rotated_frame_->GetUPitch(),
+      rotated_frame_->GetVPlane(), rotated_frame_->GetVPitch(), width, height,
+      static_cast<libyuv::RotationMode>(GetVideoRotation()));
+  if (ret == 0) {
+    return rotated_frame_.get();
+  }
+  return nullptr;
+}
+
 }  // namespace cricket
diff --git a/talk/media/webrtc/webrtcvideoframe.h b/talk/media/webrtc/webrtcvideoframe.h
index 29e5ec8..bdbe11d 100644
--- a/talk/media/webrtc/webrtcvideoframe.h
+++ b/talk/media/webrtc/webrtcvideoframe.h
@@ -124,6 +124,8 @@
   virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8* buffer,
                                     size_t size, int stride_rgb) const;
 
+  const VideoFrame* GetCopyWithRotationApplied() const override;
+
  protected:
   void SetRotation(webrtc::VideoRotation rotation) { rotation_ = rotation; }
 
@@ -140,6 +142,10 @@
   int64_t elapsed_time_ns_;
   int64_t time_stamp_ns_;
   webrtc::VideoRotation rotation_;
+
+  // This is mutable as the calculation is expensive but once calculated, it
+  // remains const.
+  mutable rtc::scoped_ptr<VideoFrame> rotated_frame_;
 };
 
 }  // namespace cricket