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