1 use super::*;
2 use bytes::Bytes;
3 use std::io::BufReader;
4 
5 /// build_ivf_container takes frames and prepends valid IVF file header
build_ivf_container(frames: &[Bytes]) -> Bytes6 fn build_ivf_container(frames: &[Bytes]) -> Bytes {
7     // Valid IVF file header taken from: https://github.com/webmproject/...
8     // vp8-test-vectors/blob/master/vp80-00-comprehensive-001.ivf
9     // Video Image Width      	- 176
10     // Video Image Height    	- 144
11     // Frame Rate Rate        	- 30000
12     // Frame Rate Scale       	- 1000
13     // Video Length in Frames	- 29
14     // BitRate: 		 64.01 kb/s
15     let header = Bytes::from_static(&[
16         0x44, 0x4b, 0x49, 0x46, 0x00, 0x00, 0x20, 0x00, 0x56, 0x50, 0x38, 0x30, 0xb0, 0x00, 0x90,
17         0x00, 0x30, 0x75, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
18         0x00, 0x00,
19     ]);
20 
21     let mut ivf = BytesMut::new();
22     ivf.extend(header);
23 
24     for frame in frames {
25         ivf.extend(frame);
26     }
27 
28     ivf.freeze()
29 }
30 
31 #[test]
test_ivf_reader_parse_valid_file_header() -> Result<()>32 fn test_ivf_reader_parse_valid_file_header() -> Result<()> {
33     let ivf = build_ivf_container(&[]);
34 
35     let r = BufReader::new(&ivf[..]);
36     let (_, header) = IVFReader::new(r)?;
37 
38     assert_eq!(&header.signature, b"DKIF", "signature is 'DKIF'");
39     assert_eq!(header.version, 0, "version should be 0");
40     assert_eq!(&header.four_cc, b"VP80", "FourCC should be 'VP80'");
41     assert_eq!(header.width, 176, "width should be 176");
42     assert_eq!(header.height, 144, "height should be 144");
43     assert_eq!(
44         header.timebase_denominator, 30000,
45         "timebase denominator should be 30000"
46     );
47     assert_eq!(
48         header.timebase_numerator, 1000,
49         "timebase numerator should be 1000"
50     );
51     assert_eq!(header.num_frames, 29, "number of frames should be 29");
52     assert_eq!(header.unused, 0, "bytes should be unused");
53 
54     Ok(())
55 }
56 
57 #[test]
test_ivf_reader_parse_valid_frames() -> Result<()>58 fn test_ivf_reader_parse_valid_frames() -> Result<()> {
59     // Frame Length - 4
60     // Timestamp - None
61     // Frame Payload - 0xDEADBEEF
62     let valid_frame1 = Bytes::from_static(&[
63         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE,
64         0xEF,
65     ]);
66 
67     // Frame Length - 12
68     // Timestamp - None
69     // Frame Payload - 0xDEADBEEFDEADBEEF
70     let valid_frame2 = Bytes::from_static(&[
71         0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE,
72         0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
73     ]);
74 
75     let ivf = build_ivf_container(&[valid_frame1, valid_frame2]);
76     let r = BufReader::new(&ivf[..]);
77     let (mut reader, _) = IVFReader::new(r)?;
78 
79     // Parse Frame #1
80     let (payload, header) = reader.parse_next_frame()?;
81 
82     assert_eq!(header.frame_size, 4, "Frame header frameSize should be 4");
83     assert_eq!(payload.len(), 4, "Payload should be length 4");
84     assert_eq!(
85         payload,
86         Bytes::from_static(&[0xDE, 0xAD, 0xBE, 0xEF,]),
87         "Payload value should be 0xDEADBEEF"
88     );
89     assert_eq!(
90         reader.bytes_read,
91         IVF_FILE_HEADER_SIZE + IVF_FRAME_HEADER_SIZE + header.frame_size as usize
92     );
93     let previous_bytes_read = reader.bytes_read;
94 
95     // Parse Frame #2
96     let (payload, header) = reader.parse_next_frame()?;
97 
98     assert_eq!(header.frame_size, 12, "Frame header frameSize should be 4");
99     assert_eq!(payload.len(), 12, "Payload should be length 12");
100     assert_eq!(
101         payload,
102         Bytes::from_static(&[
103             0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
104         ]),
105         "Payload value should be 0xDEADBEEFDEADBEEF"
106     );
107     assert_eq!(
108         reader.bytes_read,
109         previous_bytes_read + IVF_FRAME_HEADER_SIZE + header.frame_size as usize,
110     );
111 
112     Ok(())
113 }
114 
115 #[test]
test_ivf_reader_parse_incomplete_frame_header() -> Result<()>116 fn test_ivf_reader_parse_incomplete_frame_header() -> Result<()> {
117     // frame with 11-byte header (missing 1 byte)
118     let incomplete_frame = Bytes::from_static(&[
119         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120     ]);
121 
122     let ivf = build_ivf_container(&[incomplete_frame]);
123     let r = BufReader::new(&ivf[..]);
124     let (mut reader, _) = IVFReader::new(r)?;
125 
126     // Parse Frame #1
127     let result = reader.parse_next_frame();
128     assert!(result.is_err(), "Expected Error but got Ok");
129 
130     Ok(())
131 }
132 
133 #[test]
test_ivf_reader_parse_incomplete_frame_payload() -> Result<()>134 fn test_ivf_reader_parse_incomplete_frame_payload() -> Result<()> {
135     // frame with header defining frameSize of 4
136     // but only 2 bytes available (missing 2 bytes)
137     let incomplete_frame = Bytes::from_static(&[
138         0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD,
139     ]);
140 
141     let ivf = build_ivf_container(&[incomplete_frame]);
142     let r = BufReader::new(&ivf[..]);
143     let (mut reader, _) = IVFReader::new(r)?;
144 
145     // Parse Frame #1
146     let result = reader.parse_next_frame();
147     assert!(result.is_err(), "Expected Error but got Ok");
148 
149     Ok(())
150 }
151 
152 #[test]
test_ivf_reader_eof_when_no_frames_left() -> Result<()>153 fn test_ivf_reader_eof_when_no_frames_left() -> Result<()> {
154     let ivf = build_ivf_container(&[]);
155     let r = BufReader::new(&ivf[..]);
156     let (mut reader, _) = IVFReader::new(r)?;
157 
158     let result = reader.parse_next_frame();
159     assert!(result.is_err(), "Expected Error but got Ok");
160 
161     Ok(())
162 }
163