add VivoActive (imperfect) format family support
[nihav.git] / nihav-vivo / src / demuxers / vivo.rs
1 use nihav_core::demuxers::*;
2
3 struct VivoDemuxer<'a> {
4 src: &'a mut ByteReader<'a>,
5 video_id: usize,
6 audio_id: usize,
7 video_buf: Vec<u8>,
8 vpts: u64,
9 apts: u64,
10 v_num: u32,
11 v_den: u32,
12 a_num: u32,
13 a_den: u32,
14 fps: f32,
15 width: usize,
16 height: usize,
17 vname: &'static str,
18 aname: &'static str,
19 }
20
21 fn read_size(br: &mut ByteReader) -> DemuxerResult<usize> {
22 let mut ret = 0;
23 loop {
24 let c = br.read_byte()?;
25 ret = (ret << 7) | ((c & 0x7F) as usize);
26 if (c & 0x80) == 0 {
27 break;
28 }
29 }
30 Ok(ret)
31 }
32
33 impl<'a> DemuxCore<'a> for VivoDemuxer<'a> {
34 fn open(&mut self, strmgr: &mut StreamManager, _seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
35 let mut hdr_data: Vec<u8> = Vec::with_capacity(256);
36 loop {
37 let hdr = self.src.peek_byte()?;
38 if (hdr & 0xF0) != 0 { break; }
39 self.src.read_skip(1)?;
40 let hdr_len = read_size(&mut self.src)?;
41 hdr_data.resize(hdr_len, 0);
42 self.src.read_buf(&mut hdr_data)?;
43 self.parse_header_packet(&hdr_data)?;
44 }
45
46 validate!(self.vname != "none");
47 if self.width == 0 && self.height == 0 {
48 self.width = 160;
49 self.height = 120;
50 }
51 validate!(self.fps > 0.0 || (self.v_num > 0 && self.v_den > 0));
52
53 if self.v_num == 0 {
54 self.v_num = 1000;
55 self.v_den = (self.fps * 1000.0) as u32;
56 }
57
58 let vhdr = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
59 let vinfo = NACodecInfo::new(self.vname, NACodecTypeInfo::Video(vhdr), None);
60 let res = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, self.v_num, self.v_den));
61 validate!(res.is_some());
62 self.video_id = res.unwrap();
63
64 if self.aname == "none" && self.vname == "vivo1" {
65 self.aname = "g723.1";
66 self.a_num = 240;
67 self.a_den = 8000;
68 }
69 if self.aname != "none" {
70 let ahdr = NAAudioInfo::new(self.a_den, 1, SND_S16_FORMAT, self.a_num as usize);
71 let ainfo = NACodecInfo::new(self.aname, NACodecTypeInfo::Audio(ahdr), None);
72 let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, self.a_num, self.a_den));
73 validate!(res.is_some());
74 self.audio_id = res.unwrap();
75 }
76
77 Ok(())
78 }
79 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
80 let br = &mut self.src;
81
82 loop {
83 let ret = br.read_byte();
84 let hdr1 = match ret {
85 Err(ByteIOError::EOF) => return Err(DemuxerError::EOF),
86 Err(error) => return Err(error.into()),
87 Ok(val) => val,
88 };
89 let force_size = hdr1 == 0x82;
90 let hdr = if force_size { br.read_byte()? } else { hdr1 };
91 let (is_video, mut size) = match hdr >> 4 {
92 1 => { (true, 128) },
93 2 => { validate!(!force_size); (true, read_size(br)?) },
94 3 => { (false, 40) },
95 4 => { (false, 24) },
96 _ => return Err(DemuxerError::InvalidData),
97 };
98 if force_size {
99 size = read_size(br)?;
100 }
101 if is_video {
102 validate!(self.v_den != 0);
103 let cur_size = self.video_buf.len();
104 let new_size = cur_size + size;
105 self.video_buf.resize(new_size, 0);
106 br.read_buf(&mut self.video_buf[cur_size..])?;
107 if (hdr >> 4) == 2 {
108 let mut buf = Vec::new();
109 std::mem::swap(&mut self.video_buf, &mut buf);
110 let strres = strmgr.get_stream(self.video_id);
111 validate!(strres.is_some());
112 let stream = strres.unwrap();
113 let ts = NATimeInfo::new(Some(self.vpts), None, None, self.v_num, self.v_den);
114 let pkt = NAPacket::new(stream, ts, self.vpts == 0, buf);
115 self.vpts += 1;
116 return Ok(pkt);
117 }
118 } else {
119 validate!(self.a_den != 0);
120 let mut buf: Vec<u8> = vec![0; size];
121 br.read_buf(&mut buf)?;
122 let strres = strmgr.get_stream(self.audio_id);
123 validate!(strres.is_some());
124 let stream = strres.unwrap();
125 let ts = NATimeInfo::new(Some(self.apts), None, None, self.a_num, self.a_den);
126 let pkt = NAPacket::new(stream, ts, true, buf);
127 self.apts += 1;
128 return Ok(pkt);
129 }
130 }
131 }
132 fn seek(&mut self, _time: u64, _seek_idx: &SeekIndex) -> DemuxerResult<()> {
133 Err(DemuxerError::NotPossible)
134 }
135 }
136
137 impl<'a> VivoDemuxer<'a> {
138 fn new(io: &'a mut ByteReader<'a>) -> Self {
139 VivoDemuxer {
140 src: io,
141 video_id: 0,
142 audio_id: 0,
143 video_buf: Vec::new(),
144 vpts: 0,
145 apts: 0,
146 v_num: 0,
147 v_den: 0,
148 a_num: 0,
149 a_den: 0,
150 width: 0,
151 height: 0,
152 fps: 0.0,
153 vname: "none",
154 aname: "none",
155 }
156 }
157 fn parse_header_packet(&mut self, pkt: &[u8]) -> DemuxerResult<()> {
158 for entry in pkt.split(|ch| *ch == 0xD) {
159 if entry.len() < 3 || !entry.contains(&b':') { continue; }
160 let entry = if entry.len() > 0 && entry[0] == 0xA { &entry[1..] } else { entry };
161 let mut split = entry.split(|ch| *ch == b':');
162 let name = split.next().unwrap();
163 let value = split.next().unwrap();
164
165 let valstr = String::from_utf8_lossy(value);
166 match name {
167 b"Version" => {
168 match value {
169 b"Vivo/0.90" => { self.vname = "vivo1"; },
170 b"Vivo/1.00" => { self.vname = "vivo1"; },
171 b"Vivo/2.00" => { self.vname = "vivo2"; },
172 _ => {
173 println!("Unknown codec name {}", valstr);
174 return Err(DemuxerError::InvalidData);
175 },
176 };
177 },
178 b"FPS" => {
179 self.fps = if let Ok(val) = valstr.parse() {
180 val
181 } else { return Err(DemuxerError::InvalidData); };
182 validate!(self.fps > 0.0 && self.fps < 1000.0);
183 },
184 b"Width" => {
185 self.width = if let Ok(val) = valstr.parse() {
186 val
187 } else { return Err(DemuxerError::InvalidData); };
188 validate!(self.width > 0 && self.width <= 1024);
189 },
190 b"Height" => {
191 self.height = if let Ok(val) = valstr.parse() {
192 val
193 } else { return Err(DemuxerError::InvalidData); };
194 validate!(self.height > 0 && self.height <= 768);
195 },
196 b"SamplingFrequency" => {
197 let samp_freq: u32 = if let Ok(val) = valstr.parse() {
198 val
199 } else { return Err(DemuxerError::InvalidData); };
200 validate!(samp_freq == 8000 || samp_freq == 16000);
201 if samp_freq == 8000 {
202 self.aname = "g723.1";
203 self.a_num = 240;
204 self.a_den = 8000;
205 } else if samp_freq == 16000 {
206 self.aname = "siren";
207 self.a_num = 320;
208 self.a_den = 16000;
209 } else {
210 return Err(DemuxerError::InvalidData);
211 };
212 },
213 /* b"TimeUnitNumerator" => {
214 self.v_num = if let Ok(val) = valstr.parse() {
215 val
216 } else { return Err(DemuxerError::InvalidData); };
217 validate!(self.v_num > 0);
218 println!(" video codec tb_num {}", self.v_num);
219 },
220 b"TimeUnitDenominator" => {
221 self.v_den = if let Ok(val) = valstr.parse() {
222 val
223 } else { return Err(DemuxerError::InvalidData); };
224 validate!(self.v_den > 0);
225 println!(" video codec tb_den {}", self.v_den);
226 },*/
227 _ => { },
228 };
229 }
230 Ok(())
231 }
232 }
233
234 pub struct VivoDemuxerCreator { }
235
236 impl DemuxerCreator for VivoDemuxerCreator {
237 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
238 Box::new(VivoDemuxer::new(br))
239 }
240 fn get_name(&self) -> &'static str { "vivo" }
241 }
242
243 #[cfg(test)]
244 mod test {
245 use super::*;
246 use std::fs::File;
247
248 #[test]
249 fn test_vivo_demux() {
250 // let mut file = File::open("assets/Misc/greetings.viv").unwrap();
251 let mut file = File::open("assets/Misc/favmovie.viv").unwrap();
252 let mut fr = FileReader::new_read(&mut file);
253 let mut br = ByteReader::new(&mut fr);
254 let mut dmx = VivoDemuxer::new(&mut br);
255 let mut sm = StreamManager::new();
256 let mut si = SeekIndex::new();
257 dmx.open(&mut sm, &mut si).unwrap();
258 loop {
259 let pktres = dmx.get_frame(&mut sm);
260 if let Err(e) = pktres {
261 if (e as i32) == (DemuxerError::EOF as i32) { break; }
262 panic!("error {:?}", e);
263 }
264 let pkt = pktres.unwrap();
265 println!("Got {}", pkt);
266 }
267 }
268 }