Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale chroma distortion. #1583

Merged
merged 2 commits into from
Oct 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 21 additions & 39 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ pub struct FrameInvariants<T: Pixel> {
pub ac_delta_q: [i8; 3],
pub lambda: f64,
pub me_lambda: f64,
pub dist_scale: [f64; 3],
pub me_range_scale: u8,
pub use_tx_domain_distortion: bool,
pub use_tx_domain_rate: bool,
Expand Down Expand Up @@ -684,6 +685,7 @@ impl<T: Pixel> FrameInvariants<T> {
dc_delta_q: [0; 3],
ac_delta_q: [0; 3],
lambda: 0.0,
dist_scale: [1.0; 3],
me_lambda: 0.0,
me_range_scale: 1,
use_tx_domain_distortion,
Expand Down Expand Up @@ -866,6 +868,7 @@ impl<T: Pixel> FrameInvariants<T> {
self.lambda =
qps.lambda * ((1 << (2 * (self.sequence.bit_depth - 8))) as f64);
self.me_lambda = self.lambda.sqrt();
self.dist_scale = qps.dist_scale;

let q = bexp64(qps.log_target_q as i64 + q57(QSCALE)) as f32;
/* These coefficients were trained on libaom. */
Expand Down Expand Up @@ -1083,7 +1086,7 @@ pub fn encode_tx_block<T: Pixel>(
alpha: i16,
rdo_type: RDOType,
need_recon_pixel: bool,
) -> (bool, i64) {
) -> (bool, ScaledDistortion) {
let qidx = get_qidx(fi, ts, cw, tile_bo);
assert_ne!(qidx, 0); // lossless is not yet supported
let PlaneConfig { xdec, ydec, .. } = ts.input.planes[p].cfg;
Expand Down Expand Up @@ -1126,7 +1129,7 @@ pub fn encode_tx_block<T: Pixel>(
}

if skip {
return (false, -1);
return (false, ScaledDistortion::zero());
}

let mut residual_storage: AlignedArray<[i16; 64 * 64]> =
Expand Down Expand Up @@ -1192,7 +1195,7 @@ pub fn encode_tx_block<T: Pixel>(
fi.ac_delta_q[p],
);

let mut tx_dist: i64 = -1;
let mut tx_dist: u64 = 0;

if !fi.use_tx_domain_distortion || need_recon_pixel {
inverse_transform_add(
Expand All @@ -1212,27 +1215,24 @@ pub fn encode_tx_block<T: Pixel>(
let c = *a as i32 - *b as i32;
(c * c) as u64
})
.sum::<u64>() as i64;
.sum::<u64>();

let tx_dist_scale_bits = 2 * (3 - get_log_tx_scale(tx_size));
let tx_dist_scale_rounding_offset = 1 << (tx_dist_scale_bits - 1);
tx_dist = (tx_dist + tx_dist_scale_rounding_offset) >> tx_dist_scale_bits;
}
if fi.config.train_rdo {
ts.rdo.add_rate(
fi.base_q_idx,
tx_size,
tx_dist as u64,
cost_coeffs as u64,
);
ts.rdo.add_rate(fi.base_q_idx, tx_size, tx_dist, cost_coeffs as u64);
}

if rdo_type == RDOType::TxDistEstRate {
// look up rate and distortion in table
let estimated_rate = estimate_rate(fi.base_q_idx, tx_size, tx_dist as u64);
let estimated_rate = estimate_rate(fi.base_q_idx, tx_size, tx_dist);
w.add_bits_frac(estimated_rate as u32);
}
(has_coeff, tx_dist)
let bias =
compute_distortion_bias(fi, ts.to_frame_block_offset(tile_bo), bsize);
(has_coeff, RawDistortion::new(tx_dist) * bias * fi.dist_scale[p])
}

pub fn motion_compensate<T: Pixel>(
Expand Down Expand Up @@ -1486,7 +1486,7 @@ pub fn encode_block_post_cdef<T: Pixel>(
skip: bool, cfl: CFLParams, tx_size: TxSize, tx_type: TxType,
mode_context: usize, mv_stack: &[CandidateMV], rdo_type: RDOType,
need_recon_pixel: bool, record_stats: bool,
) -> (bool, i64) {
) -> (bool, ScaledDistortion) {
let is_inter = !luma_mode.is_intra();
if is_inter {
assert!(luma_mode == chroma_mode);
Expand Down Expand Up @@ -1759,15 +1759,15 @@ pub fn write_tx_blocks<T: Pixel>(
chroma_mode: PredictionMode, tile_bo: TileBlockOffset, bsize: BlockSize,
tx_size: TxSize, tx_type: TxType, skip: bool, cfl: CFLParams,
luma_only: bool, rdo_type: RDOType, need_recon_pixel: bool,
) -> (bool, i64) {
) -> (bool, ScaledDistortion) {
let bw = bsize.width_mi() / tx_size.width_mi();
let bh = bsize.height_mi() / tx_size.height_mi();
let qidx = get_qidx(fi, ts, cw, tile_bo);

let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg;
let mut ac: AlignedArray<[i16; 32 * 32]> = AlignedArray::uninitialized();
let mut partition_has_coeff: bool = false;
let mut tx_dist: i64 = 0;
let mut tx_dist = ScaledDistortion::zero();
let do_chroma = has_chroma(tile_bo, bsize, xdec, ydec);

ts.qc.update(
Expand Down Expand Up @@ -1809,9 +1809,6 @@ pub fn write_tx_blocks<T: Pixel>(
need_recon_pixel,
);
partition_has_coeff |= has_coeff;
assert!(
!fi.use_tx_domain_distortion || need_recon_pixel || skip || dist >= 0
);
tx_dist += dist;
}
}
Expand Down Expand Up @@ -1895,12 +1892,6 @@ pub fn write_tx_blocks<T: Pixel>(
need_recon_pixel,
);
partition_has_coeff |= has_coeff;
assert!(
!fi.use_tx_domain_distortion
|| need_recon_pixel
|| skip
|| dist >= 0
);
tx_dist += dist;
}
}
Expand All @@ -1918,17 +1909,16 @@ pub fn write_tx_tree<T: Pixel>(
tile_bo: TileBlockOffset, bsize: BlockSize, tx_size: TxSize,
tx_type: TxType, skip: bool, luma_only: bool, rdo_type: RDOType,
need_recon_pixel: bool,
) -> (bool, i64) {
) -> (bool, ScaledDistortion) {
if skip {
return (false, -1);
return (false, ScaledDistortion::zero());
}
let bw = bsize.width_mi() / tx_size.width_mi();
let bh = bsize.height_mi() / tx_size.height_mi();
let qidx = get_qidx(fi, ts, cw, tile_bo);

let PlaneConfig { xdec, ydec, .. } = ts.input.planes[1].cfg;
let ac = &[0i16; 0];
let mut tx_dist: i64 = 0;
let mut partition_has_coeff: bool = false;

ts.qc.update(
Expand Down Expand Up @@ -1963,10 +1953,7 @@ pub fn write_tx_tree<T: Pixel>(
need_recon_pixel,
);
partition_has_coeff |= has_coeff;
assert!(
!fi.use_tx_domain_distortion || need_recon_pixel || skip || dist >= 0
);
tx_dist += dist;
let mut tx_dist = dist;

if luma_only {
return (partition_has_coeff, tx_dist);
Expand Down Expand Up @@ -2039,12 +2026,6 @@ pub fn write_tx_tree<T: Pixel>(
need_recon_pixel,
);
partition_has_coeff |= has_coeff;
assert!(
!fi.use_tx_domain_distortion
|| need_recon_pixel
|| skip
|| dist >= 0
);
tx_dist += dist;
}
}
Expand Down Expand Up @@ -2171,7 +2152,7 @@ fn encode_partition_bottomup<T: Pixel, W: Writer>(
let w: &mut W = if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef };
let tell = w.tell_frac();
cw.write_partition(w, tile_bo, PartitionType::PARTITION_NONE, bsize);
compute_rd_cost(fi, w.tell_frac() - tell, 0)
compute_rd_cost(fi, w.tell_frac() - tell, ScaledDistortion::zero())
} else {
0.0
};
Expand Down Expand Up @@ -2271,7 +2252,8 @@ fn encode_partition_bottomup<T: Pixel, W: Writer>(
if cw.bc.cdef_coded { w_post_cdef } else { w_pre_cdef };
let tell = w.tell_frac();
cw.write_partition(w, tile_bo, partition, bsize);
rd_cost = compute_rd_cost(fi, w.tell_frac() - tell, 0);
rd_cost =
compute_rd_cost(fi, w.tell_frac() - tell, ScaledDistortion::zero());
}

let four_partitions = [
Expand Down
17 changes: 13 additions & 4 deletions src/rate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ pub struct QuantizerParameters {
pub dc_qi: [u8; 3],
pub ac_qi: [u8; 3],
pub lambda: f64,
pub dist_scale: [f64; 3],
}

const Q57_SQUARE_EXP_SCALE: f64 =
Expand All @@ -573,8 +574,16 @@ impl QuantizerParameters {
let scale = q57(QSCALE + bit_depth as i32 - 8);
let quantizer = bexp64(log_target_q + scale);
let (offset_u, offset_v) = chroma_offset(log_target_q);
let quantizer_u = bexp64(log_target_q + offset_u + scale);
let quantizer_v = bexp64(log_target_q + offset_v + scale);
let log_target_q_u = log_target_q + offset_u;
let log_target_q_v = log_target_q + offset_v;
let quantizer_u = bexp64(log_target_q_u + scale);
let quantizer_v = bexp64(log_target_q_v + scale);
let lambda = (::std::f64::consts::LN_2 / 6.0)
* ((log_target_q as f64) * Q57_SQUARE_EXP_SCALE).exp();
let lambda_u = (::std::f64::consts::LN_2 / 6.0)
* ((log_target_q_u as f64) * Q57_SQUARE_EXP_SCALE).exp();
let lambda_v = (::std::f64::consts::LN_2 / 6.0)
* ((log_target_q_v as f64) * Q57_SQUARE_EXP_SCALE).exp();
QuantizerParameters {
log_base_q,
log_target_q,
Expand All @@ -589,8 +598,8 @@ impl QuantizerParameters {
select_ac_qi(quantizer_u, bit_depth).max(1),
select_ac_qi(quantizer_v, bit_depth).max(1),
],
lambda: (::std::f64::consts::LN_2 / 6.0)
* ((log_target_q as f64) * Q57_SQUARE_EXP_SCALE).exp(),
lambda,
dist_scale: [1.0, lambda / lambda_u, lambda / lambda_v],
Copy link
Collaborator

@ycho ycho Oct 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, but scalers for YUV are derived from lambdas?! Isn't that essentially equivalent to applying different lambda values when computing rd_cost? If so, I am afraid I need to ask why we want to scale distortions?

}
}
}
Expand Down
Loading