remove trailing whitespaces
[nihav.git] / nihav-codec-support / src / test / enc_video.rs
index 1240e836d9587552d03d239488fff1bfdbc29d4c..4a258de07863ef7f185647ad16c8e55f413fd6a1 100644 (file)
@@ -1,3 +1,4 @@
+//! Routines for testing encoders and muxers.
 use std::fs::File;
 use nihav_core::frame::*;
 use nihav_core::codecs::*;
@@ -5,24 +6,210 @@ use nihav_core::demuxers::*;
 use nihav_core::muxers::*;
 use nihav_core::scale::*;
 use nihav_core::soundcvt::*;
+use super::md5::MD5;
 
+/// Parameters for the source used in the test.
 pub struct DecoderTestParams {
+    /// Demuxer name e.g. `"mov"`.
     pub demuxer:        &'static str,
+    /// Input file name.
     pub in_name:        &'static str,
+    /// Timestamp for last decoded frame.
     pub limit:          Option<u64>,
+    /// Desired input stream type (that will be decoded and fed to the encoder).
     pub stream_type:    StreamType,
+    /// Registered demuxers.
     pub dmx_reg:        RegisteredDemuxers,
+    /// Registered decoders.
     pub dec_reg:        RegisteredDecoders,
 }
 
+/// Parameters for the encoding test output.
 pub struct EncoderTestParams {
+    /// Muxer name e.g. `"avi"`.
     pub muxer:          &'static str,
+    /// Encoder name.
     pub enc_name:       &'static str,
+    /// Output file name.
     pub out_name:       &'static str,
+    /// Registered muxers.
     pub mux_reg:        RegisteredMuxers,
+    /// Registered encoders.
     pub enc_reg:        RegisteredEncoders,
 }
 
