e54ea8c7746bbbb81658dcdd3a238129c3afa6f2
[nihav.git] / nihav-rad / src / demuxers / bink.rs
1 use nihav_core::demuxers::*;
2 use nihav_core::io::byteio::ByteReader;
3
4 struct AudioTrack {
5 id: usize,
6 }
7
8 const BINK_AUD_FLAG_DCT: u8 = 0x10;
9 const BINK_AUD_FLAG_STEREO: u8 = 0x20;
10
11 impl 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
28 struct 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
40 macro_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
49 impl<'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
120 let strres = strmgr.get_stream(atrk.id);
121 validate!(strres.is_some());
122 let stream = strres.unwrap();
123 let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, self.tb_num, self.tb_den);
124 let pkt = self.src.read_packet(stream.clone(), ts, true, size)?;
125 self.queued_packets.push(pkt);
126 }
127 self.queued_packets.reverse();
128
129 let strres = strmgr.get_stream(self.video_id);
130 validate!(strres.is_some());
131 let stream = strres.unwrap();
132 let keyframe = (self.frame_pos[self.cur_frame] & 1) != 0;
133 let ts = NATimeInfo::new(Some(self.cur_frame as u64), None, None, self.tb_num, self.tb_den);
134 let pkt = self.src.read_packet(stream.clone(), ts, keyframe, payload_size)?;
135
136 self.cur_frame += 1;
137
138 Ok(pkt)
139 }
140 #[allow(unused_variables)]
141 fn seek(&mut self, time: u64) -> DemuxerResult<()> {
142 Err(DemuxerError::NotImplemented)
143 }
144 }
145
146 impl<'a> BinkDemuxer<'a> {
147 fn new(io: &'a mut ByteReader<'a>) -> Self {
148 Self {
149 src: io,
150 cur_frame: 0,
151 frames: 0,
152 video_id: 0,
153 tb_num: 0,
154 tb_den: 0,
155 ainfo: Vec::new(),
156 queued_packets: Vec::new(),
157 frame_pos: Vec::new(),
158 }
159 }
160 }
161
162
163 pub struct BinkDemuxerCreator { }
164
165 impl DemuxerCreator for BinkDemuxerCreator {
166 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<DemuxCore<'a> + 'a> {
167 Box::new(BinkDemuxer::new(br))
168 }
169 fn get_name(&self) -> &'static str { "bink" }
170 }
171
172 #[cfg(test)]
173 mod test {
174 use super::*;
175 use std::fs::File;
176
177 #[test]
178 fn test_bink_demux() {
179 let mut file = File::open("assets/RAD/ActivisionLogo.bik").unwrap();
180 // let mut file = File::open("assets/RAD/original.bik").unwrap();
181 // let mut file = File::open("assets/RAD/Snd0a110c51.dee").unwrap();
182 // let mut file = File::open("assets/RAD/NEW.BIK").unwrap();
183 // let mut file = File::open("assets/RAD/ge_video_86l.bk2").unwrap();
184 let mut fr = FileReader::new_read(&mut file);
185 let mut br = ByteReader::new(&mut fr);
186 let mut dmx = BinkDemuxer::new(&mut br);
187 let mut sm = StreamManager::new();
188 dmx.open(&mut sm).unwrap();
189 loop {
190 let pktres = dmx.get_frame(&mut sm);
191 if let Err(e) = pktres {
192 if (e as i32) == (DemuxerError::EOF as i32) { break; }
193 panic!("error");
194 }
195 let pkt = pktres.unwrap();
196 println!("Got {}", pkt);
197 }
198 }
199 }