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