diff --git a/src/common_video/common_video.gyp b/src/common_video/common_video.gyp index fae08be4c..67db5d120 100644 --- a/src/common_video/common_video.gyp +++ b/src/common_video/common_video.gyp @@ -50,6 +50,8 @@ }], ], 'sources': [ + 'interface/i420_video_frame.h', + 'i420_video_frame.cc', 'jpeg/include/jpeg.h', 'jpeg/data_manager.cc', 'jpeg/data_manager.h', @@ -58,6 +60,8 @@ 'libyuv/include/scaler.h', 'libyuv/webrtc_libyuv.cc', 'libyuv/scaler.cc', + 'plane.h', + 'plane.cc', ], }, ], # targets @@ -74,12 +78,14 @@ '<(webrtc_root)/test/test.gyp:test_support_main', ], 'sources': [ + 'i420_video_frame_unittest.cc', 'jpeg/jpeg_unittest.cc', 'libyuv/libyuv_unittest.cc', 'libyuv/scaler_unittest.cc', + 'plane_unittest.cc', ], }, ], # targets }], # include_tests ], -} +} \ No newline at end of file diff --git a/src/common_video/i420_video_frame.cc b/src/common_video/i420_video_frame.cc new file mode 100644 index 000000000..89b2f920f --- /dev/null +++ b/src/common_video/i420_video_frame.cc @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "common_video/interface/i420_video_frame.h" + +#include // swap + +namespace webrtc { + +I420VideoFrame::I420VideoFrame() + : width_(0), + height_(0), + timestamp_(0), + render_time_ms_(0) {} + +I420VideoFrame::~I420VideoFrame() {} + +int I420VideoFrame::CreateEmptyFrame(int width, int height, + int stride_y, int stride_u, int stride_v) { + if (CheckDimensions(width, height, stride_y, stride_u, stride_v) < 0) + return -1; + int size_y = stride_y * height; + int size_u = (stride_u + 1) * (height + 1) / 4; + int size_v = (stride_v + 1) * (height + 1) / 4; + width_ = width; + height_ = height; + y_plane_.CreateEmptyPlane(size_y, stride_y, size_y); + u_plane_.CreateEmptyPlane(size_u, stride_u, size_u); + v_plane_.CreateEmptyPlane(size_v, stride_v, size_v); + return 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) { + if (size_y < 1 || size_u < 1 || size_v < 1) + return -1; + if (CheckDimensions(width, height, stride_y, stride_u, stride_v) < 0) + return -1; + y_plane_.Copy(size_y, stride_y, buffer_y); + u_plane_.Copy(size_u, stride_u, buffer_u); + v_plane_.Copy(size_v, stride_v, buffer_v); + width_ = width; + height_ = height; + return 0; +} + +int I420VideoFrame::CopyFrame(const I420VideoFrame& videoFrame) { + int ret = CreateFrame(videoFrame.size(kYPlane), *videoFrame.buffer(kYPlane), + videoFrame.size(kUPlane), *videoFrame.buffer(kUPlane), + videoFrame.size(kVPlane), *videoFrame.buffer(kVPlane), + videoFrame.width_, videoFrame.height_, + videoFrame.stride(kYPlane), videoFrame.stride(kUPlane), + videoFrame.stride(kVPlane)); + if (ret < 0) + return ret; + timestamp_ = videoFrame.timestamp_; + render_time_ms_ = videoFrame.render_time_ms_; + return 0; +} + +void I420VideoFrame::SwapFrame(I420VideoFrame* videoFrame) { + y_plane_.Swap(videoFrame->y_plane_); + u_plane_.Swap(videoFrame->u_plane_); + v_plane_.Swap(videoFrame->v_plane_); + std::swap(width_, videoFrame->width_); + std::swap(height_, videoFrame->height_); + std::swap(timestamp_, videoFrame->timestamp_); + std::swap(render_time_ms_, videoFrame->render_time_ms_); +} + +const uint8_t* I420VideoFrame::buffer(PlaneType type) const { + const Plane* plane_ptr = GetPlane(type); + if (plane_ptr) + return plane_ptr->buffer(); + return NULL; +} + +int I420VideoFrame::size(PlaneType type) const { + const Plane* plane_ptr = GetPlane(type); + if (plane_ptr) + return plane_ptr->allocated_size(); + return -1; +} + +int I420VideoFrame::stride(PlaneType type) const { + const Plane* plane_ptr = GetPlane(type); + if (plane_ptr) + return plane_ptr->stride(); + return -1; +} + +int I420VideoFrame::set_width(int width) { + if (CheckDimensions(width, height_, + y_plane_.stride(), u_plane_.stride(), + v_plane_.stride()) < 0) + return -1; + width_ = width; + return 0; +} + +int I420VideoFrame::set_height(int height) { + if (CheckDimensions(width_, height, + y_plane_.stride(), u_plane_.stride(), + v_plane_.stride()) < 0) + return -1; + height_ = height; + return 0; +} + +int I420VideoFrame::CheckDimensions(int width, int height, + int stride_y, int stride_u, int stride_v) { + int half_width = (width + 1) / 2; + if (width < 1 || height < 1 || + stride_y < width || stride_u < half_width || stride_v < half_width) + return -1; + return 0; +} + +const Plane* I420VideoFrame::GetPlane(PlaneType type) const { + switch (type) { + case kYPlane : + return &y_plane_; + case kUPlane : + return &u_plane_; + case kVPlane : + return &v_plane_; + default: + assert(false); + } + return NULL; +} + + +} // namespace webrtc diff --git a/src/common_video/i420_video_frame_unittest.cc b/src/common_video/i420_video_frame_unittest.cc new file mode 100644 index 000000000..8280d1307 --- /dev/null +++ b/src/common_video/i420_video_frame_unittest.cc @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#include "common_video/interface/i420_video_frame.h" +#include "gtest/gtest.h" +#include "system_wrappers/interface/scoped_ptr.h" + +namespace webrtc { + +bool EqualFrames(const I420VideoFrame& videoFrame1, + const I420VideoFrame& videoFrame2); +bool EqualFramesExceptSize(const I420VideoFrame& frame1, + const I420VideoFrame& frame2); + +TEST(TestI420VideoFrame, InitialValues) { + I420VideoFrame frame; + // Invalid arguments - one call for each variable. + 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)); + EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 10, -2, 13)); + EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 10, 14, 0)); + EXPECT_EQ(0, frame.CreateEmptyFrame(10, 10, 10, 14, 90)); +} + +TEST(TestI420VideoFrame, WidthHeightValues) { + I420VideoFrame frame; + const int valid_value = 10; + const int invalid_value = -1; + EXPECT_EQ(0, frame.CreateEmptyFrame(10, 10, 10, 14, 90)); + EXPECT_EQ(valid_value, frame.width()); + EXPECT_EQ(invalid_value, frame.set_width(invalid_value)); + EXPECT_EQ(valid_value, frame.height()); + EXPECT_EQ(valid_value, frame.height()); + EXPECT_EQ(invalid_value, frame.set_height(0)); + EXPECT_EQ(valid_value, frame.height()); + frame.set_timestamp(100u); + EXPECT_EQ(100u, frame.timestamp()); + frame.set_render_time_ms(100); + EXPECT_EQ(100, frame.render_time_ms()); +} + +TEST(TestI420VideoFrame, SizeAllocation) { + I420VideoFrame frame; + EXPECT_EQ(0, frame. CreateEmptyFrame(10, 10, 12, 14, 220)); + int width = frame.width(); + int height = frame.height(); + int stride_y = frame.stride(kYPlane); + int stride_u = frame.stride(kUPlane); + int stride_v = frame.stride(kVPlane); + // Verify that allocated size was computed correctly. + EXPECT_EQ(width * stride_y, frame.size(kYPlane)); + EXPECT_EQ((height + 1) * (stride_u + 1) / 4, frame.size(kUPlane)); + EXPECT_EQ((height + 1) * (stride_v + 1) / 4, frame.size(kVPlane)); +} + +TEST(TestI420VideoFrame, CopyFrame) { + I420VideoFrame frame1, frame2; + uint32_t timestamp = 1; + int64_t render_time_ms = 1; + int stride_y = 15; + int stride_u = 10; + int stride_v = 10; + int width = 15; + int height = 15; + // Copy frame. + EXPECT_EQ(0, frame1.CreateEmptyFrame(width, height, + stride_y, stride_u, stride_v)); + frame1.set_timestamp(timestamp); + frame1.set_render_time_ms(render_time_ms); + int size_y = frame1.size(kYPlane); + int size_u = frame1.size(kUPlane); + int size_v = frame1.size(kVPlane); + EXPECT_EQ(0, frame2.CreateEmptyFrame(width + 5, height + 5, + stride_y + 5, stride_u, stride_v)); + // Frame of smaller dimensions - allocated sizes should not vary. + EXPECT_EQ(0, frame2.CopyFrame(frame1)); + EXPECT_TRUE(EqualFramesExceptSize(frame1, frame2)); + EXPECT_EQ(size_y, frame1.size(kYPlane)); + EXPECT_EQ(size_u, frame1.size(kUPlane)); + EXPECT_EQ(size_v, frame1.size(kVPlane)); + // Verify copy of all parameters. + // Frame of larger dimensions - update allocated sizes. + EXPECT_EQ(0, frame1.CopyFrame(frame2)); + EXPECT_TRUE(EqualFrames(frame1, frame2)); +} + +TEST(TestI420VideoFrame, CopyBuffer) { + I420VideoFrame frame1, frame2; + int width = 15; + int height = 15; + int stride_y = 15; + int stride_u = 10; + int stride_v = 10; + const int kSizeY = 225; + const int kSizeUv = 37; // (stride_u + 1) * (height + 1) / 4; + EXPECT_EQ(0, frame2.CreateEmptyFrame(width + 5, height + 5, + stride_y + 5, stride_u, stride_v)); + EXPECT_EQ(0, frame2.CreateEmptyFrame(width, height, + stride_y, stride_u, stride_v)); + uint8_t buffer_y[kSizeY]; + uint8_t buffer_u[kSizeUv]; + uint8_t buffer_v[kSizeUv]; + memset(buffer_y, 16, kSizeY); + memset(buffer_u, 8, kSizeUv); + memset(buffer_v, 4, kSizeUv); + frame2.CreateFrame(kSizeY, *buffer_y, + kSizeUv, *buffer_u, + kSizeUv, *buffer_v, + width, height, stride_y, stride_u, stride_v); + // Copy memory (at least allocated size). + EXPECT_EQ(memcmp(buffer_y, frame2.buffer(kYPlane), kSizeY), 0); + EXPECT_EQ(memcmp(buffer_u, frame2.buffer(kUPlane), kSizeUv), 0); + EXPECT_EQ(memcmp(buffer_v, frame2.buffer(kVPlane), kSizeUv), 0); + // Comapre size. + EXPECT_LE(kSizeY, frame2.size(kYPlane)); + EXPECT_LE(kSizeUv, frame2.size(kUPlane)); + EXPECT_LE(kSizeUv, frame2.size(kVPlane)); +} + +TEST(TestI420VideoFrame, FrameSwap) { + I420VideoFrame frame1, frame2; + uint32_t timestamp1 = 1; + int64_t render_time_ms1 = 1; + int stride_y1 = 15; + int stride_u1 = 10; + int stride_v1 = 10; + int width1 = 15; + int height1 = 15; + const int kSizeY1 = 225; + const int kSizeU1 = 37; + const int kSizeV1 = 37; + uint32_t timestamp2 = 2; + int64_t render_time_ms2 = 4; + int stride_y2 = 30; + int stride_u2 = 20; + int stride_v2 = 20; + int width2 = 30; + int height2 = 30; + const int kSizeY2 = 900; + const int kSizeU2 = 150; + const int kSizeV2 = 150; + // Initialize frame1 values. + EXPECT_EQ(0, frame1.CreateEmptyFrame(width1, height1, + stride_y1, stride_u1, stride_v1)); + frame1.set_timestamp(timestamp1); + frame1.set_render_time_ms(render_time_ms1); + // Set memory for frame1. + uint8_t buffer_y1[kSizeY1]; + uint8_t buffer_u1[kSizeU1]; + uint8_t buffer_v1[kSizeV1]; + memset(buffer_y1, 2, kSizeY1); + memset(buffer_u1, 4, kSizeU1); + memset(buffer_v1, 8, kSizeV1); + frame1.CreateFrame(kSizeY1, *buffer_y1, + kSizeU1, *buffer_u1, + kSizeV1, *buffer_v1, + width1, height1, stride_y1, stride_u1, stride_v1); + // Initialize frame2 values. + EXPECT_EQ(0, frame2.CreateEmptyFrame(width2, height2, + stride_y2, stride_u2, stride_v2)); + frame2.set_timestamp(timestamp2); + frame2.set_render_time_ms(render_time_ms2); + // Set memory for frame2. + uint8_t buffer_y2[kSizeY2]; + uint8_t buffer_u2[kSizeU2]; + uint8_t buffer_v2[kSizeV2]; + memset(buffer_y2, 0, kSizeY2); + memset(buffer_u2, 1, kSizeU2); + memset(buffer_v2, 2, kSizeV2); + frame2.CreateFrame(kSizeY2, *buffer_y2, + kSizeU2, *buffer_u2, + kSizeV2, *buffer_v2, + width2, height2, stride_y2, stride_u2, stride_v2); + // Copy frames for subsequent comparison. + I420VideoFrame frame1_copy, frame2_copy; + frame1_copy.CopyFrame(frame1); + frame2_copy.CopyFrame(frame2); + // Swap frames. + frame1.SwapFrame(&frame2); + // Verify swap. + EXPECT_TRUE(EqualFrames(frame1_copy, frame2)); + EXPECT_TRUE(EqualFrames(frame2_copy, frame1)); +} + +bool EqualFrames(const I420VideoFrame& frame1, + const I420VideoFrame& frame2) { + if (!EqualFramesExceptSize(frame1, frame2)) + return false; + // Compare allocated memory size. + bool ret = true; + ret |= (frame1.size(kYPlane) == frame2.size(kYPlane)); + ret |= (frame1.size(kUPlane) == frame2.size(kUPlane)); + ret |= (frame1.size(kVPlane) == frame2.size(kVPlane)); + return ret; +} + +bool EqualFramesExceptSize(const I420VideoFrame& frame1, + const I420VideoFrame& frame2) { + bool ret = true; + ret |= (frame1.width() == frame2.width()); + ret |= (frame1.height() == frame2.height()); + ret |= (frame1.stride(kYPlane) == frame2.stride(kYPlane)); + ret |= (frame1.stride(kUPlane) == frame2.stride(kUPlane)); + ret |= (frame1.stride(kVPlane) == frame2.stride(kVPlane)); + ret |= (frame1.timestamp() == frame2.timestamp()); + ret |= (frame1.render_time_ms() == frame2.render_time_ms()); + // Memory should be the equal for the minimum of the two sizes. + int size_y = std::min(frame1.size(kYPlane), frame2.size(kYPlane)); + int size_u = std::min(frame1.size(kUPlane), frame1.size(kUPlane)); + int size_v = std::min(frame1.size(kVPlane), frame1.size(kVPlane)); + ret |= memcmp(frame1.buffer(kYPlane), frame2.buffer(kYPlane), size_y); + ret |= memcmp(frame1.buffer(kUPlane), frame2.buffer(kYPlane), size_u); + ret |= memcmp(frame1.buffer(kVPlane), frame2.buffer(kYPlane), size_v); + return ret; +} + +} // namespace webrtc diff --git a/src/common_video/interface/i420_video_frame.h b/src/common_video/interface/i420_video_frame.h new file mode 100644 index 000000000..e7fc61958 --- /dev/null +++ b/src/common_video/interface/i420_video_frame.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef COMMON_VIDEO_INTERFACE_I420_VIDEO_FRAME_H +#define COMMON_VIDEO_INTERFACE_I420_VIDEO_FRAME_H + +// I420VideoFrame class +// +// Storing and handling of YUV (I420) video frames. + +#include "common_video/plane.h" +#include "typedefs.h" //NOLINT + +namespace webrtc { + +enum PlaneType { + kYPlane = 0, + kUPlane = 1, + kVPlane = 2 +}; + +class I420VideoFrame { + public: + I420VideoFrame(); + ~I420VideoFrame(); + + // CreateEmptyFrame: Sets frame dimensions and allocates buffers based + // on set dimensions - height and plane stride. + // If required size is bigger than the allocated one, new buffers of adequate + // size will be allocated. + // Return value: 0 on success ,-1 on error. + int CreateEmptyFrame(int width, int height, + int stride_y, int stride_u, int stride_v); + + // CreateFrame: Sets the frame's members and buffers. If required size is + // bigger than allocated one, new buffers of adequate size will be allocated. + // Return value: 0 on success ,-1 on error. + 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); + + // 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. + int CopyFrame(const I420VideoFrame& videoFrame); + + // Swap Frame. + void SwapFrame(I420VideoFrame* videoFrame); + + // Get pointer to buffer per plane. + const uint8_t* buffer(PlaneType type) const; + + // Get allocated size per plane. + int size(PlaneType type) const; + + // Get allocated stride per plane. + int stride(PlaneType type) const; + + // Set frame width. + int set_width(int width); + + // Set frame height. + int set_height(int height); + + // Get frame width. + int width() const {return width_;} + + // Get frame height. + int height() const {return height_;} + + // Set frame timestamp (90kHz). + void set_timestamp(const uint32_t timestamp) {timestamp_ = timestamp;} + + // Get frame timestamp (90kHz). + uint32_t timestamp() const {return timestamp_;} + + // Set render time in miliseconds. + void set_render_time_ms(int64_t render_time_ms) {render_time_ms_ = + render_time_ms;} + + // Get render time in miliseconds. + int64_t render_time_ms() const {return render_time_ms_;} + + private: + // Verifies legality of parameters. + // Return value: 0 on success ,-1 on error. + int CheckDimensions(int width, int height, + int stride_y, int stride_u, int stride_v); + // Get the pointer to a specific plane. + const Plane* GetPlane(PlaneType type) const; + + Plane y_plane_; + Plane u_plane_; + Plane v_plane_; + int width_; + int height_; + uint32_t timestamp_; + int64_t render_time_ms_; +}; // I420VideoFrame + +} // namespace webrtc + +#endif // COMMON_VIDEO_INTERFACE_I420_VIDEO_FRAME_H + diff --git a/src/common_video/plane.cc b/src/common_video/plane.cc new file mode 100644 index 000000000..21fa87c4e --- /dev/null +++ b/src/common_video/plane.cc @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "common_video/plane.h" + +#include // swap +#include // memcpy + +namespace webrtc { + +Plane::Plane() + : buffer_(NULL), + allocated_size_(0), + plane_size_(0), + stride_(0) {} + +Plane::~Plane() {} + +int Plane::CreateEmptyPlane(int allocated_size, int stride, int plane_size) { + if (allocated_size < 1 || stride < 1 || plane_size < 1) + return -1; + stride_ = stride; + plane_size_ = plane_size; + MaybeResize(allocated_size); + return 0; +} + +int Plane::MaybeResize(int new_size) { + if (new_size <= 0) + return -1; + if (new_size <= allocated_size_) + return 0; + uint8_t* new_buffer = new uint8_t[new_size]; + if (buffer_.get()) { + memcpy(new_buffer, buffer_.get(), plane_size_); + buffer_.reset(); + } + buffer_.reset(new_buffer); + allocated_size_ = new_size; + return 0; +} + +int Plane::Copy(const Plane& plane) { + if (MaybeResize(plane.allocated_size_) < 0) + return -1; + if (plane.buffer_.get()) + memcpy(buffer_.get(), plane.buffer_.get(), plane.plane_size_); + stride_ = plane.stride_; + plane_size_ = plane.plane_size_; + return 0; +} + +int Plane::Copy(int size, int stride, const uint8_t& buffer) { + if (MaybeResize(size) < 0) + return -1; + memcpy(buffer_.get(), &buffer, size); + plane_size_ = size; + stride_ = stride; + return 0; +} + +void Plane::Swap(Plane& plane) { + std::swap(stride_, plane.stride_); + std::swap(allocated_size_, plane.allocated_size_); + std::swap(plane_size_, plane.plane_size_); + buffer_.swap(plane.buffer_); +} + +} // namespace webrtc diff --git a/src/common_video/plane.h b/src/common_video/plane.h new file mode 100644 index 000000000..3a3f97e45 --- /dev/null +++ b/src/common_video/plane.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef COMMON_VIDEO_PLANE_H +#define COMMON_VIDEO_PLANE_H + +#include "system_wrappers/interface/scoped_ptr.h" +#include "typedefs.h" //NOLINT + +namespace webrtc { + +// Helper class for I420VideoFrame: Store plane data and perform basic plane +// operations. +class Plane { + public: + Plane(); + ~Plane(); + // CreateEmptyPlane - set allocated size, actual plane size and stride: + // If current size is smaller than current size, then a buffer of sufficient + // size will be allocated. + // Return value: 0 on success ,-1 on error. + int CreateEmptyPlane(int allocated_size, int stride, int plane_size); + + // Copy the entire plane data. + // Return value: 0 on success ,-1 on error. + int Copy(const Plane& plane); + + // Copy buffer: If current size is smaller + // than current size, then a buffer of sufficient size will be allocated. + // Return value: 0 on success ,-1 on error. + int Copy(int size, int stride, const uint8_t& buffer); + + // Swap plane data. + void Swap(Plane& plane); + + // Get allocated size. + int allocated_size() const {return allocated_size_;} + + // Get stride value. + int stride() const {return stride_;} + + // Return data pointer. + const uint8_t* buffer() const {return buffer_.get();} + + private: + // Resize when needed: If current allocated size is less than new_size, buffer + // will be updated. Old data will be copied to new buffer. + // Return value: 0 on success ,-1 on error. + int MaybeResize(int new_size); + + scoped_array buffer_; + int allocated_size_; + int plane_size_; + int stride_; +}; // Plane + +} // namespace webrtc + +#endif // COMMON_VIDEO_PLANE_H diff --git a/src/common_video/plane_unittest.cc b/src/common_video/plane_unittest.cc new file mode 100644 index 000000000..15d2a7cf8 --- /dev/null +++ b/src/common_video/plane_unittest.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "common_video/plane.h" + +#include +#include + +#include "gtest/gtest.h" + +namespace webrtc { + +TEST(TestPlane, CreateEmptyPlaneialValues) { + Plane plane; + int size, stride; + EXPECT_EQ(0, plane.allocated_size()); + EXPECT_EQ(0, plane.stride()); + size = 0; + stride = 20; + EXPECT_EQ(-1, plane.CreateEmptyPlane(size, stride, 1)); + EXPECT_EQ(-1, plane.CreateEmptyPlane(10, stride, size)); + size = 20; + stride = 0; + EXPECT_EQ(-1, plane.CreateEmptyPlane(size, stride, size)); + stride = 20; + EXPECT_EQ(0, plane.CreateEmptyPlane(size, stride, size)); + EXPECT_EQ(size, plane.allocated_size()); + EXPECT_EQ(stride, plane.stride()); +} + +TEST(TestPlane, PlaneCopy) { + Plane plane1, plane2; + // Copy entire plane. + plane1.CreateEmptyPlane(100, 10, 100); + int size1 = plane1.allocated_size(); + int size2 = 30; + plane2.CreateEmptyPlane(50, 15, size2); + int stride1 = plane1.stride(); + int stride2 = plane2.stride(); + plane1.Copy(plane2); + // Smaller size - keep buffer size as is. + EXPECT_EQ(size1, plane1.allocated_size()); + EXPECT_EQ(stride2, plane1.stride()); + plane2.Copy(plane1); + // Verify increment of allocated size. + EXPECT_EQ(plane1.allocated_size(), plane2.allocated_size()); + EXPECT_EQ(stride2, plane2.stride()); + // Copy buffer. + uint8_t buffer1[100]; + size1 = 80; + memset(&buffer1, 0, size1); + plane2.Copy(size1, stride1, *buffer1); + EXPECT_GE(plane2.allocated_size(), size1); + EXPECT_EQ(0, memcmp(buffer1, plane2.buffer(), size1)); +} + +TEST(TestPlane, PlaneSwap) { + Plane plane1, plane2; + int size1, size2, stride1, stride2; + plane1.CreateEmptyPlane(100, 10, 100); + plane2.CreateEmptyPlane(50, 15, 50); + size1 = plane1.allocated_size(); + stride1 = plane1.stride(); + stride2 = plane2.stride(); + size2 = plane2.allocated_size(); + plane1.Swap(plane2); + EXPECT_EQ(size1, plane2.allocated_size()); + EXPECT_EQ(size2, plane1.allocated_size()); + EXPECT_EQ(stride2, plane1.stride()); + EXPECT_EQ(stride1, plane2.stride()); +} + +} // namespace webrtc