Refactoring videoFrame - I420VideoFrame will eventually replace VideoFrame which is currently defined in modules_common_types. Main changes: the new class allows per plane pointers, stride and uses scoped_array.

BUG=

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2781 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org 2012-09-18 16:14:26 +00:00
parent 2e7c22da7d
commit 043ed9ecbd
7 changed files with 714 additions and 1 deletions

View File

@ -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
],
}
}

View File

@ -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 <algorithm> // 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

View File

@ -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 <math.h>
#include <string.h>
#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

View File

@ -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

76
src/common_video/plane.cc Normal file
View File

@ -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 <algorithm> // swap
#include <cstring> // 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

66
src/common_video/plane.h Normal file
View File

@ -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<uint8_t> buffer_;
int allocated_size_;
int plane_size_;
int stride_;
}; // Plane
} // namespace webrtc
#endif // COMMON_VIDEO_PLANE_H

View File

@ -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 <math.h>
#include <string.h>
#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