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