]> git.nihav.org Git - nihav.git/blame - nihav-commonfmt/src/muxers/wav.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-commonfmt / src / muxers / wav.rs
CommitLineData
db2b1e6c
KS
1use nihav_core::muxers::*;
2use nihav_registry::register::*;
3
4struct WAVMuxer<'a> {
5 bw: &'a mut ByteWriter<'a>,
6 data_pos: u64,
7}
8
9impl<'a> WAVMuxer<'a> {
10 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
11 Self {
12 bw,
13 data_pos: 0,
14 }
15 }
16}
17
18fn patch_size(bw: &mut ByteWriter, pos: u64) -> MuxerResult<()> {
19 let size = bw.tell() - pos;
20 bw.seek(SeekFrom::Current(-((size + 4) as i64)))?;
21 bw.write_u32le(size as u32)?;
22 bw.seek(SeekFrom::End(0))?;
23 Ok(())
24}
25
26impl<'a> MuxCore<'a> for WAVMuxer<'a> {
27 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
28 if strmgr.get_num_streams() != 1 {
29 return Err(MuxerError::InvalidArgument);
30 }
31
32 let stream = strmgr.get_stream(0).unwrap();
33
34 if stream.get_info().get_properties().get_audio_info().is_none() {
35 return Err(MuxerError::InvalidArgument);
36 }
37 let ainfo = stream.get_info().get_properties().get_audio_info().unwrap();
38
39 let edata_len = if let Some(ref buf) = stream.get_info().get_extradata() { buf.len() } else { 0 };
40 if edata_len >= (1 << 16) {
41 return Err(MuxerError::UnsupportedFormat);
42 }
43
44 let twocc = find_wav_twocc(stream.get_info().get_name());
45 if twocc.is_none() {
46 return Err(MuxerError::UnsupportedFormat);
47 }
48 let twocc = if stream.get_info().get_name() == "pcm" {
49 if !ainfo.format.float { 0x0001 } else { 0x0003 }
50 } else {
51 twocc.unwrap_or(0)
52 };
53 let avg_bytes_per_sec = if stream.get_info().get_name() == "pcm" {
61cab15b 54 (u32::from(ainfo.channels) * ainfo.sample_rate * u32::from(ainfo.format.bits)) >> 3
db2b1e6c
KS
55 } else {
56 0
57 };
58
59 self.bw.write_buf(b"RIFF\0\0\0\0WAVEfmt ")?;
60 self.bw.write_u32le(if edata_len == 0 { 16 } else { 18 + edata_len } as u32)?;
61 self.bw.write_u16le(twocc)?;
61cab15b 62 self.bw.write_u16le(u16::from(ainfo.channels))?;
db2b1e6c
KS
63 self.bw.write_u32le(ainfo.sample_rate)?;
64 self.bw.write_u32le(avg_bytes_per_sec)?;
7722cca1
KS
65 if stream.get_info().get_name() != "pcm" || ainfo.block_len > 0 {
66 self.bw.write_u16le(ainfo.block_len as u16)?;
67 } else {
68 self.bw.write_u16le(u16::from(ainfo.channels) * u16::from(ainfo.format.bits) >> 3)?;
69 }
61cab15b 70 self.bw.write_u16le(u16::from(ainfo.format.bits))?;
db2b1e6c
KS
71 if let Some(ref buf) = stream.get_info().get_extradata() {
72 self.bw.write_u16le(edata_len as u16)?;
73 self.bw.write_buf(buf.as_slice())?;
74 }
75 self.bw.write_buf(b"data\0\0\0\0")?;
76 self.data_pos = self.bw.tell();
77
78 Ok(())
79 }
80 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
81 if self.data_pos == 0 {
82 return Err(MuxerError::NotCreated);
83 }
84
85 let stream = pkt.get_stream();
86 if stream.get_num() != 0 {
87 return Err(MuxerError::UnsupportedFormat);
88 }
89
90 self.bw.write_buf(pkt.get_buffer().as_slice())?;
91 Ok(())
92 }
93 fn flush(&mut self) -> MuxerResult<()> {
94 Ok(())
95 }
96 fn end(&mut self) -> MuxerResult<()> {
6f263099
KS
97 patch_size(self.bw, self.data_pos)?;
98 patch_size(self.bw, 8)?;
db2b1e6c
KS
99 // todo patch avg_bytes_per_second if calculated
100 // todo write fact value if calculated
101 Ok(())
102 }
103}
104
dc80f48e
KS
105impl<'a> NAOptionHandler for WAVMuxer<'a> {
106 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
107 fn set_options(&mut self, _options: &[NAOption]) { }
108 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
109}
110
db2b1e6c
KS
111pub struct WAVMuxerCreator {}
112
113impl MuxerCreator for WAVMuxerCreator {
114 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
115 Box::new(WAVMuxer::new(bw))
116 }
117 fn get_name(&self) -> &'static str { "wav" }
f0081142 118 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::SingleAudio("any") }
46008a8f 119 fn get_quirks(&self) -> MuxerQuirks { MuxerQuirks::new() }
db2b1e6c
KS
120}
121
122#[cfg(test)]
123mod test {
68e5a4ca 124 use nihav_core::codecs::*;
db2b1e6c 125 use nihav_core::demuxers::*;
68e5a4ca
KS
126 use nihav_core::muxers::*;
127 use nihav_codec_support::test::enc_video::*;
128 use crate::*;
db2b1e6c
KS
129
130 #[test]
131 fn test_wav_muxer() {
132 let mut dmx_reg = RegisteredDemuxers::new();
133 generic_register_all_demuxers(&mut dmx_reg);
886cde48 134 // sample: https://samples.mplayerhq.hu/V-codecs/RT21/320x240/laser05.avi
68e5a4ca
KS
135 let dec_config = DecoderTestParams {
136 demuxer: "avi",
137 in_name: "assets/Indeo/laser05.avi",
138 limit: None,
139 stream_type: StreamType::None,
140 dmx_reg, dec_reg: RegisteredDecoders::new(),
141 };
142 let mut mux_reg = RegisteredMuxers::new();
143 generic_register_all_muxers(&mut mux_reg);
144 /*let enc_config = EncoderTestParams {
145 muxer: "wav",
146 enc_name: "",
147 out_name: "muxed.wav",
148 mux_reg, enc_reg: RegisteredEncoders::new(),
149 };
150 test_remuxing(&dec_config, &enc_config);*/
151 test_remuxing_md5(&dec_config, "wav", &mux_reg,
152 [0x1040ebe8, 0xe7a43e84, 0x49fbe234, 0xe870b6b3]);
db2b1e6c
KS
153 }
154}