mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 1 | /* |
stefan@webrtc.org | 0fe2171 | 2012-02-22 11:21:18 +0000 | [diff] [blame] | 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #include <math.h> |
| 12 | #include <string.h> |
| 13 | |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 14 | #include <memory> |
| 15 | |
pbos@webrtc.org | c69ae69 | 2013-06-04 09:02:37 +0000 | [diff] [blame] | 16 | #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 17 | #include "webrtc/test/frame_utils.h" |
magjed | 5a87245 | 2016-10-20 03:34:29 -0700 | [diff] [blame] | 18 | #include "webrtc/test/gmock.h" |
kwiberg | ac9f876 | 2016-09-30 22:29:43 -0700 | [diff] [blame] | 19 | #include "webrtc/test/gtest.h" |
pbos@webrtc.org | c69ae69 | 2013-06-04 09:02:37 +0000 | [diff] [blame] | 20 | #include "webrtc/test/testsupport/fileutils.h" |
Thiago Farina | 9bfe3da | 2015-04-10 12:52:13 +0200 | [diff] [blame] | 21 | #include "webrtc/video_frame.h" |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 22 | |
| 23 | namespace webrtc { |
| 24 | |
nisse | 69adc9c | 2016-06-02 00:58:35 -0700 | [diff] [blame] | 25 | namespace { |
| 26 | void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) { |
| 27 | *stride_y = 16 * ((width + 15) / 16); |
| 28 | *stride_uv = 16 * ((width + 31) / 32); |
| 29 | } |
| 30 | |
| 31 | } // Anonymous namespace |
| 32 | |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 33 | class TestLibYuv : public ::testing::Test { |
| 34 | protected: |
| 35 | TestLibYuv(); |
| 36 | virtual void SetUp(); |
| 37 | virtual void TearDown(); |
| 38 | |
| 39 | FILE* source_file_; |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 40 | std::unique_ptr<VideoFrame> orig_frame_; |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 41 | const int width_; |
| 42 | const int height_; |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 43 | const int size_y_; |
| 44 | const int size_uv_; |
pkasting@chromium.org | 4591fbd | 2014-11-20 22:28:14 +0000 | [diff] [blame] | 45 | const size_t frame_length_; |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 46 | }; |
| 47 | |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 48 | TestLibYuv::TestLibYuv() |
| 49 | : source_file_(NULL), |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 50 | orig_frame_(), |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 51 | width_(352), |
| 52 | height_(288), |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 53 | size_y_(width_ * height_), |
jbauch | 0f2e939 | 2015-12-10 03:11:42 -0800 | [diff] [blame] | 54 | size_uv_(((width_ + 1) / 2) * ((height_ + 1) / 2)), |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 55 | frame_length_(CalcBufferSize(kI420, 352, 288)) {} |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 56 | |
| 57 | void TestLibYuv::SetUp() { |
kjellander | 0206000 | 2016-02-16 22:06:12 -0800 | [diff] [blame] | 58 | const std::string input_file_name = webrtc::test::ResourcePath("foreman_cif", |
| 59 | "yuv"); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 60 | source_file_ = fopen(input_file_name.c_str(), "rb"); |
| 61 | ASSERT_TRUE(source_file_ != NULL) << "Cannot read file: "<< |
| 62 | input_file_name << "\n"; |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 63 | |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 64 | rtc::scoped_refptr<VideoFrameBuffer> buffer( |
| 65 | test::ReadI420Buffer(width_, height_, source_file_)); |
| 66 | |
| 67 | orig_frame_.reset(new VideoFrame(buffer, kVideoRotation_0, 0)); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | void TestLibYuv::TearDown() { |
| 71 | if (source_file_ != NULL) { |
| 72 | ASSERT_EQ(0, fclose(source_file_)); |
| 73 | } |
| 74 | source_file_ = NULL; |
| 75 | } |
| 76 | |
| 77 | TEST_F(TestLibYuv, ConvertSanityTest) { |
| 78 | // TODO(mikhal) |
| 79 | } |
| 80 | |
| 81 | TEST_F(TestLibYuv, ConvertTest) { |
| 82 | // Reading YUV frame - testing on the first frame of the foreman sequence |
| 83 | int j = 0; |
| 84 | std::string output_file_name = webrtc::test::OutputPath() + |
| 85 | "LibYuvTest_conversion.yuv"; |
| 86 | FILE* output_file = fopen(output_file_name.c_str(), "wb"); |
| 87 | ASSERT_TRUE(output_file != NULL); |
| 88 | |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 89 | double psnr = 0.0; |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 90 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 91 | rtc::scoped_refptr<I420Buffer> res_i420_buffer = I420Buffer::Create( |
| 92 | width_, height_, width_, (width_ + 1) / 2, (width_ + 1) / 2); |
| 93 | |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 94 | printf("\nConvert #%d I420 <-> I420 \n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 95 | std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 96 | EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kI420, 0, out_i420_buffer.get())); |
guoweis@webrtc.org | 59140d6 | 2015-03-09 17:07:31 +0000 | [diff] [blame] | 97 | EXPECT_EQ(0, ConvertToI420(kI420, out_i420_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 98 | height_, 0, kVideoRotation_0, |
| 99 | res_i420_buffer.get())); |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 100 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 101 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 102 | return; |
| 103 | } |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 104 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 105 | EXPECT_EQ(48.0, psnr); |
| 106 | j++; |
| 107 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 108 | printf("\nConvert #%d I420 <-> RGB24\n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 109 | std::unique_ptr<uint8_t[]> res_rgb_buffer2(new uint8_t[width_ * height_ * 3]); |
mikhal@webrtc.org | 91a0340 | 2012-10-30 19:19:32 +0000 | [diff] [blame] | 110 | // Align the stride values for the output frame. |
| 111 | int stride_y = 0; |
| 112 | int stride_uv = 0; |
| 113 | Calc16ByteAlignedStride(width_, &stride_y, &stride_uv); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 114 | res_i420_buffer = |
| 115 | I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 116 | EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kRGB24, 0, res_rgb_buffer2.get())); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 117 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 118 | EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 119 | height_, 0, kVideoRotation_0, |
| 120 | res_i420_buffer.get())); |
mikhal@webrtc.org | e264249 | 2011-12-28 21:21:40 +0000 | [diff] [blame] | 121 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 122 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
leozwang@webrtc.org | 2fc6e38 | 2012-05-29 17:33:13 +0000 | [diff] [blame] | 123 | return; |
| 124 | } |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 125 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 126 | |
mikhal@webrtc.org | e264249 | 2011-12-28 21:21:40 +0000 | [diff] [blame] | 127 | // Optimization Speed- quality trade-off => 45 dB only (platform dependant). |
stefan@webrtc.org | 0fe2171 | 2012-02-22 11:21:18 +0000 | [diff] [blame] | 128 | EXPECT_GT(ceil(psnr), 44); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 129 | j++; |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 130 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 131 | printf("\nConvert #%d I420 <-> UYVY\n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 132 | std::unique_ptr<uint8_t[]> out_uyvy_buffer(new uint8_t[width_ * height_ * 2]); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 133 | EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kUYVY, 0, out_uyvy_buffer.get())); |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 134 | EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 135 | height_, 0, kVideoRotation_0, |
| 136 | res_i420_buffer.get())); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 137 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 138 | EXPECT_EQ(48.0, psnr); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 139 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 140 | return; |
| 141 | } |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 142 | j++; |
| 143 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 144 | printf("\nConvert #%d I420 <-> YUY2\n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 145 | std::unique_ptr<uint8_t[]> out_yuy2_buffer(new uint8_t[width_ * height_ * 2]); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 146 | EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kYUY2, 0, out_yuy2_buffer.get())); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 147 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 148 | EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 149 | height_, 0, |
| 150 | kVideoRotation_0, res_i420_buffer.get())); |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 151 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 152 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 153 | return; |
leozwang@webrtc.org | 2fc6e38 | 2012-05-29 17:33:13 +0000 | [diff] [blame] | 154 | } |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 155 | |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 156 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 157 | EXPECT_EQ(48.0, psnr); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 158 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 159 | printf("\nConvert #%d I420 <-> RGB565\n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 160 | std::unique_ptr<uint8_t[]> out_rgb565_buffer( |
kwiberg@webrtc.org | 00b8f6b | 2015-02-26 14:34:55 +0000 | [diff] [blame] | 161 | new uint8_t[width_ * height_ * 2]); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 162 | EXPECT_EQ(0, |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 163 | ConvertFromI420(*orig_frame_, kRGB565, 0, out_rgb565_buffer.get())); |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 164 | |
| 165 | EXPECT_EQ(0, ConvertToI420(kRGB565, out_rgb565_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 166 | height_, 0, |
| 167 | kVideoRotation_0, res_i420_buffer.get())); |
| 168 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 169 | return; |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 170 | } |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 171 | j++; |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 172 | |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 173 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
leozwang@webrtc.org | 1ea25b4 | 2012-05-04 17:55:57 +0000 | [diff] [blame] | 174 | // TODO(leozwang) Investigate the right psnr should be set for I420ToRGB565, |
| 175 | // Another example is I420ToRGB24, the psnr is 44 |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 176 | // TODO(mikhal): Add psnr for RGB565, 1555, 4444, convert to ARGB. |
leozwang@webrtc.org | 1ea25b4 | 2012-05-04 17:55:57 +0000 | [diff] [blame] | 177 | EXPECT_GT(ceil(psnr), 40); |
leozwang@webrtc.org | 83958df | 2012-05-04 17:07:45 +0000 | [diff] [blame] | 178 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 179 | printf("\nConvert #%d I420 <-> ARGB8888\n", j); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 180 | std::unique_ptr<uint8_t[]> out_argb8888_buffer( |
kwiberg@webrtc.org | 00b8f6b | 2015-02-26 14:34:55 +0000 | [diff] [blame] | 181 | new uint8_t[width_ * height_ * 4]); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 182 | EXPECT_EQ(0, |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 183 | ConvertFromI420(*orig_frame_, kARGB, 0, out_argb8888_buffer.get())); |
leozwang@webrtc.org | 83958df | 2012-05-04 17:07:45 +0000 | [diff] [blame] | 184 | |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 185 | EXPECT_EQ(0, ConvertToI420(kARGB, out_argb8888_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 186 | height_, 0, kVideoRotation_0, |
| 187 | res_i420_buffer.get())); |
leozwang@webrtc.org | 83958df | 2012-05-04 17:07:45 +0000 | [diff] [blame] | 188 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 189 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
leozwang@webrtc.org | 2fc6e38 | 2012-05-29 17:33:13 +0000 | [diff] [blame] | 190 | return; |
| 191 | } |
mikhal@webrtc.org | 9fedff7 | 2012-10-24 18:33:04 +0000 | [diff] [blame] | 192 | |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 193 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 194 | // TODO(leozwang) Investigate the right psnr should be set for |
| 195 | // I420ToARGB8888, |
leozwang@webrtc.org | 329fcbb | 2012-05-04 21:31:22 +0000 | [diff] [blame] | 196 | EXPECT_GT(ceil(psnr), 42); |
leozwang@webrtc.org | 83958df | 2012-05-04 17:07:45 +0000 | [diff] [blame] | 197 | |
kjellander@webrtc.org | 94558d8 | 2012-01-04 13:51:50 +0000 | [diff] [blame] | 198 | ASSERT_EQ(0, fclose(output_file)); |
mikhal@webrtc.org | 6f7fbc7 | 2011-12-20 17:38:28 +0000 | [diff] [blame] | 199 | } |
| 200 | |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 201 | TEST_F(TestLibYuv, ConvertAlignedFrame) { |
| 202 | // Reading YUV frame - testing on the first frame of the foreman sequence |
| 203 | std::string output_file_name = webrtc::test::OutputPath() + |
| 204 | "LibYuvTest_conversion.yuv"; |
| 205 | FILE* output_file = fopen(output_file_name.c_str(), "wb"); |
| 206 | ASSERT_TRUE(output_file != NULL); |
| 207 | |
| 208 | double psnr = 0.0; |
| 209 | |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 210 | int stride_y = 0; |
| 211 | int stride_uv = 0; |
| 212 | Calc16ByteAlignedStride(width_, &stride_y, &stride_uv); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 213 | |
| 214 | rtc::scoped_refptr<I420Buffer> res_i420_buffer = |
| 215 | I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv); |
kwiberg | c891eb4 | 2016-03-02 03:41:34 -0800 | [diff] [blame] | 216 | std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 217 | EXPECT_EQ(0, ConvertFromI420(*orig_frame_, kI420, 0, |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 218 | out_i420_buffer.get())); |
guoweis@webrtc.org | 59140d6 | 2015-03-09 17:07:31 +0000 | [diff] [blame] | 219 | EXPECT_EQ(0, ConvertToI420(kI420, out_i420_buffer.get(), 0, 0, width_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 220 | height_, 0, kVideoRotation_0, |
| 221 | res_i420_buffer.get())); |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 222 | |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 223 | if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) { |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 224 | return; |
| 225 | } |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 226 | psnr = I420PSNR(*orig_frame_->video_frame_buffer(), *res_i420_buffer); |
mikhal@webrtc.org | 32b3f40 | 2012-11-20 23:52:50 +0000 | [diff] [blame] | 227 | EXPECT_EQ(48.0, psnr); |
| 228 | } |
| 229 | |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 230 | TEST_F(TestLibYuv, RotateTest) { |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 231 | // Use ConvertToI420 for multiple rotations - see that nothing breaks, all |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 232 | // memory is properly allocated and end result is equal to the starting point. |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 233 | int rotated_width = height_; |
| 234 | int rotated_height = width_; |
jbauch | 0f2e939 | 2015-12-10 03:11:42 -0800 | [diff] [blame] | 235 | int stride_y; |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 236 | int stride_uv; |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 237 | |
| 238 | // Assume compact layout, no padding. |
| 239 | const uint8_t *orig_buffer = orig_frame_->video_frame_buffer()->DataY(); |
| 240 | |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 241 | Calc16ByteAlignedStride(rotated_width, &stride_y, &stride_uv); |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 242 | rtc::scoped_refptr<I420Buffer> rotated_res_i420_buffer = I420Buffer::Create( |
| 243 | rotated_width, rotated_height, stride_y, stride_uv, stride_uv); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 244 | EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 245 | 0, kVideoRotation_90, |
| 246 | rotated_res_i420_buffer.get())); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 247 | EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 248 | 0, kVideoRotation_270, |
| 249 | rotated_res_i420_buffer.get())); |
| 250 | rotated_res_i420_buffer = I420Buffer::Create( |
| 251 | width_, height_, width_, (width_ + 1) / 2, (width_ + 1) / 2); |
nisse | 115bd15 | 2016-09-30 04:14:07 -0700 | [diff] [blame] | 252 | EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_, |
nisse | 64ec8f8 | 2016-09-27 00:17:25 -0700 | [diff] [blame] | 253 | 0, kVideoRotation_180, |
| 254 | rotated_res_i420_buffer.get())); |
mikhal@webrtc.org | 737ed3b | 2012-11-01 15:45:38 +0000 | [diff] [blame] | 255 | } |
| 256 | |
magjed | 5a87245 | 2016-10-20 03:34:29 -0700 | [diff] [blame] | 257 | static uint8_t Average(int a, int b, int c, int d) { |
| 258 | return (a + b + c + d + 2) / 4; |
| 259 | } |
| 260 | |
| 261 | TEST_F(TestLibYuv, NV12Scale2x2to2x2) { |
| 262 | const std::vector<uint8_t> src_y = {0, 1, |
| 263 | 2, 3}; |
| 264 | const std::vector<uint8_t> src_uv = {0, 1}; |
| 265 | std::vector<uint8_t> dst_y(4); |
| 266 | std::vector<uint8_t> dst_uv(2); |
| 267 | |
| 268 | std::vector<uint8_t> tmp_buffer; |
| 269 | NV12Scale(&tmp_buffer, |
| 270 | src_y.data(), 2, |
| 271 | src_uv.data(), 2, |
| 272 | 2, 2, |
| 273 | dst_y.data(), 2, |
| 274 | dst_uv.data(), 2, |
| 275 | 2, 2); |
| 276 | |
| 277 | EXPECT_THAT(dst_y, ::testing::ContainerEq(src_y)); |
| 278 | EXPECT_THAT(dst_uv, ::testing::ContainerEq(src_uv)); |
| 279 | } |
| 280 | |
| 281 | TEST_F(TestLibYuv, NV12Scale4x4to2x2) { |
| 282 | const uint8_t src_y[] = { 0, 1, 2, 3, |
| 283 | 4, 5, 6, 7, |
| 284 | 8, 9, 10, 11, |
| 285 | 12, 13, 14, 15}; |
| 286 | const uint8_t src_uv[] = {0, 1, 2, 3, |
| 287 | 4, 5, 6, 7}; |
| 288 | std::vector<uint8_t> dst_y(4); |
| 289 | std::vector<uint8_t> dst_uv(2); |
| 290 | |
| 291 | std::vector<uint8_t> tmp_buffer; |
| 292 | NV12Scale(&tmp_buffer, |
| 293 | src_y, 4, |
| 294 | src_uv, 4, |
| 295 | 4, 4, |
| 296 | dst_y.data(), 2, |
| 297 | dst_uv.data(), 2, |
| 298 | 2, 2); |
| 299 | |
| 300 | EXPECT_THAT(dst_y, ::testing::ElementsAre( |
| 301 | Average(0, 1, 4, 5), Average(2, 3, 6, 7), |
| 302 | Average(8, 9, 12, 13), Average(10, 11, 14, 15))); |
| 303 | EXPECT_THAT(dst_uv, |
| 304 | ::testing::ElementsAre(Average(0, 2, 4, 6), Average(1, 3, 5, 7))); |
| 305 | } |
| 306 | |
jbauch | 0f2e939 | 2015-12-10 03:11:42 -0800 | [diff] [blame] | 307 | } // namespace webrtc |