fix some clippy warnings
[nihav.git] / nihav-codec-support / src / codecs / mod.rs
CommitLineData
b4d5b851
KS
1//! Decoder support functions and definitions.
2use std::fmt;
473c2f76 3use std::ops::{Add, AddAssign, Sub, SubAssign, Neg};
b4d5b851
KS
4
5pub use nihav_core::frame::*;
6use std::mem;
7
8/// Frame manager for hold-and-modify codecs.
9///
10/// This frame manager simplifies frame management for the case when codec decodes new frame by updating parts of the previous frame.
11///
12/// # Examples
13///
fa49f061 14/// ```ignore
b4d5b851
KS
15/// let mut frame = if is_intra_frame {
16/// allocate_video_frame()
17/// } else {
18/// let ret = shuffler.clone_ref();
19/// if ret.is_none() {
fa49f061 20/// return Err(DecoderError::MissingReference);
b4d5b851
KS
21/// }
22/// ret.unwrap()
23/// };
24/// // output data into the frame
25/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
fa49f061 26/// ```
b4d5b851 27#[allow(dead_code)]
6f263099 28#[derive(Default)]
8d7a1c5c
KS
29pub struct HAMShuffler<T: Copy> {
30 lastframe: Option<NAVideoBufferRef<T>>,
b4d5b851
KS
31}
32
8d7a1c5c 33impl<T: Copy> HAMShuffler<T> {
b4d5b851
KS
34 /// Constructs a new instance of frame manager.
35 #[allow(dead_code)]
36 pub fn new() -> Self { HAMShuffler { lastframe: None } }
37 /// Clears the reference.
38 #[allow(dead_code)]
39 pub fn clear(&mut self) { self.lastframe = None; }
40 /// Sets a new frame reference.
41 #[allow(dead_code)]
8d7a1c5c 42 pub fn add_frame(&mut self, buf: NAVideoBufferRef<T>) {
b4d5b851
KS
43 self.lastframe = Some(buf);
44 }
45 /// Provides a copy of the reference frame if present or `None` if it is not.
46 #[allow(dead_code)]
8d7a1c5c 47 pub fn clone_ref(&mut self) -> Option<NAVideoBufferRef<T>> {
b4d5b851
KS
48 if let Some(ref mut frm) = self.lastframe {
49 let newfrm = frm.copy_buffer();
50 *frm = newfrm.clone().into_ref();
51 Some(newfrm.into_ref())
52 } else {
53 None
54 }
55 }
56 /// Returns the original saved reference frame or `None` if it is not present.
57 #[allow(dead_code)]
8d7a1c5c 58 pub fn get_output_frame(&mut self) -> Option<NAVideoBufferRef<T>> {
b4d5b851
KS
59 match self.lastframe {
60 Some(ref frm) => Some(frm.clone()),
61 None => None,
62 }
63 }
64}
65
b4d5b851
KS
66/// Frame manager for codecs with intra and inter frames.
67///
68/// This frame manager simplifies frame management for the case when codec decodes new frame using previous frame as source of some data.
69///
70/// # Examples
71///
fa49f061 72/// ```ignore
b4d5b851
KS
73/// let mut frame = allocate_video_frame();
74/// if is_inter_frame {
75/// let ret = shuffler.get_ref();
76/// if ret.is_none() {
fa49f061 77/// return Err(DecoderError::MissingReference);
b4d5b851
KS
78/// }
79/// let ref_frame = ret.unwrap();
80/// // keep decoding using data from ref_frame
81/// }
82/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
fa49f061 83/// ```
b4d5b851 84#[allow(dead_code)]
6f263099 85#[derive(Default)]
b4d5b851
KS
86pub struct IPShuffler {
87 lastframe: Option<NAVideoBufferRef<u8>>,
88}
89
90impl IPShuffler {
91 /// Constructs a new instance of frame manager.
92 #[allow(dead_code)]
93 pub fn new() -> Self { IPShuffler { lastframe: None } }
94 /// Clears the reference.
95 #[allow(dead_code)]
96 pub fn clear(&mut self) { self.lastframe = None; }
97 /// Sets a new frame reference.
98 #[allow(dead_code)]
99 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
100 self.lastframe = Some(buf);
101 }
102 /// Returns the original saved reference frame or `None` if it is not present.
103 #[allow(dead_code)]
104 pub fn get_ref(&mut self) -> Option<NAVideoBufferRef<u8>> {
105 if let Some(ref frm) = self.lastframe {
106 Some(frm.clone())
107 } else {
108 None
109 }
110 }
111}
112
b4d5b851
KS
113/// Frame manager for codecs with I-, P- and B-frames.
114///
115/// This frame manager simplifies frame management for the case when codec uses I/P/B frame scheme.
116///
117/// # Examples
118///
fa49f061 119/// ```ignore
b4d5b851
KS
120/// let mut frame = allocate_video_frame();
121/// for mb in all_macroblocks {
122/// // decode macroblock type
123/// match mb_type {
124/// MBType::Inter => {
125/// do_mc(&mut frame, shuffler.get_lastref().unwrap());
126/// },
127/// MBType::BForward => {
128/// do_mc(&mut frame, shuffler.get_b_fwdref().unwrap());
129/// },
130/// MBType::BBackward => {
131/// do_mc(&mut frame, shuffler.get_b_bwdref().unwrap());
132/// },
133/// // handle the rest of cases
134/// };
135/// if is_random_access_frame {
136/// shuffler.clear(); // remove all saved references
137/// }
138/// if is_intra_frame || is_p_frame {
139/// shuffler.add_frame(frame.clone()); // tells frame manager to use the frame as the next reference
140/// }
fa49f061 141/// ```
b4d5b851 142#[allow(dead_code)]
6f263099 143#[derive(Default)]
b4d5b851
KS
144pub struct IPBShuffler {
145 lastframe: Option<NAVideoBufferRef<u8>>,
146 nextframe: Option<NAVideoBufferRef<u8>>,
147}
148
149impl IPBShuffler {
150 /// Constructs a new instance of frame manager.
151 #[allow(dead_code)]
152 pub fn new() -> Self { IPBShuffler { lastframe: None, nextframe: None } }
153 /// Clears the reference.
154 #[allow(dead_code)]
155 pub fn clear(&mut self) { self.lastframe = None; self.nextframe = None; }
156 /// Sets a new frame reference.
157 #[allow(dead_code)]
158 pub fn add_frame(&mut self, buf: NAVideoBufferRef<u8>) {
159 mem::swap(&mut self.lastframe, &mut self.nextframe);
160 self.lastframe = Some(buf);
161 }
162 /// Returns the previous reference frame or `None` if it is not present.
163 #[allow(dead_code)]
164 pub fn get_lastref(&mut self) -> Option<NAVideoBufferRef<u8>> {
165 if let Some(ref frm) = self.lastframe {
166 Some(frm.clone())
167 } else {
168 None
169 }
170 }
171 /// Returns second last reference frame or `None` if it is not present.
172 #[allow(dead_code)]
173 pub fn get_nextref(&mut self) -> Option<NAVideoBufferRef<u8>> {
174 if let Some(ref frm) = self.nextframe {
175 Some(frm.clone())
176 } else {
177 None
178 }
179 }
180 /// Returns the temporally following reference for B-frame or `None` if it is not present.
181 #[allow(dead_code)]
182 pub fn get_b_fwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
183 if let Some(ref frm) = self.nextframe {
184 Some(frm.clone())
185 } else {
186 None
187 }
188 }
189 /// Returns the temporally preceeding reference for B-frame or `None` if it is not present.
190 #[allow(dead_code)]
191 pub fn get_b_bwdref(&mut self) -> Option<NAVideoBufferRef<u8>> {
192 if let Some(ref frm) = self.lastframe {
193 Some(frm.clone())
194 } else {
195 None
196 }
197 }
198}
199
b4d5b851
KS
200/// Motion vector data type.
201///
202/// # Examples
203///
204/// ```
205/// use nihav_codec_support::codecs::MV;
206///
207/// let mv0 = MV::new(1, 3);
208/// let mv1 = MV { x: 2, y: 3 }; // choose whatever style you prefer
209/// let mv2 = mv1 - mv0;
210/// let mv_pred = MV::pred(mv0, mv1, mv2); // get median prediction for the vectors (1, 0)
211/// ```
212#[derive(Debug,Clone,Copy,Default,PartialEq)]
213pub struct MV {
214 /// X coordinate of the vector.
215 pub x: i16,
216 /// Y coordinate of the vector.
217 pub y: i16,
218}
219
220#[allow(clippy::many_single_char_names)]
221#[allow(clippy::collapsible_if)]
222impl MV {
223 /// Creates a new motion vector instance.
224 pub fn new(x: i16, y: i16) -> Self { MV{ x, y } }
225 /// Predicts median from provided motion vectors.
226 ///
227 /// Each component of the vector is predicted as the median of corresponding input vector components.
228 pub fn pred(a: MV, b: MV, c: MV) -> Self {
229 let x;
230 if a.x < b.x {
231 if b.x < c.x {
232 x = b.x;
233 } else {
234 if a.x < c.x { x = c.x; } else { x = a.x; }
235 }
236 } else {
237 if b.x < c.x {
238 if a.x < c.x { x = a.x; } else { x = c.x; }
239 } else {
240 x = b.x;
241 }
242 }
243 let y;
244 if a.y < b.y {
245 if b.y < c.y {
246 y = b.y;
247 } else {
248 if a.y < c.y { y = c.y; } else { y = a.y; }
249 }
250 } else {
251 if b.y < c.y {
252 if a.y < c.y { y = a.y; } else { y = c.y; }
253 } else {
254 y = b.y;
255 }
256 }
257 MV { x, y }
258 }
259}
260
261/// Zero motion vector.
262pub const ZERO_MV: MV = MV { x: 0, y: 0 };
263
264impl Add for MV {
265 type Output = MV;
266 fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } }
267}
268
269impl AddAssign for MV {
270 fn add_assign(&mut self, other: MV) { self.x += other.x; self.y += other.y; }
271}
272
273impl Sub for MV {
274 type Output = MV;
275 fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } }
276}
277
278impl SubAssign for MV {
279 fn sub_assign(&mut self, other: MV) { self.x -= other.x; self.y -= other.y; }
280}
281
473c2f76
KS
282impl Neg for MV {
283 type Output = MV;
284 fn neg(self) -> Self::Output {
285 MV { x: -self.x, y: -self.y }
286 }
287}
288
b4d5b851
KS
289impl fmt::Display for MV {
290 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291 write!(f, "{},{}", self.x, self.y)
292 }
293}
294
295#[cfg(any(feature="blockdsp"))]
296pub mod blockdsp;
297
298#[cfg(feature="h263")]
03011b99
KS
299#[allow(clippy::collapsible_if)]
300#[allow(clippy::manual_memcpy)]
301#[allow(clippy::needless_range_loop)]
b4d5b851
KS
302pub mod h263;
303
304/// The common 8x8 zigzag scan.
305pub const ZIGZAG: [usize; 64] = [
306 0, 1, 8, 16, 9, 2, 3, 10,
307 17, 24, 32, 25, 18, 11, 4, 5,
308 12, 19, 26, 33, 40, 48, 41, 34,
309 27, 20, 13, 6, 7, 14, 21, 28,
310 35, 42, 49, 56, 57, 50, 43, 36,
311 29, 22, 15, 23, 30, 37, 44, 51,
312 58, 59, 52, 45, 38, 31, 39, 46,
313 53, 60, 61, 54, 47, 55, 62, 63
314];
e781ccc3
KS
315
316pub mod imaadpcm;