15f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org/*
25f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * libjingle
35f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Copyright 2014 Google Inc.
45f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *
55f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Redistribution and use in source and binary forms, with or without
65f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * modification, are permitted provided that the following conditions are met:
75f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *
85f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *     this list of conditions and the following disclaimer.
105f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *     and/or other materials provided with the distribution.
135f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *     derived from this software without specific prior written permission.
155f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org *
165f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org */
27704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
28704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include <string>
29704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
30704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include "libyuv/convert.h"
31704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include "libyuv/convert_from.h"
32704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include "libyuv/convert_from_argb.h"
33704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include "libyuv/mjpeg_decoder.h"
34704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#include "libyuv/planar_functions.h"
35a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "talk/media/base/testutils.h"
36a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "talk/media/base/videocommon.h"
37d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/flags.h"
38d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/gunit.h"
39d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/scoped_ptr.h"
40704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
41704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Undefine macros for the windows build.
42704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#undef max
43704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org#undef min
44704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
45704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgusing cricket::DumpPlanarYuvTestImage;
46704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
47704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgDEFINE_bool(planarfunctions_dump, false,
48704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    "whether to write out scaled images for inspection");
49704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgDEFINE_int(planarfunctions_repeat, 1,
50704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    "how many times to perform each scaling operation (for perf testing)");
51704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
52704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgnamespace cricket {
53704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
54704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Number of testing colors in each color channel.
55704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgstatic const int kTestingColorChannelResolution = 6;
56704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
57704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// The total number of testing colors
58704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// kTestingColorNum = kTestingColorChannelResolution^3;
59704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgstatic const int kTestingColorNum = kTestingColorChannelResolution *
60704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    kTestingColorChannelResolution * kTestingColorChannelResolution;
61704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
62704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgstatic const int kWidth = 1280;
63704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgstatic const int kHeight = 720;
64704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgstatic const int kAlignment = 16;
65704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
66704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgclass PlanarFunctionsTest : public testing::TestWithParam<int> {
67704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org protected:
68704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  PlanarFunctionsTest() : dump_(false), repeat_(1) {
69704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    InitializeColorBand();
70704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
71704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
72704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  virtual void SetUp() {
73704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    dump_ = FLAG_planarfunctions_dump;
74704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    repeat_ = FLAG_planarfunctions_repeat;
75704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
76704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
77704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Initialize the color band for testing.
78704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  void InitializeColorBand() {
790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_y_.reset(new uint8_t[kTestingColorNum]);
800c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_u_.reset(new uint8_t[kTestingColorNum]);
810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_v_.reset(new uint8_t[kTestingColorNum]);
820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_r_.reset(new uint8_t[kTestingColorNum]);
830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_g_.reset(new uint8_t[kTestingColorNum]);
840c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    testing_color_b_.reset(new uint8_t[kTestingColorNum]);
85704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int color_counter = 0;
86704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    for (int i = 0; i < kTestingColorChannelResolution; ++i) {
870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      uint8_t color_r =
880c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström          static_cast<uint8_t>(i * 255 / (kTestingColorChannelResolution - 1));
89704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      for (int j = 0; j < kTestingColorChannelResolution; ++j) {
900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        uint8_t color_g = static_cast<uint8_t>(
91704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            j * 255 / (kTestingColorChannelResolution - 1));
92704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int k = 0; k < kTestingColorChannelResolution; ++k) {
930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström          uint8_t color_b = static_cast<uint8_t>(
94704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              k * 255 / (kTestingColorChannelResolution - 1));
95704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          testing_color_r_[color_counter] = color_r;
96704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          testing_color_g_[color_counter] = color_g;
97704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          testing_color_b_[color_counter] = color_b;
98704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org           // Converting the testing RGB colors to YUV colors.
99704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          ConvertRgbPixel(color_r, color_g, color_b,
100704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                          &(testing_color_y_[color_counter]),
101704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                          &(testing_color_u_[color_counter]),
102704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                          &(testing_color_v_[color_counter]));
103704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          ++color_counter;
104704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
105704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
106704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
107704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
108704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Simple and slow RGB->YUV conversion. From NTSC standard, c/o Wikipedia.
109704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // (from lmivideoframe_unittest.cc)
1100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  void ConvertRgbPixel(uint8_t r,
1110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                       uint8_t g,
1120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                       uint8_t b,
1130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                       uint8_t* y,
1140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                       uint8_t* u,
1150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                       uint8_t* v) {
116704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    *y = ClampUint8(.257 * r + .504 * g + .098 * b + 16);
117704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    *u = ClampUint8(-.148 * r - .291 * g + .439 * b + 128);
118704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    *v = ClampUint8(.439 * r - .368 * g - .071 * b + 128);
119704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
120704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
1210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t ClampUint8(double value) {
122704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    value = std::max(0., std::min(255., value));
1230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t uint8_value = static_cast<uint8_t>(value);
124704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return uint8_value;
125704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
126704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
127704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a Red-Green-Blue inter-weaving chessboard-like
128704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // YUV testing image (I420/I422/I444).
129704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The pattern looks like c0 c1 c2 c3 ...
130704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c1 c2 c3 c4 ...
131704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c2 c3 c4 c5 ...
132704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        ...............
133704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The size of each chrome block is (block_size) x (block_size).
1340c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* CreateFakeYuvTestingImage(int height,
1350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     int width,
1360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     int block_size,
1370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     libyuv::JpegSubsamplingType subsample_type,
1380c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint8_t*& y_pointer,
1390c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint8_t*& u_pointer,
1400c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     uint8_t*& v_pointer) {
141704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; }
142704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int y_size = height * width;
143704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int u_size, v_size;
144704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int vertical_sample_ratio = 1, horizontal_sample_ratio = 1;
145704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    switch (subsample_type) {
146704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case libyuv::kJpegYuv420:
147704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        u_size = ((height + 1) >> 1) * ((width + 1) >> 1);
148704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        v_size = u_size;
149704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        vertical_sample_ratio = 2, horizontal_sample_ratio = 2;
150704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
151704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case libyuv::kJpegYuv422:
152704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        u_size = height * ((width + 1) >> 1);
153704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        v_size = u_size;
154704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        vertical_sample_ratio = 1, horizontal_sample_ratio = 2;
155704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
156704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case libyuv::kJpegYuv444:
157704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        v_size = u_size = y_size;
158704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        vertical_sample_ratio = 1, horizontal_sample_ratio = 1;
159704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
160704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case libyuv::kJpegUnknown:
161704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      default:
162704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        return NULL;
163704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
164704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
1650c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* image_pointer = new uint8_t[y_size + u_size + v_size + kAlignment];
166704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    y_pointer = ALIGNP(image_pointer, kAlignment);
167704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    u_pointer = ALIGNP(&image_pointer[y_size], kAlignment);
168704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    v_pointer = ALIGNP(&image_pointer[y_size + u_size], kAlignment);
1690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_y_pointer = y_pointer;
1700c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_u_pointer = u_pointer;
1710c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_v_pointer = v_pointer;
172704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    for (int j = 0; j < height; ++j) {
173704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      for (int i = 0; i < width; ++i) {
174704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        int color = ((i / block_size) + (j / block_size)) % kTestingColorNum;
175704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        *(current_y_pointer++) = testing_color_y_[color];
176704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        if (i % horizontal_sample_ratio == 0 &&
177704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            j % vertical_sample_ratio == 0) {
178704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          *(current_u_pointer++) = testing_color_u_[color];
179704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          *(current_v_pointer++) = testing_color_v_[color];
180704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
181704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
182704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
183704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return image_pointer;
184704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
185704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
186704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a Red-Green-Blue inter-weaving chessboard-like
187704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // YUY2/UYVY testing image.
188704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The pattern looks like c0 c1 c2 c3 ...
189704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c1 c2 c3 c4 ...
190704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c2 c3 c4 c5 ...
191704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        ...............
192704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The size of each chrome block is (block_size) x (block_size).
1930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* CreateFakeInterleaveYuvTestingImage(int height,
1940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                               int width,
1950c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                               int block_size,
1960c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                               uint8_t*& yuv_pointer,
1970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                               FourCC fourcc_type) {
198704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; }
199704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (fourcc_type != FOURCC_YUY2 && fourcc_type != FOURCC_UYVY) {
200704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      LOG(LS_ERROR) << "Format " << static_cast<int>(fourcc_type)
201704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                    << " is not supported.";
202704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      return NULL;
203704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
204704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    // Regularize the width of the output to be even.
205704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int awidth = (width + 1) & ~1;
206704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
2070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* image_pointer = new uint8_t[2 * height * awidth + kAlignment];
208704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    yuv_pointer = ALIGNP(image_pointer, kAlignment);
2090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_yuv_pointer = yuv_pointer;
210704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    switch (fourcc_type) {
211704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_YUY2: {
212704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
213704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < awidth; i += 2, current_yuv_pointer += 4) {
214704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color1 = ((i / block_size) + (j / block_size)) %
215704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
216704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color2 = (((i + 1) / block_size) + (j / block_size)) %
217704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
218704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            current_yuv_pointer[0] = testing_color_y_[color1];
219704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            if (i < width) {
2200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström              current_yuv_pointer[1] = static_cast<uint8_t>(
2210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  (static_cast<uint32_t>(testing_color_u_[color1]) +
2220c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                   static_cast<uint32_t>(testing_color_u_[color2])) /
2230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  2);
224704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[2] = testing_color_y_[color2];
2250c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström              current_yuv_pointer[3] = static_cast<uint8_t>(
2260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  (static_cast<uint32_t>(testing_color_v_[color1]) +
2270c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                   static_cast<uint32_t>(testing_color_v_[color2])) /
2280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  2);
229704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            } else {
230704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[1] = testing_color_u_[color1];
231704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[2] = 0;
232704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[3] = testing_color_v_[color1];
233704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            }
234704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
235704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
236704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
237704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
238704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_UYVY: {
239704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
240704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < awidth; i += 2, current_yuv_pointer += 4) {
241704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color1 = ((i / block_size) + (j / block_size)) %
242704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
243704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color2 = (((i + 1) / block_size) + (j / block_size)) %
244704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
245704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            if (i < width) {
2460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström              current_yuv_pointer[0] = static_cast<uint8_t>(
2470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  (static_cast<uint32_t>(testing_color_u_[color1]) +
2480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                   static_cast<uint32_t>(testing_color_u_[color2])) /
2490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  2);
250704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[1] = testing_color_y_[color1];
2510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström              current_yuv_pointer[2] = static_cast<uint8_t>(
2520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  (static_cast<uint32_t>(testing_color_v_[color1]) +
2530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                   static_cast<uint32_t>(testing_color_v_[color2])) /
2540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                  2);
255704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[3] = testing_color_y_[color2];
256704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            } else {
257704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[0] = testing_color_u_[color1];
258704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[1] = testing_color_y_[color1];
259704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[2] = testing_color_v_[color1];
260704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              current_yuv_pointer[3] = 0;
261704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            }
262704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
263704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
264704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
265704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
266704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
267704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return image_pointer;
268704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
269704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
270704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a Red-Green-Blue inter-weaving chessboard-like
271704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // NV12 testing image.
272704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // (Note: No interpolation is used.)
273704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The pattern looks like c0 c1 c2 c3 ...
274704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c1 c2 c3 c4 ...
275704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c2 c3 c4 c5 ...
276704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        ...............
277704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The size of each chrome block is (block_size) x (block_size).
2780c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* CreateFakeNV12TestingImage(int height,
2790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int width,
2800c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int block_size,
2810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      uint8_t*& y_pointer,
2820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      uint8_t*& uv_pointer) {
283704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; }
284704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
2850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* image_pointer =
2860c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        new uint8_t[height * width +
2870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                    ((height + 1) / 2) * ((width + 1) / 2) * 2 + kAlignment];
288704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    y_pointer = ALIGNP(image_pointer, kAlignment);
289704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    uv_pointer = y_pointer + height * width;
2900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_uv_pointer = uv_pointer;
2910c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_y_pointer = y_pointer;
292704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    for (int j = 0; j < height; ++j) {
293704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      for (int i = 0; i < width; ++i) {
294704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        int color = ((i / block_size) + (j / block_size)) %
295704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            kTestingColorNum;
296704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        *(current_y_pointer++) = testing_color_y_[color];
297704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
298704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      if (j % 2 == 0) {
299704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int i = 0; i < width; i += 2, current_uv_pointer += 2) {
300704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          int color = ((i / block_size) + (j / block_size)) %
301704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              kTestingColorNum;
302704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          current_uv_pointer[0] = testing_color_u_[color];
303704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          current_uv_pointer[1] = testing_color_v_[color];
304704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
305704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
306704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
307704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return image_pointer;
308704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
309704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
310704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a Red-Green-Blue inter-weaving chessboard-like
311704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // M420 testing image.
312704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // (Note: No interpolation is used.)
313704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The pattern looks like c0 c1 c2 c3 ...
314704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c1 c2 c3 c4 ...
315704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c2 c3 c4 c5 ...
316704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        ...............
317704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The size of each chrome block is (block_size) x (block_size).
3180c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* CreateFakeM420TestingImage(int height,
3190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int width,
3200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int block_size,
3210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      uint8_t*& m420_pointer) {
322704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; }
323704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
3240c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* image_pointer =
3250c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        new uint8_t[height * width +
3260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                    ((height + 1) / 2) * ((width + 1) / 2) * 2 + kAlignment];
327704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    m420_pointer = ALIGNP(image_pointer, kAlignment);
3280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_m420_pointer = m420_pointer;
329704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    for (int j = 0; j < height; ++j) {
330704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      for (int i = 0; i < width; ++i) {
331704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        int color = ((i / block_size) + (j / block_size)) %
332704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            kTestingColorNum;
333704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        *(current_m420_pointer++) = testing_color_y_[color];
334704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
335704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      if (j % 2 == 1) {
336704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int i = 0; i < width; i += 2, current_m420_pointer += 2) {
337704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          int color = ((i / block_size) + ((j - 1) / block_size)) %
338704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org              kTestingColorNum;
339704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          current_m420_pointer[0] = testing_color_u_[color];
340704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          current_m420_pointer[1] = testing_color_v_[color];
341704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
342704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
343704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
344704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return image_pointer;
345704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
346704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
347704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a Red-Green-Blue inter-weaving chessboard-like
348704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // ARGB/ABGR/RAW/BG24 testing image.
349704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The pattern looks like c0 c1 c2 c3 ...
350704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c1 c2 c3 c4 ...
351704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        c2 c3 c4 c5 ...
352704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  //                        ...............
353704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // The size of each chrome block is (block_size) x (block_size).
3540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* CreateFakeArgbTestingImage(int height,
3550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int width,
3560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      int block_size,
3570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      uint8_t*& argb_pointer,
3580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                      FourCC fourcc_type) {
359704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; }
3600c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* image_pointer = NULL;
361704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    if (fourcc_type == FOURCC_ABGR || fourcc_type == FOURCC_BGRA ||
362704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        fourcc_type == FOURCC_ARGB) {
3630c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      image_pointer = new uint8_t[height * width * 4 + kAlignment];
364704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    } else if (fourcc_type == FOURCC_RAW || fourcc_type == FOURCC_24BG) {
3650c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      image_pointer = new uint8_t[height * width * 3 + kAlignment];
366704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    } else {
367704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      LOG(LS_ERROR) << "Format " << static_cast<int>(fourcc_type)
368704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                    << " is not supported.";
369704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      return NULL;
370704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
371704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    argb_pointer = ALIGNP(image_pointer, kAlignment);
3720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* current_pointer = argb_pointer;
373704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    switch (fourcc_type) {
374704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_ARGB: {
375704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
376704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < width; ++i) {
377704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color = ((i / block_size) + (j / block_size)) %
378704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
379704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_b_[color];
380704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_g_[color];
381704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_r_[color];
382704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = 255;
383704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
384704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
385704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
386704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
387704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_ABGR: {
388704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
389704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < width; ++i) {
390704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color = ((i / block_size) + (j / block_size)) %
391704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
392704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_r_[color];
393704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_g_[color];
394704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_b_[color];
395704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = 255;
396704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
397704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
398704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
399704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
400704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_BGRA: {
401704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
402704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < width; ++i) {
403704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color = ((i / block_size) + (j / block_size)) %
404704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
405704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = 255;
406704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_r_[color];
407704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_g_[color];
408704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_b_[color];
409704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org           }
410704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
411704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
412704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
413704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_24BG: {
414704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
415704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < width; ++i) {
416704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color = ((i / block_size) + (j / block_size)) %
417704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
418704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_b_[color];
419704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_g_[color];
420704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_r_[color];
421704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
422704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
423704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
424704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
425704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      case FOURCC_RAW: {
426704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        for (int j = 0; j < height; ++j) {
427704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          for (int i = 0; i < width; ++i) {
428704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            int color = ((i / block_size) + (j / block_size)) %
429704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                kTestingColorNum;
430704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_r_[color];
431704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_g_[color];
432704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org            *(current_pointer++) = testing_color_b_[color];
433704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org          }
434704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        }
435704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        break;
436704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
437704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      default: {
438704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        LOG(LS_ERROR) << "Format " << static_cast<int>(fourcc_type)
439704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                      << " is not supported.";
440704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      }
441704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
442704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return image_pointer;
443704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
444704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
445704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Check if two memory chunks are equal.
446704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // (tolerate MSE errors within a threshold).
4470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  static bool IsMemoryEqual(const uint8_t* ibuf,
4480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            const uint8_t* obuf,
4490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            int osize,
4500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            double average_error) {
451704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    double sse = cricket::ComputeSumSquareError(ibuf, obuf, osize);
452704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    double error = sse / osize;  // Mean Squared Error.
453704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    double PSNR = cricket::ComputePSNR(sse, osize);
454704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    LOG(LS_INFO) << "Image MSE: "  << error << " Image PSNR: " << PSNR
455704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                 << " First Diff Byte: " << FindDiff(ibuf, obuf, osize);
456704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return (error < average_error);
457704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
458704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
459704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Returns the index of the first differing byte. Easier to debug than memcmp.
4600c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  static int FindDiff(const uint8_t* buf1, const uint8_t* buf2, int len) {
461704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    int i = 0;
462704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    while (i < len && buf1[i] == buf2[i]) {
463704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      i++;
464704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    }
465704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return (i < len) ? i : -1;
466704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
467704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
468704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Dump the result image (ARGB format).
4690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  void DumpArgbImage(const uint8_t* obuf, int width, int height) {
470704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    DumpPlanarArgbTestImage(GetTestName(), obuf, width, height);
471704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
472704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
473704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Dump the result image (YUV420 format).
4740c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  void DumpYuvImage(const uint8_t* obuf, int width, int height) {
475704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    DumpPlanarYuvTestImage(GetTestName(), obuf, width, height);
476704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
477704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
478704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  std::string GetTestName() {
479704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    const testing::TestInfo* const test_info =
480704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org        testing::UnitTest::GetInstance()->current_test_info();
481704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    std::string test_name(test_info->name());
482704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    return test_name;
483704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
484704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
485704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  bool dump_;
486704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int repeat_;
487704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
488704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Y, U, V and R, G, B channels of testing colors.
4890c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_y_;
4900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_u_;
4910c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_v_;
4920c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_r_;
4930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_g_;
4940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> testing_color_b_;
495704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org};
496704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
497704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_F(PlanarFunctionsTest, I420Copy) {
4980c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = nullptr;
4990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_pointer = nullptr;
5000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_pointer = nullptr;
501704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
502704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
503704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
504704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_size = kHeight * kWidth;
505704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
506704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 3;
507704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
5080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeYuvTestingImage(
5090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer,
5100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      v_pointer));
511704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image.
5120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output(
5130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment]);
5140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_output_pointer = ALIGNP(yuv_output.get(), kAlignment);
5150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_output_pointer = y_output_pointer + y_size;
5160c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_output_pointer = u_output_pointer + uv_size;
517704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
518704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
519704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::I420Copy(y_pointer, y_pitch,
520704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   u_pointer, u_pitch,
521704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   v_pointer, v_pitch,
522704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   y_output_pointer, y_pitch,
523704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   u_output_pointer, u_pitch,
524704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   v_output_pointer, v_pitch,
525704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                   kWidth, kHeight);
526704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
527704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
528704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Expect the copied frame to be exactly the same.
529704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_pointer,
530704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      I420_SIZE(kHeight, kWidth), 1.e-6));
531704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
532704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); }
533704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
534704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
535704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_F(PlanarFunctionsTest, I422ToI420) {
5360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = nullptr;
5370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_pointer = nullptr;
5380c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_pointer = nullptr;
539704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
540704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
541704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
542704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_size = kHeight * kWidth;
543704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
544704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 2;
545704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
5460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeYuvTestingImage(
5470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv422, y_pointer, u_pointer,
5480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      v_pointer));
549704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image.
5500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output(
5510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment]);
5520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_output_pointer = ALIGNP(yuv_output.get(), kAlignment);
5530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_output_pointer = y_output_pointer + y_size;
5540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_output_pointer = u_output_pointer + uv_size;
555704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate the expected output.
5560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_expected_pointer = nullptr;
5570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_expected_pointer = nullptr;
5580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_expected_pointer = nullptr;
5590c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output_expected(CreateFakeYuvTestingImage(
5600c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer,
5610c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      u_expected_pointer, v_expected_pointer));
562704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
563704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
564704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::I422ToI420(y_pointer, y_pitch,
565704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_pointer, u_pitch,
566704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_pointer, v_pitch,
567704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     y_output_pointer, y_pitch,
568704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_output_pointer, u_pitch,
569704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_output_pointer, v_pitch,
570704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     kWidth, kHeight);
571704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
572704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
573704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Compare the output frame with what is expected; expect exactly the same.
574704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: MSE should be set to a larger threshold if an odd block width
575704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // is used, since the conversion will be lossy.
576704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer,
577704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      I420_SIZE(kHeight, kWidth), 1.e-6));
578704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
579704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); }
580704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
581704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
582704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_P(PlanarFunctionsTest, M420ToI420) {
583704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Get the unalignment offset
584704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int unalignment = GetParam();
5850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* m420_pointer = NULL;
586704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
587704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int m420_pitch = kWidth;
588704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
589704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
590704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_size = kHeight * kWidth;
591704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
592704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 2;
593704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
5940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(
595704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      CreateFakeM420TestingImage(kHeight, kWidth, block_size, m420_pointer));
596704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image.
5970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output(
5980c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]);
5990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_output_pointer =
6000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      ALIGNP(yuv_output.get(), kAlignment) + unalignment;
6010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_output_pointer = y_output_pointer + y_size;
6020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_output_pointer = u_output_pointer + uv_size;
603704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate the expected output.
6040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_expected_pointer = nullptr;
6050c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_expected_pointer = nullptr;
6060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_expected_pointer = nullptr;
6070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output_expected(CreateFakeYuvTestingImage(
6080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer,
6090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      u_expected_pointer, v_expected_pointer));
610704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
611704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
612704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::M420ToI420(m420_pointer, m420_pitch,
613704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     y_output_pointer, y_pitch,
614704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_output_pointer, u_pitch,
615704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_output_pointer, v_pitch,
616704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     kWidth, kHeight);
617704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
618704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Compare the output frame with what is expected; expect exactly the same.
619704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: MSE should be set to a larger threshold if an odd block width
620704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // is used, since the conversion will be lossy.
621704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer,
622704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      I420_SIZE(kHeight, kWidth), 1.e-6));
623704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
624704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); }
625704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
626704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
627704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_P(PlanarFunctionsTest, NV12ToI420) {
628704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Get the unalignment offset
629704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int unalignment = GetParam();
6300c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = nullptr;
6310c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* uv_pointer = nullptr;
632704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
633704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_pitch = 2 * ((kWidth + 1) >> 1);
634704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
635704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
636704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_size = kHeight * kWidth;
637704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
638704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 2;
639704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
6400c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeNV12TestingImage(
6410c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, y_pointer, uv_pointer));
642704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image.
6430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output(
6440c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]);
6450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_output_pointer =
6460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      ALIGNP(yuv_output.get(), kAlignment) + unalignment;
6470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_output_pointer = y_output_pointer + y_size;
6480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_output_pointer = u_output_pointer + uv_size;
649704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate the expected output.
6500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_expected_pointer = nullptr;
6510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_expected_pointer = nullptr;
6520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_expected_pointer = nullptr;
6530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_output_expected(CreateFakeYuvTestingImage(
6540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer,
6550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      u_expected_pointer, v_expected_pointer));
656704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
657704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
658704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::NV12ToI420(y_pointer, y_pitch,
659704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     uv_pointer, uv_pitch,
660704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     y_output_pointer, y_pitch,
661704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_output_pointer, u_pitch,
662704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_output_pointer, v_pitch,
663704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     kWidth, kHeight);
664704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
665704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Compare the output frame with what is expected; expect exactly the same.
666704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: MSE should be set to a larger threshold if an odd block width
667704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // is used, since the conversion will be lossy.
668704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer,
669704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org      I420_SIZE(kHeight, kWidth), 1.e-6));
670704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
671704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); }
672704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
673704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
674704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// A common macro for testing converting YUY2/UYVY to I420.
6750c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström#define TEST_YUVTOI420(SRC_NAME, MSE, BLOCK_SIZE)                             \
6760c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  TEST_P(PlanarFunctionsTest, SRC_NAME##ToI420) {                             \
6770c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Get the unalignment offset.*/                                          \
6780c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int unalignment = GetParam();                                             \
6790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* yuv_pointer = nullptr;                                           \
6800c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int yuv_pitch = 2 * ((kWidth + 1) & ~1);                                  \
6810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int y_pitch = kWidth;                                                     \
6820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int u_pitch = (kWidth + 1) >> 1;                                          \
6830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int v_pitch = (kWidth + 1) >> 1;                                          \
6840c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int y_size = kHeight * kWidth;                                            \
6850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);                 \
6860c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int block_size = 2;                                                       \
6870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate a fake input image.*/                                         \
6880c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeInterleaveYuvTestingImage( \
6890c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        kHeight, kWidth, BLOCK_SIZE, yuv_pointer, FOURCC_##SRC_NAME));        \
6900c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Allocate space for the output image.*/                                 \
6910c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> yuv_output(                                    \
6920c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]);  \
6930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* y_output_pointer =                                               \
6940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        ALIGNP(yuv_output.get(), kAlignment) + unalignment;                   \
6950c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* u_output_pointer = y_output_pointer + y_size;                    \
6960c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* v_output_pointer = u_output_pointer + uv_size;                   \
6970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate the expected output.*/                                        \
6980c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* y_expected_pointer = nullptr;                                    \
6990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* u_expected_pointer = nullptr;                                    \
7000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* v_expected_pointer = nullptr;                                    \
7010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> yuv_output_expected(CreateFakeYuvTestingImage( \
7020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer, \
7030c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        u_expected_pointer, v_expected_pointer));                             \
7040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    for (int i = 0; i < repeat_; ++i) {                                       \
7050c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      libyuv::SRC_NAME##ToI420(yuv_pointer, yuv_pitch, y_output_pointer,      \
7060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               y_pitch, u_output_pointer, u_pitch,            \
7070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               v_output_pointer, v_pitch, kWidth, kHeight);   \
7080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                         \
7090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Compare the output frame with what is expected.*/                      \
7100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Note: MSE should be set to a larger threshold if an odd block width*/  \
7110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* is used, since the conversion will be lossy.*/                         \
7120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer,           \
7130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              I420_SIZE(kHeight, kWidth), MSE));              \
7140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    if (dump_) {                                                              \
7150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      DumpYuvImage(y_output_pointer, kWidth, kHeight);                        \
7160c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                         \
7170c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  }
718704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
719704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_P(PlanarFunctionsTest, YUV2ToI420)
720704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTOI420(YUY2, 1.e-6, 2);
721704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_P(PlanarFunctionsTest, UYVYToI420)
722704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTOI420(UYVY, 1.e-6, 2);
723704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
724704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// A common macro for testing converting I420 to ARGB, BGRA and ABGR.
7250c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström#define TEST_YUVTORGB(SRC_NAME, DST_NAME, JPG_TYPE, MSE, BLOCK_SIZE)           \
7260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  TEST_F(PlanarFunctionsTest, SRC_NAME##To##DST_NAME) {                        \
7270c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* y_pointer = nullptr;                                              \
7280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* u_pointer = nullptr;                                              \
7290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* v_pointer = nullptr;                                              \
7300c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* argb_expected_pointer = NULL;                                     \
7310c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int y_pitch = kWidth;                                                      \
7320c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int u_pitch = (kWidth + 1) >> 1;                                           \
7330c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int v_pitch = (kWidth + 1) >> 1;                                           \
7340c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate a fake input image.*/                                          \
7350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> yuv_input(                                      \
7360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        CreateFakeYuvTestingImage(kHeight, kWidth, BLOCK_SIZE, JPG_TYPE,       \
7370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                  y_pointer, u_pointer, v_pointer));           \
7380c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate the expected output.*/                                         \
7390c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> argb_expected(                                  \
7400c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        CreateFakeArgbTestingImage(kHeight, kWidth, BLOCK_SIZE,                \
7410c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                   argb_expected_pointer, FOURCC_##DST_NAME)); \
7420c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Allocate space for the output.*/                                        \
7430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> argb_output(                                    \
7440c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        new uint8_t[kHeight * kWidth * 4 + kAlignment]);                       \
7450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* argb_pointer = ALIGNP(argb_expected.get(), kAlignment);           \
7460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    for (int i = 0; i < repeat_; ++i) {                                        \
7470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      libyuv::SRC_NAME##To##DST_NAME(y_pointer, y_pitch, u_pointer, u_pitch,   \
7480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     v_pointer, v_pitch, argb_pointer,         \
7490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                     kWidth * 4, kWidth, kHeight);             \
7500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                          \
7510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer,             \
7520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              kHeight* kWidth * 4, MSE));                      \
7530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    if (dump_) {                                                               \
7540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      DumpArgbImage(argb_pointer, kWidth, kHeight);                            \
7550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                          \
7560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  }
757704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
758704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_F(PlanarFunctionsTest, I420ToARGB)
759704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTORGB(I420, ARGB, libyuv::kJpegYuv420, 3., 2);
760704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_F(PlanarFunctionsTest, I420ToABGR)
761704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTORGB(I420, ABGR, libyuv::kJpegYuv420, 3., 2);
762704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_F(PlanarFunctionsTest, I420ToBGRA)
763704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTORGB(I420, BGRA, libyuv::kJpegYuv420, 3., 2);
764704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_F(PlanarFunctionsTest, I422ToARGB)
765704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTORGB(I422, ARGB, libyuv::kJpegYuv422, 3., 2);
766704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// TEST_F(PlanarFunctionsTest, I444ToARGB)
767704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_YUVTORGB(I444, ARGB, libyuv::kJpegYuv444, 3., 3);
768704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Note: an empirical MSE tolerance 3.0 is used here for the probable
7690c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström// error from float-to-uint8_t type conversion.
770704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
771704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_F(PlanarFunctionsTest, I400ToARGB_Reference) {
7720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = nullptr;
7730c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_pointer = nullptr;
7740c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_pointer = nullptr;
775704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
776704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
777704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
778704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 3;
779704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
7800c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeYuvTestingImage(
7810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer,
7820c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      v_pointer));
783704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // As the comparison standard, we convert a grayscale image (by setting both
784704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // U and V channels to be 128) using an I420 converter.
785704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
786704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
7870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> uv(new uint8_t[uv_size + kAlignment]);
788704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  u_pointer = v_pointer = ALIGNP(uv.get(), kAlignment);
789704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  memset(u_pointer, 128, uv_size);
790704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
791704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image and generate the expected output.
7920c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> argb_expected(
7930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[kHeight * kWidth * 4 + kAlignment]);
7940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> argb_output(
7950c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[kHeight * kWidth * 4 + kAlignment]);
7960c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* argb_expected_pointer = ALIGNP(argb_expected.get(), kAlignment);
7970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* argb_pointer = ALIGNP(argb_output.get(), kAlignment);
798704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
799704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::I420ToARGB(y_pointer, y_pitch,
800704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_pointer, u_pitch,
801704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_pointer, v_pitch,
802704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     argb_expected_pointer, kWidth * 4,
803704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     kWidth, kHeight);
804704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
805704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    libyuv::I400ToARGB_Reference(y_pointer, y_pitch,
806704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                                 argb_pointer, kWidth * 4,
807704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                                 kWidth, kHeight);
808704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
809704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
810704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: I420ToARGB and I400ToARGB_Reference should produce identical results.
811704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer,
812704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                            kHeight * kWidth * 4, 2.));
813704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); }
814704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
815704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
816704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_P(PlanarFunctionsTest, I400ToARGB) {
817704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Get the unalignment offset
818704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int unalignment = GetParam();
8190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = nullptr;
8200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* u_pointer = nullptr;
8210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* v_pointer = nullptr;
822704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int y_pitch = kWidth;
823704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int u_pitch = (kWidth + 1) >> 1;
824704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int v_pitch = (kWidth + 1) >> 1;
825704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 3;
826704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
8270c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_input(CreateFakeYuvTestingImage(
8280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer,
8290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      v_pointer));
830704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // As the comparison standard, we convert a grayscale image (by setting both
831704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // U and V channels to be 128) using an I420 converter.
832704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1);
833704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
834704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // 1 byte extra if in the unaligned mode.
8350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> uv(new uint8_t[uv_size * 2 + kAlignment]);
836704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  u_pointer = ALIGNP(uv.get(), kAlignment);
837704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  v_pointer = u_pointer + uv_size;
838704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  memset(u_pointer, 128, uv_size);
839704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  memset(v_pointer, 128, uv_size);
840704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
841704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the output image and generate the expected output.
8420c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> argb_expected(
8430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[kHeight * kWidth * 4 + kAlignment]);
844704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // 1 byte extra if in the misalinged mode.
8450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> argb_output(
8460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[kHeight * kWidth * 4 + kAlignment + unalignment]);
8470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* argb_expected_pointer = ALIGNP(argb_expected.get(), kAlignment);
8480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* argb_pointer = ALIGNP(argb_output.get(), kAlignment) + unalignment;
849704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
850704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  libyuv::I420ToARGB(y_pointer, y_pitch,
851704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     u_pointer, u_pitch,
852704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     v_pointer, v_pitch,
853704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     argb_expected_pointer, kWidth * 4,
854704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                     kWidth, kHeight);
855704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
856704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    libyuv::I400ToARGB(y_pointer, y_pitch,
857704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                       argb_pointer, kWidth * 4,
858704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                       kWidth, kHeight);
859704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
860704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
861704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: current I400ToARGB uses an approximate method,
862704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // so the error tolerance is larger here.
863704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer,
864704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                            kHeight * kWidth * 4, 64.0));
865704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); }
866704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
867704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
868704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_P(PlanarFunctionsTest, ARGBToI400) {
869704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Get the unalignment offset
870704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int unalignment = GetParam();
871704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Create a fake ARGB input image.
8720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_pointer = NULL, * u_pointer = NULL, * v_pointer = NULL;
8730c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* argb_pointer = NULL;
874704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  int block_size = 3;
875704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate a fake input image.
8760c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> argb_input(CreateFakeArgbTestingImage(
8770c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, argb_pointer, FOURCC_ARGB));
878704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Generate the expected output. Only Y channel is used
8790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> yuv_expected(CreateFakeYuvTestingImage(
8800c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer,
8810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      v_pointer));
882704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Allocate space for the Y output.
8830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  rtc::scoped_ptr<uint8_t[]> y_output(
8840c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      new uint8_t[kHeight * kWidth + kAlignment + unalignment]);
8850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* y_output_pointer = ALIGNP(y_output.get(), kAlignment) + unalignment;
886704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
887704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  for (int i = 0; i < repeat_; ++i) {
888704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    libyuv::ARGBToI400(argb_pointer, kWidth * 4, y_output_pointer, kWidth,
889704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                       kWidth, kHeight);
890704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  }
891704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Check if the output matches the input Y channel.
892704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  // Note: an empirical MSE tolerance 2.0 is used here for the probable
8930c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  // error from float-to-uint8_t type conversion.
894704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_pointer,
895704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org                            kHeight * kWidth, 2.));
896704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org  if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); }
897704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}
898704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
899704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// A common macro for testing converting RAW, BG24, BGRA, and ABGR
900704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// to ARGB.
9010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström#define TEST_ARGB(SRC_NAME, FC_ID, BPP, BLOCK_SIZE)                            \
9020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  TEST_P(PlanarFunctionsTest, SRC_NAME##ToARGB) {                              \
9030c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    int unalignment = GetParam(); /* Get the unalignment offset.*/             \
9040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* argb_expected_pointer = NULL, * src_pointer = NULL;               \
9050c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate a fake input image.*/                                          \
9060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> src_input(CreateFakeArgbTestingImage(           \
9070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        kHeight, kWidth, BLOCK_SIZE, src_pointer, FOURCC_##FC_ID));            \
9080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Generate the expected output.*/                                         \
9090c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> argb_expected(CreateFakeArgbTestingImage(       \
9100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        kHeight, kWidth, BLOCK_SIZE, argb_expected_pointer, FOURCC_ARGB));     \
9110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Allocate space for the output; 1 byte extra if in the unaligned mode.*/ \
9120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    rtc::scoped_ptr<uint8_t[]> argb_output(                                    \
9130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        new uint8_t[kHeight * kWidth * 4 + kAlignment + unalignment]);         \
9140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint8_t* argb_pointer =                                                    \
9150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        ALIGNP(argb_output.get(), kAlignment) + unalignment;                   \
9160c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    for (int i = 0; i < repeat_; ++i) {                                        \
9170c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      libyuv::SRC_NAME##ToARGB(src_pointer, kWidth*(BPP), argb_pointer,        \
9180c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               kWidth * 4, kWidth, kHeight);                   \
9190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                          \
9200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    /* Compare the result; expect identical.*/                                 \
9210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer,             \
9220c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              kHeight* kWidth * 4, 1.e-6));                    \
9230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    if (dump_) {                                                               \
9240c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      DumpArgbImage(argb_pointer, kWidth, kHeight);                            \
9250c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    }                                                                          \
9260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  }
927704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
928704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_ARGB(RAW, RAW, 3, 3);    // TEST_P(PlanarFunctionsTest, RAWToARGB)
929704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_ARGB(BG24, 24BG, 3, 3);  // TEST_P(PlanarFunctionsTest, BG24ToARGB)
930704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_ARGB(ABGR, ABGR, 4, 3);  // TEST_P(PlanarFunctionsTest, ABGRToARGB)
931704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgTEST_ARGB(BGRA, BGRA, 4, 3);  // TEST_P(PlanarFunctionsTest, BGRAToARGB)
932704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
933704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Parameter Test: The parameter is the unalignment offset.
934704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Aligned data for testing assembly versions.
935704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgINSTANTIATE_TEST_CASE_P(PlanarFunctionsAligned, PlanarFunctionsTest,
936704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    ::testing::Values(0));
937704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
938704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org// Purposely unalign the output argb pointer to test slow path (C version).
939704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.orgINSTANTIATE_TEST_CASE_P(PlanarFunctionsMisaligned, PlanarFunctionsTest,
940704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org    ::testing::Values(1));
941704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org
942704bf9ebec9c9425e1898f6c3f15eff685175b23henrike@webrtc.org}  // namespace cricket
943