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!((palsize as u64) * 8 + 8 == size);
51 let a = br.read_u16be()?;
52 let r = br.read_u16be()?;
53 let g = br.read_u16be()?;
54 let b = br.read_u16be()?;
55 pal[i * 4] = (r >> 8) as u8;
56 pal[i * 4 + 1] = (g >> 8) as u8;
57 pal[i * 4 + 2] = (b >> 8) as u8;
58 pal[i * 4 + 3] = (a >> 8) as u8;
63 struct RootChunkHandler {
65 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
68 struct TrackChunkHandler {
70 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
73 const IGNORED_CHUNKS: &[u32] = &[
74 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
77 const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
78 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
79 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
80 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
83 fn print_cname(ctype: u32, size: u64, off: u64, depth: u8) {
84 for _ in 0..depth { print!(" "); }
85 let tag = [(ctype >> 24) as u8, (ctype >> 16) as u8, (ctype >> 8) as u8, ctype as u8];
86 let mut printable = true;
87 for &ch in tag.iter() {
88 if ch < 0x20 || ch > 0x7F {
94 print!(" '{}{}{}{}'", tag[0] as char, tag[1] as char, tag[2] as char, tag[3] as char);
96 print!(" {:08X}", ctype);
98 println!(" size {} @ {:X}", size, off);
101 macro_rules! read_chunk_list {
102 (root; $name: expr, $fname: ident, $handlers: ident) => {
103 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
105 validate!(self.depth < 32);
106 let list_end = self.src.tell() + size;
107 while self.src.tell() < list_end {
108 let ret = read_chunk_header(&mut self.src);
109 if ret.is_err() { break; }
110 let (ctype, size) = ret.unwrap();
111 if self.print_chunks {
112 print_cname(ctype, size, self.src.tell(), self.depth as u8);
114 if self.src.tell() + size > list_end {
117 if IGNORED_CHUNKS.contains(&ctype) {
118 self.src.skip64(size)?;
121 let handler = $handlers.iter().find(|x| x.ctype == ctype);
123 if let Some(ref handler) = handler {
124 read_size = (handler.parse)(self, strmgr, size)?;
126 println!("skipping unknown chunk {:08X} size {}", ctype, size);
129 validate!(read_size <= size);
130 self.src.skip64(size - read_size)?;
133 validate!(self.src.tell() == list_end);
137 (track; $name: expr, $fname: ident, $handlers: ident) => {
138 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
140 validate!(self.depth < 32);
141 let list_end = br.tell() + size;
142 while br.tell() < list_end {
143 let ret = read_chunk_header(br);
144 if ret.is_err() { break; }
145 let (ctype, size) = ret.unwrap();
146 if self.print_chunks {
147 print_cname(ctype, size, br.tell(), self.depth + 1);
149 if br.tell() + size > list_end {
152 if IGNORED_CHUNKS.contains(&ctype) {
156 let handler = $handlers.iter().find(|x| x.ctype == ctype);
158 if let Some(ref handler) = handler {
159 read_size = (handler.parse)(self, br, size)?;
163 validate!(read_size <= size);
164 br.skip64(size - read_size)?;
167 validate!(br.tell() == list_end);
173 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
178 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
179 dmx.src.skip64(size)?;
183 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
184 dmx.mdat_pos = dmx.src.tell();
185 dmx.mdat_size = size;
186 dmx.src.skip64(size)?;
190 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
191 dmx.read_moov(strmgr, size)?;
195 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
196 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
197 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
198 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
199 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
200 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
203 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
204 const KNOWN_MVHD_SIZE: u64 = 100;
205 let br = &mut dmx.src;
206 validate!(size >= KNOWN_MVHD_SIZE);
207 let version = br.read_byte()?;
208 validate!(version == 0);
209 let _flags = br.read_u24be()?;
210 let _ctime = br.read_u32be()?;
211 let _mtime = br.read_u32be()?;
212 let tscale = br.read_u32be()?;
213 let duration = br.read_u32be()?;
214 let _pref_rate = br.read_u32be()?;
215 let _pref_volume = br.read_u16be()?;
217 br.read_skip(36)?; // matrix
218 let _preview_time = br.read_u32be()?;
219 let _preview_duration = br.read_u32be()?;
220 let _poster_time = br.read_u32be()?;
221 let _sel_time = br.read_u32be()?;
222 let _sel_duration = br.read_u32be()?;
223 let _cur_time = br.read_u32be()?;
224 let _next_track_id = br.read_u32be()?;
225 dmx.duration = duration;
231 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
232 let br = &mut dmx.src;
233 validate!(size > 24);
234 let dcom_size = br.read_u32be()?;
235 let dcom_tag = br.read_tag()?;
236 let compr_type = br.read_tag()?;
237 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
238 if &compr_type != b"zlib" {
239 return Err(DemuxerError::NotImplemented);
241 let cmvd_size = u64::from(br.read_u32be()?);
242 let cmvd_tag = br.read_tag()?;
243 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
244 let comp_size = (cmvd_size - 12) as usize;
245 let uncomp_size = br.read_u32be()? as usize;
246 validate!(uncomp_size > 8);
247 let mut sbuf = vec![0; comp_size];
248 let mut dbuf = vec![0; uncomp_size];
249 br.read_buf(sbuf.as_mut_slice())?;
250 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
252 return Err(DemuxerError::InvalidData);
254 let len = ret.unwrap();
255 validate!(len == uncomp_size);
256 let mut mr = MemoryReader::new_read(dbuf.as_slice());
257 let mut br = ByteReader::new(&mut mr);
258 let (ctype, csize) = read_chunk_header(&mut br)?;
259 validate!(ctype == mktag!(b"moov"));
260 let mut ddmx = MOVDemuxer::new(&mut br);
261 ddmx.print_chunks = dmx.print_chunks;
262 ddmx.read_moov(strmgr, csize)?;
263 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
264 dmx.duration = ddmx.duration;
265 dmx.tb_den = ddmx.tb_den;
266 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
271 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
272 let mut pal = [0; 1024];
273 let size = read_palette(&mut dmx.src, size, &mut pal)?;
274 dmx.pal = Some(Arc::new(pal));
278 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
279 dmx.src.skip64(size)?;
283 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
284 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
285 track.print_chunks = dmx.print_chunks;
286 track.read_trak(&mut dmx.src, size)?;
287 validate!(track.tkhd_found && track.stsd_found);
288 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
291 std::mem::swap(&mut track.stream, &mut str);
292 if let Some(stream) = str {
293 let str_id = strmgr.add_stream(stream).unwrap();
294 track.track_str_id = str_id;
296 dmx.tracks.push(track);
300 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
301 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
302 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
303 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
304 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
305 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
306 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
307 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
308 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
311 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
312 const KNOWN_TKHD_SIZE: u64 = 84;
313 validate!(size >= KNOWN_TKHD_SIZE);
314 let version = br.read_byte()?;
315 validate!(version == 0);
316 let _flags = br.read_u24be()?;
317 let _ctime = br.read_u32be()?;
318 let _mtime = br.read_u32be()?;
319 let track_id = br.read_u32be()?;
321 let duration = br.read_u32be()?;
323 let _layer = br.read_u16be()?;
324 let _alt_group = br.read_u16be()?;
325 let _volume = br.read_u16be()?;
327 br.read_skip(36)?; // matrix
328 let width = br.read_u32be()? as usize;
329 let height = br.read_u32be()? as usize;
330 track.width = width >> 16;
331 track.height = height >> 16;
332 track.track_id = track_id;
333 track.duration = duration;
335 track.tkhd_found = true;
339 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
340 track.stream_type = StreamType::None;
341 track.read_mdia(br, size)?;
345 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
346 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: read_mdhd },
347 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
348 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
351 fn read_mdhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
352 const KNOWN_MDHD_SIZE: u64 = 24;
353 validate!(size >= KNOWN_MDHD_SIZE);
354 let version = br.read_byte()?;
355 validate!(version == 0);
356 let flags = br.read_u24be()?;
357 validate!(flags == 0);
358 let _ctime = br.read_u32be()?;
359 let _mtime = br.read_u32be()?;
360 track.tb_den = br.read_u32be()?;
361 validate!(track.tb_den != 0);
362 track.duration = br.read_u32be()?;
363 let _language = br.read_u16be()?;
364 let _quality = br.read_u16be()?;
369 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
370 const KNOWN_HDLR_SIZE: u64 = 24;
371 validate!(size >= KNOWN_HDLR_SIZE);
372 let version = br.read_byte()?;
373 validate!(version == 0);
374 let flags = br.read_u24be()?;
375 validate!(flags == 0);
376 let comp_type = br.read_u32be()?;
377 let comp_subtype = br.read_u32be()?;
378 let _comp_manufacturer = br.read_u32be()?;
379 let _comp_flags = br.read_u32be()?;
380 let _comp_flags_mask = br.read_u32be()?;
382 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
383 if comp_subtype == mktag!(b"vide") {
384 track.stream_type = StreamType::Video;
385 } else if comp_subtype == mktag!(b"soun") {
386 track.stream_type = StreamType::Audio;
388 track.stream_type = StreamType::Data;
390 } else if comp_type == mktag!(b"dhlr") {
391 track.stream_type = StreamType::Data;
393 println!("Unknown stream type");
394 track.stream_type = StreamType::Data;
400 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 track.read_minf(br, size)?;
405 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
406 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
407 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
408 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
409 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
410 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
411 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
412 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
415 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
416 const KNOWN_VMHD_SIZE: u64 = 12;
417 validate!(track.stream_type == StreamType::Video);
418 validate!(size >= KNOWN_VMHD_SIZE);
419 let version = br.read_byte()?;
420 validate!(version == 0);
421 let _flags = br.read_u24be()?;
422 br.read_skip(2)?; // graphics mode
423 br.read_skip(6)?; // opcolor
427 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
428 const KNOWN_SMHD_SIZE: u64 = 8;
429 validate!(track.stream_type == StreamType::Audio);
430 validate!(size >= KNOWN_SMHD_SIZE);
431 let version = br.read_byte()?;
432 validate!(version == 0);
433 let _flags = br.read_u24be()?;
434 br.read_skip(2)?; // balance
439 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
440 validate!(track.stream_type == StreamType::Data);
444 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
445 validate!(track.stream_type == StreamType::Data);
446 const KNOWN_GMIN_SIZE: u64 = 16;
447 validate!(size >= KNOWN_GMIN_SIZE);
448 let version = br.read_byte()?;
449 validate!(version == 0);
450 let _flags = br.read_u24be()?;
451 br.read_skip(2)?; // graphics mode
452 br.read_skip(6)?; // opcolor
453 br.read_skip(2)?; // balance
458 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
459 track.read_stbl(br, size)?;
463 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
464 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
465 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
466 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
467 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
468 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
469 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
470 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
471 TrackChunkHandler { ctype: mktag!(b"ctts"), parse: read_ctts },
474 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
475 let read_part = br.tell() - start_pos;
476 if read_part + 8 < size {
477 let mut buf = [0; 8];
478 br.peek_buf(&mut buf)?;
479 if &buf[4..8] != b"wave" {
480 let mut buf = vec![0; (size - read_part) as usize];
481 br.read_buf(&mut buf)?;
482 return Ok(Some(buf));
485 let csize = br.read_u32be()? as u64;
486 let ctag = br.read_u32be()?;
487 validate!(read_part + csize <= size);
488 validate!(ctag == mktag!(b"wave"));
492 let mut buf = [0; 8];
493 br.peek_buf(&mut buf)?;
494 if &buf[4..8] == b"frma" {
497 let mut buf = vec![0; (csize - 20) as usize];
498 br.read_buf(&mut buf)?;
503 } else if csize > 8 {
504 let mut buf = vec![0; (csize as usize) - 8];
505 br.read_buf(&mut buf)?;
515 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
516 const KNOWN_STSD_SIZE: u64 = 24;
517 validate!(size >= KNOWN_STSD_SIZE);
518 let start_pos = br.tell();
519 let version = br.read_byte()?;
520 validate!(version == 0);
521 let _flags = br.read_u24be()?;
522 let entries = br.read_u32be()?;
523 validate!(entries > 0);
524 let esize = u64::from(br.read_u32be()?);
525 validate!(esize + 8 <= size);
526 let mut fcc = [0u8; 4];
527 br.read_buf(&mut fcc)?;
529 let _data_ref = br.read_u16be()?;
534 match track.stream_type {
535 StreamType::Video => {
536 let _ver = br.read_u16be()?;
537 let _revision = br.read_u16le()?;
538 let _vendor = br.read_u32be()?;
539 let _temp_quality = br.read_u32be()?;
540 let _spat_quality = br.read_u32be()?;
541 let width = br.read_u16be()? as usize;
542 let height = br.read_u16be()? as usize;
543 let _hor_res = br.read_u32be()?;
544 let _vert_res = br.read_u32be()?;
545 let data_size = br.read_u32be()?;
546 validate!(data_size == 0);
547 let _frame_count = br.read_u16be()? as usize;
548 let _cname_len = br.read_byte()? as usize;
549 br.read_skip(31)?; // actual compressor name
550 let depth = br.read_u16be()?;
551 let ctable_id = br.read_u16be()?;
552 let grayscale = depth > 0x20 || depth == 1;
553 let depth = if grayscale { depth & 0x1F } else { depth };
554 validate!(depth <= 8 || (ctable_id == 0xFFFF));
556 let max_pal_size = start_pos + size - br.tell();
557 let mut pal = [0; 1024];
558 read_palette(br, max_pal_size, &mut pal)?;
559 track.pal = Some(Arc::new(pal));
560 } else if (depth <= 8) && !grayscale {
563 let mut pal = [0; 1024];
564 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
565 track.pal = Some(Arc::new(pal));
568 let mut pal = [0; 1024];
569 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
570 track.pal = Some(Arc::new(pal));
573 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
577 } else if grayscale && ctable_id != 0xFFFF {
578 let mut pal = [0; 1024];
579 let cdepth = depth & 0x1F;
580 let size = 1 << cdepth;
582 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
583 let mut off = 8 - cdepth;
584 while off >= cdepth {
585 clr |= clr >> (8 - off);
589 clr |= clr >> (8 - off);
592 pal[i * 4 + 1] = clr;
593 pal[i * 4 + 2] = clr;
595 track.pal = Some(Arc::new(pal));
597 // todo other atoms, put as extradata
598 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
600 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
605 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
606 let mut vhdr = NAVideoInfo::new(width, height, false, format);
607 vhdr.bits = depth as u8;
608 //skip various common atoms
609 while br.tell() - start_pos + 4 < size {
610 let mut buf = [0u8; 8];
611 br.peek_buf(&mut buf)?;
612 let tsize = read_u32be(&buf).unwrap() as usize;
613 let tag = &buf[4..8];
614 validate!(tsize >= 8);
616 b"pasp" | b"clap" => {
617 br.read_skip(tsize)?;
622 let edata = if br.tell() - start_pos + 4 < size {
623 let edata_size = br.read_u32be()? as usize;
624 validate!(edata_size >= 4);
625 let mut buf = vec![0; edata_size - 4];
626 br.read_buf(buf.as_mut_slice())?;
631 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
633 StreamType::Audio => {
634 let sver = br.read_u16be()?;
635 let _revision = br.read_u16le()?;
636 let _vendor = br.read_u32be()?;
637 let nchannels = br.read_u16be()?;
638 validate!(nchannels <= 64);
639 let sample_size = br.read_u16be()?;
640 validate!(sample_size <= 128);
641 let _compr_id = br.read_u16be()?;
642 let packet_size = br.read_u16be()? as usize;
643 validate!(packet_size == 0);
644 let sample_rate = br.read_u32be()?;
645 validate!(sample_rate > (1 << 16));
646 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
648 } 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]))) {
653 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
654 if &fcc == b"raw " && sample_size == 8 {
655 soniton.signed = false;
659 let samples_per_packet = br.read_u32be()?;
660 let _bytes_per_packet = br.read_u32be()?;
661 let bytes_per_frame = br.read_u32be()?;
662 let _bytes_per_sample = br.read_u32be()?;
663 track.bsize = bytes_per_frame as usize;
664 track.frame_samples = samples_per_packet as usize;
665 track.tb_num = samples_per_packet;
667 track.bsize = (sample_size / 8) as usize;
669 track.tb_den = sample_rate >> 16;
670 track.raw_audio = match &fcc {
671 b"NONE" | b"raw " | b"twos" | b"sowt" |
672 b"in24" | b"in32" | b"fl32" | b"fl64" |
673 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
675 b"MAC3" | b"MAC6" => true,
678 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
679 let edata = parse_audio_edata(br, start_pos, size)?;
680 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
681 track.channels = nchannels as usize;
682 track.bits = sample_size as usize;
684 StreamType::None => {
685 return Err(DemuxerError::InvalidData);
688 //todo put it all into extradata
690 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
693 let read_size = br.tell() - start_pos;
694 validate!(read_size <= size);
695 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
696 track.stsd_found = true;
700 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
701 validate!(size >= 8);
702 let start_pos = br.tell();
703 let version = br.read_byte()?;
704 validate!(version == 0);
705 let _flags = br.read_u24be()?;
706 let entries = br.read_u32be()? as usize;
707 validate!(entries as u64 <= (size - 8) / 8);
709 } else if entries == 1 {
710 let _count = br.read_u32be()?;
711 let tb_num = br.read_u32be()?;
712 validate!(tb_num != 0);
713 track.tb_div = tb_num;
714 if let Some(ref mut stream) = track.stream {
715 let tb_den = stream.tb_den;
716 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
717 stream.duration /= u64::from(track.tb_div);
718 stream.tb_num = tb_num;
719 stream.tb_den = tb_den;
720 track.tb_num = tb_num;
721 track.tb_den = tb_den;
722 track.duration /= track.tb_div;
725 track.time_to_sample.truncate(0);
726 track.time_to_sample.reserve(entries);
727 for _ in 0..entries {
728 let count = br.read_u32be()?;
729 let mult = br.read_u32be()?;
730 track.time_to_sample.push((count, mult));
733 let read_size = br.tell() - start_pos;
734 validate!(read_size <= size);
738 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
739 let version = br.read_byte()?;
740 validate!(version == 0);
741 let _flags = br.read_u24be()?;
742 let entries = br.read_u32be()? as usize;
743 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
744 validate!((entries * 4 + 8) as u64 == size);
745 track.keyframes = Vec::with_capacity(entries);
746 let mut last_sample_no = 0;
747 for _ in 0..entries {
748 let sample_no = br.read_u32be()?;
749 validate!(sample_no > last_sample_no);
750 track.keyframes.push(sample_no);
751 last_sample_no = sample_no;
756 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
757 let version = br.read_byte()?;
758 validate!(version == 0);
759 let _flags = br.read_u24be()?;
760 let entries = br.read_u32be()? as usize;
761 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
762 validate!((entries * 12 + 8) as u64 == size);
763 track.sample_map = Vec::with_capacity(entries);
764 let mut last_sample_no = 0;
765 for _i in 0..entries {
766 let sample_no = br.read_u32be()?;
767 validate!(sample_no > last_sample_no);
768 let nsamples = br.read_u32be()?;
769 let _sample_desc = br.read_u32be()?;
770 track.sample_map.push((sample_no, nsamples));
771 last_sample_no = sample_no;
776 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
777 let version = br.read_byte()?;
778 validate!(version == 0);
779 let _flags = br.read_u24be()?;
780 let sample_size = br.read_u32be()?;
781 if sample_size != 0 {
782 track.sample_size = sample_size;
783 if track.sample_size != 1 || track.bsize == 0 {
784 track.bsize = sample_size as usize;
788 let entries = br.read_u32be()? as usize;
789 validate!((entries * 4 + 12) as u64 == size);
790 track.chunk_sizes = Vec::with_capacity(entries);
791 for _ in 0..entries {
792 let sample_size = br.read_u32be()?;
793 track.chunk_sizes.push(sample_size);
799 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
800 let version = br.read_byte()?;
801 validate!(version == 0);
802 let _flags = br.read_u24be()?;
803 let entries = br.read_u32be()? as usize;
804 validate!((entries * 4 + 8) as u64 == size);
805 track.chunk_offsets = Vec::with_capacity(entries);
806 for _i in 0..entries {
807 let sample_offset = br.read_u32be()?;
808 track.chunk_offsets.push(u64::from(sample_offset));
813 fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
814 validate!(size >= 8);
815 let version = br.read_byte()?;
816 let _flags = br.read_u24be()?;
818 return Err(DemuxerError::NotImplemented);
820 let entries = br.read_u32be()? as usize;
821 track.ctts_version = version;
822 track.ctts_map.resize(entries);
825 validate!(size == (entries as u64) * 8 + 8);
826 for _ in 0..entries {
827 let samp_count = br.read_u32be()?;
828 let samp_offset = br.read_u32be()?;
829 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
834 track.ctts_map.reset();
839 struct MOVDemuxer<'a> {
840 src: &'a mut ByteReader<'a>,
848 pal: Option<Arc<[u8; 1024]>>,
866 stream_type: StreamType,
874 chunk_sizes: Vec<u32>,
875 chunk_offsets: Vec<u64>,
876 time_to_sample: Vec<(u32, u32)>,
877 sample_map: Vec<(u32, u32)>,
879 frame_samples: usize,
880 ctts_map: RLESearcher<u32>,
882 stream: Option<NAStream>,
887 pal: Option<Arc<[u8; 1024]>>,
888 timesearch: TimeSearcher,
894 struct TimeSearcher {
903 fn new() -> Self { Self::default() }
904 fn reset(&mut self) {
905 *self = Self::default();
907 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
910 } else if sample >= self.sbase {
911 let mut sample = sample - self.sbase;
913 let (cur_len, cur_mul) = tts[0];
914 self.cur_len = cur_len;
915 self.cur_mul = cur_mul;
918 while self.idx < tts.len() && sample > self.cur_len {
919 sample -= self.cur_len;
920 self.sbase += self.cur_len;
921 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
922 self.cur_len = tts[self.idx].0;
923 self.cur_mul = tts[self.idx].1;
926 self.base + u64::from(sample) * u64::from(self.cur_mul)
929 self.map_time(sample, tts)
935 struct RLESearcher<T> {
936 array: Vec<(u32, T)>,
942 impl<T:Default+Copy> RLESearcher<T> {
943 fn new() -> Self { Self::default() }
944 fn resize(&mut self, size: usize) {
945 self.array.truncate(0);
946 self.array.reserve(size);
948 fn add(&mut self, len: u32, val: T) {
949 self.array.push((len, val));
951 fn reset(&mut self) {
953 if !self.array.is_empty() {
955 self.next = u64::from(self.array[0].0);
957 self.idx = self.array.len();
961 fn map(&mut self, sample: u64) -> Option<T> {
962 if sample < self.start {
965 if self.idx < self.array.len() {
966 if sample < self.next {
967 Some(self.array[self.idx].1)
969 while (self.idx < self.array.len()) && (sample >= self.next) {
970 self.start = self.next;
972 if self.idx < self.array.len() {
973 self.next += u64::from(self.array[self.idx].0);
976 if self.idx < self.array.len() {
977 Some(self.array[self.idx].1)
989 fn new(track_no: u32, tb_den: u32) -> Self {
1002 stream_type: StreamType::None,
1009 keyframes: Vec::new(),
1010 chunk_sizes: Vec::new(),
1011 chunk_offsets: Vec::new(),
1012 time_to_sample: Vec::new(),
1013 sample_map: Vec::new(),
1016 ctts_map: RLESearcher::new(),
1025 timesearch: TimeSearcher::new(),
1027 print_chunks: false,
1030 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1031 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1032 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1033 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1034 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1035 if !self.keyframes.is_empty() {
1036 seek_index.mode = SeekIndexMode::Present;
1038 let mut tsearch = TimeSearcher::new();
1039 for kf_time in self.keyframes.iter() {
1040 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1041 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1042 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1045 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1050 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1051 (nsamp * self.bits * self.channels + 7) >> 3
1054 let nblocks = (nsamp + 63) >> 6;
1055 nblocks * 34 * self.channels
1058 (nsamp + 5) / 6 * 2 * self.channels
1061 (nsamp + 5) / 6 * self.channels
1063 b"in24" => nsamp * 3 * self.channels,
1064 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1065 b"fl64" => nsamp * 8 * self.channels,
1066 b"ulaw" | b"alaw" => nsamp,
1067 b"ms\x00\x02" => { //MS ADPCM
1068 ((nsamp - 1) / 2 + 7) * self.channels
1070 b"ms\x00\x21" => { //IMA ADPCM
1071 (nsamp / 2 + 4) * self.channels
1077 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1078 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1079 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1080 let dts = match self.ctts_version {
1081 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1082 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1083 _ => unimplemented!(),
1085 if (dts as i64) < 0 {
1093 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1094 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1095 if self.cur_sample >= self.chunk_sizes.len() {
1098 let offset = self.chunk_offsets[self.cur_sample];
1099 let size = self.chunk_sizes[self.cur_sample] as usize;
1100 self.cur_sample += 1;
1101 Some((pts, offset, size))
1103 if self.samples_left == 0 {
1104 if self.cur_chunk >= self.chunk_offsets.len() {
1107 for (idx, samples) in self.sample_map.iter() {
1108 if *idx as usize <= self.cur_chunk + 1 {
1109 self.samples_left = *samples as usize;
1114 self.last_offset = self.chunk_offsets[self.cur_chunk];
1115 self.cur_chunk += 1;
1117 let offset = self.last_offset;
1118 let size = self.get_size(self.cur_sample);
1119 self.last_offset += size as u64;
1120 if self.stream_type == StreamType::Video {
1121 self.samples_left -= 1;
1122 } else if self.frame_samples != 0 && self.bsize != 0 {
1123 let nblocks = size / self.bsize;
1125 pts.pts = Some(self.raw_apos);
1126 pts.duration = Some(nblocks as u64);
1127 self.raw_apos += nblocks as u64;
1130 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1131 self.samples_left -= consumed;
1133 self.samples_left = 0;
1135 } else if !self.raw_audio {
1136 self.samples_left -= 1;
1138 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1139 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1140 let cur_size = self.calculate_chunk_size(self.samples_left);
1141 let add_off = (size - cur_size) as u64;
1142 let dsize = cur_size.min(max_size);
1143 if self.samples_left >= BLOCK_SAMPLES {
1144 self.cur_sample += BLOCK_SAMPLES;
1145 self.samples_left -= BLOCK_SAMPLES;
1146 self.last_offset -= size as u64;
1148 self.cur_sample += self.samples_left;
1149 self.samples_left = 0;
1151 return Some((pts, offset + add_off, dsize));
1153 self.cur_sample += 1;
1154 Some((pts, offset, size))
1157 fn get_size(&self, sample_no: usize) -> usize {
1158 if !self.chunk_sizes.is_empty() {
1159 self.chunk_sizes[sample_no] as usize
1160 } else if !self.sample_map.is_empty() {
1162 for (idx, samples) in self.sample_map.iter() {
1163 if *idx as usize <= self.cur_chunk {
1169 self.calculate_chunk_size(nsamp as usize)
1174 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1175 self.cur_sample = pts as usize;
1176 self.samples_left = 0;
1177 if self.stream_type == StreamType::Audio {
1178 if let NATimePoint::Milliseconds(ms) = tpoint {
1179 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1181 if self.frame_samples != 0 {
1182 self.raw_apos = exp_pts / (self.frame_samples as u64);
1184 self.cur_sample = 0;
1186 let mut cmap = self.sample_map.iter();
1187 let mut cur_samps = 0;
1188 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1190 if self.cur_chunk + 1 == next_idx as usize {
1191 self.samples_left = cur_samps;
1192 cur_samps = next_samples as usize;
1193 if let Some((new_idx, new_samples)) = cmap.next() {
1194 next_idx = *new_idx;
1195 next_samples = *new_samples;
1198 self.raw_apos = apos;
1199 apos += (cur_samps / self.frame_samples) as u64;
1201 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1202 if self.cur_chunk >= self.chunk_offsets.len() {
1203 return Err(DemuxerError::SeekError);
1205 self.last_offset = self.chunk_offsets[self.cur_chunk];
1209 self.cur_chunk += 1;
1211 self.samples_left = cur_samps;
1212 self.cur_chunk += 1;
1214 self.raw_apos = exp_pts;
1215 self.cur_sample = exp_pts as usize;
1218 let mut cmap = self.sample_map.iter();
1219 let mut cur_samps = 0;
1220 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1222 if self.cur_chunk + 1 == next_idx as usize {
1223 self.samples_left = cur_samps;
1224 cur_samps = next_samples as usize;
1225 if let Some((new_idx, new_samples)) = cmap.next() {
1226 next_idx = *new_idx;
1227 next_samples = *new_samples;
1231 if csamp > self.cur_sample {
1232 if self.cur_chunk >= self.chunk_offsets.len() {
1233 return Err(DemuxerError::SeekError);
1235 self.last_offset = self.chunk_offsets[self.cur_chunk];
1238 self.cur_chunk += 1;
1240 self.samples_left = csamp - self.cur_sample;
1241 self.cur_chunk += 1;
1244 self.cur_chunk = self.cur_sample;
1247 self.cur_chunk = self.cur_sample;
1249 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1252 let mut cmap = self.sample_map.iter();
1253 let mut cur_samps = 0;
1254 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1256 if self.cur_chunk + 1 == next_idx as usize {
1257 self.samples_left = cur_samps;
1258 cur_samps = next_samples as usize;
1259 if let Some((new_idx, new_samples)) = cmap.next() {
1260 next_idx = *new_idx;
1261 next_samples = *new_samples;
1265 if csamp >= self.cur_sample {
1266 if self.cur_chunk >= self.chunk_offsets.len() {
1267 return Err(DemuxerError::SeekError);
1269 self.last_offset = self.chunk_offsets[self.cur_chunk];
1272 self.cur_chunk += 1;
1275 for sample_no in csamp..self.cur_sample {
1276 self.last_offset += self.get_size(sample_no) as u64;
1278 self.samples_left = csamp + cur_samps - self.cur_sample;
1279 self.cur_chunk += 1;
1285 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1286 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1287 self.read_root(strmgr)?;
1288 validate!(self.mdat_pos > 0);
1289 validate!(!self.tracks.is_empty());
1290 for track in self.tracks.iter() {
1291 track.fill_seek_index(seek_index);
1293 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1298 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1299 if self.tracks.is_empty() {
1300 return Err(DemuxerError::EOF);
1302 for _ in 0..self.tracks.len() {
1303 if self.cur_track >= self.tracks.len() {
1306 let track = &mut self.tracks[self.cur_track];
1307 self.cur_track += 1;
1308 let first = track.cur_sample == 0;
1309 if let Some((pts, offset, size)) = track.get_next_chunk() {
1310 let str = strmgr.get_stream(track.track_str_id);
1311 if str.is_none() { return Err(DemuxerError::InvalidData); }
1312 let stream = str.unwrap();
1313 self.src.seek(SeekFrom::Start(offset))?;
1314 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1315 if let Some(ref pal) = track.pal {
1316 let side_data = NASideData::Palette(first, pal.clone());
1317 pkt.add_side_data(side_data);
1322 Err(DemuxerError::EOF)
1325 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1326 let ret = seek_index.find_pos(time);
1328 return Err(DemuxerError::SeekError);
1330 let seek_info = ret.unwrap();
1331 for track in self.tracks.iter_mut() {
1332 track.seek(seek_info.pts, time)?;
1336 fn get_duration(&self) -> u64 {
1337 if self.tb_den != 0 {
1338 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1345 const PRINT_CHUNKS: &str = "print_chunks";
1347 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1348 NAOptionDefinition {
1350 description: "Print parsed file structure",
1351 opt_type: NAOptionDefinitionType::Bool },
1354 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1355 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1356 fn set_options(&mut self, options: &[NAOption]) {
1357 for option in options.iter() {
1358 for opt_def in DEMUXER_OPTIONS.iter() {
1359 if opt_def.check(option).is_ok() {
1360 match (option.name, &option.value) {
1361 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1362 self.print_chunks = *val;
1370 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1372 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1378 impl<'a> MOVDemuxer<'a> {
1379 fn new(io: &'a mut ByteReader<'a>) -> Self {
1385 tracks: Vec::with_capacity(2),
1391 print_chunks: false,
1394 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1396 while self.src.left() != 0 {
1397 let ret = read_chunk_header(&mut self.src);
1398 if ret.is_err() { break; }
1399 let (ctype, size) = ret.unwrap();
1400 if IGNORED_CHUNKS.contains(&ctype) {
1401 self.src.skip64(size)?;
1404 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1406 if let Some(ref handler) = handler {
1407 read_size = (handler.parse)(self, strmgr, size)?;
1409 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1412 validate!(read_size <= size);
1413 self.src.skip64(size - read_size)?;
1415 //todo check if all needed chunks are found
1418 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1421 pub struct MOVDemuxerCreator { }
1423 impl DemuxerCreator for MOVDemuxerCreator {
1424 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1425 Box::new(MOVDemuxer::new(br))
1427 fn get_name(&self) -> &'static str { "mov" }
1430 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1431 0x93, 0x65, 0x5E, 0x00,
1432 0xFF, 0xFF, 0xFF, 0x00,
1433 0xDF, 0xD0, 0xAB, 0x00,
1434 0x00, 0x00, 0x00, 0x00
1436 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1437 0xFF, 0xFB, 0xFF, 0x00,
1438 0xEF, 0xD9, 0xBB, 0x00,
1439 0xE8, 0xC9, 0xB1, 0x00,
1440 0x93, 0x65, 0x5E, 0x00,
1441 0xFC, 0xDE, 0xE8, 0x00,
1442 0x9D, 0x88, 0x91, 0x00,
1443 0xFF, 0xFF, 0xFF, 0x00,
1444 0xFF, 0xFF, 0xFF, 0x00,
1445 0xFF, 0xFF, 0xFF, 0x00,
1446 0x47, 0x48, 0x37, 0x00,
1447 0x7A, 0x5E, 0x55, 0x00,
1448 0xDF, 0xD0, 0xAB, 0x00,
1449 0xFF, 0xFB, 0xF9, 0x00,
1450 0xE8, 0xCA, 0xC5, 0x00,
1451 0x8A, 0x7C, 0x77, 0x00,
1452 0x00, 0x00, 0x00, 0x00
1454 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1455 0xFF, 0xFF, 0xFF, 0x00,
1456 0xFF, 0xFF, 0xCC, 0x00,
1457 0xFF, 0xFF, 0x99, 0x00,
1458 0xFF, 0xFF, 0x66, 0x00,
1459 0xFF, 0xFF, 0x33, 0x00,
1460 0xFF, 0xFF, 0x00, 0x00,
1461 0xFF, 0xCC, 0xFF, 0x00,
1462 0xFF, 0xCC, 0xCC, 0x00,
1463 0xFF, 0xCC, 0x99, 0x00,
1464 0xFF, 0xCC, 0x66, 0x00,
1465 0xFF, 0xCC, 0x33, 0x00,
1466 0xFF, 0xCC, 0x00, 0x00,
1467 0xFF, 0x99, 0xFF, 0x00,
1468 0xFF, 0x99, 0xCC, 0x00,
1469 0xFF, 0x99, 0x99, 0x00,
1470 0xFF, 0x99, 0x66, 0x00,
1471 0xFF, 0x99, 0x33, 0x00,
1472 0xFF, 0x99, 0x00, 0x00,
1473 0xFF, 0x66, 0xFF, 0x00,
1474 0xFF, 0x66, 0xCC, 0x00,
1475 0xFF, 0x66, 0x99, 0x00,
1476 0xFF, 0x66, 0x66, 0x00,
1477 0xFF, 0x66, 0x33, 0x00,
1478 0xFF, 0x66, 0x00, 0x00,
1479 0xFF, 0x33, 0xFF, 0x00,
1480 0xFF, 0x33, 0xCC, 0x00,
1481 0xFF, 0x33, 0x99, 0x00,
1482 0xFF, 0x33, 0x66, 0x00,
1483 0xFF, 0x33, 0x33, 0x00,
1484 0xFF, 0x33, 0x00, 0x00,
1485 0xFF, 0x00, 0xFF, 0x00,
1486 0xFF, 0x00, 0xCC, 0x00,
1487 0xFF, 0x00, 0x99, 0x00,
1488 0xFF, 0x00, 0x66, 0x00,
1489 0xFF, 0x00, 0x33, 0x00,
1490 0xFF, 0x00, 0x00, 0x00,
1491 0xCC, 0xFF, 0xFF, 0x00,
1492 0xCC, 0xFF, 0xCC, 0x00,
1493 0xCC, 0xFF, 0x99, 0x00,
1494 0xCC, 0xFF, 0x66, 0x00,
1495 0xCC, 0xFF, 0x33, 0x00,
1496 0xCC, 0xFF, 0x00, 0x00,
1497 0xCC, 0xCC, 0xFF, 0x00,
1498 0xCC, 0xCC, 0xCC, 0x00,
1499 0xCC, 0xCC, 0x99, 0x00,
1500 0xCC, 0xCC, 0x66, 0x00,
1501 0xCC, 0xCC, 0x33, 0x00,
1502 0xCC, 0xCC, 0x00, 0x00,
1503 0xCC, 0x99, 0xFF, 0x00,
1504 0xCC, 0x99, 0xCC, 0x00,
1505 0xCC, 0x99, 0x99, 0x00,
1506 0xCC, 0x99, 0x66, 0x00,
1507 0xCC, 0x99, 0x33, 0x00,
1508 0xCC, 0x99, 0x00, 0x00,
1509 0xCC, 0x66, 0xFF, 0x00,
1510 0xCC, 0x66, 0xCC, 0x00,
1511 0xCC, 0x66, 0x99, 0x00,
1512 0xCC, 0x66, 0x66, 0x00,
1513 0xCC, 0x66, 0x33, 0x00,
1514 0xCC, 0x66, 0x00, 0x00,
1515 0xCC, 0x33, 0xFF, 0x00,
1516 0xCC, 0x33, 0xCC, 0x00,
1517 0xCC, 0x33, 0x99, 0x00,
1518 0xCC, 0x33, 0x66, 0x00,
1519 0xCC, 0x33, 0x33, 0x00,
1520 0xCC, 0x33, 0x00, 0x00,
1521 0xCC, 0x00, 0xFF, 0x00,
1522 0xCC, 0x00, 0xCC, 0x00,
1523 0xCC, 0x00, 0x99, 0x00,
1524 0xCC, 0x00, 0x66, 0x00,
1525 0xCC, 0x00, 0x33, 0x00,
1526 0xCC, 0x00, 0x00, 0x00,
1527 0x99, 0xFF, 0xFF, 0x00,
1528 0x99, 0xFF, 0xCC, 0x00,
1529 0x99, 0xFF, 0x99, 0x00,
1530 0x99, 0xFF, 0x66, 0x00,
1531 0x99, 0xFF, 0x33, 0x00,
1532 0x99, 0xFF, 0x00, 0x00,
1533 0x99, 0xCC, 0xFF, 0x00,
1534 0x99, 0xCC, 0xCC, 0x00,
1535 0x99, 0xCC, 0x99, 0x00,
1536 0x99, 0xCC, 0x66, 0x00,
1537 0x99, 0xCC, 0x33, 0x00,
1538 0x99, 0xCC, 0x00, 0x00,
1539 0x99, 0x99, 0xFF, 0x00,
1540 0x99, 0x99, 0xCC, 0x00,
1541 0x99, 0x99, 0x99, 0x00,
1542 0x99, 0x99, 0x66, 0x00,
1543 0x99, 0x99, 0x33, 0x00,
1544 0x99, 0x99, 0x00, 0x00,
1545 0x99, 0x66, 0xFF, 0x00,
1546 0x99, 0x66, 0xCC, 0x00,
1547 0x99, 0x66, 0x99, 0x00,
1548 0x99, 0x66, 0x66, 0x00,
1549 0x99, 0x66, 0x33, 0x00,
1550 0x99, 0x66, 0x00, 0x00,
1551 0x99, 0x33, 0xFF, 0x00,
1552 0x99, 0x33, 0xCC, 0x00,
1553 0x99, 0x33, 0x99, 0x00,
1554 0x99, 0x33, 0x66, 0x00,
1555 0x99, 0x33, 0x33, 0x00,
1556 0x99, 0x33, 0x00, 0x00,
1557 0x99, 0x00, 0xFF, 0x00,
1558 0x99, 0x00, 0xCC, 0x00,
1559 0x99, 0x00, 0x99, 0x00,
1560 0x99, 0x00, 0x66, 0x00,
1561 0x99, 0x00, 0x33, 0x00,
1562 0x99, 0x00, 0x00, 0x00,
1563 0x66, 0xFF, 0xFF, 0x00,
1564 0x66, 0xFF, 0xCC, 0x00,
1565 0x66, 0xFF, 0x99, 0x00,
1566 0x66, 0xFF, 0x66, 0x00,
1567 0x66, 0xFF, 0x33, 0x00,
1568 0x66, 0xFF, 0x00, 0x00,
1569 0x66, 0xCC, 0xFF, 0x00,
1570 0x66, 0xCC, 0xCC, 0x00,
1571 0x66, 0xCC, 0x99, 0x00,
1572 0x66, 0xCC, 0x66, 0x00,
1573 0x66, 0xCC, 0x33, 0x00,
1574 0x66, 0xCC, 0x00, 0x00,
1575 0x66, 0x99, 0xFF, 0x00,
1576 0x66, 0x99, 0xCC, 0x00,
1577 0x66, 0x99, 0x99, 0x00,
1578 0x66, 0x99, 0x66, 0x00,
1579 0x66, 0x99, 0x33, 0x00,
1580 0x66, 0x99, 0x00, 0x00,
1581 0x66, 0x66, 0xFF, 0x00,
1582 0x66, 0x66, 0xCC, 0x00,
1583 0x66, 0x66, 0x99, 0x00,
1584 0x66, 0x66, 0x66, 0x00,
1585 0x66, 0x66, 0x33, 0x00,
1586 0x66, 0x66, 0x00, 0x00,
1587 0x66, 0x33, 0xFF, 0x00,
1588 0x66, 0x33, 0xCC, 0x00,
1589 0x66, 0x33, 0x99, 0x00,
1590 0x66, 0x33, 0x66, 0x00,
1591 0x66, 0x33, 0x33, 0x00,
1592 0x66, 0x33, 0x00, 0x00,
1593 0x66, 0x00, 0xFF, 0x00,
1594 0x66, 0x00, 0xCC, 0x00,
1595 0x66, 0x00, 0x99, 0x00,
1596 0x66, 0x00, 0x66, 0x00,
1597 0x66, 0x00, 0x33, 0x00,
1598 0x66, 0x00, 0x00, 0x00,
1599 0x33, 0xFF, 0xFF, 0x00,
1600 0x33, 0xFF, 0xCC, 0x00,
1601 0x33, 0xFF, 0x99, 0x00,
1602 0x33, 0xFF, 0x66, 0x00,
1603 0x33, 0xFF, 0x33, 0x00,
1604 0x33, 0xFF, 0x00, 0x00,
1605 0x33, 0xCC, 0xFF, 0x00,
1606 0x33, 0xCC, 0xCC, 0x00,
1607 0x33, 0xCC, 0x99, 0x00,
1608 0x33, 0xCC, 0x66, 0x00,
1609 0x33, 0xCC, 0x33, 0x00,
1610 0x33, 0xCC, 0x00, 0x00,
1611 0x33, 0x99, 0xFF, 0x00,
1612 0x33, 0x99, 0xCC, 0x00,
1613 0x33, 0x99, 0x99, 0x00,
1614 0x33, 0x99, 0x66, 0x00,
1615 0x33, 0x99, 0x33, 0x00,
1616 0x33, 0x99, 0x00, 0x00,
1617 0x33, 0x66, 0xFF, 0x00,
1618 0x33, 0x66, 0xCC, 0x00,
1619 0x33, 0x66, 0x99, 0x00,
1620 0x33, 0x66, 0x66, 0x00,
1621 0x33, 0x66, 0x33, 0x00,
1622 0x33, 0x66, 0x00, 0x00,
1623 0x33, 0x33, 0xFF, 0x00,
1624 0x33, 0x33, 0xCC, 0x00,
1625 0x33, 0x33, 0x99, 0x00,
1626 0x33, 0x33, 0x66, 0x00,
1627 0x33, 0x33, 0x33, 0x00,
1628 0x33, 0x33, 0x00, 0x00,
1629 0x33, 0x00, 0xFF, 0x00,
1630 0x33, 0x00, 0xCC, 0x00,
1631 0x33, 0x00, 0x99, 0x00,
1632 0x33, 0x00, 0x66, 0x00,
1633 0x33, 0x00, 0x33, 0x00,
1634 0x33, 0x00, 0x00, 0x00,
1635 0x00, 0xFF, 0xFF, 0x00,
1636 0x00, 0xFF, 0xCC, 0x00,
1637 0x00, 0xFF, 0x99, 0x00,
1638 0x00, 0xFF, 0x66, 0x00,
1639 0x00, 0xFF, 0x33, 0x00,
1640 0x00, 0xFF, 0x00, 0x00,
1641 0x00, 0xCC, 0xFF, 0x00,
1642 0x00, 0xCC, 0xCC, 0x00,
1643 0x00, 0xCC, 0x99, 0x00,
1644 0x00, 0xCC, 0x66, 0x00,
1645 0x00, 0xCC, 0x33, 0x00,
1646 0x00, 0xCC, 0x00, 0x00,
1647 0x00, 0x99, 0xFF, 0x00,
1648 0x00, 0x99, 0xCC, 0x00,
1649 0x00, 0x99, 0x99, 0x00,
1650 0x00, 0x99, 0x66, 0x00,
1651 0x00, 0x99, 0x33, 0x00,
1652 0x00, 0x99, 0x00, 0x00,
1653 0x00, 0x66, 0xFF, 0x00,
1654 0x00, 0x66, 0xCC, 0x00,
1655 0x00, 0x66, 0x99, 0x00,
1656 0x00, 0x66, 0x66, 0x00,
1657 0x00, 0x66, 0x33, 0x00,
1658 0x00, 0x66, 0x00, 0x00,
1659 0x00, 0x33, 0xFF, 0x00,
1660 0x00, 0x33, 0xCC, 0x00,
1661 0x00, 0x33, 0x99, 0x00,
1662 0x00, 0x33, 0x66, 0x00,
1663 0x00, 0x33, 0x33, 0x00,
1664 0x00, 0x33, 0x00, 0x00,
1665 0x00, 0x00, 0xFF, 0x00,
1666 0x00, 0x00, 0xCC, 0x00,
1667 0x00, 0x00, 0x99, 0x00,
1668 0x00, 0x00, 0x66, 0x00,
1669 0x00, 0x00, 0x33, 0x00,
1670 0xEE, 0x00, 0x00, 0x00,
1671 0xDD, 0x00, 0x00, 0x00,
1672 0xBB, 0x00, 0x00, 0x00,
1673 0xAA, 0x00, 0x00, 0x00,
1674 0x88, 0x00, 0x00, 0x00,
1675 0x77, 0x00, 0x00, 0x00,
1676 0x55, 0x00, 0x00, 0x00,
1677 0x44, 0x00, 0x00, 0x00,
1678 0x22, 0x00, 0x00, 0x00,
1679 0x11, 0x00, 0x00, 0x00,
1680 0x00, 0xEE, 0x00, 0x00,
1681 0x00, 0xDD, 0x00, 0x00,
1682 0x00, 0xBB, 0x00, 0x00,
1683 0x00, 0xAA, 0x00, 0x00,
1684 0x00, 0x88, 0x00, 0x00,
1685 0x00, 0x77, 0x00, 0x00,
1686 0x00, 0x55, 0x00, 0x00,
1687 0x00, 0x44, 0x00, 0x00,
1688 0x00, 0x22, 0x00, 0x00,
1689 0x00, 0x11, 0x00, 0x00,
1690 0x00, 0x00, 0xEE, 0x00,
1691 0x00, 0x00, 0xDD, 0x00,
1692 0x00, 0x00, 0xBB, 0x00,
1693 0x00, 0x00, 0xAA, 0x00,
1694 0x00, 0x00, 0x88, 0x00,
1695 0x00, 0x00, 0x77, 0x00,
1696 0x00, 0x00, 0x55, 0x00,
1697 0x00, 0x00, 0x44, 0x00,
1698 0x00, 0x00, 0x22, 0x00,
1699 0x00, 0x00, 0x11, 0x00,
1700 0xEE, 0xEE, 0xEE, 0x00,
1701 0xDD, 0xDD, 0xDD, 0x00,
1702 0xBB, 0xBB, 0xBB, 0x00,
1703 0xAA, 0xAA, 0xAA, 0x00,
1704 0x88, 0x88, 0x88, 0x00,
1705 0x77, 0x77, 0x77, 0x00,
1706 0x55, 0x55, 0x55, 0x00,
1707 0x44, 0x44, 0x44, 0x00,
1708 0x22, 0x22, 0x22, 0x00,
1709 0x11, 0x11, 0x11, 0x00,
1710 0x00, 0x00, 0x00, 0x00
1719 fn test_mov_demux() {
1720 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1721 let mut fr = FileReader::new_read(&mut file);
1722 let mut br = ByteReader::new(&mut fr);
1723 let mut dmx = MOVDemuxer::new(&mut br);
1724 let mut sm = StreamManager::new();
1725 let mut si = SeekIndex::new();
1726 dmx.open(&mut sm, &mut si).unwrap();
1729 let pktres = dmx.get_frame(&mut sm);
1730 if let Err(e) = pktres {
1731 if e == DemuxerError::EOF { break; }
1734 let pkt = pktres.unwrap();
1735 println!("Got {}", pkt);