1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan * 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Use of this source code is governed by a BSD-style license 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * that can be found in the LICENSE file in the root of the source 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan * tree. An additional intellectual property rights grant can be found 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in the file PATENTS. All contributing project authors may 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan * be found in the AUTHORS file in the root of the source tree. 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string> 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/googletest/src/include/gtest/gtest.h" 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/codec_factory.h" 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/decode_test_driver.h" 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/md5_helper.h" 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/webm_video_source.h" 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vp9/decoder/vp9_thread.h" 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan 20233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace { 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan 22233d2500723e5594f3e7c70896ffeeef32b9c950ywanusing std::string; 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan 24233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass VP9WorkerThreadTest : public ::testing::TestWithParam<bool> { 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan protected: 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan virtual ~VP9WorkerThreadTest() {} 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan virtual void SetUp() { 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_init(&worker_); 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan virtual void TearDown() { 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_end(&worker_); 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan VP9Worker worker_; 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan 38233d2500723e5594f3e7c70896ffeeef32b9c950ywanint ThreadHook(void* data, void* return_value) { 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan int* const hook_data = reinterpret_cast<int*>(data); 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan *hook_data = 5; 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan return *reinterpret_cast<int*>(return_value); 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan 44233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_P(VP9WorkerThreadTest, HookSuccess) { 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op. 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int i = 0; i < 2; ++i) { 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_reset(&worker_), 0); 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan int hook_data = 0; 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan int return_value = 1; // return successfully from the hook 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.hook = ThreadHook; 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.data1 = &hook_data; 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.data2 = &return_value; 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan const bool synchronous = GetParam(); 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (synchronous) { 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_execute(&worker_); 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_launch(&worker_); 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_sync(&worker_), 0); 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_FALSE(worker_.had_error); 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_EQ(5, hook_data); 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op. 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan 70233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST_P(VP9WorkerThreadTest, HookFailure) { 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_reset(&worker_), 0); 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan int hook_data = 0; 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan int return_value = 0; // return failure from the hook 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.hook = ThreadHook; 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.data1 = &hook_data; 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan worker_.data2 = &return_value; 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan const bool synchronous = GetParam(); 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (synchronous) { 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_execute(&worker_); 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_launch(&worker_); 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_FALSE(vp9_worker_sync(&worker_)); 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_EQ(1, worker_.had_error); 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Ensure _reset() clears the error and _launch() can be called again. 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan return_value = 1; 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_reset(&worker_), 0); 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_FALSE(worker_.had_error); 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan vp9_worker_launch(&worker_); 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_NE(vp9_worker_sync(&worker_), 0); 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_FALSE(worker_.had_error); 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ----------------------------------------------------------------------------- 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Multi-threaded decode tests 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames. 101233d2500723e5594f3e7c70896ffeeef32b9c950ywanstring DecodeFile(const string& filename, int num_threads) { 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan libvpx_test::WebMVideoSource video(filename); 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan video.Init(); 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_dec_cfg_t cfg = {0}; 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg.threads = num_threads; 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan libvpx_test::VP9Decoder decoder(cfg, 0); 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan libvpx_test::MD5 md5; 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (video.Begin(); video.cxdata(); video.Next()) { 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_codec_err_t res = 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan decoder.DecodeFrame(video.cxdata(), video.frame_size()); 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (res != VPX_CODEC_OK) { 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan libvpx_test::DxDataIterator dec_iter = decoder.GetDxData(); 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img = NULL; 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Get decompressed data 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan while ((img = dec_iter.Next())) { 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan md5.Add(img); 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan return string(md5.Get()); 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan 129233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST(VP9DecodeMTTest, MTDecode) { 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan // no tiles or frame parallel; this exercises loop filter threading. 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc", 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan DecodeFile("vp90-2-03-size-226x226.webm", 2).c_str()); 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan 135233d2500723e5594f3e7c70896ffeeef32b9c950ywanTEST(VP9DecodeMTTest, MTDecode2) { 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan static const struct { 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *name; 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *expected_md5; 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan } files[] = { 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan { "vp90-2-08-tile_1x2_frame_parallel.webm", 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan "68ede6abd66bae0a2edf2eb9232241b6" }, 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan { "vp90-2-08-tile_1x4_frame_parallel.webm", 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan "368ebc6ebf3a5e478d85b2c3149b2848" }, 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan { "vp90-2-08-tile_1x8_frame_parallel.webm", 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan "17e439da2388aff3a0f69cb22579c6c1" }, 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan }; 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) { 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int t = 2; t <= 8; ++t) { 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan EXPECT_STREQ(files[i].expected_md5, DecodeFile(files[i].name, t).c_str()) 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan << "threads = " << t; 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan 156233d2500723e5594f3e7c70896ffeeef32b9c950ywanINSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool()); 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan} // namespace 159