Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2015 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 "third_party/googletest/src/include/gtest/gtest.h"
     12 
     13 #include "test/codec_factory.h"
     14 #include "test/encode_test_driver.h"
     15 #include "test/util.h"
     16 #include "test/y4m_video_source.h"
     17 #include "test/yuv_video_source.h"
     18 #include "vp9/encoder/vp9_ratectrl.h"
     19 
     20 namespace {
     21 
     22 const unsigned int kFrames = 100;
     23 const int kBitrate = 500;
     24 
     25 #define ARF_NOT_SEEN 1000001
     26 #define ARF_SEEN_ONCE 1000000
     27 
     28 typedef struct {
     29   const char *filename;
     30   unsigned int width;
     31   unsigned int height;
     32   unsigned int framerate_num;
     33   unsigned int framerate_den;
     34   unsigned int input_bit_depth;
     35   vpx_img_fmt fmt;
     36   vpx_bit_depth_t bit_depth;
     37   unsigned int profile;
     38 } TestVideoParam;
     39 
     40 typedef struct {
     41   libvpx_test::TestMode mode;
     42   int cpu_used;
     43 } TestEncodeParam;
     44 
     45 const TestVideoParam kTestVectors[] = {
     46   // artificially increase framerate to trigger default check
     47   { "hantro_collage_w352h288.yuv", 352, 288, 5000, 1, 8, VPX_IMG_FMT_I420,
     48     VPX_BITS_8, 0 },
     49   { "hantro_collage_w352h288.yuv", 352, 288, 30, 1, 8, VPX_IMG_FMT_I420,
     50     VPX_BITS_8, 0 },
     51   { "rush_hour_444.y4m", 352, 288, 30, 1, 8, VPX_IMG_FMT_I444, VPX_BITS_8, 1 },
     52 #if CONFIG_VP9_HIGHBITDEPTH
     53 // Add list of profile 2/3 test videos here ...
     54 #endif  // CONFIG_VP9_HIGHBITDEPTH
     55 };
     56 
     57 const TestEncodeParam kEncodeVectors[] = {
     58   { ::libvpx_test::kOnePassGood, 2 }, { ::libvpx_test::kOnePassGood, 5 },
     59   { ::libvpx_test::kTwoPassGood, 1 }, { ::libvpx_test::kTwoPassGood, 2 },
     60   { ::libvpx_test::kTwoPassGood, 5 }, { ::libvpx_test::kRealTime, 5 },
     61 };
     62 
     63 const int kMinArfVectors[] = {
     64   // NOTE: 0 refers to the default built-in logic in:
     65   //       vp9_rc_get_default_min_gf_interval(...)
     66   0, 4, 8, 12, 15
     67 };
     68 
     69 int is_extension_y4m(const char *filename) {
     70   const char *dot = strrchr(filename, '.');
     71   if (!dot || dot == filename) {
     72     return 0;
     73   } else {
     74     return !strcmp(dot, ".y4m");
     75   }
     76 }
     77 
     78 class ArfFreqTest
     79     : public ::libvpx_test::EncoderTest,
     80       public ::libvpx_test::CodecTestWith3Params<TestVideoParam,
     81                                                  TestEncodeParam, int> {
     82  protected:
     83   ArfFreqTest()
     84       : EncoderTest(GET_PARAM(0)), test_video_param_(GET_PARAM(1)),
     85         test_encode_param_(GET_PARAM(2)), min_arf_requested_(GET_PARAM(3)) {}
     86 
     87   virtual ~ArfFreqTest() {}
     88 
     89   virtual void SetUp() {
     90     InitializeConfig();
     91     SetMode(test_encode_param_.mode);
     92     if (test_encode_param_.mode != ::libvpx_test::kRealTime) {
     93       cfg_.g_lag_in_frames = 25;
     94       cfg_.rc_end_usage = VPX_VBR;
     95     } else {
     96       cfg_.g_lag_in_frames = 0;
     97       cfg_.rc_end_usage = VPX_CBR;
     98       cfg_.rc_buf_sz = 1000;
     99       cfg_.rc_buf_initial_sz = 500;
    100       cfg_.rc_buf_optimal_sz = 600;
    101     }
    102     dec_cfg_.threads = 4;
    103   }
    104 
    105   virtual void BeginPassHook(unsigned int) {
    106     min_run_ = ARF_NOT_SEEN;
    107     run_of_visible_frames_ = 0;
    108   }
    109 
    110   int GetNumFramesInPkt(const vpx_codec_cx_pkt_t *pkt) {
    111     const uint8_t *buffer = reinterpret_cast<uint8_t *>(pkt->data.frame.buf);
    112     const uint8_t marker = buffer[pkt->data.frame.sz - 1];
    113     const int mag = ((marker >> 3) & 3) + 1;
    114     int frames = (marker & 0x7) + 1;
    115     const unsigned int index_sz = 2 + mag * frames;
    116     // Check for superframe or not.
    117     // Assume superframe has only one visible frame, the rest being
    118     // invisible. If superframe index is not found, then there is only
    119     // one frame.
    120     if (!((marker & 0xe0) == 0xc0 && pkt->data.frame.sz >= index_sz &&
    121           buffer[pkt->data.frame.sz - index_sz] == marker)) {
    122       frames = 1;
    123     }
    124     return frames;
    125   }
    126 
    127   virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
    128     if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
    129     const int frames = GetNumFramesInPkt(pkt);
    130     if (frames == 1) {
    131       run_of_visible_frames_++;
    132     } else if (frames == 2) {
    133       if (min_run_ == ARF_NOT_SEEN) {
    134         min_run_ = ARF_SEEN_ONCE;
    135       } else if (min_run_ == ARF_SEEN_ONCE ||
    136                  run_of_visible_frames_ < min_run_) {
    137         min_run_ = run_of_visible_frames_;
    138       }
    139       run_of_visible_frames_ = 1;
    140     } else {
    141       min_run_ = 0;
    142       run_of_visible_frames_ = 1;
    143     }
    144   }
    145 
    146   virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
    147                                   ::libvpx_test::Encoder *encoder) {
    148     if (video->frame() == 0) {
    149       encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
    150       encoder->Control(VP9E_SET_TILE_COLUMNS, 4);
    151       encoder->Control(VP8E_SET_CPUUSED, test_encode_param_.cpu_used);
    152       encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_arf_requested_);
    153       if (test_encode_param_.mode != ::libvpx_test::kRealTime) {
    154         encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
    155         encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
    156         encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
    157         encoder->Control(VP8E_SET_ARNR_TYPE, 3);
    158       }
    159     }
    160   }
    161 
    162   int GetMinVisibleRun() const { return min_run_; }
    163 
    164   int GetMinArfDistanceRequested() const {
    165     if (min_arf_requested_) {
    166       return min_arf_requested_;
    167     } else {
    168       return vp9_rc_get_default_min_gf_interval(
    169           test_video_param_.width, test_video_param_.height,
    170           (double)test_video_param_.framerate_num /
    171               test_video_param_.framerate_den);
    172     }
    173   }
    174 
    175   TestVideoParam test_video_param_;
    176   TestEncodeParam test_encode_param_;
    177 
    178  private:
    179   int min_arf_requested_;
    180   int min_run_;
    181   int run_of_visible_frames_;
    182 };
    183 
    184 TEST_P(ArfFreqTest, MinArfFreqTest) {
    185   cfg_.rc_target_bitrate = kBitrate;
    186   cfg_.g_error_resilient = 0;
    187   cfg_.g_profile = test_video_param_.profile;
    188   cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
    189   cfg_.g_bit_depth = test_video_param_.bit_depth;
    190   init_flags_ = VPX_CODEC_USE_PSNR;
    191   if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
    192 
    193   testing::internal::scoped_ptr<libvpx_test::VideoSource> video;
    194   if (is_extension_y4m(test_video_param_.filename)) {
    195     video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
    196                                                 kFrames));
    197   } else {
    198     video.reset(new libvpx_test::YUVVideoSource(
    199         test_video_param_.filename, test_video_param_.fmt,
    200         test_video_param_.width, test_video_param_.height,
    201         test_video_param_.framerate_num, test_video_param_.framerate_den, 0,
    202         kFrames));
    203   }
    204 
    205   ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
    206   const int min_run = GetMinVisibleRun();
    207   const int min_arf_dist_requested = GetMinArfDistanceRequested();
    208   if (min_run != ARF_NOT_SEEN && min_run != ARF_SEEN_ONCE) {
    209     const int min_arf_dist = min_run + 1;
    210     EXPECT_GE(min_arf_dist, min_arf_dist_requested);
    211   }
    212 }
    213 
    214 VP9_INSTANTIATE_TEST_CASE(ArfFreqTest, ::testing::ValuesIn(kTestVectors),
    215                           ::testing::ValuesIn(kEncodeVectors),
    216                           ::testing::ValuesIn(kMinArfVectors));
    217 }  // namespace
    218