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