]> git.nihav.org Git - nihav.git/blame - nihav-commonfmt/src/demuxers/mov.rs
switch some TableCodebookDescReader use cases to closures
[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
e6aaad5c 576#[allow(clippy::neg_cmp_op_on_partial_ord)]
58309c73
KS
577fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
578 const KNOWN_STSD_SIZE: u64 = 24;
579 validate!(size >= KNOWN_STSD_SIZE);
580 let start_pos = br.tell();
581 let version = br.read_byte()?;
582 validate!(version == 0);
583 let _flags = br.read_u24be()?;
584 let entries = br.read_u32be()?;
585 validate!(entries > 0);
61cab15b 586 let esize = u64::from(br.read_u32be()?);
58309c73
KS
587 validate!(esize + 8 <= size);
588 let mut fcc = [0u8; 4];
589 br.read_buf(&mut fcc)?;
590 br.read_skip(6)?;
591 let _data_ref = br.read_u16be()?;
592
593 track.fcc = fcc;
594
595 let codec_info;
596 match track.stream_type {
597 StreamType::Video => {
598 let _ver = br.read_u16be()?;
599 let _revision = br.read_u16le()?;
600 let _vendor = br.read_u32be()?;
601 let _temp_quality = br.read_u32be()?;
602 let _spat_quality = br.read_u32be()?;
603 let width = br.read_u16be()? as usize;
604 let height = br.read_u16be()? as usize;
605 let _hor_res = br.read_u32be()?;
606 let _vert_res = br.read_u32be()?;
607 let data_size = br.read_u32be()?;
608 validate!(data_size == 0);
609 let _frame_count = br.read_u16be()? as usize;
610 let _cname_len = br.read_byte()? as usize;
611 br.read_skip(31)?; // actual compressor name
612 let depth = br.read_u16be()?;
613 let ctable_id = br.read_u16be()?;
8019c866
KS
614 let grayscale = depth > 0x20 || depth == 1;
615 let depth = if grayscale { depth & 0x1F } else { depth };
58309c73 616 if ctable_id == 0 {
00333698 617 let max_pal_size = start_pos + size - br.tell();
88fd1059
KS
618 if depth <= 8 {
619 let mut pal = [0; 1024];
620 read_palette(br, max_pal_size, &mut pal)?;
621 track.pal = Some(Arc::new(pal));
622 } else {
623 br.read_skip(max_pal_size as usize)?;
624 }
8019c866 625 } else if (depth <= 8) && !grayscale {
2736c15a
KS
626 match depth & 0x1F {
627 2 => {
628 let mut pal = [0; 1024];
e6aaad5c 629 pal[..4 * 4].copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
2736c15a
KS
630 track.pal = Some(Arc::new(pal));
631 },
632 4 => {
633 let mut pal = [0; 1024];
e6aaad5c 634 pal[..16 * 4].copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
2736c15a
KS
635 track.pal = Some(Arc::new(pal));
636 },
637 8 => {
638 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
639 },
640 _ => {},
641 };
2949bcfa 642 } else if grayscale && ctable_id != 0xFFFF {
2736c15a
KS
643 let mut pal = [0; 1024];
644 let cdepth = depth & 0x1F;
645 let size = 1 << cdepth;
646 for i in 0..size {
8019c866 647 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
2736c15a
KS
648 let mut off = 8 - cdepth;
649 while off >= cdepth {
650 clr |= clr >> (8 - off);
651 off -= cdepth;
652 }
653 if off > 0 {
654 clr |= clr >> (8 - off);
655 }
656 pal[i * 4] = clr;
657 pal[i * 4 + 1] = clr;
658 pal[i * 4 + 2] = clr;
659 }
660 track.pal = Some(Arc::new(pal));
58309c73
KS
661 }
662// todo other atoms, put as extradata
663 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
664 name
665 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
666 name
667 } else {
668 "unknown"
669 };
670 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
8019c866
KS
671 let mut vhdr = NAVideoInfo::new(width, height, false, format);
672 vhdr.bits = depth as u8;
b9862e98
KS
673 //skip various common atoms
674 while br.tell() - start_pos + 4 < size {
675 let mut buf = [0u8; 8];
676 br.peek_buf(&mut buf)?;
677 let tsize = read_u32be(&buf).unwrap() as usize;
678 let tag = &buf[4..8];
679 validate!(tsize >= 8);
680 match tag {
681 b"pasp" | b"clap" => {
682 br.read_skip(tsize)?;
683 },
684 _ => break,
685 };
686 }
61cab15b 687 let edata = if br.tell() - start_pos + 4 < size {
61cab15b 688 let edata_size = br.read_u32be()? as usize;
d341f57a
KS
689 validate!(edata_size >= 4);
690 let mut buf = vec![0; edata_size - 4];
58309c73 691 br.read_buf(buf.as_mut_slice())?;
61cab15b
KS
692 Some(buf)
693 } else {
694 None
695 };
58309c73
KS
696 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
697 },
698 StreamType::Audio => {
89b16ac8 699 let sver = br.read_u16be()?;
58309c73
KS
700 let _revision = br.read_u16le()?;
701 let _vendor = br.read_u32be()?;
9559c2c8
KS
702 let mut nchannels = br.read_u16be()?;
703 if sver != 2 {
704 validate!(nchannels <= 64);
705 }
58309c73
KS
706 let sample_size = br.read_u16be()?;
707 validate!(sample_size <= 128);
708 let _compr_id = br.read_u16be()?;
709 let packet_size = br.read_u16be()? as usize;
710 validate!(packet_size == 0);
9559c2c8
KS
711 let mut sample_rate = br.read_u32be()? >> 16;
712 if sver != 2 {
713 validate!(sample_rate > 0);
714 }
58309c73
KS
715 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
716 name
717 } 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]))) {
718 name
719 } else {
720 "unknown"
721 };
e5d3fef5
KS
722 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
723 if &fcc == b"raw " && sample_size == 8 {
724 soniton.signed = false;
725 }
511f5e91 726 let mut block_align = 1;
9559c2c8
KS
727 match sver {
728 1 => {
729 let samples_per_packet = br.read_u32be()?;
730 let _bytes_per_packet = br.read_u32be()?;
731 let bytes_per_frame = br.read_u32be()?;
732 let _bytes_per_sample = br.read_u32be()?;
733 track.bsize = bytes_per_frame as usize;
734 track.frame_samples = samples_per_packet as usize;
735 track.tb_num = samples_per_packet;
511f5e91 736 block_align = bytes_per_frame as usize;
9559c2c8
KS
737 },
738 2 => {
739 br.read_u32be()?; // some size
740 let srate = br.read_f64be()?;
741 validate!(srate > 1.0);
742 sample_rate = srate as u32;
743 let channels = br.read_u32be()?;
744 validate!(channels > 0 && channels < 255);
745 nchannels = channels as u16;
746 br.read_u32be()?; // always 0x7F000000
747 let _bits_per_csample = br.read_u32be()?;
748 let _codec_flags = br.read_u32be()?;
749 let bytes_per_frame = br.read_u32be()?;
750 let samples_per_packet = br.read_u32be()?;
751 track.bsize = bytes_per_frame as usize;
752 track.frame_samples = samples_per_packet as usize;
753 track.tb_num = samples_per_packet;
754 },
755 _ => {
756 track.bsize = (sample_size / 8) as usize;
757 },
758 };
de3f3f00
KS
759 if track.tb_den <= 1 {
760 track.tb_den = sample_rate;
761 }
6f263099 762 track.raw_audio = matches!(&fcc,
7afec34d
KS
763 b"NONE" | b"raw " | b"twos" | b"sowt" |
764 b"in24" | b"in32" | b"fl32" | b"fl64" |
765 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
766 b"alaw" | b"ulaw" |
6f263099 767 b"MAC3" | b"MAC6");
9559c2c8 768 let ahdr = NAAudioInfo::new(sample_rate, nchannels as u8, soniton, block_align);
89b16ac8 769 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
770 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
771 track.channels = nchannels as usize;
772 track.bits = sample_size as usize;
773 },
774 StreamType::None => {
775 return Err(DemuxerError::InvalidData);
776 },
777 _ => {
778//todo put it all into extradata
779 let edata = None;
780 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
781 },
782 };
783 let read_size = br.tell() - start_pos;
784 validate!(read_size <= size);
7afec34d 785 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
786 track.stsd_found = true;
787 Ok(read_size)
788}
789
bbbf86dd 790fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
d4809976 791 validate!(size >= 8);
bbbf86dd
KS
792 let start_pos = br.tell();
793 let version = br.read_byte()?;
794 validate!(version == 0);
795 let _flags = br.read_u24be()?;
796 let entries = br.read_u32be()? as usize;
797 validate!(entries as u64 <= (size - 8) / 8);
d4809976
KS
798 if entries == 0 {
799 } else if entries == 1 {
bbbf86dd
KS
800 let _count = br.read_u32be()?;
801 let tb_num = br.read_u32be()?;
4e7deeda 802 validate!(tb_num != 0);
0a0456a8 803 track.rescale(tb_num);
bbbf86dd 804 } else {
37952415 805 track.time_to_sample.clear();
bbbf86dd
KS
806 track.time_to_sample.reserve(entries);
807 for _ in 0..entries {
808 let count = br.read_u32be()?;
809 let mult = br.read_u32be()?;
810 track.time_to_sample.push((count, mult));
811 }
812 }
813 let read_size = br.tell() - start_pos;
814 validate!(read_size <= size);
815 Ok(read_size)
816}
817
58309c73
KS
818fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
819 let version = br.read_byte()?;
820 validate!(version == 0);
821 let _flags = br.read_u24be()?;
822 let entries = br.read_u32be()? as usize;
823 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
824 validate!((entries * 4 + 8) as u64 == size);
825 track.keyframes = Vec::with_capacity(entries);
826 let mut last_sample_no = 0;
827 for _ in 0..entries {
828 let sample_no = br.read_u32be()?;
829 validate!(sample_no > last_sample_no);
830 track.keyframes.push(sample_no);
831 last_sample_no = sample_no;
832 }
833 Ok(size)
834}
835
836fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
837 let version = br.read_byte()?;
838 validate!(version == 0);
839 let _flags = br.read_u24be()?;
840 let entries = br.read_u32be()? as usize;
841 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
842 validate!((entries * 12 + 8) as u64 == size);
843 track.sample_map = Vec::with_capacity(entries);
844 let mut last_sample_no = 0;
845 for _i in 0..entries {
846 let sample_no = br.read_u32be()?;
847 validate!(sample_no > last_sample_no);
848 let nsamples = br.read_u32be()?;
849 let _sample_desc = br.read_u32be()?;
850 track.sample_map.push((sample_no, nsamples));
851 last_sample_no = sample_no;
852 }
853 Ok(size)
854}
855
856fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
857 let version = br.read_byte()?;
858 validate!(version == 0);
859 let _flags = br.read_u24be()?;
860 let sample_size = br.read_u32be()?;
861 if sample_size != 0 {
862 track.sample_size = sample_size;
9efec4ed
KS
863 if track.sample_size != 1 || track.bsize == 0 {
864 track.bsize = sample_size as usize;
865 }
58309c73
KS
866 Ok(8)
867 } else {
868 let entries = br.read_u32be()? as usize;
869 validate!((entries * 4 + 12) as u64 == size);
870 track.chunk_sizes = Vec::with_capacity(entries);
871 for _ in 0..entries {
872 let sample_size = br.read_u32be()?;
873 track.chunk_sizes.push(sample_size);
874 }
875 Ok(size)
876 }
877}
878
879fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
880 let version = br.read_byte()?;
881 validate!(version == 0);
882 let _flags = br.read_u24be()?;
883 let entries = br.read_u32be()? as usize;
884 validate!((entries * 4 + 8) as u64 == size);
885 track.chunk_offsets = Vec::with_capacity(entries);
886 for _i in 0..entries {
887 let sample_offset = br.read_u32be()?;
888 track.chunk_offsets.push(u64::from(sample_offset));
889 }
890 Ok(size)
891}
892
4e7deeda
KS
893fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
894 validate!(size >= 8);
895 let version = br.read_byte()?;
896 let _flags = br.read_u24be()?;
897 if version > 1 {
898 return Err(DemuxerError::NotImplemented);
899 }
900 let entries = br.read_u32be()? as usize;
901 track.ctts_version = version;
902 track.ctts_map.resize(entries);
903 match version {
904 0 | 1 => {
905 validate!(size == (entries as u64) * 8 + 8);
906 for _ in 0..entries {
907 let samp_count = br.read_u32be()?;
908 let samp_offset = br.read_u32be()?;
909 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
910 }
911 },
912 _ => unreachable!(),
913 };
914 track.ctts_map.reset();
915
916 Ok(size)
917}
918
0a0456a8
KS
919const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
920 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
921 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
922 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
923 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
924 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
925 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
926 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
927 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
928 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
929];
930
931fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
932 validate!(size >= 8);
933 let start = br.tell();
934 let _version = br.read_byte()?;
935 let flags = br.read_u24be()?;
936 let _track_id = br.read_u32be()?;
937 if (flags & 0x000001) != 0 {
938 let base_offset = br.read_u64be()?;
939 track.moof_off = base_offset;
940 }
941 if (flags & 0x000002) != 0 {
942 let _sample_description_index = br.read_u32be()?;
943 }
944 if (flags & 0x000008) != 0 {
945 let default_sample_duration = br.read_u32be()?;
946 if track.tb_div == 1 {
947 track.rescale(default_sample_duration);
948 }
949 }
950 if (flags & 0x000010) != 0 {
951 let _default_sample_size = br.read_u32be()?;
952 }
953 if (flags & 0x000020) != 0 {
954 let _default_sample_flags = br.read_u32be()?;
955 }
956 if (flags & 0x010000) != 0 {
957 }
958 /*if (flags & 0x020000) != 0 { // base offset is moof start
959 }*/
960 Ok(br.tell() - start)
961}
962
963fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
964 validate!(size >= 8);
965 let version = br.read_byte()?;
966 let flags = br.read_u24be()?;
967 let data_off_present = (flags & 0x000001) != 0;
968 let first_sample_flags = (flags & 0x000004) != 0;
969 let sample_duration_present = (flags & 0x000100) != 0;
970 let sample_size_present = (flags & 0x000200) != 0;
971 let sample_flags_present = (flags & 0x000400) != 0;
972 let sample_ct_off_present = (flags & 0x000800) != 0;
973
974 let sample_count = br.read_u32be()? as usize;
975
976 let mut hdr_size = 8;
977 let mut arr_size = 0;
978 if data_off_present {
979 hdr_size += 4;
980 }
981 if first_sample_flags {
982 hdr_size += 4;
983 }
984 if sample_duration_present {
985 arr_size += 4;
986 }
987 if sample_size_present {
988 arr_size += 4;
989 }
990 if sample_flags_present {
991 arr_size += 4;
992 }
993 if sample_ct_off_present {
994 arr_size += 4;
995 }
996 validate!(size == hdr_size + arr_size * (sample_count as u64));
997
998 let mut data_off = if data_off_present {
999 let off = br.read_u32be()? as i32;
1000 let new_off = (track.moof_off as i64) + i64::from(off);
1001 validate!(new_off > 0);
1002 new_off as u64
1003 } else {
1004 track.moof_off
1005 };
1006 if first_sample_flags {
1007 let _flags = br.read_u32be()?;
1008 }
1009
1010 if sample_size_present {
1011 track.chunk_sizes.reserve(sample_count);
1012 track.chunk_offsets.reserve(sample_count);
1013 }
1014
1015 if sample_ct_off_present {
1016 if track.ctts_version != version {
1017 track.ctts_version = version;
1018 }
1019 track.ctts_map.reserve(sample_count);
1020 }
1021
6bb26927
KS
1022 if track.chunk_offsets.len() < (std::u32::MAX as usize) {
1023 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
1024 }
0a0456a8
KS
1025 for _ in 0..sample_count {
1026 if sample_duration_present {
1027 let _duration = br.read_u32be()?;
1028 }
1029 if sample_size_present {
1030 let ssize = br.read_u32be()?;
1031 track.chunk_sizes.push(ssize);
1032 track.chunk_offsets.push(data_off);
1033 data_off += u64::from(ssize);
1034 }
1035 if sample_flags_present {
1036 let _flags = br.read_u32be()?;
1037 }
1038 if sample_ct_off_present {
1039 let samp_offset = br.read_u32be()?;
1040 if version == 0 {
1041 track.ctts_map.add(1, samp_offset / track.tb_div);
1042 } else {
1043 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1044 }
1045 }
1046 }
1047
1048 Ok(size)
1049}
1050
58309c73
KS
1051struct MOVDemuxer<'a> {
1052 src: &'a mut ByteReader<'a>,
1053 depth: usize,
1054 mdat_pos: u64,
1055 mdat_size: u64,
1056 tracks: Vec<Track>,
1057 cur_track: usize,
1058 tb_den: u32,
1059 duration: u32,
58cd51fa 1060 pal: Option<Arc<[u8; 1024]>>,
650d7bfb 1061
0a0456a8
KS
1062 moof_off: u64,
1063
650d7bfb 1064 print_chunks: bool,
88fd1059
KS
1065
1066 macbinary: bool,
58309c73
KS
1067}
1068
1069struct Track {
1070 track_id: u32,
1071 track_str_id: usize,
1072 track_no: u32,
bbbf86dd 1073 tb_num: u32,
58309c73 1074 tb_den: u32,
4e7deeda 1075 tb_div: u32,
7afec34d
KS
1076 raw_audio: bool,
1077 raw_apos: u64,
a480a0de 1078 duration: u32,
58309c73
KS
1079 depth: u8,
1080 tkhd_found: bool,
1081 stsd_found: bool,
1082 stream_type: StreamType,
1083 width: usize,
1084 height: usize,
1085 channels: usize,
1086 bits: usize,
9efec4ed 1087 bsize: usize,
58309c73
KS
1088 fcc: [u8; 4],
1089 keyframes: Vec<u32>,
1090 chunk_sizes: Vec<u32>,
1091 chunk_offsets: Vec<u64>,
bbbf86dd 1092 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
1093 sample_map: Vec<(u32, u32)>,
1094 sample_size: u32,
b0e12d42 1095 frame_samples: usize,
4e7deeda
KS
1096 ctts_map: RLESearcher<u32>,
1097 ctts_version: u8,
58309c73
KS
1098 stream: Option<NAStream>,
1099 cur_chunk: usize,
1100 cur_sample: usize,
07972bf3 1101 cur_ts: Option<u64>,
58309c73
KS
1102 samples_left: usize,
1103 last_offset: u64,
58cd51fa 1104 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 1105 timesearch: TimeSearcher,
650d7bfb 1106
0a0456a8
KS
1107 moof_off: u64,
1108
650d7bfb 1109 print_chunks: bool,
bbbf86dd
KS
1110}
1111
1112#[derive(Default)]
1113struct TimeSearcher {
1114 idx: usize,
1115 base: u64,
1116 sbase: u32,
1117 cur_len: u32,
1118 cur_mul: u32,
1119}
1120
1121impl TimeSearcher {
1122 fn new() -> Self { Self::default() }
1123 fn reset(&mut self) {
1124 *self = Self::default();
1125 }
b7c882c1 1126 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
bbbf86dd
KS
1127 if tts.is_empty() {
1128 u64::from(sample)
1129 } else if sample >= self.sbase {
1130 let mut sample = sample - self.sbase;
1131 if self.idx == 0 {
1132 let (cur_len, cur_mul) = tts[0];
1133 self.cur_len = cur_len;
1134 self.cur_mul = cur_mul;
1135 self.idx += 1;
1136 }
1137 while self.idx < tts.len() && sample > self.cur_len {
1138 sample -= self.cur_len;
1139 self.sbase += self.cur_len;
1140 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1141 self.cur_len = tts[self.idx].0;
1142 self.cur_mul = tts[self.idx].1;
1143 self.idx += 1;
1144 }
1145 self.base + u64::from(sample) * u64::from(self.cur_mul)
1146 } else {
1147 self.reset();
1148 self.map_time(sample, tts)
1149 }
1150 }
58309c73
KS
1151}
1152
4e7deeda
KS
1153#[derive(Default)]
1154struct RLESearcher<T> {
1155 array: Vec<(u32, T)>,
1156 idx: usize,
1157 start: u64,
1158 next: u64,
1159}
1160
1161impl<T:Default+Copy> RLESearcher<T> {
1162 fn new() -> Self { Self::default() }
1163 fn resize(&mut self, size: usize) {
37952415 1164 self.array.clear();
4e7deeda
KS
1165 self.array.reserve(size);
1166 }
0a0456a8
KS
1167 fn reserve(&mut self, size: usize) {
1168 self.array.reserve(size);
1169 }
4e7deeda
KS
1170 fn add(&mut self, len: u32, val: T) {
1171 self.array.push((len, val));
1172 }
1173 fn reset(&mut self) {
1174 self.start = 0;
1175 if !self.array.is_empty() {
1176 self.idx = 0;
1177 self.next = u64::from(self.array[0].0);
1178 } else {
1179 self.idx = self.array.len();
1180 self.next = 0;
1181 }
1182 }
1183 fn map(&mut self, sample: u64) -> Option<T> {
1184 if sample < self.start {
1185 self.reset();
1186 }
1187 if self.idx < self.array.len() {
1188 if sample < self.next {
1189 Some(self.array[self.idx].1)
1190 } else {
1191 while (self.idx < self.array.len()) && (sample >= self.next) {
1192 self.start = self.next;
1193 self.idx += 1;
1194 if self.idx < self.array.len() {
1195 self.next += u64::from(self.array[self.idx].0);
1196 }
1197 }
1198 if self.idx < self.array.len() {
1199 Some(self.array[self.idx].1)
1200 } else {
1201 None
1202 }
1203 }
1204 } else {
1205 None
1206 }
1207 }
1208}
1209
58309c73
KS
1210impl Track {
1211 fn new(track_no: u32, tb_den: u32) -> Self {
1212 Self {
1213 tkhd_found: false,
1214 stsd_found: false,
1215 track_id: 0,
1216 track_str_id: 0,
1217 track_no,
bbbf86dd 1218 tb_num: 1,
58309c73 1219 tb_den,
4e7deeda 1220 tb_div: 1,
7afec34d
KS
1221 raw_audio: false,
1222 raw_apos: 0,
a480a0de 1223 duration: 0,
58309c73
KS
1224 stream_type: StreamType::None,
1225 width: 0,
1226 height: 0,
1227 channels: 0,
1228 bits: 0,
9efec4ed 1229 bsize: 0,
58309c73
KS
1230 fcc: [0; 4],
1231 keyframes: Vec::new(),
1232 chunk_sizes: Vec::new(),
1233 chunk_offsets: Vec::new(),
bbbf86dd 1234 time_to_sample: Vec::new(),
58309c73
KS
1235 sample_map: Vec::new(),
1236 sample_size: 0,
b0e12d42 1237 frame_samples: 0,
4e7deeda
KS
1238 ctts_map: RLESearcher::new(),
1239 ctts_version: 0,
58309c73
KS
1240 stream: None,
1241 depth: 0,
1242 cur_chunk: 0,
1243 cur_sample: 0,
07972bf3 1244 cur_ts: None,
58309c73
KS
1245 samples_left: 0,
1246 last_offset: 0,
58cd51fa 1247 pal: None,
bbbf86dd 1248 timesearch: TimeSearcher::new(),
650d7bfb 1249
0a0456a8
KS
1250 moof_off: 0,
1251
650d7bfb 1252 print_chunks: false,
58309c73
KS
1253 }
1254 }
1255 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1256 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1257 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1258 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
0a0456a8
KS
1259 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1260 fn rescale(&mut self, tb_num: u32) {
1261 self.tb_div = tb_num;
1262 if let Some(ref mut stream) = self.stream {
1263 let tb_den = stream.tb_den;
1264 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1265 stream.duration /= u64::from(self.tb_div);
1266 stream.tb_num = tb_num;
1267 stream.tb_den = tb_den;
1268 self.tb_num = tb_num;
1269 self.tb_den = tb_den;
1270 self.duration /= self.tb_div;
1271 }
1272 }
58309c73 1273 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 1274 if !self.keyframes.is_empty() {
58309c73
KS
1275 seek_index.mode = SeekIndexMode::Present;
1276 }
bbbf86dd 1277 let mut tsearch = TimeSearcher::new();
58309c73 1278 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
1279 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1280 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
e6aaad5c 1281 seek_index.add_entry(self.track_no, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
1282 }
1283 }
1284 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1285 if nsamp == 0 {
9efec4ed 1286 self.bsize
58309c73
KS
1287 } else {
1288 match &self.fcc {
1289 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1290 (nsamp * self.bits * self.channels + 7) >> 3
1291 },
1292 b"ima4" => {
1293 let nblocks = (nsamp + 63) >> 6;
1294 nblocks * 34 * self.channels
1295 },
1296 b"MAC3" => {
1297 (nsamp + 5) / 6 * 2 * self.channels
1298 },
1299 b"MAC6" => {
1300 (nsamp + 5) / 6 * self.channels
1301 },
1302 b"in24" => nsamp * 3 * self.channels,
1303 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1304 b"fl64" => nsamp * 8 * self.channels,
1305 b"ulaw" | b"alaw" => nsamp,
1306 b"ms\x00\x02" => { //MS ADPCM
1307 ((nsamp - 1) / 2 + 7) * self.channels
1308 },
1309 b"ms\x00\x21" => { //IMA ADPCM
1310 (nsamp / 2 + 4) * self.channels
1311 },
9efec4ed 1312 _ => self.bsize,
58309c73
KS
1313 }
1314 }
1315 }
1316 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 1317 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
4e7deeda
KS
1318 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1319 let dts = match self.ctts_version {
1320 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1321 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1322 _ => unimplemented!(),
1323 };
1324 if (dts as i64) < 0 {
1325 None
1326 } else {
1327 Some(dts)
1328 }
1329 } else {
eade06ed 1330 Some(pts_val)
4e7deeda
KS
1331 };
1332 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
58309c73
KS
1333 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1334 if self.cur_sample >= self.chunk_sizes.len() {
1335 return None;
1336 }
1337 let offset = self.chunk_offsets[self.cur_sample];
1338 let size = self.chunk_sizes[self.cur_sample] as usize;
1339 self.cur_sample += 1;
1340 Some((pts, offset, size))
1341 } else {
1342 if self.samples_left == 0 {
1343 if self.cur_chunk >= self.chunk_offsets.len() {
1344 return None;
1345 }
1346 for (idx, samples) in self.sample_map.iter() {
1347 if *idx as usize <= self.cur_chunk + 1 {
1348 self.samples_left = *samples as usize;
1349 } else {
1350 break;
1351 }
1352 }
1353 self.last_offset = self.chunk_offsets[self.cur_chunk];
1354 self.cur_chunk += 1;
1355 }
1356 let offset = self.last_offset;
1357 let size = self.get_size(self.cur_sample);
1358 self.last_offset += size as u64;
1359 if self.stream_type == StreamType::Video {
1360 self.samples_left -= 1;
d940f0c2
KS
1361 } else if self.frame_samples != 0 && self.bsize != 0 {
1362 let nblocks = size / self.bsize;
7afec34d
KS
1363 if self.raw_audio {
1364 pts.pts = Some(self.raw_apos);
1365 pts.duration = Some(nblocks as u64);
1366 self.raw_apos += nblocks as u64;
1367 }
d940f0c2
KS
1368 if nblocks > 0 {
1369 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1370 self.samples_left -= consumed;
1371 } else {
1372 self.samples_left = 0;
1373 }
7afec34d
KS
1374 } else if !self.raw_audio {
1375 self.samples_left -= 1;
58309c73 1376 } else {
7afec34d
KS
1377 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1378 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1379 let cur_size = self.calculate_chunk_size(self.samples_left);
1380 let add_off = (size - cur_size) as u64;
1381 let dsize = cur_size.min(max_size);
1382 if self.samples_left >= BLOCK_SAMPLES {
1383 self.cur_sample += BLOCK_SAMPLES;
1384 self.samples_left -= BLOCK_SAMPLES;
1385 self.last_offset -= size as u64;
1386 } else {
1387 self.cur_sample += self.samples_left;
1388 self.samples_left = 0;
1389 }
1390 return Some((pts, offset + add_off, dsize));
58309c73
KS
1391 }
1392 self.cur_sample += 1;
1393 Some((pts, offset, size))
1394 }
1395 }
1396 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1397 if !self.chunk_sizes.is_empty() {
58309c73 1398 self.chunk_sizes[sample_no] as usize
61cab15b 1399 } else if !self.sample_map.is_empty() {
58309c73
KS
1400 let mut nsamp = 0;
1401 for (idx, samples) in self.sample_map.iter() {
1402 if *idx as usize <= self.cur_chunk {
1403 nsamp = *samples;
1404 } else {
1405 break;
1406 }
1407 }
1408 self.calculate_chunk_size(nsamp as usize)
1409 } else {
9efec4ed 1410 self.bsize
58309c73
KS
1411 }
1412 }
d9bf7e74 1413 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<u64> {
58309c73
KS
1414 self.cur_sample = pts as usize;
1415 self.samples_left = 0;
07972bf3 1416 self.cur_ts = None;
58309c73 1417 if self.stream_type == StreamType::Audio {
7afec34d
KS
1418 if let NATimePoint::Milliseconds(ms) = tpoint {
1419 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1420 if self.raw_audio {
1421 if self.frame_samples != 0 {
1422 self.raw_apos = exp_pts / (self.frame_samples as u64);
1423 let mut apos = 0;
1424 self.cur_sample = 0;
1425 self.cur_chunk = 0;
1426 let mut cmap = self.sample_map.iter();
1427 let mut cur_samps = 0;
1428 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1429 loop {
1430 if self.cur_chunk + 1 == next_idx as usize {
1431 self.samples_left = cur_samps;
1432 cur_samps = next_samples as usize;
1433 if let Some((new_idx, new_samples)) = cmap.next() {
1434 next_idx = *new_idx;
1435 next_samples = *new_samples;
1436 }
1437 }
1438 self.raw_apos = apos;
1439 apos += (cur_samps / self.frame_samples) as u64;
ba8718ff
KS
1440 if apos > exp_pts && (cur_samps == self.frame_samples || apos > exp_pts + 1) {
1441 if self.cur_chunk >= self.chunk_offsets.len() {
1442 return Err(DemuxerError::SeekError);
7afec34d 1443 }
ba8718ff
KS
1444 self.last_offset = self.chunk_offsets[self.cur_chunk];
1445 break;
7afec34d
KS
1446 }
1447 self.cur_chunk += 1;
1448 }
1449 self.samples_left = cur_samps;
1450 self.cur_chunk += 1;
1451 } else {
1452 self.raw_apos = exp_pts;
1453 self.cur_sample = exp_pts as usize;
1454 let mut csamp = 0;
1455 self.cur_chunk = 0;
1456 let mut cmap = self.sample_map.iter();
1457 let mut cur_samps = 0;
1458 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1459 loop {
1460 if self.cur_chunk + 1 == next_idx as usize {
1461 self.samples_left = cur_samps;
1462 cur_samps = next_samples as usize;
1463 if let Some((new_idx, new_samples)) = cmap.next() {
1464 next_idx = *new_idx;
1465 next_samples = *new_samples;
1466 }
1467 }
1468 csamp += cur_samps;
1469 if csamp > self.cur_sample {
1470 if self.cur_chunk >= self.chunk_offsets.len() {
1471 return Err(DemuxerError::SeekError);
1472 }
1473 self.last_offset = self.chunk_offsets[self.cur_chunk];
1474 break;
1475 }
1476 self.cur_chunk += 1;
1477 }
1478 self.samples_left = csamp - self.cur_sample;
1479 self.cur_chunk += 1;
1480 }
c6432d30
KS
1481 } else if self.chunk_offsets.len() == self.chunk_sizes.len() && self.duration != 0 {
1482 let new_sample = (self.chunk_sizes.len() as u64 * exp_pts / u64::from(self.duration)) as usize;
1483 self.cur_sample = new_sample;
7afec34d 1484 self.cur_chunk = self.cur_sample;
5317ee9c 1485 } else {
de82c821
KS
1486 if !self.time_to_sample.is_empty() {
1487 let mut remaining = exp_pts;
1488 let mut abs_csamp = 0;
1489 for &(count, scount) in self.time_to_sample.iter() {
1490 let count = u64::from(count);
1491 let scount = u64::from(scount);
1492 let nblk = remaining / scount;
1493 if nblk < count {
1494 abs_csamp += nblk;
1495 break;
1496 }
1497 remaining -= count * scount;
1498 abs_csamp += count;
1499 }
1500 self.cur_sample = abs_csamp as usize;
1501 } else {
1502 self.cur_sample = exp_pts as usize;
1503 }
1504 let tgt_sample = self.cur_sample;
5317ee9c
KS
1505 let mut csamp = 0;
1506 self.cur_chunk = 0;
1507 let mut cmap = self.sample_map.iter();
1508 let mut cur_samps = 0;
1509 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1510 loop {
1511 if self.cur_chunk + 1 == next_idx as usize {
1512 self.samples_left = cur_samps;
1513 cur_samps = next_samples as usize;
1514 if let Some((new_idx, new_samples)) = cmap.next() {
1515 next_idx = *new_idx;
1516 next_samples = *new_samples;
1517 }
1518 }
1519 csamp += cur_samps;
1520 if csamp > self.cur_sample {
1521 if self.cur_chunk >= self.chunk_offsets.len() {
a970b211
KS
1522 self.cur_sample = csamp - cur_samps;
1523 self.samples_left = 0;
1524 self.cur_sample = csamp;
5317ee9c
KS
1525 return Err(DemuxerError::SeekError);
1526 }
1527 self.last_offset = self.chunk_offsets[self.cur_chunk];
1528 break;
1529 }
1530 self.cur_chunk += 1;
1531 }
1532 self.cur_sample = csamp - cur_samps;
1533 self.samples_left = cur_samps;
1534 self.last_offset = self.chunk_offsets[self.cur_chunk];
1535 self.cur_chunk += 1;
de82c821
KS
1536
1537 // try to refine sample position
1538 if self.chunk_sizes.len() > self.chunk_offsets.len() {
1539 for i in self.cur_sample..tgt_sample {
1540 self.cur_sample += 1;
1541 self.samples_left -= 1;
1542 self.last_offset += u64::from(self.chunk_sizes[i]);
1543 }
1544 }
7afec34d
KS
1545 }
1546 } else {
1547 self.cur_chunk = self.cur_sample;
1548 }
61cab15b 1549 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1550 let mut csamp = 0;
1551 self.cur_chunk = 0;
1552 let mut cmap = self.sample_map.iter();
1553 let mut cur_samps = 0;
1554 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1555 loop {
bbbf86dd 1556 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1557 self.samples_left = cur_samps;
1558 cur_samps = next_samples as usize;
1559 if let Some((new_idx, new_samples)) = cmap.next() {
1560 next_idx = *new_idx;
1561 next_samples = *new_samples;
1562 }
1563 }
1564 csamp += cur_samps;
1565 if csamp >= self.cur_sample {
7afec34d
KS
1566 if self.cur_chunk >= self.chunk_offsets.len() {
1567 return Err(DemuxerError::SeekError);
1568 }
58309c73
KS
1569 self.last_offset = self.chunk_offsets[self.cur_chunk];
1570 break;
1571 }
1572 self.cur_chunk += 1;
1573 }
1574 csamp -= cur_samps;
bbbf86dd 1575 for sample_no in csamp..self.cur_sample {
58309c73
KS
1576 self.last_offset += self.get_size(sample_no) as u64;
1577 }
bbbf86dd
KS
1578 self.samples_left = csamp + cur_samps - self.cur_sample;
1579 self.cur_chunk += 1;
58309c73 1580 }
d9bf7e74
KS
1581 let cur_pts = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1582 let cur_time = NATimeInfo::ts_to_time(cur_pts, 1000, self.tb_num, self.tb_den);
1583 Ok(cur_time)
58309c73
KS
1584 }
1585}
1586
07972bf3
KS
1587fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1588 if let Some(cpts) = pts.get_pts() {
1589 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1590 track.cur_ts = Some(ts);
1591 } else {
1592 track.cur_ts = None;
1593 }
817e4872
KS
1594 let stream = strmgr.get_stream(track.track_str_id);
1595 if stream.is_none() { return Err(DemuxerError::InvalidData); }
1596 let stream = stream.unwrap();
07972bf3
KS
1597 src.seek(SeekFrom::Start(offset))?;
1598 let mut pkt = src.read_packet(stream, pts, false, size)?;
1599 if let Some(ref pal) = track.pal {
1600 let side_data = NASideData::Palette(first, pal.clone());
1601 pkt.add_side_data(side_data);
1602 }
1603 Ok(pkt)
1604}
1605
58309c73
KS
1606impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1607 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
88fd1059
KS
1608 if !self.macbinary {
1609 self.read_root(strmgr)?;
1610 } else {
1611 let ver = self.src.read_byte()?;
1612 validate!(ver == 0);
1613 self.src.read_skip(64)?;
1614 let tag = self.src.read_tag()?;
1615 validate!(&tag == b"MooV");
1616 self.src.read_skip(14)?;
1617 let data_length = self.src.read_u32be()?;
1618 validate!(data_length > 8);
1619 let rsrc_length = self.src.read_u32be()?;
1620 validate!(rsrc_length > 0);
1621 self.src.read_skip(31)?;
1622 let ver = self.src.read_byte()?;
1623 validate!(ver == 0x81);
1624 let ver = self.src.read_byte()?;
1625 validate!(ver == 0x81);
1626 //xxx: maybe check header CRC
1627
1628 let rsrc_start = 0x80 + ((data_length + 0x7F) & !0x7F);
1629 self.src.seek(SeekFrom::Start(rsrc_start.into()))?;
1630 let rsrc_off = self.src.read_u32be()?;
1631 let rsrc_map_off = self.src.read_u32be()?;
1632 let rsrc_size = self.src.read_u32be()?;
1633 let _rsrc_map_size = self.src.read_u32be()?;
1634 validate!(rsrc_off >= 0x10);
1635 validate!(rsrc_map_off >= rsrc_off + rsrc_size);
1636 self.src.seek(SeekFrom::Current(i64::from(rsrc_off - 16)))?;
1637 // I'm too lazy to parse resource map, so let's just iterate over resources for movie header
1638 let end_pos = u64::from(rsrc_start + rsrc_off + rsrc_size);
1639 let mut peek_buf = [0u8; 8];
1640 while self.src.tell() < end_pos {
1641 let cur_size = self.src.read_u32be()?;
1642 validate!(self.src.tell() + u64::from(cur_size) <= end_pos);
1643 if cur_size > 8 {
1644 let rsize = self.src.peek_u32be()?;
1645 if rsize == cur_size {
1646 self.src.peek_buf(&mut peek_buf)?;
1647 if &peek_buf[4..] == b"moov" {
1648 self.src.read_skip(8)?;
1649 self.read_moov(strmgr, rsize.into())?;
1650 self.mdat_pos = 8;
1651 break;
1652 }
1653 }
1654 }
1655 self.src.read_skip(cur_size as usize)?;
1656 }
1657 }
58309c73 1658 validate!(self.mdat_pos > 0);
61cab15b 1659 validate!(!self.tracks.is_empty());
0a0456a8 1660 for track in self.tracks.iter_mut() {
817e4872
KS
1661 let mut strm = None;
1662 std::mem::swap(&mut track.stream, &mut strm);
1663 if let Some(stream) = strm {
0a0456a8
KS
1664 let str_id = strmgr.add_stream(stream).unwrap();
1665 track.track_str_id = str_id;
1666 }
1667 }
88fd1059
KS
1668 if self.macbinary {
1669 // patch data offsets
1670 for track in self.tracks.iter_mut() {
1671 for offset in track.chunk_offsets.iter_mut() {
1672 *offset += 0x80;
1673 }
1674 }
1675 }
58309c73
KS
1676 for track in self.tracks.iter() {
1677 track.fill_seek_index(seek_index);
1678 }
1679 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1680 self.cur_track = 0;
1681 Ok(())
1682 }
1683
1684 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1685 if self.tracks.is_empty() {
58309c73
KS
1686 return Err(DemuxerError::EOF);
1687 }
07972bf3
KS
1688 let mut has_all_time = true;
1689 let mut min_ts = std::u64::MAX;
1690 for trk in self.tracks.iter() {
1691 if let Some(ts) = trk.cur_ts {
1692 min_ts = min_ts.min(ts);
1693 } else {
1694 has_all_time = false;
1695 break;
1696 }
1697 }
1698 if has_all_time {
1699 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1700 if let Some(ts) = track.cur_ts {
1701 if ts == min_ts {
1702 let first = track.cur_sample == 0;
1703 if let Some((pts, offset, size)) = track.get_next_chunk() {
1704 self.cur_track = trk_no + 1;
6f263099 1705 return process_packet(self.src, strmgr, track, pts, offset, size, first);
07972bf3
KS
1706 }
1707 }
1708 }
1709 }
1710 }
1711
58309c73
KS
1712 for _ in 0..self.tracks.len() {
1713 if self.cur_track >= self.tracks.len() {
1714 self.cur_track = 0;
1715 }
1716 let track = &mut self.tracks[self.cur_track];
1717 self.cur_track += 1;
58cd51fa 1718 let first = track.cur_sample == 0;
58309c73 1719 if let Some((pts, offset, size)) = track.get_next_chunk() {
6f263099 1720 return process_packet(self.src, strmgr, track, pts, offset, size, first);
58309c73
KS
1721 }
1722 }
61cab15b 1723 Err(DemuxerError::EOF)
58309c73
KS
1724 }
1725
24d99894 1726 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1727 let ret = seek_index.find_pos(time);
1728 if ret.is_none() {
5317ee9c
KS
1729 if let NATimePoint::Milliseconds(_) = time {
1730 let mut aonly = true;
1731 for track in self.tracks.iter() {
de82c821 1732 if track.stream_type != StreamType::Audio {
5317ee9c
KS
1733 aonly = false;
1734 break;
1735 }
1736 }
1737 if aonly {
1738 for track in self.tracks.iter_mut() {
1739 track.seek(0, time)?;
1740 }
1741 return Ok(());
1742 }
1743 }
58309c73
KS
1744 return Err(DemuxerError::SeekError);
1745 }
1746 let seek_info = ret.unwrap();
5317ee9c
KS
1747 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1748 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
d9bf7e74
KS
1749 let mut vpts = None;
1750 let mut apts = None;
58309c73 1751 for track in self.tracks.iter_mut() {
5317ee9c
KS
1752 let cur_pts = if track.track_id == seek_info.str_id {
1753 seek_info.pts
1754 } else {
1755 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1756 };
d9bf7e74
KS
1757 let actual_time = track.seek(cur_pts, time)?;
1758 match track.stream_type {
1759 StreamType::Video => vpts = Some(actual_time),
1760 StreamType::Audio => apts = Some(actual_time),
1761 _ => {},
1762 };
58309c73 1763 }
d9bf7e74
KS
1764 /* For audio+video stream case when the post-seek actual times differ
1765 by more than half a second try to seek audio to a closer position
1766 to video.
1767 */
1768 if let (true, Some(vtime), Some(atime)) = (self.tracks.len() == 2, vpts, apts) {
1769 if vtime.max(atime) - vtime.min(atime) > 500 && atime != 0 {
1770 for track in self.tracks.iter_mut() {
1771 if track.stream_type == StreamType::Audio {
1772 let new_pts = NATimeInfo::time_to_ts(vtime, 1000, track.tb_num, track.tb_den);
1773 track.seek(new_pts, NATimePoint::Milliseconds(vtime))?;
1774 }
1775 }
1776 }
1777 }
1778
58309c73
KS
1779 Ok(())
1780 }
a480a0de
KS
1781 fn get_duration(&self) -> u64 {
1782 if self.tb_den != 0 {
1783 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1784 } else {
1785 0
1786 }
1787 }
58309c73
KS
1788}
1789
650d7bfb
KS
1790const PRINT_CHUNKS: &str = "print_chunks";
1791
1792const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1793 NAOptionDefinition {
1794 name: PRINT_CHUNKS,
1795 description: "Print parsed file structure",
1796 opt_type: NAOptionDefinitionType::Bool },
1797];
1798
787b8d03 1799impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb 1800 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
b7c882c1 1801 #[allow(clippy::single_match)]
650d7bfb
KS
1802 fn set_options(&mut self, options: &[NAOption]) {
1803 for option in options.iter() {
1804 for opt_def in DEMUXER_OPTIONS.iter() {
1805 if opt_def.check(option).is_ok() {
1806 match (option.name, &option.value) {
1807 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1808 self.print_chunks = *val;
1809 },
1810 _ => {},
1811 }
1812 }
1813 }
1814 }
1815 }
1816 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1817 match name {
1818 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1819 _ => None,
1820 }
1821 }
787b8d03
KS
1822}
1823
58309c73
KS
1824impl<'a> MOVDemuxer<'a> {
1825 fn new(io: &'a mut ByteReader<'a>) -> Self {
88fd1059
KS
1826 Self::new_common(io, false)
1827 }
1828 fn new_macbinary(io: &'a mut ByteReader<'a>) -> Self {
1829 Self::new_common(io, true)
1830 }
1831 fn new_common(io: &'a mut ByteReader<'a>, macbinary: bool) -> Self {
58309c73
KS
1832 MOVDemuxer {
1833 src: io,
1834 depth: 0,
1835 mdat_pos: 0,
1836 mdat_size: 0,
1837 tracks: Vec::with_capacity(2),
1838 cur_track: 0,
1839 tb_den: 0,
1840 duration: 0,
58cd51fa 1841 pal: None,
650d7bfb 1842
0a0456a8
KS
1843 moof_off: 0,
1844
650d7bfb 1845 print_chunks: false,
88fd1059
KS
1846
1847 macbinary,
58309c73
KS
1848 }
1849 }
1850 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1851 self.depth = 0;
1852 while self.src.left() != 0 {
6f263099 1853 let ret = read_chunk_header(self.src);
58309c73
KS
1854 if ret.is_err() { break; }
1855 let (ctype, size) = ret.unwrap();
0a0456a8
KS
1856 if self.print_chunks {
1857 print_cname(ctype, size, self.src.tell(), 0);
1858 }
58309c73
KS
1859 if IGNORED_CHUNKS.contains(&ctype) {
1860 self.src.skip64(size)?;
1861 continue;
1862 }
1863 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1864 let read_size;
6f263099 1865 if let Some(handler) = handler {
58309c73
KS
1866 read_size = (handler.parse)(self, strmgr, size)?;
1867 } else {
1868 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1869 read_size = 0;
1870 }
1871 validate!(read_size <= size);
1872 self.src.skip64(size - read_size)?;
1873 }
1874//todo check if all needed chunks are found
1875 Ok(())
1876 }
1877 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
0a0456a8 1878 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
58309c73
KS
1879}
1880
1881pub struct MOVDemuxerCreator { }
1882
1883impl DemuxerCreator for MOVDemuxerCreator {
1884 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1885 Box::new(MOVDemuxer::new(br))
1886 }
1887 fn get_name(&self) -> &'static str { "mov" }
1888}
1889
88fd1059
KS
1890pub struct MacBinaryMOVDemuxerCreator { }
1891
1892impl DemuxerCreator for MacBinaryMOVDemuxerCreator {
1893 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1894 Box::new(MOVDemuxer::new_macbinary(br))
1895 }
1896 fn get_name(&self) -> &'static str { "mov-macbin" }
1897}
1898
2736c15a
KS
1899const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1900 0x93, 0x65, 0x5E, 0x00,
1901 0xFF, 0xFF, 0xFF, 0x00,
1902 0xDF, 0xD0, 0xAB, 0x00,
1903 0x00, 0x00, 0x00, 0x00
1904];
1905const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1906 0xFF, 0xFB, 0xFF, 0x00,
1907 0xEF, 0xD9, 0xBB, 0x00,
1908 0xE8, 0xC9, 0xB1, 0x00,
1909 0x93, 0x65, 0x5E, 0x00,
1910 0xFC, 0xDE, 0xE8, 0x00,
1911 0x9D, 0x88, 0x91, 0x00,
1912 0xFF, 0xFF, 0xFF, 0x00,
1913 0xFF, 0xFF, 0xFF, 0x00,
1914 0xFF, 0xFF, 0xFF, 0x00,
1915 0x47, 0x48, 0x37, 0x00,
1916 0x7A, 0x5E, 0x55, 0x00,
1917 0xDF, 0xD0, 0xAB, 0x00,
1918 0xFF, 0xFB, 0xF9, 0x00,
1919 0xE8, 0xCA, 0xC5, 0x00,
1920 0x8A, 0x7C, 0x77, 0x00,
1921 0x00, 0x00, 0x00, 0x00
1922];
1923const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1924 0xFF, 0xFF, 0xFF, 0x00,
1925 0xFF, 0xFF, 0xCC, 0x00,
1926 0xFF, 0xFF, 0x99, 0x00,
1927 0xFF, 0xFF, 0x66, 0x00,
1928 0xFF, 0xFF, 0x33, 0x00,
1929 0xFF, 0xFF, 0x00, 0x00,
1930 0xFF, 0xCC, 0xFF, 0x00,
1931 0xFF, 0xCC, 0xCC, 0x00,
1932 0xFF, 0xCC, 0x99, 0x00,
1933 0xFF, 0xCC, 0x66, 0x00,
1934 0xFF, 0xCC, 0x33, 0x00,
1935 0xFF, 0xCC, 0x00, 0x00,
1936 0xFF, 0x99, 0xFF, 0x00,
1937 0xFF, 0x99, 0xCC, 0x00,
1938 0xFF, 0x99, 0x99, 0x00,
1939 0xFF, 0x99, 0x66, 0x00,
1940 0xFF, 0x99, 0x33, 0x00,
1941 0xFF, 0x99, 0x00, 0x00,
1942 0xFF, 0x66, 0xFF, 0x00,
1943 0xFF, 0x66, 0xCC, 0x00,
1944 0xFF, 0x66, 0x99, 0x00,
1945 0xFF, 0x66, 0x66, 0x00,
1946 0xFF, 0x66, 0x33, 0x00,
1947 0xFF, 0x66, 0x00, 0x00,
1948 0xFF, 0x33, 0xFF, 0x00,
1949 0xFF, 0x33, 0xCC, 0x00,
1950 0xFF, 0x33, 0x99, 0x00,
1951 0xFF, 0x33, 0x66, 0x00,
1952 0xFF, 0x33, 0x33, 0x00,
1953 0xFF, 0x33, 0x00, 0x00,
1954 0xFF, 0x00, 0xFF, 0x00,
1955 0xFF, 0x00, 0xCC, 0x00,
1956 0xFF, 0x00, 0x99, 0x00,
1957 0xFF, 0x00, 0x66, 0x00,
1958 0xFF, 0x00, 0x33, 0x00,
1959 0xFF, 0x00, 0x00, 0x00,
1960 0xCC, 0xFF, 0xFF, 0x00,
1961 0xCC, 0xFF, 0xCC, 0x00,
1962 0xCC, 0xFF, 0x99, 0x00,
1963 0xCC, 0xFF, 0x66, 0x00,
1964 0xCC, 0xFF, 0x33, 0x00,
1965 0xCC, 0xFF, 0x00, 0x00,
1966 0xCC, 0xCC, 0xFF, 0x00,
1967 0xCC, 0xCC, 0xCC, 0x00,
1968 0xCC, 0xCC, 0x99, 0x00,
1969 0xCC, 0xCC, 0x66, 0x00,
1970 0xCC, 0xCC, 0x33, 0x00,
1971 0xCC, 0xCC, 0x00, 0x00,
1972 0xCC, 0x99, 0xFF, 0x00,
1973 0xCC, 0x99, 0xCC, 0x00,
1974 0xCC, 0x99, 0x99, 0x00,
1975 0xCC, 0x99, 0x66, 0x00,
1976 0xCC, 0x99, 0x33, 0x00,
1977 0xCC, 0x99, 0x00, 0x00,
1978 0xCC, 0x66, 0xFF, 0x00,
1979 0xCC, 0x66, 0xCC, 0x00,
1980 0xCC, 0x66, 0x99, 0x00,
1981 0xCC, 0x66, 0x66, 0x00,
1982 0xCC, 0x66, 0x33, 0x00,
1983 0xCC, 0x66, 0x00, 0x00,
1984 0xCC, 0x33, 0xFF, 0x00,
1985 0xCC, 0x33, 0xCC, 0x00,
1986 0xCC, 0x33, 0x99, 0x00,
1987 0xCC, 0x33, 0x66, 0x00,
1988 0xCC, 0x33, 0x33, 0x00,
1989 0xCC, 0x33, 0x00, 0x00,
1990 0xCC, 0x00, 0xFF, 0x00,
1991 0xCC, 0x00, 0xCC, 0x00,
1992 0xCC, 0x00, 0x99, 0x00,
1993 0xCC, 0x00, 0x66, 0x00,
1994 0xCC, 0x00, 0x33, 0x00,
1995 0xCC, 0x00, 0x00, 0x00,
1996 0x99, 0xFF, 0xFF, 0x00,
1997 0x99, 0xFF, 0xCC, 0x00,
1998 0x99, 0xFF, 0x99, 0x00,
1999 0x99, 0xFF, 0x66, 0x00,
2000 0x99, 0xFF, 0x33, 0x00,
2001 0x99, 0xFF, 0x00, 0x00,
2002 0x99, 0xCC, 0xFF, 0x00,
2003 0x99, 0xCC, 0xCC, 0x00,
2004 0x99, 0xCC, 0x99, 0x00,
2005 0x99, 0xCC, 0x66, 0x00,
2006 0x99, 0xCC, 0x33, 0x00,
2007 0x99, 0xCC, 0x00, 0x00,
2008 0x99, 0x99, 0xFF, 0x00,
2009 0x99, 0x99, 0xCC, 0x00,
2010 0x99, 0x99, 0x99, 0x00,
2011 0x99, 0x99, 0x66, 0x00,
2012 0x99, 0x99, 0x33, 0x00,
2013 0x99, 0x99, 0x00, 0x00,
2014 0x99, 0x66, 0xFF, 0x00,
2015 0x99, 0x66, 0xCC, 0x00,
2016 0x99, 0x66, 0x99, 0x00,
2017 0x99, 0x66, 0x66, 0x00,
2018 0x99, 0x66, 0x33, 0x00,
2019 0x99, 0x66, 0x00, 0x00,
2020 0x99, 0x33, 0xFF, 0x00,
2021 0x99, 0x33, 0xCC, 0x00,
2022 0x99, 0x33, 0x99, 0x00,
2023 0x99, 0x33, 0x66, 0x00,
2024 0x99, 0x33, 0x33, 0x00,
2025 0x99, 0x33, 0x00, 0x00,
2026 0x99, 0x00, 0xFF, 0x00,
2027 0x99, 0x00, 0xCC, 0x00,
2028 0x99, 0x00, 0x99, 0x00,
2029 0x99, 0x00, 0x66, 0x00,
2030 0x99, 0x00, 0x33, 0x00,
2031 0x99, 0x00, 0x00, 0x00,
2032 0x66, 0xFF, 0xFF, 0x00,
2033 0x66, 0xFF, 0xCC, 0x00,
2034 0x66, 0xFF, 0x99, 0x00,
2035 0x66, 0xFF, 0x66, 0x00,
2036 0x66, 0xFF, 0x33, 0x00,
2037 0x66, 0xFF, 0x00, 0x00,
2038 0x66, 0xCC, 0xFF, 0x00,
2039 0x66, 0xCC, 0xCC, 0x00,
2040 0x66, 0xCC, 0x99, 0x00,
2041 0x66, 0xCC, 0x66, 0x00,
2042 0x66, 0xCC, 0x33, 0x00,
2043 0x66, 0xCC, 0x00, 0x00,
2044 0x66, 0x99, 0xFF, 0x00,
2045 0x66, 0x99, 0xCC, 0x00,
2046 0x66, 0x99, 0x99, 0x00,
2047 0x66, 0x99, 0x66, 0x00,
2048 0x66, 0x99, 0x33, 0x00,
2049 0x66, 0x99, 0x00, 0x00,
2050 0x66, 0x66, 0xFF, 0x00,
2051 0x66, 0x66, 0xCC, 0x00,
2052 0x66, 0x66, 0x99, 0x00,
2053 0x66, 0x66, 0x66, 0x00,
2054 0x66, 0x66, 0x33, 0x00,
2055 0x66, 0x66, 0x00, 0x00,
2056 0x66, 0x33, 0xFF, 0x00,
2057 0x66, 0x33, 0xCC, 0x00,
2058 0x66, 0x33, 0x99, 0x00,
2059 0x66, 0x33, 0x66, 0x00,
2060 0x66, 0x33, 0x33, 0x00,
2061 0x66, 0x33, 0x00, 0x00,
2062 0x66, 0x00, 0xFF, 0x00,
2063 0x66, 0x00, 0xCC, 0x00,
2064 0x66, 0x00, 0x99, 0x00,
2065 0x66, 0x00, 0x66, 0x00,
2066 0x66, 0x00, 0x33, 0x00,
2067 0x66, 0x00, 0x00, 0x00,
2068 0x33, 0xFF, 0xFF, 0x00,
2069 0x33, 0xFF, 0xCC, 0x00,
2070 0x33, 0xFF, 0x99, 0x00,
2071 0x33, 0xFF, 0x66, 0x00,
2072 0x33, 0xFF, 0x33, 0x00,
2073 0x33, 0xFF, 0x00, 0x00,
2074 0x33, 0xCC, 0xFF, 0x00,
2075 0x33, 0xCC, 0xCC, 0x00,
2076 0x33, 0xCC, 0x99, 0x00,
2077 0x33, 0xCC, 0x66, 0x00,
2078 0x33, 0xCC, 0x33, 0x00,
2079 0x33, 0xCC, 0x00, 0x00,
2080 0x33, 0x99, 0xFF, 0x00,
2081 0x33, 0x99, 0xCC, 0x00,
2082 0x33, 0x99, 0x99, 0x00,
2083 0x33, 0x99, 0x66, 0x00,
2084 0x33, 0x99, 0x33, 0x00,
2085 0x33, 0x99, 0x00, 0x00,
2086 0x33, 0x66, 0xFF, 0x00,
2087 0x33, 0x66, 0xCC, 0x00,
2088 0x33, 0x66, 0x99, 0x00,
2089 0x33, 0x66, 0x66, 0x00,
2090 0x33, 0x66, 0x33, 0x00,
2091 0x33, 0x66, 0x00, 0x00,
2092 0x33, 0x33, 0xFF, 0x00,
2093 0x33, 0x33, 0xCC, 0x00,
2094 0x33, 0x33, 0x99, 0x00,
2095 0x33, 0x33, 0x66, 0x00,
2096 0x33, 0x33, 0x33, 0x00,
2097 0x33, 0x33, 0x00, 0x00,
2098 0x33, 0x00, 0xFF, 0x00,
2099 0x33, 0x00, 0xCC, 0x00,
2100 0x33, 0x00, 0x99, 0x00,
2101 0x33, 0x00, 0x66, 0x00,
2102 0x33, 0x00, 0x33, 0x00,
2103 0x33, 0x00, 0x00, 0x00,
2104 0x00, 0xFF, 0xFF, 0x00,
2105 0x00, 0xFF, 0xCC, 0x00,
2106 0x00, 0xFF, 0x99, 0x00,
2107 0x00, 0xFF, 0x66, 0x00,
2108 0x00, 0xFF, 0x33, 0x00,
2109 0x00, 0xFF, 0x00, 0x00,
2110 0x00, 0xCC, 0xFF, 0x00,
2111 0x00, 0xCC, 0xCC, 0x00,
2112 0x00, 0xCC, 0x99, 0x00,
2113 0x00, 0xCC, 0x66, 0x00,
2114 0x00, 0xCC, 0x33, 0x00,
2115 0x00, 0xCC, 0x00, 0x00,
2116 0x00, 0x99, 0xFF, 0x00,
2117 0x00, 0x99, 0xCC, 0x00,
2118 0x00, 0x99, 0x99, 0x00,
2119 0x00, 0x99, 0x66, 0x00,
2120 0x00, 0x99, 0x33, 0x00,
2121 0x00, 0x99, 0x00, 0x00,
2122 0x00, 0x66, 0xFF, 0x00,
2123 0x00, 0x66, 0xCC, 0x00,
2124 0x00, 0x66, 0x99, 0x00,
2125 0x00, 0x66, 0x66, 0x00,
2126 0x00, 0x66, 0x33, 0x00,
2127 0x00, 0x66, 0x00, 0x00,
2128 0x00, 0x33, 0xFF, 0x00,
2129 0x00, 0x33, 0xCC, 0x00,
2130 0x00, 0x33, 0x99, 0x00,
2131 0x00, 0x33, 0x66, 0x00,
2132 0x00, 0x33, 0x33, 0x00,
2133 0x00, 0x33, 0x00, 0x00,
2134 0x00, 0x00, 0xFF, 0x00,
2135 0x00, 0x00, 0xCC, 0x00,
2136 0x00, 0x00, 0x99, 0x00,
2137 0x00, 0x00, 0x66, 0x00,
2138 0x00, 0x00, 0x33, 0x00,
2139 0xEE, 0x00, 0x00, 0x00,
2140 0xDD, 0x00, 0x00, 0x00,
2141 0xBB, 0x00, 0x00, 0x00,
2142 0xAA, 0x00, 0x00, 0x00,
2143 0x88, 0x00, 0x00, 0x00,
2144 0x77, 0x00, 0x00, 0x00,
2145 0x55, 0x00, 0x00, 0x00,
2146 0x44, 0x00, 0x00, 0x00,
2147 0x22, 0x00, 0x00, 0x00,
2148 0x11, 0x00, 0x00, 0x00,
2149 0x00, 0xEE, 0x00, 0x00,
2150 0x00, 0xDD, 0x00, 0x00,
2151 0x00, 0xBB, 0x00, 0x00,
2152 0x00, 0xAA, 0x00, 0x00,
2153 0x00, 0x88, 0x00, 0x00,
2154 0x00, 0x77, 0x00, 0x00,
2155 0x00, 0x55, 0x00, 0x00,
2156 0x00, 0x44, 0x00, 0x00,
2157 0x00, 0x22, 0x00, 0x00,
2158 0x00, 0x11, 0x00, 0x00,
2159 0x00, 0x00, 0xEE, 0x00,
2160 0x00, 0x00, 0xDD, 0x00,
2161 0x00, 0x00, 0xBB, 0x00,
2162 0x00, 0x00, 0xAA, 0x00,
2163 0x00, 0x00, 0x88, 0x00,
2164 0x00, 0x00, 0x77, 0x00,
2165 0x00, 0x00, 0x55, 0x00,
2166 0x00, 0x00, 0x44, 0x00,
2167 0x00, 0x00, 0x22, 0x00,
2168 0x00, 0x00, 0x11, 0x00,
2169 0xEE, 0xEE, 0xEE, 0x00,
2170 0xDD, 0xDD, 0xDD, 0x00,
2171 0xBB, 0xBB, 0xBB, 0x00,
2172 0xAA, 0xAA, 0xAA, 0x00,
2173 0x88, 0x88, 0x88, 0x00,
2174 0x77, 0x77, 0x77, 0x00,
2175 0x55, 0x55, 0x55, 0x00,
2176 0x44, 0x44, 0x44, 0x00,
2177 0x22, 0x22, 0x22, 0x00,
2178 0x11, 0x11, 0x11, 0x00,
2179 0x00, 0x00, 0x00, 0x00
2180];
2181
58309c73
KS
2182#[cfg(test)]
2183mod test {
2184 use super::*;
2185 use std::fs::File;
2186
2187 #[test]
2188 fn test_mov_demux() {
886cde48 2189 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/cubes.mov
58309c73
KS
2190 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2191 let mut fr = FileReader::new_read(&mut file);
2192 let mut br = ByteReader::new(&mut fr);
2193 let mut dmx = MOVDemuxer::new(&mut br);
2194 let mut sm = StreamManager::new();
2195 let mut si = SeekIndex::new();
2196 dmx.open(&mut sm, &mut si).unwrap();
2197
2198 loop {
2199 let pktres = dmx.get_frame(&mut sm);
2200 if let Err(e) = pktres {
2201 if e == DemuxerError::EOF { break; }
2202 panic!("error");
2203 }
2204 let pkt = pktres.unwrap();
2205 println!("Got {}", pkt);
2206 }
2207 }
0a0456a8
KS
2208
2209 #[test]
2210 fn test_dash_demux() {
886cde48 2211 // sample: a stream downloaded with youtube-dl
0a0456a8
KS
2212 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2213 let mut fr = FileReader::new_read(&mut file);
2214 let mut br = ByteReader::new(&mut fr);
2215 let mut dmx = MOVDemuxer::new(&mut br);
2216 let mut sm = StreamManager::new();
2217 let mut si = SeekIndex::new();
2218 dmx.open(&mut sm, &mut si).unwrap();
2219
2220 loop {
2221 let pktres = dmx.get_frame(&mut sm);
2222 if let Err(e) = pktres {
2223 if e == DemuxerError::EOF { break; }
2224 panic!("error");
2225 }
2226 let pkt = pktres.unwrap();
2227 println!("Got {}", pkt);
2228 }
2229 }
88fd1059
KS
2230
2231 #[test]
2232 fn test_macbinary_demux() {
2233 // sample from King's Quest VI Macintosh edition
2234 let mut file = File::open("assets/QT/Halfdome.bin").unwrap();
2235 let mut fr = FileReader::new_read(&mut file);
2236 let mut br = ByteReader::new(&mut fr);
2237 let mut dmx = MOVDemuxer::new_macbinary(&mut br);
2238 let mut sm = StreamManager::new();
2239 let mut si = SeekIndex::new();
2240 dmx.open(&mut sm, &mut si).unwrap();
2241
2242 loop {
2243 let pktres = dmx.get_frame(&mut sm);
2244 if let Err(e) = pktres {
2245 if e == DemuxerError::EOF { break; }
2246 panic!("error");
2247 }
2248 let pkt = pktres.unwrap();
2249 println!("Got {}", pkt);
2250 }
2251 }
58309c73 2252}