core/codecs: document module
[nihav.git] / nihav-core / src / codecs / mod.rs
CommitLineData
3ba71779 1//! Decoder interface definitions.
c3e7a747
KS
2use std::fmt;
3use std::ops::{Add, AddAssign, Sub, SubAssign};
4
4e8b4f31 5pub use crate::frame::*;
32007ad9 6use std::mem;
aca89041
KS
7use crate::io::byteio::ByteIOError;
8use crate::io::bitreader::BitReaderError;
9use crate::io::codebook::CodebookError;
77d06de2 10
3ba71779 11/// A list specifying general decoding errors.
77d06de2
KS
12#[derive(Debug,Clone,Copy,PartialEq)]
13#[allow(dead_code)]
14pub enum DecoderError {
3ba71779 15 /// No frame was provided.
6d3bb0b2 16 NoFrame,
3ba71779 17 /// Allocation failed.
e35062e7 18 AllocError,
3ba71779 19 /// Operation requires repeating.
503374e7 20 TryAgain,
3ba71779 21 /// Invalid input data was provided.
77d06de2 22 InvalidData,
3ba71779 23 /// Provided input turned out to be incomplete.
77d06de2 24 ShortData,
3ba71779 25 /// Decoder could not decode provided frame because it references some missing previous frame.
77d06de2 26 MissingReference,
3ba71779 27 /// Feature is not implemented.
77d06de2 28 NotImplemented,
3ba71779 29 /// Some bug in decoder. It should not happen yet it might.
77d06de2
KS
30 Bug,
31}
32
3ba71779 33/// A specialised `Result` type for decoding operations.
cf64af13 34pub type DecoderResult<T> = Result<T, DecoderError>;
77d06de2
KS
35
36impl From<ByteIOError> for DecoderError {
37 fn from(_: ByteIOError) -> Self { DecoderError::ShortData }
38}
39
40impl From<BitReaderError> for DecoderError {
41 fn from(e: BitReaderError) -> Self {
42 match e {
43 BitReaderError::BitstreamEnd => DecoderError::ShortData,
44 _ => DecoderError::InvalidData,
45 }
46 }
47}
48
49impl From<CodebookError> for DecoderError {
50 fn from(_: CodebookError) -> Self { DecoderError::InvalidData }
51}
52
e35062e7
KS
53impl From<AllocatorError> for DecoderError {
54 fn from(_: AllocatorError) -> Self { DecoderError::AllocError }
55}
56
3ba71779
KS
57/// Frame manager for hold-and-modify codecs.
58///
59/// This frame manager simplifies frame management for the case when codec decodes new frame by updating parts of the previous frame.
60///
61/// # Examples
62///
63/// ````norun
64/// let mut frame = if is_intra_frame {
65/// allocate_video_frame()
66/// } else {
67/// let ret = shuffler.clone_ref();
68/// if ret.is_none() {
69/// return Err(DecodingError::MissingReference);
70/// }
71/// ret.unwrap()
72/// };
73/// // output data into the frame
74/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
75/// ````
88c03b61 76#[allow(dead_code)]
5641dccf 77pub struct HAMShuffler {
3fc28ece 78 lastframe: Option<NAVideoBufferRef<u8>>,
88c03b61
KS
79}
80
81impl HAMShuffler {
3ba71779 82 /// Constructs a new instance of frame manager.
88c03b61 83 #[allow(dead_code)]
5641dccf 84 pub fn new() -> Self { HAMShuffler { lastframe: None } }
3ba71779 85 /// Clears the reference.
88c03b61 86 #[allow(dead_code)]
5641dccf 87 pub fn clear(&mut self) { self.lastframe = None; }
3ba71779 88 /// Sets a new frame reference.
88c03b61 89 #[allow(dead_code)]
3fc28ece 90 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
22cb00db 91 self.lastframe = Some(buf);
88c03b61 92 }
3ba71779 93 /// Provides a copy of the reference frame if present or `None` if it is not.
88c03b61 94 #[allow(dead_code)]
3fc28ece 95 pub fn clone_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
3bd541c8 96 if let Some(ref mut frm) = self.lastframe {
22cb00db 97 let newfrm = frm.copy_buffer();
3fc28ece
KS
98 *frm = newfrm.clone().into_ref();
99 Some(newfrm.into_ref())
5c253468
KS
100 } else {
101 None
102 }
88c03b61 103 }
3ba71779 104 /// Returns the original saved reference frame or `None` if it is not present.
88c03b61 105 #[allow(dead_code)]
3fc28ece 106 pub fn get_output_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
88c03b61
KS
107 match self.lastframe {
108 Some(ref frm) => Some(frm.clone()),
109 None => None,
110 }
111 }
112}
113
241e56f1
KS
114impl Default for HAMShuffler {
115 fn default() -> Self { Self { lastframe: None } }
116}
117
3ba71779
KS
118/// Frame manager for codecs with intra and inter frames.
119///
120/// This frame manager simplifies frame management for the case when codec decodes new frame using previous frame as source of some data.
121///
122/// # Examples
123///
124/// ````norun
125/// let mut frame = allocate_video_frame();
126/// if is_inter_frame {
127/// let ret = shuffler.get_ref();
128/// if ret.is_none() {
129/// return Err(DecodingError::MissingReference);
130/// }
131/// let ref_frame = ret.unwrap();
132/// // keep decoding using data from ref_frame
133/// }
134/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
135/// ````
3f29a2a8 136#[allow(dead_code)]
5641dccf 137pub struct IPShuffler {
3fc28ece 138 lastframe: Option<NAVideoBufferRef<u8>>,
3f29a2a8
KS
139}
140
141impl IPShuffler {
3ba71779 142 /// Constructs a new instance of frame manager.
3f29a2a8 143 #[allow(dead_code)]
5641dccf 144 pub fn new() -> Self { IPShuffler { lastframe: None } }
3ba71779 145 /// Clears the reference.
3f29a2a8 146 #[allow(dead_code)]
5641dccf 147 pub fn clear(&mut self) { self.lastframe = None; }
3ba71779 148 /// Sets a new frame reference.
3f29a2a8 149 #[allow(dead_code)]
3fc28ece 150 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
3f29a2a8
KS
151 self.lastframe = Some(buf);
152 }
3ba71779 153 /// Returns the original saved reference frame or `None` if it is not present.
3f29a2a8 154 #[allow(dead_code)]
3fc28ece 155 pub fn get_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
3f29a2a8
KS
156 if let Some(ref frm) = self.lastframe {
157 Some(frm.clone())
158 } else {
159 None
160 }
32007ad9
KS
161 }
162}
163
241e56f1
KS
164impl Default for IPShuffler {
165 fn default() -> Self { Self { lastframe: None } }
166}
167
3ba71779
KS
168/// Frame manager for codecs with I-, P- and B-frames.
169///
170/// This frame manager simplifies frame management for the case when codec uses I/P/B frame scheme.
171///
172/// # Examples
173///
174/// ````norun
175/// let mut frame = allocate_video_frame();
176/// for mb in all_macroblocks {
177/// // decode macroblock type
178/// match mb_type {
179/// MBType::Inter => {
180/// do_mc(&mut frame, shuffler.get_lastref().unwrap());
181/// },
182/// MBType::BForward => {
183/// do_mc(&mut frame, shuffler.get_b_fwdref().unwrap());
184/// },
185/// MBType::BBackward => {
186/// do_mc(&mut frame, shuffler.get_b_bwdref().unwrap());
187/// },
188/// // handle the rest of cases
189/// };
190/// if is_random_access_frame {
191/// shuffler.clear(); // remove all saved references
192/// }
193/// if is_intra_frame || is_p_frame {
194/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
195/// }
196/// ````
32007ad9 197#[allow(dead_code)]
5641dccf 198pub struct IPBShuffler {
3fc28ece
KS
199 lastframe: Option<NAVideoBufferRef<u8>>,
200 nextframe: Option<NAVideoBufferRef<u8>>,
32007ad9
KS
201}
202
203impl IPBShuffler {
3ba71779 204 /// Constructs a new instance of frame manager.
32007ad9 205 #[allow(dead_code)]
5641dccf 206 pub fn new() -> Self { IPBShuffler { lastframe: None, nextframe: None } }
3ba71779 207 /// Clears the reference.
32007ad9 208 #[allow(dead_code)]
5641dccf 209 pub fn clear(&mut self) { self.lastframe = None; self.nextframe = None; }
3ba71779 210 /// Sets a new frame reference.
32007ad9 211 #[allow(dead_code)]
3fc28ece 212 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
32007ad9
KS
213 mem::swap(&mut self.lastframe, &mut self.nextframe);
214 self.lastframe = Some(buf);
215 }
3ba71779 216 /// Returns the previous reference frame or `None` if it is not present.
32007ad9 217 #[allow(dead_code)]
3fc28ece 218 pub fn get_lastref(&mut self) -> Option<NAVideoBufferRef<u8>> {
32007ad9
KS
219 if let Some(ref frm) = self.lastframe {
220 Some(frm.clone())
221 } else {
222 None
223 }
224 }
3ba71779 225 /// Returns second last reference frame or `None` if it is not present.
32007ad9 226 #[allow(dead_code)]
3fc28ece 227 pub fn get_nextref(&mut self) -> Option<NAVideoBufferRef<u8>> {
32007ad9
KS
228 if let Some(ref frm) = self.nextframe {
229 Some(frm.clone())
230 } else {
231 None
232 }
3f29a2a8 233 }
3ba71779 234 /// Returns the temporally following reference for B-frame or `None` if it is not present.
3c8c667d 235 #[allow(dead_code)]
3fc28ece 236 pub fn get_b_fwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
3c8c667d
KS
237 if let Some(ref frm) = self.nextframe {
238 Some(frm.clone())
239 } else {
240 None
241 }
242 }
3ba71779 243 /// Returns the temporally preceeding reference for B-frame or `None` if it is not present.
3c8c667d 244 #[allow(dead_code)]
3fc28ece 245 pub fn get_b_bwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
3c8c667d
KS
246 if let Some(ref frm) = self.lastframe {
247 Some(frm.clone())
248 } else {
249 None
250 }
251 }
3f29a2a8
KS
252}
253
241e56f1
KS
254impl Default for IPBShuffler {
255 fn default() -> Self { Self { lastframe: None, nextframe: None } }
256}
257
3ba71779
KS
258/// Motion vector data type.
259///
260/// # Examples
261///
262/// ```
263/// use nihav_core::codecs::MV;
264///
265/// let mv0 = MV::new(1, 3);
266/// let mv1 = MV { x: 2, y: 3 }; // choose whatever style you prefer
267/// let mv2 = mv1 - mv0;
268/// let mv_pred = MV::pred(mv0, mv1, mv2); // get median prediction for the vectors (1, 0)
269/// ```
3a1d1cfa 270#[derive(Debug,Clone,Copy,Default,PartialEq)]
c3e7a747 271pub struct MV {
3ba71779 272 /// X coordinate of the vector.
c3e7a747 273 pub x: i16,
3ba71779 274 /// Y coordinate of the vector.
c3e7a747
KS
275 pub y: i16,
276}
277
e243ceb4
KS
278#[allow(clippy::many_single_char_names)]
279#[allow(clippy::collapsible_if)]
c3e7a747 280impl MV {
3ba71779 281 /// Creates a new motion vector instance.
e243ceb4 282 pub fn new(x: i16, y: i16) -> Self { MV{ x, y } }
3ba71779
KS
283 /// Predicts median from provided motion vectors.
284 ///
285 /// Each component of the vector is predicted as the median of corresponding input vector components.
c3e7a747
KS
286 pub fn pred(a: MV, b: MV, c: MV) -> Self {
287 let x;
288 if a.x < b.x {
289 if b.x < c.x {
290 x = b.x;
291 } else {
292 if a.x < c.x { x = c.x; } else { x = a.x; }
293 }
294 } else {
295 if b.x < c.x {
296 if a.x < c.x { x = a.x; } else { x = c.x; }
297 } else {
298 x = b.x;
299 }
300 }
301 let y;
302 if a.y < b.y {
303 if b.y < c.y {
304 y = b.y;
305 } else {
306 if a.y < c.y { y = c.y; } else { y = a.y; }
307 }
308 } else {
309 if b.y < c.y {
310 if a.y < c.y { y = a.y; } else { y = c.y; }
311 } else {
312 y = b.y;
313 }
314 }
e243ceb4 315 MV { x, y }
c3e7a747
KS
316 }
317}
318
3ba71779 319/// Zero motion vector.
c3e7a747
KS
320pub const ZERO_MV: MV = MV { x: 0, y: 0 };
321
322impl Add for MV {
323 type Output = MV;
324 fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } }
325}
326
327impl AddAssign for MV {
328 fn add_assign(&mut self, other: MV) { self.x += other.x; self.y += other.y; }
329}
330
331impl Sub for MV {
332 type Output = MV;
333 fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } }
334}
335
336impl SubAssign for MV {
337 fn sub_assign(&mut self, other: MV) { self.x -= other.x; self.y -= other.y; }
338}
339
340impl fmt::Display for MV {
341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342 write!(f, "{},{}", self.x, self.y)
343 }
344}
345
3ba71779 346/// Auxiliary structure for storing data used by decoder but also controlled by the caller.
01613464 347pub struct NADecoderSupport {
3ba71779 348 /// Frame buffer pool for 8-bit or packed video frames.
01613464 349 pub pool_u8: NAVideoBufferPool<u8>,
3ba71779 350 /// Frame buffer pool for 16-bit video frames.
01613464 351 pub pool_u16: NAVideoBufferPool<u16>,
3ba71779 352 /// Frame buffer pool for 32-bit video frames.
01613464
KS
353 pub pool_u32: NAVideoBufferPool<u32>,
354}
355
356impl NADecoderSupport {
3ba71779 357 /// Constructs a new instance of `NADecoderSupport`.
01613464
KS
358 pub fn new() -> Self {
359 Self {
360 pool_u8: NAVideoBufferPool::new(0),
361 pool_u16: NAVideoBufferPool::new(0),
362 pool_u32: NAVideoBufferPool::new(0),
363 }
364 }
365}
366
e243ceb4
KS
367impl Default for NADecoderSupport {
368 fn default() -> Self { Self::new() }
369}
370
3ba71779 371/// Decoder trait.
77d06de2 372pub trait NADecoder {
3ba71779
KS
373 /// Initialises the decoder.
374 ///
375 /// It takes [`NADecoderSupport`] allocated by the caller and `NACodecInfoRef` provided by demuxer.
376 ///
377 /// [`NADecoderSupport`]: ./struct.NADecoderSupport.html
01613464 378 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()>;
3ba71779 379 /// Decodes a single frame.
01613464 380 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef>;
3ba71779 381 /// Tells decoder to clear internal state (e.g. after error or seeking).
f9be4e75 382 fn flush(&mut self);
77d06de2
KS
383}
384
3ba71779 385/// Decoder information using during creating a decoder for requested codec.
70259941 386#[derive(Clone,Copy)]
2a4130ba 387pub struct DecoderInfo {
3ba71779 388 /// Short decoder name.
5641dccf 389 pub name: &'static str,
3ba71779 390 /// The function that creates a decoder instance.
08a1fab7 391 pub get_decoder: fn () -> Box<dyn NADecoder + Send>,
70259941
KS
392}
393
01b4e528 394#[cfg(any(feature="blockdsp"))]
5641dccf 395pub mod blockdsp;
88c58b1b 396
88c58b1b 397#[cfg(feature="h263")]
5641dccf 398pub mod h263;
cf64af13 399
3ba71779
KS
400/// Structure for registering known decoders.
401///
402/// It is supposed to be filled using `register_all_codecs()` from some decoders crate and then it can be used to create decoders for the requested codecs.
e243ceb4 403#[derive(Default)]
5641dccf
KS
404pub struct RegisteredDecoders {
405 decs: Vec<DecoderInfo>,
406}
407
408impl RegisteredDecoders {
3ba71779 409 /// Constructs a new instance of `RegisteredDecoders`.
5641dccf
KS
410 pub fn new() -> Self {
411 Self { decs: Vec::new() }
412 }
3ba71779 413 /// Adds another decoder to the registry.
5641dccf
KS
414 pub fn add_decoder(&mut self, dec: DecoderInfo) {
415 self.decs.push(dec);
416 }
3ba71779 417 /// Searches for the decoder for the provided name and returns a function for creating it on success.
08a1fab7 418 pub fn find_decoder(&self, name: &str) -> Option<fn () -> Box<dyn NADecoder + Send>> {
5641dccf
KS
419 for &dec in self.decs.iter() {
420 if dec.name == name {
421 return Some(dec.get_decoder);
422 }
70259941 423 }
5641dccf 424 None
70259941 425 }
3ba71779 426 /// Provides an iterator over currently registered decoders.
d10c9311
KS
427 pub fn iter(&self) -> std::slice::Iter<DecoderInfo> {
428 self.decs.iter()
429 }
70259941 430}
64e8b971 431
3ba71779 432/// The common 8x8 zigzag scan.
64e8b971
KS
433pub const ZIGZAG: [usize; 64] = [
434 0, 1, 8, 16, 9, 2, 3, 10,
435 17, 24, 32, 25, 18, 11, 4, 5,
436 12, 19, 26, 33, 40, 48, 41, 34,
437 27, 20, 13, 6, 7, 14, 21, 28,
438 35, 42, 49, 56, 57, 50, 43, 36,
439 29, 22, 15, 23, 30, 37, 44, 51,
440 58, 59, 52, 45, 38, 31, 39, 46,
441 53, 60, 61, 54, 47, 55, 62, 63
442];