mod error;
mod sw;
pub mod uapi;
use error::ImageResult;
use std::io::Read;
use sw::Vp8Decoder;
pub use uapi::CtrlVp8Frame;
const DEFAULT_MV_PROBS: [[u8; 19]; 2] = [
[
162, 128, 225, 146, 172, 147, 214, 39, 156, 128, 129, 132, 75, 145, 178, 206, 239, 254, 254,
],
[
164, 128, 204, 170, 119, 235, 140, 230, 228, 128, 130, 130, 74, 148, 180, 203, 236, 254,
254,
],
];
pub struct Parser<R: core::fmt::Debug> {
sw: Vp8Decoder<R>,
}
impl<R: Read + core::fmt::Debug> Parser<R> {
pub fn new(r: R) -> Parser<R> {
let sw = Vp8Decoder::new(r);
Parser { sw }
}
pub fn parse_vp8(&mut self) -> ImageResult<CtrlVp8Frame> {
assert_eq!(std::mem::size_of::<CtrlVp8Frame>(), 1232);
self.sw.read_frame_header()?;
assert_eq!(self.sw.num_partitions, 1);
let quant_update = [
self.sw.segment[0].quantizer_level,
self.sw.segment[1].quantizer_level,
self.sw.segment[2].quantizer_level,
self.sw.segment[3].quantizer_level,
];
let lf_update = [
self.sw.segment[0].loopfilter_level,
self.sw.segment[1].loopfilter_level,
self.sw.segment[2].loopfilter_level,
self.sw.segment[3].loopfilter_level,
];
let mut flags = uapi::Vp8SegmentFlags::empty();
if self.sw.segments_enabled {
flags |= uapi::Vp8SegmentFlags::ENABLED;
}
if self.sw.segments_update_map {
flags |= uapi::Vp8SegmentFlags::UPDATE_MAP;
}
if self.sw.update_segment_feature_data {
flags |= uapi::Vp8SegmentFlags::UPDATE_FEATURE_DATA;
}
let segment = uapi::v4l2_vp8_segment {
quant_update,
lf_update,
segment_probs: self.sw.segment_tree_probs,
padding: 0,
flags,
};
let mut flags = uapi::Vp8LoopFilter::empty();
if self.sw.lf_adjust_enable {
flags |= uapi::Vp8LoopFilter::ADJ_ENABLE;
}
if self.sw.delta_update {
flags |= uapi::Vp8LoopFilter::DELTA_UPDATE;
}
if self.sw.frame.filter_type {
flags |= uapi::Vp8LoopFilter::FILTER_TYPE_SIMPLE;
}
let lf = uapi::v4l2_vp8_loop_filter {
ref_frm_delta: self.sw.ref_delta,
mb_mode_delta: self.sw.mode_delta,
sharpness_level: self.sw.frame.sharpness_level,
level: self.sw.frame.filter_level,
padding: 0,
flags,
};
let quant = uapi::v4l2_vp8_quantization {
y_ac_qi: self.sw.quant.y_ac_qi,
y_dc_delta: self.sw.quant.y_dc_delta,
y2_dc_delta: self.sw.quant.y2_dc_delta,
y2_ac_delta: self.sw.quant.y2_ac_delta,
uv_dc_delta: self.sw.quant.uv_dc_delta,
uv_ac_delta: self.sw.quant.uv_ac_delta,
padding: 0,
};
let entropy = uapi::v4l2_vp8_entropy {
coeff_probs: *self.sw.token_probs,
y_mode_probs: sw::KEYFRAME_YMODE_PROBS,
uv_mode_probs: sw::KEYFRAME_UV_MODE_PROBS,
mv_probs: DEFAULT_MV_PROBS,
padding: [0; 3],
};
let coder_state = uapi::v4l2_vp8_entropy_coder_state {
range: self.sw.b.range as u8,
value: self.sw.b.value as u8,
bit_count: self.sw.b.bit_count,
padding: 0,
};
let (mb_no_skip_coeff, prob_skip_false) =
if let Some(prob_skip_false) = self.sw.prob_skip_false {
(true, prob_skip_false)
} else {
(false, 0)
};
let mut flags = uapi::Vp8FrameFlags::empty();
if self.sw.frame.keyframe {
flags |= uapi::Vp8FrameFlags::KEY_FRAME;
}
if self.sw.frame.for_display {
flags |= uapi::Vp8FrameFlags::SHOW_FRAME;
}
if mb_no_skip_coeff {
flags |= uapi::Vp8FrameFlags::MB_NO_SKIP_COEFF;
}
Ok(CtrlVp8Frame {
segment,
lf,
quant,
entropy,
coder_state,
width: self.sw.frame.width,
height: self.sw.frame.height,
horizontal_scale: self.sw.frame.horizontal_scale,
vertical_scale: self.sw.frame.vertical_scale,
version: self.sw.frame.version,
prob_skip_false,
prob_intra: 0,
prob_last: 0,
prob_gf: 0,
num_dct_parts: self.sw.num_partitions,
first_part_size: self.sw.frame.first_partition_size,
first_part_header_bits: 0,
dct_part_sizes: [0, 0, 0, 0, 0, 0, 0, 0],
last_frame_ts: 0,
golden_frame_ts: 0,
alt_frame_ts: 0,
flags,
})
}
}