]>
Commit | Line | Data |
---|---|---|
5641dccf KS |
1 | use nihav_core::formats; |
2 | use nihav_core::frame::*; | |
3 | use nihav_core::io::bitreader::*; | |
4 | use nihav_core::io::codebook::*; | |
5 | use nihav_core::io::intcode::*; | |
6 | use nihav_core::codecs::*; | |
b4d5b851 | 7 | use nihav_codec_support::codecs::{MV, ZERO_MV}; |
47527732 KS |
8 | use super::rv3040::*; |
9 | use super::rv40dsp::*; | |
eb904044 | 10 | use super::rv40data::*; |
47527732 KS |
11 | |
12 | struct AICCodeReader8 { | |
13 | lengths: &'static [u8], | |
14 | codes: &'static [u8], | |
15 | } | |
16 | ||
17 | impl CodebookDescReader<i8> for AICCodeReader8 { | |
18 | fn bits(&mut self, idx: usize) -> u8 { self.lengths[idx] } | |
19 | fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } | |
20 | fn sym (&mut self, idx: usize) -> i8 { idx as i8 } | |
21 | fn len (&mut self) -> usize { self.lengths.len() } | |
22 | } | |
23 | ||
24 | struct AICCodeReader16 { | |
25 | lengths: &'static [u8], | |
26 | codes: &'static [u16], | |
27 | } | |
28 | ||
29 | impl CodebookDescReader<i8> for AICCodeReader16 { | |
30 | fn bits(&mut self, idx: usize) -> u8 { self.lengths[idx] } | |
31 | fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } | |
32 | fn sym (&mut self, idx: usize) -> i8 { idx as i8 } | |
33 | fn len (&mut self) -> usize { self.lengths.len() } | |
34 | } | |
35 | ||
36 | struct TypeCodeReader { | |
37 | lengths: &'static [u8], | |
38 | codes: &'static [u8], | |
39 | syms: &'static [MBType], | |
40 | } | |
41 | ||
42 | impl CodebookDescReader<MBType> for TypeCodeReader { | |
43 | fn bits(&mut self, idx: usize) -> u8 { self.lengths[idx] } | |
44 | fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } | |
45 | fn sym (&mut self, idx: usize) -> MBType{ self.syms[idx] } | |
46 | fn len (&mut self) -> usize { self.lengths.len() } | |
47 | } | |
48 | ||
49 | struct RealVideo40BR { | |
50 | width: usize, | |
51 | height: usize, | |
52 | aic_top_cb: Codebook<i8>, | |
53 | aic_mode1_cb: Vec<Codebook<i8>>, | |
54 | aic_mode2_cb: Vec<Codebook<i8>>, | |
55 | ptype_cb: Vec<Codebook<MBType>>, | |
56 | btype_cb: Vec<Codebook<MBType>>, | |
57 | had_skip_run: bool, | |
58 | } | |
59 | ||
60 | impl RealVideo40BR { | |
61 | fn new() -> Self { | |
62 | let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_TOP_BITS, codes: &RV40_AIC_TOP_CODES }; | |
63 | let aic_top_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
64 | ||
65 | let mut aic_mode1_cb: Vec<Codebook<i8>> = Vec::with_capacity(RV40_AIC_MODE1_BITS.len()); | |
66 | for i in 0..RV40_AIC_MODE1_BITS.len() { | |
67 | if (i % 10) != 9 { | |
68 | let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_MODE1_BITS[i], codes: &RV40_AIC_MODE1_CODES[i] }; | |
69 | let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
70 | aic_mode1_cb.push(cb); | |
71 | } else { | |
72 | let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_MODE1_BITS_DUMMY, codes: &RV40_AIC_MODE1_CODES_DUMMY }; | |
73 | let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
74 | aic_mode1_cb.push(cb); | |
75 | } | |
76 | } | |
77 | ||
78 | let mut aic_mode2_cb: Vec<Codebook<i8>> = Vec::with_capacity(RV40_AIC_MODE2_BITS.len()); | |
79 | for i in 0..RV40_AIC_MODE2_BITS.len() { | |
80 | let mut coderead = AICCodeReader16{ lengths: &RV40_AIC_MODE2_BITS[i], codes: &RV40_AIC_MODE2_CODES[i] }; | |
81 | let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
82 | aic_mode2_cb.push(cb); | |
83 | } | |
84 | ||
85 | let mut ptype_cb: Vec<Codebook<MBType>> = Vec::with_capacity(RV40_PTYPE_BITS.len()); | |
86 | for i in 0..RV40_PTYPE_BITS.len() { | |
87 | let mut coderead = TypeCodeReader{ lengths: &RV40_PTYPE_BITS[i], codes: &RV40_PTYPE_CODES[i], syms: RV40_PTYPE_SYMS }; | |
88 | let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
89 | ptype_cb.push(cb); | |
90 | } | |
91 | ||
92 | let mut btype_cb: Vec<Codebook<MBType>> = Vec::with_capacity(RV40_BTYPE_BITS.len()); | |
93 | for i in 0..RV40_BTYPE_BITS.len() { | |
94 | let mut coderead = TypeCodeReader{ lengths: &RV40_BTYPE_BITS[i], codes: &RV40_BTYPE_CODES[i], syms: RV40_BTYPE_SYMS }; | |
95 | let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); | |
96 | btype_cb.push(cb); | |
97 | } | |
98 | ||
99 | RealVideo40BR { | |
100 | width: 0, | |
101 | height: 0, | |
e07387c7 KS |
102 | aic_top_cb, |
103 | aic_mode1_cb, | |
104 | aic_mode2_cb, | |
105 | ptype_cb, | |
106 | btype_cb, | |
47527732 KS |
107 | had_skip_run: false, |
108 | } | |
109 | } | |
e07387c7 | 110 | fn predict_b_mv_component(&self, sstate: &SState, mvi: &MVInfo, mbinfo: &[RV34MBInfo], mbtype: MBType, fwd: bool) -> MV { |
47527732 KS |
111 | let mut pred_mvs: [MV; 3] = [ZERO_MV; 3]; |
112 | let mut mv_count: usize = 0; | |
113 | let mb_x = sstate.mb_x; | |
114 | let mb_y = sstate.mb_y; | |
115 | let mb_stride = sstate.mb_w; | |
116 | let mb_idx = mb_x + mb_y * mb_stride; | |
117 | ||
118 | if !mbtype.has_mv_dir(fwd) { | |
119 | return ZERO_MV; | |
120 | } | |
121 | ||
122 | if sstate.has_left && mbinfo[mb_idx - 1].mbtype.has_mv_dir(fwd) { | |
123 | pred_mvs[mv_count] = mvi.get_mv(mb_x - 1, mb_y, 0, 0, fwd); | |
124 | mv_count += 1; | |
125 | } | |
126 | if !sstate.has_top { | |
127 | return pred_mvs[0]; | |
128 | } | |
129 | if mbinfo[mb_idx - mb_stride].mbtype.has_mv_dir(fwd) { | |
130 | pred_mvs[mv_count] = mvi.get_mv(mb_x, mb_y - 1, 0, 0, fwd); | |
131 | mv_count += 1; | |
132 | } | |
133 | if sstate.has_tr { | |
134 | if mbinfo[mb_idx - mb_stride + 1].mbtype.has_mv_dir(fwd) { | |
135 | pred_mvs[mv_count] = mvi.get_mv(mb_x + 1, mb_y - 1, 0, 0, fwd); | |
136 | mv_count += 1; | |
137 | } | |
138 | } else { | |
139 | if sstate.has_tl && mbinfo[mb_idx - mb_stride - 1].mbtype.has_mv_dir(fwd) { | |
140 | pred_mvs[mv_count] = mvi.get_mv(mb_x - 1, mb_y - 1, 0, 0, fwd); | |
141 | mv_count += 1; | |
142 | } | |
143 | } | |
144 | ||
145 | match mv_count { | |
146 | 3 => MV::pred(pred_mvs[0], pred_mvs[1], pred_mvs[2]), | |
147 | 2 => { let sum_mv = pred_mvs[0] + pred_mvs[1]; MV { x: sum_mv.x / 2, y: sum_mv.y / 2 } }, | |
148 | 1 => pred_mvs[0], | |
149 | _ => ZERO_MV, | |
150 | } | |
151 | } | |
152 | } | |
153 | ||
154 | fn get_dimension(br: &mut BitReader, tab: &'static [i16]) -> DecoderResult<usize> { | |
155 | let t = br.read(3)? as usize; | |
156 | if tab[t] > 0 { return Ok(tab[t] as usize); } | |
157 | if tab[t] < 0 { | |
158 | let idx = (-tab[t] as usize) + (br.read(1)? as usize); | |
159 | if tab[idx] != 0 { return Ok(tab[idx] as usize); } | |
160 | } | |
161 | let mut size: usize = 0; | |
162 | loop { | |
163 | let t = br.read(8)? as usize; | |
164 | size += t << 2; | |
165 | if t != 255 { break; } | |
166 | } | |
167 | Ok(size) | |
168 | } | |
169 | ||
170 | impl RV34BitstreamDecoder for RealVideo40BR { | |
171 | fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader> { | |
172 | if br.read(1)? != 0 { return Err(DecoderError::InvalidData); } | |
173 | let ft_idx = br.read(2)?; | |
174 | let ftype = match ft_idx { | |
175 | 0|1 => FrameType::I, | |
176 | 2 => FrameType::P, | |
177 | _ => FrameType::B, | |
178 | }; | |
179 | let q = br.read(5)? as u8; | |
180 | if br.read(2)? != 0 { return Err(DecoderError::InvalidData); } | |
181 | let set_idx = br.read(2)? as usize; | |
182 | let deblock = !br.read_bool()?; | |
183 | let pts = br.read(13)? as u16; | |
184 | let w; | |
185 | let h; | |
186 | if (ftype == FrameType::I) || !br.read_bool()? { | |
187 | w = get_dimension(br, &RV40_STANDARD_WIDTHS)?; | |
188 | h = get_dimension(br, &RV40_STANDARD_HEIGHTS)?; | |
189 | } else { | |
190 | w = old_w; | |
191 | h = old_h; | |
192 | } | |
193 | let start = br.read(get_slice_start_offset_bits(w, h))? as usize; | |
47527732 KS |
194 | |
195 | self.had_skip_run = false; | |
196 | ||
e07387c7 | 197 | Ok(RV34SliceHeader{ ftype, quant: q, deblock, pts, width: w, height: h, start, end: 0, set_idx }) |
47527732 KS |
198 | } |
199 | fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], mut pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()> { | |
200 | let start; | |
47527732 KS |
201 | if has_top { |
202 | start = 0; | |
203 | } else { | |
204 | let code = br.read_cb(&self.aic_top_cb)?; | |
205 | types[pos + 0] = (code >> 2) & 2; | |
206 | types[pos + 1] = (code >> 1) & 2; | |
207 | types[pos + 2] = (code >> 0) & 2; | |
208 | types[pos + 3] = (code << 1) & 2; | |
47527732 KS |
209 | pos += tstride; |
210 | start = 1; | |
211 | } | |
212 | for _ in start..4 { | |
213 | let mut x: usize = 0; | |
214 | while x < 4 { | |
215 | let tr = types[pos + x - tstride + 1]; | |
216 | let t = types[pos + x - tstride]; | |
217 | let l = types[pos + x - 1]; | |
47527732 KS |
218 | let ctx = if x < 3 { ((tr & 0xF) as u16) + (((t as u16) & 0xF) << 4) + (((l as u16) & 0xF) << 8) } else { 0xFFF }; |
219 | let res = RV40_AIC_PATTERNS.iter().position(|&x| x == ctx); | |
220 | if let Some(idx) = res { | |
221 | let code = br.read_cb(&self.aic_mode2_cb[idx])?; | |
222 | types[pos + x + 0] = code / 9; | |
223 | types[pos + x + 1] = code % 9; | |
47527732 KS |
224 | x += 2; |
225 | } else { | |
226 | if (t != -1) && (l != -1) { | |
227 | let idx = (t as usize) + (l as usize) * 10; | |
228 | types[pos + x] = br.read_cb(&self.aic_mode1_cb[idx])?; | |
229 | } else { | |
230 | match l { | |
231 | -1 if t < 2 => { types[pos + x] = (br.read(1)? as i8) ^ 1; }, | |
232 | 0 | 2 => { types[pos + x] = ((br.read(1)? as i8) ^ 1) << 1; }, | |
233 | _ => { types[pos + x] = 0; }, | |
234 | }; | |
235 | } | |
47527732 KS |
236 | x += 1; |
237 | } | |
238 | } | |
239 | pos += tstride; | |
240 | } | |
241 | Ok(()) | |
242 | } | |
243 | fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype_ref: MBType) -> DecoderResult<MBInfo> { | |
244 | let skip_run = if self.had_skip_run { 0 } else { br.read_code(UintCodeType::Gamma)? as usize }; | |
245 | if skip_run > 0 { | |
246 | self.had_skip_run = true; | |
247 | return Ok(MBInfo { mbtype: MBType::MBSkip, skip_run: skip_run - 1, dquant: false }) | |
248 | } | |
249 | self.had_skip_run = false; | |
250 | let mut mbtype; | |
251 | let idx; | |
252 | if ftype == FrameType::P { | |
253 | idx = match mbtype_ref { | |
254 | MBType::MBIntra => 0, | |
255 | MBType::MBIntra16 => 1, | |
256 | MBType::MBP16x16 => 2, | |
257 | MBType::MBP8x8 => 3, | |
258 | MBType::MBP16x8 => 4, | |
259 | MBType::MBP8x16 => 5, | |
260 | MBType::MBP16x16Mix => 6, | |
261 | _ => unreachable!(), | |
262 | }; | |
263 | mbtype = br.read_cb(&self.ptype_cb[idx])?; | |
264 | } else { | |
265 | idx = match mbtype_ref { | |
266 | MBType::MBIntra => 0, | |
267 | MBType::MBIntra16 => 1, | |
268 | MBType::MBForward => 2, | |
269 | MBType::MBBackward => 3, | |
270 | MBType::MBBidir => 4, | |
271 | MBType::MBDirect => 5, | |
272 | _ => 0, | |
273 | }; | |
274 | mbtype = br.read_cb(&self.btype_cb[idx])?; | |
275 | } | |
276 | let dquant = mbtype == MBType::Invalid; | |
277 | if dquant { | |
278 | mbtype = if ftype == FrameType::P { br.read_cb(&self.ptype_cb[idx])? } | |
279 | else { br.read_cb(&self.btype_cb[idx])? }; | |
280 | } | |
e07387c7 | 281 | Ok(MBInfo { mbtype, skip_run: 0, dquant }) |
47527732 | 282 | } |
e07387c7 | 283 | fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV) { |
47527732 KS |
284 | let mut mv_f = self.predict_b_mv_component(sstate, mvi, mbinfo, mbtype, true); |
285 | let mut mv_b = self.predict_b_mv_component(sstate, mvi, mbinfo, mbtype, false); | |
286 | ||
287 | match mbtype { | |
288 | MBType::MBForward => { mv_f += mvs[0]; }, | |
289 | MBType::MBBackward => { mv_b += mvs[0]; }, | |
290 | MBType::MBBidir => { | |
291 | mv_f += mvs[0]; | |
292 | mv_b += mvs[1]; | |
293 | }, | |
294 | _ => {}, | |
295 | }; | |
296 | ||
297 | (mv_f, mv_b) | |
298 | } | |
299 | fn quant_dc(&self, is_intra: bool, q: u8) -> u8 { RV40_QUANT_DC[if is_intra { 0 } else { 1 }][q as usize] } | |
300 | } | |
301 | ||
302 | struct RealVideo40Decoder { | |
303 | bd: RealVideo40BR, | |
2422d969 | 304 | info: NACodecInfoRef, |
47527732 KS |
305 | dec: RV34Decoder, |
306 | } | |
307 | ||
308 | impl RealVideo40Decoder { | |
309 | fn new() -> Self { | |
310 | RealVideo40Decoder{ | |
311 | bd: RealVideo40BR::new(), | |
2422d969 | 312 | info: NACodecInfoRef::default(), |
47527732 KS |
313 | dec: RV34Decoder::new(false, Box::new(RV40DSP::new())), |
314 | } | |
315 | } | |
316 | } | |
317 | ||
318 | impl NADecoder for RealVideo40Decoder { | |
3c69ce1b | 319 | fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
47527732 KS |
320 | if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { |
321 | let fmt = formats::YUV420_FORMAT; | |
322 | let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt)); | |
2422d969 | 323 | self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); |
47527732 KS |
324 | |
325 | let edata = info.get_extradata().unwrap(); | |
326 | let src: &[u8] = &edata; | |
327 | ||
47527732 KS |
328 | if src.len() < 2 { return Err(DecoderError::InvalidData); } |
329 | ||
330 | self.bd.width = vinfo.get_width(); | |
331 | self.bd.height = vinfo.get_height(); | |
3c69ce1b KS |
332 | |
333 | supp.pool_u8.set_dec_bufs(3); | |
334 | supp.pool_u8.prealloc_video(NAVideoInfo::new(self.bd.width, self.bd.height, false, fmt), 4)?; | |
335 | ||
47527732 KS |
336 | Ok(()) |
337 | } else { | |
47527732 KS |
338 | Err(DecoderError::InvalidData) |
339 | } | |
340 | } | |
3c69ce1b | 341 | fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
47527732 KS |
342 | let src = pkt.get_buffer(); |
343 | ||
3c69ce1b | 344 | let (bufinfo, ftype, ts) = self.dec.parse_frame(supp, src.as_slice(), &mut self.bd)?; |
47527732 KS |
345 | |
346 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); | |
347 | frm.set_keyframe(ftype == FrameType::I); | |
348 | frm.set_frame_type(ftype); | |
349 | frm.set_pts(Some(ts)); | |
171860fc | 350 | Ok(frm.into_ref()) |
47527732 | 351 | } |
f9be4e75 KS |
352 | fn flush(&mut self) { |
353 | self.dec.flush(); | |
354 | } | |
47527732 KS |
355 | } |
356 | ||
7d57ae2f KS |
357 | impl NAOptionHandler for RealVideo40Decoder { |
358 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
359 | fn set_options(&mut self, _options: &[NAOption]) { } | |
360 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
361 | } | |
362 | ||
08a1fab7 | 363 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
47527732 KS |
364 | Box::new(RealVideo40Decoder::new()) |
365 | } | |
366 | ||
367 | #[cfg(test)] | |
368 | mod test { | |
3167c45c KS |
369 | use nihav_core::codecs::RegisteredDecoders; |
370 | use nihav_core::demuxers::RegisteredDemuxers; | |
ce742854 | 371 | use nihav_codec_support::test::dec_video::*; |
78fb6560 | 372 | use crate::realmedia_register_all_decoders; |
e64739f8 | 373 | use crate::realmedia_register_all_demuxers; |
886cde48 | 374 | // samples from a private collection |
47527732 KS |
375 | #[test] |
376 | fn test_rv40() { | |
3167c45c KS |
377 | let mut dmx_reg = RegisteredDemuxers::new(); |
378 | realmedia_register_all_demuxers(&mut dmx_reg); | |
379 | let mut dec_reg = RegisteredDecoders::new(); | |
78fb6560 | 380 | realmedia_register_all_decoders(&mut dec_reg); |
3167c45c | 381 | |
1702ecec KS |
382 | test_decoding("realmedia", "realvideo4", "assets/RV/rv40_weighted_mc.rmvb", Some(1500), |
383 | &dmx_reg, &dec_reg,ExpectedTestResult::MD5Frames(vec![ | |
384 | [0x27cf336a, 0xc1686c50, 0x5304783d, 0x6e77ffa2], | |
385 | [0x91f236c7, 0x3bda2d38, 0x961a0243, 0xda803cf1], | |
386 | [0x4075d7e8, 0xbcd7f85b, 0x1c0dd34b, 0x405d0a5d], | |
387 | [0x642498b7, 0xb57aa202, 0x69ea0d23, 0x1cc0794f], | |
388 | [0x1c1a4df8, 0x7e3fbd7d, 0x7fdeb57f, 0xf5d65179], | |
389 | [0x86a5dcdd, 0xd66caabf, 0xdfe1fc99, 0xb3443375], | |
390 | [0x86846664, 0xbee4268d, 0xc1e017e6, 0xc9d984c8], | |
391 | [0x0ecbe176, 0x81e5aca6, 0xb7bda49c, 0x34007e7b], | |
392 | [0x48c8a90e, 0xed003b8a, 0xc9e7e9a6, 0x54b1eca8], | |
393 | [0x540cbc0b, 0x6d7afaa8, 0xb0951c1f, 0xed22089e], | |
394 | [0x73190f85, 0x9cd72603, 0x1063ca54, 0xd4f82c7f], | |
395 | [0xef6206e8, 0x6affb292, 0xe12b7c9c, 0x37416240], | |
396 | [0x59f61c91, 0x66b2a632, 0x46556395, 0x74fbc1de], | |
397 | [0xd75635ca, 0x60d13826, 0xfa41d914, 0x9cfded0e], | |
398 | [0x7a8c4396, 0x6f3eda39, 0x4238dbaf, 0xa9052803]])); | |
399 | test_decoding("realmedia", "realvideo4", "assets/RV/rv40_weighted_mc_2.rmvb", Some(2000), | |
400 | &dmx_reg, &dec_reg, | |
401 | ExpectedTestResult::MD5([0x4224b9d6, 0x32e3ff63, 0x02df9e60, 0xfa0548ee])); | |
47527732 KS |
402 | } |
403 | } | |
404 | ||
405 | const RV40_STANDARD_WIDTHS: [i16; 8] = [ 160, 172, 240, 320, 352, 640, 704, 0 ]; | |
406 | const RV40_STANDARD_HEIGHTS: [i16; 12] = [ 120, 132, 144, 240, 288, 480, -8, -10, 180, 360, 576, 0 ]; |