Fix to scaler in libyuv for odd size frames.

Review URL: https://webrtc-codereview.appspot.com/633004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2360 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
marpan@webrtc.org 2012-06-04 21:56:13 +00:00
parent ba108aee21
commit da7fdf4af8
2 changed files with 109 additions and 8 deletions

View File

@ -65,22 +65,26 @@ int Scaler::Scale(const uint8_t* src_frame,
dst_size = required_dst_size;
}
int src_half_width = (src_width_ + 1) >> 1;
int src_half_height = (src_height_ + 1) >> 1;
// Converting to planes:
const uint8_t* src_yplane = src_frame;
const uint8_t* src_uplane = src_frame + src_width_ * src_height_;
const uint8_t* src_vplane = src_uplane + src_width_ * src_height_ / 4;
const uint8_t* src_vplane = src_uplane + src_half_width * src_half_height;
int dst_half_width = (dst_width_ + 1) >> 1;
int dst_half_height = (dst_height_ + 1) >> 1;
uint8_t* dst_yplane = dst_frame;
uint8_t* dst_uplane = dst_frame + dst_width_ * dst_height_;
uint8_t* dst_vplane = dst_uplane + dst_width_ * dst_height_ / 4;
uint8_t* dst_vplane = dst_uplane + dst_half_width * dst_half_height;
return libyuv::I420Scale(src_yplane, src_width_,
src_uplane, src_width_ / 2,
src_vplane, src_width_ / 2,
src_uplane, src_half_width,
src_vplane, src_half_width,
src_width_, src_height_,
dst_yplane, dst_width_,
dst_uplane, dst_width_ / 2,
dst_vplane, dst_width_ / 2,
dst_uplane, dst_half_width,
dst_vplane, dst_half_width,
dst_width_, dst_height_,
libyuv::FilterMode(method_));
}

View File

@ -94,6 +94,7 @@ TEST_F(TestScaler, ScaleSendingBufferTooSmall) {
//TODO (mikhal): Converge the test into one function that accepts the method.
TEST_F(TestScaler, PointScaleTest) {
FILE* source_file2;
ScaleMethod method = kScalePoint;
std::string out_name = webrtc::test::OutputPath() +
"LibYuvTest_PointScale_176_144.yuv";
@ -121,9 +122,38 @@ TEST_F(TestScaler, PointScaleTest) {
source_file_, out_name,
width_, height_,
400, 300);
// Dowsample to odd size frame and scale back up.
out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_282_231.yuv";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
282, 231);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
"upfrom_282_231.yuv";
ScaleSequence(method,
source_file2, out_name,
282, 231,
352, 288);
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";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
699, 531);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_PointScale_352_288_"
"downfrom_699_531.yuv";
ScaleSequence(method,
source_file2, out_name,
699, 531,
352, 288);
ASSERT_EQ(0, fclose(source_file2));
}
TEST_F(TestScaler, BiLinearScaleTest) {
FILE* source_file2;
ScaleMethod method = kScaleBilinear;
std::string out_name = webrtc::test::OutputPath() +
"LibYuvTest_BilinearScale_176_144.yuv";
@ -155,9 +185,40 @@ TEST_F(TestScaler, BiLinearScaleTest) {
source_file_, out_name,
width_, height_,
400, 300);
// Downsample to odd size frame and scale back up.
out_name = webrtc::test::OutputPath() +
"LibYuvTest_BilinearScale_282_231.yuv";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
282, 231);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
"upfrom_282_231.yuv";
ScaleSequence(method,
source_file2, out_name,
282, 231,
352, 288);
ASSERT_EQ(0, fclose(source_file2));
// Upsample to odd size frame and scale back down.
out_name = webrtc::test::OutputPath() +
"LibYuvTest_BilinearScale_699_531.yuv";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
699, 531);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_BilinearScale_352_288_"
"downfrom_699_531.yuv";
ScaleSequence(method,
source_file2, out_name,
699, 531,
352, 288);
ASSERT_EQ(0, fclose(source_file2));
}
TEST_F(TestScaler, BoxScaleTest) {
FILE* source_file2;
ScaleMethod method = kScaleBox;
std::string out_name = webrtc::test::OutputPath() +
"LibYuvTest_BoxScale_176_144.yuv";
@ -185,6 +246,34 @@ TEST_F(TestScaler, BoxScaleTest) {
source_file_, out_name,
width_, height_,
400, 300);
// Downsample to odd size frame and scale back up.
out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_282_231.yuv";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
282, 231);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
"upfrom_282_231.yuv";
ScaleSequence(method,
source_file2, out_name,
282, 231,
352, 288);
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";
ScaleSequence(method,
source_file_, out_name,
width_, height_,
699, 531);
source_file2 = fopen(out_name.c_str(), "rb");
out_name = webrtc::test::OutputPath() + "LibYuvTest_BoxScale_352_288_"
"downfrom_699_531.yuv";
ScaleSequence(method,
source_file2, out_name,
699, 531,
352, 288);
ASSERT_EQ(0, fclose(source_file2));
}
// TODO (mikhal): Move part to a separate scale test.
@ -202,8 +291,16 @@ void TestScaler::ScaleSequence(ScaleMethod method,
rewind(source_file);
int out_required_size = dst_width * dst_height * 3 / 2;
int in_required_size = src_height * src_width * 3 / 2;
int src_half_width = (src_width + 1) >> 1;
int src_half_height = (src_height + 1) >> 1;
int dst_half_width = (dst_width + 1) >> 1;
int dst_half_height = (dst_height + 1) >> 1;
int out_required_size = dst_width * dst_height + 2 * (dst_half_width *
dst_half_height);
int in_required_size = src_height * src_width + 2 * (src_half_width *
src_half_height);
uint8_t* input_buffer = new uint8_t[in_required_size];
uint8_t* output_buffer = new uint8_t[out_required_size];