| 1 | use nihav_core::formats::*; |
| 2 | use nihav_core::codecs::*; |
| 3 | |
| 4 | struct PCMDecoder { chmap: NAChannelMap } |
| 5 | |
| 6 | impl PCMDecoder { |
| 7 | fn new() -> Self { |
| 8 | PCMDecoder { chmap: NAChannelMap::new() } |
| 9 | } |
| 10 | } |
| 11 | |
| 12 | const CHMAP_MONO: [NAChannelType; 1] = [NAChannelType::C]; |
| 13 | const CHMAP_STEREO: [NAChannelType; 2] = [NAChannelType::L, NAChannelType::R]; |
| 14 | |
| 15 | fn get_default_chmap(nch: u8) -> NAChannelMap { |
| 16 | let mut chmap = NAChannelMap::new(); |
| 17 | match nch { |
| 18 | 1 => chmap.add_channels(&CHMAP_MONO), |
| 19 | 2 => chmap.add_channels(&CHMAP_STEREO), |
| 20 | _ => (), |
| 21 | } |
| 22 | chmap |
| 23 | } |
| 24 | |
| 25 | fn get_duration(ainfo: &NAAudioInfo, duration: Option<u64>, data_size: usize) -> u64 { |
| 26 | if duration == None { |
| 27 | let size_bits = (data_size as u64) * 8; |
| 28 | let blk_size = u64::from(ainfo.get_channels()) * u64::from(ainfo.get_format().get_bits()); |
| 29 | size_bits / blk_size |
| 30 | } else { |
| 31 | duration.unwrap() |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | impl NADecoder for PCMDecoder { |
| 36 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
| 37 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { |
| 38 | self.chmap = get_default_chmap(ainfo.get_channels()); |
| 39 | if self.chmap.num_channels() == 0 { return Err(DecoderError::InvalidData); } |
| 40 | Ok(()) |
| 41 | } else { |
| 42 | Err(DecoderError::InvalidData) |
| 43 | } |
| 44 | } |
| 45 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
| 46 | let info = pkt.get_stream().get_info(); |
| 47 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { |
| 48 | let duration = get_duration(&ainfo, pkt.get_duration(), pkt.get_buffer().len()); |
| 49 | let pktbuf = pkt.get_buffer(); |
| 50 | let abuf = NAAudioBuffer::new_from_buf(ainfo, pktbuf, self.chmap.clone()); |
| 51 | let mut frm = NAFrame::new_from_pkt(pkt, info, NABufferType::AudioPacked(abuf)); |
| 52 | frm.set_duration(Some(duration)); |
| 53 | frm.set_keyframe(true); |
| 54 | Ok(frm.into_ref()) |
| 55 | } else { |
| 56 | Err(DecoderError::InvalidData) |
| 57 | } |
| 58 | } |
| 59 | fn flush(&mut self) { |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | impl NAOptionHandler for PCMDecoder { |
| 64 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } |
| 65 | fn set_options(&mut self, _options: &[NAOption]) { } |
| 66 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } |
| 67 | } |
| 68 | |
| 69 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
| 70 | Box::new(PCMDecoder::new()) |
| 71 | } |