1 use nihav_core::muxers::*;
4 bw: &'a mut ByteWriter<'a>,
13 impl<'a> FLACMuxer<'a> {
14 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
17 maxpkt: std::usize::MAX, minpkt: 0,
18 maxblk: std::u16::MAX, minblk: 0,
25 impl<'a> MuxCore<'a> for FLACMuxer<'a> {
26 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
27 if strmgr.get_num_streams() == 0 {
28 return Err(MuxerError::InvalidArgument);
30 let stream = strmgr.get_stream(0).unwrap();
31 if let NACodecTypeInfo::Audio(ref ainfo) = stream.get_info().get_properties() {
32 self.bw.write_buf(b"fLaC")?;
33 self.bw.write_byte(0x80)?; // last metadata block - streaminfo
34 self.bw.write_u24be(34)?; // streaminfo size
35 self.bw.write_u16be(2)?; // minimum block size
36 self.bw.write_u16be(ainfo.block_len as u16)?;
37 self.bw.write_u24be(0)?; // minimum frame size
38 self.bw.write_u24be(0)?; // maximum frame size
40 let bits = ainfo.format.bits - 1;
42 self.bw.write_u24be(ainfo.sample_rate * 16 + u32::from(ainfo.channels - 1) * 2 + u32::from(bits >> 4))?;
43 self.bw.write_byte(bits << 4)?;
44 self.bw.write_u32be(0)?;//total samples low 32 bits
45 self.bw.write_u64be(0)?;self.bw.write_u64be(0)?; //MD5
49 Err(MuxerError::InvalidArgument)
52 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
53 let pktlen = pkt.get_buffer().len();
54 let slen = pkt.ts.duration.unwrap_or(0);
55 let samples = if slen != 1 { slen } else { u64::from(pkt.ts.tb_den) };
57 self.maxpkt = self.maxpkt.max(pktlen);
58 self.minpkt = self.minpkt.min(pktlen);
59 self.maxblk = self.maxblk.max(samples as u16);
60 self.minblk = self.minblk.min(samples as u16);
61 self.duration += samples;
63 self.bw.write_buf(&pkt.get_buffer())?;
66 fn flush(&mut self) -> MuxerResult<()> {
69 fn end(&mut self) -> MuxerResult<()> {
70 //todo: write MD5 somehow?
71 self.bw.seek(SeekFrom::Start(8))?;
72 self.bw.write_u16be(self.minblk)?;
73 self.bw.write_u16be(self.maxblk)?;
74 self.bw.write_u24be(self.minpkt as u32)?;
75 self.bw.write_u24be(self.maxpkt as u32)?;
76 self.bw.seek(SeekFrom::Current(3))?;
77 self.bw.write_byte((self.bits << 4) | (((self.duration >> 32) as u8) & 0xF))?;
78 self.bw.write_u32be(self.duration as u32)?;
83 impl<'a> NAOptionHandler for FLACMuxer<'a> {
84 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
85 fn set_options(&mut self, _options: &[NAOption]) { }
86 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
89 pub struct FLACMuxerCreator {}
91 impl MuxerCreator for FLACMuxerCreator {
92 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
93 Box::new(FLACMuxer::new(bw))
95 fn get_name(&self) -> &'static str { "flac" }
96 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::SingleAudio("flac") }
101 use nihav_core::codecs::*;
102 use nihav_core::demuxers::*;
103 use nihav_core::muxers::*;
104 use nihav_codec_support::test::enc_video::*;
108 fn test_flac_muxer() {
109 let mut dmx_reg = RegisteredDemuxers::new();
110 llaudio_register_all_demuxers(&mut dmx_reg);
111 // sample: https://samples.mplayerhq.hu/A-codecs/lossless/luckynight.flac
112 let dec_config = DecoderTestParams {
114 in_name: "assets/LLaudio/luckynight.flac",
116 stream_type: StreamType::None,
117 dmx_reg, dec_reg: RegisteredDecoders::new(),
119 let mut mux_reg = RegisteredMuxers::new();
120 llaudio_register_all_muxers(&mut mux_reg);
121 /* let enc_config = EncoderTestParams {
124 out_name: "muxed.flac",
125 mux_reg, enc_reg: RegisteredEncoders::new(),
127 test_remuxing(&dec_config, &enc_config);*/
128 test_remuxing_md5(&dec_config, "flac", &mux_reg,
129 [0x77afb7c0, 0x84d2bd87, 0x6e028092, 0x7db7c72e]);