]> granicus.if.org Git - libvpx/commitdiff
add auto keyframe unit test
authorJim Bankoski <jimbankoski@google.com>
Sat, 23 Jun 2012 18:20:41 +0000 (11:20 -0700)
committerJim Bankoski <jimbankoski@google.com>
Sat, 23 Jun 2012 18:20:41 +0000 (11:20 -0700)
To do so we add a framework for encoding a yv12 file..

Change-Id: I94a061eb916beaf6cde920cf1aaadb6eed10a717

test/encode_test_driver.cc
test/i420_video_source.h [new file with mode: 0644]
test/keyframe_test.cc
test/test-data.sha1 [new file with mode: 0644]
test/test.mk

index 0a188facfdaae0ec9a92bf3b802e292abccc3786..d7aaf6b2a8a4df6e98f2596eeb6ce7706fef0e52 100644 (file)
@@ -105,8 +105,7 @@ void EncoderTest::RunLoop(VideoSource *video) {
     Encoder encoder(cfg_, deadline_, &stats_);
 
     bool again;
-
-    for (video->Begin(), again = true; again; video->Next()) {
+    for (again = true, video->Begin(); again; video->Next()) {
       again = video->img() != NULL;
 
       PreEncodeFrameHook(video);
diff --git a/test/i420_video_source.h b/test/i420_video_source.h
new file mode 100644 (file)
index 0000000..f471764
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_I420_VIDEO_SOURCE_H_
+#define TEST_I420_VIDEO_SOURCE_H_
+#include <cstdio>
+#include <cstdlib>
+
+#include "test/video_source.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of raw yv12
+// so that we can do actual file encodes.
+class I420VideoSource : public VideoSource {
+ public:
+  I420VideoSource(const std::string &file_name,
+                  unsigned int width, unsigned int height,
+                  int rate_numerator, int rate_denominator,
+                  unsigned int start, int limit)
+      : file_name_(file_name),
+        img_(NULL),
+        start_(start),
+        limit_(limit),
+        framerate_numerator_(rate_numerator),
+        framerate_denominator_(rate_denominator) {
+
+    // This initializes raw_sz_, width_, height_ and allocates an img.
+    SetSize(width, height);
+  }
+
+  virtual ~I420VideoSource() {
+    vpx_img_free(img_);
+    if (input_file_)
+      fclose(input_file_);
+  }
+
+  virtual void Begin() {
+    std::string path_to_source = file_name_;
+    const char *kDataPath = getenv("LIBVPX_TEST_DATA_PATH");
+    if (kDataPath) {
+      path_to_source = kDataPath;
+      path_to_source += "/";
+      path_to_source += file_name_;
+    }
+
+    input_file_ = fopen(path_to_source.c_str(), "rb");
+    ASSERT_TRUE(input_file_) << "File open failed.";
+
+    if (start_) {
+      fseek(input_file_, raw_sz_ * start_, SEEK_SET);
+    }
+
+    frame_ = start_;
+    FillFrame();
+  }
+
+  virtual void Next() {
+    ++frame_;
+    FillFrame();
+  }
+
+  virtual vpx_image_t *img() const { return (frame_ < limit_) ? img_ : NULL;  }
+
+  // Models a stream where Timebase = 1/FPS, so pts == frame.
+  virtual vpx_codec_pts_t pts() const { return frame_; }
+
+  virtual unsigned long duration() const { return 1; }
+
+  virtual vpx_rational_t timebase() const {
+    const vpx_rational_t t = { framerate_denominator_, framerate_numerator_ };
+    return t;
+  }
+
+  virtual unsigned int frame() const { return frame_; }
+
+  void SetSize(unsigned int width, unsigned int height) {
+    if (width != width_ || height != height_) {
+      vpx_img_free(img_);
+      img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_VPXI420, width, height, 1);
+      ASSERT_TRUE(img_ != NULL);
+      width_ = width;
+      height_ = height;
+      raw_sz_ = width * height * 3 / 2;
+    }
+  }
+
+  virtual void FillFrame() {
+    // Read a frame from input_file.
+    if (fread(img_->img_data, raw_sz_, 1, input_file_) == 0) {
+      limit_ = frame_;
+    }
+  }
+
+ protected:
+  std::string file_name_;
+  FILE *input_file_;
+  vpx_image_t *img_;
+  size_t raw_sz_;
+  unsigned int start_;
+  unsigned int limit_;
+  unsigned int frame_;
+  unsigned int width_;
+  unsigned int height_;
+  unsigned int framerate_numerator_;
+  unsigned int framerate_denominator_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_I420_VIDEO_SOURCE_H_
index db18e5dab5140c2f4764503d98653e2de218e04b..aacccb1b8ae0bb60bb3fa4697dbc732bebab629b 100644 (file)
 #include <climits>
 #include <vector>
 #include "test/encode_test_driver.h"
-#include "test/video_source.h"
+#include "test/i420_video_source.h"
 #include "third_party/googletest/src/include/gtest/gtest.h"
 
 namespace {
 
 class KeyframeTest : public ::libvpx_test::EncoderTest,
-  public ::testing::TestWithParam<enum libvpx_test::TestMode> {
+    public ::testing::TestWithParam<enum libvpx_test::TestMode> {
  protected:
   virtual void SetUp() {
     InitializeConfig();
@@ -46,7 +46,7 @@ class KeyframeTest : public ::libvpx_test::EncoderTest,
   bool kf_do_force_kf_;
   int kf_count_;
   int kf_count_max_;
-  std::vector< vpx_codec_pts_t > kf_pts_list_;
+  std::vector<vpx_codec_pts_t> kf_pts_list_;
 };
 
 TEST_P(KeyframeTest, TestRandomVideoSource) {
@@ -78,9 +78,8 @@ TEST_P(KeyframeTest, TestForceKeyframe) {
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 
   // verify that every third frame is a keyframe.
-  for (std::vector<vpx_codec_pts_t>::iterator iter = kf_pts_list_.begin();
-       iter != kf_pts_list_.end();
-       ++iter) {
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
     ASSERT_EQ(0, *iter % 3) << "Unexpected keyframe at frame " << *iter;
   }
 }
@@ -92,12 +91,37 @@ TEST_P(KeyframeTest, TestKeyframeMaxDistance) {
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 
   // verify that keyframe interval matches kf_max_dist
-  for (std::vector<vpx_codec_pts_t>::iterator iter = kf_pts_list_.begin();
-       iter != kf_pts_list_.end();
-       iter++) {
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
     ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter;
   }
 }
 
+TEST_P(KeyframeTest, TestAutoKeyframe) {
+  cfg_.kf_mode = VPX_KF_AUTO;
+  kf_do_force_kf_ = false;
+
+  // This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120.
+  // I check only the first 40 frames to make sure there's a keyframe at frame
+  // 0 and 30.
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes ";
+
+  // Verify that keyframes match the file keyframes in the file.
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
+
+    if (deadline_ == VPX_DL_REALTIME && *iter > 0)
+      EXPECT_EQ(0, (*iter - 1) % 30) << "Unexpected keyframe at frame "
+        << *iter;
+    else
+      EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(AllModes, KeyframeTest, ALL_TEST_MODES);
 }  // namespace
diff --git a/test/test-data.sha1 b/test/test-data.sha1
new file mode 100644 (file)
index 0000000..8d40242
--- /dev/null
@@ -0,0 +1 @@
+d5dfb0151c9051f8c85999255645d7a23916d3c0  hantro_collage_w352h288.yuv
index d58beb41e865d1c5a23224120d2d65724186064d..c68801db06e57cfbbfbd8a00cd797480329e5d82 100644 (file)
@@ -3,8 +3,11 @@ LIBVPX_TEST_SRCS-yes += boolcoder_test.cc
 LIBVPX_TEST_SRCS-yes += config_test.cc
 LIBVPX_TEST_SRCS-yes += encode_test_driver.cc
 LIBVPX_TEST_SRCS-yes += encode_test_driver.h
+LIBVPX_TEST_SRCS-yes += i420_video_source.h
 LIBVPX_TEST_SRCS-yes += idctllm_test.cc
 LIBVPX_TEST_SRCS-yes += keyframe_test.cc
 LIBVPX_TEST_SRCS-yes += resize_test.cc
 LIBVPX_TEST_SRCS-yes += test_libvpx.cc
 LIBVPX_TEST_SRCS-yes += video_source.h
+
+LIBVPX_TEST_DATA-yes += hantro_collage_w352h288.yuv
\ No newline at end of file