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}"
--show-build-output: Show output from each library build.
--targets <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
--show-build-output)
devnull=
;;
+ --test-link)
+ EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples"
+ ;;
--targets)
TARGETS="$2"
shift
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[] = {
&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
#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)) {
}
#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;
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;
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);
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 ?
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;
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));
}
}
+class ResizeInternalRealtimeTest : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ ResizeInternalRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~ResizeInternalRealtimeTest() {}
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ }
+
+ 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<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ if (info->w != last_w || info->h != last_h) {
+ // Verify that resize down occurs.
+ ASSERT_LT(info->w, last_w);
+ ASSERT_LT(info->h, last_h);
+ last_w = info->w;
+ last_h = info->h;
+ resize_count++;
+ }
+ }
+
+ // Verify that we get 1 resize down event in this test.
+ ASSERT_EQ(1, resize_count) << "Resizing should occur.";
+}
+
+// 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<FrameInfo>::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;
::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
::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<const libvpx_test::CodecFactory *>(
+ &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
#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 {
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<EncodeParameters, \
+ public ::libvpx_test::CodecTestWith2Params<EncodeParameters,
EncodePerfTestVideo> {
protected:
VpxEncoderParmsGetToDecoder()
- : EncoderTest(GET_PARAM(0)),
- encode_parms(GET_PARAM(1)) {
- }
+ : EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}
virtual ~VpxEncoderParmsGetToDecoder() {}
::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);
}
virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
- const libvpx_test::VideoSource& video,
+ const libvpx_test::VideoSource &video,
libvpx_test::Decoder *decoder) {
- vpx_codec_ctx_t* vp9_decoder = decoder->GetDecoder();
- vpx_codec_alg_priv_t* priv =
- (vpx_codec_alg_priv_t*) get_alg_priv(vp9_decoder);
-
- VP9Decoder* pbi = priv->pbi;
- VP9_COMMON* common = &pbi->common;
+ vpx_codec_ctx_t *const vp9_decoder = decoder->GetDecoder();
+ vpx_codec_alg_priv_t *const priv =
+ reinterpret_cast<vpx_codec_alg_priv_t *>(vp9_decoder->priv);
+ FrameWorkerData *const worker_data =
+ reinterpret_cast<FrameWorkerData *>(priv->frame_workers[0].data1);
+ VP9_COMMON *const common = &worker_data->pbi->common;
if (encode_parms.lossless) {
- EXPECT_EQ(common->base_qindex, 0);
- EXPECT_EQ(common->y_dc_delta_q, 0);
- EXPECT_EQ(common->uv_dc_delta_q, 0);
- EXPECT_EQ(common->uv_ac_delta_q, 0);
- EXPECT_EQ(common->tx_mode, ONLY_4X4);
+ EXPECT_EQ(0, common->base_qindex);
+ EXPECT_EQ(0, common->y_dc_delta_q);
+ EXPECT_EQ(0, common->uv_dc_delta_q);
+ EXPECT_EQ(0, common->uv_ac_delta_q);
+ EXPECT_EQ(ONLY_4X4, common->tx_mode);
}
- EXPECT_EQ(common->error_resilient_mode, encode_parms.error_resilient);
+ EXPECT_EQ(encode_parms.error_resilient, common->error_resilient_mode);
if (encode_parms.error_resilient) {
- EXPECT_EQ(common->frame_parallel_decoding_mode, 1);
- EXPECT_EQ(common->use_prev_frame_mvs, 0);
+ EXPECT_EQ(1, common->frame_parallel_decoding_mode);
+ EXPECT_EQ(0, common->use_prev_frame_mvs);
} else {
- EXPECT_EQ(common->frame_parallel_decoding_mode,
- encode_parms.frame_parallel);
+ EXPECT_EQ(encode_parms.frame_parallel,
+ common->frame_parallel_decoding_mode);
}
- EXPECT_EQ(common->color_space, encode_parms.cs);
- EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols);
- EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows);
+ EXPECT_EQ(encode_parms.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;
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
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
int mb_to_bottom_edge;
FRAME_CONTEXT *fc;
- int frame_parallel_decoding_mode;
/* pointers to reference frames */
RefBuffer *block_refs[2];
}
}
-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);
}
}
}
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"
// 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
*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;
}
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]) {
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); \
} \
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];
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;
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 */
#endif
int error_resilient_mode;
- int frame_parallel_decoding_mode;
int log2_tile_cols, log2_tile_rows;
int byte_alignment;
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;
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);
#include "vp10/common/loopfilter.h"
#include "vpx_util/vpx_thread.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10Common;
struct FRAME_COUNTS;
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_
#include <emmintrin.h> // SSE2
+#include "./vp10_rtcd.h"
#include "vp10/common/vp10_fwd_txfm.h"
#include "vpx_dsp/txfm_common.h"
#include "vpx_dsp/x86/txfm_common_sse2.h"
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;
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);
}
}
if (!less8x8 && eobtotal == 0)
+#if CONFIG_MISC_FIXES
+ mbmi->has_no_coeffs = 1; // skip loopfilter
+#else
mbmi->skip = 1; // skip loopfilter
+#endif
}
}
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,
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,
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) {
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,
}
// 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) {
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);
}
// 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;
}
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);
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;
// 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
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,
}
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
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);
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;
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);
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,
// 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;
}
}
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)) {
}
// 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;
}
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;
#include "vpx_util/vpx_thread.h"
#include "vpx/internal/vpx_codec_internal.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10Common;
struct VP10Decoder;
void vp10_frameworker_copy_context(VPxWorker *const dst_worker,
VPxWorker *const src_worker);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_DECODER_DTHREAD_H_
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],
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);
}
}
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);
}
}
}
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);
}
}
}
-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];
}
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);
}
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);
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);
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;
#include "vp10/common/blockd.h"
#include "vp10/encoder/block.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10_COMP;
struct VP10Common;
struct ThreadData;
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_ */
// 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,
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;
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;
}
}
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));
}
}
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));
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;
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);
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);
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;
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);
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);
}
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;
// 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;
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.
int use_highbitdepth;
#endif
vpx_color_space_t color_space;
+ int color_range;
} VP10EncoderConfig;
static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) {
#ifndef VP10_ENCODER_ETHREAD_H_
#define VP10_ENCODER_ETHREAD_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP10_COMP;
struct ThreadData;
void vp10_encode_tiles_mt(struct VP10_COMP *cpi);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_ENCODER_ETHREAD_H_
#include <stdio.h>
#include "vpx/vpx_integer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void vp10_resize_plane(const uint8_t *const input,
int height,
int width,
int owidth,
int bd);
#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP10_ENCODER_RESIZE_H_
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 = {
VPX_BITS_8, // Bit depth
VP9E_CONTENT_DEFAULT, // content
VPX_CS_UNKNOWN, // color space
+ 0, // color range
};
struct vpx_codec_alg_priv {
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;
}
#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;
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},
{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},
(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;
}
}
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);
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);
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) {
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;
}
// 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;
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 {
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];
#include "vp9/common/vp9_loopfilter.h"
#include "vpx_util/vpx_thread.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9Common;
struct FRAME_COUNTS;
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_
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,
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) {
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;
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;
// 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]
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,
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);
}
}
}
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);
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.
// 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
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,
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) {
VPxWorker lf_worker;
VPxWorker *tile_workers;
TileWorkerData *tile_worker_data;
- TileInfo *tile_worker_info;
int num_tile_workers;
TileData *tile_data;
#include "vpx_util/vpx_thread.h"
#include "vpx/internal/vpx_codec_internal.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9Common;
struct VP9Decoder;
void vp9_frameworker_copy_context(VPxWorker *const dst_worker,
VPxWorker *const src_worker);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_DECODER_VP9_DTHREAD_H_
// 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),
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.
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);
}
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);
#include "vp9/common/vp9_blockd.h"
#include "vp9/encoder/vp9_block.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9_COMP;
struct VP9Common;
struct ThreadData;
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_ */
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) {
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;
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);
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,
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 &&
}
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) {
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);
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);
int use_highbitdepth;
#endif
vpx_color_space_t color_space;
+ int color_range;
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
} VP9EncoderConfig;
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);
// 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);
}
}
#ifndef VP9_ENCODER_VP9_ETHREAD_H_
#define VP9_ENCODER_VP9_ETHREAD_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct VP9_COMP;
struct ThreadData;
void vp9_encode_tiles_mt(struct VP9_COMP *cpi);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_ENCODER_VP9_ETHREAD_H_
(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);
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 {
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.
}
// 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;
#include <stdio.h>
#include "vpx/vpx_integer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void vp9_resize_plane(const uint8_t *const input,
int height,
int width,
int owidth,
int bd);
#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif // VP9_ENCODER_VP9_RESIZE_H_
#include <math.h>
+#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
#include "vp9/encoder/vp9_extend.h"
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;
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;
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);
+ }
}
}
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) {
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) {
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);
}
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);
+ }
+ }
+}
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 {
// 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;
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
"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;
}
}
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 = {
VPX_BITS_8, // Bit depth
VP9E_CONTENT_DEFAULT, // content
VPX_CS_UNKNOWN, // color space
+ 0, // color range
};
struct vpx_codec_alg_priv {
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;
}
#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;
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 =
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},
{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},
(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;
}
}
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);
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);
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) {
(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] =
// 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;
}
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;
* 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
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
#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"
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 */
* 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) {
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
+}
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
*/
#include <limits.h>
+#include <stdlib.h>
+#include "./vpx_config.h"
#include "./bitwriter_buffer.h"
size_t vpx_wb_bytes_written(const struct vpx_write_bit_buffer *wb) {
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
+}
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"
%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
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]
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
;-------------------------------------------------------------------------------
%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]
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]
;-------------------------------------------------------------------------------
%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
lea srcq, [srcq + sstrideq]
mova [dstq], m0
lea dstq, [dstq + dstrideq]
- dec heightq
+ dec heightd
jnz .loop
RET
%endm
%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
;-------------------------------------------------------------------------------
%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]
%endif
movh [dstq + 8], m3
add dstq, dst_stride
- dec heightq
+ dec heightd
jnz .loop
RET
%endm
int subsampling_y;
unsigned int bit_depth;
vpx_color_space_t color_space;
+ int color_range;
int corrupted;
int flags;