aboutsummaryrefslogtreecommitdiffstats
path: root/nihav-core/src
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2020-02-20 11:35:16 +0100
committerKostya Shishkov <kostya.shishkov@gmail.com>2020-02-20 11:35:16 +0100
commit32f7cbe538d71574f7ac05aa51599d2678f5db3f (patch)
tree27ada919c11200139c5fee4f2f299dde373476fa /nihav-core/src
parentb4d5b8515e75383b4fc59ea2813c90c615d59a96 (diff)
downloadnihav-32f7cbe538d71574f7ac05aa51599d2678f5db3f.tar.gz
split nihav-registry from nihav-core
Diffstat (limited to 'nihav-core/src')
-rw-r--r--nihav-core/src/detect.rs328
-rw-r--r--nihav-core/src/lib.rs3
-rw-r--r--nihav-core/src/register.rs284
3 files changed, 0 insertions, 615 deletions
diff --git a/nihav-core/src/detect.rs b/nihav-core/src/detect.rs
deleted file mode 100644
index a693124..0000000
--- a/nihav-core/src/detect.rs
+++ /dev/null
@@ -1,328 +0,0 @@
-//! Container format detection.
-//!
-//! Usually user does not know the container format of the opened file.
-//! That is why format detection functionality is needed.
-//! This module contains the set of rules to detect container not merely by file extension but also by its content if possible.
-//!
-//! # Examples
-//!
-//! ```no_run
-//! use nihav_core::detect::detect_format;
-//! use std::fs::File;
-//! use nihav_core::io::byteio::*;
-//!
-//! let name = "mediafile.ogv";
-//! let mut file = File::open(name).unwrap();
-//! let mut filereader = FileReader::new_read(&mut file);
-//! let mut br = ByteReader::new(&mut filereader);
-//! let result = detect_format(name, &mut br);
-//! if let Some((name, score)) = result {
-//! println!("detected format {} with score {:?}", name, score);
-//! }
-//! ```
-use std::io::SeekFrom;
-use crate::io::byteio::ByteReader;
-
-/// Format detection score.
-#[derive(Debug,Clone,Copy,PartialEq)]
-pub enum DetectionScore {
- /// Format is not detected.
- No,
- /// Format matched by file extension.
- ExtensionMatches,
- /// Format matches by markers inside the file.
- MagicMatches,
-}
-
-impl DetectionScore {
- /// Checks whether current detection score is less than a value it is compared against.
- pub fn less(self, other: DetectionScore) -> bool {
- (self as i32) < (other as i32)
- }
-}
-
-#[allow(dead_code)]
-enum Arg {
- Byte(u8),
- U16BE(u16),
- U16LE(u16),
- U24BE(u32),
- U24LE(u32),
- U32BE(u32),
- U32LE(u32),
- U64BE(u64),
- U64LE(u64),
-}
-
-impl Arg {
- fn val(&self) -> u64 {
- match *self {
- Arg::Byte(b) => { u64::from(b) }
- Arg::U16BE(v) => { u64::from(v) }
- Arg::U16LE(v) => { u64::from(v) }
- Arg::U24BE(v) => { u64::from(v) }
- Arg::U24LE(v) => { u64::from(v) }
- Arg::U32BE(v) => { u64::from(v) }
- Arg::U32LE(v) => { u64::from(v) }
- Arg::U64BE(v) => { v }
- Arg::U64LE(v) => { v }
- }
- }
- fn read_val(&self, src: &mut ByteReader) -> Option<u64> {
- match *self {
- Arg::Byte(_) => {
- let res = src.peek_byte();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U16BE(_) => {
- let res = src.peek_u16be();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U16LE(_) => {
- let res = src.peek_u16le();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U24BE(_) => {
- let res = src.peek_u24be();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U24LE(_) => {
- let res = src.peek_u24le();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U32BE(_) => {
- let res = src.peek_u32be();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U32LE(_) => {
- let res = src.peek_u32le();
- if res.is_err() { return None; }
- Some(u64::from(res.unwrap()))
- }
- Arg::U64BE(_) => {
- let res = src.peek_u64be();
- if res.is_err() { return None; }
- Some(res.unwrap())
- }
- Arg::U64LE(_) => {
- let res = src.peek_u64le();
- if res.is_err() { return None; }
- Some(res.unwrap())
- }
- }
- }
- fn eq(&self, src: &mut ByteReader) -> bool {
- let val = self.read_val(src);
- if val.is_none() { false }
- else { val.unwrap() == self.val() }
- }
- fn ge(&self, src: &mut ByteReader) -> bool {
- let val = self.read_val(src);
- if val.is_none() { false }
- else { val.unwrap() >= self.val() }
- }
- fn gt(&self, src: &mut ByteReader) -> bool {
- let val = self.read_val(src);
- if val.is_none() { false }
- else { val.unwrap() > self.val() }
- }
- fn le(&self, src: &mut ByteReader) -> bool {
- let val = self.read_val(src);
- if val.is_none() { false }
- else { val.unwrap() <= self.val() }
- }
- fn lt(&self, src: &mut ByteReader) -> bool {
- let val = self.read_val(src);
- if val.is_none() { false }
- else { val.unwrap() < self.val() }
- }
-}
-
-#[allow(dead_code)]
-enum CC<'a> {
- Or(&'a CC<'a>, &'a CC<'a>),
- Eq(Arg),
- Str(&'static [u8]),
- In(Arg, Arg),
- Lt(Arg),
- Le(Arg),
- Gt(Arg),
- Ge(Arg),
-}
-
-impl<'a> CC<'a> {
- fn eval(&self, src: &mut ByteReader) -> bool {
- match *self {
- CC::Or (ref a, ref b) => { a.eval(src) || b.eval(src) },
- CC::Eq(ref arg) => { arg.eq(src) },
- CC::In(ref a, ref b) => { a.ge(src) && b.le(src) },
- CC::Lt(ref arg) => { arg.lt(src) },
- CC::Le(ref arg) => { arg.le(src) },
- CC::Gt(ref arg) => { arg.gt(src) },
- CC::Ge(ref arg) => { arg.ge(src) },
- CC::Str(str) => {
- let mut val: Vec<u8> = vec![0; str.len()];
- let res = src.peek_buf(val.as_mut_slice());
- if res.is_err() { return false; }
- val == str
- }
- }
- }
-}
-
-struct CheckItem<'a> {
- offs: u32,
- cond: &'a CC<'a>,
-}
-
-#[allow(dead_code)]
-struct DetectConditions<'a> {
- demux_name: &'static str,
- extensions: &'static str,
- conditions: &'a [CheckItem<'a>],
-}
-
-const DETECTORS: &[DetectConditions] = &[
- DetectConditions {
- demux_name: "avi",
- extensions: ".avi",
- conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b"RIFF"), &CC::Str(b"ON2 ")) },
- CheckItem{offs: 8, cond: &CC::Or(&CC::Or(&CC::Str(b"AVI LIST"),
- &CC::Str(b"AVIXLIST")),
- &CC::Str(b"ON2fLIST")) },
- ]
- },
- DetectConditions {
- demux_name: "gdv",
- extensions: ".gdv",
- conditions: &[CheckItem{offs: 0, cond: &CC::Eq(Arg::U32LE(0x29111994))}],
- },
- DetectConditions {
- demux_name: "realaudio",
- extensions: ".ra,.ram",
- conditions: &[CheckItem{offs: 0, cond: &CC::Str(b".ra\xFD")}],
- },
- DetectConditions {
- demux_name: "realmedia",
- extensions: ".rm,.rmvb,.rma,.ra,.ram",
- conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b".RMF"), &CC::Str(b".RMP")) },
- CheckItem{offs: 4, cond: &CC::Ge(Arg::U32BE(10))}],
- },
- DetectConditions {
- demux_name: "real_ivr",
- extensions: ".ivr",
- conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b".R1M"), &CC::Str(b".REC"))}],
- },
- DetectConditions {
- demux_name: "bink",
- extensions: ".bik,.bk2",
- conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::In(Arg::U32BE(0x32494B62), // BIKb
- Arg::U32BE(0x32494B7B)), // BIKz
- &CC::In(Arg::U32BE(0x4B423261), // KB2a
- Arg::U32BE(0x4B42327B)))}], // KB2z
- },
- DetectConditions {
- demux_name: "smacker",
- extensions: ".smk",
- conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b"SMK2"), &CC::Str(b"SMK4"))}],
- },
- DetectConditions {
- demux_name: "bmv",
- extensions: ".bmv",
- conditions: &[],
- },
- DetectConditions {
- demux_name: "bmv3",
- extensions: ".bmv",
- conditions: &[CheckItem{offs: 0, cond: &CC::Str(b"BMVi") },
- CheckItem{offs: 32, cond: &CC::Str(b"DATA")}],
- },
- DetectConditions {
- demux_name: "vmd",
- extensions: ".vmd",
- conditions: &[],
- },
-];
-
-/// Tries to detect container format.
-///
-/// This function tries to determine container format using both file extension and checking against container specific markers inside.
-/// In case of success the function returns short container name and the detection score.
-/// Result should have the highest detection score among tested.
-pub fn detect_format(name: &str, src: &mut ByteReader) -> Option<(&'static str, DetectionScore)> {
- let mut result = None;
- let lname = name.to_lowercase();
- for detector in DETECTORS {
- let mut score = DetectionScore::No;
- if !name.is_empty() {
- for ext in detector.extensions.split(',') {
- if lname.ends_with(ext) {
- score = DetectionScore::ExtensionMatches;
- break;
- }
- }
- }
- let mut passed = !detector.conditions.is_empty();
- for ck in detector.conditions {
- let ret = src.seek(SeekFrom::Start(u64::from(ck.offs)));
- if ret.is_err() {
- passed = false;
- break;
- }
- if !ck.cond.eval(src) {
- passed = false;
- break;
- }
- }
- if passed {
- score = DetectionScore::MagicMatches;
- }
- if score == DetectionScore::MagicMatches {
- return Some((detector.demux_name, score));
- }
- if result.is_none() && score != DetectionScore::No {
- result = Some((detector.demux_name, score));
- } else if result.is_some() {
- let (_, oldsc) = result.unwrap();
- if oldsc.less(score) {
- result = Some((detector.demux_name, score));
- }
- }
- }
- result
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use std::fs::File;
- use crate::io::byteio::*;
-
- #[test]
- fn test_avi_detect() {
- let name = "assets/Indeo/laser05.avi";
- let mut file = File::open(name).unwrap();
- let mut fr = FileReader::new_read(&mut file);
- let mut br = ByteReader::new(&mut fr);
- let (name, score) = detect_format(name, &mut br).unwrap();
- assert_eq!(name, "avi");
- assert_eq!(score, DetectionScore::MagicMatches);
- }
-
- #[test]
- fn test_gdv_detect() {
- let name = "assets/Game/intro1.gdv";
- let mut file = File::open(name).unwrap();
- let mut fr = FileReader::new_read(&mut file);
- let mut br = ByteReader::new(&mut fr);
- let (name, score) = detect_format(name, &mut br).unwrap();
- assert_eq!(name, "gdv");
- assert_eq!(score, DetectionScore::MagicMatches);
- }
-}
diff --git a/nihav-core/src/lib.rs b/nihav-core/src/lib.rs
index a53f304..cf97841 100644
--- a/nihav-core/src/lib.rs
+++ b/nihav-core/src/lib.rs
@@ -15,9 +15,6 @@ pub mod frame;
#[allow(clippy::too_many_arguments)]
pub mod io;
pub mod refs;
-pub mod register;
-#[allow(clippy::unreadable_literal)]
-pub mod detect;
pub mod reorder;
pub mod scale;
pub mod soundcvt;
diff --git a/nihav-core/src/register.rs b/nihav-core/src/register.rs
deleted file mode 100644
index c54ce58..0000000
--- a/nihav-core/src/register.rs
+++ /dev/null
@@ -1,284 +0,0 @@
-//! Global registry of codec information.
-//!
-//! This module contains codec information from technical level that allows user to retrieve information about codec type and features without creating and invoking a decoder for such codec.
-use std::fmt;
-
-/// Codec types.
-#[derive(Debug,Clone,Copy,PartialEq)]
-#[allow(dead_code)]
-pub enum CodecType {
- /// Video codec.
- Video,
- /// Audio codec.
- Audio,
- /// Subtitle codec.
- Subtitles,
- /// Some special codec (e.g. some event stream or separate timecodes stream).
- Data,
- /// Dummy codec.
- None,
-}
-
-impl fmt::Display for CodecType {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- CodecType::Video => write!(f, "Video"),
- CodecType::Audio => write!(f, "Audio"),
- CodecType::Subtitles => write!(f, "Subtitles"),
- CodecType::Data => write!(f, "Data"),
- CodecType::None => write!(f, "-"),
- }
- }
-}
-
-const CODEC_CAP_INTRAONLY:u32 = 0x0001;
-const CODEC_CAP_LOSSLESS:u32 = 0x0002;
-const CODEC_CAP_REORDER:u32 = 0x0004;
-const CODEC_CAP_HYBRID:u32 = 0x0008;
-const CODEC_CAP_SCALABLE:u32 = 0x0010;
-
-/// Codec description structure.
-#[derive(Clone)]
-pub struct CodecDescription {
- /// Short codec name.
- ///
- /// Short codec name is used inside NihAV as the unique identifier.
- pub name: &'static str,
- /// Full codec name.
- pub fname: &'static str,
- /// Codec type.
- pub ctype: CodecType,
- /// Codec capabilities.
- pub caps: u32,
-}
-
-impl CodecDescription {
- /// Returns short codec name.
- pub fn get_name(&self) -> &'static str { self.name }
- /// Returns full codec name.
- pub fn get_full_name(&self) -> &'static str { self.fname }
- /// Returns codec type.
- pub fn get_codec_type(&self) -> CodecType { self.ctype }
- /// Reports whether the codec has only intra frames or not.
- pub fn is_intraonly(&self) -> bool { (self.caps & CODEC_CAP_INTRAONLY) != 0 }
- /// Reports whether the codec is lossless.
- pub fn is_lossless(&self) -> bool { (self.caps & CODEC_CAP_LOSSLESS) != 0 }
- /// Reports whether the codec requires frame reordering.
- pub fn has_reorder(&self) -> bool { (self.caps & CODEC_CAP_REORDER) != 0 }
- /// Reports whether the codec can be either lossless or lossy.
- pub fn is_hybrid(&self) -> bool { (self.caps & CODEC_CAP_HYBRID) != 0 }
- /// Reports whether codec supports scalability.
- ///
- /// Scalability means that codec can be decoded in reduced resolution by design.
- pub fn is_scalable(&self) -> bool { (self.caps & CODEC_CAP_SCALABLE) != 0 }
-}
-
-impl fmt::Display for CodecDescription {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut out = self.fname.to_string();
- if self.caps != 0 {
- let mut capfmt = "".to_string();
- if (self.caps & CODEC_CAP_INTRAONLY) != 0 {
- capfmt = format!("{} Intra-only", capfmt);
- }
- if (self.caps & CODEC_CAP_LOSSLESS) != 0 {
- capfmt = format!("{} Lossless", capfmt);
- }
- if (self.caps & CODEC_CAP_REORDER) != 0 {
- capfmt = format!("{} Frame reorder", capfmt);
- }
- if (self.caps & CODEC_CAP_HYBRID) != 0 {
- capfmt = format!("{} Can be lossy and lossless", capfmt);
- }
- if (self.caps & CODEC_CAP_SCALABLE) != 0 {
- capfmt = format!("{} Scalable", capfmt);
- }
- out = format!("{} ({})", out, capfmt);
- }
- write!(f, "{}", out)
- }
-}
-
-macro_rules! desc {
- (video; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: 0 }
- });
- (video; $n:expr, $fn:expr, $c:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: $c }
- });
- (video-ll; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
- });
- (video-llp; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: CODEC_CAP_LOSSLESS }
- });
- (video-im; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: CODEC_CAP_INTRAONLY }
- });
- (video-modern; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Video,
- caps: CODEC_CAP_REORDER | CODEC_CAP_HYBRID }
- });
- (audio; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
- caps: 0 }
- });
- (audio-ll; $n:expr, $fn:expr) => ({
- CodecDescription{ name: $n, fname: $fn, ctype: CodecType::Audio,
- caps: CODEC_CAP_LOSSLESS | CODEC_CAP_INTRAONLY }
- });
-}
-
-/// Returns codec description for the provided codec short name if it is found.
-pub fn get_codec_description(name: &str) -> Option<&'static CodecDescription> {
- for reg in CODEC_REGISTER {
- if reg.name == name {
- return Some(reg);
- }
- }
- None
-}
-
-static CODEC_REGISTER: &'static [CodecDescription] = &[
- desc!(audio-ll; "pcm", "PCM"),
-
- desc!(video-im; "indeo1", "Intel Raw IF09"),
- desc!(video-im; "indeo2", "Intel Indeo 2"),
- desc!(video; "indeo3", "Intel Indeo 3"),
- desc!(video; "indeo4", "Intel Indeo 4", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
- desc!(video; "indeo5", "Intel Indeo 5", CODEC_CAP_REORDER | CODEC_CAP_SCALABLE),
- desc!(video; "intel263", "Intel I263", CODEC_CAP_REORDER),
- desc!(audio; "iac", "Intel Indeo audio"),
- desc!(audio; "imc", "Intel Music Coder"),
-
- desc!(video; "realvideo1", "Real Video 1"),
- desc!(video; "realvideo2", "Real Video 2"),
- desc!(video; "realvideo3", "Real Video 3", CODEC_CAP_REORDER),
- desc!(video; "realvideo4", "Real Video 4", CODEC_CAP_REORDER),
- desc!(video; "realvideo6", "Real Video 6", CODEC_CAP_REORDER),
- desc!(video; "clearvideo", "ClearVideo"),
- desc!(video; "clearvideo_rm", "ClearVideo"),
- desc!(audio; "ra14.4", "RealAudio 14.4"),
- desc!(audio; "ra28.8", "RealAudio 28.8"),
- desc!(audio; "cook", "RealAudio Cooker"),
- desc!(audio; "ralf", "RealAudio Lossless"),
- desc!(audio; "aac", "AAC"),
- desc!(audio; "ac3", "ETSI TS 102 366"),
- desc!(audio; "atrac3", "Sony Atrac3"),
- desc!(audio; "sipro", "Sipro Labs ADPCM"),
-
- desc!(video; "truemotion1", "TrueMotion 1"),
- desc!(video-im; "truemotionrt", "TrueMotion RT"),
- desc!(video; "truemotion2", "TrueMotion 2"),
- desc!(video; "truemotion2x", "TrueMotion 2X"),
- desc!(video; "vp3", "VP3"),
- desc!(video; "vp4", "VP4"),
- desc!(video; "vp5", "VP5"),
- desc!(video; "vp6", "VP6"),
- desc!(video; "vp6a", "VP6"),
- desc!(video; "vp7", "VP7"),
- desc!(video; "vp8", "VP8"),
- desc!(video; "vp9", "VP9"),
- desc!(audio; "adpcm-dk3", "Duck DK3 ADPCM"),
- desc!(audio; "adpcm-dk4", "Duck DK4 ADPCM"),
- desc!(audio; "on2avc-500", "On2 AVC"),
- desc!(audio; "on2avc-501", "On2 AVC"),
-
- desc!(video; "gdv-video", "Gremlin Digital Video - video"),
- desc!(audio; "gdv-audio", "Gremlin Digital Video - audio"),
- desc!(video; "bmv-video", "BMV video"),
- desc!(audio; "bmv-audio", "BMV audio"),
- desc!(video; "bmv3-video", "DW Noir BMV video"),
- desc!(audio; "bmv3-audio", "DW Noir BMV audio"),
- desc!(video; "midivid", "MidiVid"),
- desc!(video; "midivid3", "MidiVid 3"),
- desc!(video-ll; "midivid-ll", "MidiVid Lossless"),
- desc!(video; "vmd-video", "VMD video"),
- desc!(audio; "vmd-audio", "VMD audio"),
-
- desc!(video; "smacker-video", "Smacker video"),
- desc!(audio; "smacker-audio", "Smacker audio"),
- desc!(video; "bink-video", "Bink video"),
- desc!(video; "bink2-video", "Bink2 video"),
- desc!(audio; "bink-audio-dct", "Bink audio (DCT)"),
- desc!(audio; "bink-audio-rdft", "Bink audio (RDFT)"),
-];
-
-static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[
- (b"IF09", "indeo1"),
- (b"RT21", "indeo2"),
- (b"IV31", "indeo3"),
- (b"IV32", "indeo3"),
- (b"IV41", "indeo4"),
- (b"IV50", "indeo5"),
- (b"I263", "intel263"),
-
- (b"UCOD", "clearvideo"),
-
- (b"MVDV", "midivid"),
- (b"MV30", "midivid3"),
- (b"MVLZ", "midivid-ll"),
-
- (b"DUCK", "truemotion1"),
- (b"TR20", "truemotionrt"),
- (b"TM20", "truemotion2"),
- (b"TM2A", "truemotion2x"),
- (b"TM2X", "truemotion2x"),
- (b"VP30", "vp3"),
- (b"VP31", "vp3"),
- (b"VP40", "vp4"),
- (b"VP50", "vp5"),
- (b"VP60", "vp6"),
- (b"VP61", "vp6"),
- (b"VP62", "vp6"),
- (b"VP6A", "vp6a"),
- (b"VP70", "vp7"),
-];
-
-static WAV_CODEC_REGISTER: &'static [(u16, &str)] = &[
- (0x0000, "pcm"),
- (0x0001, "pcm"),
- (0x0003, "pcm"),
- (0x0061, "adpcm-dk4"),
- (0x0062, "adpcm-dk3"),
- (0x0401, "imc"),
- (0x0402, "iac"),
- (0x0500, "on2avc-500"),
- (0x0501, "on2avc-501"),
-];
-
-/// Returns video codec short name for provided FOURCC (used in AVI format).
-pub fn find_codec_from_avi_fourcc(fcc: &[u8;4]) -> Option<&'static str> {
- for (fourcc, name) in AVI_VIDEO_CODEC_REGISTER.iter() {
- if *fourcc == fcc { return Some(name); }
- }
- None
-}
-
-/// Returns known audio codec short name for provided TWOCC (used in WAV and AVI format).
-pub fn find_codec_from_wav_twocc(tcc: u16) -> Option<&'static str> {
- for (twocc, name) in WAV_CODEC_REGISTER.iter() {
- if *twocc == tcc { return Some(name); }
- }
- None
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn test_register() {
- let c1 = find_codec_from_avi_fourcc(b"IV41").unwrap();
- let c2 = find_codec_from_wav_twocc(0x401).unwrap();
- println!("found {} and {}", c1, c2);
- let cd1 = get_codec_description(c1).unwrap();
- let cd2 = get_codec_description(c2).unwrap();
- println!("got {} and {}", cd1, cd2);
- }
-}