///|
/// The feature tables saved by update_reference_map do not alias header arrays.
fn av1_segmentation_copy(
params : Av1SegmentationParams,
) -> Av1SegmentationParams {
{
..params,
feature_enabled: params.feature_enabled.map(row => row.copy()),
feature_data: params.feature_data.map(row => row.copy()),
}
}
///|
fn av1_segmentation_primary(
map : Av1FrameMap?,
primary : Int,
indices : Array[Int],
) -> Av1SegmentationParams? {
if primary < 0 ||
primary >= av1_primary_ref_none ||
primary >= indices.length() {
return None
}
let state = match map {
Some(value) => value
None => return None
}
let slot = indices[primary]
if slot < 0 || slot >= av1_num_ref_frames || !state.valid[slot] {
return None
}
Some(av1_segmentation_copy(state.saved_segmentation[slot]))
}
///|
fn av1_segment_feature(
params : Av1SegmentationParams,
id : Int,
feature : Int,
) -> Bool {
params.enabled &&
id >= 0 &&
id < av1_segments &&
feature >= 0 &&
feature < av1_segment_levels &&
params.feature_enabled[id][feature]
}
///|
/// Segment map prediction uses the minimum id over the whole block footprint.
fn av1_segment_previous_id(
state : Av1IntraState,
row : Int,
col : Int,
width4 : Int,
height4 : Int,
) -> Int {
if state.previous_seg_ids.length() != state.cols * state.rows {
return 0
}
let mut predicted = 7
for y in row..<(row + height4) {
for x in col..<(col + width4) {
if y >= 0 && y < state.rows && x >= 0 && x < state.cols {
let id = state.previous_seg_ids[y * state.cols + x]
if id < predicted {
predicted = id
}
}
}
}
predicted
}