Libyuv Scalerunittest: Added PSNR check to some tests in scaler unittest:
-for downsampling to 1/2x1/2
-for the odd frame sizes cases
Review URL: https://webrtc-codereview.appspot.com/642009
git-svn-id: http://webrtc.googlecode.com/svn/trunk@2403 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/src/common_video/libyuv/scaler_unittest.cc b/src/common_video/libyuv/scaler_unittest.cc
index 1652094..f6ee15d 100644
--- a/src/common_video/libyuv/scaler_unittest.cc
+++ b/src/common_video/libyuv/scaler_unittest.cc
@@ -29,6 +29,14 @@
int src_width, int src_height,
int dst_width, int dst_height);
+ // TODO(mikhal): add a sequence reader to libyuv.
+
+ // Computes the sequence average PSNR between an input sequence in
+ // |input_file| and an output sequence with filename |out_name|. |width| and
+ // |height| are the frame sizes of both sequences.
+ double ComputeAvgSequencePSNR(FILE* input_file, std::string out_name,
+ int width, int height);
+
Scaler test_scaler_;
FILE* source_file_;
uint8_t* test_buffer_;
@@ -94,6 +102,7 @@
//TODO (mikhal): Converge the test into one function that accepts the method.
TEST_F(TestScaler, PointScaleTest) {
+ double avg_psnr;
FILE* source_file2;
ScaleMethod method = kScalePoint;
std::string out_name = webrtc::test::OutputPath() +
@@ -102,6 +111,21 @@
source_file_, out_name,
width_, height_,
width_ / 2, height_ / 2);
+ // Upsample back up and check PSNR.
+ source_file2 = fopen(out_name.c_str(), "rb");
+ out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
+ "upfrom_176_144.yuv";
+ ScaleSequence(method,
+ source_file2, out_name,
+ 176, 144,
+ 352, 288);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 176, 144, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 27.9);
+ ASSERT_EQ(0, fclose(source_file2));
out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_320_240.yuv";
ScaleSequence(method,
source_file_, out_name,
@@ -135,6 +159,12 @@
source_file2, out_name,
282, 231,
352, 288);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 282, 231, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 27.8);
ASSERT_EQ(0, fclose(source_file2));
// Upsample to odd size frame and scale back down.
out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_699_531.yuv";
@@ -149,10 +179,17 @@
source_file2, out_name,
699, 531,
352, 288);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 699, 531, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 37.8);
ASSERT_EQ(0, fclose(source_file2));
}
TEST_F(TestScaler, BiLinearScaleTest) {
+ double avg_psnr;
FILE* source_file2;
ScaleMethod method = kScaleBilinear;
std::string out_name = webrtc::test::OutputPath() +
@@ -161,6 +198,22 @@
source_file_, out_name,
width_, height_,
width_ / 2, height_ / 2);
+ // Upsample back up and check PSNR.
+ source_file2 = fopen(out_name.c_str(), "rb");
+ out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
+ "upfrom_176_144.yuv";
+ ScaleSequence(method,
+ source_file2, out_name,
+ 176, 144,
+ 352, 288);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 176, 144, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 27.5);
+ ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ ASSERT_EQ(0, fclose(source_file2));
out_name = webrtc::test::OutputPath() +
"LibYuvTest_BilinearScale_320_240.yuv";
ScaleSequence(method,
@@ -198,7 +251,13 @@
ScaleSequence(method,
source_file2, out_name,
282, 231,
- 352, 288);
+ width_, height_);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 282, 231, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 29.7);
ASSERT_EQ(0, fclose(source_file2));
// Upsample to odd size frame and scale back down.
out_name = webrtc::test::OutputPath() +
@@ -213,11 +272,18 @@
ScaleSequence(method,
source_file2, out_name,
699, 531,
- 352, 288);
+ width_, height_);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 699, 531, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 31.4);
ASSERT_EQ(0, fclose(source_file2));
}
TEST_F(TestScaler, BoxScaleTest) {
+ double avg_psnr;
FILE* source_file2;
ScaleMethod method = kScaleBox;
std::string out_name = webrtc::test::OutputPath() +
@@ -226,6 +292,21 @@
source_file_, out_name,
width_, height_,
width_ / 2, height_ / 2);
+ // Upsample back up and check PSNR.
+ source_file2 = fopen(out_name.c_str(), "rb");
+ out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
+ "upfrom_176_144.yuv";
+ ScaleSequence(method,
+ source_file2, out_name,
+ 176, 144,
+ 352, 288);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 176, 144, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 27.5);
+ ASSERT_EQ(0, fclose(source_file2));
out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_320_240.yuv";
ScaleSequence(method,
source_file_, out_name,
@@ -258,7 +339,13 @@
ScaleSequence(method,
source_file2, out_name,
282, 231,
- 352, 288);
+ width_, height_);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 282, 231, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 29.7);
ASSERT_EQ(0, fclose(source_file2));
// Upsample to odd size frame and scale back down.
out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_699_531.yuv";
@@ -272,10 +359,53 @@
ScaleSequence(method,
source_file2, out_name,
699, 531,
- 352, 288);
+ width_, height_);
+ avg_psnr = ComputeAvgSequencePSNR(source_file_, out_name, width_, height_);
+ printf("PSNR for scaling from: %d %d, down/up to: %d %d, and back to "
+ "original size: %f \n", width_, height_, 699, 531, avg_psnr);
+ // Average PSNR for lower bound in assert is ~0.1dB lower than the actual
+ // average PSNR under same conditions.
+ ASSERT_GT(avg_psnr, 31.4);
ASSERT_EQ(0, fclose(source_file2));
}
+double TestScaler::ComputeAvgSequencePSNR(FILE* input_file,
+ std::string out_name,
+ int width, int height) {
+ FILE* output_file;
+ output_file = fopen(out_name.c_str(), "rb");
+ assert(output_file != NULL);
+ rewind(input_file);
+ rewind(output_file);
+
+ int half_width = (width + 1) >> 1;
+ int half_height = (height + 1) >> 1;
+ int required_size = height * width + 2 * (half_width * half_height);
+ uint8_t* input_buffer = new uint8_t[required_size];
+ uint8_t* output_buffer = new uint8_t[required_size];
+
+ int frame_count = 0;
+ double avg_psnr = 0;
+ while (feof(input_file) == 0) {
+ if ((size_t)required_size !=
+ fread(input_buffer, 1, required_size, input_file)) {
+ break;
+ }
+ if ((size_t)required_size !=
+ fread(output_buffer, 1, required_size, output_file)) {
+ break;
+ }
+ frame_count++;
+ double psnr = I420PSNR(input_buffer, output_buffer, width, height);
+ avg_psnr += psnr;
+ }
+ avg_psnr = avg_psnr / frame_count;
+ assert(0 == fclose(output_file));
+ delete [] input_buffer;
+ delete [] output_buffer;
+ return avg_psnr;
+}
+
// TODO (mikhal): Move part to a separate scale test.
void TestScaler::ScaleSequence(ScaleMethod method,
FILE* source_file, std::string out_name,