11b362b15af34006e6a11974088a46d42b903418eJohann/*
21b362b15af34006e6a11974088a46d42b903418eJohann *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
31b362b15af34006e6a11974088a46d42b903418eJohann *
41b362b15af34006e6a11974088a46d42b903418eJohann *  Use of this source code is governed by a BSD-style license
51b362b15af34006e6a11974088a46d42b903418eJohann *  that can be found in the LICENSE file in the root of the source
61b362b15af34006e6a11974088a46d42b903418eJohann *  tree. An additional intellectual property rights grant can be found
71b362b15af34006e6a11974088a46d42b903418eJohann *  in the file PATENTS.  All contributing project authors may
81b362b15af34006e6a11974088a46d42b903418eJohann *  be found in the AUTHORS file in the root of the source tree.
91b362b15af34006e6a11974088a46d42b903418eJohann */
101b362b15af34006e6a11974088a46d42b903418eJohann#include <climits>
111b362b15af34006e6a11974088a46d42b903418eJohann#include <vector>
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "third_party/googletest/src/include/gtest/gtest.h"
13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "test/codec_factory.h"
141b362b15af34006e6a11974088a46d42b903418eJohann#include "test/encode_test_driver.h"
151b362b15af34006e6a11974088a46d42b903418eJohann#include "test/i420_video_source.h"
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "test/util.h"
171b362b15af34006e6a11974088a46d42b903418eJohann
181b362b15af34006e6a11974088a46d42b903418eJohannnamespace {
191b362b15af34006e6a11974088a46d42b903418eJohann
201b362b15af34006e6a11974088a46d42b903418eJohannclass KeyframeTest : public ::libvpx_test::EncoderTest,
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
221b362b15af34006e6a11974088a46d42b903418eJohann protected:
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  KeyframeTest() : EncoderTest(GET_PARAM(0)) {}
24a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  virtual ~KeyframeTest() {}
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
261b362b15af34006e6a11974088a46d42b903418eJohann  virtual void SetUp() {
271b362b15af34006e6a11974088a46d42b903418eJohann    InitializeConfig();
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    SetMode(GET_PARAM(1));
291b362b15af34006e6a11974088a46d42b903418eJohann    kf_count_ = 0;
301b362b15af34006e6a11974088a46d42b903418eJohann    kf_count_max_ = INT_MAX;
311b362b15af34006e6a11974088a46d42b903418eJohann    kf_do_force_kf_ = false;
321b362b15af34006e6a11974088a46d42b903418eJohann    set_cpu_used_ = 0;
331b362b15af34006e6a11974088a46d42b903418eJohann  }
341b362b15af34006e6a11974088a46d42b903418eJohann
351b362b15af34006e6a11974088a46d42b903418eJohann  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
361b362b15af34006e6a11974088a46d42b903418eJohann                                  ::libvpx_test::Encoder *encoder) {
371b362b15af34006e6a11974088a46d42b903418eJohann    if (kf_do_force_kf_)
381b362b15af34006e6a11974088a46d42b903418eJohann      frame_flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF;
391b362b15af34006e6a11974088a46d42b903418eJohann    if (set_cpu_used_ && video->frame() == 1)
401b362b15af34006e6a11974088a46d42b903418eJohann      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
411b362b15af34006e6a11974088a46d42b903418eJohann  }
421b362b15af34006e6a11974088a46d42b903418eJohann
431b362b15af34006e6a11974088a46d42b903418eJohann  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
441b362b15af34006e6a11974088a46d42b903418eJohann    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
451b362b15af34006e6a11974088a46d42b903418eJohann      kf_pts_list_.push_back(pkt->data.frame.pts);
461b362b15af34006e6a11974088a46d42b903418eJohann      kf_count_++;
471b362b15af34006e6a11974088a46d42b903418eJohann      abort_ |= kf_count_ > kf_count_max_;
481b362b15af34006e6a11974088a46d42b903418eJohann    }
491b362b15af34006e6a11974088a46d42b903418eJohann  }
501b362b15af34006e6a11974088a46d42b903418eJohann
511b362b15af34006e6a11974088a46d42b903418eJohann  bool kf_do_force_kf_;
521b362b15af34006e6a11974088a46d42b903418eJohann  int kf_count_;
531b362b15af34006e6a11974088a46d42b903418eJohann  int kf_count_max_;
541b362b15af34006e6a11974088a46d42b903418eJohann  std::vector<vpx_codec_pts_t> kf_pts_list_;
551b362b15af34006e6a11974088a46d42b903418eJohann  int set_cpu_used_;
561b362b15af34006e6a11974088a46d42b903418eJohann};
571b362b15af34006e6a11974088a46d42b903418eJohann
581b362b15af34006e6a11974088a46d42b903418eJohannTEST_P(KeyframeTest, TestRandomVideoSource) {
591b362b15af34006e6a11974088a46d42b903418eJohann  // Validate that encoding the RandomVideoSource produces multiple keyframes.
601b362b15af34006e6a11974088a46d42b903418eJohann  // This validates the results of the TestDisableKeyframes test.
611b362b15af34006e6a11974088a46d42b903418eJohann  kf_count_max_ = 2;  // early exit successful tests.
621b362b15af34006e6a11974088a46d42b903418eJohann
631b362b15af34006e6a11974088a46d42b903418eJohann  ::libvpx_test::RandomVideoSource video;
641b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
651b362b15af34006e6a11974088a46d42b903418eJohann
661b362b15af34006e6a11974088a46d42b903418eJohann  // In realtime mode - auto placed keyframes are exceedingly rare,  don't
671b362b15af34006e6a11974088a46d42b903418eJohann  // bother with this check   if(GetParam() > 0)
68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (GET_PARAM(1) > 0)
691b362b15af34006e6a11974088a46d42b903418eJohann    EXPECT_GT(kf_count_, 1);
701b362b15af34006e6a11974088a46d42b903418eJohann}
711b362b15af34006e6a11974088a46d42b903418eJohann
721b362b15af34006e6a11974088a46d42b903418eJohannTEST_P(KeyframeTest, TestDisableKeyframes) {
731b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.kf_mode = VPX_KF_DISABLED;
741b362b15af34006e6a11974088a46d42b903418eJohann  kf_count_max_ = 1;  // early exit failed tests.
751b362b15af34006e6a11974088a46d42b903418eJohann
761b362b15af34006e6a11974088a46d42b903418eJohann  ::libvpx_test::RandomVideoSource video;
771b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
781b362b15af34006e6a11974088a46d42b903418eJohann
791b362b15af34006e6a11974088a46d42b903418eJohann  EXPECT_EQ(1, kf_count_);
801b362b15af34006e6a11974088a46d42b903418eJohann}
811b362b15af34006e6a11974088a46d42b903418eJohann
821b362b15af34006e6a11974088a46d42b903418eJohannTEST_P(KeyframeTest, TestForceKeyframe) {
831b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.kf_mode = VPX_KF_DISABLED;
841b362b15af34006e6a11974088a46d42b903418eJohann  kf_do_force_kf_ = true;
851b362b15af34006e6a11974088a46d42b903418eJohann
861b362b15af34006e6a11974088a46d42b903418eJohann  ::libvpx_test::DummyVideoSource video;
871b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
881b362b15af34006e6a11974088a46d42b903418eJohann
891b362b15af34006e6a11974088a46d42b903418eJohann  // verify that every third frame is a keyframe.
901b362b15af34006e6a11974088a46d42b903418eJohann  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
911b362b15af34006e6a11974088a46d42b903418eJohann       iter != kf_pts_list_.end(); ++iter) {
921b362b15af34006e6a11974088a46d42b903418eJohann    ASSERT_EQ(0, *iter % 3) << "Unexpected keyframe at frame " << *iter;
931b362b15af34006e6a11974088a46d42b903418eJohann  }
941b362b15af34006e6a11974088a46d42b903418eJohann}
951b362b15af34006e6a11974088a46d42b903418eJohann
961b362b15af34006e6a11974088a46d42b903418eJohannTEST_P(KeyframeTest, TestKeyframeMaxDistance) {
971b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.kf_max_dist = 25;
981b362b15af34006e6a11974088a46d42b903418eJohann
991b362b15af34006e6a11974088a46d42b903418eJohann  ::libvpx_test::DummyVideoSource video;
1001b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1011b362b15af34006e6a11974088a46d42b903418eJohann
1021b362b15af34006e6a11974088a46d42b903418eJohann  // verify that keyframe interval matches kf_max_dist
1031b362b15af34006e6a11974088a46d42b903418eJohann  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
1041b362b15af34006e6a11974088a46d42b903418eJohann       iter != kf_pts_list_.end(); ++iter) {
1051b362b15af34006e6a11974088a46d42b903418eJohann    ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter;
1061b362b15af34006e6a11974088a46d42b903418eJohann  }
1071b362b15af34006e6a11974088a46d42b903418eJohann}
1081b362b15af34006e6a11974088a46d42b903418eJohann
1091b362b15af34006e6a11974088a46d42b903418eJohannTEST_P(KeyframeTest, TestAutoKeyframe) {
1101b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.kf_mode = VPX_KF_AUTO;
1111b362b15af34006e6a11974088a46d42b903418eJohann  kf_do_force_kf_ = false;
1121b362b15af34006e6a11974088a46d42b903418eJohann
1131b362b15af34006e6a11974088a46d42b903418eJohann  // Force a deterministic speed step in Real Time mode, as the faster modes
1141b362b15af34006e6a11974088a46d42b903418eJohann  // may not produce a keyframe like we expect. This is necessary when running
1151b362b15af34006e6a11974088a46d42b903418eJohann  // on very slow environments (like Valgrind). The step -11 was determined
1161b362b15af34006e6a11974088a46d42b903418eJohann  // experimentally as the fastest mode that still throws the keyframe.
1171b362b15af34006e6a11974088a46d42b903418eJohann  if (deadline_ == VPX_DL_REALTIME)
1181b362b15af34006e6a11974088a46d42b903418eJohann    set_cpu_used_ = -11;
1191b362b15af34006e6a11974088a46d42b903418eJohann
1201b362b15af34006e6a11974088a46d42b903418eJohann  // This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120.
1211b362b15af34006e6a11974088a46d42b903418eJohann  // I check only the first 40 frames to make sure there's a keyframe at frame
1221b362b15af34006e6a11974088a46d42b903418eJohann  // 0 and 30.
1231b362b15af34006e6a11974088a46d42b903418eJohann  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
1241b362b15af34006e6a11974088a46d42b903418eJohann                                       30, 1, 0, 40);
1251b362b15af34006e6a11974088a46d42b903418eJohann
1261b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
1271b362b15af34006e6a11974088a46d42b903418eJohann
1281b362b15af34006e6a11974088a46d42b903418eJohann  // In realtime mode - auto placed keyframes are exceedingly rare,  don't
1291b362b15af34006e6a11974088a46d42b903418eJohann  // bother with this check
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (GET_PARAM(1) > 0)
1311b362b15af34006e6a11974088a46d42b903418eJohann    EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes ";
1321b362b15af34006e6a11974088a46d42b903418eJohann
1331b362b15af34006e6a11974088a46d42b903418eJohann  // Verify that keyframes match the file keyframes in the file.
1341b362b15af34006e6a11974088a46d42b903418eJohann  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
1351b362b15af34006e6a11974088a46d42b903418eJohann       iter != kf_pts_list_.end(); ++iter) {
1361b362b15af34006e6a11974088a46d42b903418eJohann    if (deadline_ == VPX_DL_REALTIME && *iter > 0)
1371b362b15af34006e6a11974088a46d42b903418eJohann      EXPECT_EQ(0, (*iter - 1) % 30) << "Unexpected keyframe at frame "
1381b362b15af34006e6a11974088a46d42b903418eJohann        << *iter;
1391b362b15af34006e6a11974088a46d42b903418eJohann    else
1401b362b15af34006e6a11974088a46d42b903418eJohann      EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter;
1411b362b15af34006e6a11974088a46d42b903418eJohann  }
1421b362b15af34006e6a11974088a46d42b903418eJohann}
1431b362b15af34006e6a11974088a46d42b903418eJohann
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangVP8_INSTANTIATE_TEST_CASE(KeyframeTest, ALL_TEST_MODES);
1451b362b15af34006e6a11974088a46d42b903418eJohann}  // namespace
146