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 ch < 0x20 || ch > 0x7F {
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(&mut 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(&mut 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(&mut 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(&mut 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 };
615 validate!(depth <= 8 || (ctable_id == 0xFFFF));
617 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));
621 } else if (depth <= 8) && !grayscale {
624 let mut pal = [0; 1024];
625 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
626 track.pal = Some(Arc::new(pal));
629 let mut pal = [0; 1024];
630 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
631 track.pal = Some(Arc::new(pal));
634 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
638 } else if grayscale && ctable_id != 0xFFFF {
639 let mut pal = [0; 1024];
640 let cdepth = depth & 0x1F;
641 let size = 1 << cdepth;
643 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
644 let mut off = 8 - cdepth;
645 while off >= cdepth {
646 clr |= clr >> (8 - off);
650 clr |= clr >> (8 - off);
653 pal[i * 4 + 1] = clr;
654 pal[i * 4 + 2] = clr;
656 track.pal = Some(Arc::new(pal));
658 // todo other atoms, put as extradata
659 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
661 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
666 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
667 let mut vhdr = NAVideoInfo::new(width, height, false, format);
668 vhdr.bits = depth as u8;
669 //skip various common atoms
670 while br.tell() - start_pos + 4 < size {
671 let mut buf = [0u8; 8];
672 br.peek_buf(&mut buf)?;
673 let tsize = read_u32be(&buf).unwrap() as usize;
674 let tag = &buf[4..8];
675 validate!(tsize >= 8);
677 b"pasp" | b"clap" => {
678 br.read_skip(tsize)?;
683 let edata = if br.tell() - start_pos + 4 < size {
684 let edata_size = br.read_u32be()? as usize;
685 validate!(edata_size >= 4);
686 let mut buf = vec![0; edata_size - 4];
687 br.read_buf(buf.as_mut_slice())?;
692 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
694 StreamType::Audio => {
695 let sver = br.read_u16be()?;
696 let _revision = br.read_u16le()?;
697 let _vendor = br.read_u32be()?;
698 let mut nchannels = br.read_u16be()?;
700 validate!(nchannels <= 64);
702 let sample_size = br.read_u16be()?;
703 validate!(sample_size <= 128);
704 let _compr_id = br.read_u16be()?;
705 let packet_size = br.read_u16be()? as usize;
706 validate!(packet_size == 0);
707 let mut sample_rate = br.read_u32be()? >> 16;
709 validate!(sample_rate > 0);
711 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
713 } 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]))) {
718 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
719 if &fcc == b"raw " && sample_size == 8 {
720 soniton.signed = false;
725 let samples_per_packet = br.read_u32be()?;
726 let _bytes_per_packet = br.read_u32be()?;
727 let bytes_per_frame = br.read_u32be()?;
728 let _bytes_per_sample = br.read_u32be()?;
729 track.bsize = bytes_per_frame as usize;
730 track.frame_samples = samples_per_packet as usize;
731 track.tb_num = samples_per_packet;
734 br.read_u32be()?; // some size
735 let srate = br.read_f64be()?;
736 validate!(srate > 1.0);
737 sample_rate = srate as u32;
738 let channels = br.read_u32be()?;
739 validate!(channels > 0 && channels < 255);
740 nchannels = channels as u16;
741 br.read_u32be()?; // always 0x7F000000
742 let _bits_per_csample = br.read_u32be()?;
743 let _codec_flags = br.read_u32be()?;
744 let bytes_per_frame = br.read_u32be()?;
745 let samples_per_packet = br.read_u32be()?;
746 track.bsize = bytes_per_frame as usize;
747 track.frame_samples = samples_per_packet as usize;
748 track.tb_num = samples_per_packet;
751 track.bsize = (sample_size / 8) as usize;
754 track.tb_den = sample_rate;
755 track.raw_audio = match &fcc {
756 b"NONE" | b"raw " | b"twos" | b"sowt" |
757 b"in24" | b"in32" | b"fl32" | b"fl64" |
758 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
760 b"MAC3" | b"MAC6" => true,
763 let ahdr = NAAudioInfo::new(sample_rate, nchannels as u8, soniton, block_align);
764 let edata = parse_audio_edata(br, start_pos, size)?;
765 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
766 track.channels = nchannels as usize;
767 track.bits = sample_size as usize;
769 StreamType::None => {
770 return Err(DemuxerError::InvalidData);
773 //todo put it all into extradata
775 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
778 let read_size = br.tell() - start_pos;
779 validate!(read_size <= size);
780 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
781 track.stsd_found = true;
785 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
786 validate!(size >= 8);
787 let start_pos = br.tell();
788 let version = br.read_byte()?;
789 validate!(version == 0);
790 let _flags = br.read_u24be()?;
791 let entries = br.read_u32be()? as usize;
792 validate!(entries as u64 <= (size - 8) / 8);
794 } else if entries == 1 {
795 let _count = br.read_u32be()?;
796 let tb_num = br.read_u32be()?;
797 validate!(tb_num != 0);
798 track.rescale(tb_num);
800 track.time_to_sample.clear();
801 track.time_to_sample.reserve(entries);
802 for _ in 0..entries {
803 let count = br.read_u32be()?;
804 let mult = br.read_u32be()?;
805 track.time_to_sample.push((count, mult));
808 let read_size = br.tell() - start_pos;
809 validate!(read_size <= size);
813 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
814 let version = br.read_byte()?;
815 validate!(version == 0);
816 let _flags = br.read_u24be()?;
817 let entries = br.read_u32be()? as usize;
818 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
819 validate!((entries * 4 + 8) as u64 == size);
820 track.keyframes = Vec::with_capacity(entries);
821 let mut last_sample_no = 0;
822 for _ in 0..entries {
823 let sample_no = br.read_u32be()?;
824 validate!(sample_no > last_sample_no);
825 track.keyframes.push(sample_no);
826 last_sample_no = sample_no;
831 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
832 let version = br.read_byte()?;
833 validate!(version == 0);
834 let _flags = br.read_u24be()?;
835 let entries = br.read_u32be()? as usize;
836 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
837 validate!((entries * 12 + 8) as u64 == size);
838 track.sample_map = Vec::with_capacity(entries);
839 let mut last_sample_no = 0;
840 for _i in 0..entries {
841 let sample_no = br.read_u32be()?;
842 validate!(sample_no > last_sample_no);
843 let nsamples = br.read_u32be()?;
844 let _sample_desc = br.read_u32be()?;
845 track.sample_map.push((sample_no, nsamples));
846 last_sample_no = sample_no;
851 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
852 let version = br.read_byte()?;
853 validate!(version == 0);
854 let _flags = br.read_u24be()?;
855 let sample_size = br.read_u32be()?;
856 if sample_size != 0 {
857 track.sample_size = sample_size;
858 if track.sample_size != 1 || track.bsize == 0 {
859 track.bsize = sample_size as usize;
863 let entries = br.read_u32be()? as usize;
864 validate!((entries * 4 + 12) as u64 == size);
865 track.chunk_sizes = Vec::with_capacity(entries);
866 for _ in 0..entries {
867 let sample_size = br.read_u32be()?;
868 track.chunk_sizes.push(sample_size);
874 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
875 let version = br.read_byte()?;
876 validate!(version == 0);
877 let _flags = br.read_u24be()?;
878 let entries = br.read_u32be()? as usize;
879 validate!((entries * 4 + 8) as u64 == size);
880 track.chunk_offsets = Vec::with_capacity(entries);
881 for _i in 0..entries {
882 let sample_offset = br.read_u32be()?;
883 track.chunk_offsets.push(u64::from(sample_offset));
888 fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
889 validate!(size >= 8);
890 let version = br.read_byte()?;
891 let _flags = br.read_u24be()?;
893 return Err(DemuxerError::NotImplemented);
895 let entries = br.read_u32be()? as usize;
896 track.ctts_version = version;
897 track.ctts_map.resize(entries);
900 validate!(size == (entries as u64) * 8 + 8);
901 for _ in 0..entries {
902 let samp_count = br.read_u32be()?;
903 let samp_offset = br.read_u32be()?;
904 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
909 track.ctts_map.reset();
914 const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
915 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
916 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
917 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
918 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
919 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
920 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
921 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
922 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
923 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
926 fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
927 validate!(size >= 8);
928 let start = br.tell();
929 let _version = br.read_byte()?;
930 let flags = br.read_u24be()?;
931 let _track_id = br.read_u32be()?;
932 if (flags & 0x000001) != 0 {
933 let base_offset = br.read_u64be()?;
934 track.moof_off = base_offset;
936 if (flags & 0x000002) != 0 {
937 let _sample_description_index = br.read_u32be()?;
939 if (flags & 0x000008) != 0 {
940 let default_sample_duration = br.read_u32be()?;
941 if track.tb_div == 1 {
942 track.rescale(default_sample_duration);
945 if (flags & 0x000010) != 0 {
946 let _default_sample_size = br.read_u32be()?;
948 if (flags & 0x000020) != 0 {
949 let _default_sample_flags = br.read_u32be()?;
951 if (flags & 0x010000) != 0 {
953 /*if (flags & 0x020000) != 0 { // base offset is moof start
955 Ok(br.tell() - start)
958 fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
959 validate!(size >= 8);
960 let version = br.read_byte()?;
961 let flags = br.read_u24be()?;
962 let data_off_present = (flags & 0x000001) != 0;
963 let first_sample_flags = (flags & 0x000004) != 0;
964 let sample_duration_present = (flags & 0x000100) != 0;
965 let sample_size_present = (flags & 0x000200) != 0;
966 let sample_flags_present = (flags & 0x000400) != 0;
967 let sample_ct_off_present = (flags & 0x000800) != 0;
969 let sample_count = br.read_u32be()? as usize;
971 let mut hdr_size = 8;
972 let mut arr_size = 0;
973 if data_off_present {
976 if first_sample_flags {
979 if sample_duration_present {
982 if sample_size_present {
985 if sample_flags_present {
988 if sample_ct_off_present {
991 validate!(size == hdr_size + arr_size * (sample_count as u64));
993 let mut data_off = if data_off_present {
994 let off = br.read_u32be()? as i32;
995 let new_off = (track.moof_off as i64) + i64::from(off);
996 validate!(new_off > 0);
1001 if first_sample_flags {
1002 let _flags = br.read_u32be()?;
1005 if sample_size_present {
1006 track.chunk_sizes.reserve(sample_count);
1007 track.chunk_offsets.reserve(sample_count);
1010 if sample_ct_off_present {
1011 if track.ctts_version != version {
1012 track.ctts_version = version;
1014 track.ctts_map.reserve(sample_count);
1017 if track.chunk_offsets.len() < (std::u32::MAX as usize) {
1018 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
1020 for _ in 0..sample_count {
1021 if sample_duration_present {
1022 let _duration = br.read_u32be()?;
1024 if sample_size_present {
1025 let ssize = br.read_u32be()?;
1026 track.chunk_sizes.push(ssize);
1027 track.chunk_offsets.push(data_off);
1028 data_off += u64::from(ssize);
1030 if sample_flags_present {
1031 let _flags = br.read_u32be()?;
1033 if sample_ct_off_present {
1034 let samp_offset = br.read_u32be()?;
1036 track.ctts_map.add(1, samp_offset / track.tb_div);
1038 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1046 struct MOVDemuxer<'a> {
1047 src: &'a mut ByteReader<'a>,
1055 pal: Option<Arc<[u8; 1024]>>,
1064 track_str_id: usize,
1075 stream_type: StreamType,
1082 keyframes: Vec<u32>,
1083 chunk_sizes: Vec<u32>,
1084 chunk_offsets: Vec<u64>,
1085 time_to_sample: Vec<(u32, u32)>,
1086 sample_map: Vec<(u32, u32)>,
1088 frame_samples: usize,
1089 ctts_map: RLESearcher<u32>,
1091 stream: Option<NAStream>,
1094 cur_ts: Option<u64>,
1095 samples_left: usize,
1097 pal: Option<Arc<[u8; 1024]>>,
1098 timesearch: TimeSearcher,
1106 struct TimeSearcher {
1115 fn new() -> Self { Self::default() }
1116 fn reset(&mut self) {
1117 *self = Self::default();
1119 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
1122 } else if sample >= self.sbase {
1123 let mut sample = sample - self.sbase;
1125 let (cur_len, cur_mul) = tts[0];
1126 self.cur_len = cur_len;
1127 self.cur_mul = cur_mul;
1130 while self.idx < tts.len() && sample > self.cur_len {
1131 sample -= self.cur_len;
1132 self.sbase += self.cur_len;
1133 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1134 self.cur_len = tts[self.idx].0;
1135 self.cur_mul = tts[self.idx].1;
1138 self.base + u64::from(sample) * u64::from(self.cur_mul)
1141 self.map_time(sample, tts)
1147 struct RLESearcher<T> {
1148 array: Vec<(u32, T)>,
1154 impl<T:Default+Copy> RLESearcher<T> {
1155 fn new() -> Self { Self::default() }
1156 fn resize(&mut self, size: usize) {
1158 self.array.reserve(size);
1160 fn reserve(&mut self, size: usize) {
1161 self.array.reserve(size);
1163 fn add(&mut self, len: u32, val: T) {
1164 self.array.push((len, val));
1166 fn reset(&mut self) {
1168 if !self.array.is_empty() {
1170 self.next = u64::from(self.array[0].0);
1172 self.idx = self.array.len();
1176 fn map(&mut self, sample: u64) -> Option<T> {
1177 if sample < self.start {
1180 if self.idx < self.array.len() {
1181 if sample < self.next {
1182 Some(self.array[self.idx].1)
1184 while (self.idx < self.array.len()) && (sample >= self.next) {
1185 self.start = self.next;
1187 if self.idx < self.array.len() {
1188 self.next += u64::from(self.array[self.idx].0);
1191 if self.idx < self.array.len() {
1192 Some(self.array[self.idx].1)
1204 fn new(track_no: u32, tb_den: u32) -> Self {
1217 stream_type: StreamType::None,
1224 keyframes: Vec::new(),
1225 chunk_sizes: Vec::new(),
1226 chunk_offsets: Vec::new(),
1227 time_to_sample: Vec::new(),
1228 sample_map: Vec::new(),
1231 ctts_map: RLESearcher::new(),
1241 timesearch: TimeSearcher::new(),
1245 print_chunks: false,
1248 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1249 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1250 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1251 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1252 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1253 fn rescale(&mut self, tb_num: u32) {
1254 self.tb_div = tb_num;
1255 if let Some(ref mut stream) = self.stream {
1256 let tb_den = stream.tb_den;
1257 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1258 stream.duration /= u64::from(self.tb_div);
1259 stream.tb_num = tb_num;
1260 stream.tb_den = tb_den;
1261 self.tb_num = tb_num;
1262 self.tb_den = tb_den;
1263 self.duration /= self.tb_div;
1266 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1267 if !self.keyframes.is_empty() {
1268 seek_index.mode = SeekIndexMode::Present;
1270 let mut tsearch = TimeSearcher::new();
1271 for kf_time in self.keyframes.iter() {
1272 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1273 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1274 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1277 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1282 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1283 (nsamp * self.bits * self.channels + 7) >> 3
1286 let nblocks = (nsamp + 63) >> 6;
1287 nblocks * 34 * self.channels
1290 (nsamp + 5) / 6 * 2 * self.channels
1293 (nsamp + 5) / 6 * self.channels
1295 b"in24" => nsamp * 3 * self.channels,
1296 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1297 b"fl64" => nsamp * 8 * self.channels,
1298 b"ulaw" | b"alaw" => nsamp,
1299 b"ms\x00\x02" => { //MS ADPCM
1300 ((nsamp - 1) / 2 + 7) * self.channels
1302 b"ms\x00\x21" => { //IMA ADPCM
1303 (nsamp / 2 + 4) * self.channels
1309 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1310 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1311 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1312 let dts = match self.ctts_version {
1313 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1314 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1315 _ => unimplemented!(),
1317 if (dts as i64) < 0 {
1325 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1326 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1327 if self.cur_sample >= self.chunk_sizes.len() {
1330 let offset = self.chunk_offsets[self.cur_sample];
1331 let size = self.chunk_sizes[self.cur_sample] as usize;
1332 self.cur_sample += 1;
1333 Some((pts, offset, size))
1335 if self.samples_left == 0 {
1336 if self.cur_chunk >= self.chunk_offsets.len() {
1339 for (idx, samples) in self.sample_map.iter() {
1340 if *idx as usize <= self.cur_chunk + 1 {
1341 self.samples_left = *samples as usize;
1346 self.last_offset = self.chunk_offsets[self.cur_chunk];
1347 self.cur_chunk += 1;
1349 let offset = self.last_offset;
1350 let size = self.get_size(self.cur_sample);
1351 self.last_offset += size as u64;
1352 if self.stream_type == StreamType::Video {
1353 self.samples_left -= 1;
1354 } else if self.frame_samples != 0 && self.bsize != 0 {
1355 let nblocks = size / self.bsize;
1357 pts.pts = Some(self.raw_apos);
1358 pts.duration = Some(nblocks as u64);
1359 self.raw_apos += nblocks as u64;
1362 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1363 self.samples_left -= consumed;
1365 self.samples_left = 0;
1367 } else if !self.raw_audio {
1368 self.samples_left -= 1;
1370 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1371 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1372 let cur_size = self.calculate_chunk_size(self.samples_left);
1373 let add_off = (size - cur_size) as u64;
1374 let dsize = cur_size.min(max_size);
1375 if self.samples_left >= BLOCK_SAMPLES {
1376 self.cur_sample += BLOCK_SAMPLES;
1377 self.samples_left -= BLOCK_SAMPLES;
1378 self.last_offset -= size as u64;
1380 self.cur_sample += self.samples_left;
1381 self.samples_left = 0;
1383 return Some((pts, offset + add_off, dsize));
1385 self.cur_sample += 1;
1386 Some((pts, offset, size))
1389 fn get_size(&self, sample_no: usize) -> usize {
1390 if !self.chunk_sizes.is_empty() {
1391 self.chunk_sizes[sample_no] as usize
1392 } else if !self.sample_map.is_empty() {
1394 for (idx, samples) in self.sample_map.iter() {
1395 if *idx as usize <= self.cur_chunk {
1401 self.calculate_chunk_size(nsamp as usize)
1406 #[allow(clippy::collapsible_if)]
1407 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1408 self.cur_sample = pts as usize;
1409 self.samples_left = 0;
1411 if self.stream_type == StreamType::Audio {
1412 if let NATimePoint::Milliseconds(ms) = tpoint {
1413 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1415 if self.frame_samples != 0 {
1416 self.raw_apos = exp_pts / (self.frame_samples as u64);
1418 self.cur_sample = 0;
1420 let mut cmap = self.sample_map.iter();
1421 let mut cur_samps = 0;
1422 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1424 if self.cur_chunk + 1 == next_idx as usize {
1425 self.samples_left = cur_samps;
1426 cur_samps = next_samples as usize;
1427 if let Some((new_idx, new_samples)) = cmap.next() {
1428 next_idx = *new_idx;
1429 next_samples = *new_samples;
1432 self.raw_apos = apos;
1433 apos += (cur_samps / self.frame_samples) as u64;
1435 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1436 if self.cur_chunk >= self.chunk_offsets.len() {
1437 return Err(DemuxerError::SeekError);
1439 self.last_offset = self.chunk_offsets[self.cur_chunk];
1443 self.cur_chunk += 1;
1445 self.samples_left = cur_samps;
1446 self.cur_chunk += 1;
1448 self.raw_apos = exp_pts;
1449 self.cur_sample = exp_pts as usize;
1452 let mut cmap = self.sample_map.iter();
1453 let mut cur_samps = 0;
1454 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1456 if self.cur_chunk + 1 == next_idx as usize {
1457 self.samples_left = cur_samps;
1458 cur_samps = next_samples as usize;
1459 if let Some((new_idx, new_samples)) = cmap.next() {
1460 next_idx = *new_idx;
1461 next_samples = *new_samples;
1465 if csamp > self.cur_sample {
1466 if self.cur_chunk >= self.chunk_offsets.len() {
1467 return Err(DemuxerError::SeekError);
1469 self.last_offset = self.chunk_offsets[self.cur_chunk];
1472 self.cur_chunk += 1;
1474 self.samples_left = csamp - self.cur_sample;
1475 self.cur_chunk += 1;
1477 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
1478 self.cur_chunk = self.cur_sample;
1482 let mut cmap = self.sample_map.iter();
1483 let mut cur_samps = 0;
1484 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1486 if self.cur_chunk + 1 == next_idx as usize {
1487 self.samples_left = cur_samps;
1488 cur_samps = next_samples as usize;
1489 if let Some((new_idx, new_samples)) = cmap.next() {
1490 next_idx = *new_idx;
1491 next_samples = *new_samples;
1495 if csamp > self.cur_sample {
1496 if self.cur_chunk >= self.chunk_offsets.len() {
1497 return Err(DemuxerError::SeekError);
1499 self.last_offset = self.chunk_offsets[self.cur_chunk];
1502 self.cur_chunk += 1;
1504 self.cur_sample = csamp - cur_samps;
1505 self.samples_left = cur_samps;
1506 self.last_offset = self.chunk_offsets[self.cur_chunk];
1507 self.cur_chunk += 1;
1510 self.cur_chunk = self.cur_sample;
1512 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1515 let mut cmap = self.sample_map.iter();
1516 let mut cur_samps = 0;
1517 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1519 if self.cur_chunk + 1 == next_idx as usize {
1520 self.samples_left = cur_samps;
1521 cur_samps = next_samples as usize;
1522 if let Some((new_idx, new_samples)) = cmap.next() {
1523 next_idx = *new_idx;
1524 next_samples = *new_samples;
1528 if csamp >= self.cur_sample {
1529 if self.cur_chunk >= self.chunk_offsets.len() {
1530 return Err(DemuxerError::SeekError);
1532 self.last_offset = self.chunk_offsets[self.cur_chunk];
1535 self.cur_chunk += 1;
1538 for sample_no in csamp..self.cur_sample {
1539 self.last_offset += self.get_size(sample_no) as u64;
1541 self.samples_left = csamp + cur_samps - self.cur_sample;
1542 self.cur_chunk += 1;
1548 fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1549 if let Some(cpts) = pts.get_pts() {
1550 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1551 track.cur_ts = Some(ts);
1553 track.cur_ts = None;
1555 let str = strmgr.get_stream(track.track_str_id);
1556 if str.is_none() { return Err(DemuxerError::InvalidData); }
1557 let stream = str.unwrap();
1558 src.seek(SeekFrom::Start(offset))?;
1559 let mut pkt = src.read_packet(stream, pts, false, size)?;
1560 if let Some(ref pal) = track.pal {
1561 let side_data = NASideData::Palette(first, pal.clone());
1562 pkt.add_side_data(side_data);
1567 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1568 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1569 self.read_root(strmgr)?;
1570 validate!(self.mdat_pos > 0);
1571 validate!(!self.tracks.is_empty());
1572 for track in self.tracks.iter_mut() {
1574 std::mem::swap(&mut track.stream, &mut str);
1575 if let Some(stream) = str {
1576 let str_id = strmgr.add_stream(stream).unwrap();
1577 track.track_str_id = str_id;
1580 for track in self.tracks.iter() {
1581 track.fill_seek_index(seek_index);
1583 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1588 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1589 if self.tracks.is_empty() {
1590 return Err(DemuxerError::EOF);
1592 let mut has_all_time = true;
1593 let mut min_ts = std::u64::MAX;
1594 for trk in self.tracks.iter() {
1595 if let Some(ts) = trk.cur_ts {
1596 min_ts = min_ts.min(ts);
1598 has_all_time = false;
1603 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1604 if let Some(ts) = track.cur_ts {
1606 let first = track.cur_sample == 0;
1607 if let Some((pts, offset, size)) = track.get_next_chunk() {
1608 self.cur_track = trk_no + 1;
1609 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1616 for _ in 0..self.tracks.len() {
1617 if self.cur_track >= self.tracks.len() {
1620 let track = &mut self.tracks[self.cur_track];
1621 self.cur_track += 1;
1622 let first = track.cur_sample == 0;
1623 if let Some((pts, offset, size)) = track.get_next_chunk() {
1624 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1627 Err(DemuxerError::EOF)
1630 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1631 let ret = seek_index.find_pos(time);
1633 if let NATimePoint::Milliseconds(_) = time {
1634 let mut aonly = true;
1635 for track in self.tracks.iter() {
1636 if track.stream_type != StreamType::Audio || !track.raw_audio {
1642 for track in self.tracks.iter_mut() {
1643 track.seek(0, time)?;
1648 return Err(DemuxerError::SeekError);
1650 let seek_info = ret.unwrap();
1651 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1652 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
1653 for track in self.tracks.iter_mut() {
1654 let cur_pts = if track.track_id == seek_info.str_id {
1657 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1659 track.seek(cur_pts, time)?;
1663 fn get_duration(&self) -> u64 {
1664 if self.tb_den != 0 {
1665 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1672 const PRINT_CHUNKS: &str = "print_chunks";
1674 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1675 NAOptionDefinition {
1677 description: "Print parsed file structure",
1678 opt_type: NAOptionDefinitionType::Bool },
1681 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1682 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1683 #[allow(clippy::single_match)]
1684 fn set_options(&mut self, options: &[NAOption]) {
1685 for option in options.iter() {
1686 for opt_def in DEMUXER_OPTIONS.iter() {
1687 if opt_def.check(option).is_ok() {
1688 match (option.name, &option.value) {
1689 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1690 self.print_chunks = *val;
1698 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1700 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1706 impl<'a> MOVDemuxer<'a> {
1707 fn new(io: &'a mut ByteReader<'a>) -> Self {
1713 tracks: Vec::with_capacity(2),
1721 print_chunks: false,
1724 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1726 while self.src.left() != 0 {
1727 let ret = read_chunk_header(&mut self.src);
1728 if ret.is_err() { break; }
1729 let (ctype, size) = ret.unwrap();
1730 if self.print_chunks {
1731 print_cname(ctype, size, self.src.tell(), 0);
1733 if IGNORED_CHUNKS.contains(&ctype) {
1734 self.src.skip64(size)?;
1737 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1739 if let Some(ref handler) = handler {
1740 read_size = (handler.parse)(self, strmgr, size)?;
1742 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1745 validate!(read_size <= size);
1746 self.src.skip64(size - read_size)?;
1748 //todo check if all needed chunks are found
1751 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1752 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
1755 pub struct MOVDemuxerCreator { }
1757 impl DemuxerCreator for MOVDemuxerCreator {
1758 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1759 Box::new(MOVDemuxer::new(br))
1761 fn get_name(&self) -> &'static str { "mov" }
1764 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1765 0x93, 0x65, 0x5E, 0x00,
1766 0xFF, 0xFF, 0xFF, 0x00,
1767 0xDF, 0xD0, 0xAB, 0x00,
1768 0x00, 0x00, 0x00, 0x00
1770 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1771 0xFF, 0xFB, 0xFF, 0x00,
1772 0xEF, 0xD9, 0xBB, 0x00,
1773 0xE8, 0xC9, 0xB1, 0x00,
1774 0x93, 0x65, 0x5E, 0x00,
1775 0xFC, 0xDE, 0xE8, 0x00,
1776 0x9D, 0x88, 0x91, 0x00,
1777 0xFF, 0xFF, 0xFF, 0x00,
1778 0xFF, 0xFF, 0xFF, 0x00,
1779 0xFF, 0xFF, 0xFF, 0x00,
1780 0x47, 0x48, 0x37, 0x00,
1781 0x7A, 0x5E, 0x55, 0x00,
1782 0xDF, 0xD0, 0xAB, 0x00,
1783 0xFF, 0xFB, 0xF9, 0x00,
1784 0xE8, 0xCA, 0xC5, 0x00,
1785 0x8A, 0x7C, 0x77, 0x00,
1786 0x00, 0x00, 0x00, 0x00
1788 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1789 0xFF, 0xFF, 0xFF, 0x00,
1790 0xFF, 0xFF, 0xCC, 0x00,
1791 0xFF, 0xFF, 0x99, 0x00,
1792 0xFF, 0xFF, 0x66, 0x00,
1793 0xFF, 0xFF, 0x33, 0x00,
1794 0xFF, 0xFF, 0x00, 0x00,
1795 0xFF, 0xCC, 0xFF, 0x00,
1796 0xFF, 0xCC, 0xCC, 0x00,
1797 0xFF, 0xCC, 0x99, 0x00,
1798 0xFF, 0xCC, 0x66, 0x00,
1799 0xFF, 0xCC, 0x33, 0x00,
1800 0xFF, 0xCC, 0x00, 0x00,
1801 0xFF, 0x99, 0xFF, 0x00,
1802 0xFF, 0x99, 0xCC, 0x00,
1803 0xFF, 0x99, 0x99, 0x00,
1804 0xFF, 0x99, 0x66, 0x00,
1805 0xFF, 0x99, 0x33, 0x00,
1806 0xFF, 0x99, 0x00, 0x00,
1807 0xFF, 0x66, 0xFF, 0x00,
1808 0xFF, 0x66, 0xCC, 0x00,
1809 0xFF, 0x66, 0x99, 0x00,
1810 0xFF, 0x66, 0x66, 0x00,
1811 0xFF, 0x66, 0x33, 0x00,
1812 0xFF, 0x66, 0x00, 0x00,
1813 0xFF, 0x33, 0xFF, 0x00,
1814 0xFF, 0x33, 0xCC, 0x00,
1815 0xFF, 0x33, 0x99, 0x00,
1816 0xFF, 0x33, 0x66, 0x00,
1817 0xFF, 0x33, 0x33, 0x00,
1818 0xFF, 0x33, 0x00, 0x00,
1819 0xFF, 0x00, 0xFF, 0x00,
1820 0xFF, 0x00, 0xCC, 0x00,
1821 0xFF, 0x00, 0x99, 0x00,
1822 0xFF, 0x00, 0x66, 0x00,
1823 0xFF, 0x00, 0x33, 0x00,
1824 0xFF, 0x00, 0x00, 0x00,
1825 0xCC, 0xFF, 0xFF, 0x00,
1826 0xCC, 0xFF, 0xCC, 0x00,
1827 0xCC, 0xFF, 0x99, 0x00,
1828 0xCC, 0xFF, 0x66, 0x00,
1829 0xCC, 0xFF, 0x33, 0x00,
1830 0xCC, 0xFF, 0x00, 0x00,
1831 0xCC, 0xCC, 0xFF, 0x00,
1832 0xCC, 0xCC, 0xCC, 0x00,
1833 0xCC, 0xCC, 0x99, 0x00,
1834 0xCC, 0xCC, 0x66, 0x00,
1835 0xCC, 0xCC, 0x33, 0x00,
1836 0xCC, 0xCC, 0x00, 0x00,
1837 0xCC, 0x99, 0xFF, 0x00,
1838 0xCC, 0x99, 0xCC, 0x00,
1839 0xCC, 0x99, 0x99, 0x00,
1840 0xCC, 0x99, 0x66, 0x00,
1841 0xCC, 0x99, 0x33, 0x00,
1842 0xCC, 0x99, 0x00, 0x00,
1843 0xCC, 0x66, 0xFF, 0x00,
1844 0xCC, 0x66, 0xCC, 0x00,
1845 0xCC, 0x66, 0x99, 0x00,
1846 0xCC, 0x66, 0x66, 0x00,
1847 0xCC, 0x66, 0x33, 0x00,
1848 0xCC, 0x66, 0x00, 0x00,
1849 0xCC, 0x33, 0xFF, 0x00,
1850 0xCC, 0x33, 0xCC, 0x00,
1851 0xCC, 0x33, 0x99, 0x00,
1852 0xCC, 0x33, 0x66, 0x00,
1853 0xCC, 0x33, 0x33, 0x00,
1854 0xCC, 0x33, 0x00, 0x00,
1855 0xCC, 0x00, 0xFF, 0x00,
1856 0xCC, 0x00, 0xCC, 0x00,
1857 0xCC, 0x00, 0x99, 0x00,
1858 0xCC, 0x00, 0x66, 0x00,
1859 0xCC, 0x00, 0x33, 0x00,
1860 0xCC, 0x00, 0x00, 0x00,
1861 0x99, 0xFF, 0xFF, 0x00,
1862 0x99, 0xFF, 0xCC, 0x00,
1863 0x99, 0xFF, 0x99, 0x00,
1864 0x99, 0xFF, 0x66, 0x00,
1865 0x99, 0xFF, 0x33, 0x00,
1866 0x99, 0xFF, 0x00, 0x00,
1867 0x99, 0xCC, 0xFF, 0x00,
1868 0x99, 0xCC, 0xCC, 0x00,
1869 0x99, 0xCC, 0x99, 0x00,
1870 0x99, 0xCC, 0x66, 0x00,
1871 0x99, 0xCC, 0x33, 0x00,
1872 0x99, 0xCC, 0x00, 0x00,
1873 0x99, 0x99, 0xFF, 0x00,
1874 0x99, 0x99, 0xCC, 0x00,
1875 0x99, 0x99, 0x99, 0x00,
1876 0x99, 0x99, 0x66, 0x00,
1877 0x99, 0x99, 0x33, 0x00,
1878 0x99, 0x99, 0x00, 0x00,
1879 0x99, 0x66, 0xFF, 0x00,
1880 0x99, 0x66, 0xCC, 0x00,
1881 0x99, 0x66, 0x99, 0x00,
1882 0x99, 0x66, 0x66, 0x00,
1883 0x99, 0x66, 0x33, 0x00,
1884 0x99, 0x66, 0x00, 0x00,
1885 0x99, 0x33, 0xFF, 0x00,
1886 0x99, 0x33, 0xCC, 0x00,
1887 0x99, 0x33, 0x99, 0x00,
1888 0x99, 0x33, 0x66, 0x00,
1889 0x99, 0x33, 0x33, 0x00,
1890 0x99, 0x33, 0x00, 0x00,
1891 0x99, 0x00, 0xFF, 0x00,
1892 0x99, 0x00, 0xCC, 0x00,
1893 0x99, 0x00, 0x99, 0x00,
1894 0x99, 0x00, 0x66, 0x00,
1895 0x99, 0x00, 0x33, 0x00,
1896 0x99, 0x00, 0x00, 0x00,
1897 0x66, 0xFF, 0xFF, 0x00,
1898 0x66, 0xFF, 0xCC, 0x00,
1899 0x66, 0xFF, 0x99, 0x00,
1900 0x66, 0xFF, 0x66, 0x00,
1901 0x66, 0xFF, 0x33, 0x00,
1902 0x66, 0xFF, 0x00, 0x00,
1903 0x66, 0xCC, 0xFF, 0x00,
1904 0x66, 0xCC, 0xCC, 0x00,
1905 0x66, 0xCC, 0x99, 0x00,
1906 0x66, 0xCC, 0x66, 0x00,
1907 0x66, 0xCC, 0x33, 0x00,
1908 0x66, 0xCC, 0x00, 0x00,
1909 0x66, 0x99, 0xFF, 0x00,
1910 0x66, 0x99, 0xCC, 0x00,
1911 0x66, 0x99, 0x99, 0x00,
1912 0x66, 0x99, 0x66, 0x00,
1913 0x66, 0x99, 0x33, 0x00,
1914 0x66, 0x99, 0x00, 0x00,
1915 0x66, 0x66, 0xFF, 0x00,
1916 0x66, 0x66, 0xCC, 0x00,
1917 0x66, 0x66, 0x99, 0x00,
1918 0x66, 0x66, 0x66, 0x00,
1919 0x66, 0x66, 0x33, 0x00,
1920 0x66, 0x66, 0x00, 0x00,
1921 0x66, 0x33, 0xFF, 0x00,
1922 0x66, 0x33, 0xCC, 0x00,
1923 0x66, 0x33, 0x99, 0x00,
1924 0x66, 0x33, 0x66, 0x00,
1925 0x66, 0x33, 0x33, 0x00,
1926 0x66, 0x33, 0x00, 0x00,
1927 0x66, 0x00, 0xFF, 0x00,
1928 0x66, 0x00, 0xCC, 0x00,
1929 0x66, 0x00, 0x99, 0x00,
1930 0x66, 0x00, 0x66, 0x00,
1931 0x66, 0x00, 0x33, 0x00,
1932 0x66, 0x00, 0x00, 0x00,
1933 0x33, 0xFF, 0xFF, 0x00,
1934 0x33, 0xFF, 0xCC, 0x00,
1935 0x33, 0xFF, 0x99, 0x00,
1936 0x33, 0xFF, 0x66, 0x00,
1937 0x33, 0xFF, 0x33, 0x00,
1938 0x33, 0xFF, 0x00, 0x00,
1939 0x33, 0xCC, 0xFF, 0x00,
1940 0x33, 0xCC, 0xCC, 0x00,
1941 0x33, 0xCC, 0x99, 0x00,
1942 0x33, 0xCC, 0x66, 0x00,
1943 0x33, 0xCC, 0x33, 0x00,
1944 0x33, 0xCC, 0x00, 0x00,
1945 0x33, 0x99, 0xFF, 0x00,
1946 0x33, 0x99, 0xCC, 0x00,
1947 0x33, 0x99, 0x99, 0x00,
1948 0x33, 0x99, 0x66, 0x00,
1949 0x33, 0x99, 0x33, 0x00,
1950 0x33, 0x99, 0x00, 0x00,
1951 0x33, 0x66, 0xFF, 0x00,
1952 0x33, 0x66, 0xCC, 0x00,
1953 0x33, 0x66, 0x99, 0x00,
1954 0x33, 0x66, 0x66, 0x00,
1955 0x33, 0x66, 0x33, 0x00,
1956 0x33, 0x66, 0x00, 0x00,
1957 0x33, 0x33, 0xFF, 0x00,
1958 0x33, 0x33, 0xCC, 0x00,
1959 0x33, 0x33, 0x99, 0x00,
1960 0x33, 0x33, 0x66, 0x00,
1961 0x33, 0x33, 0x33, 0x00,
1962 0x33, 0x33, 0x00, 0x00,
1963 0x33, 0x00, 0xFF, 0x00,
1964 0x33, 0x00, 0xCC, 0x00,
1965 0x33, 0x00, 0x99, 0x00,
1966 0x33, 0x00, 0x66, 0x00,
1967 0x33, 0x00, 0x33, 0x00,
1968 0x33, 0x00, 0x00, 0x00,
1969 0x00, 0xFF, 0xFF, 0x00,
1970 0x00, 0xFF, 0xCC, 0x00,
1971 0x00, 0xFF, 0x99, 0x00,
1972 0x00, 0xFF, 0x66, 0x00,
1973 0x00, 0xFF, 0x33, 0x00,
1974 0x00, 0xFF, 0x00, 0x00,
1975 0x00, 0xCC, 0xFF, 0x00,
1976 0x00, 0xCC, 0xCC, 0x00,
1977 0x00, 0xCC, 0x99, 0x00,
1978 0x00, 0xCC, 0x66, 0x00,
1979 0x00, 0xCC, 0x33, 0x00,
1980 0x00, 0xCC, 0x00, 0x00,
1981 0x00, 0x99, 0xFF, 0x00,
1982 0x00, 0x99, 0xCC, 0x00,
1983 0x00, 0x99, 0x99, 0x00,
1984 0x00, 0x99, 0x66, 0x00,
1985 0x00, 0x99, 0x33, 0x00,
1986 0x00, 0x99, 0x00, 0x00,
1987 0x00, 0x66, 0xFF, 0x00,
1988 0x00, 0x66, 0xCC, 0x00,
1989 0x00, 0x66, 0x99, 0x00,
1990 0x00, 0x66, 0x66, 0x00,
1991 0x00, 0x66, 0x33, 0x00,
1992 0x00, 0x66, 0x00, 0x00,
1993 0x00, 0x33, 0xFF, 0x00,
1994 0x00, 0x33, 0xCC, 0x00,
1995 0x00, 0x33, 0x99, 0x00,
1996 0x00, 0x33, 0x66, 0x00,
1997 0x00, 0x33, 0x33, 0x00,
1998 0x00, 0x33, 0x00, 0x00,
1999 0x00, 0x00, 0xFF, 0x00,
2000 0x00, 0x00, 0xCC, 0x00,
2001 0x00, 0x00, 0x99, 0x00,
2002 0x00, 0x00, 0x66, 0x00,
2003 0x00, 0x00, 0x33, 0x00,
2004 0xEE, 0x00, 0x00, 0x00,
2005 0xDD, 0x00, 0x00, 0x00,
2006 0xBB, 0x00, 0x00, 0x00,
2007 0xAA, 0x00, 0x00, 0x00,
2008 0x88, 0x00, 0x00, 0x00,
2009 0x77, 0x00, 0x00, 0x00,
2010 0x55, 0x00, 0x00, 0x00,
2011 0x44, 0x00, 0x00, 0x00,
2012 0x22, 0x00, 0x00, 0x00,
2013 0x11, 0x00, 0x00, 0x00,
2014 0x00, 0xEE, 0x00, 0x00,
2015 0x00, 0xDD, 0x00, 0x00,
2016 0x00, 0xBB, 0x00, 0x00,
2017 0x00, 0xAA, 0x00, 0x00,
2018 0x00, 0x88, 0x00, 0x00,
2019 0x00, 0x77, 0x00, 0x00,
2020 0x00, 0x55, 0x00, 0x00,
2021 0x00, 0x44, 0x00, 0x00,
2022 0x00, 0x22, 0x00, 0x00,
2023 0x00, 0x11, 0x00, 0x00,
2024 0x00, 0x00, 0xEE, 0x00,
2025 0x00, 0x00, 0xDD, 0x00,
2026 0x00, 0x00, 0xBB, 0x00,
2027 0x00, 0x00, 0xAA, 0x00,
2028 0x00, 0x00, 0x88, 0x00,
2029 0x00, 0x00, 0x77, 0x00,
2030 0x00, 0x00, 0x55, 0x00,
2031 0x00, 0x00, 0x44, 0x00,
2032 0x00, 0x00, 0x22, 0x00,
2033 0x00, 0x00, 0x11, 0x00,
2034 0xEE, 0xEE, 0xEE, 0x00,
2035 0xDD, 0xDD, 0xDD, 0x00,
2036 0xBB, 0xBB, 0xBB, 0x00,
2037 0xAA, 0xAA, 0xAA, 0x00,
2038 0x88, 0x88, 0x88, 0x00,
2039 0x77, 0x77, 0x77, 0x00,
2040 0x55, 0x55, 0x55, 0x00,
2041 0x44, 0x44, 0x44, 0x00,
2042 0x22, 0x22, 0x22, 0x00,
2043 0x11, 0x11, 0x11, 0x00,
2044 0x00, 0x00, 0x00, 0x00
2053 fn test_mov_demux() {
2054 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/cubes.mov
2055 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2056 let mut fr = FileReader::new_read(&mut file);
2057 let mut br = ByteReader::new(&mut fr);
2058 let mut dmx = MOVDemuxer::new(&mut br);
2059 let mut sm = StreamManager::new();
2060 let mut si = SeekIndex::new();
2061 dmx.open(&mut sm, &mut si).unwrap();
2064 let pktres = dmx.get_frame(&mut sm);
2065 if let Err(e) = pktres {
2066 if e == DemuxerError::EOF { break; }
2069 let pkt = pktres.unwrap();
2070 println!("Got {}", pkt);
2075 fn test_dash_demux() {
2076 // sample: a stream downloaded with youtube-dl
2077 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2078 let mut fr = FileReader::new_read(&mut file);
2079 let mut br = ByteReader::new(&mut fr);
2080 let mut dmx = MOVDemuxer::new(&mut br);
2081 let mut sm = StreamManager::new();
2082 let mut si = SeekIndex::new();
2083 dmx.open(&mut sm, &mut si).unwrap();
2086 let pktres = dmx.get_frame(&mut sm);
2087 if let Err(e) = pktres {
2088 if e == DemuxerError::EOF { break; }
2091 let pkt = pktres.unwrap();
2092 println!("Got {}", pkt);