3c0ac7d2ee3c05a58a3f0faae91683247e901421
[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: NATimePoint, _seek_idx: &SeekIndex) -> DemuxerResult<()> {
133 Err(DemuxerError::NotPossible)
134 }
135 }
136
137 impl<'a> NAOptionHandler for VivoDemuxer<'a> {
138 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
139 fn set_options(&mut self, _options: &[NAOption]) { }
140 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
141 }
142
143 impl<'a> VivoDemuxer<'a> {
144 fn new(io: &'a mut ByteReader<'a>) -> Self {
145 VivoDemuxer {
146 src: io,
147 video_id: 0,
148 audio_id: 0,
149 video_buf: Vec::new(),
150 vpts: 0,
151 apts: 0,
152 v_num: 0,
153 v_den: 0,
154 a_num: 0,
155 a_den: 0,
156 width: 0,
157 height: 0,
158 fps: 0.0,
159 vname: "none",
160 aname: "none",
161 }
162 }
163 fn parse_header_packet(&mut self, pkt: &[u8]) -> DemuxerResult<()> {
164 for entry in pkt.split(|ch| *ch == 0xD) {
165 if entry.len() < 3 || !entry.contains(&b':') { continue; }
166 let entry = if !entry.is_empty() && entry[0] == 0xA { &entry[1..] } else { entry };
167 let mut split = entry.split(|ch| *ch == b':');
168 let name = split.next().unwrap();
169 let value = split.next().unwrap();
170
171 let valstr = String::from_utf8_lossy(value);
172 match name {
173 b"Version" => {
174 match value {
175 b"Vivo/0.90" => { self.vname = "vivo1"; },
176 b"Vivo/1.00" => { self.vname = "vivo1"; },
177 b"Vivo/2.00" => { self.vname = "vivo2"; },
178 _ => {
179 println!("Unknown codec name {}", valstr);
180 return Err(DemuxerError::InvalidData);
181 },
182 };
183 },
184 b"FPS" => {
185 self.fps = if let Ok(val) = valstr.parse() {
186 val
187 } else { return Err(DemuxerError::InvalidData); };
188 validate!(self.fps > 0.0 && self.fps < 1000.0);
189 },
190 b"Width" => {
191 self.width = if let Ok(val) = valstr.parse() {
192 val
193 } else { return Err(DemuxerError::InvalidData); };
194 validate!(self.width > 0 && self.width <= 1024);
195 },
196 b"Height" => {
197 self.height = if let Ok(val) = valstr.parse() {
198 val
199 } else { return Err(DemuxerError::InvalidData); };
200 validate!(self.height > 0 && self.height <= 768);
201 },
202 b"SamplingFrequency" => {
203 let samp_freq: u32 = if let Ok(val) = valstr.parse() {
204 val
205 } else { return Err(DemuxerError::InvalidData); };
206 validate!(samp_freq == 8000 || samp_freq == 16000);
207 if samp_freq == 8000 {
208 self.aname = "g723.1";
209 self.a_num = 240;
210 self.a_den = 8000;
211 } else if samp_freq == 16000 {
212 self.aname = "siren";
213 self.a_num = 320;
214 self.a_den = 16000;
215 } else {
216 return Err(DemuxerError::InvalidData);
217 };
218 },
219 /* b"TimeUnitNumerator" => {
220 self.v_num = if let Ok(val) = valstr.parse() {
221 val
222 } else { return Err(DemuxerError::InvalidData); };
223 validate!(self.v_num > 0);
224 println!(" video codec tb_num {}", self.v_num);
225 },
226 b"TimeUnitDenominator" => {
227 self.v_den = if let Ok(val) = valstr.parse() {
228 val
229 } else { return Err(DemuxerError::InvalidData); };
230 validate!(self.v_den > 0);
231 println!(" video codec tb_den {}", self.v_den);
232 },*/
233 _ => { },
234 };
235 }
236 Ok(())
237 }
238 }
239
240 pub struct VivoDemuxerCreator { }
241
242 impl DemuxerCreator for VivoDemuxerCreator {
243 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
244 Box::new(VivoDemuxer::new(br))
245 }
246 fn get_name(&self) -> &'static str { "vivo" }
247 }
248
249 #[cfg(test)]
250 mod test {
251 use super::*;
252 use std::fs::File;
253
254 #[test]
255 fn test_vivo_demux() {
256 // let mut file = File::open("assets/Misc/greetings.viv").unwrap();
257 let mut file = File::open("assets/Misc/favmovie.viv").unwrap();
258 let mut fr = FileReader::new_read(&mut file);
259 let mut br = ByteReader::new(&mut fr);
260 let mut dmx = VivoDemuxer::new(&mut br);
261 let mut sm = StreamManager::new();
262 let mut si = SeekIndex::new();
263 dmx.open(&mut sm, &mut si).unwrap();
264 loop {
265 let pktres = dmx.get_frame(&mut sm);
266 if let Err(e) = pktres {
267 if (e as i32) == (DemuxerError::EOF as i32) { break; }
268 panic!("error {:?}", e);
269 }
270 let pkt = pktres.unwrap();
271 println!("Got {}", pkt);
272 }
273 }
274 }