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 macro_rules! read_chunk_list {
84 (root; $name: expr, $fname: ident, $handlers: ident) => {
85 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
87 validate!(self.depth < 32);
88 let list_end = self.src.tell() + size;
89 while self.src.tell() < list_end {
90 let ret = read_chunk_header(&mut self.src);
91 if ret.is_err() { break; }
92 let (ctype, size) = ret.unwrap();
93 if self.src.tell() + size > list_end {
96 if IGNORED_CHUNKS.contains(&ctype) {
97 self.src.skip64(size)?;
100 let handler = $handlers.iter().find(|x| x.ctype == ctype);
102 if let Some(ref handler) = handler {
103 read_size = (handler.parse)(self, strmgr, size)?;
105 println!("skipping unknown chunk {:08X} size {}", ctype, size);
108 validate!(read_size <= size);
109 self.src.skip64(size - read_size)?;
112 validate!(self.src.tell() == list_end);
116 (track; $name: expr, $fname: ident, $handlers: ident) => {
117 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
119 validate!(self.depth < 32);
120 let list_end = br.tell() + size;
121 while br.tell() < list_end {
122 let ret = read_chunk_header(br);
123 if ret.is_err() { break; }
124 let (ctype, size) = ret.unwrap();
125 if br.tell() + size > list_end {
128 if IGNORED_CHUNKS.contains(&ctype) {
132 let handler = $handlers.iter().find(|x| x.ctype == ctype);
134 if let Some(ref handler) = handler {
135 read_size = (handler.parse)(self, br, size)?;
139 validate!(read_size <= size);
140 br.skip64(size - read_size)?;
143 validate!(br.tell() == list_end);
149 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
154 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
155 dmx.src.skip64(size)?;
159 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
160 dmx.mdat_pos = dmx.src.tell();
161 dmx.mdat_size = size;
162 dmx.src.skip64(size)?;
166 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
167 dmx.read_moov(strmgr, size)?;
171 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
172 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
173 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
174 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
175 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
176 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
179 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
180 const KNOWN_MVHD_SIZE: u64 = 100;
181 let br = &mut dmx.src;
182 validate!(size >= KNOWN_MVHD_SIZE);
183 let version = br.read_byte()?;
184 validate!(version == 0);
185 let _flags = br.read_u24be()?;
186 let _ctime = br.read_u32be()?;
187 let _mtime = br.read_u32be()?;
188 let tscale = br.read_u32be()?;
189 let duration = br.read_u32be()?;
190 let _pref_rate = br.read_u32be()?;
191 let _pref_volume = br.read_u16be()?;
193 br.read_skip(36)?; // matrix
194 let _preview_time = br.read_u32be()?;
195 let _preview_duration = br.read_u32be()?;
196 let _poster_time = br.read_u32be()?;
197 let _sel_time = br.read_u32be()?;
198 let _sel_duration = br.read_u32be()?;
199 let _cur_time = br.read_u32be()?;
200 let _next_track_id = br.read_u32be()?;
201 dmx.duration = duration;
207 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
208 let br = &mut dmx.src;
209 validate!(size > 24);
210 let dcom_size = br.read_u32be()?;
211 let dcom_tag = br.read_tag()?;
212 let compr_type = br.read_tag()?;
213 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
214 if &compr_type != b"zlib" {
215 return Err(DemuxerError::NotImplemented);
217 let cmvd_size = u64::from(br.read_u32be()?);
218 let cmvd_tag = br.read_tag()?;
219 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
220 let comp_size = (cmvd_size - 12) as usize;
221 let uncomp_size = br.read_u32be()? as usize;
222 validate!(uncomp_size > 8);
223 let mut sbuf = vec![0; comp_size];
224 let mut dbuf = vec![0; uncomp_size];
225 br.read_buf(sbuf.as_mut_slice())?;
226 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
228 return Err(DemuxerError::InvalidData);
230 let len = ret.unwrap();
231 validate!(len == uncomp_size);
232 let mut mr = MemoryReader::new_read(dbuf.as_slice());
233 let mut br = ByteReader::new(&mut mr);
234 let (ctype, csize) = read_chunk_header(&mut br)?;
235 validate!(ctype == mktag!(b"moov"));
236 let mut ddmx = MOVDemuxer::new(&mut br);
237 ddmx.read_moov(strmgr, csize)?;
238 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
239 dmx.duration = ddmx.duration;
240 dmx.tb_den = ddmx.tb_den;
241 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
246 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
247 let mut pal = [0; 1024];
248 let size = read_palette(&mut dmx.src, size, &mut pal)?;
249 dmx.pal = Some(Arc::new(pal));
253 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
254 dmx.src.skip64(size)?;
258 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
259 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
260 track.read_trak(&mut dmx.src, size)?;
261 validate!(track.tkhd_found && track.stsd_found);
262 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
265 std::mem::swap(&mut track.stream, &mut str);
266 if let Some(stream) = str {
267 let str_id = strmgr.add_stream(stream).unwrap();
268 track.track_str_id = str_id;
270 dmx.tracks.push(track);
274 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
275 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
276 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
277 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
278 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
279 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
280 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
281 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
282 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
285 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
286 const KNOWN_TKHD_SIZE: u64 = 84;
287 validate!(size >= KNOWN_TKHD_SIZE);
288 let version = br.read_byte()?;
289 validate!(version == 0);
290 let _flags = br.read_u24be()?;
291 let _ctime = br.read_u32be()?;
292 let _mtime = br.read_u32be()?;
293 let track_id = br.read_u32be()?;
295 let _duration = br.read_u32be()?;
297 let _layer = br.read_u16be()?;
298 let _alt_group = br.read_u16be()?;
299 let _volume = br.read_u16be()?;
301 br.read_skip(36)?; // matrix
302 let width = br.read_u32be()? as usize;
303 let height = br.read_u32be()? as usize;
304 track.width = width >> 16;
305 track.height = height >> 16;
306 track.track_id = track_id;
308 track.tkhd_found = true;
312 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
313 track.stream_type = StreamType::None;
314 track.read_mdia(br, size)?;
318 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
319 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
320 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
321 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
324 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
325 const KNOWN_HDLR_SIZE: u64 = 24;
326 validate!(size >= KNOWN_HDLR_SIZE);
327 let version = br.read_byte()?;
328 validate!(version == 0);
329 let flags = br.read_u24be()?;
330 validate!(flags == 0);
331 let comp_type = br.read_u32be()?;
332 let comp_subtype = br.read_u32be()?;
333 let _comp_manufacturer = br.read_u32be()?;
334 let _comp_flags = br.read_u32be()?;
335 let _comp_flags_mask = br.read_u32be()?;
337 if comp_type == mktag!(b"mhlr") {
338 if comp_subtype == mktag!(b"vide") {
339 track.stream_type = StreamType::Video;
340 } else if comp_subtype == mktag!(b"soun") {
341 track.stream_type = StreamType::Audio;
343 track.stream_type = StreamType::Data;
345 } else if comp_type == mktag!(b"dhlr") {
346 track.stream_type = StreamType::Data;
348 println!("Unknown stream type");
349 track.stream_type = StreamType::Data;
355 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
356 track.read_minf(br, size)?;
360 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
361 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
362 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
364 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
365 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
366 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
367 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
370 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
371 const KNOWN_VMHD_SIZE: u64 = 12;
372 validate!(track.stream_type == StreamType::Video);
373 validate!(size >= KNOWN_VMHD_SIZE);
374 let version = br.read_byte()?;
375 validate!(version == 0);
376 let _flags = br.read_u24be()?;
377 br.read_skip(2)?; // graphics mode
378 br.read_skip(6)?; // opcolor
382 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
383 const KNOWN_SMHD_SIZE: u64 = 8;
384 validate!(track.stream_type == StreamType::Audio);
385 validate!(size >= KNOWN_SMHD_SIZE);
386 let version = br.read_byte()?;
387 validate!(version == 0);
388 let _flags = br.read_u24be()?;
389 br.read_skip(2)?; // balance
394 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
395 validate!(track.stream_type == StreamType::Data);
399 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
400 validate!(track.stream_type == StreamType::Data);
401 const KNOWN_GMIN_SIZE: u64 = 16;
402 validate!(size >= KNOWN_GMIN_SIZE);
403 let version = br.read_byte()?;
404 validate!(version == 0);
405 let _flags = br.read_u24be()?;
406 br.read_skip(2)?; // graphics mode
407 br.read_skip(6)?; // opcolor
408 br.read_skip(2)?; // balance
413 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
414 track.read_stbl(br, size)?;
418 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
419 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
420 TrackChunkHandler { ctype: mktag!(b"stts"), parse: skip_chunk },
421 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
422 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
423 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
424 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
425 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
428 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
429 let read_part = br.tell() - start_pos;
430 if read_part + 8 < size {
431 let csize = br.read_u32be()? as u64;
432 let ctag = br.read_u32be()?;
433 validate!(read_part + csize <= size);
434 validate!(ctag == mktag!(b"wave"));
438 let mut buf = [0; 8];
439 br.peek_buf(&mut buf)?;
440 if &buf[4..8] == b"frma" {
443 let mut buf = vec![0; (csize - 20) as usize];
444 br.read_buf(&mut buf)?;
449 } else if csize > 8 {
450 let mut buf = vec![0; (csize as usize) - 8];
451 br.read_buf(&mut buf)?;
461 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
462 const KNOWN_STSD_SIZE: u64 = 24;
463 validate!(size >= KNOWN_STSD_SIZE);
464 let start_pos = br.tell();
465 let version = br.read_byte()?;
466 validate!(version == 0);
467 let _flags = br.read_u24be()?;
468 let entries = br.read_u32be()?;
469 validate!(entries > 0);
470 let esize = u64::from(br.read_u32be()?);
471 validate!(esize + 8 <= size);
472 let mut fcc = [0u8; 4];
473 br.read_buf(&mut fcc)?;
475 let _data_ref = br.read_u16be()?;
480 match track.stream_type {
481 StreamType::Video => {
482 let _ver = br.read_u16be()?;
483 let _revision = br.read_u16le()?;
484 let _vendor = br.read_u32be()?;
485 let _temp_quality = br.read_u32be()?;
486 let _spat_quality = br.read_u32be()?;
487 let width = br.read_u16be()? as usize;
488 let height = br.read_u16be()? as usize;
489 let _hor_res = br.read_u32be()?;
490 let _vert_res = br.read_u32be()?;
491 let data_size = br.read_u32be()?;
492 validate!(data_size == 0);
493 let _frame_count = br.read_u16be()? as usize;
494 let _cname_len = br.read_byte()? as usize;
495 br.read_skip(31)?; // actual compressor name
496 let depth = br.read_u16be()?;
497 let ctable_id = br.read_u16be()?;
498 let grayscale = depth > 0x20 || depth == 1;
499 let depth = if grayscale { depth & 0x1F } else { depth };
500 validate!(depth <= 8 || (ctable_id == 0xFFFF));
502 let max_pal_size = start_pos + size - br.tell();
503 let mut pal = [0; 1024];
504 read_palette(br, max_pal_size, &mut pal)?;
505 track.pal = Some(Arc::new(pal));
506 } else if (depth <= 8) && !grayscale {
509 let mut pal = [0; 1024];
510 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
511 track.pal = Some(Arc::new(pal));
514 let mut pal = [0; 1024];
515 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
516 track.pal = Some(Arc::new(pal));
519 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
523 } else if grayscale && ctable_id != 0xFFFF {
524 let mut pal = [0; 1024];
525 let cdepth = depth & 0x1F;
526 let size = 1 << cdepth;
528 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
529 let mut off = 8 - cdepth;
530 while off >= cdepth {
531 clr |= clr >> (8 - off);
535 clr |= clr >> (8 - off);
538 pal[i * 4 + 1] = clr;
539 pal[i * 4 + 2] = clr;
541 track.pal = Some(Arc::new(pal));
543 // todo other atoms, put as extradata
544 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
546 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
551 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
552 let mut vhdr = NAVideoInfo::new(width, height, false, format);
553 vhdr.bits = depth as u8;
554 let edata = if br.tell() - start_pos + 4 < size {
555 //todo skip various common atoms
556 let edata_size = br.read_u32be()? as usize;
557 let mut buf = vec![0; edata_size];
558 br.read_buf(buf.as_mut_slice())?;
563 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
565 StreamType::Audio => {
566 let sver = br.read_u16be()?;
567 let _revision = br.read_u16le()?;
568 let _vendor = br.read_u32be()?;
569 let nchannels = br.read_u16be()?;
570 validate!(nchannels <= 64);
571 let sample_size = br.read_u16be()?;
572 validate!(sample_size <= 128);
573 let _compr_id = br.read_u16be()?;
574 let packet_size = br.read_u16be()? as usize;
575 validate!(packet_size == 0);
576 let sample_rate = br.read_u32be()?;
577 validate!(sample_rate > 0);
578 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
580 } 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]))) {
585 //todo adjust format for various PCM kinds
586 let soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
589 let _samples_per_packet = br.read_u32be()?;
590 let _bytes_per_packet = br.read_u32be()?;
591 let bytes_per_frame = br.read_u32be()?;
592 let _bytes_per_sample = br.read_u32be()?;
593 track.bsize = bytes_per_frame as usize;
595 track.bsize = sample_size as usize;
597 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
598 let edata = parse_audio_edata(br, start_pos, size)?;
599 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
600 track.channels = nchannels as usize;
601 track.bits = sample_size as usize;
603 StreamType::None => {
604 return Err(DemuxerError::InvalidData);
607 //todo put it all into extradata
609 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
612 let read_size = br.tell() - start_pos;
613 validate!(read_size <= size);
614 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den));
615 track.stsd_found = true;
619 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
620 let version = br.read_byte()?;
621 validate!(version == 0);
622 let _flags = br.read_u24be()?;
623 let entries = br.read_u32be()? as usize;
624 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
625 validate!((entries * 4 + 8) as u64 == size);
626 track.keyframes = Vec::with_capacity(entries);
627 let mut last_sample_no = 0;
628 for _ in 0..entries {
629 let sample_no = br.read_u32be()?;
630 validate!(sample_no > last_sample_no);
631 track.keyframes.push(sample_no);
632 last_sample_no = sample_no;
637 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
638 let version = br.read_byte()?;
639 validate!(version == 0);
640 let _flags = br.read_u24be()?;
641 let entries = br.read_u32be()? as usize;
642 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
643 validate!((entries * 12 + 8) as u64 == size);
644 track.sample_map = Vec::with_capacity(entries);
645 let mut last_sample_no = 0;
646 for _i in 0..entries {
647 let sample_no = br.read_u32be()?;
648 validate!(sample_no > last_sample_no);
649 let nsamples = br.read_u32be()?;
650 let _sample_desc = br.read_u32be()?;
651 track.sample_map.push((sample_no, nsamples));
652 last_sample_no = sample_no;
657 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
658 let version = br.read_byte()?;
659 validate!(version == 0);
660 let _flags = br.read_u24be()?;
661 let sample_size = br.read_u32be()?;
662 if sample_size != 0 {
663 track.sample_size = sample_size;
664 if track.sample_size != 1 || track.bsize == 0 {
665 track.bsize = sample_size as usize;
669 let entries = br.read_u32be()? as usize;
670 validate!((entries * 4 + 12) as u64 == size);
671 track.chunk_sizes = Vec::with_capacity(entries);
672 for _ in 0..entries {
673 let sample_size = br.read_u32be()?;
674 track.chunk_sizes.push(sample_size);
680 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
681 let version = br.read_byte()?;
682 validate!(version == 0);
683 let _flags = br.read_u24be()?;
684 let entries = br.read_u32be()? as usize;
685 validate!((entries * 4 + 8) as u64 == size);
686 track.chunk_offsets = Vec::with_capacity(entries);
687 for _i in 0..entries {
688 let sample_offset = br.read_u32be()?;
689 track.chunk_offsets.push(u64::from(sample_offset));
694 struct MOVDemuxer<'a> {
695 src: &'a mut ByteReader<'a>,
703 pal: Option<Arc<[u8; 1024]>>,
714 stream_type: StreamType,
722 chunk_sizes: Vec<u32>,
723 chunk_offsets: Vec<u64>,
724 sample_map: Vec<(u32, u32)>,
726 stream: Option<NAStream>,
731 pal: Option<Arc<[u8; 1024]>>,
735 fn new(track_no: u32, tb_den: u32) -> Self {
743 stream_type: StreamType::None,
750 keyframes: Vec::new(),
751 chunk_sizes: Vec::new(),
752 chunk_offsets: Vec::new(),
753 sample_map: Vec::new(),
764 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
765 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
766 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
767 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
768 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
769 if !self.keyframes.is_empty() {
770 seek_index.mode = SeekIndexMode::Present;
772 for kf_time in self.keyframes.iter() {
773 let pts = u64::from(*kf_time - 1);
774 let time = NATimeInfo::ts_to_time(pts, 1000, 1, self.tb_den);
775 let idx = (*kf_time - 1) as usize;
776 if idx < self.chunk_offsets.len() {
777 let pos = self.chunk_offsets[idx];
778 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts, pos });
782 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
787 b"NONE" | b"raw " | b"twos" | b"sowt" => {
788 (nsamp * self.bits * self.channels + 7) >> 3
791 let nblocks = (nsamp + 63) >> 6;
792 nblocks * 34 * self.channels
795 (nsamp + 5) / 6 * 2 * self.channels
798 (nsamp + 5) / 6 * self.channels
800 b"in24" => nsamp * 3 * self.channels,
801 b"in32" | b"fl32" => nsamp * 4 * self.channels,
802 b"fl64" => nsamp * 8 * self.channels,
803 b"ulaw" | b"alaw" => nsamp,
804 b"ms\x00\x02" => { //MS ADPCM
805 ((nsamp - 1) / 2 + 7) * self.channels
807 b"ms\x00\x21" => { //IMA ADPCM
808 (nsamp / 2 + 4) * self.channels
814 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
815 let pts = NATimeInfo::new(Some(self.cur_sample as u64), None, None, 1, self.tb_den);
817 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
818 if self.cur_sample >= self.chunk_sizes.len() {
821 let offset = self.chunk_offsets[self.cur_sample];
822 let size = self.chunk_sizes[self.cur_sample] as usize;
823 self.cur_sample += 1;
824 Some((pts, offset, size))
826 if self.samples_left == 0 {
827 if self.cur_chunk >= self.chunk_offsets.len() {
830 for (idx, samples) in self.sample_map.iter() {
831 if *idx as usize <= self.cur_chunk + 1 {
832 self.samples_left = *samples as usize;
837 self.last_offset = self.chunk_offsets[self.cur_chunk];
840 let offset = self.last_offset;
841 let size = self.get_size(self.cur_sample);
842 self.last_offset += size as u64;
843 if self.stream_type == StreamType::Video {
844 self.samples_left -= 1;
846 self.samples_left = 0;
848 self.cur_sample += 1;
849 Some((pts, offset, size))
852 fn get_size(&self, sample_no: usize) -> usize {
853 if !self.chunk_sizes.is_empty() {
854 self.chunk_sizes[sample_no] as usize
855 } else if !self.sample_map.is_empty() {
857 for (idx, samples) in self.sample_map.iter() {
858 if *idx as usize <= self.cur_chunk {
864 self.calculate_chunk_size(nsamp as usize)
869 fn seek(&mut self, pts: u64) {
870 self.cur_sample = pts as usize;
871 self.samples_left = 0;
872 if self.stream_type == StreamType::Audio {
873 self.cur_chunk = self.cur_sample;
874 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
877 let mut cmap = self.sample_map.iter();
878 let mut cur_samps = 0;
879 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
881 if self.cur_chunk == next_idx as usize {
882 self.samples_left = cur_samps;
883 cur_samps = next_samples as usize;
884 if let Some((new_idx, new_samples)) = cmap.next() {
886 next_samples = *new_samples;
890 if csamp >= self.cur_sample {
891 self.last_offset = self.chunk_offsets[self.cur_chunk];
897 for sample_no in csamp..self.cur_chunk {
898 self.last_offset += self.get_size(sample_no) as u64;
900 self.samples_left = self.cur_sample - csamp - cur_samps;
905 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
906 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
907 self.read_root(strmgr)?;
908 validate!(self.mdat_pos > 0);
909 validate!(!self.tracks.is_empty());
910 for track in self.tracks.iter() {
911 track.fill_seek_index(seek_index);
913 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
918 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
919 if self.tracks.is_empty() {
920 return Err(DemuxerError::EOF);
922 for _ in 0..self.tracks.len() {
923 if self.cur_track >= self.tracks.len() {
926 let track = &mut self.tracks[self.cur_track];
928 let first = track.cur_sample == 0;
929 if let Some((pts, offset, size)) = track.get_next_chunk() {
930 let str = strmgr.get_stream(track.track_str_id);
931 if str.is_none() { return Err(DemuxerError::InvalidData); }
932 let stream = str.unwrap();
933 self.src.seek(SeekFrom::Start(offset))?;
934 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
935 if let Some(ref pal) = track.pal {
936 let side_data = NASideData::Palette(first, pal.clone());
937 pkt.add_side_data(side_data);
942 Err(DemuxerError::EOF)
945 fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {
946 let ret = seek_index.find_pos(time);
948 return Err(DemuxerError::SeekError);
950 let seek_info = ret.unwrap();
951 for track in self.tracks.iter_mut() {
952 track.seek(seek_info.pts);
958 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
959 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
960 fn set_options(&mut self, _options: &[NAOption]) { }
961 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
964 impl<'a> MOVDemuxer<'a> {
965 fn new(io: &'a mut ByteReader<'a>) -> Self {
971 tracks: Vec::with_capacity(2),
978 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
980 while self.src.left() != 0 {
981 let ret = read_chunk_header(&mut self.src);
982 if ret.is_err() { break; }
983 let (ctype, size) = ret.unwrap();
984 if IGNORED_CHUNKS.contains(&ctype) {
985 self.src.skip64(size)?;
988 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
990 if let Some(ref handler) = handler {
991 read_size = (handler.parse)(self, strmgr, size)?;
993 println!("skipping unknown chunk {:08X} size {}", ctype, size);
996 validate!(read_size <= size);
997 self.src.skip64(size - read_size)?;
999 //todo check if all needed chunks are found
1002 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1005 pub struct MOVDemuxerCreator { }
1007 impl DemuxerCreator for MOVDemuxerCreator {
1008 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1009 Box::new(MOVDemuxer::new(br))
1011 fn get_name(&self) -> &'static str { "mov" }
1014 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1015 0x93, 0x65, 0x5E, 0x00,
1016 0xFF, 0xFF, 0xFF, 0x00,
1017 0xDF, 0xD0, 0xAB, 0x00,
1018 0x00, 0x00, 0x00, 0x00
1020 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1021 0xFF, 0xFB, 0xFF, 0x00,
1022 0xEF, 0xD9, 0xBB, 0x00,
1023 0xE8, 0xC9, 0xB1, 0x00,
1024 0x93, 0x65, 0x5E, 0x00,
1025 0xFC, 0xDE, 0xE8, 0x00,
1026 0x9D, 0x88, 0x91, 0x00,
1027 0xFF, 0xFF, 0xFF, 0x00,
1028 0xFF, 0xFF, 0xFF, 0x00,
1029 0xFF, 0xFF, 0xFF, 0x00,
1030 0x47, 0x48, 0x37, 0x00,
1031 0x7A, 0x5E, 0x55, 0x00,
1032 0xDF, 0xD0, 0xAB, 0x00,
1033 0xFF, 0xFB, 0xF9, 0x00,
1034 0xE8, 0xCA, 0xC5, 0x00,
1035 0x8A, 0x7C, 0x77, 0x00,
1036 0x00, 0x00, 0x00, 0x00
1038 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1039 0xFF, 0xFF, 0xFF, 0x00,
1040 0xFF, 0xFF, 0xCC, 0x00,
1041 0xFF, 0xFF, 0x99, 0x00,
1042 0xFF, 0xFF, 0x66, 0x00,
1043 0xFF, 0xFF, 0x33, 0x00,
1044 0xFF, 0xFF, 0x00, 0x00,
1045 0xFF, 0xCC, 0xFF, 0x00,
1046 0xFF, 0xCC, 0xCC, 0x00,
1047 0xFF, 0xCC, 0x99, 0x00,
1048 0xFF, 0xCC, 0x66, 0x00,
1049 0xFF, 0xCC, 0x33, 0x00,
1050 0xFF, 0xCC, 0x00, 0x00,
1051 0xFF, 0x99, 0xFF, 0x00,
1052 0xFF, 0x99, 0xCC, 0x00,
1053 0xFF, 0x99, 0x99, 0x00,
1054 0xFF, 0x99, 0x66, 0x00,
1055 0xFF, 0x99, 0x33, 0x00,
1056 0xFF, 0x99, 0x00, 0x00,
1057 0xFF, 0x66, 0xFF, 0x00,
1058 0xFF, 0x66, 0xCC, 0x00,
1059 0xFF, 0x66, 0x99, 0x00,
1060 0xFF, 0x66, 0x66, 0x00,
1061 0xFF, 0x66, 0x33, 0x00,
1062 0xFF, 0x66, 0x00, 0x00,
1063 0xFF, 0x33, 0xFF, 0x00,
1064 0xFF, 0x33, 0xCC, 0x00,
1065 0xFF, 0x33, 0x99, 0x00,
1066 0xFF, 0x33, 0x66, 0x00,
1067 0xFF, 0x33, 0x33, 0x00,
1068 0xFF, 0x33, 0x00, 0x00,
1069 0xFF, 0x00, 0xFF, 0x00,
1070 0xFF, 0x00, 0xCC, 0x00,
1071 0xFF, 0x00, 0x99, 0x00,
1072 0xFF, 0x00, 0x66, 0x00,
1073 0xFF, 0x00, 0x33, 0x00,
1074 0xFF, 0x00, 0x00, 0x00,
1075 0xCC, 0xFF, 0xFF, 0x00,
1076 0xCC, 0xFF, 0xCC, 0x00,
1077 0xCC, 0xFF, 0x99, 0x00,
1078 0xCC, 0xFF, 0x66, 0x00,
1079 0xCC, 0xFF, 0x33, 0x00,
1080 0xCC, 0xFF, 0x00, 0x00,
1081 0xCC, 0xCC, 0xFF, 0x00,
1082 0xCC, 0xCC, 0xCC, 0x00,
1083 0xCC, 0xCC, 0x99, 0x00,
1084 0xCC, 0xCC, 0x66, 0x00,
1085 0xCC, 0xCC, 0x33, 0x00,
1086 0xCC, 0xCC, 0x00, 0x00,
1087 0xCC, 0x99, 0xFF, 0x00,
1088 0xCC, 0x99, 0xCC, 0x00,
1089 0xCC, 0x99, 0x99, 0x00,
1090 0xCC, 0x99, 0x66, 0x00,
1091 0xCC, 0x99, 0x33, 0x00,
1092 0xCC, 0x99, 0x00, 0x00,
1093 0xCC, 0x66, 0xFF, 0x00,
1094 0xCC, 0x66, 0xCC, 0x00,
1095 0xCC, 0x66, 0x99, 0x00,
1096 0xCC, 0x66, 0x66, 0x00,
1097 0xCC, 0x66, 0x33, 0x00,
1098 0xCC, 0x66, 0x00, 0x00,
1099 0xCC, 0x33, 0xFF, 0x00,
1100 0xCC, 0x33, 0xCC, 0x00,
1101 0xCC, 0x33, 0x99, 0x00,
1102 0xCC, 0x33, 0x66, 0x00,
1103 0xCC, 0x33, 0x33, 0x00,
1104 0xCC, 0x33, 0x00, 0x00,
1105 0xCC, 0x00, 0xFF, 0x00,
1106 0xCC, 0x00, 0xCC, 0x00,
1107 0xCC, 0x00, 0x99, 0x00,
1108 0xCC, 0x00, 0x66, 0x00,
1109 0xCC, 0x00, 0x33, 0x00,
1110 0xCC, 0x00, 0x00, 0x00,
1111 0x99, 0xFF, 0xFF, 0x00,
1112 0x99, 0xFF, 0xCC, 0x00,
1113 0x99, 0xFF, 0x99, 0x00,
1114 0x99, 0xFF, 0x66, 0x00,
1115 0x99, 0xFF, 0x33, 0x00,
1116 0x99, 0xFF, 0x00, 0x00,
1117 0x99, 0xCC, 0xFF, 0x00,
1118 0x99, 0xCC, 0xCC, 0x00,
1119 0x99, 0xCC, 0x99, 0x00,
1120 0x99, 0xCC, 0x66, 0x00,
1121 0x99, 0xCC, 0x33, 0x00,
1122 0x99, 0xCC, 0x00, 0x00,
1123 0x99, 0x99, 0xFF, 0x00,
1124 0x99, 0x99, 0xCC, 0x00,
1125 0x99, 0x99, 0x99, 0x00,
1126 0x99, 0x99, 0x66, 0x00,
1127 0x99, 0x99, 0x33, 0x00,
1128 0x99, 0x99, 0x00, 0x00,
1129 0x99, 0x66, 0xFF, 0x00,
1130 0x99, 0x66, 0xCC, 0x00,
1131 0x99, 0x66, 0x99, 0x00,
1132 0x99, 0x66, 0x66, 0x00,
1133 0x99, 0x66, 0x33, 0x00,
1134 0x99, 0x66, 0x00, 0x00,
1135 0x99, 0x33, 0xFF, 0x00,
1136 0x99, 0x33, 0xCC, 0x00,
1137 0x99, 0x33, 0x99, 0x00,
1138 0x99, 0x33, 0x66, 0x00,
1139 0x99, 0x33, 0x33, 0x00,
1140 0x99, 0x33, 0x00, 0x00,
1141 0x99, 0x00, 0xFF, 0x00,
1142 0x99, 0x00, 0xCC, 0x00,
1143 0x99, 0x00, 0x99, 0x00,
1144 0x99, 0x00, 0x66, 0x00,
1145 0x99, 0x00, 0x33, 0x00,
1146 0x99, 0x00, 0x00, 0x00,
1147 0x66, 0xFF, 0xFF, 0x00,
1148 0x66, 0xFF, 0xCC, 0x00,
1149 0x66, 0xFF, 0x99, 0x00,
1150 0x66, 0xFF, 0x66, 0x00,
1151 0x66, 0xFF, 0x33, 0x00,
1152 0x66, 0xFF, 0x00, 0x00,
1153 0x66, 0xCC, 0xFF, 0x00,
1154 0x66, 0xCC, 0xCC, 0x00,
1155 0x66, 0xCC, 0x99, 0x00,
1156 0x66, 0xCC, 0x66, 0x00,
1157 0x66, 0xCC, 0x33, 0x00,
1158 0x66, 0xCC, 0x00, 0x00,
1159 0x66, 0x99, 0xFF, 0x00,
1160 0x66, 0x99, 0xCC, 0x00,
1161 0x66, 0x99, 0x99, 0x00,
1162 0x66, 0x99, 0x66, 0x00,
1163 0x66, 0x99, 0x33, 0x00,
1164 0x66, 0x99, 0x00, 0x00,
1165 0x66, 0x66, 0xFF, 0x00,
1166 0x66, 0x66, 0xCC, 0x00,
1167 0x66, 0x66, 0x99, 0x00,
1168 0x66, 0x66, 0x66, 0x00,
1169 0x66, 0x66, 0x33, 0x00,
1170 0x66, 0x66, 0x00, 0x00,
1171 0x66, 0x33, 0xFF, 0x00,
1172 0x66, 0x33, 0xCC, 0x00,
1173 0x66, 0x33, 0x99, 0x00,
1174 0x66, 0x33, 0x66, 0x00,
1175 0x66, 0x33, 0x33, 0x00,
1176 0x66, 0x33, 0x00, 0x00,
1177 0x66, 0x00, 0xFF, 0x00,
1178 0x66, 0x00, 0xCC, 0x00,
1179 0x66, 0x00, 0x99, 0x00,
1180 0x66, 0x00, 0x66, 0x00,
1181 0x66, 0x00, 0x33, 0x00,
1182 0x66, 0x00, 0x00, 0x00,
1183 0x33, 0xFF, 0xFF, 0x00,
1184 0x33, 0xFF, 0xCC, 0x00,
1185 0x33, 0xFF, 0x99, 0x00,
1186 0x33, 0xFF, 0x66, 0x00,
1187 0x33, 0xFF, 0x33, 0x00,
1188 0x33, 0xFF, 0x00, 0x00,
1189 0x33, 0xCC, 0xFF, 0x00,
1190 0x33, 0xCC, 0xCC, 0x00,
1191 0x33, 0xCC, 0x99, 0x00,
1192 0x33, 0xCC, 0x66, 0x00,
1193 0x33, 0xCC, 0x33, 0x00,
1194 0x33, 0xCC, 0x00, 0x00,
1195 0x33, 0x99, 0xFF, 0x00,
1196 0x33, 0x99, 0xCC, 0x00,
1197 0x33, 0x99, 0x99, 0x00,
1198 0x33, 0x99, 0x66, 0x00,
1199 0x33, 0x99, 0x33, 0x00,
1200 0x33, 0x99, 0x00, 0x00,
1201 0x33, 0x66, 0xFF, 0x00,
1202 0x33, 0x66, 0xCC, 0x00,
1203 0x33, 0x66, 0x99, 0x00,
1204 0x33, 0x66, 0x66, 0x00,
1205 0x33, 0x66, 0x33, 0x00,
1206 0x33, 0x66, 0x00, 0x00,
1207 0x33, 0x33, 0xFF, 0x00,
1208 0x33, 0x33, 0xCC, 0x00,
1209 0x33, 0x33, 0x99, 0x00,
1210 0x33, 0x33, 0x66, 0x00,
1211 0x33, 0x33, 0x33, 0x00,
1212 0x33, 0x33, 0x00, 0x00,
1213 0x33, 0x00, 0xFF, 0x00,
1214 0x33, 0x00, 0xCC, 0x00,
1215 0x33, 0x00, 0x99, 0x00,
1216 0x33, 0x00, 0x66, 0x00,
1217 0x33, 0x00, 0x33, 0x00,
1218 0x33, 0x00, 0x00, 0x00,
1219 0x00, 0xFF, 0xFF, 0x00,
1220 0x00, 0xFF, 0xCC, 0x00,
1221 0x00, 0xFF, 0x99, 0x00,
1222 0x00, 0xFF, 0x66, 0x00,
1223 0x00, 0xFF, 0x33, 0x00,
1224 0x00, 0xFF, 0x00, 0x00,
1225 0x00, 0xCC, 0xFF, 0x00,
1226 0x00, 0xCC, 0xCC, 0x00,
1227 0x00, 0xCC, 0x99, 0x00,
1228 0x00, 0xCC, 0x66, 0x00,
1229 0x00, 0xCC, 0x33, 0x00,
1230 0x00, 0xCC, 0x00, 0x00,
1231 0x00, 0x99, 0xFF, 0x00,
1232 0x00, 0x99, 0xCC, 0x00,
1233 0x00, 0x99, 0x99, 0x00,
1234 0x00, 0x99, 0x66, 0x00,
1235 0x00, 0x99, 0x33, 0x00,
1236 0x00, 0x99, 0x00, 0x00,
1237 0x00, 0x66, 0xFF, 0x00,
1238 0x00, 0x66, 0xCC, 0x00,
1239 0x00, 0x66, 0x99, 0x00,
1240 0x00, 0x66, 0x66, 0x00,
1241 0x00, 0x66, 0x33, 0x00,
1242 0x00, 0x66, 0x00, 0x00,
1243 0x00, 0x33, 0xFF, 0x00,
1244 0x00, 0x33, 0xCC, 0x00,
1245 0x00, 0x33, 0x99, 0x00,
1246 0x00, 0x33, 0x66, 0x00,
1247 0x00, 0x33, 0x33, 0x00,
1248 0x00, 0x33, 0x00, 0x00,
1249 0x00, 0x00, 0xFF, 0x00,
1250 0x00, 0x00, 0xCC, 0x00,
1251 0x00, 0x00, 0x99, 0x00,
1252 0x00, 0x00, 0x66, 0x00,
1253 0x00, 0x00, 0x33, 0x00,
1254 0xEE, 0x00, 0x00, 0x00,
1255 0xDD, 0x00, 0x00, 0x00,
1256 0xBB, 0x00, 0x00, 0x00,
1257 0xAA, 0x00, 0x00, 0x00,
1258 0x88, 0x00, 0x00, 0x00,
1259 0x77, 0x00, 0x00, 0x00,
1260 0x55, 0x00, 0x00, 0x00,
1261 0x44, 0x00, 0x00, 0x00,
1262 0x22, 0x00, 0x00, 0x00,
1263 0x11, 0x00, 0x00, 0x00,
1264 0x00, 0xEE, 0x00, 0x00,
1265 0x00, 0xDD, 0x00, 0x00,
1266 0x00, 0xBB, 0x00, 0x00,
1267 0x00, 0xAA, 0x00, 0x00,
1268 0x00, 0x88, 0x00, 0x00,
1269 0x00, 0x77, 0x00, 0x00,
1270 0x00, 0x55, 0x00, 0x00,
1271 0x00, 0x44, 0x00, 0x00,
1272 0x00, 0x22, 0x00, 0x00,
1273 0x00, 0x11, 0x00, 0x00,
1274 0x00, 0x00, 0xEE, 0x00,
1275 0x00, 0x00, 0xDD, 0x00,
1276 0x00, 0x00, 0xBB, 0x00,
1277 0x00, 0x00, 0xAA, 0x00,
1278 0x00, 0x00, 0x88, 0x00,
1279 0x00, 0x00, 0x77, 0x00,
1280 0x00, 0x00, 0x55, 0x00,
1281 0x00, 0x00, 0x44, 0x00,
1282 0x00, 0x00, 0x22, 0x00,
1283 0x00, 0x00, 0x11, 0x00,
1284 0xEE, 0xEE, 0xEE, 0x00,
1285 0xDD, 0xDD, 0xDD, 0x00,
1286 0xBB, 0xBB, 0xBB, 0x00,
1287 0xAA, 0xAA, 0xAA, 0x00,
1288 0x88, 0x88, 0x88, 0x00,
1289 0x77, 0x77, 0x77, 0x00,
1290 0x55, 0x55, 0x55, 0x00,
1291 0x44, 0x44, 0x44, 0x00,
1292 0x22, 0x22, 0x22, 0x00,
1293 0x11, 0x11, 0x11, 0x00,
1294 0x00, 0x00, 0x00, 0x00
1303 fn test_mov_demux() {
1304 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1305 let mut fr = FileReader::new_read(&mut file);
1306 let mut br = ByteReader::new(&mut fr);
1307 let mut dmx = MOVDemuxer::new(&mut br);
1308 let mut sm = StreamManager::new();
1309 let mut si = SeekIndex::new();
1310 dmx.open(&mut sm, &mut si).unwrap();
1313 let pktres = dmx.get_frame(&mut sm);
1314 if let Err(e) = pktres {
1315 if e == DemuxerError::EOF { break; }
1318 let pkt = pktres.unwrap();
1319 println!("Got {}", pkt);