1use std::io::{Write, Cursor};
2
3use bitstream_io::{BitWriter, BitWrite};
4use byteorder::{WriteBytesExt, LittleEndian};
5
6use crate::common::{EncodedIFrame, PFV_MAGIC, PFV_VERSION, EncodedPFrame};
7use crate::frame::VideoFrame;
8use crate::dct::{Q_TABLE_INTER, Q_TABLE_INTRA};
9use crate::plane::VideoPlane;
10use crate::rle::{rle_encode, rle_create_huffman, update_table};
11
12pub struct Encoder<W: Write> {
13 width: usize,
14 height: usize,
15 framerate: u32,
16 prev_frame: VideoFrame,
17 px_err: f32,
18 qtable_inter_l: [i32;64],
19 qtable_inter_c: [i32;64],
20 qtable_intra_l: [i32;64],
21 qtable_intra_c: [i32;64],
22 writer: W,
23 finished: bool,
24 #[cfg(feature = "multithreading")]
25 threadpool: rayon::ThreadPool
26}
27
28impl<W: Write> Drop for Encoder<W> {
29 fn drop(&mut self) {
30 if !self.finished {
31 self.finish().unwrap();
32 }
33 }
34}
35
36impl<W: Write> Encoder<W> {
37 pub fn new(writer: W, width: usize, height: usize, framerate: u32, quality: i32, #[cfg(feature = "multithreading")] num_threads: usize) -> Result<Encoder<W>, std::io::Error> {
38 assert!(quality >= 0 && quality <= 10);
39
40 let qscale = quality as f32 * 0.25;
41 let px_err = quality as f32 * 1.5;
42
43 #[cfg(feature = "multithreading")]
44 let mut enc = {
45 Encoder { width: width, height: height, framerate: framerate,
46 prev_frame: VideoFrame::new_padded(width, height),
47 px_err: px_err,
48 qtable_inter_l: Q_TABLE_INTER.map(|x| (x as f32 * qscale * 0.5).max(1.0) as i32),
49 qtable_inter_c: Q_TABLE_INTER.map(|x| (x as f32 * qscale).max(1.0) as i32),
50 qtable_intra_l: Q_TABLE_INTRA.map(|x| (x as f32 * qscale * 0.5).max(1.0) as i32),
51 qtable_intra_c: Q_TABLE_INTRA.map(|x| (x as f32 * qscale).max(1.0) as i32),
52 writer: writer,
53 finished: false,
54 threadpool: rayon::ThreadPoolBuilder::new().num_threads(num_threads).build().unwrap() }
55 };
56
57 #[cfg(not(feature = "multithreading"))]
58 let mut enc = {
59 Encoder { width: width, height: height, framerate: framerate,
60 prev_frame: VideoFrame::new_padded(width, height),
61 px_err: px_err,
62 qtable_inter_l: Q_TABLE_INTER.map(|x| (x as f32 * qscale * 0.5).max(1.0) as i32),
63 qtable_inter_c: Q_TABLE_INTER.map(|x| (x as f32 * qscale).max(1.0) as i32),
64 qtable_intra_l: Q_TABLE_INTRA.map(|x| (x as f32 * qscale * 0.5).max(1.0) as i32),
65 qtable_intra_c: Q_TABLE_INTRA.map(|x| (x as f32 * qscale).max(1.0) as i32),
66 writer: writer,
67 finished: false, }
68 };
69
70 enc.write_header()?;
71
72 Ok(enc)
73 }
74
75 pub fn encode_iframe(self: &mut Encoder<W>, frame: &VideoFrame) -> Result<(), std::io::Error> {
76 assert!(frame.width == self.width && frame.height == self.height);
77 assert!(frame.plane_y.width == frame.width && frame.plane_y.height == frame.height);
78 assert!(frame.plane_u.width == frame.width / 2 && frame.plane_u.height == frame.height / 2);
79 assert!(frame.plane_v.width == frame.width / 2 && frame.plane_v.height == frame.height / 2);
80 assert!(!self.finished);
81
82 #[cfg(feature = "multithreading")]
83 {
84 let enc_y = frame.plane_y.encode_plane(&self.qtable_intra_l, 0, &self.threadpool);
85 let dec_y = VideoPlane::decode_plane(&enc_y, &self.qtable_intra_l, &self.threadpool);
86
87 let enc_u = frame.plane_u.encode_plane(&self.qtable_intra_c, 128, &self.threadpool);
88 let dec_u = VideoPlane::decode_plane(&enc_u, &self.qtable_intra_c, &self.threadpool);
89
90 let enc_v = frame.plane_v.encode_plane(&self.qtable_intra_c, 128, &self.threadpool);
91 let dec_v = VideoPlane::decode_plane(&enc_v, &self.qtable_intra_c, &self.threadpool);
92
93 let enc_frame = EncodedIFrame { y: enc_y, u: enc_u, v: enc_v };
94
95 self.prev_frame.plane_y.blit(&dec_y, 0, 0, 0, 0, dec_y.width, dec_y.height);
96 self.prev_frame.plane_u.blit(&dec_u, 0, 0, 0, 0, dec_u.width, dec_u.height);
97 self.prev_frame.plane_v.blit(&dec_v, 0, 0, 0, 0, dec_v.width, dec_v.height);
98
99 Encoder::<W>::write_iframe_packet(&enc_frame, &mut self.writer)?;
100 }
101
102 #[cfg(not(feature = "multithreading"))]
103 {
104 let enc_y = frame.plane_y.encode_plane(&self.qtable_intra_l, 0);
105 let dec_y = VideoPlane::decode_plane(&enc_y, &self.qtable_intra_l);
106
107 let enc_u = frame.plane_u.encode_plane(&self.qtable_intra_c, 128);
108 let dec_u = VideoPlane::decode_plane(&enc_u, &self.qtable_intra_c);
109
110 let enc_v = frame.plane_v.encode_plane(&self.qtable_intra_c, 128);
111 let dec_v = VideoPlane::decode_plane(&enc_v, &self.qtable_intra_c);
112
113 let enc_frame = EncodedIFrame { y: enc_y, u: enc_u, v: enc_v };
114
115 self.prev_frame.plane_y.blit(&dec_y, 0, 0, 0, 0, dec_y.width, dec_y.height);
116 self.prev_frame.plane_u.blit(&dec_u, 0, 0, 0, 0, dec_u.width, dec_u.height);
117 self.prev_frame.plane_v.blit(&dec_v, 0, 0, 0, 0, dec_v.width, dec_v.height);
118
119 Encoder::<W>::write_iframe_packet(&enc_frame, &mut self.writer)?;
120 }
121
122 Ok(())
123 }
124
125 pub fn encode_pframe(self: &mut Encoder<W>, frame: &VideoFrame) -> Result<(), std::io::Error> {
126 assert!(frame.width == self.width && frame.height == self.height);
127 assert!(frame.plane_y.width == frame.width && frame.plane_y.height == frame.height);
128 assert!(frame.plane_u.width == frame.width / 2 && frame.plane_u.height == frame.height / 2);
129 assert!(frame.plane_v.width == frame.width / 2 && frame.plane_v.height == frame.height / 2);
130 assert!(!self.finished);
131
132 #[cfg(feature = "multithreading")]
133 {
134 let enc_y = frame.plane_y.encode_plane_delta(&self.prev_frame.plane_y, &self.qtable_inter_l, self.px_err, 0, &self.threadpool);
135 let dec_y = VideoPlane::decode_plane_delta(&enc_y, &self.prev_frame.plane_y, &self.qtable_inter_l, &self.threadpool);
136
137 let enc_u = frame.plane_u.encode_plane_delta(&self.prev_frame.plane_u, &self.qtable_inter_c, self.px_err, 128, &self.threadpool);
138 let dec_u = VideoPlane::decode_plane_delta(&enc_u, &self.prev_frame.plane_u, &self.qtable_inter_c, &self.threadpool);
139
140 let enc_v = frame.plane_v.encode_plane_delta(&self.prev_frame.plane_v, &self.qtable_inter_c, self.px_err, 128, &self.threadpool);
141 let dec_v = VideoPlane::decode_plane_delta(&enc_v, &self.prev_frame.plane_v, &self.qtable_inter_c, &self.threadpool);
142
143 let enc_frame = EncodedPFrame { y: enc_y, u: enc_u, v: enc_v };
144
145 self.prev_frame.plane_y.blit(&dec_y, 0, 0, 0, 0, dec_y.width, dec_y.height);
146 self.prev_frame.plane_u.blit(&dec_u, 0, 0, 0, 0, dec_u.width, dec_u.height);
147 self.prev_frame.plane_v.blit(&dec_v, 0, 0, 0, 0, dec_v.width, dec_v.height);
148
149 Encoder::<W>::write_pframe_packet(&enc_frame, &mut self.writer)?;
150 }
151
152 #[cfg(not(feature = "multithreading"))]
153 {
154 let enc_y = frame.plane_y.encode_plane_delta(&self.prev_frame.plane_y, &self.qtable_inter_l, self.px_err, 0);
155 let dec_y = VideoPlane::decode_plane_delta(&enc_y, &self.prev_frame.plane_y, &self.qtable_inter_l);
156
157 let enc_u = frame.plane_u.encode_plane_delta(&self.prev_frame.plane_u, &self.qtable_inter_c, self.px_err, 128);
158 let dec_u = VideoPlane::decode_plane_delta(&enc_u, &self.prev_frame.plane_u, &self.qtable_inter_c);
159
160 let enc_v = frame.plane_v.encode_plane_delta(&self.prev_frame.plane_v, &self.qtable_inter_c, self.px_err, 128);
161 let dec_v = VideoPlane::decode_plane_delta(&enc_v, &self.prev_frame.plane_v, &self.qtable_inter_c);
162
163 let enc_frame = EncodedPFrame { y: enc_y, u: enc_u, v: enc_v };
164
165 self.prev_frame.plane_y.blit(&dec_y, 0, 0, 0, 0, dec_y.width, dec_y.height);
166 self.prev_frame.plane_u.blit(&dec_u, 0, 0, 0, 0, dec_u.width, dec_u.height);
167 self.prev_frame.plane_v.blit(&dec_v, 0, 0, 0, 0, dec_v.width, dec_v.height);
168
169 Encoder::<W>::write_pframe_packet(&enc_frame, &mut self.writer)?;
170 }
171
172 Ok(())
173 }
174
175 pub fn encode_dropframe(self: &mut Encoder<W>) -> Result<(), std::io::Error> {
176 assert!(!self.finished);
177
178 Encoder::<W>::write_drop_packet(&mut self.writer)?;
179 Ok(())
180 }
181
182 pub fn finish(self: &mut Encoder<W>) -> Result<(), std::io::Error> {
183 assert!(!self.finished);
184
185 self.finished = true;
186 Encoder::write_eof(&mut self.writer)?;
187 Ok(())
188 }
189
190 fn write_header(self: &mut Encoder<W>) -> Result<(), std::io::Error> {
191 self.writer.write_all(PFV_MAGIC)?;
193 self.writer.write_u32::<LittleEndian>(PFV_VERSION)?;
194
195 self.writer.write_u16::<LittleEndian>(self.width as u16)?;
196 self.writer.write_u16::<LittleEndian>(self.height as u16)?;
197 self.writer.write_u16::<LittleEndian>(self.framerate as u16)?;
198
199 self.writer.write_u16::<LittleEndian>(4)?;
201
202 for v in self.qtable_intra_l {
203 self.writer.write_u16::<LittleEndian>(v as u16)?;
204 }
205
206 for v in self.qtable_intra_c {
207 self.writer.write_u16::<LittleEndian>(v as u16)?;
208 }
209
210 for v in self.qtable_inter_l {
211 self.writer.write_u16::<LittleEndian>(v as u16)?;
212 }
213
214 for v in self.qtable_inter_c {
215 self.writer.write_u16::<LittleEndian>(v as u16)?;
216 }
217
218 Ok(())
219 }
220
221 fn write_eof(writer: &mut W) -> Result<(), std::io::Error> {
222 writer.write_u8(0)?; writer.write_u32::<LittleEndian>(0)?;
225
226 Ok(())
227 }
228
229 fn write_drop_packet(writer: &mut W) -> Result<(), std::io::Error> {
230 writer.write_u8(1)?; writer.write_u32::<LittleEndian>(0)?;
233
234 Ok(())
235 }
236
237 fn write_iframe_packet(f: &EncodedIFrame, writer: &mut W) -> Result<(), std::io::Error> {
238 let mut packet_data = Cursor::new(Vec::new());
240 let mut bitwriter = BitWriter::endian(&mut packet_data, bitstream_io::LittleEndian);
241
242 let mut block_coeff = Vec::new();
244 let mut symbol_table = [0;16];
245
246 for b in &f.y.blocks {
247 let mut coeff = Vec::new();
248 coeff.extend_from_slice(&b.subblocks[0].m);
249 coeff.extend_from_slice(&b.subblocks[1].m);
250 coeff.extend_from_slice(&b.subblocks[2].m);
251 coeff.extend_from_slice(&b.subblocks[3].m);
252 let mut rle_sequence = Vec::new();
253 rle_encode(&mut rle_sequence, &coeff);
254 update_table(&mut symbol_table, &rle_sequence);
255
256 block_coeff.push(rle_sequence);
257 }
258
259 for b in &f.u.blocks {
260 let mut coeff = Vec::new();
261 coeff.extend_from_slice(&b.subblocks[0].m);
262 coeff.extend_from_slice(&b.subblocks[1].m);
263 coeff.extend_from_slice(&b.subblocks[2].m);
264 coeff.extend_from_slice(&b.subblocks[3].m);
265 let mut rle_sequence = Vec::new();
266 rle_encode(&mut rle_sequence, &coeff);
267 update_table(&mut symbol_table, &rle_sequence);
268
269 block_coeff.push(rle_sequence);
270 }
271
272 for b in &f.v.blocks {
273 let mut coeff = Vec::new();
274 coeff.extend_from_slice(&b.subblocks[0].m);
275 coeff.extend_from_slice(&b.subblocks[1].m);
276 coeff.extend_from_slice(&b.subblocks[2].m);
277 coeff.extend_from_slice(&b.subblocks[3].m);
278 let mut rle_sequence = Vec::new();
279 rle_encode(&mut rle_sequence, &coeff);
280 update_table(&mut symbol_table, &rle_sequence);
281
282 block_coeff.push(rle_sequence);
283 }
284
285 let tree = rle_create_huffman(&symbol_table);
287 let tree_table = tree.get_table();
288
289 for i in 0..16 {
291 bitwriter.write(8, tree_table[i] as u8)?;
292 }
293
294 bitwriter.write(8, 0_u8)?;
297 bitwriter.write(8, 1_u8)?;
298 bitwriter.write(8, 1_u8)?;
299
300 for block in &block_coeff {
302 for sq in block {
303 let num_zeroes = tree.get_code(sq.num_zeroes);
304 let num_bits = tree.get_code(sq.coeff_size);
305
306 debug_assert!(num_zeroes.len > 0 && num_bits.len > 0);
307
308 bitwriter.write(num_zeroes.len, num_zeroes.val)?;
309 bitwriter.write(num_bits.len, num_bits.val)?;
310
311 if sq.coeff_size > 0 {
312 bitwriter.write_signed(sq.coeff_size as u32, sq.coeff)?;
313 }
314 }
315 }
316
317 bitwriter.byte_align()?;
319
320 let packet_data = packet_data.into_inner();
322
323 writer.write_u8(1)?; writer.write_u32::<LittleEndian>(packet_data.len() as u32)?;
327 writer.write_all(&packet_data)?;
328
329 Ok(())
330 }
331
332 fn write_pframe_packet(f: &EncodedPFrame, writer: &mut W) -> Result<(), std::io::Error> {
333 let mut packet_data = Cursor::new(Vec::new());
335 let mut bitwriter = BitWriter::endian(&mut packet_data, bitstream_io::LittleEndian);
336
337 let mut block_coeff = Vec::new();
339 let mut symbol_table = [0;16];
340
341 for b in &f.y.blocks {
342 match b.subblocks {
343 Some(subblocks) => {
344 let mut coeff = Vec::new();
345 coeff.extend_from_slice(&subblocks[0].m);
346 coeff.extend_from_slice(&subblocks[1].m);
347 coeff.extend_from_slice(&subblocks[2].m);
348 coeff.extend_from_slice(&subblocks[3].m);
349 let mut rle_sequence = Vec::new();
350 rle_encode(&mut rle_sequence, &coeff);
351 update_table(&mut symbol_table, &rle_sequence);
352
353 block_coeff.push(rle_sequence);
354 }
355 None => {
356 }
357 }
358 }
359
360 for b in &f.u.blocks {
361 match b.subblocks {
362 Some(subblocks) => {
363 let mut coeff = Vec::new();
364 coeff.extend_from_slice(&subblocks[0].m);
365 coeff.extend_from_slice(&subblocks[1].m);
366 coeff.extend_from_slice(&subblocks[2].m);
367 coeff.extend_from_slice(&subblocks[3].m);
368 let mut rle_sequence = Vec::new();
369 rle_encode(&mut rle_sequence, &coeff);
370 update_table(&mut symbol_table, &rle_sequence);
371
372 block_coeff.push(rle_sequence);
373 }
374 None => {
375 }
376 }
377 }
378
379 for b in &f.v.blocks {
380 match b.subblocks {
381 Some(subblocks) => {
382 let mut coeff = Vec::new();
383 coeff.extend_from_slice(&subblocks[0].m);
384 coeff.extend_from_slice(&subblocks[1].m);
385 coeff.extend_from_slice(&subblocks[2].m);
386 coeff.extend_from_slice(&subblocks[3].m);
387 let mut rle_sequence = Vec::new();
388 rle_encode(&mut rle_sequence, &coeff);
389 update_table(&mut symbol_table, &rle_sequence);
390
391 block_coeff.push(rle_sequence);
392 }
393 None => {
394 }
395 }
396 }
397
398 let tree = rle_create_huffman(&symbol_table);
400 let tree_table = tree.get_table();
401
402 for i in 0..16 {
404 bitwriter.write(8, tree_table[i] as u8)?;
405 }
406
407 bitwriter.write(8, 2_u8)?;
410 bitwriter.write(8, 3_u8)?;
411 bitwriter.write(8, 3_u8)?;
412
413 for b in &f.y.blocks {
415 let has_mvec = b.motion_x != 0 || b.motion_y != 0;
416
417 bitwriter.write_bit(has_mvec)?;
418 bitwriter.write_bit(b.subblocks.is_some())?;
419
420 if has_mvec {
421 bitwriter.write_signed(7, b.motion_x as i32)?;
422 bitwriter.write_signed(7, b.motion_y as i32)?;
423 }
424 }
425
426 for b in &f.u.blocks {
427 let has_mvec = b.motion_x != 0 || b.motion_y != 0;
428
429 bitwriter.write_bit(has_mvec)?;
430 bitwriter.write_bit(b.subblocks.is_some())?;
431
432 if has_mvec {
433 bitwriter.write_signed(7, b.motion_x as i32)?;
434 bitwriter.write_signed(7, b.motion_y as i32)?;
435 }
436 }
437
438 for b in &f.v.blocks {
439 let has_mvec = b.motion_x != 0 || b.motion_y != 0;
440
441 bitwriter.write_bit(has_mvec)?;
442 bitwriter.write_bit(b.subblocks.is_some())?;
443
444 if has_mvec {
445 bitwriter.write_signed(7, b.motion_x as i32)?;
446 bitwriter.write_signed(7, b.motion_y as i32)?;
447
448 assert!(b.motion_x >= -16 && b.motion_x <= 16);
449 assert!(b.motion_y >= -16 && b.motion_y <= 16);
450 }
451 }
452
453 for block in &block_coeff {
455 for sq in block {
456 let num_zeroes = tree.get_code(sq.num_zeroes);
457 let num_bits = tree.get_code(sq.coeff_size);
458
459 bitwriter.write(num_zeroes.len, num_zeroes.val)?;
460 bitwriter.write(num_bits.len, num_bits.val)?;
461
462 if sq.coeff_size > 0 {
463 bitwriter.write_signed(sq.coeff_size as u32, sq.coeff)?;
464 }
465 }
466 }
467
468 bitwriter.byte_align()?;
470
471 let packet_data = packet_data.into_inner();
473
474 writer.write_u8(2)?; writer.write_u32::<LittleEndian>(packet_data.len() as u32)?;
478 writer.write_all(&packet_data)?;
479
480 Ok(())
481 }
482}