diff options
author | guoweis@webrtc.org <guoweis@webrtc.org> | 2015-02-11 17:51:17 +0000 |
---|---|---|
committer | guoweis@webrtc.org <guoweis@webrtc.org> | 2015-02-11 17:51:46 +0000 |
commit | 20e8f227664a6747cea11e1fc1de4c018ebcc8e9 (patch) | |
tree | 3976839b08c017c7d1b5444d45b4f79315bc74d0 /webrtc | |
parent | 073dd7b423157020846872ca2398cc86d3ca9508 (diff) | |
download | webrtc-20e8f227664a6747cea11e1fc1de4c018ebcc8e9.tar.gz |
CVO capturer feature: allow unrotated frame flows through the capture pipeline.
split from https://webrtc-codereview.appspot.com/37029004/
This is based on clean up code change at https://webrtc-codereview.appspot.com/37129004
BUG=4145
R=perkj@webrtc.org, pthatcher@webrtc.org, stefan@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/39799004
Cr-Commit-Position: refs/heads/master@{#8337}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8337 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'webrtc')
-rw-r--r-- | webrtc/common_video/i420_video_frame.cc | 25 | ||||
-rw-r--r-- | webrtc/common_video/i420_video_frame_unittest.cc | 10 | ||||
-rw-r--r-- | webrtc/common_video/interface/texture_video_frame.h | 12 | ||||
-rw-r--r-- | webrtc/common_video/rotation.h | 2 | ||||
-rw-r--r-- | webrtc/common_video/texture_video_frame.cc | 16 | ||||
-rw-r--r-- | webrtc/modules/video_capture/include/mock/mock_video_capture.h | 2 | ||||
-rw-r--r-- | webrtc/modules/video_capture/include/video_capture.h | 9 | ||||
-rw-r--r-- | webrtc/modules/video_capture/video_capture_impl.cc | 59 | ||||
-rw-r--r-- | webrtc/modules/video_capture/video_capture_impl.h | 7 | ||||
-rw-r--r-- | webrtc/video_frame.h | 31 |
10 files changed, 154 insertions, 19 deletions
diff --git a/webrtc/common_video/i420_video_frame.cc b/webrtc/common_video/i420_video_frame.cc index fdc2bbc230..8dbbe3ad0e 100644 --- a/webrtc/common_video/i420_video_frame.cc +++ b/webrtc/common_video/i420_video_frame.cc @@ -21,7 +21,9 @@ I420VideoFrame::I420VideoFrame() height_(0), timestamp_(0), ntp_time_ms_(0), - render_time_ms_(0) {} + render_time_ms_(0), + rotation_(kVideoRotation_0) { +} I420VideoFrame::~I420VideoFrame() {} @@ -42,6 +44,7 @@ int I420VideoFrame::CreateEmptyFrame(int width, int height, timestamp_ = 0; ntp_time_ms_ = 0; render_time_ms_ = 0; + rotation_ = kVideoRotation_0; return 0; } @@ -50,6 +53,23 @@ int I420VideoFrame::CreateFrame(int size_y, const uint8_t* buffer_y, int size_v, const uint8_t* buffer_v, int width, int height, int stride_y, int stride_u, int stride_v) { + return CreateFrame(size_y, buffer_y, size_u, buffer_u, size_v, buffer_v, + width, height, stride_y, stride_u, stride_v, + kVideoRotation_0); +} + +int I420VideoFrame::CreateFrame(int size_y, + const uint8_t* buffer_y, + int size_u, + const uint8_t* buffer_u, + int size_v, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v, + VideoRotation rotation) { if (size_y < 1 || size_u < 1 || size_v < 1) return -1; if (CheckDimensions(width, height, stride_y, stride_u, stride_v) < 0) @@ -59,6 +79,7 @@ int I420VideoFrame::CreateFrame(int size_y, const uint8_t* buffer_y, v_plane_.Copy(size_v, stride_v, buffer_v); width_ = width; height_ = height; + rotation_ = rotation; return 0; } @@ -77,6 +98,7 @@ int I420VideoFrame::CopyFrame(const I420VideoFrame& videoFrame) { timestamp_ = videoFrame.timestamp_; ntp_time_ms_ = videoFrame.ntp_time_ms_; render_time_ms_ = videoFrame.render_time_ms_; + rotation_ = videoFrame.rotation_; return 0; } @@ -98,6 +120,7 @@ void I420VideoFrame::SwapFrame(I420VideoFrame* videoFrame) { std::swap(timestamp_, videoFrame->timestamp_); std::swap(ntp_time_ms_, videoFrame->ntp_time_ms_); std::swap(render_time_ms_, videoFrame->render_time_ms_); + std::swap(rotation_, videoFrame->rotation_); } uint8_t* I420VideoFrame::buffer(PlaneType type) { diff --git a/webrtc/common_video/i420_video_frame_unittest.cc b/webrtc/common_video/i420_video_frame_unittest.cc index ca01fd0cd5..6c3cb9c082 100644 --- a/webrtc/common_video/i420_video_frame_unittest.cc +++ b/webrtc/common_video/i420_video_frame_unittest.cc @@ -29,6 +29,7 @@ TEST(TestI420VideoFrame, InitialValues) { I420VideoFrame frame; // Invalid arguments - one call for each variable. EXPECT_TRUE(frame.IsZeroSize()); + EXPECT_EQ(kVideoRotation_0, frame.rotation()); EXPECT_EQ(-1, frame.CreateEmptyFrame(0, 10, 10, 14, 14)); EXPECT_EQ(-1, frame.CreateEmptyFrame(10, -1, 10, 90, 14)); EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 0, 14, 18)); @@ -100,22 +101,23 @@ TEST(TestI420VideoFrame, CopyFrame) { const int kSizeY = 225; const int kSizeU = 80; const int kSizeV = 80; + const VideoRotation kRotation = VideoFrameRotation_270; uint8_t buffer_y[kSizeY]; uint8_t buffer_u[kSizeU]; uint8_t buffer_v[kSizeV]; memset(buffer_y, 16, kSizeY); memset(buffer_u, 8, kSizeU); memset(buffer_v, 4, kSizeV); - frame2.CreateFrame(kSizeY, buffer_y, - kSizeU, buffer_u, - kSizeV, buffer_v, - width + 5, height + 5, stride_y + 5, stride_u, stride_v); + frame2.CreateFrame(kSizeY, buffer_y, kSizeU, buffer_u, kSizeV, buffer_v, + width + 5, height + 5, stride_y + 5, stride_u, stride_v, + kRotation); // Frame of smaller dimensions - allocated sizes should not vary. EXPECT_EQ(0, frame1.CopyFrame(frame2)); EXPECT_TRUE(EqualFramesExceptSize(frame1, frame2)); EXPECT_EQ(kSizeY, frame1.allocated_size(kYPlane)); EXPECT_EQ(kSizeU, frame1.allocated_size(kUPlane)); EXPECT_EQ(kSizeV, frame1.allocated_size(kVPlane)); + EXPECT_EQ(kRotation, frame1.rotation()); // Verify copy of all parameters. // Frame of larger dimensions - update allocated sizes. EXPECT_EQ(0, frame2.CopyFrame(frame1)); diff --git a/webrtc/common_video/interface/texture_video_frame.h b/webrtc/common_video/interface/texture_video_frame.h index 2c625ab57d..9a1fee0bc4 100644 --- a/webrtc/common_video/interface/texture_video_frame.h +++ b/webrtc/common_video/interface/texture_video_frame.h @@ -48,6 +48,18 @@ class TextureVideoFrame : public I420VideoFrame { int stride_y, int stride_u, int stride_v) OVERRIDE; + virtual int CreateFrame(int size_y, + const uint8_t* buffer_y, + int size_u, + const uint8_t* buffer_u, + int size_v, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v, + webrtc::VideoRotation rotation) OVERRIDE; virtual int CopyFrame(const I420VideoFrame& videoFrame) OVERRIDE; virtual I420VideoFrame* CloneFrame() const OVERRIDE; virtual void SwapFrame(I420VideoFrame* videoFrame) OVERRIDE; diff --git a/webrtc/common_video/rotation.h b/webrtc/common_video/rotation.h index 61825d83bf..46a9ecc5ea 100644 --- a/webrtc/common_video/rotation.h +++ b/webrtc/common_video/rotation.h @@ -11,8 +11,6 @@ #ifndef WEBRTC_COMMON_VIDEO_ROTATION_H_ #define WEBRTC_COMMON_VIDEO_ROTATION_H_ -#include "webrtc/base/common.h" - namespace webrtc { // enum for clockwise rotation. diff --git a/webrtc/common_video/texture_video_frame.cc b/webrtc/common_video/texture_video_frame.cc index f301d19c8e..ce6a040644 100644 --- a/webrtc/common_video/texture_video_frame.cc +++ b/webrtc/common_video/texture_video_frame.cc @@ -52,6 +52,22 @@ int TextureVideoFrame::CreateFrame(int size_y, return -1; } +int TextureVideoFrame::CreateFrame(int size_y, + const uint8_t* buffer_y, + int size_u, + const uint8_t* buffer_u, + int size_v, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v, + webrtc::VideoRotation rotation) { + assert(false); // Should not be called. + return -1; +} + int TextureVideoFrame::CopyFrame(const I420VideoFrame& videoFrame) { assert(false); // Should not be called. return -1; diff --git a/webrtc/modules/video_capture/include/mock/mock_video_capture.h b/webrtc/modules/video_capture/include/mock/mock_video_capture.h index 7938b01b90..9013820090 100644 --- a/webrtc/modules/video_capture/include/mock/mock_video_capture.h +++ b/webrtc/modules/video_capture/include/mock/mock_video_capture.h @@ -39,6 +39,8 @@ class MockVideoCaptureModule : public VideoCaptureModule { MOCK_METHOD1(SetCaptureDelay, void(int32_t delayMS)); MOCK_METHOD0(CaptureDelay, int32_t()); MOCK_METHOD1(SetCaptureRotation, int32_t(VideoCaptureRotation rotation)); + MOCK_METHOD1(SetApplyRotation, bool(bool)); + MOCK_METHOD0(GetApplyRotation, bool()); MOCK_METHOD1(GetEncodeInterface, VideoCaptureEncodeInterface*(const VideoCodec& codec)); MOCK_METHOD1(EnableFrameRateCallback, void(const bool enable)); diff --git a/webrtc/modules/video_capture/include/video_capture.h b/webrtc/modules/video_capture/include/video_capture.h index 50539ea06d..4f943177f6 100644 --- a/webrtc/modules/video_capture/include/video_capture.h +++ b/webrtc/modules/video_capture/include/video_capture.h @@ -135,6 +135,15 @@ class VideoCaptureModule: public RefCountedModule { // displayed correctly if rendered. virtual int32_t SetCaptureRotation(VideoCaptureRotation rotation) = 0; + // Tells the capture module whether to apply the pending rotation. By default, + // the rotation is applied and the generated frame is up right. When set to + // false, generated frames will carry the rotation information from + // SetCaptureRotation. Return value indicates whether this operation succeeds. + virtual bool SetApplyRotation(bool enable) = 0; + + // Return whether the rotation is applied or left pending. + virtual bool GetApplyRotation() = 0; + // Gets a pointer to an encode interface if the capture device supports the // requested type and size. NULL otherwise. virtual VideoCaptureEncodeInterface* GetEncodeInterface( diff --git a/webrtc/modules/video_capture/video_capture_impl.cc b/webrtc/modules/video_capture/video_capture_impl.cc index d7a6642044..ec88ecd6ee 100644 --- a/webrtc/modules/video_capture/video_capture_impl.cc +++ b/webrtc/modules/video_capture/video_capture_impl.cc @@ -24,6 +24,23 @@ namespace webrtc { + +// Converting the rotation mode from capturemodule's to I420VideoFrame's define. +VideoRotation ConvertRotation(VideoRotationMode rotation) { + switch (rotation) { + case kRotateNone: + return kVideoRotation_0; + case kRotate90: + return kVideoRotation_90; + case kRotate180: + return kVideoRotation_180; + case kRotate270: + return kVideoRotation_270; + } + assert(false); + return kVideoRotation_0; +} + namespace videocapturemodule { VideoCaptureModule* VideoCaptureImpl::Create( @@ -159,7 +176,8 @@ VideoCaptureImpl::VideoCaptureImpl(const int32_t id) last_capture_time_(0), delta_ntp_internal_ms_( Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() - - TickTime::MillisecondTimestamp()) { + TickTime::MillisecondTimestamp()), + apply_rotation_(true) { _requestedCapability.width = kDefaultWidth; _requestedCapability.height = kDefaultHeight; _requestedCapability.maxFPS = 30; @@ -278,11 +296,15 @@ int32_t VideoCaptureImpl::IncomingFrame( int stride_uv = (width + 1) / 2; int target_width = width; int target_height = height; - // Rotating resolution when for 90/270 degree rotations. - if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) { - target_width = abs(height); - target_height = width; + + if (apply_rotation_) { + // Rotating resolution when for 90/270 degree rotations. + if (_rotateFrame == kRotate90 || _rotateFrame == kRotate270) { + target_width = abs(height); + target_height = width; + } } + // TODO(mikhal): Update correct aligned stride values. //Calc16ByteAlignedStride(target_width, &stride_y, &stride_uv); // Setting absolute height (in case it was negative). @@ -298,19 +320,24 @@ int32_t VideoCaptureImpl::IncomingFrame( "happen due to bad parameters."; return -1; } - const int conversionResult = ConvertToI420(commonVideoType, - videoFrame, - 0, 0, // No cropping - width, height, - videoFrameLength, - _rotateFrame, - &_captureFrame); + const int conversionResult = ConvertToI420( + commonVideoType, videoFrame, 0, 0, // No cropping + width, height, videoFrameLength, + apply_rotation_ ? _rotateFrame : kRotateNone, + &_captureFrame); if (conversionResult < 0) { LOG(LS_ERROR) << "Failed to convert capture frame from type " << frameInfo.rawType << "to I420."; return -1; } + + if (!apply_rotation_) { + _captureFrame.set_rotation(ConvertRotation(_rotateFrame)); + } else { + _captureFrame.set_rotation(kVideoRotation_0); + } + DeliverCapturedFrame(_captureFrame, captureTime); } else // Encoded format @@ -364,6 +391,14 @@ void VideoCaptureImpl::EnableFrameRateCallback(const bool enable) { } } +bool VideoCaptureImpl::SetApplyRotation(bool enable) { + CriticalSectionScoped cs(&_apiCs); + CriticalSectionScoped cs2(&_callBackCs); + // The effect of this is the last caller wins. + apply_rotation_ = enable; + return true; +} + void VideoCaptureImpl::EnableNoPictureAlarm(const bool enable) { CriticalSectionScoped cs(&_apiCs); CriticalSectionScoped cs2(&_callBackCs); diff --git a/webrtc/modules/video_capture/video_capture_impl.h b/webrtc/modules/video_capture/video_capture_impl.h index 75fe7e5bae..aba15f2ac0 100644 --- a/webrtc/modules/video_capture/video_capture_impl.h +++ b/webrtc/modules/video_capture/video_capture_impl.h @@ -68,6 +68,10 @@ public: virtual void SetCaptureDelay(int32_t delayMS); virtual int32_t CaptureDelay(); virtual int32_t SetCaptureRotation(VideoCaptureRotation rotation); + virtual bool SetApplyRotation(bool enable); + virtual bool GetApplyRotation() { + return apply_rotation_; + } virtual void EnableFrameRateCallback(const bool enable); virtual void EnableNoPictureAlarm(const bool enable); @@ -140,6 +144,9 @@ private: // Delta used for translating between NTP and internal timestamps. const int64_t delta_ntp_internal_ms_; + + // Indicate whether rotation should be applied before delivered externally. + bool apply_rotation_; }; } // namespace videocapturemodule } // namespace webrtc diff --git a/webrtc/video_frame.h b/webrtc/video_frame.h index 95bcca0ee4..2dd7c6134e 100644 --- a/webrtc/video_frame.h +++ b/webrtc/video_frame.h @@ -18,6 +18,7 @@ // used). #include "webrtc/system_wrappers/interface/scoped_refptr.h" #include "webrtc/typedefs.h" +#include "webrtc/common_video/rotation.h" namespace webrtc { @@ -73,6 +74,20 @@ class I420VideoFrame { int stride_u, int stride_v); + // TODO(guoweis): remove the previous CreateFrame when chromium has this code. + virtual int CreateFrame(int size_y, + const uint8_t* buffer_y, + int size_u, + const uint8_t* buffer_u, + int size_v, + const uint8_t* buffer_v, + int width, + int height, + int stride_y, + int stride_u, + int stride_v, + VideoRotation rotation); + // Copy frame: If required size is bigger than allocated one, new buffers of // adequate size will be allocated. // Return value: 0 on success, -1 on error. @@ -122,6 +137,21 @@ class I420VideoFrame { // Get capture ntp time in miliseconds. virtual int64_t ntp_time_ms() const { return ntp_time_ms_; } + // Naming convention for Coordination of Video Orientation. Please see + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + // + // "pending rotation" or "pending" = a frame that has a VideoRotation > 0. + // + // "not pending" = a frame that has a VideoRotation == 0. + // + // "apply rotation" = modify a frame from being "pending" to being "not + // pending" rotation (a no-op for "unrotated"). + // + virtual VideoRotation rotation() const { return rotation_; } + virtual void set_rotation(VideoRotation rotation) { + rotation_ = rotation; + } + // Set render time in miliseconds. virtual void set_render_time_ms(int64_t render_time_ms) { render_time_ms_ = render_time_ms; @@ -165,6 +195,7 @@ class I420VideoFrame { uint32_t timestamp_; int64_t ntp_time_ms_; int64_t render_time_ms_; + VideoRotation rotation_; }; enum VideoFrameType { |