summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/encode_api_test.cc80
-rw-r--r--test/encode_test_driver.h5
-rw-r--r--test/fdct8x8_test.cc24
-rw-r--r--vp9/encoder/vp9_encoder.h1
-rw-r--r--vp9/encoder/vp9_tpl_model.c2
-rw-r--r--vp9/vp9_cx_iface.c18
-rw-r--r--vpx/vp8cx.h14
-rw-r--r--vpx/vpx_encoder.h2
8 files changed, 132 insertions, 14 deletions
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index ecdf92834..eac962605 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -13,9 +13,12 @@
#include <initializer_list>
#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/video_source.h"
#include "./vpx_config.h"
-#include "test/video_source.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
@@ -360,4 +363,79 @@ TEST(EncodeAPI, ConfigChangeThreadCount) {
}
}
+#if CONFIG_VP9_ENCODER
+class EncodeApiGetTplStatsTest
+ : public ::libvpx_test::EncoderTest,
+ public ::testing::TestWithParam<const libvpx_test::CodecFactory *> {
+ public:
+ EncodeApiGetTplStatsTest() : EncoderTest(GetParam()) {}
+ ~EncodeApiGetTplStatsTest() override {}
+
+ protected:
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_TPL, 1);
+ }
+ }
+
+ vpx_codec_err_t AllocateTplList(TplFrameStats **data) {
+ // Allocate MAX_ARF_GOP_SIZE * sizeof(TplFrameStats) that will be filled
+ // by VP9E_GET_TPL_STATS
+ *data = static_cast<TplFrameStats *>(calloc(50, sizeof(TplFrameStats)));
+ if (*data == nullptr) return VPX_CODEC_MEM_ERROR;
+ return VPX_CODEC_OK;
+ }
+
+ void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) override {
+ ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ switch (pkt->kind) {
+ case VPX_CODEC_CX_FRAME_PKT: {
+ TplFrameStats *tpl_stats = NULL;
+ EXPECT_EQ(AllocateTplList(&tpl_stats), VPX_CODEC_OK);
+ encoder->Control(VP9E_GET_TPL_STATS, tpl_stats);
+ bool stats_not_all_zero = false;
+ for (unsigned int i = 0; i < cfg_.g_lag_in_frames; i++) {
+ if (tpl_stats[i].frame_width != 0) {
+ ASSERT_EQ(tpl_stats[i].frame_width, width_);
+ ASSERT_EQ(tpl_stats[i].frame_height, height_);
+ ASSERT_NE(tpl_stats[i].block_stats_list, nullptr);
+ stats_not_all_zero = true;
+ }
+ }
+ ASSERT_TRUE(stats_not_all_zero);
+ // Free the memory right away now as this is only a test.
+ free(tpl_stats);
+ break;
+ }
+ default: break;
+ }
+ }
+ }
+
+ int width_;
+ int height_;
+};
+
+TEST_P(EncodeApiGetTplStatsTest, GetTplStats) {
+ cfg_.g_lag_in_frames = 25;
+ width_ = 352;
+ height_ = 288;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", width_,
+ height_, 30, 1, 0, 150);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9, EncodeApiGetTplStatsTest,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+#endif // CONFIG_VP9_ENCODER
+
} // namespace
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
index b57df8529..27a78e68d 100644
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -153,6 +153,11 @@ class Encoder {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
+
+ void Control(int ctrl_id, TplFrameStats *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
#endif // CONFIG_VP9_ENCODER
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
diff --git a/test/fdct8x8_test.cc b/test/fdct8x8_test.cc
index 83d1ff142..fcc84690a 100644
--- a/test/fdct8x8_test.cc
+++ b/test/fdct8x8_test.cc
@@ -170,7 +170,7 @@ class FwdTrans8x8TestBase {
for (int j = 0; j < 64; ++j) {
const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
const int max_diff = kSignBiasMaxDiff255;
- EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
+ ASSERT_LT(diff, max_diff << (bit_depth_ - 8))
<< "Error: 8x8 FDCT/FHT has a sign bias > "
<< 1. * max_diff / count_test_block * 100 << "%"
<< " for input range [-255, 255] at index " << j
@@ -201,7 +201,7 @@ class FwdTrans8x8TestBase {
for (int j = 0; j < 64; ++j) {
const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
const int max_diff = kSignBiasMaxDiff15;
- EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
+ ASSERT_LT(diff, max_diff << (bit_depth_ - 8))
<< "Error: 8x8 FDCT/FHT has a sign bias > "
<< 1. * max_diff / count_test_block * 100 << "%"
<< " for input range [-15, 15] at index " << j
@@ -275,11 +275,11 @@ class FwdTrans8x8TestBase {
}
}
- EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+ ASSERT_GE(1 << 2 * (bit_depth_ - 8), max_error)
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
<< " roundtrip error > 1";
- EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
+ ASSERT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
<< "error > 1/5 per block";
}
@@ -360,17 +360,17 @@ class FwdTrans8x8TestBase {
total_coeff_error += abs(coeff_diff);
}
- EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+ ASSERT_GE(1 << 2 * (bit_depth_ - 8), max_error)
<< "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
- << "an individual roundtrip error > 1";
+ << " an individual roundtrip error > 1";
- EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
+ ASSERT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
<< "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
<< " roundtrip error > 1/5 per block";
- EXPECT_EQ(0, total_coeff_error)
+ ASSERT_EQ(0, total_coeff_error)
<< "Error: Extremal 8x8 FDCT/FHT has"
- << "overflow issues in the intermediate steps > 1";
+ << " overflow issues in the intermediate steps > 1";
}
}
@@ -426,7 +426,7 @@ class FwdTrans8x8TestBase {
const int diff = dst[j] - src[j];
#endif
const uint32_t error = diff * diff;
- EXPECT_GE(1u << 2 * (bit_depth_ - 8), error)
+ ASSERT_GE(1u << 2 * (bit_depth_ - 8), error)
<< "Error: 8x8 IDCT has error " << error << " at index " << j;
}
}
@@ -456,7 +456,7 @@ class FwdTrans8x8TestBase {
for (int j = 0; j < kNumCoeffs; ++j) {
const int32_t diff = coeff[j] - coeff_r[j];
const uint32_t error = diff * diff;
- EXPECT_GE(9u << 2 * (bit_depth_ - 8), error)
+ ASSERT_GE(9u << 2 * (bit_depth_ - 8), error)
<< "Error: 8x8 DCT has error " << error << " at index " << j;
}
}
@@ -512,7 +512,7 @@ class FwdTrans8x8TestBase {
const int diff = dst[j] - ref[j];
#endif
const uint32_t error = diff * diff;
- EXPECT_EQ(0u, error)
+ ASSERT_EQ(0u, error)
<< "Error: 8x8 IDCT has error " << error << " at index " << j;
}
}
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 7c22c807b..742cf0b6d 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -505,6 +505,7 @@ typedef struct EncFrameBuf {
} EncFrameBuf;
// Maximum operating frame buffer size needed for a GOP using ARF reference.
+// This is used to allocate the memory for TPL stats for a GOP.
#define MAX_ARF_GOP_SIZE (2 * MAX_LAG_BUFFERS)
#define MAX_KMEANS_GROUPS 8
diff --git a/vp9/encoder/vp9_tpl_model.c b/vp9/encoder/vp9_tpl_model.c
index dbd7482b0..b62c66b6c 100644
--- a/vp9/encoder/vp9_tpl_model.c
+++ b/vp9/encoder/vp9_tpl_model.c
@@ -1134,6 +1134,8 @@ static void mc_flow_dispenser(VP9_COMP *cpi, GF_PICTURE *gf_picture,
const int mi_height = num_8x8_blocks_high_lookup[bsize];
const int mi_width = num_8x8_blocks_wide_lookup[bsize];
+ tpl_frame_stats_before_propagation->frame_width = cm->width;
+ tpl_frame_stats_before_propagation->frame_height = cm->height;
// Setup scaling factor
#if CONFIG_VP9_HIGHBITDEPTH
vp9_setup_scale_factors_for_frame(
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 4c7eaed72..8bd880c7b 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -1788,6 +1788,23 @@ static vpx_codec_err_t ctrl_get_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx,
return VPX_CODEC_OK;
}
+static vpx_codec_err_t ctrl_get_tpl_stats(vpx_codec_alg_priv_t *ctx,
+ va_list args) {
+ VP9_COMP *const cpi = ctx->cpi;
+ TplFrameStats *data = va_arg(args, TplFrameStats *);
+ int i;
+ if (data == NULL) {
+ return VPX_CODEC_INVALID_PARAM;
+ }
+ for (i = 0; i < MAX_ARF_GOP_SIZE; i++) {
+ data[i].frame_width = cpi->tpl_frame_stats[i].frame_width;
+ data[i].frame_height = cpi->tpl_frame_stats[i].frame_height;
+ data[i].block_stats_list = cpi->tpl_frame_stats[i].block_stats_list;
+ }
+
+ return VPX_CODEC_OK;
+}
+
static vpx_codec_err_t ctrl_set_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx,
va_list args) {
VP9_COMP *const cpi = ctx->cpi;
@@ -2035,6 +2052,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ VP9E_GET_ACTIVEMAP, ctrl_get_active_map },
{ VP9E_GET_LEVEL, ctrl_get_level },
{ VP9E_GET_SVC_REF_FRAME_CONFIG, ctrl_get_svc_ref_frame_config },
+ { VP9E_GET_TPL_STATS, ctrl_get_tpl_stats },
{ -1, NULL },
};
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index e0b679fbb..123a645d9 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -767,6 +767,18 @@ enum vp8e_enc_control_id {
*
*/
VP9E_SET_QUANTIZER_ONE_PASS,
+
+ /*!\brief Codec control to get TPL stats for the current GOP.
+ *
+ * Allocation and free of memory of size MAX_ARF_GOP_SIZE (50) *
+ * sizeof(TplFrameStats) should be done by applications.
+ *
+ * VPX_CODEC_INVALID_PARAM will be returned if the pointer passed in is NULL.
+ *
+ * Supported in codecs: VP9
+ *
+ */
+ VP9E_GET_TPL_STATS,
};
/*!\brief vpx 1-D scaling mode
@@ -1097,6 +1109,8 @@ VPX_CTRL_USE_TYPE(VP8E_SET_RTC_EXTERNAL_RATECTRL, int)
#define VPX_CTRL_VP8E_SET_RTC_EXTERNAL_RATECTRL
VPX_CTRL_USE_TYPE(VP9E_SET_QUANTIZER_ONE_PASS, int)
#define VPX_CTRL_VP9E_SET_QUANTIZER_ONE_PASS
+VPX_CTRL_USE_TYPE(VP9E_GET_TPL_STATS, void *)
+#define VPX_CTRL_VP9E_GET_TPL_STATS
/*!\endcond */
/*! @} - end defgroup vp8_encoder */
diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h
index 924723132..1910a1904 100644
--- a/vpx/vpx_encoder.h
+++ b/vpx/vpx_encoder.h
@@ -58,7 +58,7 @@ extern "C" {
* fields to structures
*/
#define VPX_ENCODER_ABI_VERSION \
- (15 + VPX_CODEC_ABI_VERSION + \
+ (16 + VPX_CODEC_ABI_VERSION + \
VPX_EXT_RATECTRL_ABI_VERSION) /**<\hideinitializer*/
/*! \brief Encoder capabilities bitfield