+/// Tests muxer by making it mux raw streams from the input file.
+///
+/// Streams not fitting the output profile (e.g. a video stream or a second audio stream for WAV muxer) will be ignored.
+pub fn test_remuxing(dec_config: &DecoderTestParams, enc_config: &EncoderTestParams) {
+    let dmx_f = dec_config.dmx_reg.find_demuxer(dec_config.demuxer).unwrap();
+    let mut file = File::open(dec_config.in_name).unwrap();
+    let mut fr = FileReader::new_read(&mut file);
+    let mut br = ByteReader::new(&mut fr);
+    let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
+
+    let mux_f = enc_config.mux_reg.find_muxer(enc_config.muxer).unwrap();
+    let out_name = "assets/test_out/".to_owned() + enc_config.out_name;
+    let file = File::create(&out_name).unwrap();
+    let mut fw = FileWriter::new_write(file);
+    let mut bw = ByteWriter::new(&mut fw);
+    let mut out_sm = StreamManager::new();
+    let mux_caps = mux_f.get_capabilities();
+    let mut stream_map: Vec<Option<usize>> = Vec::new();
+    let mut has_video = false;
+    let mut has_audio = false;
+    for stream in dmx.get_streams() {
+        let mut copy_stream = false;
+        match mux_caps {
+            MuxerCapabilities::SingleVideo(_) | MuxerCapabilities::OnlyVideo => {
+                copy_stream = stream.get_media_type() == StreamType::Video;
+                has_video = true;
+            },
+            MuxerCapabilities::SingleAudio(_) | MuxerCapabilities::OnlyAudio => {
+                copy_stream = stream.get_media_type() == StreamType::Audio;
+                has_audio = true;
+            },
+            MuxerCapabilities::SingleVideoAndAudio(_, _) => {
+                if stream.get_media_type() == StreamType::Video {
+                    copy_stream = !has_video;
+                    has_video = true;
+                }
+                if stream.get_media_type() == StreamType::Audio {
+                    copy_stream = !has_audio;
+                    has_audio = true;
+                }
+            },
+            MuxerCapabilities::Universal => {
+                if stream.get_media_type() == StreamType::Video {
+                    copy_stream = true;
+                    has_video = true;
+                }
+                if stream.get_media_type() == StreamType::Audio {
+                    copy_stream = true;
+                    has_audio = true;
+                }
+            }
+        };
+        if copy_stream {
+            let streamno = out_sm.add_stream(NAStream::clone(&stream)).unwrap();
+            stream_map.push(Some(streamno));
+            match mux_caps {
+                MuxerCapabilities::SingleVideo(_) | MuxerCapabilities::SingleAudio(_) => break,
+                _ => {},
+            };
+        } else {
+            stream_map.push(None);
+        }
+    }
+    assert!(out_sm.get_num_streams() > 0);
+    let mut mux = create_muxer(mux_f, out_sm, &mut bw).unwrap();
+
+    loop {
+        let pktres = dmx.get_frame();
+        if let Err(e) = pktres {
+            if e == DemuxerError::EOF { break; }
+            panic!("error");
+        }
+        let mut pkt = pktres.unwrap();
+        println!("Got {}", pkt);
+        if let Some(new_id) = stream_map[pkt.get_stream().id as usize] {
+            pkt.reassign(mux.get_stream(new_id).unwrap(), pkt.get_time_information());
+            mux.mux_frame(pkt).unwrap();
+        }
+    }
+
+    mux.end().unwrap();
+}
+
+/// Tests muxer by making it mux raw streams from the input file and comparing MD5 hash of the result to the provided one.
+///
+/// Streams not fitting the output profile (e.g. a video stream or a second audio stream for WAV muxer) will be ignored.
+pub fn test_remuxing_md5(dec_config: &DecoderTestParams, muxer: &str, mux_reg: &RegisteredMuxers, md5_hash: [u32; 4]) {
+    let dmx_f = dec_config.dmx_reg.find_demuxer(dec_config.demuxer).unwrap();
+    let mut file = File::open(dec_config.in_name).unwrap();
+    let mut fr = FileReader::new_read(&mut file);
+    let mut br = ByteReader::new(&mut fr);
+    let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
+
+    let mux_f = mux_reg.find_muxer(muxer).unwrap();
+
+    let mut dst = Vec::with_capacity(1048576);
+    let mut gw = GrowableMemoryWriter::new_write(&mut dst);
+    let mut bw = ByteWriter::new(&mut gw);
+    let mut out_sm = StreamManager::new();
+    let mux_caps = mux_f.get_capabilities();
+    let mut stream_map: Vec<Option<usize>> = Vec::new();
+    let mut has_video = false;
+    let mut has_audio = false;
+    for stream in dmx.get_streams() {
+        let mut copy_stream = false;
+        match mux_caps {
+            MuxerCapabilities::SingleVideo(_) | MuxerCapabilities::OnlyVideo => {
+                copy_stream = stream.get_media_type() == StreamType::Video;
+                has_video = true;
+            },
+            MuxerCapabilities::SingleAudio(_) | MuxerCapabilities::OnlyAudio => {
+                copy_stream = stream.get_media_type() == StreamType::Audio;
+                has_audio = true;
+            },
+            MuxerCapabilities::SingleVideoAndAudio(_, _) => {
+                if stream.get_media_type() == StreamType::Video {
+                    copy_stream = !has_video;
+                    has_video = true;
+                }
+                if stream.get_media_type() == StreamType::Audio {
+                    copy_stream = !has_audio;
+                    has_audio = true;
+                }
+            },
+            MuxerCapabilities::Universal => {
+                if stream.get_media_type() == StreamType::Video {
+                    copy_stream = true;
+                    has_video = true;
+                }
+                if stream.get_media_type() == StreamType::Audio {
+                    copy_stream = true;
+                    has_audio = true;
+                }
+            }
+        };
+        if copy_stream {
+            let streamno = out_sm.add_stream(NAStream::clone(&stream)).unwrap();
+            stream_map.push(Some(streamno));
+            match mux_caps {
+                MuxerCapabilities::SingleVideo(_) | MuxerCapabilities::SingleAudio(_) => break,
+                _ => {},
+            };
+        } else {
+            stream_map.push(None);
+        }
+    }
+    assert!(out_sm.get_num_streams() > 0);
+    let mut mux = create_muxer(mux_f, out_sm, &mut bw).unwrap();
+
+    loop {
+        let pktres = dmx.get_frame();
+        if let Err(e) = pktres {
+            if e == DemuxerError::EOF { break; }
+            panic!("error");
+        }
+        let mut pkt = pktres.unwrap();
+        println!("Got {}", pkt);
+        if let Some(new_id) = stream_map[pkt.get_stream().id as usize] {
+            pkt.reassign(mux.get_stream(new_id).unwrap(), pkt.get_time_information());
+            mux.mux_frame(pkt).unwrap();
+        }
+    }
+
+    mux.end().unwrap();
+
+    let mut hash = [0; 4];
+    MD5::calculate_hash(dst.as_slice(), &mut hash);
+    println!("output hash {:08x}{:08x}{:08x}{:08x}", hash[0], hash[1], hash[2], hash[3]);
+    assert_eq!(hash, md5_hash);
+}
+
+/// Tests an encoder by decoding a stream from input file, feeding it to the encoder and muxing the result into output file.
 pub fn test_encoding_to_file(dec_config: &DecoderTestParams, enc_config: &EncoderTestParams, mut enc_params: EncodeParameters) {
     let dmx_f = dec_config.dmx_reg.find_demuxer(dec_config.demuxer).unwrap();
     let mut file = File::open(dec_config.in_name).unwrap();
@@ -71,7 +258,7 @@ pub fn test_encoding_to_file(dec_config: &DecoderTestParams, enc_config: &Encode
     let mut encoder = (encfunc)();
     let out_str = encoder.init(0, enc_params).unwrap();
     out_sm.add_stream(NAStream::clone(&out_str));
-    
+
     let mux_f = enc_config.mux_reg.find_muxer(enc_config.muxer).unwrap();
     let out_name = "assets/test_out/".to_owned() + enc_config.out_name;
     let file = File::create(&out_name).unwrap();