Chromium Code Reviews| 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..540555c8b3fac7ed5c81fc1988915e326257f267 100644 |
| --- a/media/base/video_util_unittest.cc |
| +++ b/media/base/video_util_unittest.cc |
| @@ -12,6 +12,128 @@ |
| #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 InitializePlane(uint8_t* data, int stride, const gfx::Size& visible_size) { |
|
xhwang
2016/05/10 19:04:04
"Initialize" is too generic. How about something l
xjz
2016/05/10 21:08:44
Done.
|
| + if (!data || visible_size.width() > stride) |
|
xhwang
2016/05/10 19:04:04
DCHECK here. Otherwise we could silently return.
xjz
2016/05/10 21:08:44
Done.
|
| + return; |
| + |
| + 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 |InitializePlane|. |
|
xhwang
2016/05/10 19:04:04
Could you add a comment why CreateColorFrame() won
xjz
2016/05/10 21:08:44
Done.
|
| +scoped_refptr<media::VideoFrame> CreateInitializedFrame( |
|
xhwang
2016/05/10 19:04:04
ditto: "Initialized" seems too generic.
xjz
2016/05/10 21:08:44
Done.
|
| + 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)); |
|
xhwang
2016/05/10 19:04:04
nit: add an empty line here
xjz
2016/05/10 21:08:44
Done.
|
| + InitializePlane(frame->data(media::VideoFrame::kYPlane), |
| + frame->stride(media::VideoFrame::kYPlane), |
| + frame->visible_rect().size()); |
| + InitializePlane( |
| + frame->data(media::VideoFrame::kUPlane), |
| + frame->stride(media::VideoFrame::kUPlane), |
| + media::VideoFrame::PlaneSize(format, media::VideoFrame::kUPlane, |
| + frame->visible_rect().size())); |
| + InitializePlane( |
| + 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 +484,36 @@ TEST_F(VideoUtilTest, LetterboxYUV) { |
| } |
| } |
| +TEST_F(VideoUtilTest, I420CopyWithPadding) { |
| + gfx::Size visible_size(40, 30); |
| + scoped_refptr<VideoFrame> src_frame = CreateInitializedFrame( |
| + 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 = CreateInitializedFrame( |
| + 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 = CreateInitializedFrame(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 = |
| + CreateInitializedFrame(PIXEL_FORMAT_I420, odd_size, gfx::Rect(odd_size), |
| + odd_size, base::TimeDelta()); |
| + dst_frame = |
| + CreateInitializedFrame(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 |