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