1 //! Decoder interface definitions.
3 use std::ops::{Add, AddAssign, Sub, SubAssign};
5 pub use crate::frame::*;
7 use crate::io::byteio::ByteIOError;
8 use crate::io::bitreader::BitReaderError;
9 use crate::io::codebook::CodebookError;
11 /// A list specifying general decoding errors.
12 #[derive(Debug,Clone,Copy,PartialEq)]
14 pub enum DecoderError {
15 /// No frame was provided.
17 /// Allocation failed.
19 /// Operation requires repeating.
21 /// Invalid input data was provided.
23 /// Provided input turned out to be incomplete.
25 /// Decoder could not decode provided frame because it references some missing previous frame.
27 /// Feature is not implemented.
29 /// Some bug in decoder. It should not happen yet it might.
33 /// A specialised `Result` type for decoding operations.
34 pub type DecoderResult<T> = Result<T, DecoderError>;
36 impl From<ByteIOError> for DecoderError {
37 fn from(_: ByteIOError) -> Self { DecoderError::ShortData }
40 impl From<BitReaderError> for DecoderError {
41 fn from(e: BitReaderError) -> Self {
43 BitReaderError::BitstreamEnd => DecoderError::ShortData,
44 _ => DecoderError::InvalidData,
49 impl From<CodebookError> for DecoderError {
50 fn from(_: CodebookError) -> Self { DecoderError::InvalidData }
53 impl From<AllocatorError> for DecoderError {
54 fn from(_: AllocatorError) -> Self { DecoderError::AllocError }
57 /// Frame manager for hold-and-modify codecs.
59 /// This frame manager simplifies frame management for the case when codec decodes new frame by updating parts of the previous frame.
64 /// let mut frame = if is_intra_frame {
65 /// allocate_video_frame()
67 /// let ret = shuffler.clone_ref();
68 /// if ret.is_none() {
69 /// return Err(DecodingError::MissingReference);
73 /// // output data into the frame
74 /// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
77 pub struct HAMShuffler {
78 lastframe: Option<NAVideoBufferRef<u8>>,
82 /// Constructs a new instance of frame manager.
84 pub fn new() -> Self { HAMShuffler { lastframe: None } }
85 /// Clears the reference.
87 pub fn clear(&mut self) { self.lastframe = None; }
88 /// Sets a new frame reference.
90 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
91 self.lastframe = Some(buf);
93 /// Provides a copy of the reference frame if present or `None` if it is not.
95 pub fn clone_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
96 if let Some(ref mut frm) = self.lastframe {
97 let newfrm = frm.copy_buffer();
98 *frm = newfrm.clone().into_ref();
99 Some(newfrm.into_ref())
104 /// Returns the original saved reference frame or `None` if it is not present.
106 pub fn get_output_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
107 match self.lastframe {
108 Some(ref frm) => Some(frm.clone()),
114 impl Default for HAMShuffler {
115 fn default() -> Self { Self { lastframe: None } }
118 /// Frame manager for codecs with intra and inter frames.
120 /// This frame manager simplifies frame management for the case when codec decodes new frame using previous frame as source of some data.
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);
131 /// let ref_frame = ret.unwrap();
132 /// // keep decoding using data from ref_frame
134 /// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
137 pub struct IPShuffler {
138 lastframe: Option<NAVideoBufferRef<u8>>,
142 /// Constructs a new instance of frame manager.
144 pub fn new() -> Self { IPShuffler { lastframe: None } }
145 /// Clears the reference.
147 pub fn clear(&mut self) { self.lastframe = None; }
148 /// Sets a new frame reference.
150 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
151 self.lastframe = Some(buf);
153 /// Returns the original saved reference frame or `None` if it is not present.
155 pub fn get_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
156 if let Some(ref frm) = self.lastframe {
164 impl Default for IPShuffler {
165 fn default() -> Self { Self { lastframe: None } }
168 /// Frame manager for codecs with I-, P- and B-frames.
170 /// This frame manager simplifies frame management for the case when codec uses I/P/B frame scheme.
175 /// let mut frame = allocate_video_frame();
176 /// for mb in all_macroblocks {
177 /// // decode macroblock type
179 /// MBType::Inter => {
180 /// do_mc(&mut frame, shuffler.get_lastref().unwrap());
182 /// MBType::BForward => {
183 /// do_mc(&mut frame, shuffler.get_b_fwdref().unwrap());
185 /// MBType::BBackward => {
186 /// do_mc(&mut frame, shuffler.get_b_bwdref().unwrap());
188 /// // handle the rest of cases
190 /// if is_random_access_frame {
191 /// shuffler.clear(); // remove all saved references
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
198 pub struct IPBShuffler {
199 lastframe: Option<NAVideoBufferRef<u8>>,
200 nextframe: Option<NAVideoBufferRef<u8>>,
204 /// Constructs a new instance of frame manager.
206 pub fn new() -> Self { IPBShuffler { lastframe: None, nextframe: None } }
207 /// Clears the reference.
209 pub fn clear(&mut self) { self.lastframe = None; self.nextframe = None; }
210 /// Sets a new frame reference.
212 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
213 mem::swap(&mut self.lastframe, &mut self.nextframe);
214 self.lastframe = Some(buf);
216 /// Returns the previous reference frame or `None` if it is not present.
218 pub fn get_lastref(&mut self) -> Option<NAVideoBufferRef<u8>> {
219 if let Some(ref frm) = self.lastframe {
225 /// Returns second last reference frame or `None` if it is not present.
227 pub fn get_nextref(&mut self) -> Option<NAVideoBufferRef<u8>> {
228 if let Some(ref frm) = self.nextframe {
234 /// Returns the temporally following reference for B-frame or `None` if it is not present.
236 pub fn get_b_fwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
237 if let Some(ref frm) = self.nextframe {
243 /// Returns the temporally preceeding reference for B-frame or `None` if it is not present.
245 pub fn get_b_bwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
246 if let Some(ref frm) = self.lastframe {
254 impl Default for IPBShuffler {
255 fn default() -> Self { Self { lastframe: None, nextframe: None } }
258 /// Motion vector data type.
263 /// use nihav_core::codecs::MV;
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)
270 #[derive(Debug,Clone,Copy,Default,PartialEq)]
272 /// X coordinate of the vector.
274 /// Y coordinate of the vector.
278 #[allow(clippy::many_single_char_names)]
279 #[allow(clippy::collapsible_if)]
281 /// Creates a new motion vector instance.
282 pub fn new(x: i16, y: i16) -> Self { MV{ x, y } }
283 /// Predicts median from provided motion vectors.
285 /// Each component of the vector is predicted as the median of corresponding input vector components.
286 pub fn pred(a: MV, b: MV, c: MV) -> Self {
292 if a.x < c.x { x = c.x; } else { x = a.x; }
296 if a.x < c.x { x = a.x; } else { x = c.x; }
306 if a.y < c.y { y = c.y; } else { y = a.y; }
310 if a.y < c.y { y = a.y; } else { y = c.y; }
319 /// Zero motion vector.
320 pub const ZERO_MV: MV = MV { x: 0, y: 0 };
324 fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } }
327 impl AddAssign for MV {
328 fn add_assign(&mut self, other: MV) { self.x += other.x; self.y += other.y; }
333 fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } }
336 impl SubAssign for MV {
337 fn sub_assign(&mut self, other: MV) { self.x -= other.x; self.y -= other.y; }
340 impl fmt::Display for MV {
341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342 write!(f, "{},{}", self.x, self.y)
346 /// Auxiliary structure for storing data used by decoder but also controlled by the caller.
347 pub struct NADecoderSupport {
348 /// Frame buffer pool for 8-bit or packed video frames.
349 pub pool_u8: NAVideoBufferPool<u8>,
350 /// Frame buffer pool for 16-bit video frames.
351 pub pool_u16: NAVideoBufferPool<u16>,
352 /// Frame buffer pool for 32-bit video frames.
353 pub pool_u32: NAVideoBufferPool<u32>,
356 impl NADecoderSupport {
357 /// Constructs a new instance of `NADecoderSupport`.
358 pub fn new() -> Self {
360 pool_u8: NAVideoBufferPool::new(0),
361 pool_u16: NAVideoBufferPool::new(0),
362 pool_u32: NAVideoBufferPool::new(0),
367 impl Default for NADecoderSupport {
368 fn default() -> Self { Self::new() }
372 pub trait NADecoder {
373 /// Initialises the decoder.
375 /// It takes [`NADecoderSupport`] allocated by the caller and `NACodecInfoRef` provided by demuxer.
377 /// [`NADecoderSupport`]: ./struct.NADecoderSupport.html
378 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()>;
379 /// Decodes a single frame.
380 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef>;
381 /// Tells decoder to clear internal state (e.g. after error or seeking).
385 /// Decoder information using during creating a decoder for requested codec.
386 #[derive(Clone,Copy)]
387 pub struct DecoderInfo {
388 /// Short decoder name.
389 pub name: &'static str,
390 /// The function that creates a decoder instance.
391 pub get_decoder: fn () -> Box<dyn NADecoder + Send>,
394 #[cfg(any(feature="blockdsp"))]
397 #[cfg(feature="h263")]
400 /// Structure for registering known decoders.
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.
404 pub struct RegisteredDecoders {
405 decs: Vec<DecoderInfo>,
408 impl RegisteredDecoders {
409 /// Constructs a new instance of `RegisteredDecoders`.
410 pub fn new() -> Self {
411 Self { decs: Vec::new() }
413 /// Adds another decoder to the registry.
414 pub fn add_decoder(&mut self, dec: DecoderInfo) {
417 /// Searches for the decoder for the provided name and returns a function for creating it on success.
418 pub fn find_decoder(&self, name: &str) -> Option<fn () -> Box<dyn NADecoder + Send>> {
419 for &dec in self.decs.iter() {
420 if dec.name == name {
421 return Some(dec.get_decoder);
426 /// Provides an iterator over currently registered decoders.
427 pub fn iter(&self) -> std::slice::Iter<DecoderInfo> {
432 /// The common 8x8 zigzag scan.
433 pub 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