mov: add support for MacBinary format
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
CommitLineData
58309c73
KS
1use nihav_core::demuxers::*;
2use nihav_registry::register::*;
fbf1f900 3use nihav_core::compr::deflate::*;
58309c73
KS
4
5macro_rules! mktag {
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)
8 });
9 ($arr:expr) => ({
10 (($arr[0] as u32) << 24) | (($arr[1] as u32) << 16) | (($arr[2] as u32) << 8) | ($arr[3] as u32)
11 });
12}
13
14trait Skip64 {
15 fn skip64(&mut self, size: u64) -> ByteIOResult<()>;
16}
17
18impl<'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))?;
22 } else {
23 self.read_skip(size as usize)?;
24 }
25 Ok(())
26 }
27}
28
29fn read_chunk_header(br: &mut ByteReader) -> DemuxerResult<(u32, u64)> {
30 let size = br.read_u32be()?;
31 let ctype = br.read_u32be()?;
32 if size == 0 {
33 Ok((ctype, br.left() as u64))
34 } else if size == 1 {
35 let size64 = br.read_u64be()?;
36 validate!(size64 >= 16);
37 Ok((ctype, size64 - 16))
38 } else {
39 validate!(size >= 8);
40 Ok((ctype, (size as u64) - 8))
41 }
42}
43
58cd51fa 44fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
00333698 45 let _seed = br.read_u32be()?;
0ad1f05e 46 let flags = br.read_u16be()?;
00333698
KS
47 let palsize = (br.read_u16be()? as usize) + 1;
48 validate!(palsize <= 256);
0ad1f05e
KS
49 validate!(flags == 0 || flags == 0x4000 || flags == 0x8000);
50 validate!((palsize as u64) * 8 + 8 <= size);
00333698
KS
51 for i in 0..palsize {
52 let a = br.read_u16be()?;
53 let r = br.read_u16be()?;
54 let g = br.read_u16be()?;
55 let b = br.read_u16be()?;
58cd51fa
KS
56 pal[i * 4] = (r >> 8) as u8;
57 pal[i * 4 + 1] = (g >> 8) as u8;
58 pal[i * 4 + 2] = (b >> 8) as u8;
0ad1f05e
KS
59 if flags == 0x8000 {
60 pal[i * 4 + 3] = (a >> 8) as u8;
61 }
62 }
63 if flags == 0x4000 {
64 br.read_skip(8)?;
00333698
KS
65 }
66 Ok(size)
67}
68
58309c73
KS
69struct RootChunkHandler {
70 ctype: u32,
71 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
72}
73
74struct TrackChunkHandler {
75 ctype: u32,
76 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
77}
78
79const IGNORED_CHUNKS: &[u32] = &[
80 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
81];
82
83const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
7e19285f 84 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
58309c73
KS
85 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
86 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
0a0456a8
KS
87 RootChunkHandler { ctype: mktag!(b"moof"), parse: read_moof },
88 RootChunkHandler { ctype: mktag!(b"sidx"), parse: read_sidx },
58309c73
KS
89];
90
650d7bfb
KS
91fn print_cname(ctype: u32, size: u64, off: u64, depth: u8) {
92 for _ in 0..depth { print!(" "); }
93 let tag = [(ctype >> 24) as u8, (ctype >> 16) as u8, (ctype >> 8) as u8, ctype as u8];
94 let mut printable = true;
6f263099
KS
95 for ch in tag.iter() {
96 if !(0x20..=0x7F).contains(ch) {
650d7bfb
KS
97 printable = false;
98 break;
99 }
100 }
101 if printable {
102 print!(" '{}{}{}{}'", tag[0] as char, tag[1] as char, tag[2] as char, tag[3] as char);
103 } else {
104 print!(" {:08X}", ctype);
105 }
106 println!(" size {} @ {:X}", size, off);
107}
108
58309c73
KS
109macro_rules! read_chunk_list {
110 (root; $name: expr, $fname: ident, $handlers: ident) => {
111 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
112 self.depth += 1;
113 validate!(self.depth < 32);
114 let list_end = self.src.tell() + size;
115 while self.src.tell() < list_end {
6f263099 116 let ret = read_chunk_header(self.src);
58309c73
KS
117 if ret.is_err() { break; }
118 let (ctype, size) = ret.unwrap();
650d7bfb
KS
119 if self.print_chunks {
120 print_cname(ctype, size, self.src.tell(), self.depth as u8);
121 }
58309c73
KS
122 if self.src.tell() + size > list_end {
123 break;
124 }
125 if IGNORED_CHUNKS.contains(&ctype) {
126 self.src.skip64(size)?;
127 continue;
128 }
129 let handler = $handlers.iter().find(|x| x.ctype == ctype);
130 let read_size;
131 if let Some(ref handler) = handler {
132 read_size = (handler.parse)(self, strmgr, size)?;
133 } else {
134 println!("skipping unknown chunk {:08X} size {}", ctype, size);
135 read_size = 0;
136 }
137 validate!(read_size <= size);
138 self.src.skip64(size - read_size)?;
139 }
140 self.depth -= 1;
141 validate!(self.src.tell() == list_end);
142 Ok(())
143 }
144 };
145 (track; $name: expr, $fname: ident, $handlers: ident) => {
146 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
147 self.depth += 1;
148 validate!(self.depth < 32);
149 let list_end = br.tell() + size;
150 while br.tell() < list_end {
151 let ret = read_chunk_header(br);
152 if ret.is_err() { break; }
153 let (ctype, size) = ret.unwrap();
650d7bfb
KS
154 if self.print_chunks {
155 print_cname(ctype, size, br.tell(), self.depth + 1);
156 }
58309c73
KS
157 if br.tell() + size > list_end {
158 break;
159 }
160 if IGNORED_CHUNKS.contains(&ctype) {
161 br.skip64(size)?;
162 continue;
163 }
164 let handler = $handlers.iter().find(|x| x.ctype == ctype);
165 let read_size;
166 if let Some(ref handler) = handler {
167 read_size = (handler.parse)(self, br, size)?;
168 } else {
169 read_size = 0;
170 }
171 validate!(read_size <= size);
172 br.skip64(size - read_size)?;
173 }
174 self.depth -= 1;
175 validate!(br.tell() == list_end);
176 Ok(())
177 }
178 }
179}
180
181fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
182 br.skip64(size)?;
183 Ok(size)
184}
185
7e19285f
KS
186fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
187 dmx.src.skip64(size)?;
188 Ok(size)
189}
190
58309c73
KS
191fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
192 dmx.mdat_pos = dmx.src.tell();
193 dmx.mdat_size = size;
194 dmx.src.skip64(size)?;
195 Ok(size)
196}
197
0a0456a8
KS
198fn read_sidx(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
199 Ok(0)
200}
201
58309c73
KS
202fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
203 dmx.read_moov(strmgr, size)?;
204 Ok(size)
205}
206
207const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
208 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
fbf1f900 209 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
00333698 210 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
58309c73 211 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
7e19285f 212 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
0a0456a8 213 RootChunkHandler { ctype: mktag!(b"mvex"), parse: read_mvex },
554caf5d 214 RootChunkHandler { ctype: mktag!(b"iods"), parse: skip_chunk_mov },
58309c73
KS
215];
216
217fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
218 const KNOWN_MVHD_SIZE: u64 = 100;
219 let br = &mut dmx.src;
220 validate!(size >= KNOWN_MVHD_SIZE);
221 let version = br.read_byte()?;
222 validate!(version == 0);
223 let _flags = br.read_u24be()?;
224 let _ctime = br.read_u32be()?;
225 let _mtime = br.read_u32be()?;
226 let tscale = br.read_u32be()?;
227 let duration = br.read_u32be()?;
228 let _pref_rate = br.read_u32be()?;
229 let _pref_volume = br.read_u16be()?;
230 br.read_skip(10)?;
231 br.read_skip(36)?; // matrix
232 let _preview_time = br.read_u32be()?;
233 let _preview_duration = br.read_u32be()?;
234 let _poster_time = br.read_u32be()?;
235 let _sel_time = br.read_u32be()?;
236 let _sel_duration = br.read_u32be()?;
237 let _cur_time = br.read_u32be()?;
238 let _next_track_id = br.read_u32be()?;
239 dmx.duration = duration;
240 dmx.tb_den = tscale;
241
242 Ok(KNOWN_MVHD_SIZE)
243}
244
fbf1f900
KS
245fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
246 let br = &mut dmx.src;
247 validate!(size > 24);
248 let dcom_size = br.read_u32be()?;
249 let dcom_tag = br.read_tag()?;
250 let compr_type = br.read_tag()?;
251 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
252 if &compr_type != b"zlib" {
253 return Err(DemuxerError::NotImplemented);
254 }
255 let cmvd_size = u64::from(br.read_u32be()?);
256 let cmvd_tag = br.read_tag()?;
257 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
258 let comp_size = (cmvd_size - 12) as usize;
259 let uncomp_size = br.read_u32be()? as usize;
260 validate!(uncomp_size > 8);
261 let mut sbuf = vec![0; comp_size];
262 let mut dbuf = vec![0; uncomp_size];
263 br.read_buf(sbuf.as_mut_slice())?;
61a228ff 264 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
fbf1f900
KS
265 if ret.is_err() {
266 return Err(DemuxerError::InvalidData);
267 }
268 let len = ret.unwrap();
269 validate!(len == uncomp_size);
270 let mut mr = MemoryReader::new_read(dbuf.as_slice());
271 let mut br = ByteReader::new(&mut mr);
272 let (ctype, csize) = read_chunk_header(&mut br)?;
273 validate!(ctype == mktag!(b"moov"));
274 let mut ddmx = MOVDemuxer::new(&mut br);
650d7bfb 275 ddmx.print_chunks = dmx.print_chunks;
fbf1f900
KS
276 ddmx.read_moov(strmgr, csize)?;
277 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
278 dmx.duration = ddmx.duration;
279 dmx.tb_den = ddmx.tb_den;
280 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
237cc1f9 281
fbf1f900
KS
282 Ok(size)
283}
284
00333698 285fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
58cd51fa 286 let mut pal = [0; 1024];
6f263099 287 let size = read_palette(dmx.src, size, &mut pal)?;
58cd51fa
KS
288 dmx.pal = Some(Arc::new(pal));
289 Ok(size)
00333698
KS
290}
291
7e19285f
KS
292fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
293 dmx.src.skip64(size)?;
294 Ok(size)
295}
296
0a0456a8
KS
297fn read_mvex(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
298 Ok(0)
299}
300
554caf5d
KS
301fn skip_chunk_mov(_dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, _size: u64) -> DemuxerResult<u64> {
302 Ok(0)
303}
304
58309c73
KS
305fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
306 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
650d7bfb 307 track.print_chunks = dmx.print_chunks;
6f263099 308 track.read_trak(dmx.src, size)?;
58309c73
KS
309 validate!(track.tkhd_found && track.stsd_found);
310 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
311 dmx.cur_track += 1;
58309c73
KS
312 dmx.tracks.push(track);
313 Ok(size)
314}
315
0a0456a8
KS
316fn read_moof(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
317 dmx.moof_off = dmx.src.tell() - 8;
318 dmx.read_moof(strmgr, size)?;
319 Ok(size)
320}
321
322const MOOF_CHUNK_HANDLERS: &[RootChunkHandler] = &[
323 RootChunkHandler { ctype: mktag!(b"mfhd"), parse: read_mfhd },
324 RootChunkHandler { ctype: mktag!(b"traf"), parse: read_traf },
325 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
326];
327
328fn read_mfhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
329 const KNOWN_MFHD_SIZE: u64 = 8;
330 validate!(size >= KNOWN_MFHD_SIZE);
331 let version = dmx.src.read_byte()?;
332 validate!(version == 0);
333 let flags = dmx.src.read_u24be()?;
334 validate!(flags == 0);
335 let _seq_no = dmx.src.read_u32be()?;
336
337 Ok(KNOWN_MFHD_SIZE)
338}
339
340fn read_traf(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
341 let mut buf = [0u8; 16];
342 dmx.src.peek_buf(&mut buf)?;
343 validate!(&buf[4..8] == b"tfhd");
344 let track_id = read_u32be(&buf[12..16])?;
345 let mut track = None;
346 for trk in dmx.tracks.iter_mut() {
347 if trk.track_id == track_id {
348 track = Some(trk);
349 break;
350 }
351 }
352 if let Some(track) = track {
353 track.moof_off = dmx.moof_off;
6f263099 354 track.read_traf(dmx.src, size)?;
0a0456a8
KS
355 Ok(size)
356 } else {
357 Ok(0)
358 }
359}
360
58309c73
KS
361const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
362 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
364 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
365 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
366 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
367 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
368 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
369 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
370];
371
372fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
373 const KNOWN_TKHD_SIZE: u64 = 84;
374 validate!(size >= KNOWN_TKHD_SIZE);
375 let version = br.read_byte()?;
376 validate!(version == 0);
377 let _flags = br.read_u24be()?;
378 let _ctime = br.read_u32be()?;
379 let _mtime = br.read_u32be()?;
380 let track_id = br.read_u32be()?;
381 br.read_skip(4)?;
a480a0de 382 let duration = br.read_u32be()?;
58309c73
KS
383 br.read_skip(8)?;
384 let _layer = br.read_u16be()?;
385 let _alt_group = br.read_u16be()?;
386 let _volume = br.read_u16be()?;
387 br.read_skip(2)?;
388 br.read_skip(36)?; // matrix
389 let width = br.read_u32be()? as usize;
390 let height = br.read_u32be()? as usize;
391 track.width = width >> 16;
392 track.height = height >> 16;
393 track.track_id = track_id;
a480a0de 394 track.duration = duration;
58309c73
KS
395
396 track.tkhd_found = true;
397 Ok(KNOWN_TKHD_SIZE)
398}
399
400fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 track.stream_type = StreamType::None;
402 track.read_mdia(br, size)?;
403 Ok(size)
404}
405
406const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
079fff1d 407 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: read_mdhd },
58309c73
KS
408 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
409 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
410];
411
079fff1d
KS
412fn read_mdhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
413 const KNOWN_MDHD_SIZE: u64 = 24;
414 validate!(size >= KNOWN_MDHD_SIZE);
415 let version = br.read_byte()?;
416 validate!(version == 0);
417 let flags = br.read_u24be()?;
418 validate!(flags == 0);
419 let _ctime = br.read_u32be()?;
420 let _mtime = br.read_u32be()?;
421 track.tb_den = br.read_u32be()?;
422 validate!(track.tb_den != 0);
423 track.duration = br.read_u32be()?;
424 let _language = br.read_u16be()?;
425 let _quality = br.read_u16be()?;
426
427 Ok(KNOWN_MDHD_SIZE)
428}
429
58309c73
KS
430fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
431 const KNOWN_HDLR_SIZE: u64 = 24;
432 validate!(size >= KNOWN_HDLR_SIZE);
433 let version = br.read_byte()?;
434 validate!(version == 0);
435 let flags = br.read_u24be()?;
436 validate!(flags == 0);
437 let comp_type = br.read_u32be()?;
438 let comp_subtype = br.read_u32be()?;
439 let _comp_manufacturer = br.read_u32be()?;
440 let _comp_flags = br.read_u32be()?;
441 let _comp_flags_mask = br.read_u32be()?;
442
d4809976 443 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
58309c73
KS
444 if comp_subtype == mktag!(b"vide") {
445 track.stream_type = StreamType::Video;
446 } else if comp_subtype == mktag!(b"soun") {
447 track.stream_type = StreamType::Audio;
448 } else {
449 track.stream_type = StreamType::Data;
450 }
451 } else if comp_type == mktag!(b"dhlr") {
452 track.stream_type = StreamType::Data;
453 } else {
454 println!("Unknown stream type");
455 track.stream_type = StreamType::Data;
456 }
c8db9313 457
58309c73
KS
458 Ok(KNOWN_HDLR_SIZE)
459}
460
461fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
462 track.read_minf(br, size)?;
463 Ok(size)
464}
465
466const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
467 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
468 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
469 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
470 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
471 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
472 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
473 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
474];
475
476fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
477 const KNOWN_VMHD_SIZE: u64 = 12;
478 validate!(track.stream_type == StreamType::Video);
479 validate!(size >= KNOWN_VMHD_SIZE);
480 let version = br.read_byte()?;
481 validate!(version == 0);
482 let _flags = br.read_u24be()?;
483 br.read_skip(2)?; // graphics mode
484 br.read_skip(6)?; // opcolor
485 Ok(KNOWN_VMHD_SIZE)
486}
487
488fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
489 const KNOWN_SMHD_SIZE: u64 = 8;
490 validate!(track.stream_type == StreamType::Audio);
491 validate!(size >= KNOWN_SMHD_SIZE);
492 let version = br.read_byte()?;
493 validate!(version == 0);
494 let _flags = br.read_u24be()?;
495 br.read_skip(2)?; // balance
496 br.read_skip(2)?;
497 Ok(KNOWN_SMHD_SIZE)
498}
499
500fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
501 validate!(track.stream_type == StreamType::Data);
502 Ok(0)
503}
504
505fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
506 validate!(track.stream_type == StreamType::Data);
507 const KNOWN_GMIN_SIZE: u64 = 16;
508 validate!(size >= KNOWN_GMIN_SIZE);
509 let version = br.read_byte()?;
510 validate!(version == 0);
511 let _flags = br.read_u24be()?;
512 br.read_skip(2)?; // graphics mode
513 br.read_skip(6)?; // opcolor
514 br.read_skip(2)?; // balance
515 br.read_skip(2)?;
516 Ok(KNOWN_GMIN_SIZE)
517}
518
519fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
520 track.read_stbl(br, size)?;
521 Ok(size)
522}
523
524const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
525 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
bbbf86dd 526 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
58309c73
KS
527 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
528 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
529 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
530 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
531 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
4e7deeda 532 TrackChunkHandler { ctype: mktag!(b"ctts"), parse: read_ctts },
58309c73
KS
533];
534
89b16ac8
KS
535fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
536 let read_part = br.tell() - start_pos;
537 if read_part + 8 < size {
9aa783a0
KS
538 let mut buf = [0; 8];
539 br.peek_buf(&mut buf)?;
540 if &buf[4..8] != b"wave" {
541 let mut buf = vec![0; (size - read_part) as usize];
542 br.read_buf(&mut buf)?;
543 return Ok(Some(buf));
544 }
545
89b16ac8
KS
546 let csize = br.read_u32be()? as u64;
547 let ctag = br.read_u32be()?;
548 validate!(read_part + csize <= size);
549 validate!(ctag == mktag!(b"wave"));
550 if csize == 8 {
551 return Ok(None);
552 }
553 let mut buf = [0; 8];
554 br.peek_buf(&mut buf)?;
555 if &buf[4..8] == b"frma" {
556 br.read_skip(12)?;
557 if csize > 20 {
558 let mut buf = vec![0; (csize - 20) as usize];
559 br.read_buf(&mut buf)?;
560 Ok(Some(buf))
561 } else {
562 Ok(None)
563 }
564 } else if csize > 8 {
565 let mut buf = vec![0; (csize as usize) - 8];
566 br.read_buf(&mut buf)?;
567 Ok(Some(buf))
568 } else {
569 Ok(None)
570 }
571 } else {
572 Ok(None)
573 }
574}
575
58309c73
KS
576fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
577 const KNOWN_STSD_SIZE: u64 = 24;
578 validate!(size >= KNOWN_STSD_SIZE);
579 let start_pos = br.tell();
580 let version = br.read_byte()?;
581 validate!(version == 0);
582 let _flags = br.read_u24be()?;
583 let entries = br.read_u32be()?;
584 validate!(entries > 0);
61cab15b 585 let esize = u64::from(br.read_u32be()?);
58309c73
KS
586 validate!(esize + 8 <= size);
587 let mut fcc = [0u8; 4];
588 br.read_buf(&mut fcc)?;
589 br.read_skip(6)?;
590 let _data_ref = br.read_u16be()?;
591
592 track.fcc = fcc;
593
594 let codec_info;
595 match track.stream_type {
596 StreamType::Video => {
597 let _ver = br.read_u16be()?;
598 let _revision = br.read_u16le()?;
599 let _vendor = br.read_u32be()?;
600 let _temp_quality = br.read_u32be()?;
601 let _spat_quality = br.read_u32be()?;
602 let width = br.read_u16be()? as usize;
603 let height = br.read_u16be()? as usize;
604 let _hor_res = br.read_u32be()?;
605 let _vert_res = br.read_u32be()?;
606 let data_size = br.read_u32be()?;
607 validate!(data_size == 0);
608 let _frame_count = br.read_u16be()? as usize;
609 let _cname_len = br.read_byte()? as usize;
610 br.read_skip(31)?; // actual compressor name
611 let depth = br.read_u16be()?;
612 let ctable_id = br.read_u16be()?;
8019c866
KS
613 let grayscale = depth > 0x20 || depth == 1;
614 let depth = if grayscale { depth & 0x1F } else { depth };
58309c73 615 if ctable_id == 0 {
00333698 616 let max_pal_size = start_pos + size - br.tell();
88fd1059
KS
617 if depth <= 8 {
618 let mut pal = [0; 1024];
619 read_palette(br, max_pal_size, &mut pal)?;
620 track.pal = Some(Arc::new(pal));
621 } else {
622 br.read_skip(max_pal_size as usize)?;
623 }
8019c866 624 } else if (depth <= 8) && !grayscale {
2736c15a
KS
625 match depth & 0x1F {
626 2 => {
627 let mut pal = [0; 1024];
628 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
629 track.pal = Some(Arc::new(pal));
630 },
631 4 => {
632 let mut pal = [0; 1024];
633 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
634 track.pal = Some(Arc::new(pal));
635 },
636 8 => {
637 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
638 },
639 _ => {},
640 };
2949bcfa 641 } else if grayscale && ctable_id != 0xFFFF {
2736c15a
KS
642 let mut pal = [0; 1024];
643 let cdepth = depth & 0x1F;
644 let size = 1 << cdepth;
645 for i in 0..size {
8019c866 646 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
2736c15a
KS
647 let mut off = 8 - cdepth;
648 while off >= cdepth {
649 clr |= clr >> (8 - off);
650 off -= cdepth;
651 }
652 if off > 0 {
653 clr |= clr >> (8 - off);
654 }
655 pal[i * 4] = clr;
656 pal[i * 4 + 1] = clr;
657 pal[i * 4 + 2] = clr;
658 }
659 track.pal = Some(Arc::new(pal));
58309c73
KS
660 }
661// todo other atoms, put as extradata
662 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
663 name
664 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
665 name
666 } else {
667 "unknown"
668 };
669 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
8019c866
KS
670 let mut vhdr = NAVideoInfo::new(width, height, false, format);
671 vhdr.bits = depth as u8;
b9862e98
KS
672 //skip various common atoms
673 while br.tell() - start_pos + 4 < size {
674 let mut buf = [0u8; 8];
675 br.peek_buf(&mut buf)?;
676 let tsize = read_u32be(&buf).unwrap() as usize;
677 let tag = &buf[4..8];
678 validate!(tsize >= 8);
679 match tag {
680 b"pasp" | b"clap" => {
681 br.read_skip(tsize)?;
682 },
683 _ => break,
684 };
685 }
61cab15b 686 let edata = if br.tell() - start_pos + 4 < size {
61cab15b 687 let edata_size = br.read_u32be()? as usize;
d341f57a
KS
688 validate!(edata_size >= 4);
689 let mut buf = vec![0; edata_size - 4];
58309c73 690 br.read_buf(buf.as_mut_slice())?;
61cab15b
KS
691 Some(buf)
692 } else {
693 None
694 };
58309c73
KS
695 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
696 },
697 StreamType::Audio => {
89b16ac8 698 let sver = br.read_u16be()?;
58309c73
KS
699 let _revision = br.read_u16le()?;
700 let _vendor = br.read_u32be()?;
9559c2c8
KS
701 let mut nchannels = br.read_u16be()?;
702 if sver != 2 {
703 validate!(nchannels <= 64);
704 }
58309c73
KS
705 let sample_size = br.read_u16be()?;
706 validate!(sample_size <= 128);
707 let _compr_id = br.read_u16be()?;
708 let packet_size = br.read_u16be()? as usize;
709 validate!(packet_size == 0);
9559c2c8
KS
710 let mut sample_rate = br.read_u32be()? >> 16;
711 if sver != 2 {
712 validate!(sample_rate > 0);
713 }
58309c73
KS
714 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
715 name
716 } else if let (true, Some(name)) = ((fcc[0] == b'm' && fcc[1] == b's'), find_codec_from_wav_twocc(u16::from(fcc[2]) * 256 + u16::from(fcc[3]))) {
717 name
718 } else {
719 "unknown"
720 };
e5d3fef5
KS
721 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
722 if &fcc == b"raw " && sample_size == 8 {
723 soniton.signed = false;
724 }
58309c73 725 let block_align = 1;
9559c2c8
KS
726 match sver {
727 1 => {
728 let samples_per_packet = br.read_u32be()?;
729 let _bytes_per_packet = br.read_u32be()?;
730 let bytes_per_frame = br.read_u32be()?;
731 let _bytes_per_sample = br.read_u32be()?;
732 track.bsize = bytes_per_frame as usize;
733 track.frame_samples = samples_per_packet as usize;
734 track.tb_num = samples_per_packet;
735 },
736 2 => {
737 br.read_u32be()?; // some size
738 let srate = br.read_f64be()?;
739 validate!(srate > 1.0);
740 sample_rate = srate as u32;
741 let channels = br.read_u32be()?;
742 validate!(channels > 0 && channels < 255);
743 nchannels = channels as u16;
744 br.read_u32be()?; // always 0x7F000000
745 let _bits_per_csample = br.read_u32be()?;
746 let _codec_flags = br.read_u32be()?;
747 let bytes_per_frame = br.read_u32be()?;
748 let samples_per_packet = br.read_u32be()?;
749 track.bsize = bytes_per_frame as usize;
750 track.frame_samples = samples_per_packet as usize;
751 track.tb_num = samples_per_packet;
752 },
753 _ => {
754 track.bsize = (sample_size / 8) as usize;
755 },
756 };
757 track.tb_den = sample_rate;
6f263099 758 track.raw_audio = matches!(&fcc,
7afec34d
KS
759 b"NONE" | b"raw " | b"twos" | b"sowt" |
760 b"in24" | b"in32" | b"fl32" | b"fl64" |
761 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
762 b"alaw" | b"ulaw" |
6f263099 763 b"MAC3" | b"MAC6");
9559c2c8 764 let ahdr = NAAudioInfo::new(sample_rate, nchannels as u8, soniton, block_align);
89b16ac8 765 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
766 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
767 track.channels = nchannels as usize;
768 track.bits = sample_size as usize;
769 },
770 StreamType::None => {
771 return Err(DemuxerError::InvalidData);
772 },
773 _ => {
774//todo put it all into extradata
775 let edata = None;
776 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
777 },
778 };
779 let read_size = br.tell() - start_pos;
780 validate!(read_size <= size);
7afec34d 781 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
58309c73
KS
782 track.stsd_found = true;
783 Ok(read_size)
784}
785
bbbf86dd 786fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
d4809976 787 validate!(size >= 8);
bbbf86dd
KS
788 let start_pos = br.tell();
789 let version = br.read_byte()?;
790 validate!(version == 0);
791 let _flags = br.read_u24be()?;
792 let entries = br.read_u32be()? as usize;
793 validate!(entries as u64 <= (size - 8) / 8);
d4809976
KS
794 if entries == 0 {
795 } else if entries == 1 {
bbbf86dd
KS
796 let _count = br.read_u32be()?;
797 let tb_num = br.read_u32be()?;
4e7deeda 798 validate!(tb_num != 0);
0a0456a8 799 track.rescale(tb_num);
bbbf86dd 800 } else {
37952415 801 track.time_to_sample.clear();
bbbf86dd
KS
802 track.time_to_sample.reserve(entries);
803 for _ in 0..entries {
804 let count = br.read_u32be()?;
805 let mult = br.read_u32be()?;
806 track.time_to_sample.push((count, mult));
807 }
808 }
809 let read_size = br.tell() - start_pos;
810 validate!(read_size <= size);
811 Ok(read_size)
812}
813
58309c73
KS
814fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
815 let version = br.read_byte()?;
816 validate!(version == 0);
817 let _flags = br.read_u24be()?;
818 let entries = br.read_u32be()? as usize;
819 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
820 validate!((entries * 4 + 8) as u64 == size);
821 track.keyframes = Vec::with_capacity(entries);
822 let mut last_sample_no = 0;
823 for _ in 0..entries {
824 let sample_no = br.read_u32be()?;
825 validate!(sample_no > last_sample_no);
826 track.keyframes.push(sample_no);
827 last_sample_no = sample_no;
828 }
829 Ok(size)
830}
831
832fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
833 let version = br.read_byte()?;
834 validate!(version == 0);
835 let _flags = br.read_u24be()?;
836 let entries = br.read_u32be()? as usize;
837 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
838 validate!((entries * 12 + 8) as u64 == size);
839 track.sample_map = Vec::with_capacity(entries);
840 let mut last_sample_no = 0;
841 for _i in 0..entries {
842 let sample_no = br.read_u32be()?;
843 validate!(sample_no > last_sample_no);
844 let nsamples = br.read_u32be()?;
845 let _sample_desc = br.read_u32be()?;
846 track.sample_map.push((sample_no, nsamples));
847 last_sample_no = sample_no;
848 }
849 Ok(size)
850}
851
852fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
853 let version = br.read_byte()?;
854 validate!(version == 0);
855 let _flags = br.read_u24be()?;
856 let sample_size = br.read_u32be()?;
857 if sample_size != 0 {
858 track.sample_size = sample_size;
9efec4ed
KS
859 if track.sample_size != 1 || track.bsize == 0 {
860 track.bsize = sample_size as usize;
861 }
58309c73
KS
862 Ok(8)
863 } else {
864 let entries = br.read_u32be()? as usize;
865 validate!((entries * 4 + 12) as u64 == size);
866 track.chunk_sizes = Vec::with_capacity(entries);
867 for _ in 0..entries {
868 let sample_size = br.read_u32be()?;
869 track.chunk_sizes.push(sample_size);
870 }
871 Ok(size)
872 }
873}
874
875fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
876 let version = br.read_byte()?;
877 validate!(version == 0);
878 let _flags = br.read_u24be()?;
879 let entries = br.read_u32be()? as usize;
880 validate!((entries * 4 + 8) as u64 == size);
881 track.chunk_offsets = Vec::with_capacity(entries);
882 for _i in 0..entries {
883 let sample_offset = br.read_u32be()?;
884 track.chunk_offsets.push(u64::from(sample_offset));
885 }
886 Ok(size)
887}
888
4e7deeda
KS
889fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
890 validate!(size >= 8);
891 let version = br.read_byte()?;
892 let _flags = br.read_u24be()?;
893 if version > 1 {
894 return Err(DemuxerError::NotImplemented);
895 }
896 let entries = br.read_u32be()? as usize;
897 track.ctts_version = version;
898 track.ctts_map.resize(entries);
899 match version {
900 0 | 1 => {
901 validate!(size == (entries as u64) * 8 + 8);
902 for _ in 0..entries {
903 let samp_count = br.read_u32be()?;
904 let samp_offset = br.read_u32be()?;
905 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
906 }
907 },
908 _ => unreachable!(),
909 };
910 track.ctts_map.reset();
911
912 Ok(size)
913}
914
0a0456a8
KS
915const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
916 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
917 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
918 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
919 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
920 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
921 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
922 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
923 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
924 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
925];
926
927fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
928 validate!(size >= 8);
929 let start = br.tell();
930 let _version = br.read_byte()?;
931 let flags = br.read_u24be()?;
932 let _track_id = br.read_u32be()?;
933 if (flags & 0x000001) != 0 {
934 let base_offset = br.read_u64be()?;
935 track.moof_off = base_offset;
936 }
937 if (flags & 0x000002) != 0 {
938 let _sample_description_index = br.read_u32be()?;
939 }
940 if (flags & 0x000008) != 0 {
941 let default_sample_duration = br.read_u32be()?;
942 if track.tb_div == 1 {
943 track.rescale(default_sample_duration);
944 }
945 }
946 if (flags & 0x000010) != 0 {
947 let _default_sample_size = br.read_u32be()?;
948 }
949 if (flags & 0x000020) != 0 {
950 let _default_sample_flags = br.read_u32be()?;
951 }
952 if (flags & 0x010000) != 0 {
953 }
954 /*if (flags & 0x020000) != 0 { // base offset is moof start
955 }*/
956 Ok(br.tell() - start)
957}
958
959fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
960 validate!(size >= 8);
961 let version = br.read_byte()?;
962 let flags = br.read_u24be()?;
963 let data_off_present = (flags & 0x000001) != 0;
964 let first_sample_flags = (flags & 0x000004) != 0;
965 let sample_duration_present = (flags & 0x000100) != 0;
966 let sample_size_present = (flags & 0x000200) != 0;
967 let sample_flags_present = (flags & 0x000400) != 0;
968 let sample_ct_off_present = (flags & 0x000800) != 0;
969
970 let sample_count = br.read_u32be()? as usize;
971
972 let mut hdr_size = 8;
973 let mut arr_size = 0;
974 if data_off_present {
975 hdr_size += 4;
976 }
977 if first_sample_flags {
978 hdr_size += 4;
979 }
980 if sample_duration_present {
981 arr_size += 4;
982 }
983 if sample_size_present {
984 arr_size += 4;
985 }
986 if sample_flags_present {
987 arr_size += 4;
988 }
989 if sample_ct_off_present {
990 arr_size += 4;
991 }
992 validate!(size == hdr_size + arr_size * (sample_count as u64));
993
994 let mut data_off = if data_off_present {
995 let off = br.read_u32be()? as i32;
996 let new_off = (track.moof_off as i64) + i64::from(off);
997 validate!(new_off > 0);
998 new_off as u64
999 } else {
1000 track.moof_off
1001 };
1002 if first_sample_flags {
1003 let _flags = br.read_u32be()?;
1004 }
1005
1006 if sample_size_present {
1007 track.chunk_sizes.reserve(sample_count);
1008 track.chunk_offsets.reserve(sample_count);
1009 }
1010
1011 if sample_ct_off_present {
1012 if track.ctts_version != version {
1013 track.ctts_version = version;
1014 }
1015 track.ctts_map.reserve(sample_count);
1016 }
1017
6bb26927
KS
1018 if track.chunk_offsets.len() < (std::u32::MAX as usize) {
1019 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
1020 }
0a0456a8
KS
1021 for _ in 0..sample_count {
1022 if sample_duration_present {
1023 let _duration = br.read_u32be()?;
1024 }
1025 if sample_size_present {
1026 let ssize = br.read_u32be()?;
1027 track.chunk_sizes.push(ssize);
1028 track.chunk_offsets.push(data_off);
1029 data_off += u64::from(ssize);
1030 }
1031 if sample_flags_present {
1032 let _flags = br.read_u32be()?;
1033 }
1034 if sample_ct_off_present {
1035 let samp_offset = br.read_u32be()?;
1036 if version == 0 {
1037 track.ctts_map.add(1, samp_offset / track.tb_div);
1038 } else {
1039 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1040 }
1041 }
1042 }
1043
1044 Ok(size)
1045}
1046
58309c73
KS
1047struct MOVDemuxer<'a> {
1048 src: &'a mut ByteReader<'a>,
1049 depth: usize,
1050 mdat_pos: u64,
1051 mdat_size: u64,
1052 tracks: Vec<Track>,
1053 cur_track: usize,
1054 tb_den: u32,
1055 duration: u32,
58cd51fa 1056 pal: Option<Arc<[u8; 1024]>>,
650d7bfb 1057
0a0456a8
KS
1058 moof_off: u64,
1059
650d7bfb 1060 print_chunks: bool,
88fd1059
KS
1061
1062 macbinary: bool,
58309c73
KS
1063}
1064
1065struct Track {
1066 track_id: u32,
1067 track_str_id: usize,
1068 track_no: u32,
bbbf86dd 1069 tb_num: u32,
58309c73 1070 tb_den: u32,
4e7deeda 1071 tb_div: u32,
7afec34d
KS
1072 raw_audio: bool,
1073 raw_apos: u64,
a480a0de 1074 duration: u32,
58309c73
KS
1075 depth: u8,
1076 tkhd_found: bool,
1077 stsd_found: bool,
1078 stream_type: StreamType,
1079 width: usize,
1080 height: usize,
1081 channels: usize,
1082 bits: usize,
9efec4ed 1083 bsize: usize,
58309c73
KS
1084 fcc: [u8; 4],
1085 keyframes: Vec<u32>,
1086 chunk_sizes: Vec<u32>,
1087 chunk_offsets: Vec<u64>,
bbbf86dd 1088 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
1089 sample_map: Vec<(u32, u32)>,
1090 sample_size: u32,
b0e12d42 1091 frame_samples: usize,
4e7deeda
KS
1092 ctts_map: RLESearcher<u32>,
1093 ctts_version: u8,
58309c73
KS
1094 stream: Option<NAStream>,
1095 cur_chunk: usize,
1096 cur_sample: usize,
07972bf3 1097 cur_ts: Option<u64>,
58309c73
KS
1098 samples_left: usize,
1099 last_offset: u64,
58cd51fa 1100 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 1101 timesearch: TimeSearcher,
650d7bfb 1102
0a0456a8
KS
1103 moof_off: u64,
1104
650d7bfb 1105 print_chunks: bool,
bbbf86dd
KS
1106}
1107
1108#[derive(Default)]
1109struct TimeSearcher {
1110 idx: usize,
1111 base: u64,
1112 sbase: u32,
1113 cur_len: u32,
1114 cur_mul: u32,
1115}
1116
1117impl TimeSearcher {
1118 fn new() -> Self { Self::default() }
1119 fn reset(&mut self) {
1120 *self = Self::default();
1121 }
b7c882c1 1122 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
bbbf86dd
KS
1123 if tts.is_empty() {
1124 u64::from(sample)
1125 } else if sample >= self.sbase {
1126 let mut sample = sample - self.sbase;
1127 if self.idx == 0 {
1128 let (cur_len, cur_mul) = tts[0];
1129 self.cur_len = cur_len;
1130 self.cur_mul = cur_mul;
1131 self.idx += 1;
1132 }
1133 while self.idx < tts.len() && sample > self.cur_len {
1134 sample -= self.cur_len;
1135 self.sbase += self.cur_len;
1136 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1137 self.cur_len = tts[self.idx].0;
1138 self.cur_mul = tts[self.idx].1;
1139 self.idx += 1;
1140 }
1141 self.base + u64::from(sample) * u64::from(self.cur_mul)
1142 } else {
1143 self.reset();
1144 self.map_time(sample, tts)
1145 }
1146 }
58309c73
KS
1147}
1148
4e7deeda
KS
1149#[derive(Default)]
1150struct RLESearcher<T> {
1151 array: Vec<(u32, T)>,
1152 idx: usize,
1153 start: u64,
1154 next: u64,
1155}
1156
1157impl<T:Default+Copy> RLESearcher<T> {
1158 fn new() -> Self { Self::default() }
1159 fn resize(&mut self, size: usize) {
37952415 1160 self.array.clear();
4e7deeda
KS
1161 self.array.reserve(size);
1162 }
0a0456a8
KS
1163 fn reserve(&mut self, size: usize) {
1164 self.array.reserve(size);
1165 }
4e7deeda
KS
1166 fn add(&mut self, len: u32, val: T) {
1167 self.array.push((len, val));
1168 }
1169 fn reset(&mut self) {
1170 self.start = 0;
1171 if !self.array.is_empty() {
1172 self.idx = 0;
1173 self.next = u64::from(self.array[0].0);
1174 } else {
1175 self.idx = self.array.len();
1176 self.next = 0;
1177 }
1178 }
1179 fn map(&mut self, sample: u64) -> Option<T> {
1180 if sample < self.start {
1181 self.reset();
1182 }
1183 if self.idx < self.array.len() {
1184 if sample < self.next {
1185 Some(self.array[self.idx].1)
1186 } else {
1187 while (self.idx < self.array.len()) && (sample >= self.next) {
1188 self.start = self.next;
1189 self.idx += 1;
1190 if self.idx < self.array.len() {
1191 self.next += u64::from(self.array[self.idx].0);
1192 }
1193 }
1194 if self.idx < self.array.len() {
1195 Some(self.array[self.idx].1)
1196 } else {
1197 None
1198 }
1199 }
1200 } else {
1201 None
1202 }
1203 }
1204}
1205
58309c73
KS
1206impl Track {
1207 fn new(track_no: u32, tb_den: u32) -> Self {
1208 Self {
1209 tkhd_found: false,
1210 stsd_found: false,
1211 track_id: 0,
1212 track_str_id: 0,
1213 track_no,
bbbf86dd 1214 tb_num: 1,
58309c73 1215 tb_den,
4e7deeda 1216 tb_div: 1,
7afec34d
KS
1217 raw_audio: false,
1218 raw_apos: 0,
a480a0de 1219 duration: 0,
58309c73
KS
1220 stream_type: StreamType::None,
1221 width: 0,
1222 height: 0,
1223 channels: 0,
1224 bits: 0,
9efec4ed 1225 bsize: 0,
58309c73
KS
1226 fcc: [0; 4],
1227 keyframes: Vec::new(),
1228 chunk_sizes: Vec::new(),
1229 chunk_offsets: Vec::new(),
bbbf86dd 1230 time_to_sample: Vec::new(),
58309c73
KS
1231 sample_map: Vec::new(),
1232 sample_size: 0,
b0e12d42 1233 frame_samples: 0,
4e7deeda
KS
1234 ctts_map: RLESearcher::new(),
1235 ctts_version: 0,
58309c73
KS
1236 stream: None,
1237 depth: 0,
1238 cur_chunk: 0,
1239 cur_sample: 0,
07972bf3 1240 cur_ts: None,
58309c73
KS
1241 samples_left: 0,
1242 last_offset: 0,
58cd51fa 1243 pal: None,
bbbf86dd 1244 timesearch: TimeSearcher::new(),
650d7bfb 1245
0a0456a8
KS
1246 moof_off: 0,
1247
650d7bfb 1248 print_chunks: false,
58309c73
KS
1249 }
1250 }
1251 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1252 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1253 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1254 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
0a0456a8
KS
1255 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1256 fn rescale(&mut self, tb_num: u32) {
1257 self.tb_div = tb_num;
1258 if let Some(ref mut stream) = self.stream {
1259 let tb_den = stream.tb_den;
1260 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1261 stream.duration /= u64::from(self.tb_div);
1262 stream.tb_num = tb_num;
1263 stream.tb_den = tb_den;
1264 self.tb_num = tb_num;
1265 self.tb_den = tb_den;
1266 self.duration /= self.tb_div;
1267 }
1268 }
58309c73 1269 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 1270 if !self.keyframes.is_empty() {
58309c73
KS
1271 seek_index.mode = SeekIndexMode::Present;
1272 }
bbbf86dd 1273 let mut tsearch = TimeSearcher::new();
58309c73 1274 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
1275 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1276 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1277 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
1278 }
1279 }
1280 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1281 if nsamp == 0 {
9efec4ed 1282 self.bsize
58309c73
KS
1283 } else {
1284 match &self.fcc {
1285 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1286 (nsamp * self.bits * self.channels + 7) >> 3
1287 },
1288 b"ima4" => {
1289 let nblocks = (nsamp + 63) >> 6;
1290 nblocks * 34 * self.channels
1291 },
1292 b"MAC3" => {
1293 (nsamp + 5) / 6 * 2 * self.channels
1294 },
1295 b"MAC6" => {
1296 (nsamp + 5) / 6 * self.channels
1297 },
1298 b"in24" => nsamp * 3 * self.channels,
1299 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1300 b"fl64" => nsamp * 8 * self.channels,
1301 b"ulaw" | b"alaw" => nsamp,
1302 b"ms\x00\x02" => { //MS ADPCM
1303 ((nsamp - 1) / 2 + 7) * self.channels
1304 },
1305 b"ms\x00\x21" => { //IMA ADPCM
1306 (nsamp / 2 + 4) * self.channels
1307 },
9efec4ed 1308 _ => self.bsize,
58309c73
KS
1309 }
1310 }
1311 }
1312 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 1313 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
4e7deeda
KS
1314 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1315 let dts = match self.ctts_version {
1316 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1317 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1318 _ => unimplemented!(),
1319 };
1320 if (dts as i64) < 0 {
1321 None
1322 } else {
1323 Some(dts)
1324 }
1325 } else {
1326 None
1327 };
1328 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
58309c73
KS
1329 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1330 if self.cur_sample >= self.chunk_sizes.len() {
1331 return None;
1332 }
1333 let offset = self.chunk_offsets[self.cur_sample];
1334 let size = self.chunk_sizes[self.cur_sample] as usize;
1335 self.cur_sample += 1;
1336 Some((pts, offset, size))
1337 } else {
1338 if self.samples_left == 0 {
1339 if self.cur_chunk >= self.chunk_offsets.len() {
1340 return None;
1341 }
1342 for (idx, samples) in self.sample_map.iter() {
1343 if *idx as usize <= self.cur_chunk + 1 {
1344 self.samples_left = *samples as usize;
1345 } else {
1346 break;
1347 }
1348 }
1349 self.last_offset = self.chunk_offsets[self.cur_chunk];
1350 self.cur_chunk += 1;
1351 }
1352 let offset = self.last_offset;
1353 let size = self.get_size(self.cur_sample);
1354 self.last_offset += size as u64;
1355 if self.stream_type == StreamType::Video {
1356 self.samples_left -= 1;
d940f0c2
KS
1357 } else if self.frame_samples != 0 && self.bsize != 0 {
1358 let nblocks = size / self.bsize;
7afec34d
KS
1359 if self.raw_audio {
1360 pts.pts = Some(self.raw_apos);
1361 pts.duration = Some(nblocks as u64);
1362 self.raw_apos += nblocks as u64;
1363 }
d940f0c2
KS
1364 if nblocks > 0 {
1365 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1366 self.samples_left -= consumed;
1367 } else {
1368 self.samples_left = 0;
1369 }
7afec34d
KS
1370 } else if !self.raw_audio {
1371 self.samples_left -= 1;
58309c73 1372 } else {
7afec34d
KS
1373 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1374 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1375 let cur_size = self.calculate_chunk_size(self.samples_left);
1376 let add_off = (size - cur_size) as u64;
1377 let dsize = cur_size.min(max_size);
1378 if self.samples_left >= BLOCK_SAMPLES {
1379 self.cur_sample += BLOCK_SAMPLES;
1380 self.samples_left -= BLOCK_SAMPLES;
1381 self.last_offset -= size as u64;
1382 } else {
1383 self.cur_sample += self.samples_left;
1384 self.samples_left = 0;
1385 }
1386 return Some((pts, offset + add_off, dsize));
58309c73
KS
1387 }
1388 self.cur_sample += 1;
1389 Some((pts, offset, size))
1390 }
1391 }
1392 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1393 if !self.chunk_sizes.is_empty() {
58309c73 1394 self.chunk_sizes[sample_no] as usize
61cab15b 1395 } else if !self.sample_map.is_empty() {
58309c73
KS
1396 let mut nsamp = 0;
1397 for (idx, samples) in self.sample_map.iter() {
1398 if *idx as usize <= self.cur_chunk {
1399 nsamp = *samples;
1400 } else {
1401 break;
1402 }
1403 }
1404 self.calculate_chunk_size(nsamp as usize)
1405 } else {
9efec4ed 1406 self.bsize
58309c73
KS
1407 }
1408 }
b7c882c1 1409 #[allow(clippy::collapsible_if)]
7afec34d 1410 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
58309c73
KS
1411 self.cur_sample = pts as usize;
1412 self.samples_left = 0;
07972bf3 1413 self.cur_ts = None;
58309c73 1414 if self.stream_type == StreamType::Audio {
7afec34d
KS
1415 if let NATimePoint::Milliseconds(ms) = tpoint {
1416 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1417 if self.raw_audio {
1418 if self.frame_samples != 0 {
1419 self.raw_apos = exp_pts / (self.frame_samples as u64);
1420 let mut apos = 0;
1421 self.cur_sample = 0;
1422 self.cur_chunk = 0;
1423 let mut cmap = self.sample_map.iter();
1424 let mut cur_samps = 0;
1425 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1426 loop {
1427 if self.cur_chunk + 1 == next_idx as usize {
1428 self.samples_left = cur_samps;
1429 cur_samps = next_samples as usize;
1430 if let Some((new_idx, new_samples)) = cmap.next() {
1431 next_idx = *new_idx;
1432 next_samples = *new_samples;
1433 }
1434 }
1435 self.raw_apos = apos;
1436 apos += (cur_samps / self.frame_samples) as u64;
1437 if apos > exp_pts {
1438 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1439 if self.cur_chunk >= self.chunk_offsets.len() {
1440 return Err(DemuxerError::SeekError);
1441 }
1442 self.last_offset = self.chunk_offsets[self.cur_chunk];
1443 break;
1444 }
1445 }
1446 self.cur_chunk += 1;
1447 }
1448 self.samples_left = cur_samps;
1449 self.cur_chunk += 1;
1450 } else {
1451 self.raw_apos = exp_pts;
1452 self.cur_sample = exp_pts as usize;
1453 let mut csamp = 0;
1454 self.cur_chunk = 0;
1455 let mut cmap = self.sample_map.iter();
1456 let mut cur_samps = 0;
1457 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1458 loop {
1459 if self.cur_chunk + 1 == next_idx as usize {
1460 self.samples_left = cur_samps;
1461 cur_samps = next_samples as usize;
1462 if let Some((new_idx, new_samples)) = cmap.next() {
1463 next_idx = *new_idx;
1464 next_samples = *new_samples;
1465 }
1466 }
1467 csamp += cur_samps;
1468 if csamp > self.cur_sample {
1469 if self.cur_chunk >= self.chunk_offsets.len() {
1470 return Err(DemuxerError::SeekError);
1471 }
1472 self.last_offset = self.chunk_offsets[self.cur_chunk];
1473 break;
1474 }
1475 self.cur_chunk += 1;
1476 }
1477 self.samples_left = csamp - self.cur_sample;
1478 self.cur_chunk += 1;
1479 }
5317ee9c 1480 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
7afec34d 1481 self.cur_chunk = self.cur_sample;
5317ee9c
KS
1482 } else {
1483 let mut csamp = 0;
1484 self.cur_chunk = 0;
1485 let mut cmap = self.sample_map.iter();
1486 let mut cur_samps = 0;
1487 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1488 loop {
1489 if self.cur_chunk + 1 == next_idx as usize {
1490 self.samples_left = cur_samps;
1491 cur_samps = next_samples as usize;
1492 if let Some((new_idx, new_samples)) = cmap.next() {
1493 next_idx = *new_idx;
1494 next_samples = *new_samples;
1495 }
1496 }
1497 csamp += cur_samps;
1498 if csamp > self.cur_sample {
1499 if self.cur_chunk >= self.chunk_offsets.len() {
1500 return Err(DemuxerError::SeekError);
1501 }
1502 self.last_offset = self.chunk_offsets[self.cur_chunk];
1503 break;
1504 }
1505 self.cur_chunk += 1;
1506 }
1507 self.cur_sample = csamp - cur_samps;
1508 self.samples_left = cur_samps;
1509 self.last_offset = self.chunk_offsets[self.cur_chunk];
1510 self.cur_chunk += 1;
7afec34d
KS
1511 }
1512 } else {
1513 self.cur_chunk = self.cur_sample;
1514 }
61cab15b 1515 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1516 let mut csamp = 0;
1517 self.cur_chunk = 0;
1518 let mut cmap = self.sample_map.iter();
1519 let mut cur_samps = 0;
1520 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1521 loop {
bbbf86dd 1522 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1523 self.samples_left = cur_samps;
1524 cur_samps = next_samples as usize;
1525 if let Some((new_idx, new_samples)) = cmap.next() {
1526 next_idx = *new_idx;
1527 next_samples = *new_samples;
1528 }
1529 }
1530 csamp += cur_samps;
1531 if csamp >= self.cur_sample {
7afec34d
KS
1532 if self.cur_chunk >= self.chunk_offsets.len() {
1533 return Err(DemuxerError::SeekError);
1534 }
58309c73
KS
1535 self.last_offset = self.chunk_offsets[self.cur_chunk];
1536 break;
1537 }
1538 self.cur_chunk += 1;
1539 }
1540 csamp -= cur_samps;
bbbf86dd 1541 for sample_no in csamp..self.cur_sample {
58309c73
KS
1542 self.last_offset += self.get_size(sample_no) as u64;
1543 }
bbbf86dd
KS
1544 self.samples_left = csamp + cur_samps - self.cur_sample;
1545 self.cur_chunk += 1;
58309c73 1546 }
7afec34d 1547 Ok(())
58309c73
KS
1548 }
1549}
1550
07972bf3
KS
1551fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1552 if let Some(cpts) = pts.get_pts() {
1553 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1554 track.cur_ts = Some(ts);
1555 } else {
1556 track.cur_ts = None;
1557 }
817e4872
KS
1558 let stream = strmgr.get_stream(track.track_str_id);
1559 if stream.is_none() { return Err(DemuxerError::InvalidData); }
1560 let stream = stream.unwrap();
07972bf3
KS
1561 src.seek(SeekFrom::Start(offset))?;
1562 let mut pkt = src.read_packet(stream, pts, false, size)?;
1563 if let Some(ref pal) = track.pal {
1564 let side_data = NASideData::Palette(first, pal.clone());
1565 pkt.add_side_data(side_data);
1566 }
1567 Ok(pkt)
1568}
1569
58309c73
KS
1570impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1571 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
88fd1059
KS
1572 if !self.macbinary {
1573 self.read_root(strmgr)?;
1574 } else {
1575 let ver = self.src.read_byte()?;
1576 validate!(ver == 0);
1577 self.src.read_skip(64)?;
1578 let tag = self.src.read_tag()?;
1579 validate!(&tag == b"MooV");
1580 self.src.read_skip(14)?;
1581 let data_length = self.src.read_u32be()?;
1582 validate!(data_length > 8);
1583 let rsrc_length = self.src.read_u32be()?;
1584 validate!(rsrc_length > 0);
1585 self.src.read_skip(31)?;
1586 let ver = self.src.read_byte()?;
1587 validate!(ver == 0x81);
1588 let ver = self.src.read_byte()?;
1589 validate!(ver == 0x81);
1590 //xxx: maybe check header CRC
1591
1592 let rsrc_start = 0x80 + ((data_length + 0x7F) & !0x7F);
1593 self.src.seek(SeekFrom::Start(rsrc_start.into()))?;
1594 let rsrc_off = self.src.read_u32be()?;
1595 let rsrc_map_off = self.src.read_u32be()?;
1596 let rsrc_size = self.src.read_u32be()?;
1597 let _rsrc_map_size = self.src.read_u32be()?;
1598 validate!(rsrc_off >= 0x10);
1599 validate!(rsrc_map_off >= rsrc_off + rsrc_size);
1600 self.src.seek(SeekFrom::Current(i64::from(rsrc_off - 16)))?;
1601 // I'm too lazy to parse resource map, so let's just iterate over resources for movie header
1602 let end_pos = u64::from(rsrc_start + rsrc_off + rsrc_size);
1603 let mut peek_buf = [0u8; 8];
1604 while self.src.tell() < end_pos {
1605 let cur_size = self.src.read_u32be()?;
1606 validate!(self.src.tell() + u64::from(cur_size) <= end_pos);
1607 if cur_size > 8 {
1608 let rsize = self.src.peek_u32be()?;
1609 if rsize == cur_size {
1610 self.src.peek_buf(&mut peek_buf)?;
1611 if &peek_buf[4..] == b"moov" {
1612 self.src.read_skip(8)?;
1613 self.read_moov(strmgr, rsize.into())?;
1614 self.mdat_pos = 8;
1615 break;
1616 }
1617 }
1618 }
1619 self.src.read_skip(cur_size as usize)?;
1620 }
1621 }
58309c73 1622 validate!(self.mdat_pos > 0);
61cab15b 1623 validate!(!self.tracks.is_empty());
0a0456a8 1624 for track in self.tracks.iter_mut() {
817e4872
KS
1625 let mut strm = None;
1626 std::mem::swap(&mut track.stream, &mut strm);
1627 if let Some(stream) = strm {
0a0456a8
KS
1628 let str_id = strmgr.add_stream(stream).unwrap();
1629 track.track_str_id = str_id;
1630 }
1631 }
88fd1059
KS
1632 if self.macbinary {
1633 // patch data offsets
1634 for track in self.tracks.iter_mut() {
1635 for offset in track.chunk_offsets.iter_mut() {
1636 *offset += 0x80;
1637 }
1638 }
1639 }
58309c73
KS
1640 for track in self.tracks.iter() {
1641 track.fill_seek_index(seek_index);
1642 }
1643 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1644 self.cur_track = 0;
1645 Ok(())
1646 }
1647
1648 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1649 if self.tracks.is_empty() {
58309c73
KS
1650 return Err(DemuxerError::EOF);
1651 }
07972bf3
KS
1652 let mut has_all_time = true;
1653 let mut min_ts = std::u64::MAX;
1654 for trk in self.tracks.iter() {
1655 if let Some(ts) = trk.cur_ts {
1656 min_ts = min_ts.min(ts);
1657 } else {
1658 has_all_time = false;
1659 break;
1660 }
1661 }
1662 if has_all_time {
1663 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1664 if let Some(ts) = track.cur_ts {
1665 if ts == min_ts {
1666 let first = track.cur_sample == 0;
1667 if let Some((pts, offset, size)) = track.get_next_chunk() {
1668 self.cur_track = trk_no + 1;
6f263099 1669 return process_packet(self.src, strmgr, track, pts, offset, size, first);
07972bf3
KS
1670 }
1671 }
1672 }
1673 }
1674 }
1675
58309c73
KS
1676 for _ in 0..self.tracks.len() {
1677 if self.cur_track >= self.tracks.len() {
1678 self.cur_track = 0;
1679 }
1680 let track = &mut self.tracks[self.cur_track];
1681 self.cur_track += 1;
58cd51fa 1682 let first = track.cur_sample == 0;
58309c73 1683 if let Some((pts, offset, size)) = track.get_next_chunk() {
6f263099 1684 return process_packet(self.src, strmgr, track, pts, offset, size, first);
58309c73
KS
1685 }
1686 }
61cab15b 1687 Err(DemuxerError::EOF)
58309c73
KS
1688 }
1689
24d99894 1690 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1691 let ret = seek_index.find_pos(time);
1692 if ret.is_none() {
5317ee9c
KS
1693 if let NATimePoint::Milliseconds(_) = time {
1694 let mut aonly = true;
1695 for track in self.tracks.iter() {
1696 if track.stream_type != StreamType::Audio || !track.raw_audio {
1697 aonly = false;
1698 break;
1699 }
1700 }
1701 if aonly {
1702 for track in self.tracks.iter_mut() {
1703 track.seek(0, time)?;
1704 }
1705 return Ok(());
1706 }
1707 }
58309c73
KS
1708 return Err(DemuxerError::SeekError);
1709 }
1710 let seek_info = ret.unwrap();
5317ee9c
KS
1711 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1712 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
58309c73 1713 for track in self.tracks.iter_mut() {
5317ee9c
KS
1714 let cur_pts = if track.track_id == seek_info.str_id {
1715 seek_info.pts
1716 } else {
1717 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1718 };
1719 track.seek(cur_pts, time)?;
58309c73
KS
1720 }
1721 Ok(())
1722 }
a480a0de
KS
1723 fn get_duration(&self) -> u64 {
1724 if self.tb_den != 0 {
1725 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1726 } else {
1727 0
1728 }
1729 }
58309c73
KS
1730}
1731
650d7bfb
KS
1732const PRINT_CHUNKS: &str = "print_chunks";
1733
1734const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1735 NAOptionDefinition {
1736 name: PRINT_CHUNKS,
1737 description: "Print parsed file structure",
1738 opt_type: NAOptionDefinitionType::Bool },
1739];
1740
787b8d03 1741impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb 1742 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
b7c882c1 1743 #[allow(clippy::single_match)]
650d7bfb
KS
1744 fn set_options(&mut self, options: &[NAOption]) {
1745 for option in options.iter() {
1746 for opt_def in DEMUXER_OPTIONS.iter() {
1747 if opt_def.check(option).is_ok() {
1748 match (option.name, &option.value) {
1749 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1750 self.print_chunks = *val;
1751 },
1752 _ => {},
1753 }
1754 }
1755 }
1756 }
1757 }
1758 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1759 match name {
1760 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1761 _ => None,
1762 }
1763 }
787b8d03
KS
1764}
1765
58309c73
KS
1766impl<'a> MOVDemuxer<'a> {
1767 fn new(io: &'a mut ByteReader<'a>) -> Self {
88fd1059
KS
1768 Self::new_common(io, false)
1769 }
1770 fn new_macbinary(io: &'a mut ByteReader<'a>) -> Self {
1771 Self::new_common(io, true)
1772 }
1773 fn new_common(io: &'a mut ByteReader<'a>, macbinary: bool) -> Self {
58309c73
KS
1774 MOVDemuxer {
1775 src: io,
1776 depth: 0,
1777 mdat_pos: 0,
1778 mdat_size: 0,
1779 tracks: Vec::with_capacity(2),
1780 cur_track: 0,
1781 tb_den: 0,
1782 duration: 0,
58cd51fa 1783 pal: None,
650d7bfb 1784
0a0456a8
KS
1785 moof_off: 0,
1786
650d7bfb 1787 print_chunks: false,
88fd1059
KS
1788
1789 macbinary,
58309c73
KS
1790 }
1791 }
1792 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1793 self.depth = 0;
1794 while self.src.left() != 0 {
6f263099 1795 let ret = read_chunk_header(self.src);
58309c73
KS
1796 if ret.is_err() { break; }
1797 let (ctype, size) = ret.unwrap();
0a0456a8
KS
1798 if self.print_chunks {
1799 print_cname(ctype, size, self.src.tell(), 0);
1800 }
58309c73
KS
1801 if IGNORED_CHUNKS.contains(&ctype) {
1802 self.src.skip64(size)?;
1803 continue;
1804 }
1805 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1806 let read_size;
6f263099 1807 if let Some(handler) = handler {
58309c73
KS
1808 read_size = (handler.parse)(self, strmgr, size)?;
1809 } else {
1810 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1811 read_size = 0;
1812 }
1813 validate!(read_size <= size);
1814 self.src.skip64(size - read_size)?;
1815 }
1816//todo check if all needed chunks are found
1817 Ok(())
1818 }
1819 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
0a0456a8 1820 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
58309c73
KS
1821}
1822
1823pub struct MOVDemuxerCreator { }
1824
1825impl DemuxerCreator for MOVDemuxerCreator {
1826 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1827 Box::new(MOVDemuxer::new(br))
1828 }
1829 fn get_name(&self) -> &'static str { "mov" }
1830}
1831
88fd1059
KS
1832pub struct MacBinaryMOVDemuxerCreator { }
1833
1834impl DemuxerCreator for MacBinaryMOVDemuxerCreator {
1835 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1836 Box::new(MOVDemuxer::new_macbinary(br))
1837 }
1838 fn get_name(&self) -> &'static str { "mov-macbin" }
1839}
1840
2736c15a
KS
1841const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1842 0x93, 0x65, 0x5E, 0x00,
1843 0xFF, 0xFF, 0xFF, 0x00,
1844 0xDF, 0xD0, 0xAB, 0x00,
1845 0x00, 0x00, 0x00, 0x00
1846];
1847const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1848 0xFF, 0xFB, 0xFF, 0x00,
1849 0xEF, 0xD9, 0xBB, 0x00,
1850 0xE8, 0xC9, 0xB1, 0x00,
1851 0x93, 0x65, 0x5E, 0x00,
1852 0xFC, 0xDE, 0xE8, 0x00,
1853 0x9D, 0x88, 0x91, 0x00,
1854 0xFF, 0xFF, 0xFF, 0x00,
1855 0xFF, 0xFF, 0xFF, 0x00,
1856 0xFF, 0xFF, 0xFF, 0x00,
1857 0x47, 0x48, 0x37, 0x00,
1858 0x7A, 0x5E, 0x55, 0x00,
1859 0xDF, 0xD0, 0xAB, 0x00,
1860 0xFF, 0xFB, 0xF9, 0x00,
1861 0xE8, 0xCA, 0xC5, 0x00,
1862 0x8A, 0x7C, 0x77, 0x00,
1863 0x00, 0x00, 0x00, 0x00
1864];
1865const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1866 0xFF, 0xFF, 0xFF, 0x00,
1867 0xFF, 0xFF, 0xCC, 0x00,
1868 0xFF, 0xFF, 0x99, 0x00,
1869 0xFF, 0xFF, 0x66, 0x00,
1870 0xFF, 0xFF, 0x33, 0x00,
1871 0xFF, 0xFF, 0x00, 0x00,
1872 0xFF, 0xCC, 0xFF, 0x00,
1873 0xFF, 0xCC, 0xCC, 0x00,
1874 0xFF, 0xCC, 0x99, 0x00,
1875 0xFF, 0xCC, 0x66, 0x00,
1876 0xFF, 0xCC, 0x33, 0x00,
1877 0xFF, 0xCC, 0x00, 0x00,
1878 0xFF, 0x99, 0xFF, 0x00,
1879 0xFF, 0x99, 0xCC, 0x00,
1880 0xFF, 0x99, 0x99, 0x00,
1881 0xFF, 0x99, 0x66, 0x00,
1882 0xFF, 0x99, 0x33, 0x00,
1883 0xFF, 0x99, 0x00, 0x00,
1884 0xFF, 0x66, 0xFF, 0x00,
1885 0xFF, 0x66, 0xCC, 0x00,
1886 0xFF, 0x66, 0x99, 0x00,
1887 0xFF, 0x66, 0x66, 0x00,
1888 0xFF, 0x66, 0x33, 0x00,
1889 0xFF, 0x66, 0x00, 0x00,
1890 0xFF, 0x33, 0xFF, 0x00,
1891 0xFF, 0x33, 0xCC, 0x00,
1892 0xFF, 0x33, 0x99, 0x00,
1893 0xFF, 0x33, 0x66, 0x00,
1894 0xFF, 0x33, 0x33, 0x00,
1895 0xFF, 0x33, 0x00, 0x00,
1896 0xFF, 0x00, 0xFF, 0x00,
1897 0xFF, 0x00, 0xCC, 0x00,
1898 0xFF, 0x00, 0x99, 0x00,
1899 0xFF, 0x00, 0x66, 0x00,
1900 0xFF, 0x00, 0x33, 0x00,
1901 0xFF, 0x00, 0x00, 0x00,
1902 0xCC, 0xFF, 0xFF, 0x00,
1903 0xCC, 0xFF, 0xCC, 0x00,
1904 0xCC, 0xFF, 0x99, 0x00,
1905 0xCC, 0xFF, 0x66, 0x00,
1906 0xCC, 0xFF, 0x33, 0x00,
1907 0xCC, 0xFF, 0x00, 0x00,
1908 0xCC, 0xCC, 0xFF, 0x00,
1909 0xCC, 0xCC, 0xCC, 0x00,
1910 0xCC, 0xCC, 0x99, 0x00,
1911 0xCC, 0xCC, 0x66, 0x00,
1912 0xCC, 0xCC, 0x33, 0x00,
1913 0xCC, 0xCC, 0x00, 0x00,
1914 0xCC, 0x99, 0xFF, 0x00,
1915 0xCC, 0x99, 0xCC, 0x00,
1916 0xCC, 0x99, 0x99, 0x00,
1917 0xCC, 0x99, 0x66, 0x00,
1918 0xCC, 0x99, 0x33, 0x00,
1919 0xCC, 0x99, 0x00, 0x00,
1920 0xCC, 0x66, 0xFF, 0x00,
1921 0xCC, 0x66, 0xCC, 0x00,
1922 0xCC, 0x66, 0x99, 0x00,
1923 0xCC, 0x66, 0x66, 0x00,
1924 0xCC, 0x66, 0x33, 0x00,
1925 0xCC, 0x66, 0x00, 0x00,
1926 0xCC, 0x33, 0xFF, 0x00,
1927 0xCC, 0x33, 0xCC, 0x00,
1928 0xCC, 0x33, 0x99, 0x00,
1929 0xCC, 0x33, 0x66, 0x00,
1930 0xCC, 0x33, 0x33, 0x00,
1931 0xCC, 0x33, 0x00, 0x00,
1932 0xCC, 0x00, 0xFF, 0x00,
1933 0xCC, 0x00, 0xCC, 0x00,
1934 0xCC, 0x00, 0x99, 0x00,
1935 0xCC, 0x00, 0x66, 0x00,
1936 0xCC, 0x00, 0x33, 0x00,
1937 0xCC, 0x00, 0x00, 0x00,
1938 0x99, 0xFF, 0xFF, 0x00,
1939 0x99, 0xFF, 0xCC, 0x00,
1940 0x99, 0xFF, 0x99, 0x00,
1941 0x99, 0xFF, 0x66, 0x00,
1942 0x99, 0xFF, 0x33, 0x00,
1943 0x99, 0xFF, 0x00, 0x00,
1944 0x99, 0xCC, 0xFF, 0x00,
1945 0x99, 0xCC, 0xCC, 0x00,
1946 0x99, 0xCC, 0x99, 0x00,
1947 0x99, 0xCC, 0x66, 0x00,
1948 0x99, 0xCC, 0x33, 0x00,
1949 0x99, 0xCC, 0x00, 0x00,
1950 0x99, 0x99, 0xFF, 0x00,
1951 0x99, 0x99, 0xCC, 0x00,
1952 0x99, 0x99, 0x99, 0x00,
1953 0x99, 0x99, 0x66, 0x00,
1954 0x99, 0x99, 0x33, 0x00,
1955 0x99, 0x99, 0x00, 0x00,
1956 0x99, 0x66, 0xFF, 0x00,
1957 0x99, 0x66, 0xCC, 0x00,
1958 0x99, 0x66, 0x99, 0x00,
1959 0x99, 0x66, 0x66, 0x00,
1960 0x99, 0x66, 0x33, 0x00,
1961 0x99, 0x66, 0x00, 0x00,
1962 0x99, 0x33, 0xFF, 0x00,
1963 0x99, 0x33, 0xCC, 0x00,
1964 0x99, 0x33, 0x99, 0x00,
1965 0x99, 0x33, 0x66, 0x00,
1966 0x99, 0x33, 0x33, 0x00,
1967 0x99, 0x33, 0x00, 0x00,
1968 0x99, 0x00, 0xFF, 0x00,
1969 0x99, 0x00, 0xCC, 0x00,
1970 0x99, 0x00, 0x99, 0x00,
1971 0x99, 0x00, 0x66, 0x00,
1972 0x99, 0x00, 0x33, 0x00,
1973 0x99, 0x00, 0x00, 0x00,
1974 0x66, 0xFF, 0xFF, 0x00,
1975 0x66, 0xFF, 0xCC, 0x00,
1976 0x66, 0xFF, 0x99, 0x00,
1977 0x66, 0xFF, 0x66, 0x00,
1978 0x66, 0xFF, 0x33, 0x00,
1979 0x66, 0xFF, 0x00, 0x00,
1980 0x66, 0xCC, 0xFF, 0x00,
1981 0x66, 0xCC, 0xCC, 0x00,
1982 0x66, 0xCC, 0x99, 0x00,
1983 0x66, 0xCC, 0x66, 0x00,
1984 0x66, 0xCC, 0x33, 0x00,
1985 0x66, 0xCC, 0x00, 0x00,
1986 0x66, 0x99, 0xFF, 0x00,
1987 0x66, 0x99, 0xCC, 0x00,
1988 0x66, 0x99, 0x99, 0x00,
1989 0x66, 0x99, 0x66, 0x00,
1990 0x66, 0x99, 0x33, 0x00,
1991 0x66, 0x99, 0x00, 0x00,
1992 0x66, 0x66, 0xFF, 0x00,
1993 0x66, 0x66, 0xCC, 0x00,
1994 0x66, 0x66, 0x99, 0x00,
1995 0x66, 0x66, 0x66, 0x00,
1996 0x66, 0x66, 0x33, 0x00,
1997 0x66, 0x66, 0x00, 0x00,
1998 0x66, 0x33, 0xFF, 0x00,
1999 0x66, 0x33, 0xCC, 0x00,
2000 0x66, 0x33, 0x99, 0x00,
2001 0x66, 0x33, 0x66, 0x00,
2002 0x66, 0x33, 0x33, 0x00,
2003 0x66, 0x33, 0x00, 0x00,
2004 0x66, 0x00, 0xFF, 0x00,
2005 0x66, 0x00, 0xCC, 0x00,
2006 0x66, 0x00, 0x99, 0x00,
2007 0x66, 0x00, 0x66, 0x00,
2008 0x66, 0x00, 0x33, 0x00,
2009 0x66, 0x00, 0x00, 0x00,
2010 0x33, 0xFF, 0xFF, 0x00,
2011 0x33, 0xFF, 0xCC, 0x00,
2012 0x33, 0xFF, 0x99, 0x00,
2013 0x33, 0xFF, 0x66, 0x00,
2014 0x33, 0xFF, 0x33, 0x00,
2015 0x33, 0xFF, 0x00, 0x00,
2016 0x33, 0xCC, 0xFF, 0x00,
2017 0x33, 0xCC, 0xCC, 0x00,
2018 0x33, 0xCC, 0x99, 0x00,
2019 0x33, 0xCC, 0x66, 0x00,
2020 0x33, 0xCC, 0x33, 0x00,
2021 0x33, 0xCC, 0x00, 0x00,
2022 0x33, 0x99, 0xFF, 0x00,
2023 0x33, 0x99, 0xCC, 0x00,
2024 0x33, 0x99, 0x99, 0x00,
2025 0x33, 0x99, 0x66, 0x00,
2026 0x33, 0x99, 0x33, 0x00,
2027 0x33, 0x99, 0x00, 0x00,
2028 0x33, 0x66, 0xFF, 0x00,
2029 0x33, 0x66, 0xCC, 0x00,
2030 0x33, 0x66, 0x99, 0x00,
2031 0x33, 0x66, 0x66, 0x00,
2032 0x33, 0x66, 0x33, 0x00,
2033 0x33, 0x66, 0x00, 0x00,
2034 0x33, 0x33, 0xFF, 0x00,
2035 0x33, 0x33, 0xCC, 0x00,
2036 0x33, 0x33, 0x99, 0x00,
2037 0x33, 0x33, 0x66, 0x00,
2038 0x33, 0x33, 0x33, 0x00,
2039 0x33, 0x33, 0x00, 0x00,
2040 0x33, 0x00, 0xFF, 0x00,
2041 0x33, 0x00, 0xCC, 0x00,
2042 0x33, 0x00, 0x99, 0x00,
2043 0x33, 0x00, 0x66, 0x00,
2044 0x33, 0x00, 0x33, 0x00,
2045 0x33, 0x00, 0x00, 0x00,
2046 0x00, 0xFF, 0xFF, 0x00,
2047 0x00, 0xFF, 0xCC, 0x00,
2048 0x00, 0xFF, 0x99, 0x00,
2049 0x00, 0xFF, 0x66, 0x00,
2050 0x00, 0xFF, 0x33, 0x00,
2051 0x00, 0xFF, 0x00, 0x00,
2052 0x00, 0xCC, 0xFF, 0x00,
2053 0x00, 0xCC, 0xCC, 0x00,
2054 0x00, 0xCC, 0x99, 0x00,
2055 0x00, 0xCC, 0x66, 0x00,
2056 0x00, 0xCC, 0x33, 0x00,
2057 0x00, 0xCC, 0x00, 0x00,
2058 0x00, 0x99, 0xFF, 0x00,
2059 0x00, 0x99, 0xCC, 0x00,
2060 0x00, 0x99, 0x99, 0x00,
2061 0x00, 0x99, 0x66, 0x00,
2062 0x00, 0x99, 0x33, 0x00,
2063 0x00, 0x99, 0x00, 0x00,
2064 0x00, 0x66, 0xFF, 0x00,
2065 0x00, 0x66, 0xCC, 0x00,
2066 0x00, 0x66, 0x99, 0x00,
2067 0x00, 0x66, 0x66, 0x00,
2068 0x00, 0x66, 0x33, 0x00,
2069 0x00, 0x66, 0x00, 0x00,
2070 0x00, 0x33, 0xFF, 0x00,
2071 0x00, 0x33, 0xCC, 0x00,
2072 0x00, 0x33, 0x99, 0x00,
2073 0x00, 0x33, 0x66, 0x00,
2074 0x00, 0x33, 0x33, 0x00,
2075 0x00, 0x33, 0x00, 0x00,
2076 0x00, 0x00, 0xFF, 0x00,
2077 0x00, 0x00, 0xCC, 0x00,
2078 0x00, 0x00, 0x99, 0x00,
2079 0x00, 0x00, 0x66, 0x00,
2080 0x00, 0x00, 0x33, 0x00,
2081 0xEE, 0x00, 0x00, 0x00,
2082 0xDD, 0x00, 0x00, 0x00,
2083 0xBB, 0x00, 0x00, 0x00,
2084 0xAA, 0x00, 0x00, 0x00,
2085 0x88, 0x00, 0x00, 0x00,
2086 0x77, 0x00, 0x00, 0x00,
2087 0x55, 0x00, 0x00, 0x00,
2088 0x44, 0x00, 0x00, 0x00,
2089 0x22, 0x00, 0x00, 0x00,
2090 0x11, 0x00, 0x00, 0x00,
2091 0x00, 0xEE, 0x00, 0x00,
2092 0x00, 0xDD, 0x00, 0x00,
2093 0x00, 0xBB, 0x00, 0x00,
2094 0x00, 0xAA, 0x00, 0x00,
2095 0x00, 0x88, 0x00, 0x00,
2096 0x00, 0x77, 0x00, 0x00,
2097 0x00, 0x55, 0x00, 0x00,
2098 0x00, 0x44, 0x00, 0x00,
2099 0x00, 0x22, 0x00, 0x00,
2100 0x00, 0x11, 0x00, 0x00,
2101 0x00, 0x00, 0xEE, 0x00,
2102 0x00, 0x00, 0xDD, 0x00,
2103 0x00, 0x00, 0xBB, 0x00,
2104 0x00, 0x00, 0xAA, 0x00,
2105 0x00, 0x00, 0x88, 0x00,
2106 0x00, 0x00, 0x77, 0x00,
2107 0x00, 0x00, 0x55, 0x00,
2108 0x00, 0x00, 0x44, 0x00,
2109 0x00, 0x00, 0x22, 0x00,
2110 0x00, 0x00, 0x11, 0x00,
2111 0xEE, 0xEE, 0xEE, 0x00,
2112 0xDD, 0xDD, 0xDD, 0x00,
2113 0xBB, 0xBB, 0xBB, 0x00,
2114 0xAA, 0xAA, 0xAA, 0x00,
2115 0x88, 0x88, 0x88, 0x00,
2116 0x77, 0x77, 0x77, 0x00,
2117 0x55, 0x55, 0x55, 0x00,
2118 0x44, 0x44, 0x44, 0x00,
2119 0x22, 0x22, 0x22, 0x00,
2120 0x11, 0x11, 0x11, 0x00,
2121 0x00, 0x00, 0x00, 0x00
2122];
2123
58309c73
KS
2124#[cfg(test)]
2125mod test {
2126 use super::*;
2127 use std::fs::File;
2128
2129 #[test]
2130 fn test_mov_demux() {
886cde48 2131 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/cubes.mov
58309c73
KS
2132 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2133 let mut fr = FileReader::new_read(&mut file);
2134 let mut br = ByteReader::new(&mut fr);
2135 let mut dmx = MOVDemuxer::new(&mut br);
2136 let mut sm = StreamManager::new();
2137 let mut si = SeekIndex::new();
2138 dmx.open(&mut sm, &mut si).unwrap();
2139
2140 loop {
2141 let pktres = dmx.get_frame(&mut sm);
2142 if let Err(e) = pktres {
2143 if e == DemuxerError::EOF { break; }
2144 panic!("error");
2145 }
2146 let pkt = pktres.unwrap();
2147 println!("Got {}", pkt);
2148 }
2149 }
0a0456a8
KS
2150
2151 #[test]
2152 fn test_dash_demux() {
886cde48 2153 // sample: a stream downloaded with youtube-dl
0a0456a8
KS
2154 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2155 let mut fr = FileReader::new_read(&mut file);
2156 let mut br = ByteReader::new(&mut fr);
2157 let mut dmx = MOVDemuxer::new(&mut br);
2158 let mut sm = StreamManager::new();
2159 let mut si = SeekIndex::new();
2160 dmx.open(&mut sm, &mut si).unwrap();
2161
2162 loop {
2163 let pktres = dmx.get_frame(&mut sm);
2164 if let Err(e) = pktres {
2165 if e == DemuxerError::EOF { break; }
2166 panic!("error");
2167 }
2168 let pkt = pktres.unwrap();
2169 println!("Got {}", pkt);
2170 }
2171 }
88fd1059
KS
2172
2173 #[test]
2174 fn test_macbinary_demux() {
2175 // sample from King's Quest VI Macintosh edition
2176 let mut file = File::open("assets/QT/Halfdome.bin").unwrap();
2177 let mut fr = FileReader::new_read(&mut file);
2178 let mut br = ByteReader::new(&mut fr);
2179 let mut dmx = MOVDemuxer::new_macbinary(&mut br);
2180 let mut sm = StreamManager::new();
2181 let mut si = SeekIndex::new();
2182 dmx.open(&mut sm, &mut si).unwrap();
2183
2184 loop {
2185 let pktres = dmx.get_frame(&mut sm);
2186 if let Err(e) = pktres {
2187 if e == DemuxerError::EOF { break; }
2188 panic!("error");
2189 }
2190 let pkt = pktres.unwrap();
2191 println!("Got {}", pkt);
2192 }
2193 }
58309c73 2194}