]> git.nihav.org Git - nihav.git/blob - nihav-commonfmt/src/demuxers/mov.rs
a1c3669750156334f431cbec40b142c3e3e7763e
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
1 use nihav_core::demuxers::*;
2 use nihav_registry::register::*;
3 use nihav_core::compr::deflate::*;
4
5 macro_rules! mktag {
6 ($a:expr, $b:expr, $c:expr, $d:expr) => ({
7 (($a as u32) << 24) | (($b as u32) << 16) | (($c as u32) << 8) | ($d as u32)
8 });
9 ($arr:expr) => ({
10 (($arr[0] as u32) << 24) | (($arr[1] as u32) << 16) | (($arr[2] as u32) << 8) | ($arr[3] as u32)
11 });
12 }
13
14 #[derive(Clone,Copy,Debug,PartialEq)]
15 enum DemuxMode {
16 Normal,
17 MacBin,
18 ResFork,
19 }
20
21 trait Skip64 {
22 fn skip64(&mut self, size: u64) -> ByteIOResult<()>;
23 }
24
25 impl<'a> Skip64 for ByteReader<'a> {
26 fn skip64(&mut self, size: u64) -> ByteIOResult<()> {
27 if (size as usize as u64) != size {
28 self.seek(SeekFrom::Current(size as i64))?;
29 } else {
30 self.read_skip(size as usize)?;
31 }
32 Ok(())
33 }
34 }
35
36 fn read_chunk_header(br: &mut ByteReader) -> DemuxerResult<(u32, u64)> {
37 let size = br.read_u32be()?;
38 let ctype = br.read_u32be()?;
39 if size == 0 {
40 Ok((ctype, br.left() as u64))
41 } else if size == 1 {
42 let size64 = br.read_u64be()?;
43 validate!(size64 >= 16);
44 Ok((ctype, size64 - 16))
45 } else {
46 validate!(size >= 8);
47 Ok((ctype, (size as u64) - 8))
48 }
49 }
50
51 fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
52 let _seed = br.read_u32be()?;
53 let flags = br.read_u16be()?;
54 let palsize = (br.read_u16be()? as usize) + 1;
55 validate!(palsize <= 256);
56 validate!(flags == 0 || flags == 0x4000 || flags == 0x8000);
57 validate!((palsize as u64) * 8 + 8 <= size);
58 for i in 0..palsize {
59 let a = br.read_u16be()?;
60 let r = br.read_u16be()?;
61 let g = br.read_u16be()?;
62 let b = br.read_u16be()?;
63 pal[i * 4] = (r >> 8) as u8;
64 pal[i * 4 + 1] = (g >> 8) as u8;
65 pal[i * 4 + 2] = (b >> 8) as u8;
66 if flags == 0x8000 {
67 pal[i * 4 + 3] = (a >> 8) as u8;
68 }
69 }
70 if flags == 0x4000 {
71 br.read_skip(8)?;
72 }
73 Ok(size)
74 }
75
76 struct RootChunkHandler {
77 ctype: u32,
78 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
79 }
80
81 struct TrackChunkHandler {
82 ctype: u32,
83 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
84 }
85
86 const IGNORED_CHUNKS: &[u32] = &[
87 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
88 ];
89
90 const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
91 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
92 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
93 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
94 RootChunkHandler { ctype: mktag!(b"moof"), parse: read_moof },
95 RootChunkHandler { ctype: mktag!(b"sidx"), parse: read_sidx },
96 ];
97
98 fn print_cname(ctype: u32, size: u64, off: u64, depth: u8) {
99 for _ in 0..depth { print!(" "); }
100 let tag = [(ctype >> 24) as u8, (ctype >> 16) as u8, (ctype >> 8) as u8, ctype as u8];
101 let mut printable = true;
102 for ch in tag.iter() {
103 if !(0x20..=0x7F).contains(ch) {
104 printable = false;
105 break;
106 }
107 }
108 if printable {
109 print!(" '{}{}{}{}'", tag[0] as char, tag[1] as char, tag[2] as char, tag[3] as char);
110 } else {
111 print!(" {:08X}", ctype);
112 }
113 println!(" size {} @ {:X}", size, off);
114 }
115
116 macro_rules! read_chunk_list {
117 (root; $name: expr, $fname: ident, $handlers: ident) => {
118 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
119 self.depth += 1;
120 validate!(self.depth < 32);
121 let list_end = self.src.tell() + size;
122 while self.src.tell() < list_end {
123 let ret = read_chunk_header(self.src);
124 if ret.is_err() { break; }
125 let (ctype, size) = ret.unwrap();
126 if self.print_chunks {
127 print_cname(ctype, size, self.src.tell(), self.depth as u8);
128 }
129 if self.src.tell() + size > list_end {
130 break;
131 }
132 if IGNORED_CHUNKS.contains(&ctype) {
133 self.src.skip64(size)?;
134 continue;
135 }
136 let handler = $handlers.iter().find(|x| x.ctype == ctype);
137 let read_size;
138 if let Some(ref handler) = handler {
139 read_size = (handler.parse)(self, strmgr, size)?;
140 } else {
141 println!("skipping unknown chunk {:08X} size {}", ctype, size);
142 read_size = 0;
143 }
144 validate!(read_size <= size);
145 self.src.skip64(size - read_size)?;
146 }
147 self.depth -= 1;
148 validate!(self.src.tell() == list_end);
149 Ok(())
150 }
151 };
152 (track; $name: expr, $fname: ident, $handlers: ident) => {
153 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
154 self.depth += 1;
155 validate!(self.depth < 32);
156 let list_end = br.tell() + size;
157 while br.tell() < list_end {
158 let ret = read_chunk_header(br);
159 if ret.is_err() { break; }
160 let (ctype, size) = ret.unwrap();
161 if self.print_chunks {
162 print_cname(ctype, size, br.tell(), self.depth + 1);
163 }
164 if br.tell() + size > list_end {
165 break;
166 }
167 if IGNORED_CHUNKS.contains(&ctype) {
168 br.skip64(size)?;
169 continue;
170 }
171 let handler = $handlers.iter().find(|x| x.ctype == ctype);
172 let read_size;
173 if let Some(ref handler) = handler {
174 read_size = (handler.parse)(self, br, size)?;
175 } else {
176 read_size = 0;
177 }
178 validate!(read_size <= size);
179 br.skip64(size - read_size)?;
180 }
181 self.depth -= 1;
182 validate!(br.tell() == list_end);
183 Ok(())
184 }
185 }
186 }
187
188 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
189 br.skip64(size)?;
190 Ok(size)
191 }
192
193 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
194 dmx.src.skip64(size)?;
195 Ok(size)
196 }
197
198 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
199 dmx.mdat_pos = dmx.src.tell();
200 dmx.mdat_size = size;
201 dmx.src.skip64(size)?;
202 Ok(size)
203 }
204
205 fn read_sidx(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
206 Ok(0)
207 }
208
209 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
210 dmx.read_moov(strmgr, size)?;
211 Ok(size)
212 }
213
214 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
215 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
216 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
217 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
218 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
219 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
220 RootChunkHandler { ctype: mktag!(b"mvex"), parse: read_mvex },
221 RootChunkHandler { ctype: mktag!(b"iods"), parse: skip_chunk_mov },
222 ];
223
224 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
225 const KNOWN_MVHD_SIZE: u64 = 100;
226 let br = &mut dmx.src;
227 validate!(size >= KNOWN_MVHD_SIZE);
228 let version = br.read_byte()?;
229 validate!(version == 0);
230 let _flags = br.read_u24be()?;
231 let _ctime = br.read_u32be()?;
232 let _mtime = br.read_u32be()?;
233 let tscale = br.read_u32be()?;
234 let duration = br.read_u32be()?;
235 let _pref_rate = br.read_u32be()?;
236 let _pref_volume = br.read_u16be()?;
237 br.read_skip(10)?;
238 br.read_skip(36)?; // matrix
239 let _preview_time = br.read_u32be()?;
240 let _preview_duration = br.read_u32be()?;
241 let _poster_time = br.read_u32be()?;
242 let _sel_time = br.read_u32be()?;
243 let _sel_duration = br.read_u32be()?;
244 let _cur_time = br.read_u32be()?;
245 let _next_track_id = br.read_u32be()?;
246 dmx.duration = duration;
247 dmx.tb_den = tscale;
248
249 Ok(KNOWN_MVHD_SIZE)
250 }
251
252 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
253 let br = &mut dmx.src;
254 validate!(size > 24);
255 let dcom_size = br.read_u32be()?;
256 let dcom_tag = br.read_tag()?;
257 let compr_type = br.read_tag()?;
258 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
259 if &compr_type != b"zlib" {
260 return Err(DemuxerError::NotImplemented);
261 }
262 let cmvd_size = u64::from(br.read_u32be()?);
263 let cmvd_tag = br.read_tag()?;
264 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
265 let comp_size = (cmvd_size - 12) as usize;
266 let uncomp_size = br.read_u32be()? as usize;
267 validate!(uncomp_size > 8);
268 let mut sbuf = vec![0; comp_size];
269 let mut dbuf = vec![0; uncomp_size];
270 br.read_buf(sbuf.as_mut_slice())?;
271 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
272 if ret.is_err() {
273 return Err(DemuxerError::InvalidData);
274 }
275 let len = ret.unwrap();
276 validate!(len == uncomp_size);
277 let mut mr = MemoryReader::new_read(dbuf.as_slice());
278 let mut br = ByteReader::new(&mut mr);
279 let (ctype, csize) = read_chunk_header(&mut br)?;
280 validate!(ctype == mktag!(b"moov"));
281 let mut ddmx = MOVDemuxer::new(&mut br);
282 ddmx.print_chunks = dmx.print_chunks;
283 ddmx.read_moov(strmgr, csize)?;
284 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
285 dmx.duration = ddmx.duration;
286 dmx.tb_den = ddmx.tb_den;
287 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
288
289 Ok(size)
290 }
291
292 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
293 let mut pal = [0; 1024];
294 let size = read_palette(dmx.src, size, &mut pal)?;
295 dmx.pal = Some(Arc::new(pal));
296 Ok(size)
297 }
298
299 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
300 dmx.src.skip64(size)?;
301 Ok(size)
302 }
303
304 fn read_mvex(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
305 Ok(0)
306 }
307
308 fn skip_chunk_mov(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
309 Ok(0)
310 }
311
312 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
313 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
314 track.print_chunks = dmx.print_chunks;
315 track.read_trak(dmx.src, size)?;
316 validate!(track.tkhd_found && track.stsd_found);
317 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
318 dmx.cur_track += 1;
319 dmx.tracks.push(track);
320 Ok(size)
321 }
322
323 fn read_moof(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
324 dmx.moof_off = dmx.src.tell() - 8;
325 dmx.read_moof(strmgr, size)?;
326 Ok(size)
327 }
328
329 const MOOF_CHUNK_HANDLERS: &[RootChunkHandler] = &[
330 RootChunkHandler { ctype: mktag!(b"mfhd"), parse: read_mfhd },
331 RootChunkHandler { ctype: mktag!(b"traf"), parse: read_traf },
332 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
333 ];
334
335 fn read_mfhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
336 const KNOWN_MFHD_SIZE: u64 = 8;
337 validate!(size >= KNOWN_MFHD_SIZE);
338 let version = dmx.src.read_byte()?;
339 validate!(version == 0);
340 let flags = dmx.src.read_u24be()?;
341 validate!(flags == 0);
342 let _seq_no = dmx.src.read_u32be()?;
343
344 Ok(KNOWN_MFHD_SIZE)
345 }
346
347 fn read_traf(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
348 let mut buf = [0u8; 16];
349 dmx.src.peek_buf(&mut buf)?;
350 validate!(&buf[4..8] == b"tfhd");
351 let track_id = read_u32be(&buf[12..16])?;
352 let mut track = None;
353 for trk in dmx.tracks.iter_mut() {
354 if trk.track_id == track_id {
355 track = Some(trk);
356 break;
357 }
358 }
359 if let Some(track) = track {
360 track.moof_off = dmx.moof_off;
361 track.read_traf(dmx.src, size)?;
362 Ok(size)
363 } else {
364 Ok(0)
365 }
366 }
367
368 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
369 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
370 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
371 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
372 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
373 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
374 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
375 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
376 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
377 ];
378
379 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
380 const KNOWN_TKHD_SIZE: u64 = 84;
381 validate!(size >= KNOWN_TKHD_SIZE);
382 let version = br.read_byte()?;
383 validate!(version == 0);
384 let _flags = br.read_u24be()?;
385 let _ctime = br.read_u32be()?;
386 let _mtime = br.read_u32be()?;
387 let track_id = br.read_u32be()?;
388 br.read_skip(4)?;
389 let duration = br.read_u32be()?;
390 br.read_skip(8)?;
391 let _layer = br.read_u16be()?;
392 let _alt_group = br.read_u16be()?;
393 let _volume = br.read_u16be()?;
394 br.read_skip(2)?;
395 br.read_skip(36)?; // matrix
396 let width = br.read_u32be()? as usize;
397 let height = br.read_u32be()? as usize;
398 track.width = width >> 16;
399 track.height = height >> 16;
400 track.track_id = track_id;
401 track.duration = duration;
402
403 track.tkhd_found = true;
404 Ok(KNOWN_TKHD_SIZE)
405 }
406
407 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
408 track.stream_type = StreamType::None;
409 track.read_mdia(br, size)?;
410 Ok(size)
411 }
412
413 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
414 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: read_mdhd },
415 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
416 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
417 ];
418
419 fn read_mdhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
420 const KNOWN_MDHD_SIZE: u64 = 24;
421 validate!(size >= KNOWN_MDHD_SIZE);
422 let version = br.read_byte()?;
423 validate!(version == 0);
424 let flags = br.read_u24be()?;
425 validate!(flags == 0);
426 let _ctime = br.read_u32be()?;
427 let _mtime = br.read_u32be()?;
428 track.tb_den = br.read_u32be()?;
429 validate!(track.tb_den != 0);
430 track.duration = br.read_u32be()?;
431 let _language = br.read_u16be()?;
432 let _quality = br.read_u16be()?;
433
434 Ok(KNOWN_MDHD_SIZE)
435 }
436
437 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
438 const KNOWN_HDLR_SIZE: u64 = 24;
439 validate!(size >= KNOWN_HDLR_SIZE);
440 let version = br.read_byte()?;
441 validate!(version == 0);
442 let flags = br.read_u24be()?;
443 validate!(flags == 0);
444 let comp_type = br.read_u32be()?;
445 let comp_subtype = br.read_u32be()?;
446 let _comp_manufacturer = br.read_u32be()?;
447 let _comp_flags = br.read_u32be()?;
448 let _comp_flags_mask = br.read_u32be()?;
449
450 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
451 if comp_subtype == mktag!(b"vide") {
452 track.stream_type = StreamType::Video;
453 } else if comp_subtype == mktag!(b"soun") {
454 track.stream_type = StreamType::Audio;
455 } else {
456 track.stream_type = StreamType::Data;
457 }
458 } else if comp_type == mktag!(b"dhlr") {
459 track.stream_type = StreamType::Data;
460 } else {
461 println!("Unknown stream type");
462 track.stream_type = StreamType::Data;
463 }
464
465 Ok(KNOWN_HDLR_SIZE)
466 }
467
468 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
469 track.read_minf(br, size)?;
470 Ok(size)
471 }
472
473 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
474 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
475 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
476 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
477 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
478 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
479 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
480 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
481 ];
482
483 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
484 const KNOWN_VMHD_SIZE: u64 = 12;
485 validate!(track.stream_type == StreamType::Video);
486 validate!(size >= KNOWN_VMHD_SIZE);
487 let version = br.read_byte()?;
488 validate!(version == 0);
489 let _flags = br.read_u24be()?;
490 br.read_skip(2)?; // graphics mode
491 br.read_skip(6)?; // opcolor
492 Ok(KNOWN_VMHD_SIZE)
493 }
494
495 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
496 const KNOWN_SMHD_SIZE: u64 = 8;
497 validate!(track.stream_type == StreamType::Audio);
498 validate!(size >= KNOWN_SMHD_SIZE);
499 let version = br.read_byte()?;
500 validate!(version == 0);
501 let _flags = br.read_u24be()?;
502 br.read_skip(2)?; // balance
503 br.read_skip(2)?;
504 Ok(KNOWN_SMHD_SIZE)
505 }
506
507 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
508 validate!(track.stream_type == StreamType::Data);
509 Ok(0)
510 }
511
512 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
513 validate!(track.stream_type == StreamType::Data);
514 const KNOWN_GMIN_SIZE: u64 = 16;
515 validate!(size >= KNOWN_GMIN_SIZE);
516 let version = br.read_byte()?;
517 validate!(version == 0);
518 let _flags = br.read_u24be()?;
519 br.read_skip(2)?; // graphics mode
520 br.read_skip(6)?; // opcolor
521 br.read_skip(2)?; // balance
522 br.read_skip(2)?;
523 Ok(KNOWN_GMIN_SIZE)
524 }
525
526 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
527 track.read_stbl(br, size)?;
528 Ok(size)
529 }
530
531 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
532 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
533 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
534 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
535 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
536 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
537 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
538 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
539 TrackChunkHandler { ctype: mktag!(b"ctts"), parse: read_ctts },
540 ];
541
542 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
543 let read_part = br.tell() - start_pos;
544 if read_part + 8 < size {
545 let mut buf = [0; 8];
546 br.peek_buf(&mut buf)?;
547 if &buf[4..8] != b"wave" {
548 let mut buf = vec![0; (size - read_part) as usize];
549 br.read_buf(&mut buf)?;
550 return Ok(Some(buf));
551 }
552
553 let csize = br.read_u32be()? as u64;
554 let ctag = br.read_u32be()?;
555 validate!(read_part + csize <= size);
556 validate!(ctag == mktag!(b"wave"));
557 if csize == 8 {
558 return Ok(None);
559 }
560 let mut buf = [0; 8];
561 br.peek_buf(&mut buf)?;
562 if &buf[4..8] == b"frma" {
563 br.read_skip(12)?;
564 if csize > 20 {
565 let mut buf = vec![0; (csize - 20) as usize];
566 br.read_buf(&mut buf)?;
567 Ok(Some(buf))
568 } else {
569 Ok(None)
570 }
571 } else if csize > 8 {
572 let mut buf = vec![0; (csize as usize) - 8];
573 br.read_buf(&mut buf)?;
574 Ok(Some(buf))
575 } else {
576 Ok(None)
577 }
578 } else {
579 Ok(None)
580 }
581 }
582
583 #[allow(clippy::neg_cmp_op_on_partial_ord)]
584 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
585 const KNOWN_STSD_SIZE: u64 = 24;
586 validate!(size >= KNOWN_STSD_SIZE);
587 let start_pos = br.tell();
588 let version = br.read_byte()?;
589 validate!(version == 0);
590 let _flags = br.read_u24be()?;
591 let entries = br.read_u32be()?;
592 validate!(entries > 0);
593 let esize = u64::from(br.read_u32be()?);
594 validate!(esize + 8 <= size);
595 let mut fcc = [0u8; 4];
596 br.read_buf(&mut fcc)?;
597 br.read_skip(6)?;
598 let _data_ref = br.read_u16be()?;
599
600 track.fcc = fcc;
601
602 let codec_info;
603 match track.stream_type {
604 StreamType::Video => {
605 let _ver = br.read_u16be()?;
606 let _revision = br.read_u16le()?;
607 let _vendor = br.read_u32be()?;
608 let _temp_quality = br.read_u32be()?;
609 let _spat_quality = br.read_u32be()?;
610 let width = br.read_u16be()? as usize;
611 let height = br.read_u16be()? as usize;
612 let _hor_res = br.read_u32be()?;
613 let _vert_res = br.read_u32be()?;
614 let data_size = br.read_u32be()?;
615 validate!(data_size == 0);
616 let _frame_count = br.read_u16be()? as usize;
617 let _cname_len = br.read_byte()? as usize;
618 br.read_skip(31)?; // actual compressor name
619 let depth = br.read_u16be()?;
620 let ctable_id = br.read_u16be()?;
621 let grayscale = depth > 0x20 || depth == 1;
622 let depth = if grayscale { depth & 0x1F } else { depth };
623 if ctable_id == 0 {
624 let max_pal_size = start_pos + size - br.tell();
625 if depth <= 8 {
626 let mut pal = [0; 1024];
627 read_palette(br, max_pal_size, &mut pal)?;
628 track.pal = Some(Arc::new(pal));
629 } else {
630 br.read_skip(max_pal_size as usize)?;
631 }
632 } else if (depth <= 8) && !grayscale {
633 match depth & 0x1F {
634 2 => {
635 let mut pal = [0; 1024];
636 pal[..4 * 4].copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
637 track.pal = Some(Arc::new(pal));
638 },
639 4 => {
640 let mut pal = [0; 1024];
641 pal[..16 * 4].copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
642 track.pal = Some(Arc::new(pal));
643 },
644 8 => {
645 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
646 },
647 _ => {},
648 };
649 } else if grayscale && ctable_id != 0xFFFF {
650 let mut pal = [0; 1024];
651 let cdepth = depth & 0x1F;
652 let size = 1 << cdepth;
653 for i in 0..size {
654 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
655 let mut off = 8 - cdepth;
656 while off >= cdepth {
657 clr |= clr >> (8 - off);
658 off -= cdepth;
659 }
660 if off > 0 {
661 clr |= clr >> (8 - off);
662 }
663 pal[i * 4] = clr;
664 pal[i * 4 + 1] = clr;
665 pal[i * 4 + 2] = clr;
666 }
667 track.pal = Some(Arc::new(pal));
668 }
669 // todo other atoms, put as extradata
670 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
671 name
672 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
673 name
674 } else {
675 "unknown"
676 };
677 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
678 let mut vhdr = NAVideoInfo::new(width, height, false, format);
679 vhdr.bits = depth as u8;
680 //skip various common atoms
681 while br.tell() - start_pos + 4 < size {
682 let mut buf = [0u8; 8];
683 br.peek_buf(&mut buf)?;
684 let tsize = read_u32be(&buf).unwrap() as usize;
685 let tag = &buf[4..8];
686 validate!(tsize >= 8);
687 match tag {
688 b"pasp" | b"clap" => {
689 br.read_skip(tsize)?;
690 },
691 _ => break,
692 };
693 }
694 let edata = if br.tell() - start_pos + 4 < size {
695 let edata_size = br.read_u32be()? as usize;
696 validate!(edata_size >= 4);
697 let mut buf = vec![0; edata_size - 4];
698 br.read_buf(buf.as_mut_slice())?;
699 Some(buf)
700 } else {
701 None
702 };
703 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
704 },
705 StreamType::Audio => {
706 let sver = br.read_u16be()?;
707 let _revision = br.read_u16le()?;
708 let _vendor = br.read_u32be()?;
709 let mut nchannels = br.read_u16be()?;
710 if sver != 2 {
711 validate!(nchannels <= 64);
712 }
713 let sample_size = br.read_u16be()?;
714 validate!(sample_size <= 128);
715 let _compr_id = br.read_u16be()?;
716 let packet_size = br.read_u16be()? as usize;
717 validate!(packet_size == 0);
718 let mut sample_rate = br.read_u32be()? >> 16;
719 if sver != 2 {
720 validate!(sample_rate > 0);
721 }
722 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
723 name
724 } else if let (true, Some(name)) = ((fcc[0] == b'm' && fcc[1] == b's'), find_codec_from_wav_twocc(u16::from(fcc[2]) * 256 + u16::from(fcc[3]))) {
725 name
726 } else {
727 "unknown"
728 };
729 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
730 if &fcc == b"raw " && sample_size == 8 {
731 soniton.signed = false;
732 }
733 let mut block_align = 1;
734 match sver {
735 1 => {
736 let samples_per_packet = br.read_u32be()?;
737 let _bytes_per_packet = br.read_u32be()?;
738 let bytes_per_frame = br.read_u32be()?;
739 let _bytes_per_sample = br.read_u32be()?;
740 track.bsize = bytes_per_frame as usize;
741 track.frame_samples = samples_per_packet as usize;
742 track.tb_num = samples_per_packet.max(1);
743 block_align = bytes_per_frame as usize;
744 },
745 2 => {
746 br.read_u32be()?; // some size
747 let srate = br.read_f64be()?;
748 validate!(srate > 1.0);
749 sample_rate = srate as u32;
750 let channels = br.read_u32be()?;
751 validate!(channels > 0 && channels < 255);
752 nchannels = channels as u16;
753 br.read_u32be()?; // always 0x7F000000
754 let _bits_per_csample = br.read_u32be()?;
755 let _codec_flags = br.read_u32be()?;
756 let bytes_per_frame = br.read_u32be()?;
757 let samples_per_packet = br.read_u32be()?;
758 track.bsize = bytes_per_frame as usize;
759 track.frame_samples = samples_per_packet as usize;
760 track.tb_num = samples_per_packet;
761 },
762 _ => {
763 track.bsize = (sample_size / 8) as usize;
764 },
765 };
766 if track.tb_den <= 1 {
767 track.tb_den = sample_rate;
768 }
769 track.raw_audio = matches!(&fcc,
770 b"NONE" | b"raw " | b"twos" | b"sowt" |
771 b"in24" | b"in32" | b"fl32" | b"fl64" |
772 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
773 b"alaw" | b"ulaw" |
774 b"MAC3" | b"MAC6");
775 let ahdr = NAAudioInfo::new(sample_rate, nchannels as u8, soniton, block_align);
776 let edata = parse_audio_edata(br, start_pos, size)?;
777 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
778 track.channels = nchannels as usize;
779 track.bits = sample_size as usize;
780 },
781 StreamType::None => {
782 return Err(DemuxerError::InvalidData);
783 },
784 _ => {
785 //todo put it all into extradata
786 let edata = None;
787 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
788 },
789 };
790 let read_size = br.tell() - start_pos;
791 validate!(read_size <= size);
792 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
793 track.stsd_found = true;
794 Ok(read_size)
795 }
796
797 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
798 validate!(size >= 8);
799 let start_pos = br.tell();
800 let version = br.read_byte()?;
801 validate!(version == 0);
802 let _flags = br.read_u24be()?;
803 let entries = br.read_u32be()? as usize;
804 validate!(entries as u64 <= (size - 8) / 8);
805 if entries == 0 {
806 } else if entries == 1 {
807 let _count = br.read_u32be()?;
808 let tb_num = br.read_u32be()?;
809 validate!(tb_num != 0);
810 track.rescale(tb_num);
811 } else {
812 track.time_to_sample.clear();
813 track.time_to_sample.reserve(entries);
814 for _ in 0..entries {
815 let count = br.read_u32be()?;
816 let mult = br.read_u32be()?;
817 track.time_to_sample.push((count, mult));
818 }
819 }
820 let read_size = br.tell() - start_pos;
821 validate!(read_size <= size);
822 Ok(read_size)
823 }
824
825 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
826 let version = br.read_byte()?;
827 validate!(version == 0);
828 let _flags = br.read_u24be()?;
829 let entries = br.read_u32be()? as usize;
830 validate!(entries < ((u32::MAX >> 2) - 8) as usize);
831 validate!((entries * 4 + 8) as u64 == size);
832 track.keyframes = Vec::with_capacity(entries);
833 let mut last_sample_no = 0;
834 for _ in 0..entries {
835 let sample_no = br.read_u32be()?;
836 validate!(sample_no > last_sample_no);
837 track.keyframes.push(sample_no);
838 last_sample_no = sample_no;
839 }
840 Ok(size)
841 }
842
843 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
844 let version = br.read_byte()?;
845 validate!(version == 0);
846 let _flags = br.read_u24be()?;
847 let entries = br.read_u32be()? as usize;
848 validate!(entries < ((u32::MAX / 12) - 8) as usize);
849 validate!((entries * 12 + 8) as u64 == size);
850 track.sample_map = Vec::with_capacity(entries);
851 let mut last_sample_no = 0;
852 for _i in 0..entries {
853 let sample_no = br.read_u32be()?;
854 validate!(sample_no > last_sample_no);
855 let nsamples = br.read_u32be()?;
856 let _sample_desc = br.read_u32be()?;
857 track.sample_map.push((sample_no, nsamples));
858 last_sample_no = sample_no;
859 }
860 Ok(size)
861 }
862
863 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
864 let version = br.read_byte()?;
865 validate!(version == 0);
866 let _flags = br.read_u24be()?;
867 let sample_size = br.read_u32be()?;
868 if sample_size != 0 {
869 track.sample_size = sample_size;
870 if track.sample_size != 1 || track.bsize == 0 {
871 track.bsize = sample_size as usize;
872 }
873 Ok(8)
874 } else {
875 let entries = br.read_u32be()? as usize;
876 validate!((entries * 4 + 12) as u64 == size);
877 if entries < 1024 {
878 track.chunk_sizes = Vec::with_capacity(entries);
879 for _ in 0..entries {
880 let sample_size = br.read_u32be()?;
881 track.chunk_sizes.push(sample_size);
882 }
883 } else {
884 // reading whole array at once and converting it later is much faster
885 track.chunk_sizes = vec![0; entries];
886 unsafe {
887 let ptr = track.chunk_sizes.as_mut_ptr() as *mut u8;
888 let dbuf = std::slice::from_raw_parts_mut(ptr, entries * 4);
889 br.read_buf(dbuf)?;
890 }
891 for el in track.chunk_sizes.iter_mut() {
892 *el = u32::from_be(*el);
893 }
894 }
895 Ok(size)
896 }
897 }
898
899 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
900 let version = br.read_byte()?;
901 validate!(version == 0);
902 let _flags = br.read_u24be()?;
903 let entries = br.read_u32be()? as usize;
904 validate!((entries * 4 + 8) as u64 == size);
905 if entries < 1024 {
906 track.chunk_offsets = Vec::with_capacity(entries);
907 for _i in 0..entries {
908 let sample_offset = br.read_u32be()?;
909 track.chunk_offsets.push(u64::from(sample_offset));
910 }
911 } else {
912 // reading whole array at once and converting it later is much faster
913 track.chunk_offsets = vec![0; entries];
914 let mut tmp = vec![0u32; entries];
915 unsafe {
916 let data = tmp.as_mut_ptr();
917 let ptr = std::slice::from_raw_parts_mut(data as *mut u8, entries * 4);
918 br.read_buf(ptr)?;
919 }
920 for (dst, &src) in track.chunk_offsets.iter_mut().zip(tmp.iter()) {
921 *dst = u64::from(u32::from_be(src));
922 }
923 }
924 Ok(size)
925 }
926
927 fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
928 validate!(size >= 8);
929 let version = br.read_byte()?;
930 let _flags = br.read_u24be()?;
931 if version > 1 {
932 return Err(DemuxerError::NotImplemented);
933 }
934 let entries = br.read_u32be()? as usize;
935 track.ctts_version = version;
936 track.ctts_map.resize(entries);
937 match version {
938 0 | 1 => {
939 validate!(size == (entries as u64) * 8 + 8);
940 if entries < 1024 {
941 for _ in 0..entries {
942 let samp_count = br.read_u32be()?;
943 let samp_offset = br.read_u32be()?;
944 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
945 }
946 } else {
947 // reading whole array at once and converting it later is much faster
948 track.ctts_map.array.resize(entries, RLEPair(0, 0));
949 unsafe {
950 let data = track.ctts_map.array.as_mut_ptr();
951 let ptr = std::slice::from_raw_parts_mut(data as *mut u8, entries * 8);
952 br.read_buf(ptr)?;
953 }
954 for RLEPair(count, offset) in track.ctts_map.array.iter_mut() {
955 *count = u32::from_be(*count);
956 *offset = u32::from_be(*offset) / track.tb_div;
957 }
958 }
959 },
960 _ => unreachable!(),
961 };
962 track.ctts_map.reset();
963
964 Ok(size)
965 }
966
967 const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
968 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
969 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
970 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
971 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
972 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
973 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
974 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
975 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
976 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
977 ];
978
979 fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
980 validate!(size >= 8);
981 let start = br.tell();
982 let _version = br.read_byte()?;
983 let flags = br.read_u24be()?;
984 let _track_id = br.read_u32be()?;
985 if (flags & 0x000001) != 0 {
986 let base_offset = br.read_u64be()?;
987 track.moof_off = base_offset;
988 }
989 if (flags & 0x000002) != 0 {
990 let _sample_description_index = br.read_u32be()?;
991 }
992 if (flags & 0x000008) != 0 {
993 let default_sample_duration = br.read_u32be()?;
994 if track.tb_div == 1 {
995 track.rescale(default_sample_duration);
996 }
997 }
998 if (flags & 0x000010) != 0 {
999 let _default_sample_size = br.read_u32be()?;
1000 }
1001 if (flags & 0x000020) != 0 {
1002 let _default_sample_flags = br.read_u32be()?;
1003 }
1004 if (flags & 0x010000) != 0 {
1005 }
1006 /*if (flags & 0x020000) != 0 { // base offset is moof start
1007 }*/
1008 Ok(br.tell() - start)
1009 }
1010
1011 fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
1012 validate!(size >= 8);
1013 let version = br.read_byte()?;
1014 let flags = br.read_u24be()?;
1015 let data_off_present = (flags & 0x000001) != 0;
1016 let first_sample_flags = (flags & 0x000004) != 0;
1017 let sample_duration_present = (flags & 0x000100) != 0;
1018 let sample_size_present = (flags & 0x000200) != 0;
1019 let sample_flags_present = (flags & 0x000400) != 0;
1020 let sample_ct_off_present = (flags & 0x000800) != 0;
1021
1022 let sample_count = br.read_u32be()? as usize;
1023
1024 let mut hdr_size = 8;
1025 let mut arr_size = 0;
1026 if data_off_present {
1027 hdr_size += 4;
1028 }
1029 if first_sample_flags {
1030 hdr_size += 4;
1031 }
1032 if sample_duration_present {
1033 arr_size += 4;
1034 }
1035 if sample_size_present {
1036 arr_size += 4;
1037 }
1038 if sample_flags_present {
1039 arr_size += 4;
1040 }
1041 if sample_ct_off_present {
1042 arr_size += 4;
1043 }
1044 validate!(size == hdr_size + arr_size * (sample_count as u64));
1045
1046 let mut data_off = if data_off_present {
1047 let off = br.read_u32be()? as i32;
1048 let new_off = (track.moof_off as i64) + i64::from(off);
1049 validate!(new_off > 0);
1050 new_off as u64
1051 } else {
1052 track.moof_off
1053 };
1054 if first_sample_flags {
1055 let _flags = br.read_u32be()?;
1056 }
1057
1058 if sample_size_present {
1059 track.chunk_sizes.reserve(sample_count);
1060 track.chunk_offsets.reserve(sample_count);
1061 }
1062
1063 if sample_ct_off_present {
1064 if track.ctts_version != version {
1065 track.ctts_version = version;
1066 }
1067 track.ctts_map.reserve(sample_count);
1068 }
1069
1070 if track.chunk_offsets.len() < (u32::MAX as usize) {
1071 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
1072 }
1073 for _ in 0..sample_count {
1074 if sample_duration_present {
1075 let _duration = br.read_u32be()?;
1076 }
1077 if sample_size_present {
1078 let ssize = br.read_u32be()?;
1079 track.chunk_sizes.push(ssize);
1080 track.chunk_offsets.push(data_off);
1081 data_off += u64::from(ssize);
1082 }
1083 if sample_flags_present {
1084 let _flags = br.read_u32be()?;
1085 }
1086 if sample_ct_off_present {
1087 let samp_offset = br.read_u32be()?;
1088 if version == 0 {
1089 track.ctts_map.add(1, samp_offset / track.tb_div);
1090 } else {
1091 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1092 }
1093 }
1094 }
1095
1096 Ok(size)
1097 }
1098
1099 struct MOVDemuxer<'a> {
1100 src: &'a mut ByteReader<'a>,
1101 depth: usize,
1102 mdat_pos: u64,
1103 mdat_size: u64,
1104 tracks: Vec<Track>,
1105 cur_track: usize,
1106 tb_den: u32,
1107 duration: u32,
1108 pal: Option<Arc<[u8; 1024]>>,
1109
1110 moof_off: u64,
1111
1112 print_chunks: bool,
1113
1114 demux_mode: DemuxMode,
1115 }
1116
1117 struct Track {
1118 track_id: u32,
1119 track_str_id: usize,
1120 track_no: u32,
1121 tb_num: u32,
1122 tb_den: u32,
1123 tb_div: u32,
1124 raw_audio: bool,
1125 raw_apos: u64,
1126 duration: u32,
1127 depth: u8,
1128 tkhd_found: bool,
1129 stsd_found: bool,
1130 stream_type: StreamType,
1131 width: usize,
1132 height: usize,
1133 channels: usize,
1134 bits: usize,
1135 bsize: usize,
1136 fcc: [u8; 4],
1137 keyframes: Vec<u32>,
1138 chunk_sizes: Vec<u32>,
1139 chunk_offsets: Vec<u64>,
1140 time_to_sample: Vec<(u32, u32)>,
1141 sample_map: Vec<(u32, u32)>,
1142 sample_size: u32,
1143 frame_samples: usize,
1144 ctts_map: RLESearcher<u32>,
1145 ctts_version: u8,
1146 stream: Option<NAStream>,
1147 cur_chunk: usize,
1148 cur_sample: usize,
1149 cur_ts: Option<u64>,
1150 samples_left: usize,
1151 last_offset: u64,
1152 pal: Option<Arc<[u8; 1024]>>,
1153 timesearch: TimeSearcher,
1154
1155 moof_off: u64,
1156
1157 print_chunks: bool,
1158 }
1159
1160 #[derive(Default)]
1161 struct TimeSearcher {
1162 idx: usize,
1163 base: u64,
1164 sbase: u32,
1165 cur_len: u32,
1166 cur_mul: u32,
1167 }
1168
1169 impl TimeSearcher {
1170 fn new() -> Self { Self::default() }
1171 fn reset(&mut self) {
1172 *self = Self::default();
1173 }
1174 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
1175 if tts.is_empty() {
1176 u64::from(sample)
1177 } else if sample >= self.sbase {
1178 let mut sample = sample - self.sbase;
1179 if self.idx == 0 {
1180 let (cur_len, cur_mul) = tts[0];
1181 self.cur_len = cur_len;
1182 self.cur_mul = cur_mul;
1183 self.idx += 1;
1184 }
1185 while self.idx < tts.len() && sample > self.cur_len {
1186 sample -= self.cur_len;
1187 self.sbase += self.cur_len;
1188 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1189 self.cur_len = tts[self.idx].0;
1190 self.cur_mul = tts[self.idx].1;
1191 self.idx += 1;
1192 }
1193 self.base + u64::from(sample) * u64::from(self.cur_mul)
1194 } else {
1195 self.reset();
1196 self.map_time(sample, tts)
1197 }
1198 }
1199 }
1200
1201 #[repr(C)]
1202 #[derive(Clone,Copy,Default)]
1203 struct RLEPair<T>(u32, T);
1204
1205 #[derive(Default)]
1206 struct RLESearcher<T> {
1207 array: Vec<RLEPair<T>>,
1208 idx: usize,
1209 start: u64,
1210 next: u64,
1211 }
1212
1213 impl<T:Default+Copy> RLESearcher<T> {
1214 fn new() -> Self { Self::default() }
1215 fn resize(&mut self, size: usize) {
1216 self.array.clear();
1217 self.array.reserve(size);
1218 }
1219 fn reserve(&mut self, size: usize) {
1220 self.array.reserve(size);
1221 }
1222 fn add(&mut self, len: u32, val: T) {
1223 self.array.push(RLEPair(len, val));
1224 }
1225 fn reset(&mut self) {
1226 self.start = 0;
1227 if !self.array.is_empty() {
1228 self.idx = 0;
1229 self.next = u64::from(self.array[0].0);
1230 } else {
1231 self.idx = self.array.len();
1232 self.next = 0;
1233 }
1234 }
1235 fn map(&mut self, sample: u64) -> Option<T> {
1236 if sample < self.start {
1237 self.reset();
1238 }
1239 if self.idx < self.array.len() {
1240 if sample < self.next {
1241 Some(self.array[self.idx].1)
1242 } else {
1243 while (self.idx < self.array.len()) && (sample >= self.next) {
1244 self.start = self.next;
1245 self.idx += 1;
1246 if self.idx < self.array.len() {
1247 self.next += u64::from(self.array[self.idx].0);
1248 }
1249 }
1250 if self.idx < self.array.len() {
1251 Some(self.array[self.idx].1)
1252 } else {
1253 None
1254 }
1255 }
1256 } else {
1257 None
1258 }
1259 }
1260 }
1261
1262 impl Track {
1263 fn new(track_no: u32, tb_den: u32) -> Self {
1264 Self {
1265 tkhd_found: false,
1266 stsd_found: false,
1267 track_id: 0,
1268 track_str_id: 0,
1269 track_no,
1270 tb_num: 1,
1271 tb_den,
1272 tb_div: 1,
1273 raw_audio: false,
1274 raw_apos: 0,
1275 duration: 0,
1276 stream_type: StreamType::None,
1277 width: 0,
1278 height: 0,
1279 channels: 0,
1280 bits: 0,
1281 bsize: 0,
1282 fcc: [0; 4],
1283 keyframes: Vec::new(),
1284 chunk_sizes: Vec::new(),
1285 chunk_offsets: Vec::new(),
1286 time_to_sample: Vec::new(),
1287 sample_map: Vec::new(),
1288 sample_size: 0,
1289 frame_samples: 0,
1290 ctts_map: RLESearcher::new(),
1291 ctts_version: 0,
1292 stream: None,
1293 depth: 0,
1294 cur_chunk: 0,
1295 cur_sample: 0,
1296 cur_ts: None,
1297 samples_left: 0,
1298 last_offset: 0,
1299 pal: None,
1300 timesearch: TimeSearcher::new(),
1301
1302 moof_off: 0,
1303
1304 print_chunks: false,
1305 }
1306 }
1307 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1308 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1309 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1310 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1311 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1312 fn rescale(&mut self, tb_num: u32) {
1313 self.tb_div = tb_num;
1314 if let Some(ref mut stream) = self.stream {
1315 let tb_den = stream.tb_den;
1316 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1317 stream.duration /= u64::from(self.tb_div);
1318 stream.tb_num = tb_num;
1319 stream.tb_den = tb_den;
1320 self.tb_num = tb_num;
1321 self.tb_den = tb_den;
1322 self.duration /= self.tb_div;
1323 }
1324 }
1325 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1326 if !self.keyframes.is_empty() {
1327 seek_index.mode = SeekIndexMode::Present;
1328 }
1329 let mut tsearch = TimeSearcher::new();
1330 for kf_time in self.keyframes.iter() {
1331 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1332 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1333 seek_index.add_entry(self.track_no, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1334 }
1335 }
1336 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1337 if nsamp == 0 {
1338 self.bsize
1339 } else {
1340 match &self.fcc {
1341 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1342 (nsamp * self.bits * self.channels + 7) >> 3
1343 },
1344 b"ima4" => {
1345 let nblocks = (nsamp + 63) >> 6;
1346 nblocks * 34 * self.channels
1347 },
1348 b"MAC3" => {
1349 (nsamp + 5) / 6 * 2 * self.channels
1350 },
1351 b"MAC6" => {
1352 (nsamp + 5) / 6 * self.channels
1353 },
1354 b"in24" => nsamp * 3 * self.channels,
1355 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1356 b"fl64" => nsamp * 8 * self.channels,
1357 b"ulaw" | b"alaw" => nsamp,
1358 b"ms\x00\x02" => { //MS ADPCM
1359 ((nsamp - 1) / 2 + 7) * self.channels
1360 },
1361 b"ms\x00\x21" => { //IMA ADPCM
1362 (nsamp / 2 + 4) * self.channels
1363 },
1364 _ => self.bsize,
1365 }
1366 }
1367 }
1368 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1369 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1370 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1371 let dts = match self.ctts_version {
1372 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1373 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1374 _ => unimplemented!(),
1375 };
1376 if (dts as i64) < 0 {
1377 None
1378 } else {
1379 Some(dts)
1380 }
1381 } else {
1382 Some(pts_val)
1383 };
1384 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1385 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1386 if self.cur_sample >= self.chunk_sizes.len() {
1387 return None;
1388 }
1389 let offset = self.chunk_offsets[self.cur_sample];
1390 let size = self.chunk_sizes[self.cur_sample] as usize;
1391 self.cur_sample += 1;
1392 Some((pts, offset, size))
1393 } else {
1394 if self.samples_left == 0 {
1395 if self.cur_chunk >= self.chunk_offsets.len() {
1396 return None;
1397 }
1398 for (idx, samples) in self.sample_map.iter() {
1399 if *idx as usize <= self.cur_chunk + 1 {
1400 self.samples_left = *samples as usize;
1401 } else {
1402 break;
1403 }
1404 }
1405 self.last_offset = self.chunk_offsets[self.cur_chunk];
1406 self.cur_chunk += 1;
1407 }
1408 let offset = self.last_offset;
1409 let size = self.get_size(self.cur_sample);
1410 self.last_offset += size as u64;
1411 if self.stream_type == StreamType::Video {
1412 self.samples_left -= 1;
1413 } else if self.frame_samples != 0 && self.bsize != 0 {
1414 let nblocks = size / self.bsize;
1415 if self.raw_audio {
1416 pts.pts = Some(self.raw_apos);
1417 pts.duration = Some(nblocks as u64);
1418 self.raw_apos += nblocks as u64;
1419 }
1420 if nblocks > 0 {
1421 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1422 self.samples_left -= consumed;
1423 } else {
1424 self.samples_left = 0;
1425 }
1426 } else if !self.raw_audio {
1427 self.samples_left -= 1;
1428 } else {
1429 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1430 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1431 let cur_size = self.calculate_chunk_size(self.samples_left);
1432 let add_off = (size - cur_size) as u64;
1433 let dsize = cur_size.min(max_size);
1434 if self.samples_left >= BLOCK_SAMPLES {
1435 self.cur_sample += BLOCK_SAMPLES;
1436 self.samples_left -= BLOCK_SAMPLES;
1437 self.last_offset -= size as u64;
1438 } else {
1439 self.cur_sample += self.samples_left;
1440 self.samples_left = 0;
1441 }
1442 return Some((pts, offset + add_off, dsize));
1443 }
1444 self.cur_sample += 1;
1445 Some((pts, offset, size))
1446 }
1447 }
1448 fn get_size(&self, sample_no: usize) -> usize {
1449 if !self.chunk_sizes.is_empty() {
1450 self.chunk_sizes[sample_no] as usize
1451 } else if !self.sample_map.is_empty() {
1452 let mut nsamp = 0;
1453 for (idx, samples) in self.sample_map.iter() {
1454 if *idx as usize <= self.cur_chunk {
1455 nsamp = *samples;
1456 } else {
1457 break;
1458 }
1459 }
1460 self.calculate_chunk_size(nsamp as usize)
1461 } else {
1462 self.bsize
1463 }
1464 }
1465 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<u64> {
1466 self.cur_sample = pts as usize;
1467 self.samples_left = 0;
1468 self.cur_ts = None;
1469 if self.stream_type == StreamType::Audio {
1470 if let NATimePoint::Milliseconds(ms) = tpoint {
1471 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1472 if self.raw_audio {
1473 if self.frame_samples != 0 {
1474 self.raw_apos = exp_pts / (self.frame_samples as u64);
1475 let mut apos = 0;
1476 self.cur_sample = 0;
1477 self.cur_chunk = 0;
1478 let mut cmap = self.sample_map.iter();
1479 let mut cur_samps = 0;
1480 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1481 loop {
1482 if self.cur_chunk + 1 == next_idx as usize {
1483 self.samples_left = cur_samps;
1484 cur_samps = next_samples as usize;
1485 if let Some((new_idx, new_samples)) = cmap.next() {
1486 next_idx = *new_idx;
1487 next_samples = *new_samples;
1488 }
1489 }
1490 self.raw_apos = apos;
1491 apos += (cur_samps / self.frame_samples) as u64;
1492 if apos > exp_pts && (cur_samps == self.frame_samples || apos > exp_pts + 1) {
1493 if self.cur_chunk >= self.chunk_offsets.len() {
1494 return Err(DemuxerError::SeekError);
1495 }
1496 self.last_offset = self.chunk_offsets[self.cur_chunk];
1497 break;
1498 }
1499 self.cur_chunk += 1;
1500 }
1501 self.samples_left = cur_samps;
1502 self.cur_chunk += 1;
1503 } else {
1504 self.raw_apos = exp_pts;
1505 self.cur_sample = exp_pts as usize;
1506 let mut csamp = 0;
1507 self.cur_chunk = 0;
1508 let mut cmap = self.sample_map.iter();
1509 let mut cur_samps = 0;
1510 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1511 loop {
1512 if self.cur_chunk + 1 == next_idx as usize {
1513 self.samples_left = cur_samps;
1514 cur_samps = next_samples as usize;
1515 if let Some((new_idx, new_samples)) = cmap.next() {
1516 next_idx = *new_idx;
1517 next_samples = *new_samples;
1518 }
1519 }
1520 csamp += cur_samps;
1521 if csamp > self.cur_sample {
1522 if self.cur_chunk >= self.chunk_offsets.len() {
1523 return Err(DemuxerError::SeekError);
1524 }
1525 self.last_offset = self.chunk_offsets[self.cur_chunk];
1526 break;
1527 }
1528 self.cur_chunk += 1;
1529 }
1530 self.samples_left = csamp - self.cur_sample;
1531 self.cur_chunk += 1;
1532 }
1533 } else if self.chunk_offsets.len() == self.chunk_sizes.len() && self.duration != 0 {
1534 let new_sample = (self.chunk_sizes.len() as u64 * exp_pts / u64::from(self.duration)) as usize;
1535 self.cur_sample = new_sample;
1536 self.cur_chunk = self.cur_sample;
1537 } else {
1538 if !self.time_to_sample.is_empty() {
1539 let mut remaining = exp_pts;
1540 let mut abs_csamp = 0;
1541 for &(count, scount) in self.time_to_sample.iter() {
1542 let count = u64::from(count);
1543 let scount = u64::from(scount);
1544 let nblk = remaining / scount;
1545 if nblk < count {
1546 abs_csamp += nblk;
1547 break;
1548 }
1549 remaining -= count * scount;
1550 abs_csamp += count;
1551 }
1552 self.cur_sample = abs_csamp as usize;
1553 } else {
1554 self.cur_sample = exp_pts as usize;
1555 }
1556 let tgt_sample = self.cur_sample;
1557 let mut csamp = 0;
1558 self.cur_chunk = 0;
1559 let mut cmap = self.sample_map.iter();
1560 let mut cur_samps = 0;
1561 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1562 loop {
1563 if self.cur_chunk + 1 == next_idx as usize {
1564 self.samples_left = cur_samps;
1565 cur_samps = next_samples as usize;
1566 if let Some((new_idx, new_samples)) = cmap.next() {
1567 next_idx = *new_idx;
1568 next_samples = *new_samples;
1569 }
1570 }
1571 csamp += cur_samps;
1572 if csamp > self.cur_sample {
1573 if self.cur_chunk >= self.chunk_offsets.len() {
1574 self.cur_sample = csamp - cur_samps;
1575 self.samples_left = 0;
1576 self.cur_sample = csamp;
1577 return Err(DemuxerError::SeekError);
1578 }
1579 self.last_offset = self.chunk_offsets[self.cur_chunk];
1580 break;
1581 }
1582 self.cur_chunk += 1;
1583 }
1584 self.cur_sample = csamp - cur_samps;
1585 self.samples_left = cur_samps;
1586 self.last_offset = self.chunk_offsets[self.cur_chunk];
1587 self.cur_chunk += 1;
1588
1589 // try to refine sample position
1590 if self.chunk_sizes.len() > self.chunk_offsets.len() {
1591 for i in self.cur_sample..tgt_sample {
1592 self.cur_sample += 1;
1593 self.samples_left -= 1;
1594 self.last_offset += u64::from(self.chunk_sizes[i]);
1595 }
1596 }
1597 }
1598 } else {
1599 self.cur_chunk = self.cur_sample;
1600 }
1601 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1602 let mut csamp = 0;
1603 self.cur_chunk = 0;
1604 let mut cmap = self.sample_map.iter();
1605 let mut cur_samps = 0;
1606 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1607 loop {
1608 if self.cur_chunk + 1 == next_idx as usize {
1609 self.samples_left = cur_samps;
1610 cur_samps = next_samples as usize;
1611 if let Some((new_idx, new_samples)) = cmap.next() {
1612 next_idx = *new_idx;
1613 next_samples = *new_samples;
1614 }
1615 }
1616 csamp += cur_samps;
1617 if csamp >= self.cur_sample {
1618 if self.cur_chunk >= self.chunk_offsets.len() {
1619 return Err(DemuxerError::SeekError);
1620 }
1621 self.last_offset = self.chunk_offsets[self.cur_chunk];
1622 break;
1623 }
1624 self.cur_chunk += 1;
1625 }
1626 csamp -= cur_samps;
1627 for sample_no in csamp..self.cur_sample {
1628 self.last_offset += self.get_size(sample_no) as u64;
1629 }
1630 self.samples_left = csamp + cur_samps - self.cur_sample;
1631 self.cur_chunk += 1;
1632 }
1633 let cur_pts = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1634 let cur_time = NATimeInfo::ts_to_time(cur_pts, 1000, self.tb_num, self.tb_den);
1635 Ok(cur_time)
1636 }
1637 }
1638
1639 fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1640 if let Some(cpts) = pts.get_pts() {
1641 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1642 track.cur_ts = Some(ts);
1643 } else {
1644 track.cur_ts = None;
1645 }
1646 let stream = strmgr.get_stream(track.track_str_id);
1647 if stream.is_none() { return Err(DemuxerError::InvalidData); }
1648 let stream = stream.unwrap();
1649 src.seek(SeekFrom::Start(offset))?;
1650 let mut pkt = src.read_packet(stream, pts, false, size)?;
1651 if let Some(ref pal) = track.pal {
1652 let side_data = NASideData::Palette(first, pal.clone());
1653 pkt.add_side_data(side_data);
1654 }
1655 Ok(pkt)
1656 }
1657
1658 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1659 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1660 let mut data_start = 0;
1661 match self.demux_mode {
1662 DemuxMode::Normal => self.read_root(strmgr)?,
1663 DemuxMode::MacBin => {
1664 let ver = self.src.read_byte()?;
1665 validate!(ver == 0);
1666 self.src.read_skip(64)?;
1667 let tag = self.src.read_tag()?;
1668 validate!(&tag == b"MooV");
1669 self.src.read_skip(14)?;
1670 let data_length = self.src.read_u32be()?;
1671 validate!(data_length > 8);
1672 let rsrc_length = self.src.read_u32be()?;
1673 validate!(rsrc_length > 0);
1674 self.src.read_skip(31)?;
1675 let ver = self.src.read_byte()?;
1676 validate!(ver == 0x81);
1677 let ver = self.src.read_byte()?;
1678 validate!(ver == 0x81);
1679 //xxx: maybe check header CRC
1680
1681 let rsrc_start = 0x80 + ((data_length + 0x7F) & !0x7F);
1682 self.src.seek(SeekFrom::Start(rsrc_start.into()))?;
1683 let rsrc_off = self.src.read_u32be()?;
1684 let rsrc_map_off = self.src.read_u32be()?;
1685 let rsrc_size = self.src.read_u32be()?;
1686 let _rsrc_map_size = self.src.read_u32be()?;
1687 validate!(rsrc_off >= 0x10);
1688 validate!(rsrc_map_off >= rsrc_off + rsrc_size);
1689 self.src.seek(SeekFrom::Current(i64::from(rsrc_off - 16)))?;
1690 // I'm too lazy to parse resource map, so let's just iterate over resources for movie header
1691 let end_pos = u64::from(rsrc_start + rsrc_off + rsrc_size);
1692 let mut peek_buf = [0u8; 8];
1693 while self.src.tell() < end_pos {
1694 let cur_size = self.src.read_u32be()?;
1695 validate!(self.src.tell() + u64::from(cur_size) <= end_pos);
1696 if cur_size > 8 {
1697 let rsize = self.src.peek_u32be()?;
1698 if rsize == cur_size {
1699 self.src.peek_buf(&mut peek_buf)?;
1700 if &peek_buf[4..] == b"moov" {
1701 self.src.read_skip(8)?;
1702 self.read_moov(strmgr, rsize.into())?;
1703 self.mdat_pos = 8;
1704 break;
1705 }
1706 }
1707 }
1708 self.src.read_skip(cur_size as usize)?;
1709 }
1710 },
1711 DemuxMode::ResFork => {
1712 let res_data_offset = self.src.read_u32be()?;
1713 let res_map_offset = self.src.read_u32be()?;
1714 let res_map_data_len = self.src.read_u32be()?;
1715 let res_map_length = self.src.read_u32be()?;
1716 validate!(res_data_offset == 0x100 && res_map_length > 16);
1717 self.src.seek(SeekFrom::Start(u64::from(res_map_offset)))?;
1718 let res_data_offset2 = self.src.read_u32be()?;
1719 let res_map_offset2 = self.src.read_u32be()?;
1720 let res_map_data_len2 = self.src.read_u32be()?;
1721 let res_map_length2 = self.src.read_u32be()?;
1722 validate!(res_data_offset == res_data_offset2
1723 && res_map_offset == res_map_offset2
1724 && res_map_data_len == res_map_data_len2
1725 && res_map_length == res_map_length2);
1726 self.src.read_skip(res_map_length as usize - 16)?;
1727 data_start = self.src.tell();
1728 self.read_root(strmgr)?;
1729 },
1730 };
1731 validate!(self.mdat_pos > 0);
1732 validate!(!self.tracks.is_empty());
1733 for track in self.tracks.iter_mut() {
1734 let mut strm = None;
1735 std::mem::swap(&mut track.stream, &mut strm);
1736 if let Some(stream) = strm {
1737 let str_id = strmgr.add_stream(stream).unwrap();
1738 track.track_str_id = str_id;
1739 }
1740 }
1741 match self.demux_mode {
1742 DemuxMode::MacBin => {
1743 // patch data offsets
1744 for track in self.tracks.iter_mut() {
1745 for offset in track.chunk_offsets.iter_mut() {
1746 *offset += 0x80;
1747 }
1748 }
1749 },
1750 DemuxMode::ResFork => {
1751 // patch data offsets
1752 for track in self.tracks.iter_mut() {
1753 for offset in track.chunk_offsets.iter_mut() {
1754 *offset += data_start;
1755 }
1756 }
1757 },
1758 _ => {},
1759 }
1760 for track in self.tracks.iter() {
1761 track.fill_seek_index(seek_index);
1762 }
1763 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1764 self.cur_track = 0;
1765 Ok(())
1766 }
1767
1768 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1769 if self.tracks.is_empty() {
1770 return Err(DemuxerError::EOF);
1771 }
1772 let mut has_all_time = true;
1773 let mut min_ts = u64::MAX;
1774 for trk in self.tracks.iter() {
1775 if let Some(ts) = trk.cur_ts {
1776 min_ts = min_ts.min(ts);
1777 } else {
1778 has_all_time = false;
1779 break;
1780 }
1781 }
1782 if has_all_time {
1783 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1784 if let Some(ts) = track.cur_ts {
1785 if ts == min_ts {
1786 let first = track.cur_sample == 0;
1787 if let Some((pts, offset, size)) = track.get_next_chunk() {
1788 self.cur_track = trk_no + 1;
1789 return process_packet(self.src, strmgr, track, pts, offset, size, first);
1790 }
1791 }
1792 }
1793 }
1794 }
1795
1796 for _ in 0..self.tracks.len() {
1797 if self.cur_track >= self.tracks.len() {
1798 self.cur_track = 0;
1799 }
1800 let track = &mut self.tracks[self.cur_track];
1801 self.cur_track += 1;
1802 let first = track.cur_sample == 0;
1803 if let Some((pts, offset, size)) = track.get_next_chunk() {
1804 return process_packet(self.src, strmgr, track, pts, offset, size, first);
1805 }
1806 }
1807 Err(DemuxerError::EOF)
1808 }
1809
1810 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1811 let ret = seek_index.find_pos(time);
1812 if ret.is_none() {
1813 if let NATimePoint::Milliseconds(_) = time {
1814 let mut aonly = true;
1815 for track in self.tracks.iter() {
1816 if track.stream_type != StreamType::Audio {
1817 aonly = false;
1818 break;
1819 }
1820 }
1821 if aonly {
1822 for track in self.tracks.iter_mut() {
1823 track.seek(0, time)?;
1824 }
1825 return Ok(());
1826 }
1827 }
1828 return Err(DemuxerError::SeekError);
1829 }
1830 let seek_info = ret.unwrap();
1831 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1832 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
1833 let mut vpts = None;
1834 let mut apts = None;
1835 for track in self.tracks.iter_mut() {
1836 let cur_pts = if track.track_id == seek_info.str_id {
1837 seek_info.pts
1838 } else {
1839 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1840 };
1841 let actual_time = track.seek(cur_pts, time)?;
1842 match track.stream_type {
1843 StreamType::Video => vpts = Some(actual_time),
1844 StreamType::Audio => apts = Some(actual_time),
1845 _ => {},
1846 };
1847 }
1848 /* For audio+video stream case when the post-seek actual times differ
1849 by more than half a second try to seek audio to a closer position
1850 to video.
1851 */
1852 if let (true, Some(vtime), Some(atime)) = (self.tracks.len() == 2, vpts, apts) {
1853 if vtime.max(atime) - vtime.min(atime) > 500 && atime != 0 {
1854 for track in self.tracks.iter_mut() {
1855 if track.stream_type == StreamType::Audio {
1856 let new_pts = NATimeInfo::time_to_ts(vtime, 1000, track.tb_num, track.tb_den);
1857 track.seek(new_pts, NATimePoint::Milliseconds(vtime))?;
1858 }
1859 }
1860 }
1861 }
1862
1863 Ok(())
1864 }
1865 fn get_duration(&self) -> u64 {
1866 if self.tb_den != 0 {
1867 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1868 } else {
1869 0
1870 }
1871 }
1872 }
1873
1874 const PRINT_CHUNKS: &str = "print_chunks";
1875
1876 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1877 NAOptionDefinition {
1878 name: PRINT_CHUNKS,
1879 description: "Print parsed file structure",
1880 opt_type: NAOptionDefinitionType::Bool },
1881 ];
1882
1883 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1884 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1885 #[allow(clippy::single_match)]
1886 fn set_options(&mut self, options: &[NAOption]) {
1887 for option in options.iter() {
1888 for opt_def in DEMUXER_OPTIONS.iter() {
1889 if opt_def.check(option).is_ok() {
1890 match (option.name, &option.value) {
1891 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1892 self.print_chunks = *val;
1893 },
1894 _ => {},
1895 }
1896 }
1897 }
1898 }
1899 }
1900 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1901 match name {
1902 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1903 _ => None,
1904 }
1905 }
1906 }
1907
1908 impl<'a> MOVDemuxer<'a> {
1909 fn new(io: &'a mut ByteReader<'a>) -> Self {
1910 Self::new_common(io, DemuxMode::Normal)
1911 }
1912 fn new_macbinary(io: &'a mut ByteReader<'a>) -> Self {
1913 Self::new_common(io, DemuxMode::MacBin)
1914 }
1915 fn new_resfork(io: &'a mut ByteReader<'a>) -> Self {
1916 Self::new_common(io, DemuxMode::ResFork)
1917 }
1918 fn new_common(io: &'a mut ByteReader<'a>, demux_mode: DemuxMode,) -> Self {
1919 MOVDemuxer {
1920 src: io,
1921 depth: 0,
1922 mdat_pos: 0,
1923 mdat_size: 0,
1924 tracks: Vec::with_capacity(2),
1925 cur_track: 0,
1926 tb_den: 0,
1927 duration: 0,
1928 pal: None,
1929
1930 moof_off: 0,
1931
1932 print_chunks: false,
1933
1934 demux_mode,
1935 }
1936 }
1937 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1938 self.depth = 0;
1939 while self.src.left() != 0 {
1940 let ret = read_chunk_header(self.src);
1941 if ret.is_err() { break; }
1942 let (ctype, size) = ret.unwrap();
1943 if self.print_chunks {
1944 print_cname(ctype, size, self.src.tell(), 0);
1945 }
1946 if IGNORED_CHUNKS.contains(&ctype) {
1947 self.src.skip64(size)?;
1948 continue;
1949 }
1950 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1951 let read_size;
1952 if let Some(handler) = handler {
1953 read_size = (handler.parse)(self, strmgr, size)?;
1954 } else {
1955 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1956 read_size = 0;
1957 }
1958 validate!(read_size <= size);
1959 self.src.skip64(size - read_size)?;
1960 }
1961 //todo check if all needed chunks are found
1962 Ok(())
1963 }
1964 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1965 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
1966 }
1967
1968 pub struct MOVDemuxerCreator { }
1969
1970 impl DemuxerCreator for MOVDemuxerCreator {
1971 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1972 Box::new(MOVDemuxer::new(br))
1973 }
1974 fn get_name(&self) -> &'static str { "mov" }
1975 }
1976
1977 pub struct MacBinaryMOVDemuxerCreator { }
1978
1979 impl DemuxerCreator for MacBinaryMOVDemuxerCreator {
1980 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1981 Box::new(MOVDemuxer::new_macbinary(br))
1982 }
1983 fn get_name(&self) -> &'static str { "mov-macbin" }
1984 }
1985
1986 pub struct MacResForkMOVDemuxerCreator { }
1987
1988 impl DemuxerCreator for MacResForkMOVDemuxerCreator {
1989 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1990 Box::new(MOVDemuxer::new_resfork(br))
1991 }
1992 fn get_name(&self) -> &'static str { "mov-resfork" }
1993 }
1994
1995 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1996 0x93, 0x65, 0x5E, 0x00,
1997 0xFF, 0xFF, 0xFF, 0x00,
1998 0xDF, 0xD0, 0xAB, 0x00,
1999 0x00, 0x00, 0x00, 0x00
2000 ];
2001 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
2002 0xFF, 0xFB, 0xFF, 0x00,
2003 0xEF, 0xD9, 0xBB, 0x00,
2004 0xE8, 0xC9, 0xB1, 0x00,
2005 0x93, 0x65, 0x5E, 0x00,
2006 0xFC, 0xDE, 0xE8, 0x00,
2007 0x9D, 0x88, 0x91, 0x00,
2008 0xFF, 0xFF, 0xFF, 0x00,
2009 0xFF, 0xFF, 0xFF, 0x00,
2010 0xFF, 0xFF, 0xFF, 0x00,
2011 0x47, 0x48, 0x37, 0x00,
2012 0x7A, 0x5E, 0x55, 0x00,
2013 0xDF, 0xD0, 0xAB, 0x00,
2014 0xFF, 0xFB, 0xF9, 0x00,
2015 0xE8, 0xCA, 0xC5, 0x00,
2016 0x8A, 0x7C, 0x77, 0x00,
2017 0x00, 0x00, 0x00, 0x00
2018 ];
2019 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
2020 0xFF, 0xFF, 0xFF, 0x00,
2021 0xFF, 0xFF, 0xCC, 0x00,
2022 0xFF, 0xFF, 0x99, 0x00,
2023 0xFF, 0xFF, 0x66, 0x00,
2024 0xFF, 0xFF, 0x33, 0x00,
2025 0xFF, 0xFF, 0x00, 0x00,
2026 0xFF, 0xCC, 0xFF, 0x00,
2027 0xFF, 0xCC, 0xCC, 0x00,
2028 0xFF, 0xCC, 0x99, 0x00,
2029 0xFF, 0xCC, 0x66, 0x00,
2030 0xFF, 0xCC, 0x33, 0x00,
2031 0xFF, 0xCC, 0x00, 0x00,
2032 0xFF, 0x99, 0xFF, 0x00,
2033 0xFF, 0x99, 0xCC, 0x00,
2034 0xFF, 0x99, 0x99, 0x00,
2035 0xFF, 0x99, 0x66, 0x00,
2036 0xFF, 0x99, 0x33, 0x00,
2037 0xFF, 0x99, 0x00, 0x00,
2038 0xFF, 0x66, 0xFF, 0x00,
2039 0xFF, 0x66, 0xCC, 0x00,
2040 0xFF, 0x66, 0x99, 0x00,
2041 0xFF, 0x66, 0x66, 0x00,
2042 0xFF, 0x66, 0x33, 0x00,
2043 0xFF, 0x66, 0x00, 0x00,
2044 0xFF, 0x33, 0xFF, 0x00,
2045 0xFF, 0x33, 0xCC, 0x00,
2046 0xFF, 0x33, 0x99, 0x00,
2047 0xFF, 0x33, 0x66, 0x00,
2048 0xFF, 0x33, 0x33, 0x00,
2049 0xFF, 0x33, 0x00, 0x00,
2050 0xFF, 0x00, 0xFF, 0x00,
2051 0xFF, 0x00, 0xCC, 0x00,
2052 0xFF, 0x00, 0x99, 0x00,
2053 0xFF, 0x00, 0x66, 0x00,
2054 0xFF, 0x00, 0x33, 0x00,
2055 0xFF, 0x00, 0x00, 0x00,
2056 0xCC, 0xFF, 0xFF, 0x00,
2057 0xCC, 0xFF, 0xCC, 0x00,
2058 0xCC, 0xFF, 0x99, 0x00,
2059 0xCC, 0xFF, 0x66, 0x00,
2060 0xCC, 0xFF, 0x33, 0x00,
2061 0xCC, 0xFF, 0x00, 0x00,
2062 0xCC, 0xCC, 0xFF, 0x00,
2063 0xCC, 0xCC, 0xCC, 0x00,
2064 0xCC, 0xCC, 0x99, 0x00,
2065 0xCC, 0xCC, 0x66, 0x00,
2066 0xCC, 0xCC, 0x33, 0x00,
2067 0xCC, 0xCC, 0x00, 0x00,
2068 0xCC, 0x99, 0xFF, 0x00,
2069 0xCC, 0x99, 0xCC, 0x00,
2070 0xCC, 0x99, 0x99, 0x00,
2071 0xCC, 0x99, 0x66, 0x00,
2072 0xCC, 0x99, 0x33, 0x00,
2073 0xCC, 0x99, 0x00, 0x00,
2074 0xCC, 0x66, 0xFF, 0x00,
2075 0xCC, 0x66, 0xCC, 0x00,
2076 0xCC, 0x66, 0x99, 0x00,
2077 0xCC, 0x66, 0x66, 0x00,
2078 0xCC, 0x66, 0x33, 0x00,
2079 0xCC, 0x66, 0x00, 0x00,
2080 0xCC, 0x33, 0xFF, 0x00,
2081 0xCC, 0x33, 0xCC, 0x00,
2082 0xCC, 0x33, 0x99, 0x00,
2083 0xCC, 0x33, 0x66, 0x00,
2084 0xCC, 0x33, 0x33, 0x00,
2085 0xCC, 0x33, 0x00, 0x00,
2086 0xCC, 0x00, 0xFF, 0x00,
2087 0xCC, 0x00, 0xCC, 0x00,
2088 0xCC, 0x00, 0x99, 0x00,
2089 0xCC, 0x00, 0x66, 0x00,
2090 0xCC, 0x00, 0x33, 0x00,
2091 0xCC, 0x00, 0x00, 0x00,
2092 0x99, 0xFF, 0xFF, 0x00,
2093 0x99, 0xFF, 0xCC, 0x00,
2094 0x99, 0xFF, 0x99, 0x00,
2095 0x99, 0xFF, 0x66, 0x00,
2096 0x99, 0xFF, 0x33, 0x00,
2097 0x99, 0xFF, 0x00, 0x00,
2098 0x99, 0xCC, 0xFF, 0x00,
2099 0x99, 0xCC, 0xCC, 0x00,
2100 0x99, 0xCC, 0x99, 0x00,
2101 0x99, 0xCC, 0x66, 0x00,
2102 0x99, 0xCC, 0x33, 0x00,
2103 0x99, 0xCC, 0x00, 0x00,
2104 0x99, 0x99, 0xFF, 0x00,
2105 0x99, 0x99, 0xCC, 0x00,
2106 0x99, 0x99, 0x99, 0x00,
2107 0x99, 0x99, 0x66, 0x00,
2108 0x99, 0x99, 0x33, 0x00,
2109 0x99, 0x99, 0x00, 0x00,
2110 0x99, 0x66, 0xFF, 0x00,
2111 0x99, 0x66, 0xCC, 0x00,
2112 0x99, 0x66, 0x99, 0x00,
2113 0x99, 0x66, 0x66, 0x00,
2114 0x99, 0x66, 0x33, 0x00,
2115 0x99, 0x66, 0x00, 0x00,
2116 0x99, 0x33, 0xFF, 0x00,
2117 0x99, 0x33, 0xCC, 0x00,
2118 0x99, 0x33, 0x99, 0x00,
2119 0x99, 0x33, 0x66, 0x00,
2120 0x99, 0x33, 0x33, 0x00,
2121 0x99, 0x33, 0x00, 0x00,
2122 0x99, 0x00, 0xFF, 0x00,
2123 0x99, 0x00, 0xCC, 0x00,
2124 0x99, 0x00, 0x99, 0x00,
2125 0x99, 0x00, 0x66, 0x00,
2126 0x99, 0x00, 0x33, 0x00,
2127 0x99, 0x00, 0x00, 0x00,
2128 0x66, 0xFF, 0xFF, 0x00,
2129 0x66, 0xFF, 0xCC, 0x00,
2130 0x66, 0xFF, 0x99, 0x00,
2131 0x66, 0xFF, 0x66, 0x00,
2132 0x66, 0xFF, 0x33, 0x00,
2133 0x66, 0xFF, 0x00, 0x00,
2134 0x66, 0xCC, 0xFF, 0x00,
2135 0x66, 0xCC, 0xCC, 0x00,
2136 0x66, 0xCC, 0x99, 0x00,
2137 0x66, 0xCC, 0x66, 0x00,
2138 0x66, 0xCC, 0x33, 0x00,
2139 0x66, 0xCC, 0x00, 0x00,
2140 0x66, 0x99, 0xFF, 0x00,
2141 0x66, 0x99, 0xCC, 0x00,
2142 0x66, 0x99, 0x99, 0x00,
2143 0x66, 0x99, 0x66, 0x00,
2144 0x66, 0x99, 0x33, 0x00,
2145 0x66, 0x99, 0x00, 0x00,
2146 0x66, 0x66, 0xFF, 0x00,
2147 0x66, 0x66, 0xCC, 0x00,
2148 0x66, 0x66, 0x99, 0x00,
2149 0x66, 0x66, 0x66, 0x00,
2150 0x66, 0x66, 0x33, 0x00,
2151 0x66, 0x66, 0x00, 0x00,
2152 0x66, 0x33, 0xFF, 0x00,
2153 0x66, 0x33, 0xCC, 0x00,
2154 0x66, 0x33, 0x99, 0x00,
2155 0x66, 0x33, 0x66, 0x00,
2156 0x66, 0x33, 0x33, 0x00,
2157 0x66, 0x33, 0x00, 0x00,
2158 0x66, 0x00, 0xFF, 0x00,
2159 0x66, 0x00, 0xCC, 0x00,
2160 0x66, 0x00, 0x99, 0x00,
2161 0x66, 0x00, 0x66, 0x00,
2162 0x66, 0x00, 0x33, 0x00,
2163 0x66, 0x00, 0x00, 0x00,
2164 0x33, 0xFF, 0xFF, 0x00,
2165 0x33, 0xFF, 0xCC, 0x00,
2166 0x33, 0xFF, 0x99, 0x00,
2167 0x33, 0xFF, 0x66, 0x00,
2168 0x33, 0xFF, 0x33, 0x00,
2169 0x33, 0xFF, 0x00, 0x00,
2170 0x33, 0xCC, 0xFF, 0x00,
2171 0x33, 0xCC, 0xCC, 0x00,
2172 0x33, 0xCC, 0x99, 0x00,
2173 0x33, 0xCC, 0x66, 0x00,
2174 0x33, 0xCC, 0x33, 0x00,
2175 0x33, 0xCC, 0x00, 0x00,
2176 0x33, 0x99, 0xFF, 0x00,
2177 0x33, 0x99, 0xCC, 0x00,
2178 0x33, 0x99, 0x99, 0x00,
2179 0x33, 0x99, 0x66, 0x00,
2180 0x33, 0x99, 0x33, 0x00,
2181 0x33, 0x99, 0x00, 0x00,
2182 0x33, 0x66, 0xFF, 0x00,
2183 0x33, 0x66, 0xCC, 0x00,
2184 0x33, 0x66, 0x99, 0x00,
2185 0x33, 0x66, 0x66, 0x00,
2186 0x33, 0x66, 0x33, 0x00,
2187 0x33, 0x66, 0x00, 0x00,
2188 0x33, 0x33, 0xFF, 0x00,
2189 0x33, 0x33, 0xCC, 0x00,
2190 0x33, 0x33, 0x99, 0x00,
2191 0x33, 0x33, 0x66, 0x00,
2192 0x33, 0x33, 0x33, 0x00,
2193 0x33, 0x33, 0x00, 0x00,
2194 0x33, 0x00, 0xFF, 0x00,
2195 0x33, 0x00, 0xCC, 0x00,
2196 0x33, 0x00, 0x99, 0x00,
2197 0x33, 0x00, 0x66, 0x00,
2198 0x33, 0x00, 0x33, 0x00,
2199 0x33, 0x00, 0x00, 0x00,
2200 0x00, 0xFF, 0xFF, 0x00,
2201 0x00, 0xFF, 0xCC, 0x00,
2202 0x00, 0xFF, 0x99, 0x00,
2203 0x00, 0xFF, 0x66, 0x00,
2204 0x00, 0xFF, 0x33, 0x00,
2205 0x00, 0xFF, 0x00, 0x00,
2206 0x00, 0xCC, 0xFF, 0x00,
2207 0x00, 0xCC, 0xCC, 0x00,
2208 0x00, 0xCC, 0x99, 0x00,
2209 0x00, 0xCC, 0x66, 0x00,
2210 0x00, 0xCC, 0x33, 0x00,
2211 0x00, 0xCC, 0x00, 0x00,
2212 0x00, 0x99, 0xFF, 0x00,
2213 0x00, 0x99, 0xCC, 0x00,
2214 0x00, 0x99, 0x99, 0x00,
2215 0x00, 0x99, 0x66, 0x00,
2216 0x00, 0x99, 0x33, 0x00,
2217 0x00, 0x99, 0x00, 0x00,
2218 0x00, 0x66, 0xFF, 0x00,
2219 0x00, 0x66, 0xCC, 0x00,
2220 0x00, 0x66, 0x99, 0x00,
2221 0x00, 0x66, 0x66, 0x00,
2222 0x00, 0x66, 0x33, 0x00,
2223 0x00, 0x66, 0x00, 0x00,
2224 0x00, 0x33, 0xFF, 0x00,
2225 0x00, 0x33, 0xCC, 0x00,
2226 0x00, 0x33, 0x99, 0x00,
2227 0x00, 0x33, 0x66, 0x00,
2228 0x00, 0x33, 0x33, 0x00,
2229 0x00, 0x33, 0x00, 0x00,
2230 0x00, 0x00, 0xFF, 0x00,
2231 0x00, 0x00, 0xCC, 0x00,
2232 0x00, 0x00, 0x99, 0x00,
2233 0x00, 0x00, 0x66, 0x00,
2234 0x00, 0x00, 0x33, 0x00,
2235 0xEE, 0x00, 0x00, 0x00,
2236 0xDD, 0x00, 0x00, 0x00,
2237 0xBB, 0x00, 0x00, 0x00,
2238 0xAA, 0x00, 0x00, 0x00,
2239 0x88, 0x00, 0x00, 0x00,
2240 0x77, 0x00, 0x00, 0x00,
2241 0x55, 0x00, 0x00, 0x00,
2242 0x44, 0x00, 0x00, 0x00,
2243 0x22, 0x00, 0x00, 0x00,
2244 0x11, 0x00, 0x00, 0x00,
2245 0x00, 0xEE, 0x00, 0x00,
2246 0x00, 0xDD, 0x00, 0x00,
2247 0x00, 0xBB, 0x00, 0x00,
2248 0x00, 0xAA, 0x00, 0x00,
2249 0x00, 0x88, 0x00, 0x00,
2250 0x00, 0x77, 0x00, 0x00,
2251 0x00, 0x55, 0x00, 0x00,
2252 0x00, 0x44, 0x00, 0x00,
2253 0x00, 0x22, 0x00, 0x00,
2254 0x00, 0x11, 0x00, 0x00,
2255 0x00, 0x00, 0xEE, 0x00,
2256 0x00, 0x00, 0xDD, 0x00,
2257 0x00, 0x00, 0xBB, 0x00,
2258 0x00, 0x00, 0xAA, 0x00,
2259 0x00, 0x00, 0x88, 0x00,
2260 0x00, 0x00, 0x77, 0x00,
2261 0x00, 0x00, 0x55, 0x00,
2262 0x00, 0x00, 0x44, 0x00,
2263 0x00, 0x00, 0x22, 0x00,
2264 0x00, 0x00, 0x11, 0x00,
2265 0xEE, 0xEE, 0xEE, 0x00,
2266 0xDD, 0xDD, 0xDD, 0x00,
2267 0xBB, 0xBB, 0xBB, 0x00,
2268 0xAA, 0xAA, 0xAA, 0x00,
2269 0x88, 0x88, 0x88, 0x00,
2270 0x77, 0x77, 0x77, 0x00,
2271 0x55, 0x55, 0x55, 0x00,
2272 0x44, 0x44, 0x44, 0x00,
2273 0x22, 0x22, 0x22, 0x00,
2274 0x11, 0x11, 0x11, 0x00,
2275 0x00, 0x00, 0x00, 0x00
2276 ];
2277
2278 #[cfg(test)]
2279 mod test {
2280 use super::*;
2281 use std::fs::File;
2282
2283 #[test]
2284 fn test_mov_demux() {
2285 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/cubes.mov
2286 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2287 let mut fr = FileReader::new_read(&mut file);
2288 let mut br = ByteReader::new(&mut fr);
2289 let mut dmx = MOVDemuxer::new(&mut br);
2290 let mut sm = StreamManager::new();
2291 let mut si = SeekIndex::new();
2292 dmx.open(&mut sm, &mut si).unwrap();
2293
2294 loop {
2295 let pktres = dmx.get_frame(&mut sm);
2296 if let Err(e) = pktres {
2297 if e == DemuxerError::EOF { break; }
2298 panic!("error");
2299 }
2300 let pkt = pktres.unwrap();
2301 println!("Got {}", pkt);
2302 }
2303 }
2304
2305 #[test]
2306 fn test_dash_demux() {
2307 // sample: a stream downloaded with youtube-dl
2308 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2309 let mut fr = FileReader::new_read(&mut file);
2310 let mut br = ByteReader::new(&mut fr);
2311 let mut dmx = MOVDemuxer::new(&mut br);
2312 let mut sm = StreamManager::new();
2313 let mut si = SeekIndex::new();
2314 dmx.open(&mut sm, &mut si).unwrap();
2315
2316 loop {
2317 let pktres = dmx.get_frame(&mut sm);
2318 if let Err(e) = pktres {
2319 if e == DemuxerError::EOF { break; }
2320 panic!("error");
2321 }
2322 let pkt = pktres.unwrap();
2323 println!("Got {}", pkt);
2324 }
2325 }
2326
2327 #[test]
2328 fn test_macbinary_demux() {
2329 // sample from King's Quest VI Macintosh edition
2330 let mut file = File::open("assets/QT/Halfdome.bin").unwrap();
2331 let mut fr = FileReader::new_read(&mut file);
2332 let mut br = ByteReader::new(&mut fr);
2333 let mut dmx = MOVDemuxer::new_macbinary(&mut br);
2334 let mut sm = StreamManager::new();
2335 let mut si = SeekIndex::new();
2336 dmx.open(&mut sm, &mut si).unwrap();
2337
2338 loop {
2339 let pktres = dmx.get_frame(&mut sm);
2340 if let Err(e) = pktres {
2341 if e == DemuxerError::EOF { break; }
2342 panic!("error");
2343 }
2344 let pkt = pktres.unwrap();
2345 println!("Got {}", pkt);
2346 }
2347 }
2348
2349 #[test]
2350 fn test_resfork_demux() {
2351 // sample from The Wonders of Electricity: An Adventure in Safety
2352 let mut file = File::open("assets/QT/car.mov").unwrap();
2353 let mut fr = FileReader::new_read(&mut file);
2354 let mut br = ByteReader::new(&mut fr);
2355 let mut dmx = MOVDemuxer::new_resfork(&mut br);
2356 let mut sm = StreamManager::new();
2357 let mut si = SeekIndex::new();
2358 dmx.open(&mut sm, &mut si).unwrap();
2359
2360 loop {
2361 let pktres = dmx.get_frame(&mut sm);
2362 if let Err(e) = pktres {
2363 if e == DemuxerError::EOF { break; }
2364 panic!("error");
2365 }
2366 let pkt = pktres.unwrap();
2367 println!("Got {}", pkt);
2368 }
2369 }
2370 }