|  | /* | 
|  | *  Copyright (c) 2018 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 "rtc_tools/frame_analyzer/video_geometry_aligner.h" | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | #include "api/video/i420_buffer.h" | 
|  | #include "rtc_tools/frame_analyzer/video_quality_analysis.h" | 
|  | #include "rtc_tools/video_file_reader.h" | 
|  | #include "test/gtest.h" | 
|  | #include "test/testsupport/file_utils.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace test { | 
|  |  | 
|  | class VideoGeometryAlignerTest : public ::testing::Test { | 
|  | protected: | 
|  | void SetUp() { | 
|  | reference_video_ = | 
|  | OpenYuvFile(ResourcePath("foreman_128x96", "yuv"), 128, 96); | 
|  | ASSERT_TRUE(reference_video_); | 
|  |  | 
|  | // Very simple 4x4 frame used for verying CropAndZoom. | 
|  | const uint8_t data_y[] = {0, 1, 2,  3,  4,  5,  6,  7, | 
|  | 8, 9, 10, 11, 12, 13, 14, 15}; | 
|  | const uint8_t data_u[] = {0, 1, 2, 3}; | 
|  | const uint8_t data_v[] = {0, 1, 2, 3}; | 
|  | test_frame_ = I420Buffer::Copy( | 
|  | /* width= */ 4, /* height= */ 4, data_y, /* stride_y= */ 4, data_u, | 
|  | /* stride_u= */ 2, data_v, /* stride_v= */ 2); | 
|  | } | 
|  |  | 
|  | rtc::scoped_refptr<Video> reference_video_; | 
|  | rtc::scoped_refptr<I420BufferInterface> test_frame_; | 
|  | }; | 
|  |  | 
|  | // Teach gtest how to compare CropRegions. | 
|  | bool operator==(const CropRegion& a, const CropRegion& b) { | 
|  | return a.left == b.left && a.top == b.top && a.right == b.right && | 
|  | a.bottom == b.bottom; | 
|  | } | 
|  |  | 
|  | TEST_F(VideoGeometryAlignerTest, CropAndZoomIdentity) { | 
|  | const rtc::scoped_refptr<I420BufferInterface> frame = | 
|  | reference_video_->GetFrame(0); | 
|  |  | 
|  | // Assume perfect match, i.e. SSIM == 1. | 
|  | CropRegion identity_region; | 
|  | EXPECT_EQ(1.0, Ssim(frame, CropAndZoom(identity_region, frame))); | 
|  | } | 
|  |  | 
|  | TEST_F(VideoGeometryAlignerTest, CropAndZoomLeft) { | 
|  | CropRegion region; | 
|  | region.left = 2; | 
|  | const rtc::scoped_refptr<I420BufferInterface> cropped_frame = | 
|  | CropAndZoom(region, test_frame_); | 
|  | EXPECT_EQ(std::vector<uint8_t>( | 
|  | {2, 2, 3, 3, 6, 6, 7, 7, 10, 10, 11, 11, 14, 14, 15, 15}), | 
|  | std::vector<uint8_t>(cropped_frame->DataY(), | 
|  | cropped_frame->DataY() + 16)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({1, 1, 3, 3}), | 
|  | std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({1, 1, 3, 3}), | 
|  | std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4)); | 
|  | } | 
|  |  | 
|  | // TODO(magjed): Re-enable when libyuv filtering is updated. | 
|  | TEST_F(VideoGeometryAlignerTest, DISABLED_CropAndZoomTop) { | 
|  | CropRegion region; | 
|  | region.top = 2; | 
|  | const rtc::scoped_refptr<I420BufferInterface> cropped_frame = | 
|  | CropAndZoom(region, test_frame_); | 
|  | EXPECT_EQ(std::vector<uint8_t>( | 
|  | {8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 12, 13, 14, 15}), | 
|  | std::vector<uint8_t>(cropped_frame->DataY(), | 
|  | cropped_frame->DataY() + 16)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({2, 3, 2, 3}), | 
|  | std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({2, 3, 2, 3}), | 
|  | std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4)); | 
|  | } | 
|  |  | 
|  | TEST_F(VideoGeometryAlignerTest, CropAndZoomRight) { | 
|  | CropRegion region; | 
|  | region.right = 2; | 
|  | const rtc::scoped_refptr<I420BufferInterface> cropped_frame = | 
|  | CropAndZoom(region, test_frame_); | 
|  | EXPECT_EQ(std::vector<uint8_t>( | 
|  | {0, 0, 1, 1, 4, 4, 5, 5, 8, 8, 9, 9, 12, 12, 13, 13}), | 
|  | std::vector<uint8_t>(cropped_frame->DataY(), | 
|  | cropped_frame->DataY() + 16)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({0, 0, 2, 2}), | 
|  | std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({0, 0, 2, 2}), | 
|  | std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4)); | 
|  | } | 
|  |  | 
|  | // TODO(magjed): Re-enable when libyuv filtering is updated. | 
|  | TEST_F(VideoGeometryAlignerTest, DISABLED_CropAndZoomBottom) { | 
|  | CropRegion region; | 
|  | region.bottom = 2; | 
|  | const rtc::scoped_refptr<I420BufferInterface> cropped_frame = | 
|  | CropAndZoom(region, test_frame_); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 4, 5, 6, 7}), | 
|  | std::vector<uint8_t>(cropped_frame->DataY(), | 
|  | cropped_frame->DataY() + 16)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({0, 1, 0, 1}), | 
|  | std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4)); | 
|  | EXPECT_EQ( | 
|  | std::vector<uint8_t>({0, 1, 0, 1}), | 
|  | std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4)); | 
|  | } | 
|  |  | 
|  | TEST_F(VideoGeometryAlignerTest, CalculateCropRegionIdentity) { | 
|  | const rtc::scoped_refptr<I420BufferInterface> frame = | 
|  | reference_video_->GetFrame(0); | 
|  | CropRegion identity_region; | 
|  | EXPECT_EQ(identity_region, CalculateCropRegion(frame, frame)); | 
|  | } | 
|  |  | 
|  | TEST_F(VideoGeometryAlignerTest, CalculateCropRegionArbitrary) { | 
|  | // Arbitrary crop region. | 
|  | CropRegion crop_region; | 
|  | crop_region.left = 2; | 
|  | crop_region.top = 4; | 
|  | crop_region.right = 5; | 
|  | crop_region.bottom = 3; | 
|  |  | 
|  | const rtc::scoped_refptr<I420BufferInterface> frame = | 
|  | reference_video_->GetFrame(0); | 
|  |  | 
|  | EXPECT_EQ(crop_region, | 
|  | CalculateCropRegion(frame, CropAndZoom(crop_region, frame))); | 
|  | } | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace webrtc |