]>
Commit | Line | Data |
---|---|---|
38953fb5 KS |
1 | use nihav_core::formats::*; |
2 | use nihav_core::codecs::*; | |
f5c54c10 | 3 | use nihav_core::io::byteio::*; |
3234da61 KS |
4 | |
5 | struct PCMDecoder { chmap: NAChannelMap } | |
6 | ||
7 | impl PCMDecoder { | |
8 | fn new() -> Self { | |
9 | PCMDecoder { chmap: NAChannelMap::new() } | |
10 | } | |
11 | } | |
12 | ||
13 | const CHMAP_MONO: [NAChannelType; 1] = [NAChannelType::C]; | |
14 | const CHMAP_STEREO: [NAChannelType; 2] = [NAChannelType::L, NAChannelType::R]; | |
15 | ||
16 | fn get_default_chmap(nch: u8) -> NAChannelMap { | |
17 | let mut chmap = NAChannelMap::new(); | |
18 | match nch { | |
19 | 1 => chmap.add_channels(&CHMAP_MONO), | |
20 | 2 => chmap.add_channels(&CHMAP_STEREO), | |
21 | _ => (), | |
22 | } | |
23 | chmap | |
24 | } | |
25 | ||
12ccce74 | 26 | fn get_duration(ainfo: &NAAudioInfo, duration: Option<u64>, data_size: usize) -> u64 { |
3234da61 | 27 | if duration == None { |
12ccce74 | 28 | let size_bits = (data_size as u64) * 8; |
c83013a1 | 29 | let blk_size = u64::from(ainfo.get_channels()) * u64::from(ainfo.get_format().get_bits()); |
3234da61 KS |
30 | size_bits / blk_size |
31 | } else { | |
c83013a1 | 32 | duration.unwrap() |
3234da61 KS |
33 | } |
34 | } | |
35 | ||
36 | impl NADecoder for PCMDecoder { | |
01613464 | 37 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
3234da61 | 38 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { |
3234da61 KS |
39 | self.chmap = get_default_chmap(ainfo.get_channels()); |
40 | if self.chmap.num_channels() == 0 { return Err(DecoderError::InvalidData); } | |
41 | Ok(()) | |
42 | } else { | |
43 | Err(DecoderError::InvalidData) | |
44 | } | |
45 | } | |
01613464 | 46 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
3234da61 KS |
47 | let info = pkt.get_stream().get_info(); |
48 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
49 | let duration = get_duration(&ainfo, pkt.get_duration(), pkt.get_buffer().len()); | |
3234da61 | 50 | let pktbuf = pkt.get_buffer(); |
1a967e6b | 51 | let abuf = NAAudioBuffer::new_from_buf(ainfo, pktbuf, self.chmap.clone()); |
3234da61 | 52 | let mut frm = NAFrame::new_from_pkt(pkt, info, NABufferType::AudioPacked(abuf)); |
12ccce74 | 53 | frm.set_duration(Some(duration)); |
3234da61 | 54 | frm.set_keyframe(true); |
171860fc | 55 | Ok(frm.into_ref()) |
3234da61 KS |
56 | } else { |
57 | Err(DecoderError::InvalidData) | |
58 | } | |
59 | } | |
f9be4e75 KS |
60 | fn flush(&mut self) { |
61 | } | |
3234da61 KS |
62 | } |
63 | ||
7d57ae2f KS |
64 | impl NAOptionHandler for PCMDecoder { |
65 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
66 | fn set_options(&mut self, _options: &[NAOption]) { } | |
67 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
68 | } | |
69 | ||
08a1fab7 | 70 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
3234da61 KS |
71 | Box::new(PCMDecoder::new()) |
72 | } | |
f5c54c10 KS |
73 | |
74 | struct PCMEncoder { | |
75 | stream: Option<NAStreamRef>, | |
76 | pkt: Option<NAPacket>, | |
77 | } | |
78 | ||
79 | impl PCMEncoder { | |
80 | fn new() -> Self { | |
81 | PCMEncoder { | |
82 | stream: None, | |
83 | pkt: None, | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
88 | macro_rules! write_buffer { | |
89 | ($abuf: expr, $dvec: expr, $write_be: ident, $write_le: ident, $dtype: tt) => { | |
90 | let info = $abuf.get_info(); | |
91 | let len = $abuf.get_length(); | |
92 | let data = $abuf.get_data(); | |
93 | let channels = $abuf.get_chmap().num_channels(); | |
94 | let stride = $abuf.get_stride(); | |
95 | let step = $abuf.get_step(); | |
96 | let is_be = info.format.be; | |
97 | ||
98 | $dvec = vec![0u8; len * channels * std::mem::size_of::<$dtype>()]; | |
99 | let mut mw = MemoryWriter::new_write($dvec.as_mut_slice()); | |
100 | let mut bw = ByteWriter::new(&mut mw); | |
101 | for off in 0..len { | |
102 | for j in 0..channels { | |
103 | if is_be { | |
104 | bw.$write_be(data[off * step + j * stride] as $dtype).unwrap(); | |
105 | } else { | |
106 | bw.$write_le(data[off * step + j * stride] as $dtype).unwrap(); | |
107 | } | |
108 | } | |
109 | } | |
110 | } | |
111 | } | |
112 | ||
113 | impl NAEncoder for PCMEncoder { | |
114 | fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> { | |
115 | match encinfo.format { | |
116 | NACodecTypeInfo::None => { | |
117 | let mut ofmt = EncodeParameters::default(); | |
118 | ofmt.format = NACodecTypeInfo::Audio(NAAudioInfo::new(0, 0, SND_S16P_FORMAT, 0)); | |
119 | Ok(ofmt) | |
120 | }, | |
121 | NACodecTypeInfo::Video(_) => return Err(EncoderError::FormatError), | |
122 | NACodecTypeInfo::Audio(_) => { | |
123 | Ok(*encinfo) | |
124 | } | |
125 | } | |
126 | } | |
127 | fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> { | |
128 | match encinfo.format { | |
129 | NACodecTypeInfo::None => Err(EncoderError::FormatError), | |
130 | NACodecTypeInfo::Video(_) => Err(EncoderError::FormatError), | |
131 | NACodecTypeInfo::Audio(_) => { | |
132 | let info = NACodecInfo::new("pcm", encinfo.format, None); | |
133 | let mut stream = NAStream::new(StreamType::Audio, stream_id, info, encinfo.tb_num, encinfo.tb_den); | |
134 | stream.set_num(stream_id as usize); | |
135 | let stream = stream.into_ref(); | |
136 | self.stream = Some(stream.clone()); | |
137 | Ok(stream) | |
138 | } | |
139 | } | |
140 | } | |
141 | fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> { | |
142 | let buf = frm.get_buffer(); | |
143 | let mut dbuf; | |
144 | match buf { | |
145 | NABufferType::AudioU8(ref abuf) => { | |
146 | let stride = abuf.get_stride(); | |
147 | if stride == 1 { // packed already | |
148 | self.pkt = Some(NAPacket::new_from_refbuf(self.stream.clone().unwrap(), frm.ts, true, abuf.get_data_ref())); | |
149 | return Ok(()); | |
150 | } | |
151 | let len = abuf.get_length(); | |
152 | let data = abuf.get_data(); | |
153 | let channels = abuf.get_chmap().num_channels(); | |
154 | dbuf = Vec::with_capacity(len * channels); | |
155 | for off in 0..len { | |
156 | for j in 0..channels { | |
157 | dbuf.push(data[off + j * stride]); | |
158 | } | |
159 | } | |
160 | }, | |
161 | NABufferType::AudioI16(ref abuf) => { | |
162 | write_buffer!(abuf, dbuf, write_u16be, write_u16le, u16); | |
163 | }, | |
164 | NABufferType::AudioI32(ref abuf) => { | |
165 | write_buffer!(abuf, dbuf, write_u32be, write_u32le, u32); | |
166 | }, | |
167 | NABufferType::AudioF32(ref abuf) => { | |
168 | write_buffer!(abuf, dbuf, write_f32be, write_f32le, f32); | |
169 | }, | |
170 | NABufferType::AudioPacked(ref abuf) => { | |
171 | self.pkt = Some(NAPacket::new_from_refbuf(self.stream.clone().unwrap(), frm.ts, true, abuf.get_data_ref())); | |
172 | return Ok(()); | |
173 | }, | |
174 | NABufferType::None => { | |
175 | self.pkt = None; | |
176 | return Ok(()); | |
177 | }, | |
178 | _ => return Err(EncoderError::FormatError), | |
179 | }; | |
180 | self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, true, dbuf)); | |
181 | Ok(()) | |
182 | } | |
183 | fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> { | |
184 | let mut npkt = None; | |
185 | std::mem::swap(&mut self.pkt, &mut npkt); | |
186 | Ok(npkt) | |
187 | } | |
188 | fn flush(&mut self) -> EncoderResult<()> { | |
189 | Ok(()) | |
190 | } | |
191 | } | |
192 | ||
193 | impl NAOptionHandler for PCMEncoder { | |
194 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
195 | fn set_options(&mut self, _options: &[NAOption]) { } | |
196 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
197 | } | |
198 | ||
199 | pub fn get_encoder() -> Box<dyn NAEncoder + Send> { | |
200 | Box::new(PCMEncoder::new()) | |
201 | } |