]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::formats::*; | |
2 | use nihav_core::codecs::*; | |
3 | use nihav_core::io::byteio::*; | |
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 | ||
26 | fn get_duration(ainfo: &NAAudioInfo, duration: Option<u64>, data_size: usize) -> u64 { | |
27 | if duration == None { | |
28 | let size_bits = (data_size as u64) * 8; | |
29 | let blk_size = u64::from(ainfo.get_channels()) * u64::from(ainfo.get_format().get_bits()); | |
30 | size_bits / blk_size | |
31 | } else { | |
32 | duration.unwrap() | |
33 | } | |
34 | } | |
35 | ||
36 | impl NADecoder for PCMDecoder { | |
37 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { | |
38 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
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 | } | |
46 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
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()); | |
50 | let pktbuf = pkt.get_buffer(); | |
51 | let abuf = NAAudioBuffer::new_from_buf(ainfo, pktbuf, self.chmap.clone()); | |
52 | let mut frm = NAFrame::new_from_pkt(pkt, info, NABufferType::AudioPacked(abuf)); | |
53 | frm.set_duration(Some(duration)); | |
54 | frm.set_keyframe(true); | |
55 | Ok(frm.into_ref()) | |
56 | } else { | |
57 | Err(DecoderError::InvalidData) | |
58 | } | |
59 | } | |
60 | fn flush(&mut self) { | |
61 | } | |
62 | } | |
63 | ||
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 | ||
70 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { | |
71 | Box::new(PCMDecoder::new()) | |
72 | } | |
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 | } |