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