1use std::sync::atomic::{AtomicBool, Ordering};
2use std::sync::{Arc, Condvar, Mutex, Once};
3
4use crate::cpu;
5use crate::data::Data;
6use crate::dsp::{DSPContext, PalDSPContext, RefmvsDSPContext};
7use crate::error::Rav2dError;
8use crate::internal::DecoderContext;
9use crate::log::Logger;
10use crate::mem::MemPool;
11use crate::obu;
12use crate::picture::{DefaultPicAllocator, PicAllocator, Picture, ThreadPicture};
13
14pub const MAX_THREADS: u32 = 256;
15pub const MAX_FRAME_DELAY: u32 = 256;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[repr(u8)]
19#[non_exhaustive]
21#[derive(Default)]
22pub enum InloopFilterType {
23 None = 0,
24 Deblock = 1,
25 Cdef = 2,
26 Restoration = 4,
27 Wiener = 8,
28 Gdf = 16,
29 #[default]
30 All = 31,
31}
32
33impl InloopFilterType {
34 pub(crate) fn to_flags(self) -> u32 {
39 self as u8 as u32
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44#[repr(u8)]
45#[non_exhaustive]
47#[derive(Default)]
48pub enum DecodeFrameType {
49 #[default]
50 All = 0,
51 Reference = 1,
52 Intra = 2,
53 Key = 3,
54}
55
56#[derive(Debug, Clone)]
58pub struct Settings {
59 pub n_threads: u32,
61 pub max_frame_delay: u32,
63 pub apply_grain: bool,
65 pub operating_point: u32,
67 pub all_layers: bool,
69 pub frame_size_limit: u32,
71 pub strict_std_compliance: bool,
73 pub output_invisible_frames: bool,
75 pub inloop_filters: InloopFilterType,
77 pub decode_frame_type: DecodeFrameType,
79 pub run_decode: bool,
83}
84
85impl Default for Settings {
86 fn default() -> Self {
87 Self {
88 n_threads: 0,
89 max_frame_delay: 0,
90 apply_grain: true,
91 operating_point: 0,
92 all_layers: true,
93 frame_size_limit: 0,
94 strict_std_compliance: false,
95 output_invisible_frames: false,
96 inloop_filters: InloopFilterType::All,
97 decode_frame_type: DecodeFrameType::All,
98 run_decode: false,
99 }
100 }
101}
102
103fn get_num_threads(s: &Settings) -> (u32, u32) {
104 #[rustfmt::skip]
105 const FC_LUT: [u8; 49] = [
106 1,
107 2, 2, 2,
108 3, 3, 3, 3, 3,
109 4, 4, 4, 4, 4, 4, 4,
110 5, 5, 5, 5, 5, 5, 5, 5, 5,
111 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
112 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
113 ];
114
115 let n_tc = if s.n_threads > 0 {
116 s.n_threads.clamp(1, MAX_THREADS)
117 } else {
118 (cpu::num_logical_processors() as u32).clamp(1, MAX_THREADS)
119 };
120
121 let n_fc = if s.max_frame_delay > 0 {
122 s.max_frame_delay.min(n_tc)
123 } else if n_tc < 50 {
124 FC_LUT[(n_tc - 1) as usize] as u32
125 } else {
126 8
127 };
128
129 (n_tc, n_fc)
130}
131
132pub fn get_frame_delay(s: &Settings) -> Result<u32, Rav2dError> {
133 if s.n_threads > MAX_THREADS || s.max_frame_delay > MAX_FRAME_DELAY {
134 return Err(Rav2dError::InvalidParam);
135 }
136 let (_, n_fc) = get_num_threads(s);
137 Ok(n_fc)
138}
139
140static INIT_ONCE: Once = Once::new();
141
142fn init_internal() {
143 INIT_ONCE.call_once(|| {
144 cpu::init_cpu();
145 });
146}
147
148struct OutputQueue {
149 pic: ThreadPicture,
150 res: i32,
151}
152
153pub struct Decoder {
158 logger: Logger,
159 allocator: Arc<dyn PicAllocator>,
160 inloop_filters: InloopFilterType,
161 decode_frame_type: DecodeFrameType,
162
163 n_tc: u32,
164 n_fc: u32,
165
166 ctx: DecoderContext,
167
168 input: Data,
169 drain: bool,
170 flush: AtomicBool,
171
172 dpb: Vec<OutputQueue>,
173 dpb_in: usize,
174 dpb_out: usize,
175 dpb_sz: usize,
176 dpb_poc: u8,
180
181 seq_hdr_pool: Arc<MemPool>,
182 frame_hdr_pool: Arc<MemPool>,
183 segmap_pool: Arc<MemPool>,
184 segmap_uv_pool: Arc<MemPool>,
185 refmvs_pool: Arc<MemPool>,
186 ccsomap_pool: Arc<MemPool>,
187 pic_ctx_pool: Arc<MemPool>,
188 cdf_pool: Arc<MemPool>,
189 fgm_pool: Arc<MemPool>,
190 ci_pool: Arc<MemPool>,
191 picture_pool: Arc<MemPool>,
192
193 task_thread: Option<TaskThread>,
194}
195
196struct TaskThread {
197 lock: Mutex<()>,
198 cond: Condvar,
199 cur: u32,
200 n_passes: u32,
201}
202
203impl Decoder {
204 pub fn open(s: &Settings) -> Result<Self, Rav2dError> {
206 init_internal();
207
208 if s.n_threads > MAX_THREADS || s.max_frame_delay > MAX_FRAME_DELAY {
209 return Err(Rav2dError::InvalidParam);
210 }
211 if s.operating_point > 31 {
212 return Err(Rav2dError::InvalidParam);
213 }
214
215 let (n_tc, n_fc) = get_num_threads(s);
216
217 let allocator: Arc<dyn PicAllocator> = Arc::new(DefaultPicAllocator::new());
218 let logger = Logger::with_default();
219
220 let dpb_sz = n_fc as usize + 16;
221 let mut dpb = Vec::with_capacity(dpb_sz);
222 for _ in 0..dpb_sz {
223 dpb.push(OutputQueue {
224 pic: ThreadPicture::new(),
225 res: 0,
226 });
227 }
228
229 let task_thread = if n_tc > 1 {
230 Some(TaskThread {
231 lock: Mutex::new(()),
232 cond: Condvar::new(),
233 cur: n_fc,
234 n_passes: 1 + (n_tc > 1) as u32 + (n_fc > 1) as u32,
235 })
236 } else {
237 None
238 };
239
240 let ctx = DecoderContext {
241 seq_hdr: None,
242 frame_hdr: None,
243 tile: Vec::new(),
244 n_tile_data: 0,
245 n_tiles: 0,
246 refs: Default::default(),
247 cdf: Vec::new(),
248 dsp: Arc::new(std::array::from_fn(|_| DSPContext::default())),
249 pal_dsp: PalDSPContext::default(),
250 refmvs_dsp: RefmvsDSPContext::default(),
251 content_light: None,
252 mastering_display: None,
253 ci: None,
254 fgm: Default::default(),
255 apply_grain: s.apply_grain,
256 operating_point: s.operating_point as i32,
257 operating_point_idc: 0,
258 all_layers: s.all_layers,
259 max_spatial_id: 0,
260 frame_size_limit: s.frame_size_limit,
261 strict_std_compliance: s.strict_std_compliance,
262 output_invisible_frames: s.output_invisible_frames,
263 n_passes: 1,
264 inloop_filters: s.inloop_filters.to_flags(),
265 run_decode: s.run_decode,
266 frame_out: Vec::new(),
267 n_tc,
268 };
269
270 Ok(Self {
271 logger,
272 allocator,
273 inloop_filters: s.inloop_filters,
274 decode_frame_type: s.decode_frame_type,
275 n_tc,
276 n_fc,
277 ctx,
278 input: Data::new(),
279 drain: false,
280 flush: AtomicBool::new(false),
281 dpb,
282 dpb_in: 0,
283 dpb_out: 0,
284 dpb_sz,
285 dpb_poc: 0,
286 seq_hdr_pool: Arc::new(MemPool::new()),
287 frame_hdr_pool: Arc::new(MemPool::new()),
288 segmap_pool: Arc::new(MemPool::new()),
289 segmap_uv_pool: Arc::new(MemPool::new()),
290 refmvs_pool: Arc::new(MemPool::new()),
291 ccsomap_pool: Arc::new(MemPool::new()),
292 pic_ctx_pool: Arc::new(MemPool::new()),
293 cdf_pool: Arc::new(MemPool::new()),
294 fgm_pool: Arc::new(MemPool::new()),
295 ci_pool: Arc::new(MemPool::new()),
296 picture_pool: Arc::new(MemPool::new()),
297 task_thread,
298 })
299 }
300
301 pub fn send_data(&mut self, data: Option<Data>) -> Result<(), Rav2dError> {
306 match data {
307 None => {
308 self.drain = true;
309 Ok(())
310 }
311 Some(d) => {
312 if self.drain {
313 return Err(Rav2dError::Eof);
314 }
315 if d.is_empty() || d.len() > usize::MAX / 2 {
316 return Err(Rav2dError::InvalidParam);
317 }
318 if self.input.has_data() {
319 return Err(Rav2dError::Again);
320 }
321 self.input = d;
322 Ok(())
323 }
324 }
325 }
326
327 pub fn get_picture(&mut self) -> Result<Picture, Rav2dError> {
332 self.gen_picture()?;
333
334 if self.drain {
335 self.queue_flush();
336 }
337
338 self.output_image()
339 }
340
341 fn output_picture_ready(&self) -> bool {
342 if self.dpb_out == self.dpb_in {
343 return false;
344 }
345 true
346 }
347
348 fn gen_picture(&mut self) -> Result<(), Rav2dError> {
349 if self.output_picture_ready() {
350 return Ok(());
351 }
352
353 while !self.input.is_empty() {
354 let data = match self.input.data() {
355 Some(d) => d,
356 None => break,
357 };
358 match obu::parse_obus(&mut self.ctx, data) {
359 Ok(consumed) => {
360 assert!(consumed <= self.input.len());
361 self.input.consume(consumed);
362 if self.input.is_empty() {
363 self.input.unref();
364 }
365 let frames: Vec<_> = self.ctx.frame_out.drain(..).collect();
368 for pic in frames {
369 if let Some(fh) = pic.frame_hdr.as_ref() {
373 self.dpb_poc = fh.frame_offset;
374 }
375 self.dpb[self.dpb_in].pic.p = pic;
376 self.dpb_in += 1;
377 if self.dpb_in == self.dpb_sz {
378 self.dpb_in = 0;
379 }
380 }
381 }
382 Err(_e) => {
383 self.input.unref();
384 return Err(Rav2dError::InvalidData);
385 }
386 }
387
388 if self.output_picture_ready() {
389 break;
390 }
391 }
392
393 Ok(())
394 }
395
396 fn output_image(&mut self) -> Result<Picture, Rav2dError> {
397 if self.dpb_in == self.dpb_out {
398 if !self.drain {
399 return Err(Rav2dError::Again);
400 }
401 self.drain = false;
402 return Err(Rav2dError::Eof);
403 }
404
405 let q = &mut self.dpb[self.dpb_out];
406 let mut pic = Picture::new();
407 std::mem::swap(&mut pic, &mut q.pic.p);
408 q.pic.unref();
409
410 self.dpb_out += 1;
411 if self.dpb_out == self.dpb_sz {
412 self.dpb_out = 0;
413 }
414
415 if self.ctx.apply_grain && crate::decode::picture_has_grain(&pic) {
421 let grained = crate::decode::apply_grain_to_picture_mt(&pic, self.n_tc);
422 pic.unref();
423 return Ok(grained);
424 }
425
426 Ok(pic)
427 }
428
429 fn queue_flush(&mut self) {
436 let nb = match self.ctx.seq_hdr.as_ref() {
437 Some(s) => s.order_hint_n_bits as i32,
438 None => return,
439 };
440 let mut mask: u32 = 0;
441 loop {
442 let mut cand: Option<(usize, u8)> = None; for n in 0..8 {
444 if mask & (1 << n) != 0 {
445 continue;
446 }
447 let r = &self.ctx.refs[n];
448 let pic = match r.p.pic.as_ref() {
449 Some(p) if p.has_data() => p,
450 _ => continue,
451 };
452 let hdr = match r.p.frame_hdr.as_ref() {
453 Some(h) => h,
454 None => continue,
455 };
456 if hdr.show_implicit == 0 {
457 continue;
458 }
459 let ipoc = pic
460 .frame_hdr
461 .as_ref()
462 .map(|h| h.frame_offset)
463 .unwrap_or(hdr.frame_offset);
464 if crate::env::get_poc_diff(nb, ipoc as i32, self.dpb_poc as i32) > 0
465 && (cand.is_none()
466 || crate::env::get_poc_diff(nb, ipoc as i32, cand.unwrap().1 as i32) < 0)
467 {
468 cand = Some((n, ipoc));
469 }
470 }
471 let (slot, ipoc) = match cand {
472 Some(c) => c,
473 None => break,
474 };
475 let pic = self.ctx.refs[slot].p.pic.as_ref().unwrap().clone();
477 self.dpb[self.dpb_in].pic.p = crate::decode::clone_picture_mt(&pic, self.n_tc);
478 self.dpb_in += 1;
479 if self.dpb_in == self.dpb_sz {
480 self.dpb_in = 0;
481 }
482 self.dpb_poc = ipoc;
483 mask |= 1 << slot;
484 }
485 }
486
487 pub fn flush(&mut self) {
489 self.input.unref();
490
491 for q in &mut self.dpb {
492 if q.pic.p.has_data() {
493 q.pic.unref();
494 }
495 }
496 self.dpb_in = 0;
497 self.dpb_out = 0;
498 self.drain = false;
499
500 for r in &mut self.ctx.refs {
501 r.segmap = None;
502 r.refmvs = None;
503 r.ccsomap = None;
504 r.p.frame_hdr = None;
505 r.refpoc = [0; 7];
506 }
507
508 self.ctx.frame_hdr = None;
509 self.ctx.seq_hdr = None;
510 self.ctx.tile.clear();
511 self.ctx.n_tile_data = 0;
512 self.ctx.n_tiles = 0;
513
514 self.flush.store(false, Ordering::Release);
515 }
516
517 pub fn n_threads(&self) -> u32 {
518 self.n_tc
519 }
520
521 pub fn n_frame_contexts(&self) -> u32 {
522 self.n_fc
523 }
524}
525
526impl Drop for Decoder {
527 fn drop(&mut self) {
528 self.flush();
529
530 self.seq_hdr_pool.end();
531 self.frame_hdr_pool.end();
532 self.segmap_pool.end();
533 self.segmap_uv_pool.end();
534 self.refmvs_pool.end();
535 self.ccsomap_pool.end();
536 self.pic_ctx_pool.end();
537 self.cdf_pool.end();
538 self.fgm_pool.end();
539 self.ci_pool.end();
540 self.picture_pool.end();
541 }
542}
543
544pub fn version() -> &'static str {
545 "0.1.0"
546}
547
548pub fn version_api() -> u32 {
549 1 << 8
550}
551
552#[cfg(test)]
553mod tests {
554 use super::*;
555
556 #[test]
557 fn test_default_settings() {
558 let s = Settings::default();
559 assert_eq!(s.n_threads, 0);
560 assert_eq!(s.max_frame_delay, 0);
561 assert!(s.apply_grain);
562 assert_eq!(s.operating_point, 0);
563 assert!(s.all_layers);
564 }
565
566 #[test]
567 fn test_get_num_threads() {
568 let mut s = Settings::default();
569 s.n_threads = 4;
570 let (n_tc, n_fc) = get_num_threads(&s);
571 assert_eq!(n_tc, 4);
572 assert_eq!(n_fc, 2);
573 }
574
575 #[test]
576 fn test_get_num_threads_single() {
577 let mut s = Settings::default();
578 s.n_threads = 1;
579 let (n_tc, n_fc) = get_num_threads(&s);
580 assert_eq!(n_tc, 1);
581 assert_eq!(n_fc, 1);
582 }
583
584 #[test]
585 fn test_get_num_threads_many() {
586 let mut s = Settings::default();
587 s.n_threads = 49;
588 let (n_tc, n_fc) = get_num_threads(&s);
589 assert_eq!(n_tc, 49);
590 assert_eq!(n_fc, 7);
591 }
592
593 #[test]
594 fn test_get_num_threads_over_50() {
595 let mut s = Settings::default();
596 s.n_threads = 100;
597 let (n_tc, n_fc) = get_num_threads(&s);
598 assert_eq!(n_tc, 100);
599 assert_eq!(n_fc, 8);
600 }
601
602 #[test]
603 fn test_get_frame_delay() {
604 let mut s = Settings::default();
605 s.n_threads = 8;
606 assert_eq!(get_frame_delay(&s).unwrap(), 3);
607 }
608
609 #[test]
610 fn test_get_frame_delay_invalid() {
611 let mut s = Settings::default();
612 s.n_threads = MAX_THREADS + 1;
613 assert_eq!(get_frame_delay(&s), Err(Rav2dError::InvalidParam));
614 }
615
616 #[test]
617 fn test_decoder_open() {
618 let s = Settings::default();
619 let decoder = Decoder::open(&s);
620 assert!(decoder.is_ok());
621 let d = decoder.unwrap();
622 assert!(d.n_threads() >= 1);
623 }
624
625 #[test]
626 fn test_decoder_open_single_thread() {
627 let mut s = Settings::default();
628 s.n_threads = 1;
629 let d = Decoder::open(&s).unwrap();
630 assert_eq!(d.n_threads(), 1);
631 assert_eq!(d.n_frame_contexts(), 1);
632 }
633
634 #[test]
635 fn test_decoder_open_invalid() {
636 let mut s = Settings::default();
637 s.operating_point = 32;
638 assert!(Decoder::open(&s).is_err());
639 }
640
641 #[test]
642 fn test_send_data_drain() {
643 let s = Settings::default();
644 let mut d = Decoder::open(&s).unwrap();
645 assert!(d.send_data(None).is_ok());
646 assert!(d.drain);
647 }
648
649 #[test]
650 fn test_send_data_after_drain() {
651 let s = Settings::default();
652 let mut d = Decoder::open(&s).unwrap();
653 d.send_data(None).unwrap();
654 let data = Data::wrap(vec![1, 2, 3]);
655 assert_eq!(d.send_data(Some(data)), Err(Rav2dError::Eof));
656 }
657
658 #[test]
659 fn test_send_data_empty() {
660 let s = Settings::default();
661 let mut d = Decoder::open(&s).unwrap();
662 let data = Data::new();
663 assert_eq!(d.send_data(Some(data)), Err(Rav2dError::InvalidParam));
664 }
665
666 #[test]
667 fn test_send_data_double() {
668 let s = Settings::default();
669 let mut d = Decoder::open(&s).unwrap();
670 d.send_data(Some(Data::wrap(vec![1, 2, 3]))).unwrap();
671 assert_eq!(
672 d.send_data(Some(Data::wrap(vec![4, 5, 6]))),
673 Err(Rav2dError::Again)
674 );
675 }
676
677 #[test]
678 fn test_get_picture_no_data() {
679 let s = Settings::default();
680 let mut d = Decoder::open(&s).unwrap();
681 assert_eq!(d.get_picture().err(), Some(Rav2dError::Again));
682 }
683
684 #[test]
685 fn test_flush() {
686 let s = Settings::default();
687 let mut d = Decoder::open(&s).unwrap();
688 d.send_data(Some(Data::wrap(vec![1, 2, 3]))).unwrap();
689 d.flush();
690 assert!(d.input.is_empty());
691 assert!(!d.drain);
692 }
693
694 #[test]
695 fn test_version() {
696 assert!(!version().is_empty());
697 }
698
699 #[test]
700 fn test_version_api() {
701 assert!(version_api() > 0);
702 }
703
704 #[test]
705 fn test_decoder_drop() {
706 let s = Settings::default();
707 let d = Decoder::open(&s).unwrap();
708 drop(d);
709 }
710}