h264: move decoder-specific bits into separate module
[nihav.git] / nihav-itu / src / codecs / h264 / mod.rs
CommitLineData
696e4e20
KS
1/*
2 known bugs and limitations:
696e4e20
KS
3 * wrong slice boundary filtering
4 * not fully correct deblock strength selection for P/B-macroblocks
5 * scaling lists for 4x4 blocks
6*/
7use nihav_core::codecs::*;
8use nihav_core::io::byteio::*;
9use nihav_core::io::bitreader::*;
10use nihav_core::io::intcode::*;
11use nihav_codec_support::codecs::{MV, ZERO_MV};
12
13mod types;
14pub use types::*;
15mod pic_ref;
16pub use pic_ref::*;
4a1ca15c
KS
17#[allow(clippy::identity_op)]
18#[allow(clippy::erasing_op)]
19#[allow(clippy::many_single_char_names)]
20#[allow(clippy::range_plus_one)]
696e4e20
KS
21mod dsp;
22use dsp::*;
23mod cabac;
24use cabac::*;
25mod cabac_coder;
26use cabac_coder::*;
27mod cavlc;
28use cavlc::*;
29mod loopfilter;
30use loopfilter::*;
495b7ec0
KS
31mod mb_recon;
32use mb_recon::*;
696e4e20
KS
33mod sets;
34use sets::*;
35mod slice;
36use slice::*;
37
47ecb2b7
KS
38mod decoder_st;
39pub use decoder_st::*;
40
696e4e20
KS
41trait ReadUE {
42 fn read_ue(&mut self) -> DecoderResult<u32>;
43 fn read_te(&mut self, range: u32) -> DecoderResult<u32>;
44 fn read_ue_lim(&mut self, max_val: u32) -> DecoderResult<u32> {
45 let val = self.read_ue()?;
46 validate!(val <= max_val);
47 Ok(val)
48 }
49 fn read_se(&mut self) -> DecoderResult<i32> {
50 let val = self.read_ue()?;
51 if (val & 1) != 0 {
52 Ok (((val >> 1) as i32) + 1)
53 } else {
54 Ok (-((val >> 1) as i32))
55 }
56 }
57}
58
59impl<'a> ReadUE for BitReader<'a> {
60 fn read_ue(&mut self) -> DecoderResult<u32> {
61 Ok(self.read_code(UintCodeType::GammaP)? - 1)
62 }
63 fn read_te(&mut self, range: u32) -> DecoderResult<u32> {
64 if range == 1 {
65 if self.read_bool()? {
66 Ok(0)
67 } else {
68 Ok(1)
69 }
70 } else {
71 let val = self.read_ue()?;
72 validate!(val <= range);
73 Ok(val)
74 }
75 }
76}
77
78#[derive(Clone,Copy)]
79pub struct Coeff8x8 {
80 pub coeffs: [i16; 64],
81}
82
83impl Coeff8x8 {
84 fn clear(&mut self) {
85 self.coeffs = [0; 64];
86 }
87}
88
89impl Default for Coeff8x8 {
90 fn default() -> Self {
91 Self {
92 coeffs: [0; 64],
93 }
94 }
95}
96
97#[derive(Clone,Copy,Default)]
98pub struct CurrentMBInfo {
99 pub mb_type: MBType,
100 pub sub_mb_type: [SubMBType; 4],
101 pub ipred: [IntraPredMode; 16],
102 pub chroma_ipred: u8,
103 pub luma_ipred: [u8; 16],
104 pub mv_l0: [MV; 16],
105 pub ref_l0: [PicRef; 4],
106 pub mv_l1: [MV; 16],
107 pub ref_l1: [PicRef; 4],
108 pub qp_y: u8,
109 pub cbpy: u8,
110 pub cbpc: u8,
111 pub coeffs: [[i16; 16]; 25],
112 pub coeffs8x8: [Coeff8x8; 4],
113 pub chroma_dc: [[i16; 4]; 2],
114 pub coded: [bool; 25],
115 pub transform_size_8x8: bool,
116}
117
118impl CurrentMBInfo {
119 fn clear_coeffs8x8(&mut self) {
120 for c in self.coeffs8x8.iter_mut() {
121 c.clear();
122 }
123 }
124 fn can_have_8x8_tx(&self, inference_flag: bool) -> bool {
125 match self.mb_type {
126 MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM => false,
127 MBType::P8x8 | MBType::P8x8Ref0 | MBType::B8x8 => {
128 for &sub_id in self.sub_mb_type.iter() {
129 match sub_id {
130 SubMBType::P8x8 |
131 SubMBType::B8x8(_)
132 => {},
133 SubMBType::Direct8x8
134 => if !inference_flag { return false; },
135 _ => return false,
136 };
137 }
138 true
139 },
140 MBType::Direct => inference_flag,
141 _ => true,
142 }
143 }
144}
145
146fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option<usize> {
147 if is_idr && !slice_hdr.long_term_reference {
148 None
149 } else {
150 let marking = &slice_hdr.adaptive_ref_pic_marking;
151 for (&op, &arg) in marking.memory_management_control_op.iter().zip(marking.operation_arg.iter()).take(marking.num_ops) {
152 if op == 6 {
153 return Some(arg as usize);
154 }
155 }
156 None
157 }
158}
159
696e4e20
KS
160fn unescape_nal(src: &[u8], dst: &mut Vec<u8>) -> usize {
161 let mut off = 0;
162 let mut zrun = 0;
37952415 163 dst.clear();
696e4e20
KS
164 dst.reserve(src.len());
165 while off < src.len() {
166 dst.push(src[off]);
167 if src[off] != 0 {
168 zrun = 0;
169 } else {
170 zrun += 1;
171 if zrun == 2 && off + 1 < src.len() && src[off + 1] == 0x03 {
172 zrun = 0;
173 off += 1;
174 }
175 if zrun >= 3 && off + 1 < src.len() && src[off + 1] == 0x01 {
176 off -= 3;
177 dst.truncate(off);
178 break;
179 }
180 }
181 off += 1;
182 }
183 off
184}
185
696e4e20
KS
186const DEBLOCK_SKIP_OPTION: &str = "skip_deblock";
187
188const DECODER_OPTIONS: &[NAOptionDefinition] = &[
189 NAOptionDefinition {
190 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
191 opt_type: NAOptionDefinitionType::Bool },
192 NAOptionDefinition {
193 name: DEBLOCK_SKIP_OPTION, description: "Loop filter skipping mode",
194 opt_type: NAOptionDefinitionType::String(Some(&[
195 FRAME_SKIP_OPTION_VAL_NONE,
196 FRAME_SKIP_OPTION_VAL_KEYFRAME,
197 FRAME_SKIP_OPTION_VAL_INTRA
198 ])) },
199];
200
696e4e20
KS
201#[cfg(test)]
202mod test {
203 use nihav_core::codecs::RegisteredDecoders;
204 use nihav_core::demuxers::RegisteredDemuxers;
205 use nihav_codec_support::test::dec_video::*;
206 use crate::itu_register_all_decoders;
207 use nihav_commonfmt::generic_register_all_demuxers;
208
886cde48 209 // samples if not specified otherwise come from H.264 conformance suite
696e4e20
KS
210 mod raw_demux;
211 mod conformance;
212 use self::raw_demux::RawH264DemuxerCreator;
213
214 #[test]
215 fn test_h264_perframe() {
216 let mut dmx_reg = RegisteredDemuxers::new();
217 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
218 generic_register_all_demuxers(&mut dmx_reg);
219 let mut dec_reg = RegisteredDecoders::new();
220 itu_register_all_decoders(&mut dec_reg);
221
222 test_decoding("rawh264", "h264",
223 "assets/ITU/h264-conformance/CABAST3_Sony_E.jsv",
224 None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
7d251522
KS
225 [0xb5e5e368, 0x6ac59bfc, 0x82e35b7b, 0xbed17b81],
226 [0x8343b34d, 0x0de80ae9, 0xe9c08cc9, 0x05161d82],
227 [0x26e08b9b, 0x84949759, 0x71622124, 0x9bfff254],
228 [0x940c38bc, 0x559fb990, 0x2b82a7ca, 0x3543188a],
229 [0x60d7544d, 0x2fc8cc23, 0x4acac90f, 0x44c2a91c],
230 [0x68d86265, 0x15fc15b9, 0xe4946d83, 0x39d9584d],
231 [0xaed8e194, 0xa24b3a8a, 0xbed9085d, 0x05d68293],
232 [0x1cddffac, 0x0ce9d209, 0xc4090b8a, 0xc3008856],
233 [0x42ee0e5e, 0x4c1c3b64, 0xd91cc00b, 0x88be4b15],
234 [0x19a70aa8, 0xd8bc987d, 0x51c04849, 0x71191523],
235 [0x74532da6, 0xecb92919, 0xd39cb150, 0x9ca9933d],
236 [0x0444b315, 0x2ddfb91a, 0x1e21ce06, 0x0c8613e6],
237 [0xce209363, 0xf8d8331f, 0x72e0102f, 0x88de3a97],
238 [0xdbcfa40a, 0x7eed5940, 0xa5c53a66, 0xdfcd3cea],
239 [0x00796b14, 0x58f16117, 0xb6a5efd1, 0xfb129acd],
240 [0x7673f569, 0xfccfb96a, 0x1f614c82, 0xf62ea376],
241 [0x8669d98b, 0x9fdf4e7d, 0xa4083a7f, 0x9b66d296],
242 [0xf0537976, 0x924229ab, 0xd0f4612f, 0xad4b614e],
243 [0xbde82067, 0x6cf23a0c, 0xdd29e64d, 0xcaa72ff3],
244 [0xcfcb544a, 0x1f1a81b0, 0x2217108c, 0x4888d5ef],
245 [0x3369f874, 0x6a6dde75, 0x46d64780, 0xbf6ced32],
246 [0x253a1f45, 0x85954311, 0x983dbabe, 0x658f4ce3],
247 [0xec97b332, 0xa17b26d0, 0xbead22af, 0xa6bd7d8e],
248 [0x5673d973, 0x78528036, 0xabfe5e13, 0xdcedfb26],
249 [0xd6110fa9, 0x532d6a30, 0xb7f0aa7c, 0xae7b544b]]));
696e4e20
KS
250 }
251
886cde48 252 // mostly static music video downloaded with youtube-dl
696e4e20
KS
253 #[test]
254 fn test_h264_real1() {
255 let mut dmx_reg = RegisteredDemuxers::new();
256 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
257 generic_register_all_demuxers(&mut dmx_reg);
258 let mut dec_reg = RegisteredDecoders::new();
259 itu_register_all_decoders(&mut dec_reg);
260
261 test_decoding("mov", "h264", "assets/ITU/1.mp4",
262 Some(60), &dmx_reg, &dec_reg,
263 ExpectedTestResult::MD5Frames(vec![
264 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
265 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
266 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
267 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
268 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
269 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
270 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
271 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
272 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
273 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
274 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
275 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
276 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
277 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
278 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
279 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
280 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
281 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
282 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
283 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
284 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
285 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
286 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
287 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
288 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
289 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
290 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
291 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
292 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
293 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
294 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
295 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
296 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
297 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
298 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
299 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
300 [0x9dbac04a, 0xc49ca8c1, 0x09bb9182, 0xc7928970],
7d251522
KS
301 [0xc54f1b6e, 0xaba56a71, 0x8b45132b, 0x3c8bde7f],
302 [0xe2742374, 0x7b9d6fa6, 0xd57eb3bb, 0x42986664],
303 [0xa5ebdc2e, 0x9753a46a, 0x631c6359, 0x861ae0e3],
304 [0x4d2c8769, 0xb9e15141, 0x03274d1f, 0xc15a3733],
305 [0x17ebec8f, 0xe417571e, 0x75eb2559, 0x2f9b882b],
306 [0x148e8c97, 0x778f92ba, 0x93646539, 0xeebe643a],
307 [0xc6770caa, 0x1ac11a57, 0x1388a550, 0x2347758e],
308 [0x91eb3ae4, 0xaf664462, 0x858d344a, 0xda3baa79],
309 [0x4de79514, 0x3597aff0, 0x53e1a22f, 0x7875aa4c],
310 [0xd5afcf7c, 0xa0f4ce82, 0x21a70eb2, 0x3911cde1],
311 [0x9efa2a08, 0x29019ca6, 0xaba90890, 0xfb982857],
312 [0xc5755e20, 0x4c66cb54, 0x1194812e, 0x11a9d940],
313 [0xfd131bbb, 0x0acefb02, 0x6c79b7ab, 0x35bcdd26],
314 [0xad159db0, 0xfa65ced2, 0xf77e2b22, 0x9e6283a8],
315 [0xba2059e3, 0xc9f1e5e7, 0x7ea5fbcb, 0xf48d4fc3],
316 [0xbe794078, 0x64d69f9b, 0x7b6355c5, 0x7dfb5b0f],
317 [0x6031b77b, 0x712f42fd, 0x30d423df, 0x740e488c],
318 [0xcc475484, 0x30a664fc, 0x227a9725, 0x4b2bfb18],
319 [0x44bef2ea, 0xaf1e69e8, 0x832d94a8, 0xffb22712],
320 [0xe9471e3d, 0x103de80f, 0xdc44136f, 0x67dacaa8],
321 [0x4df3823d, 0xf6486ca9, 0x016f3114, 0x1c2d0b42],
322 [0x1171666b, 0x08ca0ced, 0x98719757, 0xbd6b4a86],
323 [0x9d2fc556, 0x5569fbbd, 0x0ebf629f, 0xd4fdc3b5],
324 [0x27dbd3c3, 0x803f0230, 0x13f2ff1b, 0xb661b622]]));
696e4e20 325 }
886cde48 326 // a sample downloaded from gfycat.com
696e4e20
KS
327 #[test]
328 fn test_h264_real2() {
329 let mut dmx_reg = RegisteredDemuxers::new();
330 dmx_reg.add_demuxer(&RawH264DemuxerCreator{});
331 generic_register_all_demuxers(&mut dmx_reg);
332 let mut dec_reg = RegisteredDecoders::new();
333 itu_register_all_decoders(&mut dec_reg);
334 test_decoding("mov", "h264", "assets/ITU/DimpledSpanishCuckoo-mobile.mp4",
335 Some(10), &dmx_reg, &dec_reg,
336 ExpectedTestResult::MD5Frames(vec![
7d251522
KS
337 [0x674c6d60, 0xc7ab918d, 0x9db1beaf, 0xda9f2456],
338 [0x6a935350, 0x3d463ab2, 0xa3ab3c53, 0x97eb896b],
339 [0xf6c60411, 0x19ea2c49, 0x3512371a, 0xce6cb26a],
340 [0xc87afeaa, 0x79899908, 0x152e6320, 0xe689827f],
341 [0xa3d829e3, 0xb404dd32, 0x11983613, 0xbdf10ee6],
342 [0x2440ea01, 0x5b9d7fc7, 0x4fa5632b, 0xd2d76090],
343 [0xd80e8bf9, 0xe9190ab7, 0x2be8fa38, 0xb94182e8],
344 [0x50b9fd9a, 0x64393126, 0xd03162ec, 0xfb54172a],
345 [0x80d1f58f, 0x12e454c0, 0x2140ca5c, 0xe19350ba],
346 [0x26078d38, 0xf6a59d57, 0xcd14eaf8, 0x8eb08259],
347 [0x31494337, 0x6f8d3f52, 0x4bc9ff92, 0x0c601b1c]]));
696e4e20
KS
348 }
349}
350
351pub const I4X4_SCAN: [(u8, u8); 16] = [
352 (0,0), (1,0), (0,1), (1,1), (2,0), (3,0), (2,1), (3,1),
353 (0,2), (1,2), (0,3), (1,3), (2,2), (3,2), (2,3), (3,3)
354];