Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Unified Diff: media/base/video_util_unittest.cc

Issue 1958913005: Memory copy the VideoFrame to match the requirement for HW encoders. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/video_util.cc ('k') | media/cast/sender/external_video_encoder.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « media/base/video_util.cc ('k') | media/cast/sender/external_video_encoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698