From: James Zern Date: Fri, 18 Sep 2015 23:18:10 +0000 (+0000) Subject: Merge "configure: add --extra-cxxflags option" X-Git-Tag: v1.5.0~136 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=57694362e027c2e76c7a06bfc64f6e46735cf612;hp=12355c4c4c356057656f5f07c9cc46691d7f4c6c;p=platform%2Fupstream%2Flibvpx.git Merge "configure: add --extra-cxxflags option" --- diff --git a/build/make/iosbuild.sh b/build/make/iosbuild.sh index 89fa681..927f3e5 100755 --- a/build/make/iosbuild.sh +++ b/build/make/iosbuild.sh @@ -41,13 +41,22 @@ TARGETS="arm64-darwin-gcc build_target() { local target="$1" local old_pwd="$(pwd)" + local target_specific_flags="" vlog "***Building target: ${target}***" + case "${target}" in + x86-*) + target_specific_flags="--enable-pic" + vlog "Enabled PIC for ${target}" + ;; + esac + mkdir "${target}" cd "${target}" eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \ - ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${devnull} + ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \ + ${devnull} export DIST_DIR eval make -j ${MAKE_JOBS} dist ${devnull} cd "${old_pwd}" @@ -199,6 +208,8 @@ cat << EOF --show-build-output: Show output from each library build. --targets : Override default target list. Defaults: ${TARGETS} + --test-link: Confirms all targets can be linked. Functionally identical to + passing --enable-examples via --extra-configure-args. --verbose: Output information about the environment and each stage of the build. EOF @@ -237,6 +248,9 @@ while [ -n "$1" ]; do --show-build-output) devnull= ;; + --test-link) + EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples" + ;; --targets) TARGETS="$2" shift diff --git a/examples/vp9_spatial_svc_encoder.c b/examples/vp9_spatial_svc_encoder.c index af8aa86..b26e987 100644 --- a/examples/vp9_spatial_svc_encoder.c +++ b/examples/vp9_spatial_svc_encoder.c @@ -80,6 +80,8 @@ static const arg_def_t rc_end_usage_arg = 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 @@ static const arg_def_t *svc_args[] = { &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 @@ static void parse_command_line(int argc, const char **argv_, #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)) { @@ -540,6 +544,59 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, } #endif +// Example pattern for spatial layers and 2 temporal layers used in the +// bypass/flexible mode. The pattern corresponds to the pattern +// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in +// non-flexible mode. +void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers, + int is_key_frame, + vpx_svc_ref_frame_config_t *ref_frame_config) { + for (sl = 0; sl < num_spatial_layers; ++sl) { + if (!tl) { + if (!sl) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + if (is_key_frame) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } else { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + } + } + } else if (tl == 1) { + if (!sl) { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF | + VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF; + } else { + ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_UPD_GF; + } + } + if (tl == 0) { + ref_frame_config->lst_fb_idx[sl] = sl; + if (sl) + ref_frame_config->gld_fb_idx[sl] = sl - 1; + else + ref_frame_config->gld_fb_idx[sl] = 0; + ref_frame_config->alt_fb_idx[sl] = 0; + } else if (tl == 1) { + ref_frame_config->lst_fb_idx[sl] = sl; + ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1; + ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl; + } + } +} + int main(int argc, const char **argv) { AppInput app_input = {0}; VpxVideoWriter *writer = NULL; @@ -560,6 +617,7 @@ int main(int argc, const char **argv) { VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; struct RateControlStats rc; vpx_svc_layer_id_t layer_id; + vpx_svc_ref_frame_config_t ref_frame_config; int sl, tl; double sum_bitrate = 0.0; double sum_bitrate2 = 0.0; @@ -635,7 +693,7 @@ int main(int argc, const char **argv) { 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); @@ -649,6 +707,30 @@ int main(int argc, const char **argv) { end_of_stream = 1; } + // For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates) + // and the buffer indices for each spatial layer of the current + // (super)frame to be encoded. The temporal layer_id for the current frame + // also needs to be set. + // TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS" + // mode to "VP9E_LAYERING_MODE_BYPASS". + if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + // Example for 2 temporal layers. + if (frame_cnt % 2 == 0) + layer_id.temporal_layer_id = 0; + else + layer_id.temporal_layer_id = 1; + // Note that we only set the temporal layer_id, since we are calling + // the encode for the whole superframe. The encoder will internally loop + // over all the spatial layers for the current superframe. + vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id); + set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id, + svc_ctx.spatial_layers, + frame_cnt == 0, + &ref_frame_config); + vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG, + &ref_frame_config); + } + vpx_usec_timer_start(&timer); res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw), pts, frame_duration, svc_ctx.speed >= 5 ? diff --git a/test/resize_test.cc b/test/resize_test.cc index f1134aa..a86c9d1 100644 --- a/test/resize_test.cc +++ b/test/resize_test.cc @@ -81,6 +81,15 @@ static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt, 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 @@ class ResizeTest : public ::libvpx_test::EncoderTest, 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,134 @@ TEST_P(ResizeInternalTest, TestInternalResizeWorks) { } } +class ResizeInternalRealtimeTest : public ::libvpx_test::EncoderTest, + public ::libvpx_test::CodecTestWith2Params { + 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_); + } + + if (change_bitrate_ && video->frame() == 120) { + change_bitrate_ = false; + cfg_.rc_target_bitrate = 500; + encoder->Config(&cfg_); + } + } + + 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_; + bool change_bitrate_; +}; + +// 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, TestInternalResizeDown) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 299); + DefaultConfig(); + change_bitrate_ = false; + 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::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."; +} + +// Verify the dynamic resizer behavior for real time, 1 pass CBR mode. +// Start at low target bitrate, raise the bitrate in the middle of the clip, +// scaling-up should occur after bitrate changed. +TEST_P(ResizeInternalRealtimeTest, TestInternalResizeDownUpChangeBitRate) { + ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, + 30, 1, 0, 299); + DefaultConfig(); + change_bitrate_ = true; + // Disable dropped frames. + cfg_.rc_dropframe_thresh = 0; + // Starting bitrate low. + cfg_.rc_target_bitrate = 100; + 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::const_iterator info = frame_info_list_.begin(); + info != frame_info_list_.end(); ++info) { + if (info->w != last_w || info->h != last_h) { + resize_count++; + if (resize_count == 1) { + // Verify that resize down occurs. + ASSERT_LT(info->w, last_w); + ASSERT_LT(info->h, last_h); + } else if (resize_count == 2) { + // Verify that resize up occurs. + ASSERT_GT(info->w, last_w); + ASSERT_GT(info->h, last_h); + } + last_w = info->w; + last_h = info->h; + } + } + + // Verify that we get 2 resize events in this test. + ASSERT_EQ(2, resize_count) << "Resizing should occur twice."; +} + vpx_img_fmt_t CspForFrameNumber(int frame) { if (frame < 10) return VPX_IMG_FMT_I420; @@ -371,6 +499,9 @@ VP9_INSTANTIATE_TEST_CASE(ResizeTest, ::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_arf_freq_test.cc b/test/vp9_arf_freq_test.cc index 87ff15b..89200d4 100644 --- a/test/vp9_arf_freq_test.cc +++ b/test/vp9_arf_freq_test.cc @@ -230,9 +230,23 @@ VP9_INSTANTIATE_TEST_CASE( ::testing::ValuesIn(kEncodeVectors), ::testing::ValuesIn(kMinArfVectors)); +#if CONFIG_VP9_HIGHBITDEPTH +# if CONFIG_VP10_ENCODER +// TODO(angiebird): 25-29 fail in high bitdepth mode. +INSTANTIATE_TEST_CASE_P( + DISABLED_VP10, ArfFreqTest, + ::testing::Combine( + ::testing::Values(static_cast( + &libvpx_test::kVP10)), + ::testing::ValuesIn(kTestVectors), + ::testing::ValuesIn(kEncodeVectors), + ::testing::ValuesIn(kMinArfVectors))); +# endif // CONFIG_VP10_ENCODER +#else VP10_INSTANTIATE_TEST_CASE( ArfFreqTest, ::testing::ValuesIn(kTestVectors), ::testing::ValuesIn(kEncodeVectors), ::testing::ValuesIn(kMinArfVectors)); +#endif // CONFIG_VP9_HIGHBITDEPTH } // namespace diff --git a/test/vp9_encoder_parms_get_to_decoder.cc b/test/vp9_encoder_parms_get_to_decoder.cc index a02070e..901605d 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 { @@ -66,35 +40,26 @@ struct EncodeParameters { int32_t lossless; int32_t error_resilient; int32_t frame_parallel; + int32_t color_range; vpx_color_space_t cs; // TODO(JBB): quantizers / bitrate }; 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, 0, VPX_CS_BT_601}, + {0, 0, 0, 0, 0, 1, VPX_CS_BT_709}, + {0, 0, 1, 0, 0, 1, VPX_CS_BT_2020}, + {0, 2, 0, 0, 1, 0, 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 { protected: VpxEncoderParmsGetToDecoder() - : EncoderTest(GET_PARAM(0)), - encode_parms(GET_PARAM(1)) { - } + : EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {} virtual ~VpxEncoderParmsGetToDecoder() {} @@ -112,6 +77,7 @@ class VpxEncoderParmsGetToDecoder ::libvpx_test::Encoder *encoder) { if (video->frame() == 1) { encoder->Control(VP9E_SET_COLOR_SPACE, encode_parms.cs); + encoder->Control(VP9E_SET_COLOR_RANGE, encode_parms.color_range); encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless); encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, encode_parms.frame_parallel); @@ -126,33 +92,34 @@ class VpxEncoderParmsGetToDecoder } 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(vp9_decoder->priv); + FrameWorkerData *const worker_data = + reinterpret_cast(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.color_range, common->color_range); + 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 +131,18 @@ class VpxEncoderParmsGetToDecoder 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/blockd.h b/vp10/common/blockd.h index 52c77cd..db49d97 100644 --- a/vp10/common/blockd.h +++ b/vp10/common/blockd.h @@ -70,6 +70,9 @@ typedef struct { PREDICTION_MODE mode; TX_SIZE tx_size; int8_t skip; +#if CONFIG_MISC_FIXES + int8_t has_no_coeffs; +#endif int8_t segment_id; int8_t seg_id_predicted; // valid only when temporal_update is enabled @@ -176,7 +179,6 @@ typedef struct macroblockd { int mb_to_bottom_edge; FRAME_CONTEXT *fc; - int frame_parallel_decoding_mode; /* pointers to reference frames */ RefBuffer *block_refs[2]; diff --git a/vp10/common/entropymv.c b/vp10/common/entropymv.c index ebf7a07..6b99606 100644 --- a/vp10/common/entropymv.c +++ b/vp10/common/entropymv.c @@ -161,17 +161,19 @@ static void inc_mv_component(int v, nmv_component_counts *comp_counts, } } -void vp10_inc_mv(const MV *mv, nmv_context_counts *counts) { +void vp10_inc_mv(const MV *mv, nmv_context_counts *counts, const int usehp) { if (counts != NULL) { const MV_JOINT_TYPE j = vp10_get_mv_joint(mv); ++counts->joints[j]; if (mv_joint_vertical(j)) { - inc_mv_component(mv->row, &counts->comps[0], 1, 1); + inc_mv_component(mv->row, &counts->comps[0], 1, + !CONFIG_MISC_FIXES || usehp); } if (mv_joint_horizontal(j)) { - inc_mv_component(mv->col, &counts->comps[1], 1, 1); + inc_mv_component(mv->col, &counts->comps[1], 1, + !CONFIG_MISC_FIXES || usehp); } } } diff --git a/vp10/common/entropymv.h b/vp10/common/entropymv.h index fd9f1c0..d1eb95c 100644 --- a/vp10/common/entropymv.h +++ b/vp10/common/entropymv.h @@ -124,7 +124,7 @@ typedef struct { nmv_component_counts comps[2]; } nmv_context_counts; -void vp10_inc_mv(const MV *mv, nmv_context_counts *mvctx); +void vp10_inc_mv(const MV *mv, nmv_context_counts *mvctx, const int usehp); #ifdef __cplusplus } // extern "C" diff --git a/vp10/common/loopfilter.c b/vp10/common/loopfilter.c index 1b1f67d..1b89ed5 100644 --- a/vp10/common/loopfilter.c +++ b/vp10/common/loopfilter.c @@ -754,8 +754,13 @@ static void build_masks(const loop_filter_info_n *const lfi_n, // If the block has no coefficients and is not intra we skip applying // the loop filter on block edges. +#if CONFIG_MISC_FIXES + if ((mbmi->skip || mbmi->has_no_coeffs) && is_inter_block(mbmi)) + return; +#else if (mbmi->skip && is_inter_block(mbmi)) return; +#endif // Here we are adding a mask for the transform size. The transform // size mask is set to be correct for a 64x64 prediction block size. We @@ -812,8 +817,13 @@ static void build_y_mask(const loop_filter_info_n *const lfi_n, *above_y |= above_prediction_mask[block_size] << shift_y; *left_y |= left_prediction_mask[block_size] << shift_y; +#if CONFIG_MISC_FIXES + if ((mbmi->skip || mbmi->has_no_coeffs) && is_inter_block(mbmi)) + return; +#else if (mbmi->skip && is_inter_block(mbmi)) return; +#endif *above_y |= (size_mask[block_size] & above_64x64_txform_mask[tx_size_y]) << shift_y; diff --git a/vp10/common/mvref_common.c b/vp10/common/mvref_common.c index c0a8456..2678560 100644 --- a/vp10/common/mvref_common.c +++ b/vp10/common/mvref_common.c @@ -125,8 +125,10 @@ static void find_mv_refs_idx(const VP10_COMMON *cm, const MACROBLOCKD *xd, } if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME && - prev_frame_mvs->ref_frame[1] != ref_frame && - prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int) { +#if !CONFIG_MISC_FIXES + prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int && +#endif + prev_frame_mvs->ref_frame[1] != ref_frame) { int_mv mv = prev_frame_mvs->mv[1]; if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] != ref_sign_bias[ref_frame]) { diff --git a/vp10/common/mvref_common.h b/vp10/common/mvref_common.h index 8e918b8..0774f70 100644 --- a/vp10/common/mvref_common.h +++ b/vp10/common/mvref_common.h @@ -180,8 +180,9 @@ static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref, ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias), \ refmv_count, mv_ref_list, Done); \ if (has_second_ref(mbmi) && \ - (mbmi)->ref_frame[1] != ref_frame && \ - (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) \ + (CONFIG_MISC_FIXES || \ + (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) && \ + (mbmi)->ref_frame[1] != ref_frame) \ ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias), \ refmv_count, mv_ref_list, Done); \ } \ diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h index 303a154..eeaadc6 100644 --- a/vp10/common/onyxc_int.h +++ b/vp10/common/onyxc_int.h @@ -63,6 +63,23 @@ typedef enum { RESET_FRAME_CONTEXT_ALL = 2, } RESET_FRAME_CONTEXT_MODE; +typedef enum { + /** + * Don't update frame context + */ + REFRESH_FRAME_CONTEXT_OFF, + /** + * Update frame context to values resulting from forward probability + * updates signaled in the frame header + */ + REFRESH_FRAME_CONTEXT_FORWARD, + /** + * Update frame context to values resulting from backward probability + * updates based on entropy/counts in the decoded frame + */ + REFRESH_FRAME_CONTEXT_BACKWARD, +} REFRESH_FRAME_CONTEXT_MODE; + typedef struct { int_mv mv[2]; MV_REFERENCE_FRAME ref_frame[2]; @@ -112,6 +129,7 @@ typedef struct BufferPool { typedef struct VP10Common { struct vpx_internal_error_info error; vpx_color_space_t color_space; + int color_range; int width; int height; int display_width; @@ -226,7 +244,9 @@ typedef struct VP10Common { loop_filter_info_n lf_info; - int refresh_frame_context; /* Two state 0 = NO, 1 = YES */ + // Flag signaling how frame contexts should be updated at the end of + // a frame decode + REFRESH_FRAME_CONTEXT_MODE refresh_frame_context; int ref_frame_sign_bias[MAX_REF_FRAMES]; /* Two state 0, 1 */ @@ -257,7 +277,6 @@ typedef struct VP10Common { #endif int error_resilient_mode; - int frame_parallel_decoding_mode; int log2_tile_cols, log2_tile_rows; int byte_alignment; @@ -372,7 +391,6 @@ static INLINE void vp10_init_macroblockd(VP10_COMMON *cm, MACROBLOCKD *xd, memcpy(xd->plane[i].seg_dequant, cm->uv_dequant, sizeof(cm->uv_dequant)); } xd->fc = cm->fc; - xd->frame_parallel_decoding_mode = cm->frame_parallel_decoding_mode; } xd->above_seg_context = cm->above_seg_context; diff --git a/vp10/common/reconinter.c b/vp10/common/reconinter.c index c9e46e0..97c4abc 100644 --- a/vp10/common/reconinter.c +++ b/vp10/common/reconinter.c @@ -135,20 +135,26 @@ static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize, const int mi_x = mi_col * MI_SIZE; const int mi_y = mi_row * MI_SIZE; for (plane = plane_from; plane <= plane_to; ++plane) { - const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, - &xd->plane[plane]); - const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize]; - const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize]; - const int bw = 4 * num_4x4_w; - const int bh = 4 * num_4x4_h; + const struct macroblockd_plane *pd = &xd->plane[plane]; + const int bw = 4 * num_4x4_blocks_wide_lookup[bsize] >> pd->subsampling_x; + const int bh = 4 * num_4x4_blocks_high_lookup[bsize] >> pd->subsampling_y; if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) { - int i = 0, x, y; + const PARTITION_TYPE bp = bsize - xd->mi[0]->mbmi.sb_type; + const int have_vsplit = bp != PARTITION_HORZ; + const int have_hsplit = bp != PARTITION_VERT; + const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x); + const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y); + const int pw = 8 >> (have_vsplit | pd->subsampling_x); + const int ph = 8 >> (have_hsplit | pd->subsampling_y); + int x, y; + assert(bp != PARTITION_NONE && bp < PARTITION_TYPES); assert(bsize == BLOCK_8X8); + assert(pw * num_4x4_w == bw && ph * num_4x4_h == bh); for (y = 0; y < num_4x4_h; ++y) for (x = 0; x < num_4x4_w; ++x) - build_inter_predictors(xd, plane, i++, bw, bh, - 4 * x, 4 * y, 4, 4, mi_x, mi_y); + build_inter_predictors(xd, plane, y * 2 + x, bw, bh, + 4 * x, 4 * y, pw, ph, mi_x, mi_y); } else { build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh, mi_x, mi_y); 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_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, 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 // 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 16706ee..50d50f8 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -81,12 +81,18 @@ static int decode_unsigned_max(struct vpx_read_bit_buffer *rb, int max) { return data > max ? max : data; } +#if CONFIG_MISC_FIXES +static TX_MODE read_tx_mode(struct vpx_read_bit_buffer *rb) { + return vpx_rb_read_bit(rb) ? TX_MODE_SELECT : vpx_rb_read_literal(rb, 2); +} +#else static TX_MODE read_tx_mode(vpx_reader *r) { TX_MODE tx_mode = vpx_read_literal(r, 2); if (tx_mode == ALLOW_32X32) tx_mode += vpx_read_bit(r); return tx_mode; } +#endif static void read_tx_mode_probs(struct tx_probs *tx_probs, vpx_reader *r) { int i, j; @@ -701,12 +707,19 @@ static void dec_build_inter_predictors_sb(VP10Decoder *const pbi, const int is_scaled = vp10_is_scaled(sf); if (sb_type < BLOCK_8X8) { - int i = 0, x, y; + const PARTITION_TYPE bp = BLOCK_8X8 - sb_type; + const int have_vsplit = bp != PARTITION_HORZ; + const int have_hsplit = bp != PARTITION_VERT; + const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x); + const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y); + const int pw = 8 >> (have_vsplit | pd->subsampling_x); + const int ph = 8 >> (have_hsplit | pd->subsampling_y); + int x, y; for (y = 0; y < num_4x4_h; ++y) { for (x = 0; x < num_4x4_w; ++x) { - const MV mv = average_split_mvs(pd, mi, ref, i++); + const MV mv = average_split_mvs(pd, mi, ref, y * 2 + x); dec_build_inter_predictors(pbi, xd, plane, n4w_x4, n4h_x4, - 4 * x, 4 * y, 4, 4, mi_x, mi_y, kernel, + 4 * x, 4 * y, pw, ph, mi_x, mi_y, kernel, sf, pre_buf, dst_buf, &mv, ref_frame_buf, is_scaled, ref); } @@ -858,7 +871,11 @@ static void decode_block(VP10Decoder *const pbi, MACROBLOCKD *const xd, } if (!less8x8 && eobtotal == 0) +#if CONFIG_MISC_FIXES + mbmi->has_no_coeffs = 1; // skip loopfilter +#else mbmi->skip = 1; // skip loopfilter +#endif } } @@ -1091,17 +1108,17 @@ static void setup_loopfilter(struct loopfilter *lf, for (i = 0; i < MAX_REF_FRAMES; i++) if (vpx_rb_read_bit(rb)) - lf->ref_deltas[i] = vpx_rb_read_signed_literal(rb, 6); + lf->ref_deltas[i] = vpx_rb_read_inv_signed_literal(rb, 6); for (i = 0; i < MAX_MODE_LF_DELTAS; i++) if (vpx_rb_read_bit(rb)) - lf->mode_deltas[i] = vpx_rb_read_signed_literal(rb, 6); + lf->mode_deltas[i] = vpx_rb_read_inv_signed_literal(rb, 6); } } } static INLINE int read_delta_q(struct vpx_read_bit_buffer *rb) { - return vpx_rb_read_bit(rb) ? vpx_rb_read_signed_literal(rb, 4) : 0; + return vpx_rb_read_bit(rb) ? vpx_rb_read_inv_signed_literal(rb, 4) : 0; } static void setup_quantization(VP10_COMMON *const cm, MACROBLOCKD *const xd, @@ -1228,6 +1245,7 @@ static void setup_frame_size(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; } static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, @@ -1309,6 +1327,7 @@ static void setup_frame_size_with_refs(VP10_COMMON *cm, pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; } static void setup_tile_info(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { @@ -1454,8 +1473,9 @@ static const uint8_t *decode_tiles(VP10Decoder *pbi, tile_data->cm = cm; tile_data->xd = pbi->mb; tile_data->xd.corrupted = 0; - tile_data->xd.counts = cm->frame_parallel_decoding_mode ? - NULL : &cm->counts; + tile_data->xd.counts = + cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD ? + &cm->counts : NULL; vp10_zero(tile_data->dqcoeff); vp10_tile_init(&tile_data->xd.tile, tile_data->cm, tile_row, tile_col); setup_token_decoder(buf->data, data_end, buf->size, &cm->error, @@ -1652,7 +1672,7 @@ static const uint8_t *decode_tiles_mt(VP10Decoder *pbi, } // Initialize thread frame counts. - if (!cm->frame_parallel_decoding_mode) { + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD) { int i; for (i = 0; i < num_workers; ++i) { @@ -1674,8 +1694,9 @@ static const uint8_t *decode_tiles_mt(VP10Decoder *pbi, tile_data->pbi = pbi; tile_data->xd = pbi->mb; tile_data->xd.corrupted = 0; - tile_data->xd.counts = cm->frame_parallel_decoding_mode ? - 0 : &tile_data->counts; + tile_data->xd.counts = + cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD ? + &tile_data->counts : NULL; vp10_zero(tile_data->dqcoeff); vp10_tile_init(tile, cm, 0, buf->col); vp10_tile_init(&tile_data->xd.tile, cm, 0, buf->col); @@ -1714,7 +1735,8 @@ static const uint8_t *decode_tiles_mt(VP10Decoder *pbi, } // Accumulate thread frame counts. - if (n >= tile_cols && !cm->frame_parallel_decoding_mode) { + if (n >= tile_cols && + cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD) { for (i = 0; i < num_workers; ++i) { TileWorkerData *const tile_data = (TileWorkerData*)pbi->tile_workers[i].data1; @@ -1746,7 +1768,8 @@ static void read_bitdepth_colorspace_sampling( } cm->color_space = vpx_rb_read_literal(rb, 3); if (cm->color_space != VPX_CS_SRGB) { - vpx_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range + // [16,235] (including xvycc) vs [0,255] range + cm->color_range = vpx_rb_read_bit(rb); if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { cm->subsampling_x = vpx_rb_read_bit(rb); cm->subsampling_y = vpx_rb_read_bit(rb); @@ -1777,6 +1800,9 @@ static void read_bitdepth_colorspace_sampling( static size_t read_uncompressed_header(VP10Decoder *pbi, struct vpx_read_bit_buffer *rb) { VP10_COMMON *const cm = &pbi->common; +#if CONFIG_MISC_FIXES + MACROBLOCKD *const xd = &pbi->mb; +#endif BufferPool *const pool = cm->buffer_pool; RefCntBuffer *const frame_bufs = pool->frame_bufs; int i, mask, ref_index = 0; @@ -1890,6 +1916,7 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, // specifies that the default color format should be YUV 4:2:0 in this // case (normative). cm->color_space = VPX_CS_BT_601; + cm->color_range = 0; cm->subsampling_y = cm->subsampling_x = 1; cm->bit_depth = VPX_BITS_8; #if CONFIG_VP9_HIGHBITDEPTH @@ -1940,6 +1967,7 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; #endif get_frame_new_buffer(cm)->color_space = cm->color_space; + get_frame_new_buffer(cm)->color_range = cm->color_range; if (pbi->need_resync) { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, @@ -1948,11 +1976,20 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, } if (!cm->error_resilient_mode) { - cm->refresh_frame_context = vpx_rb_read_bit(rb); - cm->frame_parallel_decoding_mode = vpx_rb_read_bit(rb); + cm->refresh_frame_context = + vpx_rb_read_bit(rb) ? REFRESH_FRAME_CONTEXT_FORWARD + : REFRESH_FRAME_CONTEXT_OFF; + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_FORWARD) { + cm->refresh_frame_context = + vpx_rb_read_bit(rb) ? REFRESH_FRAME_CONTEXT_FORWARD + : REFRESH_FRAME_CONTEXT_BACKWARD; +#if !CONFIG_MISC_FIXES + } else { + vpx_rb_read_bit(rb); // parallel decoding mode flag +#endif + } } else { - cm->refresh_frame_context = 0; - cm->frame_parallel_decoding_mode = 1; + cm->refresh_frame_context = REFRESH_FRAME_CONTEXT_OFF; } // This flag will be overridden by the call to vp10_setup_past_independence @@ -1990,6 +2027,9 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, setup_quantization(cm, &pbi->mb, rb); setup_segmentation(cm, rb); setup_segmentation_dequant(cm); +#if CONFIG_MISC_FIXES + cm->tx_mode = xd->lossless ? ONLY_4X4 : read_tx_mode(rb); +#endif setup_tile_info(cm, rb); sz = vpx_rb_read_literal(rb, 16); @@ -2004,7 +2044,9 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data, size_t partition_size) { VP10_COMMON *const cm = &pbi->common; +#if !CONFIG_MISC_FIXES MACROBLOCKD *const xd = &pbi->mb; +#endif FRAME_CONTEXT *const fc = cm->fc; vpx_reader r; int k; @@ -2014,7 +2056,9 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data, vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder 0"); +#if !CONFIG_MISC_FIXES cm->tx_mode = xd->lossless ? ONLY_4X4 : read_tx_mode(&r); +#endif if (cm->tx_mode == TX_MODE_SELECT) read_tx_mode_probs(&fc->tx_probs, &r); read_coef_probs(fc, cm->tx_mode, &r); @@ -2061,7 +2105,8 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data, 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, @@ -2187,10 +2232,11 @@ void vp10_decode_frame(VP10Decoder *pbi, // If encoded in frame parallel mode, frame context is ready after decoding // the frame header. - if (cm->frame_parallel_decode && cm->frame_parallel_decoding_mode) { + if (cm->frame_parallel_decode && + cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_BACKWARD) { VPxWorker *const worker = pbi->frame_worker_owner; FrameWorkerData *const frame_worker_data = worker->data1; - if (cm->refresh_frame_context) { + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_FORWARD) { context_updated = 1; cm->frame_contexts[cm->frame_context_idx] = *cm->fc; } @@ -2224,7 +2270,7 @@ void vp10_decode_frame(VP10Decoder *pbi, } if (!xd->corrupted) { - if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) { + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD) { vp10_adapt_coef_probs(cm); if (!frame_is_intra_only(cm)) { @@ -2240,6 +2286,7 @@ void vp10_decode_frame(VP10Decoder *pbi, } // Non frame parallel update frame context here. - if (cm->refresh_frame_context && !context_updated) + if (cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF && + !context_updated) cm->frame_contexts[cm->frame_context_idx] = *cm->fc; } diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c index b190f73..f157ada 100644 --- a/vp10/decoder/decodemv.c +++ b/vp10/decoder/decodemv.c @@ -294,7 +294,7 @@ static INLINE void read_mv(vpx_reader *r, MV *mv, const MV *ref, if (mv_joint_horizontal(joint_type)) diff.col = read_mv_component(r, &ctx->comps[1], use_hp); - vp10_inc_mv(&diff, counts); + vp10_inc_mv(&diff, counts, use_hp); mv->row = ref->row + diff.row; mv->col = ref->col + diff.col; 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_broadcast(RefCntBuffer *const buf, int row); 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/bitstream.c b/vp10/encoder/bitstream.c index c41f0ef..da51599 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -386,8 +386,7 @@ static void write_modes_b(VP10_COMP *cpi, const TileInfo *const tile, xd->mi = cm->mi_grid_visible + (mi_row * cm->mi_stride + mi_col); m = xd->mi[0]; - cpi->td.mb.mbmi_ext = cpi->td.mb.mbmi_ext_base + - (mi_row * cm->mi_cols + mi_col); + cpi->td.mb.mbmi_ext = cpi->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col); set_mi_row_col(xd, tile, mi_row, num_8x8_blocks_high_lookup[m->mbmi.sb_type], @@ -714,8 +713,7 @@ static void encode_loopfilter(struct loopfilter *lf, vpx_wb_write_bit(wb, changed); if (changed) { lf->last_ref_deltas[i] = delta; - vpx_wb_write_literal(wb, abs(delta) & 0x3F, 6); - vpx_wb_write_bit(wb, delta < 0); + vpx_wb_write_inv_signed_literal(wb, delta, 6); } } @@ -725,8 +723,7 @@ static void encode_loopfilter(struct loopfilter *lf, vpx_wb_write_bit(wb, changed); if (changed) { lf->last_mode_deltas[i] = delta; - vpx_wb_write_literal(wb, abs(delta) & 0x3F, 6); - vpx_wb_write_bit(wb, delta < 0); + vpx_wb_write_inv_signed_literal(wb, delta, 6); } } } @@ -736,8 +733,7 @@ static void encode_loopfilter(struct loopfilter *lf, static void write_delta_q(struct vpx_write_bit_buffer *wb, int delta_q) { if (delta_q != 0) { vpx_wb_write_bit(wb, 1); - vpx_wb_write_literal(wb, abs(delta_q), 4); - vpx_wb_write_bit(wb, delta_q < 0); + vpx_wb_write_inv_signed_literal(wb, delta_q, 4); } else { vpx_wb_write_bit(wb, 0); } @@ -821,14 +817,25 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd, } } -static void encode_txfm_probs(VP10_COMMON *cm, vpx_writer *w, +#if CONFIG_MISC_FIXES +static void write_txfm_mode(TX_MODE mode, struct vpx_write_bit_buffer *wb) { + vpx_wb_write_bit(wb, mode == TX_MODE_SELECT); + if (mode != TX_MODE_SELECT) + vpx_wb_write_literal(wb, mode, 2); +} +#endif + +static void update_txfm_probs(VP10_COMMON *cm, vpx_writer *w, FRAME_COUNTS *counts) { +#if !CONFIG_MISC_FIXES // Mode vpx_write_literal(w, VPXMIN(cm->tx_mode, ALLOW_32X32), 2); if (cm->tx_mode >= ALLOW_32X32) vpx_write_bit(w, cm->tx_mode == TX_MODE_SELECT); // Probabilities +#endif + if (cm->tx_mode == TX_MODE_SELECT) { int i, j; unsigned int ct_8x8p[TX_SIZES - 3][2]; @@ -1055,7 +1062,8 @@ static void write_bitdepth_colorspace_sampling( } vpx_wb_write_literal(wb, cm->color_space, 3); if (cm->color_space != VPX_CS_SRGB) { - vpx_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] + // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] + vpx_wb_write_bit(wb, cm->color_range); if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { assert(cm->subsampling_x != 1 || cm->subsampling_y != 1); vpx_wb_write_bit(wb, cm->subsampling_x); @@ -1142,8 +1150,13 @@ static void write_uncompressed_header(VP10_COMP *cpi, } if (!cm->error_resilient_mode) { - vpx_wb_write_bit(wb, cm->refresh_frame_context); - vpx_wb_write_bit(wb, cm->frame_parallel_decoding_mode); + vpx_wb_write_bit(wb, + cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF); +#if CONFIG_MISC_FIXES + if (cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF) +#endif + vpx_wb_write_bit(wb, cm->refresh_frame_context != + REFRESH_FRAME_CONTEXT_BACKWARD); } vpx_wb_write_literal(wb, cm->frame_context_idx, FRAME_CONTEXTS_LOG2); @@ -1151,24 +1164,32 @@ static void write_uncompressed_header(VP10_COMP *cpi, encode_loopfilter(&cm->lf, wb); encode_quantization(cm, wb); encode_segmentation(cm, xd, wb); +#if CONFIG_MISC_FIXES + if (xd->lossless) + cm->tx_mode = TX_4X4; + else + write_txfm_mode(cm->tx_mode, wb); +#endif write_tile_info(cm, wb); } static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) { VP10_COMMON *const cm = &cpi->common; - MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; FRAME_CONTEXT *const fc = cm->fc; FRAME_COUNTS *counts = cpi->td.counts; vpx_writer header_bc; vpx_start_encode(&header_bc, data); - if (xd->lossless) - cm->tx_mode = ONLY_4X4; +#if !CONFIG_MISC_FIXES + if (cpi->td.mb.e_mbd.lossless) + cm->tx_mode = TX_4X4; else - encode_txfm_probs(cm, &header_bc, counts); - + update_txfm_probs(cm, &header_bc, counts); +#else + update_txfm_probs(cm, &header_bc, counts); +#endif update_coef_probs(cpi, &header_bc); update_skip_probs(cm, &header_bc, counts); diff --git a/vp10/encoder/block.h b/vp10/encoder/block.h index cd3baa7..9eff31a 100644 --- a/vp10/encoder/block.h +++ b/vp10/encoder/block.h @@ -58,7 +58,6 @@ struct macroblock { MACROBLOCKD e_mbd; MB_MODE_INFO_EXT *mbmi_ext; - MB_MODE_INFO_EXT *mbmi_ext_base; int skip_block; int select_tx_size; int skip_recode; 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 @@ typedef struct PC_TREE { 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/encodeframe.c b/vp10/encoder/encodeframe.c index ddea8cd..c3b6265 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -170,15 +170,16 @@ static BLOCK_SIZE get_rd_var_based_fixed_partition(VP10_COMP *cpi, // Lighter version of set_offsets that only sets the mode info // pointers. -static INLINE void set_mode_info_offsets(VP10_COMMON *const cm, +static INLINE void set_mode_info_offsets(VP10_COMP *const cpi, MACROBLOCK *const x, MACROBLOCKD *const xd, int mi_row, int mi_col) { + VP10_COMMON *const cm = &cpi->common; const int idx_str = xd->mi_stride * mi_row + mi_col; xd->mi = cm->mi_grid_visible + idx_str; xd->mi[0] = cm->mi + idx_str; - x->mbmi_ext = x->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col); + x->mbmi_ext = cpi->mbmi_ext_base + (mi_row * cm->mi_cols + mi_col); } static void set_offsets(VP10_COMP *cpi, const TileInfo *const tile, @@ -193,7 +194,7 @@ static void set_offsets(VP10_COMP *cpi, const TileInfo *const tile, set_skip_context(xd, mi_row, mi_col); - set_mode_info_offsets(cm, x, xd, mi_row, mi_col); + set_mode_info_offsets(cpi, x, xd, mi_row, mi_col); mbmi = &xd->mi[0]->mbmi; @@ -244,7 +245,7 @@ static void set_block_size(VP10_COMP * const cpi, int mi_row, int mi_col, BLOCK_SIZE bsize) { if (cpi->common.mi_cols > mi_col && cpi->common.mi_rows > mi_row) { - set_mode_info_offsets(&cpi->common, x, xd, mi_row, mi_col); + set_mode_info_offsets(cpi, x, xd, mi_row, mi_col); xd->mi[0]->mbmi.sb_type = bsize; } } diff --git a/vp10/encoder/encodemv.c b/vp10/encoder/encodemv.c index f1fe5a7..ca2de1f 100644 --- a/vp10/encoder/encodemv.c +++ b/vp10/encoder/encodemv.c @@ -239,7 +239,7 @@ static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext, const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_mv; const MV diff = {mvs[i].as_mv.row - ref->row, mvs[i].as_mv.col - ref->col}; - vp10_inc_mv(&diff, counts); + vp10_inc_mv(&diff, counts, vp10_use_mv_hp(ref)); } } diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index 85659a2..6ae4c5e 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -710,7 +710,6 @@ static void update_frame_size(VP10_COMP *cpi) { vp10_set_mb_mi(cm, cm->width, cm->height); vp10_init_context_buffers(cm); vp10_init_macroblockd(cm, xd, NULL); - cpi->td.mb.mbmi_ext_base = cpi->mbmi_ext_base; memset(cpi->mbmi_ext_base, 0, cm->mi_rows * cm->mi_cols * sizeof(*cpi->mbmi_ext_base)); @@ -735,6 +734,7 @@ static void init_config(struct VP10_COMP *cpi, VP10EncoderConfig *oxcf) { cm->use_highbitdepth = oxcf->use_highbitdepth; #endif cm->color_space = oxcf->color_space; + cm->color_range = oxcf->color_range; cm->width = oxcf->width; cm->height = oxcf->height; @@ -1406,6 +1406,7 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) { cm->profile = oxcf->profile; cm->bit_depth = oxcf->bit_depth; cm->color_space = oxcf->color_space; + cm->color_range = oxcf->color_range; if (cm->profile <= PROFILE_1) assert(cm->bit_depth == VPX_BITS_8); @@ -1421,7 +1422,10 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) { cpi->refresh_golden_frame = 0; cpi->refresh_last_frame = 1; - cm->refresh_frame_context = 1; + cm->refresh_frame_context = + oxcf->error_resilient_mode ? REFRESH_FRAME_CONTEXT_OFF : + oxcf->frame_parallel_decoding_mode ? REFRESH_FRAME_CONTEXT_FORWARD + : REFRESH_FRAME_CONTEXT_BACKWARD; cm->reset_frame_context = RESET_FRAME_CONTEXT_NONE; vp10_reset_segment_features(&cm->seg); @@ -3549,13 +3553,11 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, cpi->rc.source_alt_ref_active = 0; cm->error_resilient_mode = oxcf->error_resilient_mode; - cm->frame_parallel_decoding_mode = oxcf->frame_parallel_decoding_mode; // By default, encoder assumes decoder can use prev_mi. if (cm->error_resilient_mode) { - cm->frame_parallel_decoding_mode = 1; cm->reset_frame_context = RESET_FRAME_CONTEXT_NONE; - cm->refresh_frame_context = 0; + cm->refresh_frame_context = REFRESH_FRAME_CONTEXT_OFF; } else if (cm->intra_only) { // Only reset the current context. cm->reset_frame_context = RESET_FRAME_CONTEXT_CURRENT; @@ -3622,6 +3624,8 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, cpi->refresh_last_frame = 1; cm->frame_to_show = get_frame_new_buffer(cm); + cm->frame_to_show->color_space = cm->color_space; + cm->frame_to_show->color_range = cm->color_range; // Pick the loop filter level for the frame. loopfilter_frame(cpi, cm); @@ -3641,11 +3645,11 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, full_to_model_counts(cpi->td.counts->coef[t], cpi->td.rd_counts.coef_counts[t]); - if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD) vp10_adapt_coef_probs(cm); if (!frame_is_intra_only(cm)) { - if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) { + if (cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_BACKWARD) { vp10_adapt_mode_probs(cm); vp10_adapt_mv_probs(cm, cm->allow_high_precision_mv); } @@ -3828,7 +3832,7 @@ static int frame_is_reference(const VP10_COMP *cpi) { cpi->refresh_last_frame || cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame || - cm->refresh_frame_context || + cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF || cm->lf.mode_ref_delta_update || cm->seg.update_map || cm->seg.update_data; @@ -3956,7 +3960,10 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, // Normal defaults cm->reset_frame_context = RESET_FRAME_CONTEXT_NONE; - cm->refresh_frame_context = 1; + cm->refresh_frame_context = + oxcf->error_resilient_mode ? REFRESH_FRAME_CONTEXT_OFF : + oxcf->frame_parallel_decoding_mode ? REFRESH_FRAME_CONTEXT_FORWARD + : REFRESH_FRAME_CONTEXT_BACKWARD; cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 0; @@ -4100,7 +4107,7 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, Pass0Encode(cpi, size, dest, frame_flags); } - if (cm->refresh_frame_context) + if (cm->refresh_frame_context != REFRESH_FRAME_CONTEXT_OFF) cm->frame_contexts[cm->frame_context_idx] = *cm->fc; // No frame encoded, or frame was dropped, release scaled references. diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index d0beac4..8ab1efa 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -228,6 +228,7 @@ typedef struct VP10EncoderConfig { int use_highbitdepth; #endif vpx_color_space_t color_space; + int color_range; } VP10EncoderConfig; static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) { 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 @@ typedef struct EncWorkerData { 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 #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 @@ void vp10_highbd_resize_frame444(const uint8_t *const y, int owidth, int bd); #endif // CONFIG_VP9_HIGHBITDEPTH + +#ifdef __cplusplus +} // extern "C" +#endif + #endif // VP10_ENCODER_RESIZE_H_ diff --git a/vp10/vp10_cx_iface.c b/vp10/vp10_cx_iface.c index ec89aae..2cb309d 100644 --- a/vp10/vp10_cx_iface.c +++ b/vp10/vp10_cx_iface.c @@ -45,6 +45,7 @@ struct vp10_extracfg { vpx_bit_depth_t bit_depth; vp9e_tune_content content; vpx_color_space_t color_space; + int color_range; }; static struct vp10_extracfg default_extra_cfg = { @@ -71,6 +72,7 @@ static struct vp10_extracfg default_extra_cfg = { VPX_BITS_8, // Bit depth VP9E_CONTENT_DEFAULT, // content VPX_CS_UNKNOWN, // color space + 0, // color range }; struct vpx_codec_alg_priv { @@ -255,6 +257,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, ERROR("Codec bit-depth 8 not supported in profile > 1"); } RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB); + RANGE_CHECK(extra_cfg, color_range, 0, 1); return VPX_CODEC_OK; } @@ -398,6 +401,7 @@ static vpx_codec_err_t set_encoder_config( #endif oxcf->color_space = extra_cfg->color_space; + oxcf->color_range = extra_cfg->color_range; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->min_gf_interval = extra_cfg->min_gf_interval; @@ -1221,6 +1225,13 @@ static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp10_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, args); + return update_extra_cfg(ctx, &extra_cfg); +} + static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, {VP8E_UPD_ENTROPY, ctrl_update_entropy}, @@ -1254,6 +1265,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback}, {VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content}, {VP9E_SET_COLOR_SPACE, ctrl_set_color_space}, + {VP9E_SET_COLOR_RANGE, ctrl_set_color_range}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, 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 @@ static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx, (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..7987d18 100644 --- a/vp10/vp10_iface_common.h +++ b/vp10/vp10_iface_common.h @@ -37,6 +37,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, } } img->cs = yv12->color_space; + img->range = yv12->color_range; img->bit_depth = 8; img->w = yv12->y_stride; img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); @@ -56,7 +57,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, 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); @@ -96,6 +97,7 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->y_stride = img->stride[VPX_PLANE_Y]; yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->color_space = img->cs; + yv12->color_range = img->range; #if CONFIG_VP9_HIGHBITDEPTH if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index c373c02..5d8eb90 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -112,6 +112,7 @@ typedef struct BufferPool { typedef struct VP9Common { struct vpx_internal_error_info error; vpx_color_space_t color_space; + int color_range; int width; int height; int display_width; diff --git a/vp9/common/vp9_thread_common.c b/vp9/common/vp9_thread_common.c index 8324cea..978e0bf 100644 --- a/vp9/common/vp9_thread_common.c +++ b/vp9/common/vp9_thread_common.c @@ -318,21 +318,21 @@ void vp9_loop_filter_dealloc(VP9LfSync *lf_sync) { } // Accumulate frame counts. -void vp9_accumulate_frame_counts(VP9_COMMON *cm, FRAME_COUNTS *counts, - int is_dec) { +void vp9_accumulate_frame_counts(FRAME_COUNTS *accum, + const FRAME_COUNTS *counts, int is_dec) { int i, j, k, l, m; for (i = 0; i < BLOCK_SIZE_GROUPS; i++) for (j = 0; j < INTRA_MODES; j++) - cm->counts.y_mode[i][j] += counts->y_mode[i][j]; + accum->y_mode[i][j] += counts->y_mode[i][j]; for (i = 0; i < INTRA_MODES; i++) for (j = 0; j < INTRA_MODES; j++) - cm->counts.uv_mode[i][j] += counts->uv_mode[i][j]; + accum->uv_mode[i][j] += counts->uv_mode[i][j]; for (i = 0; i < PARTITION_CONTEXTS; i++) for (j = 0; j < PARTITION_TYPES; j++) - cm->counts.partition[i][j] += counts->partition[i][j]; + accum->partition[i][j] += counts->partition[i][j]; if (is_dec) { int n; @@ -341,10 +341,10 @@ void vp9_accumulate_frame_counts(VP9_COMMON *cm, FRAME_COUNTS *counts, for (k = 0; k < REF_TYPES; k++) for (l = 0; l < COEF_BANDS; l++) for (m = 0; m < COEFF_CONTEXTS; m++) { - cm->counts.eob_branch[i][j][k][l][m] += + accum->eob_branch[i][j][k][l][m] += counts->eob_branch[i][j][k][l][m]; for (n = 0; n < UNCONSTRAINED_NODES + 1; n++) - cm->counts.coef[i][j][k][l][m][n] += + accum->coef[i][j][k][l][m][n] += counts->coef[i][j][k][l][m][n]; } } else { @@ -353,64 +353,64 @@ void vp9_accumulate_frame_counts(VP9_COMMON *cm, FRAME_COUNTS *counts, for (k = 0; k < REF_TYPES; k++) for (l = 0; l < COEF_BANDS; l++) for (m = 0; m < COEFF_CONTEXTS; m++) - cm->counts.eob_branch[i][j][k][l][m] += + accum->eob_branch[i][j][k][l][m] += counts->eob_branch[i][j][k][l][m]; - // In the encoder, cm->counts.coef is only updated at frame + // In the encoder, coef is only updated at frame // level, so not need to accumulate it here. // for (n = 0; n < UNCONSTRAINED_NODES + 1; n++) - // cm->counts.coef[i][j][k][l][m][n] += + // accum->coef[i][j][k][l][m][n] += // counts->coef[i][j][k][l][m][n]; } for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) for (j = 0; j < SWITCHABLE_FILTERS; j++) - cm->counts.switchable_interp[i][j] += counts->switchable_interp[i][j]; + accum->switchable_interp[i][j] += counts->switchable_interp[i][j]; for (i = 0; i < INTER_MODE_CONTEXTS; i++) for (j = 0; j < INTER_MODES; j++) - cm->counts.inter_mode[i][j] += counts->inter_mode[i][j]; + accum->inter_mode[i][j] += counts->inter_mode[i][j]; for (i = 0; i < INTRA_INTER_CONTEXTS; i++) for (j = 0; j < 2; j++) - cm->counts.intra_inter[i][j] += counts->intra_inter[i][j]; + accum->intra_inter[i][j] += counts->intra_inter[i][j]; for (i = 0; i < COMP_INTER_CONTEXTS; i++) for (j = 0; j < 2; j++) - cm->counts.comp_inter[i][j] += counts->comp_inter[i][j]; + accum->comp_inter[i][j] += counts->comp_inter[i][j]; for (i = 0; i < REF_CONTEXTS; i++) for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) - cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k]; + accum->single_ref[i][j][k] += counts->single_ref[i][j][k]; for (i = 0; i < REF_CONTEXTS; i++) for (j = 0; j < 2; j++) - cm->counts.comp_ref[i][j] += counts->comp_ref[i][j]; + accum->comp_ref[i][j] += counts->comp_ref[i][j]; for (i = 0; i < TX_SIZE_CONTEXTS; i++) { for (j = 0; j < TX_SIZES; j++) - cm->counts.tx.p32x32[i][j] += counts->tx.p32x32[i][j]; + accum->tx.p32x32[i][j] += counts->tx.p32x32[i][j]; for (j = 0; j < TX_SIZES - 1; j++) - cm->counts.tx.p16x16[i][j] += counts->tx.p16x16[i][j]; + accum->tx.p16x16[i][j] += counts->tx.p16x16[i][j]; for (j = 0; j < TX_SIZES - 2; j++) - cm->counts.tx.p8x8[i][j] += counts->tx.p8x8[i][j]; + accum->tx.p8x8[i][j] += counts->tx.p8x8[i][j]; } for (i = 0; i < TX_SIZES; i++) - cm->counts.tx.tx_totals[i] += counts->tx.tx_totals[i]; + accum->tx.tx_totals[i] += counts->tx.tx_totals[i]; for (i = 0; i < SKIP_CONTEXTS; i++) for (j = 0; j < 2; j++) - cm->counts.skip[i][j] += counts->skip[i][j]; + accum->skip[i][j] += counts->skip[i][j]; for (i = 0; i < MV_JOINTS; i++) - cm->counts.mv.joints[i] += counts->mv.joints[i]; + accum->mv.joints[i] += counts->mv.joints[i]; for (k = 0; k < 2; k++) { - nmv_component_counts *comps = &cm->counts.mv.comps[k]; - nmv_component_counts *comps_t = &counts->mv.comps[k]; + nmv_component_counts *const comps = &accum->mv.comps[k]; + const nmv_component_counts *const comps_t = &counts->mv.comps[k]; for (i = 0; i < 2; i++) { comps->sign[i] += comps_t->sign[i]; diff --git a/vp9/common/vp9_thread_common.h b/vp9/common/vp9_thread_common.h index 07af1bc..db6587f 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; @@ -51,7 +55,11 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, VPxWorker *workers, int num_workers, VP9LfSync *lf_sync); -void vp9_accumulate_frame_counts(struct VP9Common *cm, - struct FRAME_COUNTS *counts, int is_dec); +void vp9_accumulate_frame_counts(struct FRAME_COUNTS *accum, + const 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_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 18b8c70..ba8c8dd 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -1256,6 +1256,7 @@ static void setup_frame_size(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) { pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; } static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, @@ -1337,6 +1338,7 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm, pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; + pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; } static void setup_tile_info(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) { @@ -1561,9 +1563,10 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi, return vpx_reader_find_end(&tile_data->bit_reader); } -static int tile_worker_hook(TileWorkerData *const tile_data, - const TileInfo *const tile) { +static int tile_worker_hook(TileWorkerData *const tile_data, void *unused) { + const TileInfo *const tile = &tile_data->xd.tile; int mi_row, mi_col; + (void)unused; if (setjmp(tile_data->error_info.jmp)) { tile_data->error_info.setjmp = 0; @@ -1626,8 +1629,6 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, CHECK_MEM_ERROR(cm, pbi->tile_worker_data, vpx_memalign(32, num_threads * sizeof(*pbi->tile_worker_data))); - CHECK_MEM_ERROR(cm, pbi->tile_worker_info, - vpx_malloc(num_threads * sizeof(*pbi->tile_worker_info))); for (i = 0; i < num_threads; ++i) { VPxWorker *const worker = &pbi->tile_workers[i]; ++pbi->num_tile_workers; @@ -1643,10 +1644,15 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, // Reset tile decoding hook for (n = 0; n < num_workers; ++n) { VPxWorker *const worker = &pbi->tile_workers[n]; + TileWorkerData *const tile_data = &pbi->tile_worker_data[n]; winterface->sync(worker); + tile_data->pbi = pbi; + tile_data->xd = pbi->mb; + tile_data->xd.counts = + cm->frame_parallel_decoding_mode ? NULL : &tile_data->counts; worker->hook = (VPxWorkerHook)tile_worker_hook; - worker->data1 = &pbi->tile_worker_data[n]; - worker->data2 = &pbi->tile_worker_info[n]; + worker->data1 = tile_data; + worker->data2 = NULL; } // Note: this memset assumes above_context[0], [1] and [2] @@ -1696,16 +1702,10 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, for (i = 0; i < num_workers && n < tile_cols; ++i) { VPxWorker *const worker = &pbi->tile_workers[i]; TileWorkerData *const tile_data = (TileWorkerData*)worker->data1; - TileInfo *const tile = (TileInfo*)worker->data2; TileBuffer *const buf = &tile_buffers[0][n]; - tile_data->pbi = pbi; - tile_data->xd = pbi->mb; tile_data->xd.corrupted = 0; - tile_data->xd.counts = cm->frame_parallel_decoding_mode ? - 0 : &tile_data->counts; vp9_zero(tile_data->dqcoeff); - vp9_tile_init(tile, cm, 0, buf->col); vp9_tile_init(&tile_data->xd.tile, cm, 0, buf->col); setup_token_decoder(buf->data, data_end, buf->size, &cm->error, &tile_data->bit_reader, pbi->decrypt_cb, @@ -1740,14 +1740,15 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, bit_reader_end = vpx_reader_find_end(&tile_data->bit_reader); final_worker = -1; } + } - // Accumulate thread frame counts. - if (n >= tile_cols && !cm->frame_parallel_decoding_mode) { - for (i = 0; i < num_workers; ++i) { - TileWorkerData *const tile_data = - (TileWorkerData*)pbi->tile_workers[i].data1; - vp9_accumulate_frame_counts(cm, &tile_data->counts, 1); - } + // Accumulate thread frame counts. + if (!cm->frame_parallel_decoding_mode) { + int i; + for (i = 0; i < num_workers; ++i) { + TileWorkerData *const tile_data = + (TileWorkerData*)pbi->tile_workers[i].data1; + vp9_accumulate_frame_counts(&cm->counts, &tile_data->counts, 1); } } @@ -1774,7 +1775,8 @@ static void read_bitdepth_colorspace_sampling( } cm->color_space = vpx_rb_read_literal(rb, 3); if (cm->color_space != VPX_CS_SRGB) { - vpx_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range + // [16,235] (including xvycc) vs [0,255] range + cm->color_range = vpx_rb_read_bit(rb); if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { cm->subsampling_x = vpx_rb_read_bit(rb); cm->subsampling_y = vpx_rb_read_bit(rb); @@ -1788,6 +1790,7 @@ static void read_bitdepth_colorspace_sampling( cm->subsampling_y = cm->subsampling_x = 1; } } else { + cm->color_range = 1; if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { // Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed. // 4:2:2 or 4:4:0 chroma sampling is not allowed. @@ -1893,6 +1896,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, // specifies that the default color format should be YUV 4:2:0 in this // case (normative). cm->color_space = VPX_CS_BT_601; + cm->color_range = 0; cm->subsampling_y = cm->subsampling_x = 1; cm->bit_depth = VPX_BITS_8; #if CONFIG_VP9_HIGHBITDEPTH @@ -1943,6 +1947,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; #endif get_frame_new_buffer(cm)->color_space = cm->color_space; + get_frame_new_buffer(cm)->color_range = cm->color_range; if (pbi->need_resync) { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, diff --git a/vp9/decoder/vp9_decoder.c b/vp9/decoder/vp9_decoder.c index 6734d00..61077cd 100644 --- a/vp9/decoder/vp9_decoder.c +++ b/vp9/decoder/vp9_decoder.c @@ -134,7 +134,6 @@ void vp9_decoder_remove(VP9Decoder *pbi) { vpx_get_worker_interface()->end(worker); } vpx_free(pbi->tile_worker_data); - vpx_free(pbi->tile_worker_info); vpx_free(pbi->tile_workers); if (pbi->num_tile_workers > 0) { diff --git a/vp9/decoder/vp9_decoder.h b/vp9/decoder/vp9_decoder.h index 915f9dc..944f7da 100644 --- a/vp9/decoder/vp9_decoder.h +++ b/vp9/decoder/vp9_decoder.h @@ -65,7 +65,6 @@ typedef struct VP9Decoder { VPxWorker lf_worker; VPxWorker *tile_workers; TileWorkerData *tile_worker_data; - TileInfo *tile_worker_info; int num_tile_workers; TileData *tile_data; 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_broadcast(RefCntBuffer *const buf, int row); 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 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, // 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 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) { 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 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { 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_bitstream.c b/vp9/encoder/vp9_bitstream.c index 71715f0..01cced0 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1060,7 +1060,8 @@ static void write_bitdepth_colorspace_sampling( } vpx_wb_write_literal(wb, cm->color_space, 3); if (cm->color_space != VPX_CS_SRGB) { - vpx_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] + // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] + vpx_wb_write_bit(wb, cm->color_range); if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { assert(cm->subsampling_x != 1 || cm->subsampling_y != 1); vpx_wb_write_bit(wb, cm->subsampling_x); 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 @@ typedef struct PC_TREE { 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..91e92ff 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -412,6 +412,8 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { 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) { @@ -773,6 +775,7 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) { cm->use_highbitdepth = oxcf->use_highbitdepth; #endif cm->color_space = oxcf->color_space; + cm->color_range = oxcf->color_range; cm->width = oxcf->width; cm->height = oxcf->height; @@ -1460,6 +1463,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { cm->profile = oxcf->profile; cm->bit_depth = oxcf->bit_depth; cm->color_space = oxcf->color_space; + cm->color_range = oxcf->color_range; if (cm->profile <= PROFILE_1) assert(cm->bit_depth == VPX_BITS_8); @@ -3200,7 +3204,8 @@ static void encode_without_recode_loop(VP9_COMP *cpi, 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 +3215,8 @@ static void encode_without_recode_loop(VP9_COMP *cpi, 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 +3348,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi, } 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 +3605,17 @@ static void set_ext_overrides(VP9_COMP *cpi) { 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 +3818,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->refresh_last_frame = 1; cm->frame_to_show = get_frame_new_buffer(cm); + cm->frame_to_show->color_space = cm->color_space; + cm->frame_to_show->color_range = cm->color_range; // 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..b50f2fb 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -238,6 +238,7 @@ typedef struct VP9EncoderConfig { int use_highbitdepth; #endif vpx_color_space_t color_space; + int color_range; VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode; } VP9EncoderConfig; @@ -613,7 +614,8 @@ void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv); 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.c b/vp9/encoder/vp9_ethread.c index 69ed132..ad25712 100644 --- a/vp9/encoder/vp9_ethread.c +++ b/vp9/encoder/vp9_ethread.c @@ -192,7 +192,7 @@ void vp9_encode_tiles_mt(VP9_COMP *cpi) { // Accumulate counters. if (i < cpi->num_workers - 1) { - vp9_accumulate_frame_counts(cm, thread_data->td->counts, 0); + vp9_accumulate_frame_counts(&cm->counts, thread_data->td->counts, 0); accumulate_rd_opt(&cpi->td, thread_data->td); } } 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 @@ typedef struct EncWorkerData { 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 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { (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 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame, 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 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { 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 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { } // 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 #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 @@ void vp9_highbd_resize_frame444(const uint8_t *const y, 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..64a4ebd 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -10,6 +10,7 @@ #include +#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 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { 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 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { 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 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) { 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 @@ void vp9_save_layer_context(VP9_COMP *const cpi) { 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) { @@ -491,19 +541,35 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { set_flags_and_fb_idx_for_temporal_mode2(cpi); } else if (cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { - // VP9E_TEMPORAL_LAYERING_MODE_BYPASS : - // if the code goes here, it means the encoder will be relying on the - // flags from outside for layering. - // However, since when spatial+temporal layering is used, the buffer indices - // cannot be derived automatically, the bypass mode will only work when the - // number of spatial layers equals 1. - assert(cpi->svc.number_spatial_layers == 1); + // In the BYPASS/flexible mode, the encoder is relying on the application + // to specify, for each spatial layer, the flags and buffer indices for the + // layering. + // Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is + // needed to support the case where the frame flags may be passed in via + // vpx_codec_encode(), which can be used for the temporal-only svc case. + if (cpi->ext_refresh_frame_flags_pending == 0) { + int sl; + cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode; + sl = cpi->svc.spatial_layer_id; + vp9_apply_encoding_flags(cpi, cpi->svc.ext_frame_flags[sl]); + cpi->lst_fb_idx = cpi->svc.ext_lst_fb_idx[sl]; + cpi->gld_fb_idx = cpi->svc.ext_gld_fb_idx[sl]; + cpi->alt_fb_idx = cpi->svc.ext_alt_fb_idx[sl]; + } } lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id * 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 +708,19 @@ struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi, } 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..ae55c2f 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -41,6 +41,10 @@ typedef struct { 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 { @@ -70,6 +74,12 @@ typedef struct { // Indicates what sort of temporal layering is used. // Currently, this only works for CBR mode. VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode; + // Frame flags and buffer indexes for each spatial layer, set by the + // application (external settings). + int ext_frame_flags[VPX_MAX_LAYERS]; + int ext_lst_fb_idx[VPX_MAX_LAYERS]; + int ext_gld_fb_idx[VPX_MAX_LAYERS]; + int ext_alt_fb_idx[VPX_MAX_LAYERS]; } SVC; struct VP9_COMP; @@ -115,6 +125,8 @@ int vp9_svc_start_frame(struct VP9_COMP *const cpi); 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 @@ void vp9_temporal_filter(VP9_COMP *cpi, int distance) { "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_cx_iface.c b/vp9/vp9_cx_iface.c index f155b9a..aea1a5f 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -45,6 +45,7 @@ struct vp9_extracfg { vpx_bit_depth_t bit_depth; vp9e_tune_content content; vpx_color_space_t color_space; + int color_range; }; static struct vp9_extracfg default_extra_cfg = { @@ -71,6 +72,7 @@ static struct vp9_extracfg default_extra_cfg = { VPX_BITS_8, // Bit depth VP9E_CONTENT_DEFAULT, // content VPX_CS_UNKNOWN, // color space + 0, // color range }; struct vpx_codec_alg_priv { @@ -321,6 +323,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, ERROR("Codec bit-depth 8 not supported in profile > 1"); } RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB); + RANGE_CHECK(extra_cfg, color_range, 0, 2); return VPX_CODEC_OK; } @@ -465,6 +468,7 @@ static vpx_codec_err_t set_encoder_config( #endif oxcf->color_space = extra_cfg->color_space; + oxcf->color_range = extra_cfg->color_range; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->min_gf_interval = extra_cfg->min_gf_interval; @@ -1412,6 +1416,20 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx, 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; + vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *); + int sl; + for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) { + cpi->svc.ext_frame_flags[sl] = data->frame_flags[sl]; + cpi->svc.ext_lst_fb_idx[sl] = data->lst_fb_idx[sl]; + cpi->svc.ext_gld_fb_idx[sl] = data->gld_fb_idx[sl]; + cpi->svc.ext_alt_fb_idx[sl] = data->alt_fb_idx[sl]; + } + return VPX_CODEC_OK; +} + static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx, va_list args) { vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp = @@ -1436,6 +1454,13 @@ static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp9_extracfg extra_cfg = ctx->extra_cfg; + extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, args); + return update_extra_cfg(ctx, &extra_cfg); +} + static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, {VP8E_UPD_ENTROPY, ctrl_update_entropy}, @@ -1472,9 +1497,11 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id}, {VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content}, {VP9E_SET_COLOR_SPACE, ctrl_set_color_space}, + {VP9E_SET_COLOR_RANGE, ctrl_set_color_range}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, + {VP9E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config}, // Getters {VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer}, 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 @@ static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx, (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..7d514ba 100644 --- a/vp9/vp9_iface_common.h +++ b/vp9/vp9_iface_common.h @@ -37,6 +37,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, } } img->cs = yv12->color_space; + img->range = yv12->color_range; img->bit_depth = 8; img->w = yv12->y_stride; img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); @@ -56,7 +57,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, 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); @@ -96,6 +97,7 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->y_stride = img->stride[VPX_PLANE_Y]; yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->color_space = img->cs; + yv12->color_range = img->range; #if CONFIG_VP9_HIGHBITDEPTH if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { diff --git a/vpx/src/svc_encodeframe.c b/vpx/src/svc_encodeframe.c index 78932d2..ff60083 100644 --- a/vpx/src/svc_encodeframe.c +++ b/vpx/src/svc_encodeframe.c @@ -339,7 +339,8 @@ void assign_layer_bitrates(const SvcContext *svc_ctx, (spatial_layer_target >> 1) + (spatial_layer_target >> 2); enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] = spatial_layer_target; - } else if (svc_ctx->temporal_layering_mode == 2) { + } else if (svc_ctx->temporal_layering_mode == 2 || + svc_ctx->temporal_layering_mode == 1) { enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] = spatial_layer_target * 2 / 3; enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] = @@ -417,7 +418,8 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, // si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode; if (svc_ctx->temporal_layering_mode == 3) { svc_ctx->temporal_layers = 3; - } else if (svc_ctx->temporal_layering_mode == 2) { + } else if (svc_ctx->temporal_layering_mode == 2 || + svc_ctx->temporal_layering_mode == 1) { svc_ctx->temporal_layers = 2; } 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 @@ typedef struct { 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; diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index 31120df..a437ac9 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -547,6 +547,23 @@ enum vp8e_enc_control_id { * Supported in codecs: VP9 */ VP9E_GET_ACTIVEMAP, + + /*!\brief Codec control function to set color range bit. + * \note Valid ranges: 0..1, default is 0 + * 0 = Limited range (16..235 or HBD equivalent) + * 1 = Full range (0..255 or HBD equivalent) + * + * Supported in codecs: VP9 + */ + VP9E_SET_COLOR_RANGE, + + /*!\brief Codec control function to set the frame flags and buffer indices + * for spatial layers. The frame flags and buffer indices are set using the + * struct #vpx_svc_ref_frame_config defined below. + * + * Supported in codecs: VP9 + */ + VP9E_SET_SVC_REF_FRAME_CONFIG, }; /*!\brief vpx 1-D scaling mode @@ -673,6 +690,21 @@ typedef struct vpx_svc_layer_id { int temporal_layer_id; /**< Temporal layer id number. */ } vpx_svc_layer_id_t; +/*!\brief vp9 svc frame flag parameters. + * + * This defines the frame flags and buffer indices for each spatial layer for + * svc encoding. + * This is used with the #VP9E_SET_SVC_REF_FRAME_CONFIG control to set frame + * flags and buffer indices for each spatial layer for the current (super)frame. + * + */ +typedef struct vpx_svc_ref_frame_config { + int frame_flags[VPX_TS_MAX_LAYERS]; /**< Frame flags. */ + int lst_fb_idx[VPX_TS_MAX_LAYERS]; /**< Last buffer index. */ + int gld_fb_idx[VPX_TS_MAX_LAYERS]; /**< Golden buffer index. */ + int alt_fb_idx[VPX_TS_MAX_LAYERS]; /**< Altref buffer index. */ +} vpx_svc_ref_frame_config_t; + /*!\brief VP8 encoder control function parameter type * * Defines the data types that VP8E control functions take. Note that @@ -757,6 +789,15 @@ VPX_CTRL_USE_TYPE(VP9E_SET_MAX_GF_INTERVAL, unsigned int) #define VPX_CTRL_VP9E_SET_MAX_GF_INTERVAL VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *) + +/*!\brief + * + * TODO(rbultje) : add support of the control in ffmpeg + */ +#define VPX_CTRL_VP9E_SET_COLOR_RANGE +VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int) + +VPX_CTRL_USE_TYPE(VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_svc_ref_frame_config_t *) /*! @} - end defgroup vp8_encoder */ #ifdef __cplusplus } // extern "C" diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h index c06d351..be93147 100644 --- a/vpx/vpx_image.h +++ b/vpx/vpx_image.h @@ -82,6 +82,7 @@ extern "C" { typedef struct vpx_image { vpx_img_fmt_t fmt; /**< Image Format */ vpx_color_space_t cs; /**< Color Space */ + int range; /**< Limited (0) vs. Full-range (1) sample data */ /* Image storage dimensions */ unsigned int w; /**< Stored image width */ diff --git a/vpx_dsp/bitreader_buffer.c b/vpx_dsp/bitreader_buffer.c index fb04ee6..bb91726 100644 --- a/vpx_dsp/bitreader_buffer.c +++ b/vpx_dsp/bitreader_buffer.c @@ -7,6 +7,7 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ +#include "./vpx_config.h" #include "./bitreader_buffer.h" size_t vpx_rb_bytes_read(struct vpx_read_bit_buffer *rb) { @@ -39,3 +40,14 @@ int vpx_rb_read_signed_literal(struct vpx_read_bit_buffer *rb, const int value = vpx_rb_read_literal(rb, bits); return vpx_rb_read_bit(rb) ? -value : value; } + +int vpx_rb_read_inv_signed_literal(struct vpx_read_bit_buffer *rb, + int bits) { +#if CONFIG_MISC_FIXES + const int nbits = sizeof(unsigned) * 8 - bits - 1; + const unsigned value = vpx_rb_read_literal(rb, bits + 1) << nbits; + return ((int) value) >> nbits; +#else + return vpx_rb_read_signed_literal(rb, bits); +#endif +} diff --git a/vpx_dsp/bitreader_buffer.h b/vpx_dsp/bitreader_buffer.h index 03b156b..8a48a95 100644 --- a/vpx_dsp/bitreader_buffer.h +++ b/vpx_dsp/bitreader_buffer.h @@ -38,6 +38,8 @@ int vpx_rb_read_literal(struct vpx_read_bit_buffer *rb, int bits); int vpx_rb_read_signed_literal(struct vpx_read_bit_buffer *rb, int bits); +int vpx_rb_read_inv_signed_literal(struct vpx_read_bit_buffer *rb, int bits); + #ifdef __cplusplus } // extern "C" #endif diff --git a/vpx_dsp/bitwriter_buffer.c b/vpx_dsp/bitwriter_buffer.c index 0dfb859..6182a72 100644 --- a/vpx_dsp/bitwriter_buffer.c +++ b/vpx_dsp/bitwriter_buffer.c @@ -9,7 +9,9 @@ */ #include +#include +#include "./vpx_config.h" #include "./bitwriter_buffer.h" size_t vpx_wb_bytes_written(const struct vpx_write_bit_buffer *wb) { @@ -34,3 +36,13 @@ void vpx_wb_write_literal(struct vpx_write_bit_buffer *wb, int data, int bits) { for (bit = bits - 1; bit >= 0; bit--) vpx_wb_write_bit(wb, (data >> bit) & 1); } + +void vpx_wb_write_inv_signed_literal(struct vpx_write_bit_buffer *wb, + int data, int bits) { +#if CONFIG_MISC_FIXES + vpx_wb_write_literal(wb, data, bits + 1); +#else + vpx_wb_write_literal(wb, abs(data), bits); + vpx_wb_write_bit(wb, data < 0); +#endif +} diff --git a/vpx_dsp/bitwriter_buffer.h b/vpx_dsp/bitwriter_buffer.h index 9397668..a123a2f 100644 --- a/vpx_dsp/bitwriter_buffer.h +++ b/vpx_dsp/bitwriter_buffer.h @@ -28,6 +28,8 @@ void vpx_wb_write_bit(struct vpx_write_bit_buffer *wb, int bit); void vpx_wb_write_literal(struct vpx_write_bit_buffer *wb, int data, int bits); +void vpx_wb_write_inv_signed_literal(struct vpx_write_bit_buffer *wb, int data, + int bits); #ifdef __cplusplus } // extern "C" diff --git a/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm b/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm index 7ea6a0e..3fbaa27 100644 --- a/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm +++ b/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm @@ -104,7 +104,7 @@ cglobal filter_block1d4_%1, 6, 6+(ARCH_X86_64*2), 11, LOCAL_VARS_SIZE, \ %define k0k1k4k5 m8 %define k2k3k6k7 m9 %define krd m10 - %define orig_height r7 + %define orig_height r7d mova krd, [GLOBAL(pw_64)] pshuflw k0k1k4k5, m4, 0b ;k0_k1 pshufhw k0k1k4k5, k0k1k4k5, 10101010b ;k0_k1_k4_k5 @@ -131,8 +131,8 @@ cglobal filter_block1d4_%1, 6, 6+(ARCH_X86_64*2), 11, LOCAL_VARS_SIZE, \ mova k2k3k6k7, m7 mova krd, m1 %endif - mov orig_height, heightq - shr heightq, 1 + mov orig_height, heightd + shr heightd, 1 .loop: ;Do two rows at once movh m0, [srcq - 3] @@ -200,12 +200,12 @@ cglobal filter_block1d4_%1, 6, 6+(ARCH_X86_64*2), 11, LOCAL_VARS_SIZE, \ lea dstq, [dstq + 2 * dstrideq ] prefetcht0 [srcq + 2 * sstrideq - 3] - dec heightq + dec heightd jnz .loop ; Do last row if output_height is odd - mov heightq, orig_height - and heightq, 1 + mov heightd, orig_height + and heightd, 1 je .done movh m0, [srcq - 3] ; load src @@ -254,17 +254,17 @@ cglobal filter_block1d4_%1, 6, 6+(ARCH_X86_64*2), 11, LOCAL_VARS_SIZE, \ ;------------------------------------------------------------------------------- %macro SUBPIX_HFILTER8 1 -cglobal filter_block1d8_%1, 6, 6+(ARCH_X86_64*1), 13, LOCAL_VARS_SIZE, \ +cglobal filter_block1d8_%1, 6, 6+(ARCH_X86_64*1), 14, LOCAL_VARS_SIZE, \ src, sstride, dst, dstride, height, filter mova m4, [filterq] SETUP_LOCAL_VARS %if ARCH_X86_64 - %define orig_height r7 + %define orig_height r7d %else %define orig_height heightmp %endif - mov orig_height, heightq - shr heightq, 1 + mov orig_height, heightd + shr heightd, 1 .loop: movh m0, [srcq - 3] @@ -336,12 +336,12 @@ cglobal filter_block1d8_%1, 6, 6+(ARCH_X86_64*1), 13, LOCAL_VARS_SIZE, \ lea srcq, [srcq + sstrideq ] lea dstq, [dstq + 2 * dstrideq ] prefetcht0 [srcq + 2 * sstrideq - 3] - dec heightq + dec heightd jnz .loop ;Do last row if output_height is odd - mov heightq, orig_height - and heightq, 1 + mov heightd, orig_height + and heightd, 1 je .done movh m0, [srcq - 3] @@ -361,7 +361,7 @@ cglobal filter_block1d8_%1, 6, 6+(ARCH_X86_64*1), 13, LOCAL_VARS_SIZE, \ ;------------------------------------------------------------------------------- %macro SUBPIX_HFILTER16 1 -cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*0), 13, LOCAL_VARS_SIZE, \ +cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*0), 14, LOCAL_VARS_SIZE, \ src, sstride, dst, dstride, height, filter mova m4, [filterq] SETUP_LOCAL_VARS @@ -427,7 +427,7 @@ cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*0), 13, LOCAL_VARS_SIZE, \ lea srcq, [srcq + sstrideq] mova [dstq], m0 lea dstq, [dstq + dstrideq] - dec heightq + dec heightd jnz .loop RET %endm @@ -527,11 +527,11 @@ cglobal filter_block1d%2_%1, 6, 6+(ARCH_X86_64*3), 14, LOCAL_VARS_SIZE, \ %endif movx [dstq], m1 add dstq, dst_stride - sub heightq, 2 - cmp heightq, 1 + sub heightd, 2 + cmp heightd, 1 jg .loop - cmp heightq, 0 + cmp heightd, 0 je .done movx m0, [srcq ] ;A @@ -570,7 +570,7 @@ cglobal filter_block1d%2_%1, 6, 6+(ARCH_X86_64*3), 14, LOCAL_VARS_SIZE, \ ;------------------------------------------------------------------------------- %macro SUBPIX_VFILTER16 1 -cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*2), 13, LOCAL_VARS_SIZE, \ +cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*3), 14, LOCAL_VARS_SIZE, \ src, sstride, dst, dstride, height, filter mova m4, [filterq] @@ -655,7 +655,7 @@ cglobal filter_block1d16_%1, 6, 6+(ARCH_X86_64*2), 13, LOCAL_VARS_SIZE, \ %endif movh [dstq + 8], m3 add dstq, dst_stride - dec heightq + dec heightd jnz .loop RET %endm diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h index fd5d54b..2e12ace 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -56,6 +56,7 @@ typedef struct yv12_buffer_config { int subsampling_y; unsigned int bit_depth; vpx_color_space_t color_space; + int color_range; int corrupted; int flags;