shithub: libvpx

Download patch

ref: caf0f14f84b7d66a614bc6f83ca7b311dcda437b
parent: d708e7fbbefb1db496a1073e1f8e3b113f073aab
parent: 2fb29ff7f9267b7bcb5cd29907d2b00f1c279ae3
author: John Koleszar <jkoleszar@google.com>
date: Thu May 24 08:22:34 EDT 2012

Merge changes I231c062e,Idadc42c7

* changes:
  Add external resize tests
  Prevent external frame size changes in two-pass

--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -32,6 +32,10 @@
                                          ::libvpx_test::kTwoPassGood, \
                                          ::libvpx_test::kTwoPassBest)
 
+#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
+                                              ::libvpx_test::kOnePassGood, \
+                                              ::libvpx_test::kOnePassBest)
+
 
 // Provides an object to handle the libvpx get_cx_data() iteration pattern
 class CxDataIterator {
--- /dev/null
+++ b/test/resize_test.cc
@@ -1,0 +1,104 @@
+/*
+ *  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.
+ */
+#include <climits>
+#include <vector>
+#include "test/encode_test_driver.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace {
+
+const unsigned int kInitialWidth = 320;
+const unsigned int kInitialHeight = 240;
+
+unsigned int ScaleForFrameNumber(unsigned int frame, unsigned int val) {
+  if (frame < 10)
+    return val;
+  if (frame < 20)
+    return val / 2;
+  if (frame < 30)
+    return val * 2 / 3;
+  if (frame < 40)
+    return val / 4;
+  if (frame < 50)
+    return val * 7 / 8;
+  return val;
+}
+
+class ResizingVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+  ResizingVideoSource() {
+    SetSize(kInitialWidth, kInitialHeight);
+    limit_ = 60;
+  }
+
+ protected:
+  virtual void Next() {
+    ++frame_;
+    SetSize(ScaleForFrameNumber(frame_, kInitialWidth),
+            ScaleForFrameNumber(frame_, kInitialHeight));
+    FillFrame();
+  }
+};
+
+class ResizeTest : public ::libvpx_test::EncoderTest,
+  public ::testing::TestWithParam<enum libvpx_test::TestMode> {
+ protected:
+  struct FrameInfo {
+    FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
+        : pts(_pts), w(_w), h(_h) {}
+
+    vpx_codec_pts_t pts;
+    unsigned int    w;
+    unsigned int    h;
+  };
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GetParam());
+  }
+
+  virtual bool Continue() const {
+    return !HasFatalFailure() && !abort_;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+      const unsigned char *buf =
+          reinterpret_cast<const unsigned char *>(pkt->data.frame.buf);
+      const unsigned int w = (buf[6] | (buf[7] << 8)) & 0x3fff;
+      const unsigned int h = (buf[8] | (buf[9] << 8)) & 0x3fff;
+
+      frame_info_list_.push_back(FrameInfo(pkt->data.frame.pts, w, h));
+    }
+  }
+
+  std::vector< FrameInfo > frame_info_list_;
+};
+
+TEST_P(ResizeTest, TestExternalResizeWorks) {
+  ResizingVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  for (std::vector<FrameInfo>::iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    const vpx_codec_pts_t pts = info->pts;
+    const unsigned int expected_w = ScaleForFrameNumber(pts, kInitialWidth);
+    const unsigned int expected_h = ScaleForFrameNumber(pts, kInitialHeight);
+
+    EXPECT_EQ(expected_w, info->w)
+        << "Frame " << pts << "had unexpected width";
+    EXPECT_EQ(expected_h, info->h)
+        << "Frame " << pts << "had unexpected height";
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(OnePass, ResizeTest, ONE_PASS_TEST_MODES);
+}  // namespace
--- a/test/test.mk
+++ b/test/test.mk
@@ -4,5 +4,6 @@
 LIBVPX_TEST_SRCS-yes += encode_test_driver.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
--- a/test/video_source.h
+++ b/test/video_source.h
@@ -44,8 +44,9 @@
 
 class DummyVideoSource : public VideoSource {
  public:
-  DummyVideoSource()
-    : img_(NULL), limit_(100) { SetSize(80, 64); }
+  DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) {
+    SetSize(80, 64);
+  }
 
   virtual ~DummyVideoSource() { vpx_img_free(img_); }
 
@@ -76,9 +77,13 @@
   virtual unsigned int frame() const { return frame_; }
 
   void SetSize(unsigned int width, unsigned int height) {
-    vpx_img_free(img_);
-    raw_sz_ = ((width + 31)&~31) * height * 3 / 2;
-    img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_VPXI420, width, height, 32);
+    if (width != width_ || height != height_) {
+      vpx_img_free(img_);
+      raw_sz_ = ((width + 31)&~31) * height * 3 / 2;
+      img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_VPXI420, width, height, 32);
+      width_ = width;
+      height_ = height;
+    }
   }
 
  protected:
@@ -88,6 +93,8 @@
   size_t       raw_sz_;
   unsigned int limit_;
   unsigned int frame_;
+  unsigned int width_;
+  unsigned int height_;
 };
 
 
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -447,7 +447,7 @@
     vpx_codec_err_t res;
 
     if (((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
-        && cfg->g_lag_in_frames > 1)
+        && (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS))
         ERROR("Cannot change width or height after initialization");
 
     /* Prevent increasing lag_in_frames. This check is stricter than it needs