Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <cstdio>
     12 #include <cstdlib>
     13 #include <set>
     14 #include <string>
     15 #include "third_party/googletest/src/include/gtest/gtest.h"
     16 #include "../tools_common.h"
     17 #include "./vpx_config.h"
     18 #include "test/codec_factory.h"
     19 #include "test/decode_test_driver.h"
     20 #include "test/ivf_video_source.h"
     21 #include "test/md5_helper.h"
     22 #include "test/test_vectors.h"
     23 #include "test/util.h"
     24 #if CONFIG_WEBM_IO
     25 #include "test/webm_video_source.h"
     26 #endif
     27 #include "vpx_mem/vpx_mem.h"
     28 
     29 namespace {
     30 
     31 const int kThreads = 0;
     32 const int kFileName = 1;
     33 
     34 typedef std::tr1::tuple<int, const char *> DecodeParam;
     35 
     36 class TestVectorTest : public ::libvpx_test::DecoderTest,
     37                        public ::libvpx_test::CodecTestWithParam<DecodeParam> {
     38  protected:
     39   TestVectorTest() : DecoderTest(GET_PARAM(0)), md5_file_(NULL) {
     40 #if CONFIG_VP9_DECODER
     41     resize_clips_.insert(::libvpx_test::kVP9TestVectorsResize,
     42                          ::libvpx_test::kVP9TestVectorsResize +
     43                              ::libvpx_test::kNumVP9TestVectorsResize);
     44 #endif
     45   }
     46 
     47   virtual ~TestVectorTest() {
     48     if (md5_file_) fclose(md5_file_);
     49   }
     50 
     51   void OpenMD5File(const std::string &md5_file_name_) {
     52     md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
     53     ASSERT_TRUE(md5_file_ != NULL)
     54         << "Md5 file open failed. Filename: " << md5_file_name_;
     55   }
     56 
     57   virtual void DecompressedFrameHook(const vpx_image_t &img,
     58                                      const unsigned int frame_number) {
     59     ASSERT_TRUE(md5_file_ != NULL);
     60     char expected_md5[33];
     61     char junk[128];
     62 
     63     // Read correct md5 checksums.
     64     const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
     65     ASSERT_NE(res, EOF) << "Read md5 data failed";
     66     expected_md5[32] = '\0';
     67 
     68     ::libvpx_test::MD5 md5_res;
     69     md5_res.Add(&img);
     70     const char *actual_md5 = md5_res.Get();
     71 
     72     // Check md5 match.
     73     ASSERT_STREQ(expected_md5, actual_md5)
     74         << "Md5 checksums don't match: frame number = " << frame_number;
     75   }
     76 
     77 #if CONFIG_VP9_DECODER
     78   std::set<std::string> resize_clips_;
     79 #endif
     80 
     81  private:
     82   FILE *md5_file_;
     83 };
     84 
     85 // This test runs through the whole set of test vectors, and decodes them.
     86 // The md5 checksums are computed for each frame in the video file. If md5
     87 // checksums match the correct md5 data, then the test is passed. Otherwise,
     88 // the test failed.
     89 TEST_P(TestVectorTest, MD5Match) {
     90   const DecodeParam input = GET_PARAM(1);
     91   const std::string filename = std::tr1::get<kFileName>(input);
     92   vpx_codec_flags_t flags = 0;
     93   vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
     94   char str[256];
     95 
     96   cfg.threads = std::tr1::get<kThreads>(input);
     97 
     98   snprintf(str, sizeof(str) / sizeof(str[0]) - 1, "file: %s threads: %d",
     99            filename.c_str(), cfg.threads);
    100   SCOPED_TRACE(str);
    101 
    102   // Open compressed video file.
    103   testing::internal::scoped_ptr<libvpx_test::CompressedVideoSource> video;
    104   if (filename.substr(filename.length() - 3, 3) == "ivf") {
    105     video.reset(new libvpx_test::IVFVideoSource(filename));
    106   } else if (filename.substr(filename.length() - 4, 4) == "webm") {
    107 #if CONFIG_WEBM_IO
    108     video.reset(new libvpx_test::WebMVideoSource(filename));
    109 #else
    110     fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
    111             filename.c_str());
    112     return;
    113 #endif
    114   }
    115   ASSERT_TRUE(video.get() != NULL);
    116   video->Init();
    117 
    118   // Construct md5 file name.
    119   const std::string md5_filename = filename + ".md5";
    120   OpenMD5File(md5_filename);
    121 
    122   // Set decode config and flags.
    123   set_cfg(cfg);
    124   set_flags(flags);
    125 
    126   // Decode frame, and check the md5 matching.
    127   ASSERT_NO_FATAL_FAILURE(RunLoop(video.get(), cfg));
    128 }
    129 
    130 #if CONFIG_VP8_DECODER
    131 VP8_INSTANTIATE_TEST_CASE(
    132     TestVectorTest,
    133     ::testing::Combine(
    134         ::testing::Values(1),  // Single thread.
    135         ::testing::ValuesIn(libvpx_test::kVP8TestVectors,
    136                             libvpx_test::kVP8TestVectors +
    137                                 libvpx_test::kNumVP8TestVectors)));
    138 
    139 // Test VP8 decode in with different numbers of threads.
    140 INSTANTIATE_TEST_CASE_P(
    141     VP8MultiThreaded, TestVectorTest,
    142     ::testing::Combine(
    143         ::testing::Values(
    144             static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP8)),
    145         ::testing::Combine(
    146             ::testing::Range(2, 9),  // With 2 ~ 8 threads.
    147             ::testing::ValuesIn(libvpx_test::kVP8TestVectors,
    148                                 libvpx_test::kVP8TestVectors +
    149                                     libvpx_test::kNumVP8TestVectors))));
    150 
    151 #endif  // CONFIG_VP8_DECODER
    152 
    153 #if CONFIG_VP9_DECODER
    154 VP9_INSTANTIATE_TEST_CASE(
    155     TestVectorTest,
    156     ::testing::Combine(
    157         ::testing::Values(1),  // Single thread.
    158         ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
    159                             libvpx_test::kVP9TestVectors +
    160                                 libvpx_test::kNumVP9TestVectors)));
    161 
    162 INSTANTIATE_TEST_CASE_P(
    163     VP9MultiThreaded, TestVectorTest,
    164     ::testing::Combine(
    165         ::testing::Values(
    166             static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
    167         ::testing::Combine(
    168             ::testing::Range(2, 9),  // With 2 ~ 8 threads.
    169             ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
    170                                 libvpx_test::kVP9TestVectors +
    171                                     libvpx_test::kNumVP9TestVectors))));
    172 #endif
    173 }  // namespace
    174