core/frame: remove unneeded FrameFromPacket trait
[nihav.git] / nihav-core / src / codecs / mod.rs
1 //! Decoder interface definitions.
2 use std::fmt;
3 use std::ops::{Add, AddAssign, Sub, SubAssign};
4
5 pub use crate::frame::*;
6 use std::mem;
7 use crate::io::byteio::ByteIOError;
8 use crate::io::bitreader::BitReaderError;
9 use crate::io::codebook::CodebookError;
10
11 /// A list specifying general decoding errors.
12 #[derive(Debug,Clone,Copy,PartialEq)]
13 #[allow(dead_code)]
14 pub enum DecoderError {
15 /// No frame was provided.
16 NoFrame,
17 /// Allocation failed.
18 AllocError,
19 /// Operation requires repeating.
20 TryAgain,
21 /// Invalid input data was provided.
22 InvalidData,
23 /// Provided input turned out to be incomplete.
24 ShortData,
25 /// Decoder could not decode provided frame because it references some missing previous frame.
26 MissingReference,
27 /// Feature is not implemented.
28 NotImplemented,
29 /// Some bug in decoder. It should not happen yet it might.
30 Bug,
31 }
32
33 /// A specialised `Result` type for decoding operations.
34 pub type DecoderResult<T> = Result<T, DecoderError>;
35
36 impl From<ByteIOError> for DecoderError {
37 fn from(_: ByteIOError) -> Self { DecoderError::ShortData }
38 }
39
40 impl 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
49 impl From<CodebookError> for DecoderError {
50 fn from(_: CodebookError) -> Self { DecoderError::InvalidData }
51 }
52
53 impl From<AllocatorError> for DecoderError {
54 fn from(_: AllocatorError) -> Self { DecoderError::AllocError }
55 }
56
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 /// ````
76 #[allow(dead_code)]
77 pub struct HAMShuffler {
78 lastframe: Option<NAVideoBufferRef<u8>>,
79 }
80
81 impl HAMShuffler {
82 /// Constructs a new instance of frame manager.
83 #[allow(dead_code)]
84 pub fn new() -> Self { HAMShuffler { lastframe: None } }
85 /// Clears the reference.
86 #[allow(dead_code)]
87 pub fn clear(&mut self) { self.lastframe = None; }
88 /// Sets a new frame reference.
89 #[allow(dead_code)]
90 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
91 self.lastframe = Some(buf);
92 }
93 /// Provides a copy of the reference frame if present or `None` if it is not.
94 #[allow(dead_code)]
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())
100 } else {
101 None
102 }
103 }
104 /// Returns the original saved reference frame or `None` if it is not present.
105 #[allow(dead_code)]
106 pub fn get_output_frame(&mut self) -> Option<NAVideoBufferRef<u8>> {
107 match self.lastframe {
108 Some(ref frm) => Some(frm.clone()),
109 None => None,
110 }
111 }
112 }
113
114 impl Default for HAMShuffler {
115 fn default() -> Self { Self { lastframe: None } }
116 }
117
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 /// ````
136 #[allow(dead_code)]
137 pub struct IPShuffler {
138 lastframe: Option<NAVideoBufferRef<u8>>,
139 }
140
141 impl IPShuffler {
142 /// Constructs a new instance of frame manager.
143 #[allow(dead_code)]
144 pub fn new() -> Self { IPShuffler { lastframe: None } }
145 /// Clears the reference.
146 #[allow(dead_code)]
147 pub fn clear(&mut self) { self.lastframe = None; }
148 /// Sets a new frame reference.
149 #[allow(dead_code)]
150 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
151 self.lastframe = Some(buf);
152 }
153 /// Returns the original saved reference frame or `None` if it is not present.
154 #[allow(dead_code)]
155 pub fn get_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
156 if let Some(ref frm) = self.lastframe {
157 Some(frm.clone())
158 } else {
159 None
160 }
161 }
162 }
163
164 impl Default for IPShuffler {
165 fn default() -> Self { Self { lastframe: None } }
166 }
167
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 /// ````
197 #[allow(dead_code)]
198 pub struct IPBShuffler {
199 lastframe: Option<NAVideoBufferRef<u8>>,
200 nextframe: Option<NAVideoBufferRef<u8>>,
201 }
202
203 impl IPBShuffler {
204 /// Constructs a new instance of frame manager.
205 #[allow(dead_code)]
206 pub fn new() -> Self { IPBShuffler { lastframe: None, nextframe: None } }
207 /// Clears the reference.
208 #[allow(dead_code)]
209 pub fn clear(&mut self) { self.lastframe = None; self.nextframe = None; }
210 /// Sets a new frame reference.
211 #[allow(dead_code)]
212 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
213 mem::swap(&mut self.lastframe, &mut self.nextframe);
214 self.lastframe = Some(buf);
215 }
216 /// Returns the previous reference frame or `None` if it is not present.
217 #[allow(dead_code)]
218 pub fn get_lastref(&mut self) -> Option<NAVideoBufferRef<u8>> {
219 if let Some(ref frm) = self.lastframe {
220 Some(frm.clone())
221 } else {
222 None
223 }
224 }
225 /// Returns second last reference frame or `None` if it is not present.
226 #[allow(dead_code)]
227 pub fn get_nextref(&mut self) -> Option<NAVideoBufferRef<u8>> {
228 if let Some(ref frm) = self.nextframe {
229 Some(frm.clone())
230 } else {
231 None
232 }
233 }
234 /// Returns the temporally following reference for B-frame or `None` if it is not present.
235 #[allow(dead_code)]
236 pub fn get_b_fwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
237 if let Some(ref frm) = self.nextframe {
238 Some(frm.clone())
239 } else {
240 None
241 }
242 }
243 /// Returns the temporally preceeding reference for B-frame or `None` if it is not present.
244 #[allow(dead_code)]
245 pub fn get_b_bwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
246 if let Some(ref frm) = self.lastframe {
247 Some(frm.clone())
248 } else {
249 None
250 }
251 }
252 }
253
254 impl Default for IPBShuffler {
255 fn default() -> Self { Self { lastframe: None, nextframe: None } }
256 }
257
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 /// ```
270 #[derive(Debug,Clone,Copy,Default,PartialEq)]
271 pub struct MV {
272 /// X coordinate of the vector.
273 pub x: i16,
274 /// Y coordinate of the vector.
275 pub y: i16,
276 }
277
278 #[allow(clippy::many_single_char_names)]
279 #[allow(clippy::collapsible_if)]
280 impl MV {
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.
284 ///
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 {
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 }
315 MV { x, y }
316 }
317 }
318
319 /// Zero motion vector.
320 pub const ZERO_MV: MV = MV { x: 0, y: 0 };
321
322 impl 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
327 impl AddAssign for MV {
328 fn add_assign(&mut self, other: MV) { self.x += other.x; self.y += other.y; }
329 }
330
331 impl 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
336 impl SubAssign for MV {
337 fn sub_assign(&mut self, other: MV) { self.x -= other.x; self.y -= other.y; }
338 }
339
340 impl fmt::Display for MV {
341 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342 write!(f, "{},{}", self.x, self.y)
343 }
344 }
345
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>,
354 }
355
356 impl NADecoderSupport {
357 /// Constructs a new instance of `NADecoderSupport`.
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
367 impl Default for NADecoderSupport {
368 fn default() -> Self { Self::new() }
369 }
370
371 /// Decoder trait.
372 pub trait NADecoder {
373 /// Initialises the decoder.
374 ///
375 /// It takes [`NADecoderSupport`] allocated by the caller and `NACodecInfoRef` provided by demuxer.
376 ///
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).
382 fn flush(&mut self);
383 }
384
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>,
392 }
393
394 #[cfg(any(feature="blockdsp"))]
395 pub mod blockdsp;
396
397 #[cfg(feature="h263")]
398 pub mod h263;
399
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.
403 #[derive(Default)]
404 pub struct RegisteredDecoders {
405 decs: Vec<DecoderInfo>,
406 }
407
408 impl RegisteredDecoders {
409 /// Constructs a new instance of `RegisteredDecoders`.
410 pub fn new() -> Self {
411 Self { decs: Vec::new() }
412 }
413 /// Adds another decoder to the registry.
414 pub fn add_decoder(&mut self, dec: DecoderInfo) {
415 self.decs.push(dec);
416 }
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);
422 }
423 }
424 None
425 }
426 /// Provides an iterator over currently registered decoders.
427 pub fn iter(&self) -> std::slice::Iter<DecoderInfo> {
428 self.decs.iter()
429 }
430 }
431
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
442 ];