Merge "vp10: fix entropy counts for the hp bit."
diff --git a/examples/vp9_spatial_svc_encoder.c b/examples/vp9_spatial_svc_encoder.c
index af8aa86..9f41911 100644
--- a/examples/vp9_spatial_svc_encoder.c
+++ b/examples/vp9_spatial_svc_encoder.c
@@ -80,6 +80,8 @@
ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
static const arg_def_t speed_arg =
ARG_DEF("sp", "speed", 1, "speed configuration");
+static const arg_def_t aqmode_arg =
+ ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
#if CONFIG_VP9_HIGHBITDEPTH
static const struct arg_enum_list bitdepth_enum[] = {
@@ -101,7 +103,7 @@
&kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg,
&fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
&max_bitrate_arg, &temporal_layers_arg, &temporal_layering_mode_arg,
- &lag_in_frame_arg, &threads_arg,
+ &lag_in_frame_arg, &threads_arg, &aqmode_arg,
#if OUTPUT_RC_STATS
&output_rc_stats_arg,
#endif
@@ -221,6 +223,8 @@
#endif
} else if (arg_match(&arg, &speed_arg, argi)) {
svc_ctx->speed = arg_parse_uint(&arg);
+ } else if (arg_match(&arg, &aqmode_arg, argi)) {
+ svc_ctx->aqmode = arg_parse_uint(&arg);
} else if (arg_match(&arg, &threads_arg, argi)) {
svc_ctx->threads = arg_parse_uint(&arg);
} else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
@@ -635,7 +639,7 @@
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
if (svc_ctx.threads)
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
- if (svc_ctx.speed >= 5)
+ if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
diff --git a/test/resize_test.cc b/test/resize_test.cc
index f1134aa..2d10322 100644
--- a/test/resize_test.cc
+++ b/test/resize_test.cc
@@ -81,6 +81,15 @@
const unsigned int kInitialWidth = 320;
const unsigned int kInitialHeight = 240;
+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;
+};
+
unsigned int ScaleForFrameNumber(unsigned int frame, unsigned int val) {
if (frame < 10)
return val;
@@ -120,15 +129,6 @@
virtual ~ResizeTest() {}
- 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(GET_PARAM(1));
@@ -261,6 +261,87 @@
}
}
+class ResizeInternalRealtimeTest : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ ResizeInternalRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~ResizeInternalRealtimeTest() {}
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ }
+ }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ set_cpu_used_ = GET_PARAM(2);
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ vpx_codec_pts_t pts) {
+ frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
+ }
+
+ void DefaultConfig() {
+ cfg_.g_w = 352;
+ cfg_.g_h = 288;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.kf_mode = VPX_KF_AUTO;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
+ // Enable dropped frames.
+ cfg_.rc_dropframe_thresh = 1;
+ // Enable error_resilience mode.
+ cfg_.g_error_resilient = 1;
+ // Enable dynamic resizing.
+ cfg_.rc_resize_allowed = 1;
+ // Run at low bitrate.
+ cfg_.rc_target_bitrate = 200;
+ }
+
+ std::vector< FrameInfo > frame_info_list_;
+ int set_cpu_used_;
+};
+
+// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
+// Run at low bitrate, with resize_allowed = 1, and verify that we get
+// one resize down event.
+TEST_P(ResizeInternalRealtimeTest, TestInternalRealtimeResizeDown) {
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 299);
+ DefaultConfig();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ unsigned int last_w = cfg_.g_w;
+ unsigned int last_h = cfg_.g_h;
+ int resize_count = 0;
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ if (info->w != last_w || info->h != last_h) {
+ // Verify that resize down occurs.
+ ASSERT_LT(info->w, last_w);
+ ASSERT_LT(info->h, last_h);
+ last_w = info->w;
+ last_h = info->h;
+ resize_count++;
+ }
+ }
+
+ // Verify that we get 1 resize down event in this test.
+ ASSERT_EQ(1, resize_count) << "Resizing should occur.";
+}
+
vpx_img_fmt_t CspForFrameNumber(int frame) {
if (frame < 10)
return VPX_IMG_FMT_I420;
@@ -371,6 +452,9 @@
::testing::Values(::libvpx_test::kRealTime));
VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
::testing::Values(::libvpx_test::kOnePassBest));
+VP9_INSTANTIATE_TEST_CASE(ResizeInternalRealtimeTest,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::Range(5, 9));
VP9_INSTANTIATE_TEST_CASE(ResizeCspTest,
::testing::Values(::libvpx_test::kRealTime));
} // namespace
diff --git a/test/vp9_encoder_parms_get_to_decoder.cc b/test/vp9_encoder_parms_get_to_decoder.cc
index a02070e..1ceff1e 100644
--- a/test/vp9_encoder_parms_get_to_decoder.cc
+++ b/test/vp9_encoder_parms_get_to_decoder.cc
@@ -14,38 +14,12 @@
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
-#include "test/yuv_video_source.h"
#include "vp9/decoder/vp9_decoder.h"
-typedef vpx_codec_stream_info_t vp9_stream_info_t;
-struct vpx_codec_alg_priv {
- vpx_codec_priv_t base;
- vpx_codec_dec_cfg_t cfg;
- vp9_stream_info_t si;
- struct VP9Decoder *pbi;
- int postproc_cfg_set;
- vp8_postproc_cfg_t postproc_cfg;
- vpx_decrypt_cb decrypt_cb;
- void *decrypt_state;
- vpx_image_t img;
- int img_avail;
- int flushed;
- int invert_tile_order;
- int frame_parallel_decode;
-
- // External frame buffer info to save for VP9 common.
- void *ext_priv; // Private data associated with the external frame buffers.
- vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
- vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
-};
-
-static vpx_codec_alg_priv_t *get_alg_priv(vpx_codec_ctx_t *ctx) {
- return (vpx_codec_alg_priv_t *)ctx->priv;
-}
+#include "vp9/vp9_dx_iface.c"
namespace {
-const unsigned int kFramerate = 50;
const int kCpuUsed = 2;
struct EncodePerfTestVideo {
@@ -71,30 +45,20 @@
};
const EncodeParameters kVP9EncodeParameterSet[] = {
- {0, 0, 0, 1, 0, VPX_CS_BT_601},
- {0, 0, 0, 0, 0, VPX_CS_BT_709},
- {0, 0, 1, 0, 0, VPX_CS_BT_2020},
- {0, 2, 0, 0, 1, VPX_CS_UNKNOWN},
- // TODO(JBB): Test profiles (requires more work).
+ {0, 0, 0, 1, 0, VPX_CS_BT_601},
+ {0, 0, 0, 0, 0, VPX_CS_BT_709},
+ {0, 0, 1, 0, 0, VPX_CS_BT_2020},
+ {0, 2, 0, 0, 1, VPX_CS_UNKNOWN},
+ // TODO(JBB): Test profiles (requires more work).
};
-int is_extension_y4m(const char *filename) {
- const char *dot = strrchr(filename, '.');
- if (!dot || dot == filename)
- return 0;
- else
- return !strcmp(dot, ".y4m");
-}
-
class VpxEncoderParmsGetToDecoder
: public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWith2Params<EncodeParameters, \
+ public ::libvpx_test::CodecTestWith2Params<EncodeParameters,
EncodePerfTestVideo> {
protected:
VpxEncoderParmsGetToDecoder()
- : EncoderTest(GET_PARAM(0)),
- encode_parms(GET_PARAM(1)) {
- }
+ : EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}
virtual ~VpxEncoderParmsGetToDecoder() {}
@@ -126,33 +90,33 @@
}
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
- const libvpx_test::VideoSource& video,
+ const libvpx_test::VideoSource &video,
libvpx_test::Decoder *decoder) {
- vpx_codec_ctx_t* vp9_decoder = decoder->GetDecoder();
- vpx_codec_alg_priv_t* priv =
- (vpx_codec_alg_priv_t*) get_alg_priv(vp9_decoder);
-
- VP9Decoder* pbi = priv->pbi;
- VP9_COMMON* common = &pbi->common;
+ vpx_codec_ctx_t *const vp9_decoder = decoder->GetDecoder();
+ vpx_codec_alg_priv_t *const priv =
+ reinterpret_cast<vpx_codec_alg_priv_t *>(vp9_decoder->priv);
+ FrameWorkerData *const worker_data =
+ reinterpret_cast<FrameWorkerData *>(priv->frame_workers[0].data1);
+ VP9_COMMON *const common = &worker_data->pbi->common;
if (encode_parms.lossless) {
- EXPECT_EQ(common->base_qindex, 0);
- EXPECT_EQ(common->y_dc_delta_q, 0);
- EXPECT_EQ(common->uv_dc_delta_q, 0);
- EXPECT_EQ(common->uv_ac_delta_q, 0);
- EXPECT_EQ(common->tx_mode, ONLY_4X4);
+ EXPECT_EQ(0, common->base_qindex);
+ EXPECT_EQ(0, common->y_dc_delta_q);
+ EXPECT_EQ(0, common->uv_dc_delta_q);
+ EXPECT_EQ(0, common->uv_ac_delta_q);
+ EXPECT_EQ(ONLY_4X4, common->tx_mode);
}
- EXPECT_EQ(common->error_resilient_mode, encode_parms.error_resilient);
+ EXPECT_EQ(encode_parms.error_resilient, common->error_resilient_mode);
if (encode_parms.error_resilient) {
- EXPECT_EQ(common->frame_parallel_decoding_mode, 1);
- EXPECT_EQ(common->use_prev_frame_mvs, 0);
+ EXPECT_EQ(1, common->frame_parallel_decoding_mode);
+ EXPECT_EQ(0, common->use_prev_frame_mvs);
} else {
- EXPECT_EQ(common->frame_parallel_decoding_mode,
- encode_parms.frame_parallel);
+ EXPECT_EQ(encode_parms.frame_parallel,
+ common->frame_parallel_decoding_mode);
}
- EXPECT_EQ(common->color_space, encode_parms.cs);
- EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols);
- EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows);
+ EXPECT_EQ(encode_parms.cs, common->color_space);
+ EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols);
+ EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows);
EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
return VPX_CODEC_OK == res_dec;
@@ -164,35 +128,18 @@
EncodeParameters encode_parms;
};
-// TODO(hkuang): This test conflicts with frame parallel decode. So disable it
-// for now until fix.
-TEST_P(VpxEncoderParmsGetToDecoder, DISABLED_BitstreamParms) {
+TEST_P(VpxEncoderParmsGetToDecoder, BitstreamParms) {
init_flags_ = VPX_CODEC_USE_PSNR;
- libvpx_test::VideoSource *video;
- if (is_extension_y4m(test_video_.name)) {
- video = new libvpx_test::Y4mVideoSource(test_video_.name,
- 0, test_video_.frames);
- } else {
- video = new libvpx_test::YUVVideoSource(test_video_.name,
- VPX_IMG_FMT_I420,
- test_video_.width,
- test_video_.height,
- kFramerate, 1, 0,
- test_video_.frames);
- }
+ libvpx_test::VideoSource *const video =
+ new libvpx_test::Y4mVideoSource(test_video_.name, 0, test_video_.frames);
+ ASSERT_TRUE(video != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video));
- delete(video);
+ delete video;
}
-VP9_INSTANTIATE_TEST_CASE(
- VpxEncoderParmsGetToDecoder,
- ::testing::ValuesIn(kVP9EncodeParameterSet),
- ::testing::ValuesIn(kVP9EncodePerfTestVectors));
-
-VP10_INSTANTIATE_TEST_CASE(
- VpxEncoderParmsGetToDecoder,
- ::testing::ValuesIn(kVP9EncodeParameterSet),
- ::testing::ValuesIn(kVP9EncodePerfTestVectors));
+VP9_INSTANTIATE_TEST_CASE(VpxEncoderParmsGetToDecoder,
+ ::testing::ValuesIn(kVP9EncodeParameterSet),
+ ::testing::ValuesIn(kVP9EncodePerfTestVectors));
} // namespace
diff --git a/vp10/common/thread_common.h b/vp10/common/thread_common.h
index 6388c7a..a401ddc 100644
--- a/vp10/common/thread_common.h
+++ b/vp10/common/thread_common.h
@@ -14,6 +14,10 @@
#include "vp10/common/loopfilter.h"
#include "vpx_util/vpx_thread.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10Common;
struct FRAME_COUNTS;
@@ -54,4 +58,8 @@
void vp10_accumulate_frame_counts(struct VP10Common *cm,
struct FRAME_COUNTS *counts, int is_dec);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_COMMON_LOOPFILTER_THREAD_H_
diff --git a/vp10/common/x86/vp10_fwd_dct32x32_impl_sse2.h b/vp10/common/x86/vp10_fwd_dct32x32_impl_sse2.h
index ef78709..2490973 100644
--- a/vp10/common/x86/vp10_fwd_dct32x32_impl_sse2.h
+++ b/vp10/common/x86/vp10_fwd_dct32x32_impl_sse2.h
@@ -10,6 +10,7 @@
#include <emmintrin.h> // SSE2
+#include "./vp10_rtcd.h"
#include "vp10/common/vp10_fwd_txfm.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_dsp/x86/txfm_common_sse2.h"
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index f1a7aa1..e31cf72 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -2073,7 +2073,8 @@
static void debug_check_frame_counts(const VP10_COMMON *const cm) {
FRAME_COUNTS zero_counts;
vp10_zero(zero_counts);
- assert(cm->frame_parallel_decoding_mode || cm->error_resilient_mode);
+ assert(cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_BACKWARD ||
+ cm->error_resilient_mode);
assert(!memcmp(cm->counts.y_mode, zero_counts.y_mode,
sizeof(cm->counts.y_mode)));
assert(!memcmp(cm->counts.uv_mode, zero_counts.uv_mode,
diff --git a/vp10/decoder/dthread.h b/vp10/decoder/dthread.h
index 7332aad..1b0dc01 100644
--- a/vp10/decoder/dthread.h
+++ b/vp10/decoder/dthread.h
@@ -15,6 +15,10 @@
#include "vpx_util/vpx_thread.h"
#include "vpx/internal/vpx_codec_internal.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10Common;
struct VP10Decoder;
@@ -63,4 +67,8 @@
void vp10_frameworker_copy_context(VPxWorker *const dst_worker,
VPxWorker *const src_worker);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_DECODER_DTHREAD_H_
diff --git a/vp10/encoder/context_tree.h b/vp10/encoder/context_tree.h
index 9310d1f..67a07cb 100644
--- a/vp10/encoder/context_tree.h
+++ b/vp10/encoder/context_tree.h
@@ -14,6 +14,10 @@
#include "vp10/common/blockd.h"
#include "vp10/encoder/block.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10_COMP;
struct VP10Common;
struct ThreadData;
@@ -84,4 +88,8 @@
void vp10_setup_pc_tree(struct VP10Common *cm, struct ThreadData *td);
void vp10_free_pc_tree(struct ThreadData *td);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* VP10_ENCODER_CONTEXT_TREE_H_ */
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index 06cce93..58c6423 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -3623,6 +3623,7 @@
cpi->refresh_last_frame = 1;
cm->frame_to_show = get_frame_new_buffer(cm);
+ cm->frame_to_show->color_space = cm->color_space;
// Pick the loop filter level for the frame.
loopfilter_frame(cpi, cm);
diff --git a/vp10/encoder/ethread.h b/vp10/encoder/ethread.h
index 997df0d..d72816c 100644
--- a/vp10/encoder/ethread.h
+++ b/vp10/encoder/ethread.h
@@ -11,6 +11,10 @@
#ifndef VP10_ENCODER_ETHREAD_H_
#define VP10_ENCODER_ETHREAD_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10_COMP;
struct ThreadData;
@@ -22,4 +26,8 @@
void vp10_encode_tiles_mt(struct VP10_COMP *cpi);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_ENCODER_ETHREAD_H_
diff --git a/vp10/encoder/resize.h b/vp10/encoder/resize.h
index 131fc80..bf63770 100644
--- a/vp10/encoder/resize.h
+++ b/vp10/encoder/resize.h
@@ -14,6 +14,10 @@
#include <stdio.h>
#include "vpx/vpx_integer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void vp10_resize_plane(const uint8_t *const input,
int height,
int width,
@@ -121,4 +125,9 @@
int owidth,
int bd);
#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_ENCODER_RESIZE_H_
diff --git a/vp10/vp10_dx_iface.c b/vp10/vp10_dx_iface.c
index e2feca7..a8f9aa3 100644
--- a/vp10/vp10_dx_iface.c
+++ b/vp10/vp10_dx_iface.c
@@ -88,7 +88,8 @@
(void)data;
if (!ctx->priv) {
- vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
+ vpx_codec_alg_priv_t *const priv =
+ (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv));
if (priv == NULL)
return VPX_CODEC_MEM_ERROR;
diff --git a/vp10/vp10_iface_common.h b/vp10/vp10_iface_common.h
index 4bc3437..8e1bfc2 100644
--- a/vp10/vp10_iface_common.h
+++ b/vp10/vp10_iface_common.h
@@ -56,7 +56,7 @@
if (yv12->flags & YV12_FLAG_HIGHBITDEPTH) {
// vpx_image_t uses byte strides and a pointer to the first byte
// of the image.
- img->fmt |= VPX_IMG_FMT_HIGHBITDEPTH;
+ img->fmt = (vpx_img_fmt_t)(img->fmt | VPX_IMG_FMT_HIGHBITDEPTH);
img->bit_depth = yv12->bit_depth;
img->planes[VPX_PLANE_Y] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->y_buffer);
img->planes[VPX_PLANE_U] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->u_buffer);
diff --git a/vp9/common/vp9_thread_common.h b/vp9/common/vp9_thread_common.h
index 07af1bc..04666b6 100644
--- a/vp9/common/vp9_thread_common.h
+++ b/vp9/common/vp9_thread_common.h
@@ -14,6 +14,10 @@
#include "vp9/common/vp9_loopfilter.h"
#include "vpx_util/vpx_thread.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9Common;
struct FRAME_COUNTS;
@@ -54,4 +58,8 @@
void vp9_accumulate_frame_counts(struct VP9Common *cm,
struct FRAME_COUNTS *counts, int is_dec);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_COMMON_VP9_LOOPFILTER_THREAD_H_
diff --git a/vp9/decoder/vp9_dthread.h b/vp9/decoder/vp9_dthread.h
index f6cdccd..ba7c38a 100644
--- a/vp9/decoder/vp9_dthread.h
+++ b/vp9/decoder/vp9_dthread.h
@@ -15,6 +15,10 @@
#include "vpx_util/vpx_thread.h"
#include "vpx/internal/vpx_codec_internal.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9Common;
struct VP9Decoder;
@@ -63,4 +67,8 @@
void vp9_frameworker_copy_context(VPxWorker *const dst_worker,
VPxWorker *const src_worker);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_DECODER_VP9_DTHREAD_H_
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c
index ebef1a2..e17b397 100644
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -232,10 +232,12 @@
// don't update the map for them. For cases where motion is non-zero or
// the reference frame isn't the previous frame, the previous value in
// the map for this spatial location is not entirely correct.
- if (!is_inter_block(mbmi) || !skip)
+ if ((!is_inter_block(mbmi) || !skip) &&
+ mbmi->segment_id <= CR_SEGMENT_ID_BOOST2) {
cr->last_coded_q_map[map_offset] = clamp(
cm->base_qindex + cr->qindex_delta[mbmi->segment_id], 0, MAXQ);
- else if (is_inter_block(mbmi) && skip) {
+ } else if (is_inter_block(mbmi) && skip &&
+ mbmi->segment_id <= CR_SEGMENT_ID_BOOST2) {
cr->last_coded_q_map[map_offset] = VPXMIN(
clamp(cm->base_qindex + cr->qindex_delta[mbmi->segment_id],
0, MAXQ),
@@ -447,6 +449,10 @@
cr->motion_thresh = 32;
cr->rate_boost_fac = 17;
}
+ if (cpi->svc.spatial_layer_id > 0) {
+ cr->motion_thresh = 4;
+ cr->rate_boost_fac = 12;
+ }
}
// Setup cyclic background refresh: set delta q and segmentation map.
@@ -458,11 +464,10 @@
const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc);
if (cm->current_video_frame == 0)
cr->low_content_avg = 0.0;
- // Don't apply refresh on key frame or enhancement layer frames.
+ // Don't apply refresh on key frame or temporal enhancement layer frames.
if (!apply_cyclic_refresh ||
(cm->frame_type == KEY_FRAME) ||
- (cpi->svc.temporal_layer_id > 0) ||
- (cpi->svc.spatial_layer_id > 0)) {
+ (cpi->svc.temporal_layer_id > 0)) {
// Set segmentation map to 0 and disable.
unsigned char *const seg_map = cpi->segmentation_map;
memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
diff --git a/vp9/encoder/vp9_context_tree.h b/vp9/encoder/vp9_context_tree.h
index ac24497..8e365ce 100644
--- a/vp9/encoder/vp9_context_tree.h
+++ b/vp9/encoder/vp9_context_tree.h
@@ -14,6 +14,10 @@
#include "vp9/common/vp9_blockd.h"
#include "vp9/encoder/vp9_block.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9_COMP;
struct VP9Common;
struct ThreadData;
@@ -84,4 +88,8 @@
void vp9_setup_pc_tree(struct VP9Common *cm, struct ThreadData *td);
void vp9_free_pc_tree(struct ThreadData *td);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* VP9_ENCODER_VP9_CONTEXT_TREE_H_ */
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 7a4cf3c..60c6cec 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -412,6 +412,8 @@
vpx_free_frame_buffer(&cpi->svc.empty_frame.img);
memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
+
+ vp9_free_svc_cyclic_refresh(cpi);
}
static void save_coding_context(VP9_COMP *cpi) {
@@ -3200,7 +3202,8 @@
cpi->Source = vp9_scale_if_required(cm,
cpi->un_scaled_source,
- &cpi->scaled_source);
+ &cpi->scaled_source,
+ (cpi->oxcf.pass == 0));
// Avoid scaling last_source unless its needed.
// Last source is currently only used for screen-content mode,
@@ -3210,7 +3213,8 @@
cpi->sf.partition_search_type == SOURCE_VAR_BASED_PARTITION))
cpi->Last_Source = vp9_scale_if_required(cm,
cpi->unscaled_last_source,
- &cpi->scaled_last_source);
+ &cpi->scaled_last_source,
+ (cpi->oxcf.pass == 0));
if (cpi->oxcf.pass == 0 &&
cpi->oxcf.rc_mode == VPX_CBR &&
@@ -3342,11 +3346,13 @@
}
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
- &cpi->scaled_source);
+ &cpi->scaled_source,
+ (cpi->oxcf.pass == 0));
if (cpi->unscaled_last_source != NULL)
cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
- &cpi->scaled_last_source);
+ &cpi->scaled_last_source,
+ (cpi->oxcf.pass == 0));
if (frame_is_intra_only(cm) == 0) {
if (loop_count > 0) {
@@ -3597,20 +3603,17 @@
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
YV12_BUFFER_CONFIG *unscaled,
- YV12_BUFFER_CONFIG *scaled) {
+ YV12_BUFFER_CONFIG *scaled,
+ int use_normative_scaler) {
if (cm->mi_cols * MI_SIZE != unscaled->y_width ||
cm->mi_rows * MI_SIZE != unscaled->y_height) {
#if CONFIG_VP9_HIGHBITDEPTH
- if (unscaled->y_width == (scaled->y_width << 1) &&
- unscaled->y_height == (scaled->y_height << 1))
+ if (use_normative_scaler)
scale_and_extend_frame(unscaled, scaled, (int)cm->bit_depth);
else
scale_and_extend_frame_nonnormative(unscaled, scaled, (int)cm->bit_depth);
#else
- // Use the faster normative (convolve8) scaling filter: for now only for
- // scaling factor of 2.
- if (unscaled->y_width == (scaled->y_width << 1) &&
- unscaled->y_height == (scaled->y_height << 1))
+ if (use_normative_scaler)
scale_and_extend_frame(unscaled, scaled);
else
scale_and_extend_frame_nonnormative(unscaled, scaled);
@@ -3813,6 +3816,7 @@
cpi->refresh_last_frame = 1;
cm->frame_to_show = get_frame_new_buffer(cm);
+ cm->frame_to_show->color_space = cm->color_space;
// Pick the loop filter level for the frame.
loopfilter_frame(cpi, cm);
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 7c21018..c3a9839 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -613,7 +613,8 @@
YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
YV12_BUFFER_CONFIG *unscaled,
- YV12_BUFFER_CONFIG *scaled);
+ YV12_BUFFER_CONFIG *scaled,
+ int use_normative_scaler);
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
diff --git a/vp9/encoder/vp9_ethread.h b/vp9/encoder/vp9_ethread.h
index e87c50b..1efa4dc 100644
--- a/vp9/encoder/vp9_ethread.h
+++ b/vp9/encoder/vp9_ethread.h
@@ -11,6 +11,10 @@
#ifndef VP9_ENCODER_VP9_ETHREAD_H_
#define VP9_ENCODER_VP9_ETHREAD_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9_COMP;
struct ThreadData;
@@ -22,4 +26,8 @@
void vp9_encode_tiles_mt(struct VP9_COMP *cpi);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_ENCODER_VP9_ETHREAD_H_
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 51cc403..a6b5ebb 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -597,7 +597,7 @@
(cpi->ref_frame_flags & VP9_GOLD_FLAG) ? GOLDEN_FRAME : NONE);
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
- &cpi->scaled_source);
+ &cpi->scaled_source, 0);
}
vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index f57c525..973cde8 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -533,8 +533,7 @@
do {
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cm->seg.enabled &&
- cpi->svc.temporal_layer_id == 0 &&
- cpi->svc.spatial_layer_id == 0) {
+ cpi->svc.temporal_layer_id == 0) {
bits_per_mb_at_this_q =
(int)vp9_cyclic_refresh_rc_bits_per_mb(cpi, i, correction_factor);
} else {
@@ -1354,7 +1353,7 @@
rc->total_target_vs_actual = rc->total_actual_bits - rc->total_target_bits;
- if (!cpi->use_svc) {
+ if (!cpi->use_svc || is_two_pass_svc(cpi)) {
if (is_altref_enabled(cpi) && cpi->refresh_alt_ref_frame &&
(cm->frame_type != KEY_FRAME))
// Update the alternate reference frame stats as appropriate.
@@ -1832,8 +1831,8 @@
}
// Resize based on average buffer underflow and QP over some window.
// Ignore samples close to key frame, since QP is usually high after key.
- if (cpi->rc.frames_since_key > 2 * cpi->framerate) {
- const int window = (int)(5 * cpi->framerate);
+ if (cpi->rc.frames_since_key > 1 * cpi->framerate) {
+ const int window = (int)(4 * cpi->framerate);
cpi->resize_avg_qp += cm->base_qindex;
if (cpi->rc.buffer_level < (int)(30 * rc->optimal_buffer_level / 100))
++cpi->resize_buffer_underflow;
diff --git a/vp9/encoder/vp9_resize.h b/vp9/encoder/vp9_resize.h
index 067af53..b5feb38 100644
--- a/vp9/encoder/vp9_resize.h
+++ b/vp9/encoder/vp9_resize.h
@@ -14,6 +14,10 @@
#include <stdio.h>
#include "vpx/vpx_integer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void vp9_resize_plane(const uint8_t *const input,
int height,
int width,
@@ -121,4 +125,9 @@
int owidth,
int bd);
#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_ENCODER_VP9_RESIZE_H_
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index a6c5373..58d273f 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -10,6 +10,7 @@
#include <math.h>
+#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
#include "vp9/encoder/vp9_extend.h"
@@ -22,6 +23,8 @@
void vp9_init_layer_context(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
+ int mi_rows = cpi->common.mi_rows;
+ int mi_cols = cpi->common.mi_cols;
int sl, tl;
int alt_ref_idx = svc->number_spatial_layers;
@@ -52,6 +55,7 @@
int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
RATE_CONTROL *const lrc = &lc->rc;
+ size_t last_coded_q_map_size;
int i;
lc->current_video_frame_in_layer = 0;
lc->layer_size = 0;
@@ -94,6 +98,22 @@
lrc->buffer_level = oxcf->starting_buffer_level_ms *
lc->target_bandwidth / 1000;
lrc->bits_off_target = lrc->buffer_level;
+
+ // Initialize the cyclic refresh parameters. If spatial layers are used
+ // (i.e., ss_number_layers > 1), these need to be updated per spatial
+ // layer.
+ // Cyclic refresh is only applied on base temporal layer.
+ if (oxcf->ss_number_layers > 1 &&
+ tl == 0) {
+ lc->sb_index = 0;
+ lc->map = vpx_malloc(mi_rows * mi_cols * sizeof(signed char));
+ memset(lc->map, 0, mi_rows * mi_cols);
+ last_coded_q_map_size =
+ mi_rows * mi_cols * sizeof(uint8_t);
+ lc->last_coded_q_map = vpx_malloc(last_coded_q_map_size);
+ assert(MAXQ <= 255);
+ memset(lc->last_coded_q_map, MAXQ, last_coded_q_map_size);
+ }
}
}
@@ -257,6 +277,21 @@
cpi->rc.frames_since_key = old_frame_since_key;
cpi->rc.frames_to_key = old_frame_to_key;
}
+
+ // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
+ // for the base temporal layer.
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cpi->svc.number_spatial_layers > 1 &&
+ cpi->svc.temporal_layer_id == 0) {
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ signed char *temp = cr->map;
+ uint8_t *temp2 = cr->last_coded_q_map;
+ cr->map = lc->map;
+ lc->map = temp;
+ cr->last_coded_q_map = lc->last_coded_q_map;
+ lc->last_coded_q_map = temp2;
+ cr->sb_index = lc->sb_index;
+ }
}
void vp9_save_layer_context(VP9_COMP *const cpi) {
@@ -267,6 +302,21 @@
lc->twopass = cpi->twopass;
lc->target_bandwidth = (int)oxcf->target_bandwidth;
lc->alt_ref_source = cpi->alt_ref_source;
+
+ // For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
+ // for the base temporal layer.
+ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
+ cpi->svc.number_spatial_layers > 1 &&
+ cpi->svc.temporal_layer_id == 0) {
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ signed char *temp = lc->map;
+ uint8_t *temp2 = lc->last_coded_q_map;
+ lc->map = cr->map;
+ cr->map = temp;
+ lc->last_coded_q_map = cr->last_coded_q_map;
+ cr->last_coded_q_map = temp2;
+ lc->sb_index = cr->sb_index;
+ }
}
void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
@@ -504,6 +554,14 @@
cpi->svc.number_temporal_layers +
cpi->svc.temporal_layer_id];
+ // Setting the worst/best_quality via the encoder control: SET_SVC_PARAMETERS,
+ // only for non-BYPASS mode for now.
+ if (cpi->svc.temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
+ RATE_CONTROL *const lrc = &lc->rc;
+ lrc->worst_quality = vp9_quantizer_to_qindex(lc->max_q);
+ lrc->best_quality = vp9_quantizer_to_qindex(lc->min_q);
+ }
+
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
lc->scaling_factor_num, lc->scaling_factor_den,
&width, &height);
@@ -642,3 +700,19 @@
}
return buf;
}
+
+void vp9_free_svc_cyclic_refresh(VP9_COMP *const cpi) {
+ int sl, tl;
+ SVC *const svc = &cpi->svc;
+ const VP9EncoderConfig *const oxcf = &cpi->oxcf;
+ for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
+ for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
+ int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
+ LAYER_CONTEXT *const lc = &svc->layer_context[layer];
+ if (lc->map)
+ vpx_free(lc->map);
+ if (lc->last_coded_q_map)
+ vpx_free(lc->last_coded_q_map);
+ }
+ }
+}
diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h
index b6a5ea5..168edbf 100644
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -41,6 +41,10 @@
int has_alt_frame;
size_t layer_size;
struct vpx_psnr_pkt psnr_pkt;
+ // Cyclic refresh parameters (aq-mode=3), that need to be updated per-frame.
+ int sb_index;
+ signed char *map;
+ uint8_t *last_coded_q_map;
} LAYER_CONTEXT;
typedef struct {
@@ -115,6 +119,8 @@
int vp9_one_pass_cbr_svc_start_layer(struct VP9_COMP *const cpi);
+void vp9_free_svc_cyclic_refresh(struct VP9_COMP *const cpi);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index 6ef3b49..16f9c85 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -721,7 +721,7 @@
"Failed to reallocate alt_ref_buffer");
}
frames[frame] = vp9_scale_if_required(
- cm, frames[frame], &cpi->svc.scaled_frames[frame_used]);
+ cm, frames[frame], &cpi->svc.scaled_frames[frame_used], 0);
++frame_used;
}
}
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index 8119df8..eb2371e 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -88,7 +88,8 @@
(void)data;
if (!ctx->priv) {
- vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
+ vpx_codec_alg_priv_t *const priv =
+ (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv));
if (priv == NULL)
return VPX_CODEC_MEM_ERROR;
diff --git a/vp9/vp9_iface_common.h b/vp9/vp9_iface_common.h
index 58bb7d5..da7ae0e 100644
--- a/vp9/vp9_iface_common.h
+++ b/vp9/vp9_iface_common.h
@@ -56,7 +56,7 @@
if (yv12->flags & YV12_FLAG_HIGHBITDEPTH) {
// vpx_image_t uses byte strides and a pointer to the first byte
// of the image.
- img->fmt |= VPX_IMG_FMT_HIGHBITDEPTH;
+ img->fmt = (vpx_img_fmt_t)(img->fmt | VPX_IMG_FMT_HIGHBITDEPTH);
img->bit_depth = yv12->bit_depth;
img->planes[VPX_PLANE_Y] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->y_buffer);
img->planes[VPX_PLANE_U] = (uint8_t*)CONVERT_TO_SHORTPTR(yv12->u_buffer);
diff --git a/vpx/svc_context.h b/vpx/svc_context.h
index a09651c..432c3c7 100644
--- a/vpx/svc_context.h
+++ b/vpx/svc_context.h
@@ -40,6 +40,7 @@
int output_rc_stat; // for outputting rc stats
int speed; // speed setting for codec
int threads;
+ int aqmode; // turns on aq-mdoe=3 (cyclic_refresh): 0=off, 1=on.
// private storage for vpx_svc_encode
void *internal;
} SvcContext;