revc/api/
mod.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3use std::vec::Vec;
4use std::{cmp, fmt, io};
5
6use thiserror::Error;
7
8use num_derive::FromPrimitive;
9use num_traits::FromPrimitive;
10
11pub mod frame;
12
13use crate::dec::*;
14use crate::def::*;
15use crate::enc::*;
16use frame::*;
17
18/*****************************************************************************
19 * return values and error code
20 *****************************************************************************/
21/* not matched CRC value */
22pub const EVC_ERR_BAD_CRC: usize = (201);
23/* CRC value presented but ignored at decoder*/
24pub const EVC_WARN_CRC_IGNORED: usize = (200);
25pub const EVC_OK: usize = 0;
26
27#[derive(Debug, FromPrimitive, ToPrimitive, PartialOrd, Ord, PartialEq, Eq)]
28pub enum EvcError {
29    /* no more output, but it is OK */
30    EVC_OK_NO_MORE_OUTPUT = 205,
31    /* progress success, but output is not available temporarily */
32    EVC_OK_OUTPUT_NOT_AVAILABLE = 204,
33    /* frame dimension (width or height) has been changed */
34    EVC_OK_DIM_CHANGED = 203,
35    /* flush decoding process */
36    EVC_OK_FLUSH = 202,
37
38    EVC_ERR = (-1), /* generic error */
39    EVC_ERR_INVALID_ARGUMENT = (-101),
40    EVC_ERR_OUT_OF_MEMORY = (-102),
41    EVC_ERR_REACHED_MAX = (-103),
42    EVC_ERR_UNSUPPORTED = (-104),
43    EVC_ERR_UNEXPECTED = (-105),
44    EVC_ERR_UNSUPPORTED_COLORSPACE = (-201),
45    EVC_ERR_MALFORMED_BITSTREAM = (-202),
46    EVC_ERR_EMPTY_PACKET = (-203),
47    EVC_ERR_EMPTY_FRAME = (-204),
48
49    EVC_ERR_UNKNOWN = (-32767), /* unknown error */
50}
51
52impl Default for EvcError {
53    fn default() -> Self {
54        EvcError::EVC_ERR
55    }
56}
57
58pub const NALU_SIZE_FIELD_IN_BYTES: usize = 4;
59
60#[allow(dead_code, non_camel_case_types)]
61#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone, Copy)]
62pub enum NaluType {
63    EVC_NONIDR_NUT = 0,
64    EVC_IDR_NUT = 1,
65    EVC_SPS_NUT = 24,
66    EVC_PPS_NUT = 25,
67    EVC_APS_NUT = 26,
68    EVC_FD_NUT = 27,
69    EVC_SEI_NUT = 28,
70    EVC_UNKNOWN_NUT,
71}
72
73impl fmt::Display for NaluType {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        use self::NaluType::*;
76        match self {
77            EVC_NONIDR_NUT => write!(f, "Non-IDR"),
78            EVC_IDR_NUT => write!(f, "Instantaneous Decoder Refresh"),
79            EVC_SPS_NUT => write!(f, "Sequence Parameter Se"),
80            EVC_PPS_NUT => write!(f, "Picture Parameter Set"),
81            EVC_APS_NUT => write!(f, "Adaptation Parameter Set"),
82            EVC_FD_NUT => write!(f, "Filler Data"),
83            EVC_SEI_NUT => write!(f, "Supplemental Enhancement Information"),
84            EVC_UNKNOWN_NUT => write!(f, "Unknown"),
85        }
86    }
87}
88
89impl From<u8> for NaluType {
90    fn from(val: u8) -> Self {
91        use self::NaluType::*;
92        match val {
93            0 => EVC_NONIDR_NUT,
94            1 => EVC_IDR_NUT,
95            24 => EVC_SPS_NUT,
96            25 => EVC_PPS_NUT,
97            26 => EVC_APS_NUT,
98            27 => EVC_FD_NUT,
99            28 => EVC_SEI_NUT,
100            _ => EVC_UNKNOWN_NUT,
101        }
102    }
103}
104
105impl Default for NaluType {
106    fn default() -> Self {
107        NaluType::EVC_NONIDR_NUT
108    }
109}
110
111#[allow(dead_code, non_camel_case_types)]
112#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone, Copy)]
113#[repr(C)]
114pub enum SliceType {
115    EVC_ST_UNKNOWN = 0,
116    EVC_ST_I = 1,
117    EVC_ST_P = 2,
118    EVC_ST_B = 3,
119}
120
121impl fmt::Display for SliceType {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        use self::SliceType::*;
124        match self {
125            EVC_ST_UNKNOWN => write!(f, "Unknown"),
126            EVC_ST_I => write!(f, "I"),
127            EVC_ST_P => write!(f, "P"),
128            EVC_ST_B => write!(f, "B"),
129        }
130    }
131}
132
133impl From<u8> for SliceType {
134    fn from(val: u8) -> Self {
135        use self::SliceType::*;
136        match val {
137            1 => EVC_ST_I,
138            2 => EVC_ST_P,
139            3 => EVC_ST_B,
140            _ => EVC_ST_UNKNOWN,
141        }
142    }
143}
144
145impl Default for SliceType {
146    fn default() -> Self {
147        SliceType::EVC_ST_UNKNOWN
148    }
149}
150
151impl SliceType {
152    #[inline]
153    pub(crate) fn IS_INTRA_SLICE(&self) -> bool {
154        *self == SliceType::EVC_ST_I
155    }
156
157    #[inline]
158    pub(crate) fn IS_INTER_SLICE(&self) -> bool {
159        *self == SliceType::EVC_ST_P || *self == SliceType::EVC_ST_B
160    }
161}
162
163/*****************************************************************************
164 * status after decoder/encoder operation
165 *****************************************************************************/
166#[derive(Debug, Default)]
167pub struct EvcStat {
168    /* byte size of decoded/encoded bitstream (read/write size of bitstream) */
169    pub bytes: usize,
170    /* nalu type */
171    pub nalu_type: NaluType,
172    /* slice type */
173    pub stype: SliceType,
174    /* frame number monotonically increased whenever decoding a frame.
175    note that it has negative value if the decoded data is not frame */
176    pub fnum: isize,
177    /* picture order count */
178    pub poc: isize,
179    /* layer id */
180    pub tid: isize,
181
182    /* number of reference pictures */
183    pub refpic_num: [u8; 2],
184    /* list of reference pictures */
185    pub refpic: [[isize; 16]; 2], //[2][16]
186
187    pub ret: usize,
188
189    // encoder only
190    /* encoded sei messages byte size */
191    pub sei_size: usize,
192    /* picture number increased whenever encoding a frame */
193    /* quantization parameter used for encoding */
194    pub qp: u8,
195    pub rec: Option<Rc<RefCell<Frame<pel>>>>,
196    pub psnr: Option<[f64; N_C]>,
197}
198
199pub const MAX_NUM_REF_PICS: usize = 21;
200pub const MAX_NUM_ACTIVE_REF_FRAME: usize = 5;
201pub const MAX_NUM_RPLS: usize = 32;
202
203/* rpl structure */
204#[derive(Default)]
205pub struct EvcRpl {
206    pub poc: usize,
207    pub tid: usize,
208    pub ref_pic_num: u8,
209    pub ref_pic_active_num: u8,
210    pub ref_pics: [u8; MAX_NUM_REF_PICS],
211    pub pic_type: u8,
212}
213
214pub const MAX_QP_TABLE_SIZE: usize = 58;
215pub const MAX_QP_TABLE_SIZE_EXT: usize = 70;
216
217/* chromaQP table structure to be signalled in SPS*/
218pub struct EvcChromaTable {
219    pub chroma_qp_table_present_flag: bool,
220    pub same_qp_table_for_chroma: bool,
221    pub global_offset_flag: bool,
222    pub num_points_in_qp_table_minus1: [usize; 2],
223    pub delta_qp_in_val_minus1: [[i8; MAX_QP_TABLE_SIZE]; 2],
224    pub delta_qp_out_val: [[i8; MAX_QP_TABLE_SIZE]; 2],
225}
226
227static default_qp_talbe: [[i8; MAX_QP_TABLE_SIZE]; 2] = [[0; MAX_QP_TABLE_SIZE]; 2];
228impl Default for EvcChromaTable {
229    fn default() -> Self {
230        EvcChromaTable {
231            chroma_qp_table_present_flag: false,
232            same_qp_table_for_chroma: false,
233            global_offset_flag: false,
234            num_points_in_qp_table_minus1: [0; 2],
235            delta_qp_in_val_minus1: default_qp_talbe,
236            delta_qp_out_val: default_qp_talbe,
237        }
238    }
239}
240
241pub enum Data {
242    Empty,
243    RefFrame(Rc<RefCell<Frame<pel>>>),
244    Frame(Option<Frame<pel>>),
245    RefPacket(Rc<RefCell<Packet>>),
246    Packet(Option<Packet>),
247}
248
249#[derive(Debug, Default)]
250pub struct Packet {
251    pub data: Vec<u8>,
252    pub ts: u64,
253}
254
255impl fmt::Display for Packet {
256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257        write!(f, "Packet {} - {} bytes", self.ts, self.data.len())
258    }
259}
260
261#[derive(Copy, Clone, Debug, PartialEq, FromPrimitive)]
262#[repr(C)]
263pub enum ChromaSampling {
264    Cs400,
265    Cs420,
266    Cs422,
267    Cs444,
268}
269
270impl Default for ChromaSampling {
271    fn default() -> Self {
272        ChromaSampling::Cs420
273    }
274}
275
276impl From<u8> for ChromaSampling {
277    fn from(val: u8) -> Self {
278        use self::ChromaSampling::*;
279        match val {
280            0 => Cs400,
281            1 => Cs420,
282            2 => Cs422,
283            _ => Cs444,
284        }
285    }
286}
287
288impl ChromaSampling {
289    // Provides the sampling period in the horizontal and vertical axes.
290    pub fn sampling_period(self) -> (usize, usize) {
291        use self::ChromaSampling::*;
292        match self {
293            Cs420 => (2, 2),
294            Cs422 => (2, 1),
295            Cs444 => (1, 1),
296            Cs400 => (2, 2),
297        }
298    }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, FromPrimitive)]
302#[repr(C)]
303pub enum PixelRange {
304    Unspecified = 0,
305    Limited,
306    Full,
307}
308
309impl Default for PixelRange {
310    fn default() -> Self {
311        PixelRange::Unspecified
312    }
313}
314
315#[derive(Clone, Copy, Debug, Default)]
316#[repr(C)]
317pub struct Rational {
318    pub num: u64,
319    pub den: u64,
320}
321
322impl Rational {
323    pub fn new(num: u64, den: u64) -> Self {
324        Rational { num, den }
325    }
326}
327
328#[derive(Clone, Copy, Debug)]
329#[repr(C)]
330pub struct Point {
331    pub x: u16,
332    pub y: u16,
333}
334
335/// Enumeration of possible invalid configuration errors.
336#[derive(Debug, Clone, Copy, Eq, PartialEq, Error)]
337#[non_exhaustive]
338pub enum InvalidConfig {
339    /// The width is invalid.
340    #[error("invalid width {0} (expected >= 16, <= 32767)")]
341    InvalidWidth(usize),
342    /// The height is invalid.
343    #[error("invalid height {0} (expected >= 16, <= 32767)")]
344    InvalidHeight(usize),
345    /// RDO lookahead frame count is invalid.
346    #[error("invalid rdo lookahead frames {actual} (expected <= {max} and >= {min})")]
347    InvalidRdoLookaheadFrames {
348        /// The actual value.
349        actual: usize,
350        /// The maximal supported value.
351        max: usize,
352        /// The minimal supported value.
353        min: usize,
354    },
355    /// Maximal keyframe interval is invalid.
356    #[error("invalid max keyframe interval {actual} (expected <= {max})")]
357    InvalidMaxKeyFrameInterval {
358        /// The actual value.
359        actual: usize,
360        /// The maximal supported value.
361        max: usize,
362    },
363    /// Framerate numerator is invalid.
364    #[error("invalid framerate numerator {actual} (expected > 0, <= {max})")]
365    InvalidFrameRateNum {
366        /// The actual value.
367        actual: u64,
368        /// The maximal supported value.
369        max: u64,
370    },
371    /// Framerate denominator is invalid.
372    #[error("invalid framerate denominator {actual} (expected > 0, <= {max})")]
373    InvalidFrameRateDen {
374        /// The actual value.
375        actual: u64,
376        /// The maximal supported value.
377        max: u64,
378    },
379
380    /// The QP is invalid.
381    #[error("invalid qp {actual} (expected <= {max} and >= {min})")]
382    InvalidQP {
383        /// The actual value.
384        actual: u8,
385        /// The maximal supported value.
386        max: u8,
387        /// The minimal supported value.
388        min: u8,
389    },
390
391    #[error("Invalid Max B Frames")]
392    InvalidMaxBFrames,
393    #[error("Invalid Ref Pic GAP Length")]
394    InvalidRefPicGapLength,
395    #[error("Invalid Hierarchical GOP")]
396    InvalidHierarchicalGOP,
397
398    /// The rate control needs a target bitrate in order to produce results
399    #[error("The rate control requires a target bitrate")]
400    TargetBitrateNeeded,
401}
402
403// We add 1 to rdo_lookahead_frames in a bunch of places.
404pub(crate) const MAX_RDO_LOOKAHEAD_FRAMES: usize = usize::max_value() - 1;
405// Due to the math in RCState::new() regarding the reservoir frame delay.
406pub const MAX_MAX_KEY_FRAME_INTERVAL: usize = i32::max_value() as usize / 3;
407
408#[derive(Clone, Copy, Debug, Default)]
409pub struct EncoderConfig {
410    // output size
411    // Width of the frames in pixels.
412    pub width: usize,
413    // Height of the frames in pixels.
414    pub height: usize,
415    // Video time base.
416    pub time_base: Rational,
417    pub fps: u64,
418
419    // Bit depth.
420    pub bit_depth: usize,
421    // Chroma subsampling.
422    pub chroma_sampling: ChromaSampling,
423
424    // encoder configuration
425    // The *minimum* interval between two keyframes
426    pub min_key_frame_interval: usize,
427    // The *maximum* interval between two keyframes
428    pub max_key_frame_interval: usize, //iperiod
429
430    // The base quantizer to use.
431    pub qp: u8,
432    // The minimum allowed base quantizer to use in bitrate mode.
433    pub min_qp: u8,
434    // The maximum allowed base quantizer to use in bitrate mode.
435    pub max_qp: u8,
436    // The target bitrate for the bitrate mode.
437    pub bitrate: i32,
438
439    pub cb_qp_offset: i8,
440    pub cr_qp_offset: i8,
441    pub cu_qp_delta_area: u8,
442    pub max_b_frames: u8,
443    pub ref_pic_gap_length: u8,
444    pub closed_gop: bool,
445    pub disable_hgop: bool,
446    pub level: u8,
447    pub enable_cip: bool,
448    pub disable_dbf: bool,
449    pub num_slices_in_pic: usize,
450    pub inter_slice_type: SliceType,
451
452    // Number of frames to read ahead for the RDO lookahead computation.
453    pub rdo_lookahead_frames: usize,
454    // Settings which affect the enconding speed vs. quality trade-off.
455    //pub speed_settings: SpeedSettings,
456    // Rate control configuration
457    // rate_control: RateControlConfig,
458}
459
460impl EncoderConfig {
461    /// Validates the configuration.
462    pub fn validate(&self) -> Result<(), InvalidConfig> {
463        use InvalidConfig::*;
464
465        let config = self;
466
467        if config.width < 16 || config.width > u16::max_value() as usize || config.width & 7 != 0 {
468            return Err(InvalidWidth(config.width));
469        }
470        if config.height < 16 || config.height > u16::max_value() as usize || config.height & 7 != 0
471        {
472            return Err(InvalidHeight(config.height));
473        }
474
475        if config.qp < MIN_QUANT || config.qp > MAX_QUANT {
476            return Err(InvalidQP {
477                actual: config.qp,
478                max: MAX_QUANT,
479                min: MIN_QUANT,
480            });
481        }
482
483        /*if config.rdo_lookahead_frames > MAX_RDO_LOOKAHEAD_FRAMES || config.rdo_lookahead_frames < 1
484        {
485            return Err(InvalidRdoLookaheadFrames {
486                actual: config.rdo_lookahead_frames,
487                max: MAX_RDO_LOOKAHEAD_FRAMES,
488                min: 1,
489            });
490        }*/
491        if config.max_key_frame_interval > MAX_MAX_KEY_FRAME_INTERVAL {
492            return Err(InvalidMaxKeyFrameInterval {
493                actual: config.max_key_frame_interval,
494                max: MAX_MAX_KEY_FRAME_INTERVAL,
495            });
496        }
497
498        if config.time_base.num == 0 || config.time_base.num > u32::max_value() as u64 {
499            return Err(InvalidFrameRateNum {
500                actual: config.time_base.num,
501                max: u32::max_value() as u64,
502            });
503        }
504        if config.time_base.den == 0 || config.time_base.den > u32::max_value() as u64 {
505            return Err(InvalidFrameRateDen {
506                actual: config.time_base.den,
507                max: u32::max_value() as u64,
508            });
509        }
510
511        if !config.disable_hgop {
512            if !(config.max_b_frames == 0
513                || config.max_b_frames == 1
514                || config.max_b_frames == 3
515                || config.max_b_frames == 7
516                || config.max_b_frames == 15)
517            {
518                return Err(InvalidMaxBFrames);
519            }
520
521            if config.max_b_frames != 0 {
522                if config.max_key_frame_interval % (config.max_b_frames + 1) as usize != 0 {
523                    return Err(InvalidHierarchicalGOP);
524                }
525            }
526        }
527
528        if config.ref_pic_gap_length != 0 && config.max_b_frames != 0 {
529            return Err(InvalidMaxBFrames);
530        }
531
532        if config.max_b_frames == 0 {
533            if !(config.ref_pic_gap_length == 1
534                || config.ref_pic_gap_length == 2
535                || config.ref_pic_gap_length == 4
536                || config.ref_pic_gap_length == 8
537                || config.ref_pic_gap_length == 16)
538            {
539                return Err(InvalidRefPicGapLength);
540            }
541        }
542
543        // TODO: add more validation
544        /*let rc = &self.rate_control;
545
546        if (rc.emit_pass_data || rc.summary.is_some()) && config.bitrate == 0 {
547            return Err(TargetBitrateNeeded);
548        }*/
549
550        Ok(())
551    }
552}
553
554/// Contains the encoder configuration.
555#[derive(Clone, Copy, Debug, Default)]
556pub struct Config {
557    /// The number of threads in the threadpool.
558    pub threads: usize,
559
560    /// Encoder configuration (optional)
561    pub enc: Option<EncoderConfig>,
562}
563
564pub struct DecoderContext(EvcdCtx);
565pub struct EncoderContext(EvceCtx);
566
567pub enum Context {
568    Invalid(InvalidConfig),
569    Decoder(DecoderContext),
570    Encoder(EncoderContext),
571}
572
573impl Context {
574    pub fn new(cfg: &Config) -> Self {
575        if let Some(cfg_enc) = &cfg.enc {
576            match cfg_enc.validate() {
577                Ok(_) => Context::Encoder(EncoderContext(EvceCtx::new(cfg))),
578                Err(err) => return Context::Invalid(err),
579            }
580        } else {
581            Context::Decoder(DecoderContext(EvcdCtx::new(cfg)))
582        }
583    }
584
585    pub fn push(&mut self, data: &mut Data) -> Result<(), EvcError> {
586        match self {
587            Context::Decoder(ctx) => {
588                if let Data::Packet(pkt) = data {
589                    ctx.0.push_pkt(pkt)
590                } else {
591                    Err(EvcError::EVC_ERR_EMPTY_PACKET)
592                }
593            }
594            Context::Encoder(ctx) => {
595                if let Data::Frame(frm) = data {
596                    ctx.0.push_frm(frm)
597                } else {
598                    Err(EvcError::EVC_ERR_EMPTY_FRAME)
599                }
600            }
601            Context::Invalid(_) => Err(EvcError::EVC_ERR_UNSUPPORTED),
602        }
603    }
604
605    pub fn pull(&mut self, data: &mut Data) -> Result<Option<EvcStat>, EvcError> {
606        *data = Data::Empty;
607
608        match self {
609            Context::Decoder(ctx) => {
610                let mut stat = None;
611                let mut pull_frm = false;
612                match ctx.0.decode_nalu() {
613                    Ok(st) => {
614                        pull_frm = st.fnum >= 0;
615                        stat = Some(st);
616                    }
617                    Err(err) => {
618                        if err == EvcError::EVC_OK_FLUSH {
619                            pull_frm = true;
620                        }
621                    }
622                }
623
624                if pull_frm {
625                    match ctx.0.pull_frm() {
626                        Ok(frame) => *data = Data::RefFrame(frame),
627                        Err(err) => {
628                            if err != EvcError::EVC_OK_OUTPUT_NOT_AVAILABLE {
629                                return Err(err);
630                            }
631                        }
632                    }
633                }
634
635                Ok(stat)
636            }
637            Context::Encoder(ctx) => {
638                let mut stat = None;
639                let mut pull_pkt = false;
640                match ctx.0.encode_frm() {
641                    Ok(st) => {
642                        pull_pkt = true;
643                        stat = Some(st);
644                    }
645                    Err(err) => {
646                        if err != EvcError::EVC_OK_OUTPUT_NOT_AVAILABLE {
647                            return Err(err);
648                        }
649                    }
650                }
651
652                if pull_pkt {
653                    let packet = ctx.0.pull_pkt()?;
654                    *data = Data::RefPacket(packet);
655                }
656
657                Ok(stat)
658            }
659            Context::Invalid(_) => Err(EvcError::EVC_ERR_UNSUPPORTED),
660        }
661    }
662}