blob: 092e669589ad9f0b57ea97fef24a8e0ef2801fa4 [file] [log] [blame]
John Koleszarb9180fc2012-05-16 15:27:00 -07001/*
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
John Koleszarb9180fc2012-05-16 15:27:00 -07003 *
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*/
Deb Mukherjee01cafaa2013-01-15 06:43:35 -080011
Frank Galligan89df6d12015-03-09 15:52:29 -070012#include <string>
13
Jingning Han097d59c2015-07-29 14:51:36 -070014#include "third_party/googletest/src/include/gtest/gtest.h"
15
Yaowu Xuf883b422016-08-30 14:01:10 -070016#include "./aom_config.h"
Yaowu Xuc27fc142016-08-22 16:08:15 -070017#include "aom_ports/mem.h"
John Koleszar706cafe2013-01-18 11:51:12 -080018#include "test/codec_factory.h"
Yaowu Xuc953aea2012-08-30 13:43:15 -070019#include "test/decode_test_driver.h"
Jingning Han097d59c2015-07-29 14:51:36 -070020#include "test/encode_test_driver.h"
James Zerneebb6482012-11-27 13:08:05 -080021#include "test/register_state_check.h"
John Koleszarb9180fc2012-05-16 15:27:00 -070022#include "test/video_source.h"
John Koleszarb9180fc2012-05-16 15:27:00 -070023
Yaowu Xuc27fc142016-08-22 16:08:15 -070024namespace libaom_test {
Yunqing Wang36664782014-12-12 14:34:30 -080025void Encoder::InitEncoder(VideoSource *video) {
Yaowu Xuf883b422016-08-30 14:01:10 -070026 aom_codec_err_t res;
27 const aom_image_t *img = video->img();
Yunqing Wang36664782014-12-12 14:34:30 -080028
29 if (video->img() && !encoder_.priv) {
30 cfg_.g_w = img->d_w;
31 cfg_.g_h = img->d_h;
32 cfg_.g_timebase = video->timebase();
33 cfg_.rc_twopass_stats_in = stats_->buf();
Frank Galligan89df6d12015-03-09 15:52:29 -070034
Yaowu Xuf883b422016-08-30 14:01:10 -070035 res = aom_codec_enc_init(&encoder_, CodecInterface(), &cfg_, init_flags_);
36 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
Frank Galligan89df6d12015-03-09 15:52:29 -070037
Yaowu Xuf883b422016-08-30 14:01:10 -070038#if CONFIG_AV1_ENCODER
39 if (CodecInterface() == &aom_codec_av1_cx_algo) {
40// Default to 1 tile column for AV1. With CONFIG_EXT_TILE, the
clang-format3a826f12016-08-11 17:46:05 -070041// default is already the largest possible tile size
Geza Lore67a2ff72016-05-03 11:53:55 +010042#if !CONFIG_EXT_TILE
Jingning Han41be09a2015-08-19 14:13:18 -070043 const int log2_tile_columns = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -070044 res = aom_codec_control_(&encoder_, AV1E_SET_TILE_COLUMNS,
Jingning Han41be09a2015-08-19 14:13:18 -070045 log2_tile_columns);
Yaowu Xuf883b422016-08-30 14:01:10 -070046 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
Geza Lore67a2ff72016-05-03 11:53:55 +010047#endif // !CONFIG_EXT_TILE
Jingning Han41be09a2015-08-19 14:13:18 -070048 } else
49#endif
Yaowu Xu0924bcd2016-05-20 11:33:07 -070050 {
Frank Galligan89df6d12015-03-09 15:52:29 -070051 }
Yunqing Wang36664782014-12-12 14:34:30 -080052 }
53}
54
Adrian Grange4206c6d2012-10-02 11:03:09 -070055void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) {
John Koleszarb9180fc2012-05-16 15:27:00 -070056 if (video->img())
Adrian Grange4206c6d2012-10-02 11:03:09 -070057 EncodeFrameInternal(*video, frame_flags);
John Koleszarb9180fc2012-05-16 15:27:00 -070058 else
59 Flush();
60
61 // Handle twopass stats
62 CxDataIterator iter = GetCxData();
63
Yaowu Xuf883b422016-08-30 14:01:10 -070064 while (const aom_codec_cx_pkt_t *pkt = iter.Next()) {
65 if (pkt->kind != AOM_CODEC_STATS_PKT) continue;
John Koleszarb9180fc2012-05-16 15:27:00 -070066
67 stats_->Append(*pkt);
68 }
69}
70
71void Encoder::EncodeFrameInternal(const VideoSource &video,
Adrian Grange4206c6d2012-10-02 11:03:09 -070072 const unsigned long frame_flags) {
Yaowu Xuf883b422016-08-30 14:01:10 -070073 aom_codec_err_t res;
74 const aom_image_t *img = video.img();
John Koleszarb9180fc2012-05-16 15:27:00 -070075
John Koleszarb9180fc2012-05-16 15:27:00 -070076 // Handle frame resizing
77 if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) {
78 cfg_.g_w = img->d_w;
79 cfg_.g_h = img->d_h;
Yaowu Xuf883b422016-08-30 14:01:10 -070080 res = aom_codec_enc_config_set(&encoder_, &cfg_);
81 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
John Koleszarb9180fc2012-05-16 15:27:00 -070082 }
83
84 // Encode the frame
Yaowu Xuf883b422016-08-30 14:01:10 -070085 API_REGISTER_STATE_CHECK(res = aom_codec_encode(&encoder_, img, video.pts(),
clang-format3a826f12016-08-11 17:46:05 -070086 video.duration(), frame_flags,
87 deadline_));
Yaowu Xuf883b422016-08-30 14:01:10 -070088 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
John Koleszarb9180fc2012-05-16 15:27:00 -070089}
90
91void Encoder::Flush() {
Yaowu Xuf883b422016-08-30 14:01:10 -070092 const aom_codec_err_t res =
93 aom_codec_encode(&encoder_, NULL, 0, 0, 0, deadline_);
Deb Mukherjeebdbaa5b2014-07-18 03:06:07 -070094 if (!encoder_.priv)
Yaowu Xuf883b422016-08-30 14:01:10 -070095 ASSERT_EQ(AOM_CODEC_ERROR, res) << EncoderError();
Deb Mukherjeebdbaa5b2014-07-18 03:06:07 -070096 else
Yaowu Xuf883b422016-08-30 14:01:10 -070097 ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
John Koleszarb9180fc2012-05-16 15:27:00 -070098}
99
John Koleszar706cafe2013-01-18 11:51:12 -0800100void EncoderTest::InitializeConfig() {
Yaowu Xuf883b422016-08-30 14:01:10 -0700101 const aom_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0);
102 dec_cfg_ = aom_codec_dec_cfg_t();
103 ASSERT_EQ(AOM_CODEC_OK, res);
John Koleszar706cafe2013-01-18 11:51:12 -0800104}
105
John Koleszarb9180fc2012-05-16 15:27:00 -0700106void EncoderTest::SetMode(TestMode mode) {
107 switch (mode) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700108 case kRealTime: deadline_ = AOM_DL_REALTIME; break;
John Koleszarb9180fc2012-05-16 15:27:00 -0700109
110 case kOnePassGood:
Yaowu Xuf883b422016-08-30 14:01:10 -0700111 case kTwoPassGood: deadline_ = AOM_DL_GOOD_QUALITY; break;
John Koleszarb9180fc2012-05-16 15:27:00 -0700112
113 case kOnePassBest:
Yaowu Xuf883b422016-08-30 14:01:10 -0700114 case kTwoPassBest: deadline_ = AOM_DL_BEST_QUALITY; break;
John Koleszarb9180fc2012-05-16 15:27:00 -0700115
clang-format3a826f12016-08-11 17:46:05 -0700116 default: ASSERT_TRUE(false) << "Unexpected mode " << mode;
John Koleszarb9180fc2012-05-16 15:27:00 -0700117 }
118
119 if (mode == kTwoPassGood || mode == kTwoPassBest)
120 passes_ = 2;
121 else
122 passes_ = 1;
123}
Geza Loree0dcab92016-05-09 13:19:34 +0100124
125static bool compare_plane(const uint8_t *const buf1, const int stride1,
126 const uint8_t *const buf2, const int stride2,
clang-format3a826f12016-08-11 17:46:05 -0700127 const int w, const int h, int *const mismatch_row,
128 int *const mismatch_col, int *const mismatch_pix1,
Geza Loree0dcab92016-05-09 13:19:34 +0100129 int *const mismatch_pix2) {
130 int r, c;
131
132 for (r = 0; r < h; ++r) {
133 for (c = 0; c < w; ++c) {
134 const int pix1 = buf1[r * stride1 + c];
135 const int pix2 = buf2[r * stride2 + c];
136
137 if (pix1 != pix2) {
clang-format3a826f12016-08-11 17:46:05 -0700138 if (mismatch_row != NULL) *mismatch_row = r;
139 if (mismatch_col != NULL) *mismatch_col = c;
140 if (mismatch_pix1 != NULL) *mismatch_pix1 = pix1;
141 if (mismatch_pix2 != NULL) *mismatch_pix2 = pix2;
Geza Loree0dcab92016-05-09 13:19:34 +0100142 return false;
143 }
144 }
145 }
146
147 return true;
148}
149
Yaowu Xuc953aea2012-08-30 13:43:15 -0700150// The function should return "true" most of the time, therefore no early
151// break-out is implemented within the match checking process.
Yaowu Xuf883b422016-08-30 14:01:10 -0700152static bool compare_img(const aom_image_t *img1, const aom_image_t *img2,
clang-format3a826f12016-08-11 17:46:05 -0700153 int *const mismatch_row, int *const mismatch_col,
154 int *const mismatch_plane, int *const mismatch_pix1,
Geza Loree0dcab92016-05-09 13:19:34 +0100155 int *const mismatch_pix2) {
Geza Loree0dcab92016-05-09 13:19:34 +0100156 const unsigned int w_y = img1->d_w;
157 const unsigned int h_y = img1->d_h;
Pascal Massiminoe5fb2d42016-07-11 06:17:17 -0700158 const unsigned int w_uv = ROUND_POWER_OF_TWO(w_y, img1->x_chroma_shift);
159 const unsigned int h_uv = ROUND_POWER_OF_TWO(h_y, img1->y_chroma_shift);
Geza Loree0dcab92016-05-09 13:19:34 +0100160
clang-format3a826f12016-08-11 17:46:05 -0700161 if (img1->fmt != img2->fmt || img1->cs != img2->cs ||
162 img1->d_w != img2->d_w || img1->d_h != img2->d_h) {
163 if (mismatch_row != NULL) *mismatch_row = -1;
164 if (mismatch_col != NULL) *mismatch_col = -1;
Geza Loree0dcab92016-05-09 13:19:34 +0100165 return false;
166 }
167
Yaowu Xuf883b422016-08-30 14:01:10 -0700168 if (!compare_plane(img1->planes[AOM_PLANE_Y], img1->stride[AOM_PLANE_Y],
169 img2->planes[AOM_PLANE_Y], img2->stride[AOM_PLANE_Y], w_y,
clang-format3a826f12016-08-11 17:46:05 -0700170 h_y, mismatch_row, mismatch_col, mismatch_pix1,
171 mismatch_pix2)) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700172 if (mismatch_plane != NULL) *mismatch_plane = AOM_PLANE_Y;
Geza Loree0dcab92016-05-09 13:19:34 +0100173 return false;
174 }
175
Yaowu Xuf883b422016-08-30 14:01:10 -0700176 if (!compare_plane(img1->planes[AOM_PLANE_U], img1->stride[AOM_PLANE_U],
177 img2->planes[AOM_PLANE_U], img2->stride[AOM_PLANE_U], w_uv,
clang-format3a826f12016-08-11 17:46:05 -0700178 h_uv, mismatch_row, mismatch_col, mismatch_pix1,
179 mismatch_pix2)) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700180 if (mismatch_plane != NULL) *mismatch_plane = AOM_PLANE_U;
Geza Loree0dcab92016-05-09 13:19:34 +0100181 return false;
182 }
183
Yaowu Xuf883b422016-08-30 14:01:10 -0700184 if (!compare_plane(img1->planes[AOM_PLANE_V], img1->stride[AOM_PLANE_V],
185 img2->planes[AOM_PLANE_V], img2->stride[AOM_PLANE_V], w_uv,
clang-format3a826f12016-08-11 17:46:05 -0700186 h_uv, mismatch_row, mismatch_col, mismatch_pix1,
187 mismatch_pix2)) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700188 if (mismatch_plane != NULL) *mismatch_plane = AOM_PLANE_U;
Geza Loree0dcab92016-05-09 13:19:34 +0100189 return false;
190 }
191
192 return true;
Yaowu Xuc953aea2012-08-30 13:43:15 -0700193}
John Koleszarb9180fc2012-05-16 15:27:00 -0700194
Yaowu Xuf883b422016-08-30 14:01:10 -0700195void EncoderTest::MismatchHook(const aom_image_t *img_enc,
196 const aom_image_t *img_dec) {
Geza Lore7de2ba32016-06-19 21:35:01 +0100197 int mismatch_row = 0;
198 int mismatch_col = 0;
199 int mismatch_plane = 0;
200 int mismatch_pix_enc = 0;
201 int mismatch_pix_dec = 0;
Geza Loree0dcab92016-05-09 13:19:34 +0100202
clang-format3a826f12016-08-11 17:46:05 -0700203 ASSERT_FALSE(compare_img(img_enc, img_dec, &mismatch_row, &mismatch_col,
204 &mismatch_plane, &mismatch_pix_enc,
Geza Loree0dcab92016-05-09 13:19:34 +0100205 &mismatch_pix_dec));
206
clang-format3a826f12016-08-11 17:46:05 -0700207 GTEST_FAIL() << "Encode/Decode mismatch found:" << std::endl
208 << " pixel value enc/dec: " << mismatch_pix_enc << "/"
209 << mismatch_pix_dec << std::endl
210 << " plane: " << mismatch_plane << std::endl
211 << " row/col: " << mismatch_row << "/"
212 << mismatch_col << std::endl;
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800213}
214
John Koleszarb9180fc2012-05-16 15:27:00 -0700215void EncoderTest::RunLoop(VideoSource *video) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700216 aom_codec_dec_cfg_t dec_cfg = aom_codec_dec_cfg_t();
hkuang93536072014-11-20 15:39:56 -0800217
Adrian Grange30f58b52012-10-02 09:36:41 -0700218 stats_.Reset();
219
Ronald S. Bultjee189edf2013-03-01 12:43:10 -0800220 ASSERT_TRUE(passes_ == 1 || passes_ == 2);
John Koleszarb9180fc2012-05-16 15:27:00 -0700221 for (unsigned int pass = 0; pass < passes_; pass++) {
James Zern51ebb9a2012-08-08 14:16:08 -0700222 last_pts_ = 0;
223
John Koleszarb9180fc2012-05-16 15:27:00 -0700224 if (passes_ == 1)
Yaowu Xuf883b422016-08-30 14:01:10 -0700225 cfg_.g_pass = AOM_RC_ONE_PASS;
John Koleszarb9180fc2012-05-16 15:27:00 -0700226 else if (pass == 0)
Yaowu Xuf883b422016-08-30 14:01:10 -0700227 cfg_.g_pass = AOM_RC_FIRST_PASS;
John Koleszarb9180fc2012-05-16 15:27:00 -0700228 else
Yaowu Xuf883b422016-08-30 14:01:10 -0700229 cfg_.g_pass = AOM_RC_LAST_PASS;
John Koleszarb9180fc2012-05-16 15:27:00 -0700230
231 BeginPassHook(pass);
Alex Converse1c1bc942016-07-21 11:36:41 -0700232 testing::internal::scoped_ptr<Encoder> encoder(
233 codec_->CreateEncoder(cfg_, deadline_, init_flags_, &stats_));
234 ASSERT_TRUE(encoder.get() != NULL);
hkuang93536072014-11-20 15:39:56 -0800235
Alex Converse1c1bc942016-07-21 11:36:41 -0700236 ASSERT_NO_FATAL_FAILURE(video->Begin());
Yunqing Wang36664782014-12-12 14:34:30 -0800237 encoder->InitEncoder(video);
James Zernd1ff1e92015-08-27 16:05:52 -0700238 ASSERT_FALSE(::testing::Test::HasFatalFailure());
Yunqing Wang36664782014-12-12 14:34:30 -0800239
hkuang93536072014-11-20 15:39:56 -0800240 unsigned long dec_init_flags = 0; // NOLINT
241 // Use fragment decoder if encoder outputs partitions.
242 // NOTE: fragment decoder and partition encoder are only supported by VP8.
Yaowu Xuf883b422016-08-30 14:01:10 -0700243 if (init_flags_ & AOM_CODEC_USE_OUTPUT_PARTITION)
244 dec_init_flags |= AOM_CODEC_USE_INPUT_FRAGMENTS;
Alex Converse1c1bc942016-07-21 11:36:41 -0700245 testing::internal::scoped_ptr<Decoder> decoder(
246 codec_->CreateDecoder(dec_cfg, dec_init_flags, 0));
Yaowu Xuf883b422016-08-30 14:01:10 -0700247#if CONFIG_AV1 && CONFIG_EXT_TILE
248 if (decoder->IsAV1()) {
Yunqing Wang8e5e3382016-05-05 16:42:57 -0700249 // Set dec_cfg.tile_row = -1 and dec_cfg.tile_col = -1 so that the whole
250 // frame is decoded.
Yaowu Xuf883b422016-08-30 14:01:10 -0700251 decoder->Control(AV1_SET_DECODE_TILE_ROW, -1);
252 decoder->Control(AV1_SET_DECODE_TILE_COL, -1);
Yunqing Wang8e5e3382016-05-05 16:42:57 -0700253 }
254#endif
255
John Koleszarb9180fc2012-05-16 15:27:00 -0700256 bool again;
Yunqing Wang36664782014-12-12 14:34:30 -0800257 for (again = true; again; video->Next()) {
Deb Mukherjee0d8723f2013-08-19 14:16:26 -0700258 again = (video->img() != NULL);
John Koleszarb9180fc2012-05-16 15:27:00 -0700259
260 PreEncodeFrameHook(video);
Alex Converse1c1bc942016-07-21 11:36:41 -0700261 PreEncodeFrameHook(video, encoder.get());
John Koleszar706cafe2013-01-18 11:51:12 -0800262 encoder->EncodeFrame(video, frame_flags_);
John Koleszarb9180fc2012-05-16 15:27:00 -0700263
John Koleszar706cafe2013-01-18 11:51:12 -0800264 CxDataIterator iter = encoder->GetCxData();
John Koleszarb9180fc2012-05-16 15:27:00 -0700265
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800266 bool has_cxdata = false;
267 bool has_dxdata = false;
Yaowu Xuf883b422016-08-30 14:01:10 -0700268 while (const aom_codec_cx_pkt_t *pkt = iter.Next()) {
John Koleszar522d4bf2013-03-05 12:23:34 -0800269 pkt = MutateEncoderOutputHook(pkt);
John Koleszarb9180fc2012-05-16 15:27:00 -0700270 again = true;
Adrian Grangee6109db2012-10-02 11:27:29 -0700271 switch (pkt->kind) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700272 case AOM_CODEC_CX_FRAME_PKT:
Adrian Grangee6109db2012-10-02 11:27:29 -0700273 has_cxdata = true;
Alex Converse1c1bc942016-07-21 11:36:41 -0700274 if (decoder.get() != NULL && DoDecode()) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700275 aom_codec_err_t res_dec = decoder->DecodeFrame(
clang-format3a826f12016-08-11 17:46:05 -0700276 (const uint8_t *)pkt->data.frame.buf, pkt->data.frame.sz);
Jim Bankoski943e4322014-07-17 06:31:50 -0700277
Urvang Joshid71a2312016-07-14 12:33:48 -0700278 if (!HandleDecodeResult(res_dec, decoder.get())) break;
Jim Bankoski943e4322014-07-17 06:31:50 -0700279
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800280 has_dxdata = true;
281 }
Adrian Grangee6109db2012-10-02 11:27:29 -0700282 ASSERT_GE(pkt->data.frame.pts, last_pts_);
283 last_pts_ = pkt->data.frame.pts;
284 FramePktHook(pkt);
285 break;
286
Yaowu Xuf883b422016-08-30 14:01:10 -0700287 case AOM_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
Adrian Grangee6109db2012-10-02 11:27:29 -0700288
clang-format3a826f12016-08-11 17:46:05 -0700289 default: break;
Adrian Grangee6109db2012-10-02 11:27:29 -0700290 }
John Koleszarb9180fc2012-05-16 15:27:00 -0700291 }
292
hkuang93536072014-11-20 15:39:56 -0800293 // Flush the decoder when there are no more fragments.
Yaowu Xuf883b422016-08-30 14:01:10 -0700294 if ((init_flags_ & AOM_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) {
295 const aom_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
Urvang Joshid71a2312016-07-14 12:33:48 -0700296 if (!HandleDecodeResult(res_dec, decoder.get())) break;
hkuang93536072014-11-20 15:39:56 -0800297 }
298
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800299 if (has_dxdata && has_cxdata) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700300 const aom_image_t *img_enc = encoder->GetPreviewFrame();
John Koleszar706cafe2013-01-18 11:51:12 -0800301 DxDataIterator dec_iter = decoder->GetDxData();
Yaowu Xuf883b422016-08-30 14:01:10 -0700302 const aom_image_t *img_dec = dec_iter.Next();
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800303 if (img_enc && img_dec) {
clang-format3a826f12016-08-11 17:46:05 -0700304 const bool res =
305 compare_img(img_enc, img_dec, NULL, NULL, NULL, NULL, NULL);
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800306 if (!res) { // Mismatch
307 MismatchHook(img_enc, img_dec);
308 }
Yaowu Xuc953aea2012-08-30 13:43:15 -0700309 }
clang-format3a826f12016-08-11 17:46:05 -0700310 if (img_dec) DecompressedFrameHook(*img_dec, video->pts());
Yaowu Xuc953aea2012-08-30 13:43:15 -0700311 }
clang-format3a826f12016-08-11 17:46:05 -0700312 if (!Continue()) break;
John Koleszarb9180fc2012-05-16 15:27:00 -0700313 }
314
315 EndPassHook();
316
clang-format3a826f12016-08-11 17:46:05 -0700317 if (!Continue()) break;
John Koleszarb9180fc2012-05-16 15:27:00 -0700318 }
319}
Deb Mukherjee01cafaa2013-01-15 06:43:35 -0800320
Yaowu Xuc27fc142016-08-22 16:08:15 -0700321} // namespace libaom_test