1 use nihav_core::demuxers::*;
2 use nihav_registry::register::*;
3 use nihav_core::compr::deflate::*;
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)
10 (($arr[0] as u32) << 24) | (($arr[1] as u32) << 16) | (($arr[2] as u32) << 8) | ($arr[3] as u32)
15 fn skip64(&mut self, size: u64) -> ByteIOResult<()>;
18 impl<'a> Skip64 for ByteReader<'a> {
19 fn skip64(&mut self, size: u64) -> ByteIOResult<()> {
20 if (size as usize as u64) != size {
21 self.seek(SeekFrom::Current(size as i64))?;
23 self.read_skip(size as usize)?;
29 fn read_chunk_header(br: &mut ByteReader) -> DemuxerResult<(u32, u64)> {
30 let size = br.read_u32be()?;
31 let ctype = br.read_u32be()?;
33 Ok((ctype, br.left() as u64))
35 let size64 = br.read_u64be()?;
36 validate!(size64 >= 16);
37 Ok((ctype, size64 - 16))
40 Ok((ctype, (size as u64) - 8))
44 fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
45 let _seed = br.read_u32be()?;
46 let flags = br.read_u16be()?;
47 let palsize = (br.read_u16be()? as usize) + 1;
48 validate!(palsize <= 256);
49 validate!(flags == 0 || flags == 0x4000 || flags == 0x8000);
50 validate!((palsize as u64) * 8 + 8 <= size);
52 let a = br.read_u16be()?;
53 let r = br.read_u16be()?;
54 let g = br.read_u16be()?;
55 let b = br.read_u16be()?;
56 pal[i * 4] = (r >> 8) as u8;
57 pal[i * 4 + 1] = (g >> 8) as u8;
58 pal[i * 4 + 2] = (b >> 8) as u8;
60 pal[i * 4 + 3] = (a >> 8) as u8;
69 struct RootChunkHandler {
71 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
74 struct TrackChunkHandler {
76 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
79 const IGNORED_CHUNKS: &[u32] = &[
80 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
83 const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
84 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
85 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
86 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
87 RootChunkHandler { ctype: mktag!(b"moof"), parse: read_moof },
88 RootChunkHandler { ctype: mktag!(b"sidx"), parse: read_sidx },
91 fn print_cname(ctype: u32, size: u64, off: u64, depth: u8) {
92 for _ in 0..depth { print!(" "); }
93 let tag = [(ctype >> 24) as u8, (ctype >> 16) as u8, (ctype >> 8) as u8, ctype as u8];
94 let mut printable = true;
95 for ch in tag.iter() {
96 if !(0x20..=0x7F).contains(ch) {
102 print!(" '{}{}{}{}'", tag[0] as char, tag[1] as char, tag[2] as char, tag[3] as char);
104 print!(" {:08X}", ctype);
106 println!(" size {} @ {:X}", size, off);
109 macro_rules! read_chunk_list {
110 (root; $name: expr, $fname: ident, $handlers: ident) => {
111 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
113 validate!(self.depth < 32);
114 let list_end = self.src.tell() + size;
115 while self.src.tell() < list_end {
116 let ret = read_chunk_header(self.src);
117 if ret.is_err() { break; }
118 let (ctype, size) = ret.unwrap();
119 if self.print_chunks {
120 print_cname(ctype, size, self.src.tell(), self.depth as u8);
122 if self.src.tell() + size > list_end {
125 if IGNORED_CHUNKS.contains(&ctype) {
126 self.src.skip64(size)?;
129 let handler = $handlers.iter().find(|x| x.ctype == ctype);
131 if let Some(ref handler) = handler {
132 read_size = (handler.parse)(self, strmgr, size)?;
134 println!("skipping unknown chunk {:08X} size {}", ctype, size);
137 validate!(read_size <= size);
138 self.src.skip64(size - read_size)?;
141 validate!(self.src.tell() == list_end);
145 (track; $name: expr, $fname: ident, $handlers: ident) => {
146 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
148 validate!(self.depth < 32);
149 let list_end = br.tell() + size;
150 while br.tell() < list_end {
151 let ret = read_chunk_header(br);
152 if ret.is_err() { break; }
153 let (ctype, size) = ret.unwrap();
154 if self.print_chunks {
155 print_cname(ctype, size, br.tell(), self.depth + 1);
157 if br.tell() + size > list_end {
160 if IGNORED_CHUNKS.contains(&ctype) {
164 let handler = $handlers.iter().find(|x| x.ctype == ctype);
166 if let Some(ref handler) = handler {
167 read_size = (handler.parse)(self, br, size)?;
171 validate!(read_size <= size);
172 br.skip64(size - read_size)?;
175 validate!(br.tell() == list_end);
181 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
186 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
187 dmx.src.skip64(size)?;
191 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
192 dmx.mdat_pos = dmx.src.tell();
193 dmx.mdat_size = size;
194 dmx.src.skip64(size)?;
198 fn read_sidx(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
202 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
203 dmx.read_moov(strmgr, size)?;
207 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
208 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
209 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
210 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
211 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
212 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
213 RootChunkHandler { ctype: mktag!(b"mvex"), parse: read_mvex },
214 RootChunkHandler { ctype: mktag!(b"iods"), parse: skip_chunk_mov },
217 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
218 const KNOWN_MVHD_SIZE: u64 = 100;
219 let br = &mut dmx.src;
220 validate!(size >= KNOWN_MVHD_SIZE);
221 let version = br.read_byte()?;
222 validate!(version == 0);
223 let _flags = br.read_u24be()?;
224 let _ctime = br.read_u32be()?;
225 let _mtime = br.read_u32be()?;
226 let tscale = br.read_u32be()?;
227 let duration = br.read_u32be()?;
228 let _pref_rate = br.read_u32be()?;
229 let _pref_volume = br.read_u16be()?;
231 br.read_skip(36)?; // matrix
232 let _preview_time = br.read_u32be()?;
233 let _preview_duration = br.read_u32be()?;
234 let _poster_time = br.read_u32be()?;
235 let _sel_time = br.read_u32be()?;
236 let _sel_duration = br.read_u32be()?;
237 let _cur_time = br.read_u32be()?;
238 let _next_track_id = br.read_u32be()?;
239 dmx.duration = duration;
245 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
246 let br = &mut dmx.src;
247 validate!(size > 24);
248 let dcom_size = br.read_u32be()?;
249 let dcom_tag = br.read_tag()?;
250 let compr_type = br.read_tag()?;
251 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
252 if &compr_type != b"zlib" {
253 return Err(DemuxerError::NotImplemented);
255 let cmvd_size = u64::from(br.read_u32be()?);
256 let cmvd_tag = br.read_tag()?;
257 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
258 let comp_size = (cmvd_size - 12) as usize;
259 let uncomp_size = br.read_u32be()? as usize;
260 validate!(uncomp_size > 8);
261 let mut sbuf = vec![0; comp_size];
262 let mut dbuf = vec![0; uncomp_size];
263 br.read_buf(sbuf.as_mut_slice())?;
264 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
266 return Err(DemuxerError::InvalidData);
268 let len = ret.unwrap();
269 validate!(len == uncomp_size);
270 let mut mr = MemoryReader::new_read(dbuf.as_slice());
271 let mut br = ByteReader::new(&mut mr);
272 let (ctype, csize) = read_chunk_header(&mut br)?;
273 validate!(ctype == mktag!(b"moov"));
274 let mut ddmx = MOVDemuxer::new(&mut br);
275 ddmx.print_chunks = dmx.print_chunks;
276 ddmx.read_moov(strmgr, csize)?;
277 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
278 dmx.duration = ddmx.duration;
279 dmx.tb_den = ddmx.tb_den;
280 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
285 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
286 let mut pal = [0; 1024];
287 let size = read_palette(dmx.src, size, &mut pal)?;
288 dmx.pal = Some(Arc::new(pal));
292 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
293 dmx.src.skip64(size)?;
297 fn read_mvex(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
301 fn skip_chunk_mov(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
305 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
306 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
307 track.print_chunks = dmx.print_chunks;
308 track.read_trak(dmx.src, size)?;
309 validate!(track.tkhd_found && track.stsd_found);
310 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
312 dmx.tracks.push(track);
316 fn read_moof(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
317 dmx.moof_off = dmx.src.tell() - 8;
318 dmx.read_moof(strmgr, size)?;
322 const MOOF_CHUNK_HANDLERS: &[RootChunkHandler] = &[
323 RootChunkHandler { ctype: mktag!(b"mfhd"), parse: read_mfhd },
324 RootChunkHandler { ctype: mktag!(b"traf"), parse: read_traf },
325 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
328 fn read_mfhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
329 const KNOWN_MFHD_SIZE: u64 = 8;
330 validate!(size >= KNOWN_MFHD_SIZE);
331 let version = dmx.src.read_byte()?;
332 validate!(version == 0);
333 let flags = dmx.src.read_u24be()?;
334 validate!(flags == 0);
335 let _seq_no = dmx.src.read_u32be()?;
340 fn read_traf(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
341 let mut buf = [0u8; 16];
342 dmx.src.peek_buf(&mut buf)?;
343 validate!(&buf[4..8] == b"tfhd");
344 let track_id = read_u32be(&buf[12..16])?;
345 let mut track = None;
346 for trk in dmx.tracks.iter_mut() {
347 if trk.track_id == track_id {
352 if let Some(track) = track {
353 track.moof_off = dmx.moof_off;
354 track.read_traf(dmx.src, size)?;
361 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
362 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
364 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
365 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
366 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
367 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
368 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
369 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
372 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
373 const KNOWN_TKHD_SIZE: u64 = 84;
374 validate!(size >= KNOWN_TKHD_SIZE);
375 let version = br.read_byte()?;
376 validate!(version == 0);
377 let _flags = br.read_u24be()?;
378 let _ctime = br.read_u32be()?;
379 let _mtime = br.read_u32be()?;
380 let track_id = br.read_u32be()?;
382 let duration = br.read_u32be()?;
384 let _layer = br.read_u16be()?;
385 let _alt_group = br.read_u16be()?;
386 let _volume = br.read_u16be()?;
388 br.read_skip(36)?; // matrix
389 let width = br.read_u32be()? as usize;
390 let height = br.read_u32be()? as usize;
391 track.width = width >> 16;
392 track.height = height >> 16;
393 track.track_id = track_id;
394 track.duration = duration;
396 track.tkhd_found = true;
400 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 track.stream_type = StreamType::None;
402 track.read_mdia(br, size)?;
406 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
407 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: read_mdhd },
408 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
409 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
412 fn read_mdhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
413 const KNOWN_MDHD_SIZE: u64 = 24;
414 validate!(size >= KNOWN_MDHD_SIZE);
415 let version = br.read_byte()?;
416 validate!(version == 0);
417 let flags = br.read_u24be()?;
418 validate!(flags == 0);
419 let _ctime = br.read_u32be()?;
420 let _mtime = br.read_u32be()?;
421 track.tb_den = br.read_u32be()?;
422 validate!(track.tb_den != 0);
423 track.duration = br.read_u32be()?;
424 let _language = br.read_u16be()?;
425 let _quality = br.read_u16be()?;
430 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
431 const KNOWN_HDLR_SIZE: u64 = 24;
432 validate!(size >= KNOWN_HDLR_SIZE);
433 let version = br.read_byte()?;
434 validate!(version == 0);
435 let flags = br.read_u24be()?;
436 validate!(flags == 0);
437 let comp_type = br.read_u32be()?;
438 let comp_subtype = br.read_u32be()?;
439 let _comp_manufacturer = br.read_u32be()?;
440 let _comp_flags = br.read_u32be()?;
441 let _comp_flags_mask = br.read_u32be()?;
443 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
444 if comp_subtype == mktag!(b"vide") {
445 track.stream_type = StreamType::Video;
446 } else if comp_subtype == mktag!(b"soun") {
447 track.stream_type = StreamType::Audio;
449 track.stream_type = StreamType::Data;
451 } else if comp_type == mktag!(b"dhlr") {
452 track.stream_type = StreamType::Data;
454 println!("Unknown stream type");
455 track.stream_type = StreamType::Data;
461 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
462 track.read_minf(br, size)?;
466 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
467 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
468 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
469 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
470 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
471 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
472 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
473 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
476 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
477 const KNOWN_VMHD_SIZE: u64 = 12;
478 validate!(track.stream_type == StreamType::Video);
479 validate!(size >= KNOWN_VMHD_SIZE);
480 let version = br.read_byte()?;
481 validate!(version == 0);
482 let _flags = br.read_u24be()?;
483 br.read_skip(2)?; // graphics mode
484 br.read_skip(6)?; // opcolor
488 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
489 const KNOWN_SMHD_SIZE: u64 = 8;
490 validate!(track.stream_type == StreamType::Audio);
491 validate!(size >= KNOWN_SMHD_SIZE);
492 let version = br.read_byte()?;
493 validate!(version == 0);
494 let _flags = br.read_u24be()?;
495 br.read_skip(2)?; // balance
500 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
501 validate!(track.stream_type == StreamType::Data);
505 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
506 validate!(track.stream_type == StreamType::Data);
507 const KNOWN_GMIN_SIZE: u64 = 16;
508 validate!(size >= KNOWN_GMIN_SIZE);
509 let version = br.read_byte()?;
510 validate!(version == 0);
511 let _flags = br.read_u24be()?;
512 br.read_skip(2)?; // graphics mode
513 br.read_skip(6)?; // opcolor
514 br.read_skip(2)?; // balance
519 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
520 track.read_stbl(br, size)?;
524 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
525 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
526 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
527 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
528 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
529 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
530 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
531 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
532 TrackChunkHandler { ctype: mktag!(b"ctts"), parse: read_ctts },
535 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
536 let read_part = br.tell() - start_pos;
537 if read_part + 8 < size {
538 let mut buf = [0; 8];
539 br.peek_buf(&mut buf)?;
540 if &buf[4..8] != b"wave" {
541 let mut buf = vec![0; (size - read_part) as usize];
542 br.read_buf(&mut buf)?;
543 return Ok(Some(buf));
546 let csize = br.read_u32be()? as u64;
547 let ctag = br.read_u32be()?;
548 validate!(read_part + csize <= size);
549 validate!(ctag == mktag!(b"wave"));
553 let mut buf = [0; 8];
554 br.peek_buf(&mut buf)?;
555 if &buf[4..8] == b"frma" {
558 let mut buf = vec![0; (csize - 20) as usize];
559 br.read_buf(&mut buf)?;
564 } else if csize > 8 {
565 let mut buf = vec![0; (csize as usize) - 8];
566 br.read_buf(&mut buf)?;
576 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
577 const KNOWN_STSD_SIZE: u64 = 24;
578 validate!(size >= KNOWN_STSD_SIZE);
579 let start_pos = br.tell();
580 let version = br.read_byte()?;
581 validate!(version == 0);
582 let _flags = br.read_u24be()?;
583 let entries = br.read_u32be()?;
584 validate!(entries > 0);
585 let esize = u64::from(br.read_u32be()?);
586 validate!(esize + 8 <= size);
587 let mut fcc = [0u8; 4];
588 br.read_buf(&mut fcc)?;
590 let _data_ref = br.read_u16be()?;
595 match track.stream_type {
596 StreamType::Video => {
597 let _ver = br.read_u16be()?;
598 let _revision = br.read_u16le()?;
599 let _vendor = br.read_u32be()?;
600 let _temp_quality = br.read_u32be()?;
601 let _spat_quality = br.read_u32be()?;
602 let width = br.read_u16be()? as usize;
603 let height = br.read_u16be()? as usize;
604 let _hor_res = br.read_u32be()?;
605 let _vert_res = br.read_u32be()?;
606 let data_size = br.read_u32be()?;
607 validate!(data_size == 0);
608 let _frame_count = br.read_u16be()? as usize;
609 let _cname_len = br.read_byte()? as usize;
610 br.read_skip(31)?; // actual compressor name
611 let depth = br.read_u16be()?;
612 let ctable_id = br.read_u16be()?;
613 let grayscale = depth > 0x20 || depth == 1;
614 let depth = if grayscale { depth & 0x1F } else { depth };
616 let max_pal_size = start_pos + size - br.tell();
618 let mut pal = [0; 1024];
619 read_palette(br, max_pal_size, &mut pal)?;
620 track.pal = Some(Arc::new(pal));
622 br.read_skip(max_pal_size as usize)?;
624 } else if (depth <= 8) && !grayscale {
627 let mut pal = [0; 1024];
628 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
629 track.pal = Some(Arc::new(pal));
632 let mut pal = [0; 1024];
633 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
634 track.pal = Some(Arc::new(pal));
637 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
641 } else if grayscale && ctable_id != 0xFFFF {
642 let mut pal = [0; 1024];
643 let cdepth = depth & 0x1F;
644 let size = 1 << cdepth;
646 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
647 let mut off = 8 - cdepth;
648 while off >= cdepth {
649 clr |= clr >> (8 - off);
653 clr |= clr >> (8 - off);
656 pal[i * 4 + 1] = clr;
657 pal[i * 4 + 2] = clr;
659 track.pal = Some(Arc::new(pal));
661 // todo other atoms, put as extradata
662 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
664 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
669 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
670 let mut vhdr = NAVideoInfo::new(width, height, false, format);
671 vhdr.bits = depth as u8;
672 //skip various common atoms
673 while br.tell() - start_pos + 4 < size {
674 let mut buf = [0u8; 8];
675 br.peek_buf(&mut buf)?;
676 let tsize = read_u32be(&buf).unwrap() as usize;
677 let tag = &buf[4..8];
678 validate!(tsize >= 8);
680 b"pasp" | b"clap" => {
681 br.read_skip(tsize)?;
686 let edata = if br.tell() - start_pos + 4 < size {
687 let edata_size = br.read_u32be()? as usize;
688 validate!(edata_size >= 4);
689 let mut buf = vec![0; edata_size - 4];
690 br.read_buf(buf.as_mut_slice())?;
695 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
697 StreamType::Audio => {
698 let sver = br.read_u16be()?;
699 let _revision = br.read_u16le()?;
700 let _vendor = br.read_u32be()?;
701 let mut nchannels = br.read_u16be()?;
703 validate!(nchannels <= 64);
705 let sample_size = br.read_u16be()?;
706 validate!(sample_size <= 128);
707 let _compr_id = br.read_u16be()?;
708 let packet_size = br.read_u16be()? as usize;
709 validate!(packet_size == 0);
710 let mut sample_rate = br.read_u32be()? >> 16;
712 validate!(sample_rate > 0);
714 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
716 } 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]))) {
721 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
722 if &fcc == b"raw " && sample_size == 8 {
723 soniton.signed = false;
728 let samples_per_packet = br.read_u32be()?;
729 let _bytes_per_packet = br.read_u32be()?;
730 let bytes_per_frame = br.read_u32be()?;
731 let _bytes_per_sample = br.read_u32be()?;
732 track.bsize = bytes_per_frame as usize;
733 track.frame_samples = samples_per_packet as usize;
734 track.tb_num = samples_per_packet;
737 br.read_u32be()?; // some size
738 let srate = br.read_f64be()?;
739 validate!(srate > 1.0);
740 sample_rate = srate as u32;
741 let channels = br.read_u32be()?;
742 validate!(channels > 0 && channels < 255);
743 nchannels = channels as u16;
744 br.read_u32be()?; // always 0x7F000000
745 let _bits_per_csample = br.read_u32be()?;
746 let _codec_flags = br.read_u32be()?;
747 let bytes_per_frame = br.read_u32be()?;
748 let samples_per_packet = br.read_u32be()?;
749 track.bsize = bytes_per_frame as usize;
750 track.frame_samples = samples_per_packet as usize;
751 track.tb_num = samples_per_packet;
754 track.bsize = (sample_size / 8) as usize;
757 track.tb_den = sample_rate;
758 track.raw_audio = matches!(&fcc,
759 b"NONE" | b"raw " | b"twos" | b"sowt" |
760 b"in24" | b"in32" | b"fl32" | b"fl64" |
761 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
764 let ahdr = NAAudioInfo::new(sample_rate, nchannels as u8, soniton, block_align);
765 let edata = parse_audio_edata(br, start_pos, size)?;
766 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
767 track.channels = nchannels as usize;
768 track.bits = sample_size as usize;
770 StreamType::None => {
771 return Err(DemuxerError::InvalidData);
774 //todo put it all into extradata
776 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
779 let read_size = br.tell() - start_pos;
780 validate!(read_size <= size);
781 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
782 track.stsd_found = true;
786 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
787 validate!(size >= 8);
788 let start_pos = br.tell();
789 let version = br.read_byte()?;
790 validate!(version == 0);
791 let _flags = br.read_u24be()?;
792 let entries = br.read_u32be()? as usize;
793 validate!(entries as u64 <= (size - 8) / 8);
795 } else if entries == 1 {
796 let _count = br.read_u32be()?;
797 let tb_num = br.read_u32be()?;
798 validate!(tb_num != 0);
799 track.rescale(tb_num);
801 track.time_to_sample.clear();
802 track.time_to_sample.reserve(entries);
803 for _ in 0..entries {
804 let count = br.read_u32be()?;
805 let mult = br.read_u32be()?;
806 track.time_to_sample.push((count, mult));
809 let read_size = br.tell() - start_pos;
810 validate!(read_size <= size);
814 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
815 let version = br.read_byte()?;
816 validate!(version == 0);
817 let _flags = br.read_u24be()?;
818 let entries = br.read_u32be()? as usize;
819 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
820 validate!((entries * 4 + 8) as u64 == size);
821 track.keyframes = Vec::with_capacity(entries);
822 let mut last_sample_no = 0;
823 for _ in 0..entries {
824 let sample_no = br.read_u32be()?;
825 validate!(sample_no > last_sample_no);
826 track.keyframes.push(sample_no);
827 last_sample_no = sample_no;
832 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
833 let version = br.read_byte()?;
834 validate!(version == 0);
835 let _flags = br.read_u24be()?;
836 let entries = br.read_u32be()? as usize;
837 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
838 validate!((entries * 12 + 8) as u64 == size);
839 track.sample_map = Vec::with_capacity(entries);
840 let mut last_sample_no = 0;
841 for _i in 0..entries {
842 let sample_no = br.read_u32be()?;
843 validate!(sample_no > last_sample_no);
844 let nsamples = br.read_u32be()?;
845 let _sample_desc = br.read_u32be()?;
846 track.sample_map.push((sample_no, nsamples));
847 last_sample_no = sample_no;
852 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
853 let version = br.read_byte()?;
854 validate!(version == 0);
855 let _flags = br.read_u24be()?;
856 let sample_size = br.read_u32be()?;
857 if sample_size != 0 {
858 track.sample_size = sample_size;
859 if track.sample_size != 1 || track.bsize == 0 {
860 track.bsize = sample_size as usize;
864 let entries = br.read_u32be()? as usize;
865 validate!((entries * 4 + 12) as u64 == size);
866 track.chunk_sizes = Vec::with_capacity(entries);
867 for _ in 0..entries {
868 let sample_size = br.read_u32be()?;
869 track.chunk_sizes.push(sample_size);
875 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
876 let version = br.read_byte()?;
877 validate!(version == 0);
878 let _flags = br.read_u24be()?;
879 let entries = br.read_u32be()? as usize;
880 validate!((entries * 4 + 8) as u64 == size);
881 track.chunk_offsets = Vec::with_capacity(entries);
882 for _i in 0..entries {
883 let sample_offset = br.read_u32be()?;
884 track.chunk_offsets.push(u64::from(sample_offset));
889 fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
890 validate!(size >= 8);
891 let version = br.read_byte()?;
892 let _flags = br.read_u24be()?;
894 return Err(DemuxerError::NotImplemented);
896 let entries = br.read_u32be()? as usize;
897 track.ctts_version = version;
898 track.ctts_map.resize(entries);
901 validate!(size == (entries as u64) * 8 + 8);
902 for _ in 0..entries {
903 let samp_count = br.read_u32be()?;
904 let samp_offset = br.read_u32be()?;
905 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
910 track.ctts_map.reset();
915 const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
916 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
917 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
918 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
919 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
920 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
921 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
922 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
923 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
924 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
927 fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
928 validate!(size >= 8);
929 let start = br.tell();
930 let _version = br.read_byte()?;
931 let flags = br.read_u24be()?;
932 let _track_id = br.read_u32be()?;
933 if (flags & 0x000001) != 0 {
934 let base_offset = br.read_u64be()?;
935 track.moof_off = base_offset;
937 if (flags & 0x000002) != 0 {
938 let _sample_description_index = br.read_u32be()?;
940 if (flags & 0x000008) != 0 {
941 let default_sample_duration = br.read_u32be()?;
942 if track.tb_div == 1 {
943 track.rescale(default_sample_duration);
946 if (flags & 0x000010) != 0 {
947 let _default_sample_size = br.read_u32be()?;
949 if (flags & 0x000020) != 0 {
950 let _default_sample_flags = br.read_u32be()?;
952 if (flags & 0x010000) != 0 {
954 /*if (flags & 0x020000) != 0 { // base offset is moof start
956 Ok(br.tell() - start)
959 fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
960 validate!(size >= 8);
961 let version = br.read_byte()?;
962 let flags = br.read_u24be()?;
963 let data_off_present = (flags & 0x000001) != 0;
964 let first_sample_flags = (flags & 0x000004) != 0;
965 let sample_duration_present = (flags & 0x000100) != 0;
966 let sample_size_present = (flags & 0x000200) != 0;
967 let sample_flags_present = (flags & 0x000400) != 0;
968 let sample_ct_off_present = (flags & 0x000800) != 0;
970 let sample_count = br.read_u32be()? as usize;
972 let mut hdr_size = 8;
973 let mut arr_size = 0;
974 if data_off_present {
977 if first_sample_flags {
980 if sample_duration_present {
983 if sample_size_present {
986 if sample_flags_present {
989 if sample_ct_off_present {
992 validate!(size == hdr_size + arr_size * (sample_count as u64));
994 let mut data_off = if data_off_present {
995 let off = br.read_u32be()? as i32;
996 let new_off = (track.moof_off as i64) + i64::from(off);
997 validate!(new_off > 0);
1002 if first_sample_flags {
1003 let _flags = br.read_u32be()?;
1006 if sample_size_present {
1007 track.chunk_sizes.reserve(sample_count);
1008 track.chunk_offsets.reserve(sample_count);
1011 if sample_ct_off_present {
1012 if track.ctts_version != version {
1013 track.ctts_version = version;
1015 track.ctts_map.reserve(sample_count);
1018 if track.chunk_offsets.len() < (std::u32::MAX as usize) {
1019 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
1021 for _ in 0..sample_count {
1022 if sample_duration_present {
1023 let _duration = br.read_u32be()?;
1025 if sample_size_present {
1026 let ssize = br.read_u32be()?;
1027 track.chunk_sizes.push(ssize);
1028 track.chunk_offsets.push(data_off);
1029 data_off += u64::from(ssize);
1031 if sample_flags_present {
1032 let _flags = br.read_u32be()?;
1034 if sample_ct_off_present {
1035 let samp_offset = br.read_u32be()?;
1037 track.ctts_map.add(1, samp_offset / track.tb_div);
1039 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1047 struct MOVDemuxer<'a> {
1048 src: &'a mut ByteReader<'a>,
1056 pal: Option<Arc<[u8; 1024]>>,
1067 track_str_id: usize,
1078 stream_type: StreamType,
1085 keyframes: Vec<u32>,
1086 chunk_sizes: Vec<u32>,
1087 chunk_offsets: Vec<u64>,
1088 time_to_sample: Vec<(u32, u32)>,
1089 sample_map: Vec<(u32, u32)>,
1091 frame_samples: usize,
1092 ctts_map: RLESearcher<u32>,
1094 stream: Option<NAStream>,
1097 cur_ts: Option<u64>,
1098 samples_left: usize,
1100 pal: Option<Arc<[u8; 1024]>>,
1101 timesearch: TimeSearcher,
1109 struct TimeSearcher {
1118 fn new() -> Self { Self::default() }
1119 fn reset(&mut self) {
1120 *self = Self::default();
1122 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
1125 } else if sample >= self.sbase {
1126 let mut sample = sample - self.sbase;
1128 let (cur_len, cur_mul) = tts[0];
1129 self.cur_len = cur_len;
1130 self.cur_mul = cur_mul;
1133 while self.idx < tts.len() && sample > self.cur_len {
1134 sample -= self.cur_len;
1135 self.sbase += self.cur_len;
1136 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1137 self.cur_len = tts[self.idx].0;
1138 self.cur_mul = tts[self.idx].1;
1141 self.base + u64::from(sample) * u64::from(self.cur_mul)
1144 self.map_time(sample, tts)
1150 struct RLESearcher<T> {
1151 array: Vec<(u32, T)>,
1157 impl<T:Default+Copy> RLESearcher<T> {
1158 fn new() -> Self { Self::default() }
1159 fn resize(&mut self, size: usize) {
1161 self.array.reserve(size);
1163 fn reserve(&mut self, size: usize) {
1164 self.array.reserve(size);
1166 fn add(&mut self, len: u32, val: T) {
1167 self.array.push((len, val));
1169 fn reset(&mut self) {
1171 if !self.array.is_empty() {
1173 self.next = u64::from(self.array[0].0);
1175 self.idx = self.array.len();
1179 fn map(&mut self, sample: u64) -> Option<T> {
1180 if sample < self.start {
1183 if self.idx < self.array.len() {
1184 if sample < self.next {
1185 Some(self.array[self.idx].1)
1187 while (self.idx < self.array.len()) && (sample >= self.next) {
1188 self.start = self.next;
1190 if self.idx < self.array.len() {
1191 self.next += u64::from(self.array[self.idx].0);
1194 if self.idx < self.array.len() {
1195 Some(self.array[self.idx].1)
1207 fn new(track_no: u32, tb_den: u32) -> Self {
1220 stream_type: StreamType::None,
1227 keyframes: Vec::new(),
1228 chunk_sizes: Vec::new(),
1229 chunk_offsets: Vec::new(),
1230 time_to_sample: Vec::new(),
1231 sample_map: Vec::new(),
1234 ctts_map: RLESearcher::new(),
1244 timesearch: TimeSearcher::new(),
1248 print_chunks: false,
1251 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1252 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1253 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1254 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1255 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1256 fn rescale(&mut self, tb_num: u32) {
1257 self.tb_div = tb_num;
1258 if let Some(ref mut stream) = self.stream {
1259 let tb_den = stream.tb_den;
1260 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1261 stream.duration /= u64::from(self.tb_div);
1262 stream.tb_num = tb_num;
1263 stream.tb_den = tb_den;
1264 self.tb_num = tb_num;
1265 self.tb_den = tb_den;
1266 self.duration /= self.tb_div;
1269 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1270 if !self.keyframes.is_empty() {
1271 seek_index.mode = SeekIndexMode::Present;
1273 let mut tsearch = TimeSearcher::new();
1274 for kf_time in self.keyframes.iter() {
1275 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1276 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1277 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1280 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1285 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1286 (nsamp * self.bits * self.channels + 7) >> 3
1289 let nblocks = (nsamp + 63) >> 6;
1290 nblocks * 34 * self.channels
1293 (nsamp + 5) / 6 * 2 * self.channels
1296 (nsamp + 5) / 6 * self.channels
1298 b"in24" => nsamp * 3 * self.channels,
1299 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1300 b"fl64" => nsamp * 8 * self.channels,
1301 b"ulaw" | b"alaw" => nsamp,
1302 b"ms\x00\x02" => { //MS ADPCM
1303 ((nsamp - 1) / 2 + 7) * self.channels
1305 b"ms\x00\x21" => { //IMA ADPCM
1306 (nsamp / 2 + 4) * self.channels
1312 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1313 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1314 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1315 let dts = match self.ctts_version {
1316 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1317 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1318 _ => unimplemented!(),
1320 if (dts as i64) < 0 {
1328 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1329 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1330 if self.cur_sample >= self.chunk_sizes.len() {
1333 let offset = self.chunk_offsets[self.cur_sample];
1334 let size = self.chunk_sizes[self.cur_sample] as usize;
1335 self.cur_sample += 1;
1336 Some((pts, offset, size))
1338 if self.samples_left == 0 {
1339 if self.cur_chunk >= self.chunk_offsets.len() {
1342 for (idx, samples) in self.sample_map.iter() {
1343 if *idx as usize <= self.cur_chunk + 1 {
1344 self.samples_left = *samples as usize;
1349 self.last_offset = self.chunk_offsets[self.cur_chunk];
1350 self.cur_chunk += 1;
1352 let offset = self.last_offset;
1353 let size = self.get_size(self.cur_sample);
1354 self.last_offset += size as u64;
1355 if self.stream_type == StreamType::Video {
1356 self.samples_left -= 1;
1357 } else if self.frame_samples != 0 && self.bsize != 0 {
1358 let nblocks = size / self.bsize;
1360 pts.pts = Some(self.raw_apos);
1361 pts.duration = Some(nblocks as u64);
1362 self.raw_apos += nblocks as u64;
1365 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1366 self.samples_left -= consumed;
1368 self.samples_left = 0;
1370 } else if !self.raw_audio {
1371 self.samples_left -= 1;
1373 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1374 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1375 let cur_size = self.calculate_chunk_size(self.samples_left);
1376 let add_off = (size - cur_size) as u64;
1377 let dsize = cur_size.min(max_size);
1378 if self.samples_left >= BLOCK_SAMPLES {
1379 self.cur_sample += BLOCK_SAMPLES;
1380 self.samples_left -= BLOCK_SAMPLES;
1381 self.last_offset -= size as u64;
1383 self.cur_sample += self.samples_left;
1384 self.samples_left = 0;
1386 return Some((pts, offset + add_off, dsize));
1388 self.cur_sample += 1;
1389 Some((pts, offset, size))
1392 fn get_size(&self, sample_no: usize) -> usize {
1393 if !self.chunk_sizes.is_empty() {
1394 self.chunk_sizes[sample_no] as usize
1395 } else if !self.sample_map.is_empty() {
1397 for (idx, samples) in self.sample_map.iter() {
1398 if *idx as usize <= self.cur_chunk {
1404 self.calculate_chunk_size(nsamp as usize)
1409 #[allow(clippy::collapsible_if)]
1410 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1411 self.cur_sample = pts as usize;
1412 self.samples_left = 0;
1414 if self.stream_type == StreamType::Audio {
1415 if let NATimePoint::Milliseconds(ms) = tpoint {
1416 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1418 if self.frame_samples != 0 {
1419 self.raw_apos = exp_pts / (self.frame_samples as u64);
1421 self.cur_sample = 0;
1423 let mut cmap = self.sample_map.iter();
1424 let mut cur_samps = 0;
1425 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1427 if self.cur_chunk + 1 == next_idx as usize {
1428 self.samples_left = cur_samps;
1429 cur_samps = next_samples as usize;
1430 if let Some((new_idx, new_samples)) = cmap.next() {
1431 next_idx = *new_idx;
1432 next_samples = *new_samples;
1435 self.raw_apos = apos;
1436 apos += (cur_samps / self.frame_samples) as u64;
1438 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1439 if self.cur_chunk >= self.chunk_offsets.len() {
1440 return Err(DemuxerError::SeekError);
1442 self.last_offset = self.chunk_offsets[self.cur_chunk];
1446 self.cur_chunk += 1;
1448 self.samples_left = cur_samps;
1449 self.cur_chunk += 1;
1451 self.raw_apos = exp_pts;
1452 self.cur_sample = exp_pts as usize;
1455 let mut cmap = self.sample_map.iter();
1456 let mut cur_samps = 0;
1457 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1459 if self.cur_chunk + 1 == next_idx as usize {
1460 self.samples_left = cur_samps;
1461 cur_samps = next_samples as usize;
1462 if let Some((new_idx, new_samples)) = cmap.next() {
1463 next_idx = *new_idx;
1464 next_samples = *new_samples;
1468 if csamp > self.cur_sample {
1469 if self.cur_chunk >= self.chunk_offsets.len() {
1470 return Err(DemuxerError::SeekError);
1472 self.last_offset = self.chunk_offsets[self.cur_chunk];
1475 self.cur_chunk += 1;
1477 self.samples_left = csamp - self.cur_sample;
1478 self.cur_chunk += 1;
1480 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
1481 self.cur_chunk = self.cur_sample;
1483 if !self.time_to_sample.is_empty() {
1484 let mut remaining = exp_pts;
1485 let mut abs_csamp = 0;
1486 for &(count, scount) in self.time_to_sample.iter() {
1487 let count = u64::from(count);
1488 let scount = u64::from(scount);
1489 let nblk = remaining / scount;
1494 remaining -= count * scount;
1497 self.cur_sample = abs_csamp as usize;
1499 self.cur_sample = exp_pts as usize;
1501 let tgt_sample = self.cur_sample;
1504 let mut cmap = self.sample_map.iter();
1505 let mut cur_samps = 0;
1506 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1508 if self.cur_chunk + 1 == next_idx as usize {
1509 self.samples_left = cur_samps;
1510 cur_samps = next_samples as usize;
1511 if let Some((new_idx, new_samples)) = cmap.next() {
1512 next_idx = *new_idx;
1513 next_samples = *new_samples;
1517 if csamp > self.cur_sample {
1518 if self.cur_chunk >= self.chunk_offsets.len() {
1519 self.cur_sample = csamp - cur_samps;
1520 self.samples_left = 0;
1521 self.cur_sample = csamp;
1522 return Err(DemuxerError::SeekError);
1524 self.last_offset = self.chunk_offsets[self.cur_chunk];
1527 self.cur_chunk += 1;
1529 self.cur_sample = csamp - cur_samps;
1530 self.samples_left = cur_samps;
1531 self.last_offset = self.chunk_offsets[self.cur_chunk];
1532 self.cur_chunk += 1;
1534 // try to refine sample position
1535 if self.chunk_sizes.len() > self.chunk_offsets.len() {
1536 for i in self.cur_sample..tgt_sample {
1537 self.cur_sample += 1;
1538 self.samples_left -= 1;
1539 self.last_offset += u64::from(self.chunk_sizes[i]);
1544 self.cur_chunk = self.cur_sample;
1546 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1549 let mut cmap = self.sample_map.iter();
1550 let mut cur_samps = 0;
1551 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1553 if self.cur_chunk + 1 == next_idx as usize {
1554 self.samples_left = cur_samps;
1555 cur_samps = next_samples as usize;
1556 if let Some((new_idx, new_samples)) = cmap.next() {
1557 next_idx = *new_idx;
1558 next_samples = *new_samples;
1562 if csamp >= self.cur_sample {
1563 if self.cur_chunk >= self.chunk_offsets.len() {
1564 return Err(DemuxerError::SeekError);
1566 self.last_offset = self.chunk_offsets[self.cur_chunk];
1569 self.cur_chunk += 1;
1572 for sample_no in csamp..self.cur_sample {
1573 self.last_offset += self.get_size(sample_no) as u64;
1575 self.samples_left = csamp + cur_samps - self.cur_sample;
1576 self.cur_chunk += 1;
1582 fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1583 if let Some(cpts) = pts.get_pts() {
1584 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1585 track.cur_ts = Some(ts);
1587 track.cur_ts = None;
1589 let stream = strmgr.get_stream(track.track_str_id);
1590 if stream.is_none() { return Err(DemuxerError::InvalidData); }
1591 let stream = stream.unwrap();
1592 src.seek(SeekFrom::Start(offset))?;
1593 let mut pkt = src.read_packet(stream, pts, false, size)?;
1594 if let Some(ref pal) = track.pal {
1595 let side_data = NASideData::Palette(first, pal.clone());
1596 pkt.add_side_data(side_data);
1601 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1602 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1603 if !self.macbinary {
1604 self.read_root(strmgr)?;
1606 let ver = self.src.read_byte()?;
1607 validate!(ver == 0);
1608 self.src.read_skip(64)?;
1609 let tag = self.src.read_tag()?;
1610 validate!(&tag == b"MooV");
1611 self.src.read_skip(14)?;
1612 let data_length = self.src.read_u32be()?;
1613 validate!(data_length > 8);
1614 let rsrc_length = self.src.read_u32be()?;
1615 validate!(rsrc_length > 0);
1616 self.src.read_skip(31)?;
1617 let ver = self.src.read_byte()?;
1618 validate!(ver == 0x81);
1619 let ver = self.src.read_byte()?;
1620 validate!(ver == 0x81);
1621 //xxx: maybe check header CRC
1623 let rsrc_start = 0x80 + ((data_length + 0x7F) & !0x7F);
1624 self.src.seek(SeekFrom::Start(rsrc_start.into()))?;
1625 let rsrc_off = self.src.read_u32be()?;
1626 let rsrc_map_off = self.src.read_u32be()?;
1627 let rsrc_size = self.src.read_u32be()?;
1628 let _rsrc_map_size = self.src.read_u32be()?;
1629 validate!(rsrc_off >= 0x10);
1630 validate!(rsrc_map_off >= rsrc_off + rsrc_size);
1631 self.src.seek(SeekFrom::Current(i64::from(rsrc_off - 16)))?;
1632 // I'm too lazy to parse resource map, so let's just iterate over resources for movie header
1633 let end_pos = u64::from(rsrc_start + rsrc_off + rsrc_size);
1634 let mut peek_buf = [0u8; 8];
1635 while self.src.tell() < end_pos {
1636 let cur_size = self.src.read_u32be()?;
1637 validate!(self.src.tell() + u64::from(cur_size) <= end_pos);
1639 let rsize = self.src.peek_u32be()?;
1640 if rsize == cur_size {
1641 self.src.peek_buf(&mut peek_buf)?;
1642 if &peek_buf[4..] == b"moov" {
1643 self.src.read_skip(8)?;
1644 self.read_moov(strmgr, rsize.into())?;
1650 self.src.read_skip(cur_size as usize)?;
1653 validate!(self.mdat_pos > 0);
1654 validate!(!self.tracks.is_empty());
1655 for track in self.tracks.iter_mut() {
1656 let mut strm = None;
1657 std::mem::swap(&mut track.stream, &mut strm);
1658 if let Some(stream) = strm {
1659 let str_id = strmgr.add_stream(stream).unwrap();
1660 track.track_str_id = str_id;
1664 // patch data offsets
1665 for track in self.tracks.iter_mut() {
1666 for offset in track.chunk_offsets.iter_mut() {
1671 for track in self.tracks.iter() {
1672 track.fill_seek_index(seek_index);
1674 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1679 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1680 if self.tracks.is_empty() {
1681 return Err(DemuxerError::EOF);
1683 let mut has_all_time = true;
1684 let mut min_ts = std::u64::MAX;
1685 for trk in self.tracks.iter() {
1686 if let Some(ts) = trk.cur_ts {
1687 min_ts = min_ts.min(ts);
1689 has_all_time = false;
1694 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1695 if let Some(ts) = track.cur_ts {
1697 let first = track.cur_sample == 0;
1698 if let Some((pts, offset, size)) = track.get_next_chunk() {
1699 self.cur_track = trk_no + 1;
1700 return process_packet(self.src, strmgr, track, pts, offset, size, first);
1707 for _ in 0..self.tracks.len() {
1708 if self.cur_track >= self.tracks.len() {
1711 let track = &mut self.tracks[self.cur_track];
1712 self.cur_track += 1;
1713 let first = track.cur_sample == 0;
1714 if let Some((pts, offset, size)) = track.get_next_chunk() {
1715 return process_packet(self.src, strmgr, track, pts, offset, size, first);
1718 Err(DemuxerError::EOF)
1721 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1722 let ret = seek_index.find_pos(time);
1724 if let NATimePoint::Milliseconds(_) = time {
1725 let mut aonly = true;
1726 for track in self.tracks.iter() {
1727 if track.stream_type != StreamType::Audio {
1733 for track in self.tracks.iter_mut() {
1734 track.seek(0, time)?;
1739 return Err(DemuxerError::SeekError);
1741 let seek_info = ret.unwrap();
1742 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1743 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
1744 for track in self.tracks.iter_mut() {
1745 let cur_pts = if track.track_id == seek_info.str_id {
1748 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1750 track.seek(cur_pts, time)?;
1754 fn get_duration(&self) -> u64 {
1755 if self.tb_den != 0 {
1756 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1763 const PRINT_CHUNKS: &str = "print_chunks";
1765 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1766 NAOptionDefinition {
1768 description: "Print parsed file structure",
1769 opt_type: NAOptionDefinitionType::Bool },
1772 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1773 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1774 #[allow(clippy::single_match)]
1775 fn set_options(&mut self, options: &[NAOption]) {
1776 for option in options.iter() {
1777 for opt_def in DEMUXER_OPTIONS.iter() {
1778 if opt_def.check(option).is_ok() {
1779 match (option.name, &option.value) {
1780 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1781 self.print_chunks = *val;
1789 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1791 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1797 impl<'a> MOVDemuxer<'a> {
1798 fn new(io: &'a mut ByteReader<'a>) -> Self {
1799 Self::new_common(io, false)
1801 fn new_macbinary(io: &'a mut ByteReader<'a>) -> Self {
1802 Self::new_common(io, true)
1804 fn new_common(io: &'a mut ByteReader<'a>, macbinary: bool) -> Self {
1810 tracks: Vec::with_capacity(2),
1818 print_chunks: false,
1823 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1825 while self.src.left() != 0 {
1826 let ret = read_chunk_header(self.src);
1827 if ret.is_err() { break; }
1828 let (ctype, size) = ret.unwrap();
1829 if self.print_chunks {
1830 print_cname(ctype, size, self.src.tell(), 0);
1832 if IGNORED_CHUNKS.contains(&ctype) {
1833 self.src.skip64(size)?;
1836 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1838 if let Some(handler) = handler {
1839 read_size = (handler.parse)(self, strmgr, size)?;
1841 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1844 validate!(read_size <= size);
1845 self.src.skip64(size - read_size)?;
1847 //todo check if all needed chunks are found
1850 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1851 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
1854 pub struct MOVDemuxerCreator { }
1856 impl DemuxerCreator for MOVDemuxerCreator {
1857 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1858 Box::new(MOVDemuxer::new(br))
1860 fn get_name(&self) -> &'static str { "mov" }
1863 pub struct MacBinaryMOVDemuxerCreator { }
1865 impl DemuxerCreator for MacBinaryMOVDemuxerCreator {
1866 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1867 Box::new(MOVDemuxer::new_macbinary(br))
1869 fn get_name(&self) -> &'static str { "mov-macbin" }
1872 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1873 0x93, 0x65, 0x5E, 0x00,
1874 0xFF, 0xFF, 0xFF, 0x00,
1875 0xDF, 0xD0, 0xAB, 0x00,
1876 0x00, 0x00, 0x00, 0x00
1878 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1879 0xFF, 0xFB, 0xFF, 0x00,
1880 0xEF, 0xD9, 0xBB, 0x00,
1881 0xE8, 0xC9, 0xB1, 0x00,
1882 0x93, 0x65, 0x5E, 0x00,
1883 0xFC, 0xDE, 0xE8, 0x00,
1884 0x9D, 0x88, 0x91, 0x00,
1885 0xFF, 0xFF, 0xFF, 0x00,
1886 0xFF, 0xFF, 0xFF, 0x00,
1887 0xFF, 0xFF, 0xFF, 0x00,
1888 0x47, 0x48, 0x37, 0x00,
1889 0x7A, 0x5E, 0x55, 0x00,
1890 0xDF, 0xD0, 0xAB, 0x00,
1891 0xFF, 0xFB, 0xF9, 0x00,
1892 0xE8, 0xCA, 0xC5, 0x00,
1893 0x8A, 0x7C, 0x77, 0x00,
1894 0x00, 0x00, 0x00, 0x00
1896 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1897 0xFF, 0xFF, 0xFF, 0x00,
1898 0xFF, 0xFF, 0xCC, 0x00,
1899 0xFF, 0xFF, 0x99, 0x00,
1900 0xFF, 0xFF, 0x66, 0x00,
1901 0xFF, 0xFF, 0x33, 0x00,
1902 0xFF, 0xFF, 0x00, 0x00,
1903 0xFF, 0xCC, 0xFF, 0x00,
1904 0xFF, 0xCC, 0xCC, 0x00,
1905 0xFF, 0xCC, 0x99, 0x00,
1906 0xFF, 0xCC, 0x66, 0x00,
1907 0xFF, 0xCC, 0x33, 0x00,
1908 0xFF, 0xCC, 0x00, 0x00,
1909 0xFF, 0x99, 0xFF, 0x00,
1910 0xFF, 0x99, 0xCC, 0x00,
1911 0xFF, 0x99, 0x99, 0x00,
1912 0xFF, 0x99, 0x66, 0x00,
1913 0xFF, 0x99, 0x33, 0x00,
1914 0xFF, 0x99, 0x00, 0x00,
1915 0xFF, 0x66, 0xFF, 0x00,
1916 0xFF, 0x66, 0xCC, 0x00,
1917 0xFF, 0x66, 0x99, 0x00,
1918 0xFF, 0x66, 0x66, 0x00,
1919 0xFF, 0x66, 0x33, 0x00,
1920 0xFF, 0x66, 0x00, 0x00,
1921 0xFF, 0x33, 0xFF, 0x00,
1922 0xFF, 0x33, 0xCC, 0x00,
1923 0xFF, 0x33, 0x99, 0x00,
1924 0xFF, 0x33, 0x66, 0x00,
1925 0xFF, 0x33, 0x33, 0x00,
1926 0xFF, 0x33, 0x00, 0x00,
1927 0xFF, 0x00, 0xFF, 0x00,
1928 0xFF, 0x00, 0xCC, 0x00,
1929 0xFF, 0x00, 0x99, 0x00,
1930 0xFF, 0x00, 0x66, 0x00,
1931 0xFF, 0x00, 0x33, 0x00,
1932 0xFF, 0x00, 0x00, 0x00,
1933 0xCC, 0xFF, 0xFF, 0x00,
1934 0xCC, 0xFF, 0xCC, 0x00,
1935 0xCC, 0xFF, 0x99, 0x00,
1936 0xCC, 0xFF, 0x66, 0x00,
1937 0xCC, 0xFF, 0x33, 0x00,
1938 0xCC, 0xFF, 0x00, 0x00,
1939 0xCC, 0xCC, 0xFF, 0x00,
1940 0xCC, 0xCC, 0xCC, 0x00,
1941 0xCC, 0xCC, 0x99, 0x00,
1942 0xCC, 0xCC, 0x66, 0x00,
1943 0xCC, 0xCC, 0x33, 0x00,
1944 0xCC, 0xCC, 0x00, 0x00,
1945 0xCC, 0x99, 0xFF, 0x00,
1946 0xCC, 0x99, 0xCC, 0x00,
1947 0xCC, 0x99, 0x99, 0x00,
1948 0xCC, 0x99, 0x66, 0x00,
1949 0xCC, 0x99, 0x33, 0x00,
1950 0xCC, 0x99, 0x00, 0x00,
1951 0xCC, 0x66, 0xFF, 0x00,
1952 0xCC, 0x66, 0xCC, 0x00,
1953 0xCC, 0x66, 0x99, 0x00,
1954 0xCC, 0x66, 0x66, 0x00,
1955 0xCC, 0x66, 0x33, 0x00,
1956 0xCC, 0x66, 0x00, 0x00,
1957 0xCC, 0x33, 0xFF, 0x00,
1958 0xCC, 0x33, 0xCC, 0x00,
1959 0xCC, 0x33, 0x99, 0x00,
1960 0xCC, 0x33, 0x66, 0x00,
1961 0xCC, 0x33, 0x33, 0x00,
1962 0xCC, 0x33, 0x00, 0x00,
1963 0xCC, 0x00, 0xFF, 0x00,
1964 0xCC, 0x00, 0xCC, 0x00,
1965 0xCC, 0x00, 0x99, 0x00,
1966 0xCC, 0x00, 0x66, 0x00,
1967 0xCC, 0x00, 0x33, 0x00,
1968 0xCC, 0x00, 0x00, 0x00,
1969 0x99, 0xFF, 0xFF, 0x00,
1970 0x99, 0xFF, 0xCC, 0x00,
1971 0x99, 0xFF, 0x99, 0x00,
1972 0x99, 0xFF, 0x66, 0x00,
1973 0x99, 0xFF, 0x33, 0x00,
1974 0x99, 0xFF, 0x00, 0x00,
1975 0x99, 0xCC, 0xFF, 0x00,
1976 0x99, 0xCC, 0xCC, 0x00,
1977 0x99, 0xCC, 0x99, 0x00,
1978 0x99, 0xCC, 0x66, 0x00,
1979 0x99, 0xCC, 0x33, 0x00,
1980 0x99, 0xCC, 0x00, 0x00,
1981 0x99, 0x99, 0xFF, 0x00,
1982 0x99, 0x99, 0xCC, 0x00,
1983 0x99, 0x99, 0x99, 0x00,
1984 0x99, 0x99, 0x66, 0x00,
1985 0x99, 0x99, 0x33, 0x00,
1986 0x99, 0x99, 0x00, 0x00,
1987 0x99, 0x66, 0xFF, 0x00,
1988 0x99, 0x66, 0xCC, 0x00,
1989 0x99, 0x66, 0x99, 0x00,
1990 0x99, 0x66, 0x66, 0x00,
1991 0x99, 0x66, 0x33, 0x00,
1992 0x99, 0x66, 0x00, 0x00,
1993 0x99, 0x33, 0xFF, 0x00,
1994 0x99, 0x33, 0xCC, 0x00,
1995 0x99, 0x33, 0x99, 0x00,
1996 0x99, 0x33, 0x66, 0x00,
1997 0x99, 0x33, 0x33, 0x00,
1998 0x99, 0x33, 0x00, 0x00,
1999 0x99, 0x00, 0xFF, 0x00,
2000 0x99, 0x00, 0xCC, 0x00,
2001 0x99, 0x00, 0x99, 0x00,
2002 0x99, 0x00, 0x66, 0x00,
2003 0x99, 0x00, 0x33, 0x00,
2004 0x99, 0x00, 0x00, 0x00,
2005 0x66, 0xFF, 0xFF, 0x00,
2006 0x66, 0xFF, 0xCC, 0x00,
2007 0x66, 0xFF, 0x99, 0x00,
2008 0x66, 0xFF, 0x66, 0x00,
2009 0x66, 0xFF, 0x33, 0x00,
2010 0x66, 0xFF, 0x00, 0x00,
2011 0x66, 0xCC, 0xFF, 0x00,
2012 0x66, 0xCC, 0xCC, 0x00,
2013 0x66, 0xCC, 0x99, 0x00,
2014 0x66, 0xCC, 0x66, 0x00,
2015 0x66, 0xCC, 0x33, 0x00,
2016 0x66, 0xCC, 0x00, 0x00,
2017 0x66, 0x99, 0xFF, 0x00,
2018 0x66, 0x99, 0xCC, 0x00,
2019 0x66, 0x99, 0x99, 0x00,
2020 0x66, 0x99, 0x66, 0x00,
2021 0x66, 0x99, 0x33, 0x00,
2022 0x66, 0x99, 0x00, 0x00,
2023 0x66, 0x66, 0xFF, 0x00,
2024 0x66, 0x66, 0xCC, 0x00,
2025 0x66, 0x66, 0x99, 0x00,
2026 0x66, 0x66, 0x66, 0x00,
2027 0x66, 0x66, 0x33, 0x00,
2028 0x66, 0x66, 0x00, 0x00,
2029 0x66, 0x33, 0xFF, 0x00,
2030 0x66, 0x33, 0xCC, 0x00,
2031 0x66, 0x33, 0x99, 0x00,
2032 0x66, 0x33, 0x66, 0x00,
2033 0x66, 0x33, 0x33, 0x00,
2034 0x66, 0x33, 0x00, 0x00,
2035 0x66, 0x00, 0xFF, 0x00,
2036 0x66, 0x00, 0xCC, 0x00,
2037 0x66, 0x00, 0x99, 0x00,
2038 0x66, 0x00, 0x66, 0x00,
2039 0x66, 0x00, 0x33, 0x00,
2040 0x66, 0x00, 0x00, 0x00,
2041 0x33, 0xFF, 0xFF, 0x00,
2042 0x33, 0xFF, 0xCC, 0x00,
2043 0x33, 0xFF, 0x99, 0x00,
2044 0x33, 0xFF, 0x66, 0x00,
2045 0x33, 0xFF, 0x33, 0x00,
2046 0x33, 0xFF, 0x00, 0x00,
2047 0x33, 0xCC, 0xFF, 0x00,
2048 0x33, 0xCC, 0xCC, 0x00,
2049 0x33, 0xCC, 0x99, 0x00,
2050 0x33, 0xCC, 0x66, 0x00,
2051 0x33, 0xCC, 0x33, 0x00,
2052 0x33, 0xCC, 0x00, 0x00,
2053 0x33, 0x99, 0xFF, 0x00,
2054 0x33, 0x99, 0xCC, 0x00,
2055 0x33, 0x99, 0x99, 0x00,
2056 0x33, 0x99, 0x66, 0x00,
2057 0x33, 0x99, 0x33, 0x00,
2058 0x33, 0x99, 0x00, 0x00,
2059 0x33, 0x66, 0xFF, 0x00,
2060 0x33, 0x66, 0xCC, 0x00,
2061 0x33, 0x66, 0x99, 0x00,
2062 0x33, 0x66, 0x66, 0x00,
2063 0x33, 0x66, 0x33, 0x00,
2064 0x33, 0x66, 0x00, 0x00,
2065 0x33, 0x33, 0xFF, 0x00,
2066 0x33, 0x33, 0xCC, 0x00,
2067 0x33, 0x33, 0x99, 0x00,
2068 0x33, 0x33, 0x66, 0x00,
2069 0x33, 0x33, 0x33, 0x00,
2070 0x33, 0x33, 0x00, 0x00,
2071 0x33, 0x00, 0xFF, 0x00,
2072 0x33, 0x00, 0xCC, 0x00,
2073 0x33, 0x00, 0x99, 0x00,
2074 0x33, 0x00, 0x66, 0x00,
2075 0x33, 0x00, 0x33, 0x00,
2076 0x33, 0x00, 0x00, 0x00,
2077 0x00, 0xFF, 0xFF, 0x00,
2078 0x00, 0xFF, 0xCC, 0x00,
2079 0x00, 0xFF, 0x99, 0x00,
2080 0x00, 0xFF, 0x66, 0x00,
2081 0x00, 0xFF, 0x33, 0x00,
2082 0x00, 0xFF, 0x00, 0x00,
2083 0x00, 0xCC, 0xFF, 0x00,
2084 0x00, 0xCC, 0xCC, 0x00,
2085 0x00, 0xCC, 0x99, 0x00,
2086 0x00, 0xCC, 0x66, 0x00,
2087 0x00, 0xCC, 0x33, 0x00,
2088 0x00, 0xCC, 0x00, 0x00,
2089 0x00, 0x99, 0xFF, 0x00,
2090 0x00, 0x99, 0xCC, 0x00,
2091 0x00, 0x99, 0x99, 0x00,
2092 0x00, 0x99, 0x66, 0x00,
2093 0x00, 0x99, 0x33, 0x00,
2094 0x00, 0x99, 0x00, 0x00,
2095 0x00, 0x66, 0xFF, 0x00,
2096 0x00, 0x66, 0xCC, 0x00,
2097 0x00, 0x66, 0x99, 0x00,
2098 0x00, 0x66, 0x66, 0x00,
2099 0x00, 0x66, 0x33, 0x00,
2100 0x00, 0x66, 0x00, 0x00,
2101 0x00, 0x33, 0xFF, 0x00,
2102 0x00, 0x33, 0xCC, 0x00,
2103 0x00, 0x33, 0x99, 0x00,
2104 0x00, 0x33, 0x66, 0x00,
2105 0x00, 0x33, 0x33, 0x00,
2106 0x00, 0x33, 0x00, 0x00,
2107 0x00, 0x00, 0xFF, 0x00,
2108 0x00, 0x00, 0xCC, 0x00,
2109 0x00, 0x00, 0x99, 0x00,
2110 0x00, 0x00, 0x66, 0x00,
2111 0x00, 0x00, 0x33, 0x00,
2112 0xEE, 0x00, 0x00, 0x00,
2113 0xDD, 0x00, 0x00, 0x00,
2114 0xBB, 0x00, 0x00, 0x00,
2115 0xAA, 0x00, 0x00, 0x00,
2116 0x88, 0x00, 0x00, 0x00,
2117 0x77, 0x00, 0x00, 0x00,
2118 0x55, 0x00, 0x00, 0x00,
2119 0x44, 0x00, 0x00, 0x00,
2120 0x22, 0x00, 0x00, 0x00,
2121 0x11, 0x00, 0x00, 0x00,
2122 0x00, 0xEE, 0x00, 0x00,
2123 0x00, 0xDD, 0x00, 0x00,
2124 0x00, 0xBB, 0x00, 0x00,
2125 0x00, 0xAA, 0x00, 0x00,
2126 0x00, 0x88, 0x00, 0x00,
2127 0x00, 0x77, 0x00, 0x00,
2128 0x00, 0x55, 0x00, 0x00,
2129 0x00, 0x44, 0x00, 0x00,
2130 0x00, 0x22, 0x00, 0x00,
2131 0x00, 0x11, 0x00, 0x00,
2132 0x00, 0x00, 0xEE, 0x00,
2133 0x00, 0x00, 0xDD, 0x00,
2134 0x00, 0x00, 0xBB, 0x00,
2135 0x00, 0x00, 0xAA, 0x00,
2136 0x00, 0x00, 0x88, 0x00,
2137 0x00, 0x00, 0x77, 0x00,
2138 0x00, 0x00, 0x55, 0x00,
2139 0x00, 0x00, 0x44, 0x00,
2140 0x00, 0x00, 0x22, 0x00,
2141 0x00, 0x00, 0x11, 0x00,
2142 0xEE, 0xEE, 0xEE, 0x00,
2143 0xDD, 0xDD, 0xDD, 0x00,
2144 0xBB, 0xBB, 0xBB, 0x00,
2145 0xAA, 0xAA, 0xAA, 0x00,
2146 0x88, 0x88, 0x88, 0x00,
2147 0x77, 0x77, 0x77, 0x00,
2148 0x55, 0x55, 0x55, 0x00,
2149 0x44, 0x44, 0x44, 0x00,
2150 0x22, 0x22, 0x22, 0x00,
2151 0x11, 0x11, 0x11, 0x00,
2152 0x00, 0x00, 0x00, 0x00
2161 fn test_mov_demux() {
2162 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/cubes.mov
2163 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2164 let mut fr = FileReader::new_read(&mut file);
2165 let mut br = ByteReader::new(&mut fr);
2166 let mut dmx = MOVDemuxer::new(&mut br);
2167 let mut sm = StreamManager::new();
2168 let mut si = SeekIndex::new();
2169 dmx.open(&mut sm, &mut si).unwrap();
2172 let pktres = dmx.get_frame(&mut sm);
2173 if let Err(e) = pktres {
2174 if e == DemuxerError::EOF { break; }
2177 let pkt = pktres.unwrap();
2178 println!("Got {}", pkt);
2183 fn test_dash_demux() {
2184 // sample: a stream downloaded with youtube-dl
2185 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2186 let mut fr = FileReader::new_read(&mut file);
2187 let mut br = ByteReader::new(&mut fr);
2188 let mut dmx = MOVDemuxer::new(&mut br);
2189 let mut sm = StreamManager::new();
2190 let mut si = SeekIndex::new();
2191 dmx.open(&mut sm, &mut si).unwrap();
2194 let pktres = dmx.get_frame(&mut sm);
2195 if let Err(e) = pktres {
2196 if e == DemuxerError::EOF { break; }
2199 let pkt = pktres.unwrap();
2200 println!("Got {}", pkt);
2205 fn test_macbinary_demux() {
2206 // sample from King's Quest VI Macintosh edition
2207 let mut file = File::open("assets/QT/Halfdome.bin").unwrap();
2208 let mut fr = FileReader::new_read(&mut file);
2209 let mut br = ByteReader::new(&mut fr);
2210 let mut dmx = MOVDemuxer::new_macbinary(&mut br);
2211 let mut sm = StreamManager::new();
2212 let mut si = SeekIndex::new();
2213 dmx.open(&mut sm, &mut si).unwrap();
2216 let pktres = dmx.get_frame(&mut sm);
2217 if let Err(e) = pktres {
2218 if e == DemuxerError::EOF { break; }
2221 let pkt = pktres.unwrap();
2222 println!("Got {}", pkt);