1 use nihav_core::demuxers::*;
2 use nihav_registry::register::*;
5 ($a:expr, $b:expr, $c:expr, $d:expr) => ({
6 (($a as u32) << 24) | (($b as u32) << 16) | (($c as u32) << 8) | ($d as u32)
9 (($arr[0] as u32) << 24) | (($arr[1] as u32) << 16) | (($arr[2] as u32) << 8) | ($arr[3] as u32)
14 fn skip64(&mut self, size: u64) -> ByteIOResult<()>;
17 impl<'a> Skip64 for ByteReader<'a> {
18 fn skip64(&mut self, size: u64) -> ByteIOResult<()> {
19 if (size as usize as u64) != size {
20 self.seek(SeekFrom::Current(size as i64))?;
22 self.read_skip(size as usize)?;
28 fn read_chunk_header(br: &mut ByteReader) -> DemuxerResult<(u32, u64)> {
29 let size = br.read_u32be()?;
30 let ctype = br.read_u32be()?;
32 Ok((ctype, br.left() as u64))
34 let size64 = br.read_u64be()?;
35 validate!(size64 >= 16);
36 Ok((ctype, size64 - 16))
39 Ok((ctype, (size as u64) - 8))
43 fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
44 let _seed = br.read_u32be()?;
45 let _flags = br.read_u16be()?;
46 let palsize = (br.read_u16be()? as usize) + 1;
47 validate!(palsize <= 256);
48 validate!((palsize as u64) * 8 + 8 == size);
50 let a = br.read_u16be()?;
51 let r = br.read_u16be()?;
52 let g = br.read_u16be()?;
53 let b = br.read_u16be()?;
54 pal[i * 4] = (r >> 8) as u8;
55 pal[i * 4 + 1] = (g >> 8) as u8;
56 pal[i * 4 + 2] = (b >> 8) as u8;
57 pal[i * 4 + 3] = (a >> 8) as u8;
62 struct RootChunkHandler {
64 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
67 struct TrackChunkHandler {
69 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
72 const IGNORED_CHUNKS: &[u32] = &[
73 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
76 const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
77 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
78 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
79 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
82 macro_rules! read_chunk_list {
83 (root; $name: expr, $fname: ident, $handlers: ident) => {
84 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
86 validate!(self.depth < 32);
87 let list_end = self.src.tell() + size;
88 while self.src.tell() < list_end {
89 let ret = read_chunk_header(&mut self.src);
90 if ret.is_err() { break; }
91 let (ctype, size) = ret.unwrap();
92 if self.src.tell() + size > list_end {
95 if IGNORED_CHUNKS.contains(&ctype) {
96 self.src.skip64(size)?;
99 let handler = $handlers.iter().find(|x| x.ctype == ctype);
101 if let Some(ref handler) = handler {
102 read_size = (handler.parse)(self, strmgr, size)?;
104 println!("skipping unknown chunk {:08X} size {}", ctype, size);
107 validate!(read_size <= size);
108 self.src.skip64(size - read_size)?;
111 validate!(self.src.tell() == list_end);
115 (track; $name: expr, $fname: ident, $handlers: ident) => {
116 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
118 validate!(self.depth < 32);
119 let list_end = br.tell() + size;
120 while br.tell() < list_end {
121 let ret = read_chunk_header(br);
122 if ret.is_err() { break; }
123 let (ctype, size) = ret.unwrap();
124 if br.tell() + size > list_end {
127 if IGNORED_CHUNKS.contains(&ctype) {
131 let handler = $handlers.iter().find(|x| x.ctype == ctype);
133 if let Some(ref handler) = handler {
134 read_size = (handler.parse)(self, br, size)?;
138 validate!(read_size <= size);
139 br.skip64(size - read_size)?;
142 validate!(br.tell() == list_end);
148 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
153 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
154 dmx.src.skip64(size)?;
158 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
159 dmx.mdat_pos = dmx.src.tell();
160 dmx.mdat_size = size;
161 dmx.src.skip64(size)?;
165 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
166 dmx.read_moov(strmgr, size)?;
170 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
171 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
172 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
173 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
174 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
177 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
178 const KNOWN_MVHD_SIZE: u64 = 100;
179 let br = &mut dmx.src;
180 validate!(size >= KNOWN_MVHD_SIZE);
181 let version = br.read_byte()?;
182 validate!(version == 0);
183 let _flags = br.read_u24be()?;
184 let _ctime = br.read_u32be()?;
185 let _mtime = br.read_u32be()?;
186 let tscale = br.read_u32be()?;
187 let duration = br.read_u32be()?;
188 let _pref_rate = br.read_u32be()?;
189 let _pref_volume = br.read_u16be()?;
191 br.read_skip(36)?; // matrix
192 let _preview_time = br.read_u32be()?;
193 let _preview_duration = br.read_u32be()?;
194 let _poster_time = br.read_u32be()?;
195 let _sel_time = br.read_u32be()?;
196 let _sel_duration = br.read_u32be()?;
197 let _cur_time = br.read_u32be()?;
198 let _next_track_id = br.read_u32be()?;
199 dmx.duration = duration;
205 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
206 let mut pal = [0; 1024];
207 let size = read_palette(&mut dmx.src, size, &mut pal)?;
208 dmx.pal = Some(Arc::new(pal));
212 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
213 dmx.src.skip64(size)?;
217 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
218 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
219 track.read_trak(&mut dmx.src, size)?;
220 validate!(track.tkhd_found && track.stsd_found);
221 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
224 std::mem::swap(&mut track.stream, &mut str);
225 if let Some(stream) = str {
226 let str_id = strmgr.add_stream(stream).unwrap();
227 track.track_str_id = str_id;
229 dmx.tracks.push(track);
233 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
234 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
235 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
236 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
237 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
238 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
239 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
240 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
241 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
244 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
245 const KNOWN_TKHD_SIZE: u64 = 84;
246 validate!(size >= KNOWN_TKHD_SIZE);
247 let version = br.read_byte()?;
248 validate!(version == 0);
249 let _flags = br.read_u24be()?;
250 let _ctime = br.read_u32be()?;
251 let _mtime = br.read_u32be()?;
252 let track_id = br.read_u32be()?;
254 let _duration = br.read_u32be()?;
256 let _layer = br.read_u16be()?;
257 let _alt_group = br.read_u16be()?;
258 let _volume = br.read_u16be()?;
260 br.read_skip(36)?; // matrix
261 let width = br.read_u32be()? as usize;
262 let height = br.read_u32be()? as usize;
263 track.width = width >> 16;
264 track.height = height >> 16;
265 track.track_id = track_id;
267 track.tkhd_found = true;
271 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
272 track.stream_type = StreamType::None;
273 track.read_mdia(br, size)?;
277 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
278 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
279 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
280 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
283 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
284 const KNOWN_HDLR_SIZE: u64 = 24;
285 validate!(size >= KNOWN_HDLR_SIZE);
286 let version = br.read_byte()?;
287 validate!(version == 0);
288 let flags = br.read_u24be()?;
289 validate!(flags == 0);
290 let comp_type = br.read_u32be()?;
291 let comp_subtype = br.read_u32be()?;
292 let _comp_manufacturer = br.read_u32be()?;
293 let _comp_flags = br.read_u32be()?;
294 let _comp_flags_mask = br.read_u32be()?;
296 if comp_type == mktag!(b"mhlr") {
297 if comp_subtype == mktag!(b"vide") {
298 track.stream_type = StreamType::Video;
299 } else if comp_subtype == mktag!(b"soun") {
300 track.stream_type = StreamType::Audio;
302 track.stream_type = StreamType::Data;
304 } else if comp_type == mktag!(b"dhlr") {
305 track.stream_type = StreamType::Data;
307 println!("Unknown stream type");
308 track.stream_type = StreamType::Data;
314 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
315 track.read_minf(br, size)?;
319 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
320 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
321 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
322 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
323 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
324 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
325 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
326 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
329 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
330 const KNOWN_VMHD_SIZE: u64 = 12;
331 validate!(track.stream_type == StreamType::Video);
332 validate!(size >= KNOWN_VMHD_SIZE);
333 let version = br.read_byte()?;
334 validate!(version == 0);
335 let _flags = br.read_u24be()?;
336 br.read_skip(2)?; // graphics mode
337 br.read_skip(6)?; // opcolor
341 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
342 const KNOWN_SMHD_SIZE: u64 = 8;
343 validate!(track.stream_type == StreamType::Audio);
344 validate!(size >= KNOWN_SMHD_SIZE);
345 let version = br.read_byte()?;
346 validate!(version == 0);
347 let _flags = br.read_u24be()?;
348 br.read_skip(2)?; // balance
353 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
354 validate!(track.stream_type == StreamType::Data);
358 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
359 validate!(track.stream_type == StreamType::Data);
360 const KNOWN_GMIN_SIZE: u64 = 16;
361 validate!(size >= KNOWN_GMIN_SIZE);
362 let version = br.read_byte()?;
363 validate!(version == 0);
364 let _flags = br.read_u24be()?;
365 br.read_skip(2)?; // graphics mode
366 br.read_skip(6)?; // opcolor
367 br.read_skip(2)?; // balance
372 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
373 track.read_stbl(br, size)?;
377 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
378 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
379 TrackChunkHandler { ctype: mktag!(b"stts"), parse: skip_chunk },
380 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
381 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
382 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
383 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
384 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
387 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
388 const KNOWN_STSD_SIZE: u64 = 24;
389 validate!(size >= KNOWN_STSD_SIZE);
390 let start_pos = br.tell();
391 let version = br.read_byte()?;
392 validate!(version == 0);
393 let _flags = br.read_u24be()?;
394 let entries = br.read_u32be()?;
395 validate!(entries > 0);
396 let esize = br.read_u32be()? as u64;
397 validate!(esize + 8 <= size);
398 let mut fcc = [0u8; 4];
399 br.read_buf(&mut fcc)?;
401 let _data_ref = br.read_u16be()?;
406 match track.stream_type {
407 StreamType::Video => {
408 let _ver = br.read_u16be()?;
409 let _revision = br.read_u16le()?;
410 let _vendor = br.read_u32be()?;
411 let _temp_quality = br.read_u32be()?;
412 let _spat_quality = br.read_u32be()?;
413 let width = br.read_u16be()? as usize;
414 let height = br.read_u16be()? as usize;
415 let _hor_res = br.read_u32be()?;
416 let _vert_res = br.read_u32be()?;
417 let data_size = br.read_u32be()?;
418 validate!(data_size == 0);
419 let _frame_count = br.read_u16be()? as usize;
420 let _cname_len = br.read_byte()? as usize;
421 br.read_skip(31)?; // actual compressor name
422 let depth = br.read_u16be()?;
423 let ctable_id = br.read_u16be()?;
424 validate!(((depth & 0x1F) <= 8) || (ctable_id == 0xFFFF));
426 let max_pal_size = start_pos + size - br.tell();
427 let mut pal = [0; 1024];
428 read_palette(br, max_pal_size, &mut pal)?;
429 track.pal = Some(Arc::new(pal));
430 } else if (depth & 0x20) == 0 && (depth & 0x1F) <= 8 {
433 let mut pal = [0; 1024];
434 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
435 track.pal = Some(Arc::new(pal));
438 let mut pal = [0; 1024];
439 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
440 track.pal = Some(Arc::new(pal));
443 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
447 } else if (depth & 0x1F) <= 8 {
448 let mut pal = [0; 1024];
449 let cdepth = depth & 0x1F;
450 let size = 1 << cdepth;
452 let mut clr = (size - 1 - i) as u8;
453 let mut off = 8 - cdepth;
454 while off >= cdepth {
455 clr |= clr >> (8 - off);
459 clr |= clr >> (8 - off);
462 pal[i * 4 + 1] = clr;
463 pal[i * 4 + 2] = clr;
465 track.pal = Some(Arc::new(pal));
467 // todo other atoms, put as extradata
468 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
470 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
475 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
476 let vhdr = NAVideoInfo::new(width, height, false, format);
478 if br.tell() - start_pos + 4 < size {
479 //todo skip various common atoms
480 let edata_size = br.read_u32be()? as usize;
481 let mut buf = vec![0; edata_size];
482 br.read_buf(buf.as_mut_slice())?;
487 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
489 StreamType::Audio => {
490 let _ver = br.read_u16be()?;
491 let _revision = br.read_u16le()?;
492 let _vendor = br.read_u32be()?;
493 let nchannels = br.read_u16be()?;
494 validate!(nchannels <= 64);
495 let sample_size = br.read_u16be()?;
496 validate!(sample_size <= 128);
497 let _compr_id = br.read_u16be()?;
498 let packet_size = br.read_u16be()? as usize;
499 validate!(packet_size == 0);
500 let sample_rate = br.read_u32be()?;
501 validate!(sample_rate > 0);
502 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
504 } 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]))) {
509 //todo adjust format for various PCM kinds
510 let soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
512 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
514 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
515 track.channels = nchannels as usize;
516 track.bits = sample_size as usize;
518 StreamType::None => {
519 return Err(DemuxerError::InvalidData);
522 //todo put it all into extradata
524 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
527 let read_size = br.tell() - start_pos;
528 validate!(read_size <= size);
529 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den));
530 track.stsd_found = true;
534 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
535 let version = br.read_byte()?;
536 validate!(version == 0);
537 let _flags = br.read_u24be()?;
538 let entries = br.read_u32be()? as usize;
539 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
540 validate!((entries * 4 + 8) as u64 == size);
541 track.keyframes = Vec::with_capacity(entries);
542 let mut last_sample_no = 0;
543 for _ in 0..entries {
544 let sample_no = br.read_u32be()?;
545 validate!(sample_no > last_sample_no);
546 track.keyframes.push(sample_no);
547 last_sample_no = sample_no;
552 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
553 let version = br.read_byte()?;
554 validate!(version == 0);
555 let _flags = br.read_u24be()?;
556 let entries = br.read_u32be()? as usize;
557 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
558 validate!((entries * 12 + 8) as u64 == size);
559 track.sample_map = Vec::with_capacity(entries);
560 let mut last_sample_no = 0;
561 for _i in 0..entries {
562 let sample_no = br.read_u32be()?;
563 validate!(sample_no > last_sample_no);
564 let nsamples = br.read_u32be()?;
565 let _sample_desc = br.read_u32be()?;
566 track.sample_map.push((sample_no, nsamples));
567 last_sample_no = sample_no;
572 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
573 let version = br.read_byte()?;
574 validate!(version == 0);
575 let _flags = br.read_u24be()?;
576 let sample_size = br.read_u32be()?;
577 if sample_size != 0 {
578 track.sample_size = sample_size;
581 let entries = br.read_u32be()? as usize;
582 validate!((entries * 4 + 12) as u64 == size);
583 track.chunk_sizes = Vec::with_capacity(entries);
584 for _ in 0..entries {
585 let sample_size = br.read_u32be()?;
586 track.chunk_sizes.push(sample_size);
592 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
593 let version = br.read_byte()?;
594 validate!(version == 0);
595 let _flags = br.read_u24be()?;
596 let entries = br.read_u32be()? as usize;
597 validate!((entries * 4 + 8) as u64 == size);
598 track.chunk_offsets = Vec::with_capacity(entries);
599 for _i in 0..entries {
600 let sample_offset = br.read_u32be()?;
601 track.chunk_offsets.push(u64::from(sample_offset));
606 struct MOVDemuxer<'a> {
607 src: &'a mut ByteReader<'a>,
615 pal: Option<Arc<[u8; 1024]>>,
626 stream_type: StreamType,
633 chunk_sizes: Vec<u32>,
634 chunk_offsets: Vec<u64>,
635 sample_map: Vec<(u32, u32)>,
637 stream: Option<NAStream>,
642 pal: Option<Arc<[u8; 1024]>>,
646 fn new(track_no: u32, tb_den: u32) -> Self {
654 stream_type: StreamType::None,
660 keyframes: Vec::new(),
661 chunk_sizes: Vec::new(),
662 chunk_offsets: Vec::new(),
663 sample_map: Vec::new(),
674 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
675 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
676 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
677 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
678 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
679 if self.keyframes.len() > 0 {
680 seek_index.mode = SeekIndexMode::Present;
682 for kf_time in self.keyframes.iter() {
683 let pts = u64::from(*kf_time - 1);
684 let time = NATimeInfo::ts_to_time(pts, 1000, 1, self.tb_den);
685 let idx = (*kf_time - 1) as usize;
686 if idx < self.chunk_offsets.len() {
687 let pos = self.chunk_offsets[idx];
688 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts, pos });
692 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
694 self.sample_size as usize
697 b"NONE" | b"raw " | b"twos" | b"sowt" => {
698 (nsamp * self.bits * self.channels + 7) >> 3
701 let nblocks = (nsamp + 63) >> 6;
702 nblocks * 34 * self.channels
705 (nsamp + 5) / 6 * 2 * self.channels
708 (nsamp + 5) / 6 * self.channels
710 b"in24" => nsamp * 3 * self.channels,
711 b"in32" | b"fl32" => nsamp * 4 * self.channels,
712 b"fl64" => nsamp * 8 * self.channels,
713 b"ulaw" | b"alaw" => nsamp,
714 b"ms\x00\x02" => { //MS ADPCM
715 ((nsamp - 1) / 2 + 7) * self.channels
717 b"ms\x00\x21" => { //IMA ADPCM
718 (nsamp / 2 + 4) * self.channels
720 _ => self.sample_size as usize,
724 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
725 let pts = NATimeInfo::new(Some(self.cur_sample as u64), None, None, 1, self.tb_den);
727 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
728 if self.cur_sample >= self.chunk_sizes.len() {
731 let offset = self.chunk_offsets[self.cur_sample];
732 let size = self.chunk_sizes[self.cur_sample] as usize;
733 self.cur_sample += 1;
734 Some((pts, offset, size))
736 if self.samples_left == 0 {
737 if self.cur_chunk >= self.chunk_offsets.len() {
740 for (idx, samples) in self.sample_map.iter() {
741 if *idx as usize <= self.cur_chunk + 1 {
742 self.samples_left = *samples as usize;
747 self.last_offset = self.chunk_offsets[self.cur_chunk];
750 let offset = self.last_offset;
751 let size = self.get_size(self.cur_sample);
752 self.last_offset += size as u64;
753 if self.stream_type == StreamType::Video {
754 self.samples_left -= 1;
756 self.samples_left = 0;
758 self.cur_sample += 1;
759 Some((pts, offset, size))
762 fn get_size(&self, sample_no: usize) -> usize {
763 if self.chunk_sizes.len() > 0 {
764 self.chunk_sizes[sample_no] as usize
765 } else if self.sample_map.len() > 0 {
767 for (idx, samples) in self.sample_map.iter() {
768 if *idx as usize <= self.cur_chunk {
774 self.calculate_chunk_size(nsamp as usize)
776 self.sample_size as usize
779 fn seek(&mut self, pts: u64) {
780 self.cur_sample = pts as usize;
781 self.samples_left = 0;
782 if self.stream_type == StreamType::Audio {
783 self.cur_chunk = self.cur_sample;
784 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && self.sample_map.len() > 0{
787 let mut cmap = self.sample_map.iter();
788 let mut cur_samps = 0;
789 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
791 if self.cur_chunk == next_idx as usize {
792 self.samples_left = cur_samps;
793 cur_samps = next_samples as usize;
794 if let Some((new_idx, new_samples)) = cmap.next() {
796 next_samples = *new_samples;
800 if csamp >= self.cur_sample {
801 self.last_offset = self.chunk_offsets[self.cur_chunk];
807 for sample_no in csamp..self.cur_chunk {
808 self.last_offset += self.get_size(sample_no) as u64;
810 self.samples_left = self.cur_sample - csamp - cur_samps;
815 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
816 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
817 self.read_root(strmgr)?;
818 validate!(self.mdat_pos > 0);
819 validate!(self.tracks.len() > 0);
820 for track in self.tracks.iter() {
821 track.fill_seek_index(seek_index);
823 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
828 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
829 if self.tracks.len() == 0 {
830 return Err(DemuxerError::EOF);
832 for _ in 0..self.tracks.len() {
833 if self.cur_track >= self.tracks.len() {
836 let track = &mut self.tracks[self.cur_track];
838 let first = track.cur_sample == 0;
839 if let Some((pts, offset, size)) = track.get_next_chunk() {
840 let str = strmgr.get_stream(track.track_str_id);
841 if str.is_none() { return Err(DemuxerError::InvalidData); }
842 let stream = str.unwrap();
843 self.src.seek(SeekFrom::Start(offset))?;
844 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
845 if let Some(ref pal) = track.pal {
846 let side_data = NASideData::Palette(first, pal.clone());
847 pkt.add_side_data(side_data);
852 return Err(DemuxerError::EOF);
855 fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {
856 let ret = seek_index.find_pos(time);
858 return Err(DemuxerError::SeekError);
860 let seek_info = ret.unwrap();
861 for track in self.tracks.iter_mut() {
862 track.seek(seek_info.pts);
868 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
869 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
870 fn set_options(&mut self, _options: &[NAOption]) { }
871 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
874 impl<'a> MOVDemuxer<'a> {
875 fn new(io: &'a mut ByteReader<'a>) -> Self {
881 tracks: Vec::with_capacity(2),
888 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
890 while self.src.left() != 0 {
891 let ret = read_chunk_header(&mut self.src);
892 if ret.is_err() { break; }
893 let (ctype, size) = ret.unwrap();
894 if IGNORED_CHUNKS.contains(&ctype) {
895 self.src.skip64(size)?;
898 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
900 if let Some(ref handler) = handler {
901 read_size = (handler.parse)(self, strmgr, size)?;
903 println!("skipping unknown chunk {:08X} size {}", ctype, size);
906 validate!(read_size <= size);
907 self.src.skip64(size - read_size)?;
909 //todo check if all needed chunks are found
912 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
915 pub struct MOVDemuxerCreator { }
917 impl DemuxerCreator for MOVDemuxerCreator {
918 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
919 Box::new(MOVDemuxer::new(br))
921 fn get_name(&self) -> &'static str { "mov" }
924 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
925 0x93, 0x65, 0x5E, 0x00,
926 0xFF, 0xFF, 0xFF, 0x00,
927 0xDF, 0xD0, 0xAB, 0x00,
928 0x00, 0x00, 0x00, 0x00
930 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
931 0xFF, 0xFB, 0xFF, 0x00,
932 0xEF, 0xD9, 0xBB, 0x00,
933 0xE8, 0xC9, 0xB1, 0x00,
934 0x93, 0x65, 0x5E, 0x00,
935 0xFC, 0xDE, 0xE8, 0x00,
936 0x9D, 0x88, 0x91, 0x00,
937 0xFF, 0xFF, 0xFF, 0x00,
938 0xFF, 0xFF, 0xFF, 0x00,
939 0xFF, 0xFF, 0xFF, 0x00,
940 0x47, 0x48, 0x37, 0x00,
941 0x7A, 0x5E, 0x55, 0x00,
942 0xDF, 0xD0, 0xAB, 0x00,
943 0xFF, 0xFB, 0xF9, 0x00,
944 0xE8, 0xCA, 0xC5, 0x00,
945 0x8A, 0x7C, 0x77, 0x00,
946 0x00, 0x00, 0x00, 0x00
948 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
949 0xFF, 0xFF, 0xFF, 0x00,
950 0xFF, 0xFF, 0xCC, 0x00,
951 0xFF, 0xFF, 0x99, 0x00,
952 0xFF, 0xFF, 0x66, 0x00,
953 0xFF, 0xFF, 0x33, 0x00,
954 0xFF, 0xFF, 0x00, 0x00,
955 0xFF, 0xCC, 0xFF, 0x00,
956 0xFF, 0xCC, 0xCC, 0x00,
957 0xFF, 0xCC, 0x99, 0x00,
958 0xFF, 0xCC, 0x66, 0x00,
959 0xFF, 0xCC, 0x33, 0x00,
960 0xFF, 0xCC, 0x00, 0x00,
961 0xFF, 0x99, 0xFF, 0x00,
962 0xFF, 0x99, 0xCC, 0x00,
963 0xFF, 0x99, 0x99, 0x00,
964 0xFF, 0x99, 0x66, 0x00,
965 0xFF, 0x99, 0x33, 0x00,
966 0xFF, 0x99, 0x00, 0x00,
967 0xFF, 0x66, 0xFF, 0x00,
968 0xFF, 0x66, 0xCC, 0x00,
969 0xFF, 0x66, 0x99, 0x00,
970 0xFF, 0x66, 0x66, 0x00,
971 0xFF, 0x66, 0x33, 0x00,
972 0xFF, 0x66, 0x00, 0x00,
973 0xFF, 0x33, 0xFF, 0x00,
974 0xFF, 0x33, 0xCC, 0x00,
975 0xFF, 0x33, 0x99, 0x00,
976 0xFF, 0x33, 0x66, 0x00,
977 0xFF, 0x33, 0x33, 0x00,
978 0xFF, 0x33, 0x00, 0x00,
979 0xFF, 0x00, 0xFF, 0x00,
980 0xFF, 0x00, 0xCC, 0x00,
981 0xFF, 0x00, 0x99, 0x00,
982 0xFF, 0x00, 0x66, 0x00,
983 0xFF, 0x00, 0x33, 0x00,
984 0xFF, 0x00, 0x00, 0x00,
985 0xCC, 0xFF, 0xFF, 0x00,
986 0xCC, 0xFF, 0xCC, 0x00,
987 0xCC, 0xFF, 0x99, 0x00,
988 0xCC, 0xFF, 0x66, 0x00,
989 0xCC, 0xFF, 0x33, 0x00,
990 0xCC, 0xFF, 0x00, 0x00,
991 0xCC, 0xCC, 0xFF, 0x00,
992 0xCC, 0xCC, 0xCC, 0x00,
993 0xCC, 0xCC, 0x99, 0x00,
994 0xCC, 0xCC, 0x66, 0x00,
995 0xCC, 0xCC, 0x33, 0x00,
996 0xCC, 0xCC, 0x00, 0x00,
997 0xCC, 0x99, 0xFF, 0x00,
998 0xCC, 0x99, 0xCC, 0x00,
999 0xCC, 0x99, 0x99, 0x00,
1000 0xCC, 0x99, 0x66, 0x00,
1001 0xCC, 0x99, 0x33, 0x00,
1002 0xCC, 0x99, 0x00, 0x00,
1003 0xCC, 0x66, 0xFF, 0x00,
1004 0xCC, 0x66, 0xCC, 0x00,
1005 0xCC, 0x66, 0x99, 0x00,
1006 0xCC, 0x66, 0x66, 0x00,
1007 0xCC, 0x66, 0x33, 0x00,
1008 0xCC, 0x66, 0x00, 0x00,
1009 0xCC, 0x33, 0xFF, 0x00,
1010 0xCC, 0x33, 0xCC, 0x00,
1011 0xCC, 0x33, 0x99, 0x00,
1012 0xCC, 0x33, 0x66, 0x00,
1013 0xCC, 0x33, 0x33, 0x00,
1014 0xCC, 0x33, 0x00, 0x00,
1015 0xCC, 0x00, 0xFF, 0x00,
1016 0xCC, 0x00, 0xCC, 0x00,
1017 0xCC, 0x00, 0x99, 0x00,
1018 0xCC, 0x00, 0x66, 0x00,
1019 0xCC, 0x00, 0x33, 0x00,
1020 0xCC, 0x00, 0x00, 0x00,
1021 0x99, 0xFF, 0xFF, 0x00,
1022 0x99, 0xFF, 0xCC, 0x00,
1023 0x99, 0xFF, 0x99, 0x00,
1024 0x99, 0xFF, 0x66, 0x00,
1025 0x99, 0xFF, 0x33, 0x00,
1026 0x99, 0xFF, 0x00, 0x00,
1027 0x99, 0xCC, 0xFF, 0x00,
1028 0x99, 0xCC, 0xCC, 0x00,
1029 0x99, 0xCC, 0x99, 0x00,
1030 0x99, 0xCC, 0x66, 0x00,
1031 0x99, 0xCC, 0x33, 0x00,
1032 0x99, 0xCC, 0x00, 0x00,
1033 0x99, 0x99, 0xFF, 0x00,
1034 0x99, 0x99, 0xCC, 0x00,
1035 0x99, 0x99, 0x99, 0x00,
1036 0x99, 0x99, 0x66, 0x00,
1037 0x99, 0x99, 0x33, 0x00,
1038 0x99, 0x99, 0x00, 0x00,
1039 0x99, 0x66, 0xFF, 0x00,
1040 0x99, 0x66, 0xCC, 0x00,
1041 0x99, 0x66, 0x99, 0x00,
1042 0x99, 0x66, 0x66, 0x00,
1043 0x99, 0x66, 0x33, 0x00,
1044 0x99, 0x66, 0x00, 0x00,
1045 0x99, 0x33, 0xFF, 0x00,
1046 0x99, 0x33, 0xCC, 0x00,
1047 0x99, 0x33, 0x99, 0x00,
1048 0x99, 0x33, 0x66, 0x00,
1049 0x99, 0x33, 0x33, 0x00,
1050 0x99, 0x33, 0x00, 0x00,
1051 0x99, 0x00, 0xFF, 0x00,
1052 0x99, 0x00, 0xCC, 0x00,
1053 0x99, 0x00, 0x99, 0x00,
1054 0x99, 0x00, 0x66, 0x00,
1055 0x99, 0x00, 0x33, 0x00,
1056 0x99, 0x00, 0x00, 0x00,
1057 0x66, 0xFF, 0xFF, 0x00,
1058 0x66, 0xFF, 0xCC, 0x00,
1059 0x66, 0xFF, 0x99, 0x00,
1060 0x66, 0xFF, 0x66, 0x00,
1061 0x66, 0xFF, 0x33, 0x00,
1062 0x66, 0xFF, 0x00, 0x00,
1063 0x66, 0xCC, 0xFF, 0x00,
1064 0x66, 0xCC, 0xCC, 0x00,
1065 0x66, 0xCC, 0x99, 0x00,
1066 0x66, 0xCC, 0x66, 0x00,
1067 0x66, 0xCC, 0x33, 0x00,
1068 0x66, 0xCC, 0x00, 0x00,
1069 0x66, 0x99, 0xFF, 0x00,
1070 0x66, 0x99, 0xCC, 0x00,
1071 0x66, 0x99, 0x99, 0x00,
1072 0x66, 0x99, 0x66, 0x00,
1073 0x66, 0x99, 0x33, 0x00,
1074 0x66, 0x99, 0x00, 0x00,
1075 0x66, 0x66, 0xFF, 0x00,
1076 0x66, 0x66, 0xCC, 0x00,
1077 0x66, 0x66, 0x99, 0x00,
1078 0x66, 0x66, 0x66, 0x00,
1079 0x66, 0x66, 0x33, 0x00,
1080 0x66, 0x66, 0x00, 0x00,
1081 0x66, 0x33, 0xFF, 0x00,
1082 0x66, 0x33, 0xCC, 0x00,
1083 0x66, 0x33, 0x99, 0x00,
1084 0x66, 0x33, 0x66, 0x00,
1085 0x66, 0x33, 0x33, 0x00,
1086 0x66, 0x33, 0x00, 0x00,
1087 0x66, 0x00, 0xFF, 0x00,
1088 0x66, 0x00, 0xCC, 0x00,
1089 0x66, 0x00, 0x99, 0x00,
1090 0x66, 0x00, 0x66, 0x00,
1091 0x66, 0x00, 0x33, 0x00,
1092 0x66, 0x00, 0x00, 0x00,
1093 0x33, 0xFF, 0xFF, 0x00,
1094 0x33, 0xFF, 0xCC, 0x00,
1095 0x33, 0xFF, 0x99, 0x00,
1096 0x33, 0xFF, 0x66, 0x00,
1097 0x33, 0xFF, 0x33, 0x00,
1098 0x33, 0xFF, 0x00, 0x00,
1099 0x33, 0xCC, 0xFF, 0x00,
1100 0x33, 0xCC, 0xCC, 0x00,
1101 0x33, 0xCC, 0x99, 0x00,
1102 0x33, 0xCC, 0x66, 0x00,
1103 0x33, 0xCC, 0x33, 0x00,
1104 0x33, 0xCC, 0x00, 0x00,
1105 0x33, 0x99, 0xFF, 0x00,
1106 0x33, 0x99, 0xCC, 0x00,
1107 0x33, 0x99, 0x99, 0x00,
1108 0x33, 0x99, 0x66, 0x00,
1109 0x33, 0x99, 0x33, 0x00,
1110 0x33, 0x99, 0x00, 0x00,
1111 0x33, 0x66, 0xFF, 0x00,
1112 0x33, 0x66, 0xCC, 0x00,
1113 0x33, 0x66, 0x99, 0x00,
1114 0x33, 0x66, 0x66, 0x00,
1115 0x33, 0x66, 0x33, 0x00,
1116 0x33, 0x66, 0x00, 0x00,
1117 0x33, 0x33, 0xFF, 0x00,
1118 0x33, 0x33, 0xCC, 0x00,
1119 0x33, 0x33, 0x99, 0x00,
1120 0x33, 0x33, 0x66, 0x00,
1121 0x33, 0x33, 0x33, 0x00,
1122 0x33, 0x33, 0x00, 0x00,
1123 0x33, 0x00, 0xFF, 0x00,
1124 0x33, 0x00, 0xCC, 0x00,
1125 0x33, 0x00, 0x99, 0x00,
1126 0x33, 0x00, 0x66, 0x00,
1127 0x33, 0x00, 0x33, 0x00,
1128 0x33, 0x00, 0x00, 0x00,
1129 0x00, 0xFF, 0xFF, 0x00,
1130 0x00, 0xFF, 0xCC, 0x00,
1131 0x00, 0xFF, 0x99, 0x00,
1132 0x00, 0xFF, 0x66, 0x00,
1133 0x00, 0xFF, 0x33, 0x00,
1134 0x00, 0xFF, 0x00, 0x00,
1135 0x00, 0xCC, 0xFF, 0x00,
1136 0x00, 0xCC, 0xCC, 0x00,
1137 0x00, 0xCC, 0x99, 0x00,
1138 0x00, 0xCC, 0x66, 0x00,
1139 0x00, 0xCC, 0x33, 0x00,
1140 0x00, 0xCC, 0x00, 0x00,
1141 0x00, 0x99, 0xFF, 0x00,
1142 0x00, 0x99, 0xCC, 0x00,
1143 0x00, 0x99, 0x99, 0x00,
1144 0x00, 0x99, 0x66, 0x00,
1145 0x00, 0x99, 0x33, 0x00,
1146 0x00, 0x99, 0x00, 0x00,
1147 0x00, 0x66, 0xFF, 0x00,
1148 0x00, 0x66, 0xCC, 0x00,
1149 0x00, 0x66, 0x99, 0x00,
1150 0x00, 0x66, 0x66, 0x00,
1151 0x00, 0x66, 0x33, 0x00,
1152 0x00, 0x66, 0x00, 0x00,
1153 0x00, 0x33, 0xFF, 0x00,
1154 0x00, 0x33, 0xCC, 0x00,
1155 0x00, 0x33, 0x99, 0x00,
1156 0x00, 0x33, 0x66, 0x00,
1157 0x00, 0x33, 0x33, 0x00,
1158 0x00, 0x33, 0x00, 0x00,
1159 0x00, 0x00, 0xFF, 0x00,
1160 0x00, 0x00, 0xCC, 0x00,
1161 0x00, 0x00, 0x99, 0x00,
1162 0x00, 0x00, 0x66, 0x00,
1163 0x00, 0x00, 0x33, 0x00,
1164 0xEE, 0x00, 0x00, 0x00,
1165 0xDD, 0x00, 0x00, 0x00,
1166 0xBB, 0x00, 0x00, 0x00,
1167 0xAA, 0x00, 0x00, 0x00,
1168 0x88, 0x00, 0x00, 0x00,
1169 0x77, 0x00, 0x00, 0x00,
1170 0x55, 0x00, 0x00, 0x00,
1171 0x44, 0x00, 0x00, 0x00,
1172 0x22, 0x00, 0x00, 0x00,
1173 0x11, 0x00, 0x00, 0x00,
1174 0x00, 0xEE, 0x00, 0x00,
1175 0x00, 0xDD, 0x00, 0x00,
1176 0x00, 0xBB, 0x00, 0x00,
1177 0x00, 0xAA, 0x00, 0x00,
1178 0x00, 0x88, 0x00, 0x00,
1179 0x00, 0x77, 0x00, 0x00,
1180 0x00, 0x55, 0x00, 0x00,
1181 0x00, 0x44, 0x00, 0x00,
1182 0x00, 0x22, 0x00, 0x00,
1183 0x00, 0x11, 0x00, 0x00,
1184 0x00, 0x00, 0xEE, 0x00,
1185 0x00, 0x00, 0xDD, 0x00,
1186 0x00, 0x00, 0xBB, 0x00,
1187 0x00, 0x00, 0xAA, 0x00,
1188 0x00, 0x00, 0x88, 0x00,
1189 0x00, 0x00, 0x77, 0x00,
1190 0x00, 0x00, 0x55, 0x00,
1191 0x00, 0x00, 0x44, 0x00,
1192 0x00, 0x00, 0x22, 0x00,
1193 0x00, 0x00, 0x11, 0x00,
1194 0xEE, 0xEE, 0xEE, 0x00,
1195 0xDD, 0xDD, 0xDD, 0x00,
1196 0xBB, 0xBB, 0xBB, 0x00,
1197 0xAA, 0xAA, 0xAA, 0x00,
1198 0x88, 0x88, 0x88, 0x00,
1199 0x77, 0x77, 0x77, 0x00,
1200 0x55, 0x55, 0x55, 0x00,
1201 0x44, 0x44, 0x44, 0x00,
1202 0x22, 0x22, 0x22, 0x00,
1203 0x11, 0x11, 0x11, 0x00,
1204 0x00, 0x00, 0x00, 0x00
1213 fn test_mov_demux() {
1214 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1215 let mut fr = FileReader::new_read(&mut file);
1216 let mut br = ByteReader::new(&mut fr);
1217 let mut dmx = MOVDemuxer::new(&mut br);
1218 let mut sm = StreamManager::new();
1219 let mut si = SeekIndex::new();
1220 dmx.open(&mut sm, &mut si).unwrap();
1223 let pktres = dmx.get_frame(&mut sm);
1224 if let Err(e) = pktres {
1225 if e == DemuxerError::EOF { break; }
1228 let pkt = pktres.unwrap();
1229 println!("Got {}", pkt);