Commit | Line | Data |
---|---|---|
3ba71779 | 1 | //! Decoder interface definitions. |
c3e7a747 KS |
2 | use std::fmt; |
3 | use std::ops::{Add, AddAssign, Sub, SubAssign}; | |
4 | ||
4e8b4f31 | 5 | pub use crate::frame::*; |
32007ad9 | 6 | use std::mem; |
aca89041 KS |
7 | use crate::io::byteio::ByteIOError; |
8 | use crate::io::bitreader::BitReaderError; | |
9 | use 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)] | |
14 | pub 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 | 34 | pub type DecoderResult<T> = Result<T, DecoderError>; |
77d06de2 KS |
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 | ||
e35062e7 KS |
53 | impl 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 | 77 | pub struct HAMShuffler { |
3fc28ece | 78 | lastframe: Option<NAVideoBufferRef<u8>>, |
88c03b61 KS |
79 | } |
80 | ||
81 | impl 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 |
114 | impl 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 | 137 | pub struct IPShuffler { |
3fc28ece | 138 | lastframe: Option<NAVideoBufferRef<u8>>, |
3f29a2a8 KS |
139 | } |
140 | ||
141 | impl 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 |
164 | impl 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 | 198 | pub struct IPBShuffler { |
3fc28ece KS |
199 | lastframe: Option<NAVideoBufferRef<u8>>, |
200 | nextframe: Option<NAVideoBufferRef<u8>>, | |
32007ad9 KS |
201 | } |
202 | ||
203 | impl 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 |
254 | impl 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 | 271 | pub 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 | 280 | impl 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 |
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 | ||
3ba71779 | 346 | /// Auxiliary structure for storing data used by decoder but also controlled by the caller. |
01613464 | 347 | pub 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 | ||
356 | impl 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 |
367 | impl Default for NADecoderSupport { |
368 | fn default() -> Self { Self::new() } | |
369 | } | |
370 | ||
3ba71779 | 371 | /// Decoder trait. |
77d06de2 | 372 | pub 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 | 387 | pub 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 | 395 | pub mod blockdsp; |
88c58b1b | 396 | |
88c58b1b | 397 | #[cfg(feature="h263")] |
5641dccf | 398 | pub 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 |
404 | pub struct RegisteredDecoders { |
405 | decs: Vec<DecoderInfo>, | |
406 | } | |
407 | ||
408 | impl 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 |
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 | ]; |