binkdmx: do not demux zero audio frames
[nihav.git] / nihav-rad / src / demuxers / bink.rs
CommitLineData
606c448e
KS
1use nihav_core::demuxers::*;
2use nihav_core::io::byteio::ByteReader;
3
c6c21059
KS
4struct AudioTrack {
5 id: usize,
6}
7
8const BINK_AUD_FLAG_DCT: u8 = 0x10;
9const BINK_AUD_FLAG_STEREO: u8 = 0x20;
10
11impl AudioTrack {
12 fn new(strmgr: &mut StreamManager, srate: u32, flags: u8, str_id: usize) -> DemuxerResult<Self> {
13 let channels = if (flags & BINK_AUD_FLAG_STEREO) != 0 { 2 } else { 1 };
14 let codecname = if (flags & BINK_AUD_FLAG_DCT) != 0 {
15 "bink-audio-dct"
16 } else {
17 "bink-audio-rdft"
18 };
19 let ahdr = NAAudioInfo::new(srate, channels, SND_F32P_FORMAT, 1);
20 let ainfo = NACodecInfo::new(codecname, NACodecTypeInfo::Audio(ahdr), None);
21 let res = strmgr.add_stream(NAStream::new(StreamType::Audio, (str_id + 1) as u32, ainfo, 1, srate));
22 validate!(res.is_some());
23 let id = res.unwrap();
24 Ok(Self{ id })
25 }
26}
27
28struct BinkDemuxer<'a> {
29 src: &'a mut ByteReader<'a>,
30 cur_frame: usize,
31 frames: usize,
32 video_id: usize,
33 tb_num: u32,
34 tb_den: u32,
35 ainfo: Vec<AudioTrack>,
36 queued_packets: Vec<NAPacket>,
37 frame_pos: Vec<u32>,
38}
39
40macro_rules! mktag {
41 ($a:expr, $b:expr, $c:expr, $d:expr) => ({
42 (($a as u32) << 24) | (($b as u32) << 16) | (($c as u32) << 8) | ($d as u32)
43 });
44 ($arr:expr) => ({
45 (($arr[0] as u32) << 24) | (($arr[1] as u32) << 16) | (($arr[2] as u32) << 8) | ($arr[3] as u32)
46 });
47}
48
49impl<'a> DemuxCore<'a> for BinkDemuxer<'a> {
50 fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
51 let src = &mut self.src;
52 let mut magic: [u8; 4] = [0; 4];
53 src.read_buf(&mut magic)?;
54 let magic_tag = mktag!(magic);
55 validate!((magic_tag >= mktag!(b"BIKb") && magic_tag <= mktag!(b"BIKk")) ||
56 (magic_tag >= mktag!(b"KB2a") && magic_tag <= mktag!(b"KB2k")));
57 let fsize = (src.read_u32le()? as usize) + 8;
58 self.frames = src.read_u32le()? as usize;
59 let max_size = src.read_u32le()? as usize;
60 let _frames2 = src.read_u32le()? as usize;
61 let width = src.read_u32le()? as usize;
62 let height = src.read_u32le()? as usize;
63 let tb_den = src.read_u32le()?;
64 let tb_num = src.read_u32le()?;
65 validate!((width > 0) && (height > 0) && (width <= 7680) && (height <= 4800));
66 validate!((self.frames > 0) && (tb_num > 0) && (tb_den > 0) && (max_size < fsize));
67 let mut flags: [u8; 4] = [0; 4];
68 src.read_buf(&mut flags)?;
69 let mut edata: Vec<u8> = Vec::with_capacity(8);
70 edata.resize(8, 0);
71 let p0 = &mut edata[0..4];
72 p0.copy_from_slice(&magic);
73 let p1 = &mut edata[4..][..4];
74 p1.copy_from_slice(&flags);
75 let vhdr = NAVideoInfo::new(width, height, false, YUV420_FORMAT);
76 let codec = if magic[0] == b'K' && magic[1] == b'B' && magic[2] == b'2' { "bink2-video" } else { "bink-video" };
77 let vinfo = NACodecInfo::new(codec, NACodecTypeInfo::Video(vhdr), Some(edata));
78 let res = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, self.tb_num, self.tb_den));
79 validate!(res.is_some());
80 self.video_id = res.unwrap();
81
82 let num_audio = src.read_u32le()? as usize;
83 validate!(num_audio < 256);
84 src.read_skip(num_audio * 4)?; // audio max output frame size?
85 self.ainfo = Vec::with_capacity(num_audio);
86 for i in 0..num_audio {
87 let srate = src.read_u24le()?;
88 let flags = src.read_byte()?;
89 validate!(srate > 0);
90 self.ainfo.push(AudioTrack::new(strmgr, srate, flags, i)?);
91 }
92 for _ in 0..num_audio {
93 let _trk_id = src.read_u32le()?;
94 }
95
96 self.frame_pos = Vec::with_capacity(self.frames + 1);
97 for _ in 0..self.frames+1 {
98 let pos = src.read_u32le()?;
99 self.frame_pos.push(pos);
100 }
101 validate!((src.tell() as u32) == (self.frame_pos[0] & !1));
102
103 self.cur_frame = 0;
104
105 Ok(())
106 }
107 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
108 if !self.queued_packets.is_empty() {
109 let pkt = self.queued_packets.pop().unwrap();
110 return Ok(pkt);
111 }
112 if self.cur_frame >= self.frames { return Err(DemuxerError::EOF); }
113 let mut payload_size = ((self.frame_pos[self.cur_frame + 1] & !1) - (self.frame_pos[self.cur_frame] & !1)) as usize;
114 validate!(payload_size > self.ainfo.len() * 4);
115 for atrk in self.ainfo.iter() {
116 let size = self.src.read_u32le()? as usize;
117 validate!(payload_size > size + 4);
118 payload_size -= size + 4;
119
5faa5676
KS
120 if size > 0 {
121 let strres = strmgr.get_stream(atrk.id);
122 validate!(strres.is_some());
123 let stream = strres.unwrap();
124 let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, self.tb_num, self.tb_den);
125 let pkt = self.src.read_packet(stream.clone(), ts, true, size)?;
126 self.queued_packets.push(pkt);
127 }
c6c21059
KS
128 }
129 self.queued_packets.reverse();
130
131 let strres = strmgr.get_stream(self.video_id);
132 validate!(strres.is_some());
133 let stream = strres.unwrap();
134 let keyframe = (self.frame_pos[self.cur_frame] & 1) != 0;
135 let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, self.tb_num, self.tb_den);
136 let pkt = self.src.read_packet(stream.clone(), ts, keyframe, payload_size)?;
137
138 self.cur_frame += 1;
139
140 Ok(pkt)
141 }
142 #[allow(unused_variables)]
143 fn seek(&mut self, time: u64) -> DemuxerResult<()> {
144 Err(DemuxerError::NotImplemented)
145 }
146}
147
148impl<'a> BinkDemuxer<'a> {
149 fn new(io: &'a mut ByteReader<'a>) -> Self {
150 Self {
151 src: io,
152 cur_frame: 0,
153 frames: 0,
154 video_id: 0,
155 tb_num: 0,
156 tb_den: 0,
157 ainfo: Vec::new(),
158 queued_packets: Vec::new(),
159 frame_pos: Vec::new(),
160 }
161 }
162}
163
164
606c448e
KS
165pub struct BinkDemuxerCreator { }
166
167impl DemuxerCreator for BinkDemuxerCreator {
168 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<DemuxCore<'a> + 'a> {
c6c21059 169 Box::new(BinkDemuxer::new(br))
606c448e
KS
170 }
171 fn get_name(&self) -> &'static str { "bink" }
172}
173
c6c21059
KS
174#[cfg(test)]
175mod test {
176 use super::*;
177 use std::fs::File;
178
179 #[test]
180 fn test_bink_demux() {
181 let mut file = File::open("assets/RAD/ActivisionLogo.bik").unwrap();
182// let mut file = File::open("assets/RAD/original.bik").unwrap();
183// let mut file = File::open("assets/RAD/Snd0a110c51.dee").unwrap();
184// let mut file = File::open("assets/RAD/NEW.BIK").unwrap();
185// let mut file = File::open("assets/RAD/ge_video_86l.bk2").unwrap();
186 let mut fr = FileReader::new_read(&mut file);
187 let mut br = ByteReader::new(&mut fr);
188 let mut dmx = BinkDemuxer::new(&mut br);
189 let mut sm = StreamManager::new();
190 dmx.open(&mut sm).unwrap();
191 loop {
192 let pktres = dmx.get_frame(&mut sm);
193 if let Err(e) = pktres {
194 if (e as i32) == (DemuxerError::EOF as i32) { break; }
195 panic!("error");
196 }
197 let pkt = pktres.unwrap();
198 println!("Got {}", pkt);
199 }
200 }
201}