| Index: media/base/video_util_unittest.cc
|
| diff --git a/media/base/video_util_unittest.cc b/media/base/video_util_unittest.cc
|
| index 94fe7e9cb07d00b0b1c23b8380495c1383a2e093..26ca2c027bc74c2c2fd729acc190e1036f12b8b7 100644
|
| --- a/media/base/video_util_unittest.cc
|
| +++ b/media/base/video_util_unittest.cc
|
| @@ -12,6 +12,134 @@
|
| #include "media/base/video_frame.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| +namespace {
|
| +
|
| +// Initialize a plane's visible rect with value circularly from 0 to 255.
|
| +void FillPlaneWithPattern(uint8_t* data,
|
| + int stride,
|
| + const gfx::Size& visible_size) {
|
| + DCHECK(data && visible_size.width() <= stride);
|
| +
|
| + uint32_t val = 0;
|
| + uint8_t* src = data;
|
| + for (int i = 0; i < visible_size.height(); ++i, src += stride) {
|
| + for (int j = 0; j < visible_size.width(); ++j, ++val)
|
| + src[j] = val & 0xff;
|
| + }
|
| +}
|
| +
|
| +// Create a VideoFrame and initialize the visible rect using
|
| +// |FillPlaneWithPattern()|. For testing purpose, the VideoFrame should be
|
| +// filled with varying values, which is different from
|
| +// |VideoFrame::CreateColorFrame()| where the entrire VideoFrame is filled
|
| +// with a given color.
|
| +scoped_refptr<media::VideoFrame> CreateFrameWithPatternFilled(
|
| + media::VideoPixelFormat format,
|
| + const gfx::Size& coded_size,
|
| + const gfx::Rect& visible_rect,
|
| + const gfx::Size& natural_size,
|
| + base::TimeDelta timestamp) {
|
| + scoped_refptr<media::VideoFrame> frame(media::VideoFrame::CreateFrame(
|
| + format, coded_size, visible_rect, natural_size, timestamp));
|
| +
|
| + FillPlaneWithPattern(frame->data(media::VideoFrame::kYPlane),
|
| + frame->stride(media::VideoFrame::kYPlane),
|
| + frame->visible_rect().size());
|
| + FillPlaneWithPattern(
|
| + frame->data(media::VideoFrame::kUPlane),
|
| + frame->stride(media::VideoFrame::kUPlane),
|
| + media::VideoFrame::PlaneSize(format, media::VideoFrame::kUPlane,
|
| + frame->visible_rect().size()));
|
| + FillPlaneWithPattern(
|
| + frame->data(media::VideoFrame::kVPlane),
|
| + frame->stride(media::VideoFrame::kVPlane),
|
| + media::VideoFrame::PlaneSize(format, media::VideoFrame::kVPlane,
|
| + frame->visible_rect().size()));
|
| + return frame;
|
| +}
|
| +
|
| +// Helper function used to verify the data in the coded region after copying the
|
| +// visible region and padding the remaining area.
|
| +bool VerifyPlanCopyWithPadding(const uint8_t* src,
|
| + size_t src_stride,
|
| + // Size of visible region.
|
| + const gfx::Size& src_size,
|
| + const uint8_t* dst,
|
| + size_t dst_stride,
|
| + // Coded size of |dst|.
|
| + const gfx::Size& dst_size) {
|
| + if (!src || !dst)
|
| + return false;
|
| +
|
| + const size_t src_width = src_size.width();
|
| + const size_t src_height = src_size.height();
|
| + const size_t dst_width = dst_size.width();
|
| + const size_t dst_height = dst_size.height();
|
| + if (src_width > dst_width || src_width > src_stride ||
|
| + src_height > dst_height || src_size.IsEmpty() || dst_size.IsEmpty())
|
| + return false;
|
| +
|
| + const uint8_t *src_ptr = src, *dst_ptr = dst;
|
| + for (size_t i = 0; i < src_height;
|
| + ++i, src_ptr += src_stride, dst_ptr += dst_stride) {
|
| + if (memcmp(src_ptr, dst_ptr, src_width))
|
| + return false;
|
| + for (size_t j = src_width; j < dst_width; ++j) {
|
| + if (src_ptr[src_width - 1] != dst_ptr[j])
|
| + return false;
|
| + }
|
| + }
|
| + if (src_height < dst_height) {
|
| + src_ptr = dst + (src_height - 1) * dst_stride;
|
| + if (memcmp(src_ptr, dst_ptr, dst_width))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool VerifyCopyWithPadding(const media::VideoFrame& src_frame,
|
| + const media::VideoFrame& dst_frame) {
|
| + if (!src_frame.IsMappable() || !dst_frame.IsMappable() ||
|
| + src_frame.visible_rect().size() != dst_frame.visible_rect().size())
|
| + return false;
|
| +
|
| + if (!VerifyPlanCopyWithPadding(
|
| + src_frame.visible_data(media::VideoFrame::kYPlane),
|
| + src_frame.stride(media::VideoFrame::kYPlane),
|
| + src_frame.visible_rect().size(),
|
| + dst_frame.data(media::VideoFrame::kYPlane),
|
| + dst_frame.stride(media::VideoFrame::kYPlane), dst_frame.coded_size()))
|
| + return false;
|
| + if (!VerifyPlanCopyWithPadding(
|
| + src_frame.visible_data(media::VideoFrame::kUPlane),
|
| + src_frame.stride(media::VideoFrame::kUPlane),
|
| + media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
|
| + media::VideoFrame::kUPlane,
|
| + src_frame.visible_rect().size()),
|
| + dst_frame.data(media::VideoFrame::kUPlane),
|
| + dst_frame.stride(media::VideoFrame::kUPlane),
|
| + media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
|
| + media::VideoFrame::kUPlane,
|
| + dst_frame.coded_size())))
|
| + return false;
|
| + if (!VerifyPlanCopyWithPadding(
|
| + src_frame.visible_data(media::VideoFrame::kVPlane),
|
| + src_frame.stride(media::VideoFrame::kVPlane),
|
| + media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
|
| + media::VideoFrame::kVPlane,
|
| + src_frame.visible_rect().size()),
|
| + dst_frame.data(media::VideoFrame::kVPlane),
|
| + dst_frame.stride(media::VideoFrame::kVPlane),
|
| + media::VideoFrame::PlaneSize(media::PIXEL_FORMAT_I420,
|
| + media::VideoFrame::kVPlane,
|
| + dst_frame.coded_size())))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace media {
|
|
|
| class VideoUtilTest : public testing::Test {
|
| @@ -362,4 +490,36 @@ TEST_F(VideoUtilTest, LetterboxYUV) {
|
| }
|
| }
|
|
|
| +TEST_F(VideoUtilTest, I420CopyWithPadding) {
|
| + gfx::Size visible_size(40, 30);
|
| + scoped_refptr<VideoFrame> src_frame = CreateFrameWithPatternFilled(
|
| + PIXEL_FORMAT_I420, visible_size, gfx::Rect(visible_size), visible_size,
|
| + base::TimeDelta());
|
| + // Expect to return false when copying to an empty buffer.
|
| + EXPECT_FALSE(I420CopyWithPadding(*src_frame, nullptr));
|
| +
|
| + scoped_refptr<VideoFrame> dst_frame = CreateFrameWithPatternFilled(
|
| + PIXEL_FORMAT_I420, visible_size, gfx::Rect(visible_size), visible_size,
|
| + base::TimeDelta());
|
| + EXPECT_TRUE(I420CopyWithPadding(*src_frame, dst_frame.get()));
|
| + EXPECT_TRUE(VerifyCopyWithPadding(*src_frame, *dst_frame));
|
| +
|
| + gfx::Size coded_size(60, 40);
|
| + dst_frame = CreateFrameWithPatternFilled(PIXEL_FORMAT_I420, coded_size,
|
| + gfx::Rect(visible_size), coded_size,
|
| + base::TimeDelta());
|
| + EXPECT_TRUE(I420CopyWithPadding(*src_frame, dst_frame.get()));
|
| + EXPECT_TRUE(VerifyCopyWithPadding(*src_frame, *dst_frame));
|
| +
|
| + gfx::Size odd_size(39, 31);
|
| + src_frame = CreateFrameWithPatternFilled(PIXEL_FORMAT_I420, odd_size,
|
| + gfx::Rect(odd_size), odd_size,
|
| + base::TimeDelta());
|
| + dst_frame = CreateFrameWithPatternFilled(PIXEL_FORMAT_I420, coded_size,
|
| + gfx::Rect(odd_size), coded_size,
|
| + base::TimeDelta());
|
| + EXPECT_TRUE(I420CopyWithPadding(*src_frame, dst_frame.get()));
|
| + EXPECT_TRUE(VerifyCopyWithPadding(*src_frame, *dst_frame));
|
| +}
|
| +
|
| } // namespace media
|
|
|