mov: serve packets with equal timestamps if possible
[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 cur_ts: Option<u64>,
1062 samples_left: usize,
1063 last_offset: u64,
1064 pal: Option<Arc<[u8; 1024]>>,
1065 timesearch: TimeSearcher,
1066
1067 moof_off: u64,
1068
1069 print_chunks: bool,
1070 }
1071
1072 #[derive(Default)]
1073 struct TimeSearcher {
1074 idx: usize,
1075 base: u64,
1076 sbase: u32,
1077 cur_len: u32,
1078 cur_mul: u32,
1079 }
1080
1081 impl TimeSearcher {
1082 fn new() -> Self { Self::default() }
1083 fn reset(&mut self) {
1084 *self = Self::default();
1085 }
1086 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
1087 if tts.is_empty() {
1088 u64::from(sample)
1089 } else if sample >= self.sbase {
1090 let mut sample = sample - self.sbase;
1091 if self.idx == 0 {
1092 let (cur_len, cur_mul) = tts[0];
1093 self.cur_len = cur_len;
1094 self.cur_mul = cur_mul;
1095 self.idx += 1;
1096 }
1097 while self.idx < tts.len() && sample > self.cur_len {
1098 sample -= self.cur_len;
1099 self.sbase += self.cur_len;
1100 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1101 self.cur_len = tts[self.idx].0;
1102 self.cur_mul = tts[self.idx].1;
1103 self.idx += 1;
1104 }
1105 self.base + u64::from(sample) * u64::from(self.cur_mul)
1106 } else {
1107 self.reset();
1108 self.map_time(sample, tts)
1109 }
1110 }
1111 }
1112
1113 #[derive(Default)]
1114 struct RLESearcher<T> {
1115 array: Vec<(u32, T)>,
1116 idx: usize,
1117 start: u64,
1118 next: u64,
1119 }
1120
1121 impl<T:Default+Copy> RLESearcher<T> {
1122 fn new() -> Self { Self::default() }
1123 fn resize(&mut self, size: usize) {
1124 self.array.truncate(0);
1125 self.array.reserve(size);
1126 }
1127 fn reserve(&mut self, size: usize) {
1128 self.array.reserve(size);
1129 }
1130 fn add(&mut self, len: u32, val: T) {
1131 self.array.push((len, val));
1132 }
1133 fn reset(&mut self) {
1134 self.start = 0;
1135 if !self.array.is_empty() {
1136 self.idx = 0;
1137 self.next = u64::from(self.array[0].0);
1138 } else {
1139 self.idx = self.array.len();
1140 self.next = 0;
1141 }
1142 }
1143 fn map(&mut self, sample: u64) -> Option<T> {
1144 if sample < self.start {
1145 self.reset();
1146 }
1147 if self.idx < self.array.len() {
1148 if sample < self.next {
1149 Some(self.array[self.idx].1)
1150 } else {
1151 while (self.idx < self.array.len()) && (sample >= self.next) {
1152 self.start = self.next;
1153 self.idx += 1;
1154 if self.idx < self.array.len() {
1155 self.next += u64::from(self.array[self.idx].0);
1156 }
1157 }
1158 if self.idx < self.array.len() {
1159 Some(self.array[self.idx].1)
1160 } else {
1161 None
1162 }
1163 }
1164 } else {
1165 None
1166 }
1167 }
1168 }
1169
1170 impl Track {
1171 fn new(track_no: u32, tb_den: u32) -> Self {
1172 Self {
1173 tkhd_found: false,
1174 stsd_found: false,
1175 track_id: 0,
1176 track_str_id: 0,
1177 track_no,
1178 tb_num: 1,
1179 tb_den,
1180 tb_div: 1,
1181 raw_audio: false,
1182 raw_apos: 0,
1183 duration: 0,
1184 stream_type: StreamType::None,
1185 width: 0,
1186 height: 0,
1187 channels: 0,
1188 bits: 0,
1189 bsize: 0,
1190 fcc: [0; 4],
1191 keyframes: Vec::new(),
1192 chunk_sizes: Vec::new(),
1193 chunk_offsets: Vec::new(),
1194 time_to_sample: Vec::new(),
1195 sample_map: Vec::new(),
1196 sample_size: 0,
1197 frame_samples: 0,
1198 ctts_map: RLESearcher::new(),
1199 ctts_version: 0,
1200 stream: None,
1201 depth: 0,
1202 cur_chunk: 0,
1203 cur_sample: 0,
1204 cur_ts: None,
1205 samples_left: 0,
1206 last_offset: 0,
1207 pal: None,
1208 timesearch: TimeSearcher::new(),
1209
1210 moof_off: 0,
1211
1212 print_chunks: false,
1213 }
1214 }
1215 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1216 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1217 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1218 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1219 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1220 fn rescale(&mut self, tb_num: u32) {
1221 self.tb_div = tb_num;
1222 if let Some(ref mut stream) = self.stream {
1223 let tb_den = stream.tb_den;
1224 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1225 stream.duration /= u64::from(self.tb_div);
1226 stream.tb_num = tb_num;
1227 stream.tb_den = tb_den;
1228 self.tb_num = tb_num;
1229 self.tb_den = tb_den;
1230 self.duration /= self.tb_div;
1231 }
1232 }
1233 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1234 if !self.keyframes.is_empty() {
1235 seek_index.mode = SeekIndexMode::Present;
1236 }
1237 let mut tsearch = TimeSearcher::new();
1238 for kf_time in self.keyframes.iter() {
1239 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1240 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1241 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1242 }
1243 }
1244 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1245 if nsamp == 0 {
1246 self.bsize
1247 } else {
1248 match &self.fcc {
1249 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1250 (nsamp * self.bits * self.channels + 7) >> 3
1251 },
1252 b"ima4" => {
1253 let nblocks = (nsamp + 63) >> 6;
1254 nblocks * 34 * self.channels
1255 },
1256 b"MAC3" => {
1257 (nsamp + 5) / 6 * 2 * self.channels
1258 },
1259 b"MAC6" => {
1260 (nsamp + 5) / 6 * self.channels
1261 },
1262 b"in24" => nsamp * 3 * self.channels,
1263 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1264 b"fl64" => nsamp * 8 * self.channels,
1265 b"ulaw" | b"alaw" => nsamp,
1266 b"ms\x00\x02" => { //MS ADPCM
1267 ((nsamp - 1) / 2 + 7) * self.channels
1268 },
1269 b"ms\x00\x21" => { //IMA ADPCM
1270 (nsamp / 2 + 4) * self.channels
1271 },
1272 _ => self.bsize,
1273 }
1274 }
1275 }
1276 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1277 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1278 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1279 let dts = match self.ctts_version {
1280 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1281 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1282 _ => unimplemented!(),
1283 };
1284 if (dts as i64) < 0 {
1285 None
1286 } else {
1287 Some(dts)
1288 }
1289 } else {
1290 None
1291 };
1292 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1293 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1294 if self.cur_sample >= self.chunk_sizes.len() {
1295 return None;
1296 }
1297 let offset = self.chunk_offsets[self.cur_sample];
1298 let size = self.chunk_sizes[self.cur_sample] as usize;
1299 self.cur_sample += 1;
1300 Some((pts, offset, size))
1301 } else {
1302 if self.samples_left == 0 {
1303 if self.cur_chunk >= self.chunk_offsets.len() {
1304 return None;
1305 }
1306 for (idx, samples) in self.sample_map.iter() {
1307 if *idx as usize <= self.cur_chunk + 1 {
1308 self.samples_left = *samples as usize;
1309 } else {
1310 break;
1311 }
1312 }
1313 self.last_offset = self.chunk_offsets[self.cur_chunk];
1314 self.cur_chunk += 1;
1315 }
1316 let offset = self.last_offset;
1317 let size = self.get_size(self.cur_sample);
1318 self.last_offset += size as u64;
1319 if self.stream_type == StreamType::Video {
1320 self.samples_left -= 1;
1321 } else if self.frame_samples != 0 && self.bsize != 0 {
1322 let nblocks = size / self.bsize;
1323 if self.raw_audio {
1324 pts.pts = Some(self.raw_apos);
1325 pts.duration = Some(nblocks as u64);
1326 self.raw_apos += nblocks as u64;
1327 }
1328 if nblocks > 0 {
1329 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1330 self.samples_left -= consumed;
1331 } else {
1332 self.samples_left = 0;
1333 }
1334 } else if !self.raw_audio {
1335 self.samples_left -= 1;
1336 } else {
1337 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1338 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1339 let cur_size = self.calculate_chunk_size(self.samples_left);
1340 let add_off = (size - cur_size) as u64;
1341 let dsize = cur_size.min(max_size);
1342 if self.samples_left >= BLOCK_SAMPLES {
1343 self.cur_sample += BLOCK_SAMPLES;
1344 self.samples_left -= BLOCK_SAMPLES;
1345 self.last_offset -= size as u64;
1346 } else {
1347 self.cur_sample += self.samples_left;
1348 self.samples_left = 0;
1349 }
1350 return Some((pts, offset + add_off, dsize));
1351 }
1352 self.cur_sample += 1;
1353 Some((pts, offset, size))
1354 }
1355 }
1356 fn get_size(&self, sample_no: usize) -> usize {
1357 if !self.chunk_sizes.is_empty() {
1358 self.chunk_sizes[sample_no] as usize
1359 } else if !self.sample_map.is_empty() {
1360 let mut nsamp = 0;
1361 for (idx, samples) in self.sample_map.iter() {
1362 if *idx as usize <= self.cur_chunk {
1363 nsamp = *samples;
1364 } else {
1365 break;
1366 }
1367 }
1368 self.calculate_chunk_size(nsamp as usize)
1369 } else {
1370 self.bsize
1371 }
1372 }
1373 #[allow(clippy::collapsible_if)]
1374 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1375 self.cur_sample = pts as usize;
1376 self.samples_left = 0;
1377 self.cur_ts = None;
1378 if self.stream_type == StreamType::Audio {
1379 if let NATimePoint::Milliseconds(ms) = tpoint {
1380 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1381 if self.raw_audio {
1382 if self.frame_samples != 0 {
1383 self.raw_apos = exp_pts / (self.frame_samples as u64);
1384 let mut apos = 0;
1385 self.cur_sample = 0;
1386 self.cur_chunk = 0;
1387 let mut cmap = self.sample_map.iter();
1388 let mut cur_samps = 0;
1389 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1390 loop {
1391 if self.cur_chunk + 1 == next_idx as usize {
1392 self.samples_left = cur_samps;
1393 cur_samps = next_samples as usize;
1394 if let Some((new_idx, new_samples)) = cmap.next() {
1395 next_idx = *new_idx;
1396 next_samples = *new_samples;
1397 }
1398 }
1399 self.raw_apos = apos;
1400 apos += (cur_samps / self.frame_samples) as u64;
1401 if apos > exp_pts {
1402 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1403 if self.cur_chunk >= self.chunk_offsets.len() {
1404 return Err(DemuxerError::SeekError);
1405 }
1406 self.last_offset = self.chunk_offsets[self.cur_chunk];
1407 break;
1408 }
1409 }
1410 self.cur_chunk += 1;
1411 }
1412 self.samples_left = cur_samps;
1413 self.cur_chunk += 1;
1414 } else {
1415 self.raw_apos = exp_pts;
1416 self.cur_sample = exp_pts as usize;
1417 let mut csamp = 0;
1418 self.cur_chunk = 0;
1419 let mut cmap = self.sample_map.iter();
1420 let mut cur_samps = 0;
1421 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1422 loop {
1423 if self.cur_chunk + 1 == next_idx as usize {
1424 self.samples_left = cur_samps;
1425 cur_samps = next_samples as usize;
1426 if let Some((new_idx, new_samples)) = cmap.next() {
1427 next_idx = *new_idx;
1428 next_samples = *new_samples;
1429 }
1430 }
1431 csamp += cur_samps;
1432 if csamp > self.cur_sample {
1433 if self.cur_chunk >= self.chunk_offsets.len() {
1434 return Err(DemuxerError::SeekError);
1435 }
1436 self.last_offset = self.chunk_offsets[self.cur_chunk];
1437 break;
1438 }
1439 self.cur_chunk += 1;
1440 }
1441 self.samples_left = csamp - self.cur_sample;
1442 self.cur_chunk += 1;
1443 }
1444 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
1445 self.cur_chunk = self.cur_sample;
1446 } else {
1447 let mut csamp = 0;
1448 self.cur_chunk = 0;
1449 let mut cmap = self.sample_map.iter();
1450 let mut cur_samps = 0;
1451 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1452 loop {
1453 if self.cur_chunk + 1 == next_idx as usize {
1454 self.samples_left = cur_samps;
1455 cur_samps = next_samples as usize;
1456 if let Some((new_idx, new_samples)) = cmap.next() {
1457 next_idx = *new_idx;
1458 next_samples = *new_samples;
1459 }
1460 }
1461 csamp += cur_samps;
1462 if csamp > self.cur_sample {
1463 if self.cur_chunk >= self.chunk_offsets.len() {
1464 return Err(DemuxerError::SeekError);
1465 }
1466 self.last_offset = self.chunk_offsets[self.cur_chunk];
1467 break;
1468 }
1469 self.cur_chunk += 1;
1470 }
1471 self.cur_sample = csamp - cur_samps;
1472 self.samples_left = cur_samps;
1473 self.last_offset = self.chunk_offsets[self.cur_chunk];
1474 self.cur_chunk += 1;
1475 }
1476 } else {
1477 self.cur_chunk = self.cur_sample;
1478 }
1479 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1480 let mut csamp = 0;
1481 self.cur_chunk = 0;
1482 let mut cmap = self.sample_map.iter();
1483 let mut cur_samps = 0;
1484 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1485 loop {
1486 if self.cur_chunk + 1 == next_idx as usize {
1487 self.samples_left = cur_samps;
1488 cur_samps = next_samples as usize;
1489 if let Some((new_idx, new_samples)) = cmap.next() {
1490 next_idx = *new_idx;
1491 next_samples = *new_samples;
1492 }
1493 }
1494 csamp += cur_samps;
1495 if csamp >= self.cur_sample {
1496 if self.cur_chunk >= self.chunk_offsets.len() {
1497 return Err(DemuxerError::SeekError);
1498 }
1499 self.last_offset = self.chunk_offsets[self.cur_chunk];
1500 break;
1501 }
1502 self.cur_chunk += 1;
1503 }
1504 csamp -= cur_samps;
1505 for sample_no in csamp..self.cur_sample {
1506 self.last_offset += self.get_size(sample_no) as u64;
1507 }
1508 self.samples_left = csamp + cur_samps - self.cur_sample;
1509 self.cur_chunk += 1;
1510 }
1511 Ok(())
1512 }
1513 }
1514
1515 fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1516 if let Some(cpts) = pts.get_pts() {
1517 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1518 track.cur_ts = Some(ts);
1519 } else {
1520 track.cur_ts = None;
1521 }
1522 let str = strmgr.get_stream(track.track_str_id);
1523 if str.is_none() { return Err(DemuxerError::InvalidData); }
1524 let stream = str.unwrap();
1525 src.seek(SeekFrom::Start(offset))?;
1526 let mut pkt = src.read_packet(stream, pts, false, size)?;
1527 if let Some(ref pal) = track.pal {
1528 let side_data = NASideData::Palette(first, pal.clone());
1529 pkt.add_side_data(side_data);
1530 }
1531 Ok(pkt)
1532 }
1533
1534 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1535 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1536 self.read_root(strmgr)?;
1537 validate!(self.mdat_pos > 0);
1538 validate!(!self.tracks.is_empty());
1539 for track in self.tracks.iter_mut() {
1540 let mut str = None;
1541 std::mem::swap(&mut track.stream, &mut str);
1542 if let Some(stream) = str {
1543 let str_id = strmgr.add_stream(stream).unwrap();
1544 track.track_str_id = str_id;
1545 }
1546 }
1547 for track in self.tracks.iter() {
1548 track.fill_seek_index(seek_index);
1549 }
1550 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1551 self.cur_track = 0;
1552 Ok(())
1553 }
1554
1555 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1556 if self.tracks.is_empty() {
1557 return Err(DemuxerError::EOF);
1558 }
1559 let mut has_all_time = true;
1560 let mut min_ts = std::u64::MAX;
1561 for trk in self.tracks.iter() {
1562 if let Some(ts) = trk.cur_ts {
1563 min_ts = min_ts.min(ts);
1564 } else {
1565 has_all_time = false;
1566 break;
1567 }
1568 }
1569 if has_all_time {
1570 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1571 if let Some(ts) = track.cur_ts {
1572 if ts == min_ts {
1573 let first = track.cur_sample == 0;
1574 if let Some((pts, offset, size)) = track.get_next_chunk() {
1575 self.cur_track = trk_no + 1;
1576 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1577 }
1578 }
1579 }
1580 }
1581 }
1582
1583 for _ in 0..self.tracks.len() {
1584 if self.cur_track >= self.tracks.len() {
1585 self.cur_track = 0;
1586 }
1587 let track = &mut self.tracks[self.cur_track];
1588 self.cur_track += 1;
1589 let first = track.cur_sample == 0;
1590 if let Some((pts, offset, size)) = track.get_next_chunk() {
1591 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1592 }
1593 }
1594 Err(DemuxerError::EOF)
1595 }
1596
1597 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1598 let ret = seek_index.find_pos(time);
1599 if ret.is_none() {
1600 if let NATimePoint::Milliseconds(_) = time {
1601 let mut aonly = true;
1602 for track in self.tracks.iter() {
1603 if track.stream_type != StreamType::Audio || !track.raw_audio {
1604 aonly = false;
1605 break;
1606 }
1607 }
1608 if aonly {
1609 for track in self.tracks.iter_mut() {
1610 track.seek(0, time)?;
1611 }
1612 return Ok(());
1613 }
1614 }
1615 return Err(DemuxerError::SeekError);
1616 }
1617 let seek_info = ret.unwrap();
1618 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1619 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
1620 for track in self.tracks.iter_mut() {
1621 let cur_pts = if track.track_id == seek_info.str_id {
1622 seek_info.pts
1623 } else {
1624 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1625 };
1626 track.seek(cur_pts, time)?;
1627 }
1628 Ok(())
1629 }
1630 fn get_duration(&self) -> u64 {
1631 if self.tb_den != 0 {
1632 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1633 } else {
1634 0
1635 }
1636 }
1637 }
1638
1639 const PRINT_CHUNKS: &str = "print_chunks";
1640
1641 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1642 NAOptionDefinition {
1643 name: PRINT_CHUNKS,
1644 description: "Print parsed file structure",
1645 opt_type: NAOptionDefinitionType::Bool },
1646 ];
1647
1648 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1649 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1650 #[allow(clippy::single_match)]
1651 fn set_options(&mut self, options: &[NAOption]) {
1652 for option in options.iter() {
1653 for opt_def in DEMUXER_OPTIONS.iter() {
1654 if opt_def.check(option).is_ok() {
1655 match (option.name, &option.value) {
1656 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1657 self.print_chunks = *val;
1658 },
1659 _ => {},
1660 }
1661 }
1662 }
1663 }
1664 }
1665 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1666 match name {
1667 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1668 _ => None,
1669 }
1670 }
1671 }
1672
1673 impl<'a> MOVDemuxer<'a> {
1674 fn new(io: &'a mut ByteReader<'a>) -> Self {
1675 MOVDemuxer {
1676 src: io,
1677 depth: 0,
1678 mdat_pos: 0,
1679 mdat_size: 0,
1680 tracks: Vec::with_capacity(2),
1681 cur_track: 0,
1682 tb_den: 0,
1683 duration: 0,
1684 pal: None,
1685
1686 moof_off: 0,
1687
1688 print_chunks: false,
1689 }
1690 }
1691 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1692 self.depth = 0;
1693 while self.src.left() != 0 {
1694 let ret = read_chunk_header(&mut self.src);
1695 if ret.is_err() { break; }
1696 let (ctype, size) = ret.unwrap();
1697 if self.print_chunks {
1698 print_cname(ctype, size, self.src.tell(), 0);
1699 }
1700 if IGNORED_CHUNKS.contains(&ctype) {
1701 self.src.skip64(size)?;
1702 continue;
1703 }
1704 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1705 let read_size;
1706 if let Some(ref handler) = handler {
1707 read_size = (handler.parse)(self, strmgr, size)?;
1708 } else {
1709 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1710 read_size = 0;
1711 }
1712 validate!(read_size <= size);
1713 self.src.skip64(size - read_size)?;
1714 }
1715 //todo check if all needed chunks are found
1716 Ok(())
1717 }
1718 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1719 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
1720 }
1721
1722 pub struct MOVDemuxerCreator { }
1723
1724 impl DemuxerCreator for MOVDemuxerCreator {
1725 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1726 Box::new(MOVDemuxer::new(br))
1727 }
1728 fn get_name(&self) -> &'static str { "mov" }
1729 }
1730
1731 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1732 0x93, 0x65, 0x5E, 0x00,
1733 0xFF, 0xFF, 0xFF, 0x00,
1734 0xDF, 0xD0, 0xAB, 0x00,
1735 0x00, 0x00, 0x00, 0x00
1736 ];
1737 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1738 0xFF, 0xFB, 0xFF, 0x00,
1739 0xEF, 0xD9, 0xBB, 0x00,
1740 0xE8, 0xC9, 0xB1, 0x00,
1741 0x93, 0x65, 0x5E, 0x00,
1742 0xFC, 0xDE, 0xE8, 0x00,
1743 0x9D, 0x88, 0x91, 0x00,
1744 0xFF, 0xFF, 0xFF, 0x00,
1745 0xFF, 0xFF, 0xFF, 0x00,
1746 0xFF, 0xFF, 0xFF, 0x00,
1747 0x47, 0x48, 0x37, 0x00,
1748 0x7A, 0x5E, 0x55, 0x00,
1749 0xDF, 0xD0, 0xAB, 0x00,
1750 0xFF, 0xFB, 0xF9, 0x00,
1751 0xE8, 0xCA, 0xC5, 0x00,
1752 0x8A, 0x7C, 0x77, 0x00,
1753 0x00, 0x00, 0x00, 0x00
1754 ];
1755 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1756 0xFF, 0xFF, 0xFF, 0x00,
1757 0xFF, 0xFF, 0xCC, 0x00,
1758 0xFF, 0xFF, 0x99, 0x00,
1759 0xFF, 0xFF, 0x66, 0x00,
1760 0xFF, 0xFF, 0x33, 0x00,
1761 0xFF, 0xFF, 0x00, 0x00,
1762 0xFF, 0xCC, 0xFF, 0x00,
1763 0xFF, 0xCC, 0xCC, 0x00,
1764 0xFF, 0xCC, 0x99, 0x00,
1765 0xFF, 0xCC, 0x66, 0x00,
1766 0xFF, 0xCC, 0x33, 0x00,
1767 0xFF, 0xCC, 0x00, 0x00,
1768 0xFF, 0x99, 0xFF, 0x00,
1769 0xFF, 0x99, 0xCC, 0x00,
1770 0xFF, 0x99, 0x99, 0x00,
1771 0xFF, 0x99, 0x66, 0x00,
1772 0xFF, 0x99, 0x33, 0x00,
1773 0xFF, 0x99, 0x00, 0x00,
1774 0xFF, 0x66, 0xFF, 0x00,
1775 0xFF, 0x66, 0xCC, 0x00,
1776 0xFF, 0x66, 0x99, 0x00,
1777 0xFF, 0x66, 0x66, 0x00,
1778 0xFF, 0x66, 0x33, 0x00,
1779 0xFF, 0x66, 0x00, 0x00,
1780 0xFF, 0x33, 0xFF, 0x00,
1781 0xFF, 0x33, 0xCC, 0x00,
1782 0xFF, 0x33, 0x99, 0x00,
1783 0xFF, 0x33, 0x66, 0x00,
1784 0xFF, 0x33, 0x33, 0x00,
1785 0xFF, 0x33, 0x00, 0x00,
1786 0xFF, 0x00, 0xFF, 0x00,
1787 0xFF, 0x00, 0xCC, 0x00,
1788 0xFF, 0x00, 0x99, 0x00,
1789 0xFF, 0x00, 0x66, 0x00,
1790 0xFF, 0x00, 0x33, 0x00,
1791 0xFF, 0x00, 0x00, 0x00,
1792 0xCC, 0xFF, 0xFF, 0x00,
1793 0xCC, 0xFF, 0xCC, 0x00,
1794 0xCC, 0xFF, 0x99, 0x00,
1795 0xCC, 0xFF, 0x66, 0x00,
1796 0xCC, 0xFF, 0x33, 0x00,
1797 0xCC, 0xFF, 0x00, 0x00,
1798 0xCC, 0xCC, 0xFF, 0x00,
1799 0xCC, 0xCC, 0xCC, 0x00,
1800 0xCC, 0xCC, 0x99, 0x00,
1801 0xCC, 0xCC, 0x66, 0x00,
1802 0xCC, 0xCC, 0x33, 0x00,
1803 0xCC, 0xCC, 0x00, 0x00,
1804 0xCC, 0x99, 0xFF, 0x00,
1805 0xCC, 0x99, 0xCC, 0x00,
1806 0xCC, 0x99, 0x99, 0x00,
1807 0xCC, 0x99, 0x66, 0x00,
1808 0xCC, 0x99, 0x33, 0x00,
1809 0xCC, 0x99, 0x00, 0x00,
1810 0xCC, 0x66, 0xFF, 0x00,
1811 0xCC, 0x66, 0xCC, 0x00,
1812 0xCC, 0x66, 0x99, 0x00,
1813 0xCC, 0x66, 0x66, 0x00,
1814 0xCC, 0x66, 0x33, 0x00,
1815 0xCC, 0x66, 0x00, 0x00,
1816 0xCC, 0x33, 0xFF, 0x00,
1817 0xCC, 0x33, 0xCC, 0x00,
1818 0xCC, 0x33, 0x99, 0x00,
1819 0xCC, 0x33, 0x66, 0x00,
1820 0xCC, 0x33, 0x33, 0x00,
1821 0xCC, 0x33, 0x00, 0x00,
1822 0xCC, 0x00, 0xFF, 0x00,
1823 0xCC, 0x00, 0xCC, 0x00,
1824 0xCC, 0x00, 0x99, 0x00,
1825 0xCC, 0x00, 0x66, 0x00,
1826 0xCC, 0x00, 0x33, 0x00,
1827 0xCC, 0x00, 0x00, 0x00,
1828 0x99, 0xFF, 0xFF, 0x00,
1829 0x99, 0xFF, 0xCC, 0x00,
1830 0x99, 0xFF, 0x99, 0x00,
1831 0x99, 0xFF, 0x66, 0x00,
1832 0x99, 0xFF, 0x33, 0x00,
1833 0x99, 0xFF, 0x00, 0x00,
1834 0x99, 0xCC, 0xFF, 0x00,
1835 0x99, 0xCC, 0xCC, 0x00,
1836 0x99, 0xCC, 0x99, 0x00,
1837 0x99, 0xCC, 0x66, 0x00,
1838 0x99, 0xCC, 0x33, 0x00,
1839 0x99, 0xCC, 0x00, 0x00,
1840 0x99, 0x99, 0xFF, 0x00,
1841 0x99, 0x99, 0xCC, 0x00,
1842 0x99, 0x99, 0x99, 0x00,
1843 0x99, 0x99, 0x66, 0x00,
1844 0x99, 0x99, 0x33, 0x00,
1845 0x99, 0x99, 0x00, 0x00,
1846 0x99, 0x66, 0xFF, 0x00,
1847 0x99, 0x66, 0xCC, 0x00,
1848 0x99, 0x66, 0x99, 0x00,
1849 0x99, 0x66, 0x66, 0x00,
1850 0x99, 0x66, 0x33, 0x00,
1851 0x99, 0x66, 0x00, 0x00,
1852 0x99, 0x33, 0xFF, 0x00,
1853 0x99, 0x33, 0xCC, 0x00,
1854 0x99, 0x33, 0x99, 0x00,
1855 0x99, 0x33, 0x66, 0x00,
1856 0x99, 0x33, 0x33, 0x00,
1857 0x99, 0x33, 0x00, 0x00,
1858 0x99, 0x00, 0xFF, 0x00,
1859 0x99, 0x00, 0xCC, 0x00,
1860 0x99, 0x00, 0x99, 0x00,
1861 0x99, 0x00, 0x66, 0x00,
1862 0x99, 0x00, 0x33, 0x00,
1863 0x99, 0x00, 0x00, 0x00,
1864 0x66, 0xFF, 0xFF, 0x00,
1865 0x66, 0xFF, 0xCC, 0x00,
1866 0x66, 0xFF, 0x99, 0x00,
1867 0x66, 0xFF, 0x66, 0x00,
1868 0x66, 0xFF, 0x33, 0x00,
1869 0x66, 0xFF, 0x00, 0x00,
1870 0x66, 0xCC, 0xFF, 0x00,
1871 0x66, 0xCC, 0xCC, 0x00,
1872 0x66, 0xCC, 0x99, 0x00,
1873 0x66, 0xCC, 0x66, 0x00,
1874 0x66, 0xCC, 0x33, 0x00,
1875 0x66, 0xCC, 0x00, 0x00,
1876 0x66, 0x99, 0xFF, 0x00,
1877 0x66, 0x99, 0xCC, 0x00,
1878 0x66, 0x99, 0x99, 0x00,
1879 0x66, 0x99, 0x66, 0x00,
1880 0x66, 0x99, 0x33, 0x00,
1881 0x66, 0x99, 0x00, 0x00,
1882 0x66, 0x66, 0xFF, 0x00,
1883 0x66, 0x66, 0xCC, 0x00,
1884 0x66, 0x66, 0x99, 0x00,
1885 0x66, 0x66, 0x66, 0x00,
1886 0x66, 0x66, 0x33, 0x00,
1887 0x66, 0x66, 0x00, 0x00,
1888 0x66, 0x33, 0xFF, 0x00,
1889 0x66, 0x33, 0xCC, 0x00,
1890 0x66, 0x33, 0x99, 0x00,
1891 0x66, 0x33, 0x66, 0x00,
1892 0x66, 0x33, 0x33, 0x00,
1893 0x66, 0x33, 0x00, 0x00,
1894 0x66, 0x00, 0xFF, 0x00,
1895 0x66, 0x00, 0xCC, 0x00,
1896 0x66, 0x00, 0x99, 0x00,
1897 0x66, 0x00, 0x66, 0x00,
1898 0x66, 0x00, 0x33, 0x00,
1899 0x66, 0x00, 0x00, 0x00,
1900 0x33, 0xFF, 0xFF, 0x00,
1901 0x33, 0xFF, 0xCC, 0x00,
1902 0x33, 0xFF, 0x99, 0x00,
1903 0x33, 0xFF, 0x66, 0x00,
1904 0x33, 0xFF, 0x33, 0x00,
1905 0x33, 0xFF, 0x00, 0x00,
1906 0x33, 0xCC, 0xFF, 0x00,
1907 0x33, 0xCC, 0xCC, 0x00,
1908 0x33, 0xCC, 0x99, 0x00,
1909 0x33, 0xCC, 0x66, 0x00,
1910 0x33, 0xCC, 0x33, 0x00,
1911 0x33, 0xCC, 0x00, 0x00,
1912 0x33, 0x99, 0xFF, 0x00,
1913 0x33, 0x99, 0xCC, 0x00,
1914 0x33, 0x99, 0x99, 0x00,
1915 0x33, 0x99, 0x66, 0x00,
1916 0x33, 0x99, 0x33, 0x00,
1917 0x33, 0x99, 0x00, 0x00,
1918 0x33, 0x66, 0xFF, 0x00,
1919 0x33, 0x66, 0xCC, 0x00,
1920 0x33, 0x66, 0x99, 0x00,
1921 0x33, 0x66, 0x66, 0x00,
1922 0x33, 0x66, 0x33, 0x00,
1923 0x33, 0x66, 0x00, 0x00,
1924 0x33, 0x33, 0xFF, 0x00,
1925 0x33, 0x33, 0xCC, 0x00,
1926 0x33, 0x33, 0x99, 0x00,
1927 0x33, 0x33, 0x66, 0x00,
1928 0x33, 0x33, 0x33, 0x00,
1929 0x33, 0x33, 0x00, 0x00,
1930 0x33, 0x00, 0xFF, 0x00,
1931 0x33, 0x00, 0xCC, 0x00,
1932 0x33, 0x00, 0x99, 0x00,
1933 0x33, 0x00, 0x66, 0x00,
1934 0x33, 0x00, 0x33, 0x00,
1935 0x33, 0x00, 0x00, 0x00,
1936 0x00, 0xFF, 0xFF, 0x00,
1937 0x00, 0xFF, 0xCC, 0x00,
1938 0x00, 0xFF, 0x99, 0x00,
1939 0x00, 0xFF, 0x66, 0x00,
1940 0x00, 0xFF, 0x33, 0x00,
1941 0x00, 0xFF, 0x00, 0x00,
1942 0x00, 0xCC, 0xFF, 0x00,
1943 0x00, 0xCC, 0xCC, 0x00,
1944 0x00, 0xCC, 0x99, 0x00,
1945 0x00, 0xCC, 0x66, 0x00,
1946 0x00, 0xCC, 0x33, 0x00,
1947 0x00, 0xCC, 0x00, 0x00,
1948 0x00, 0x99, 0xFF, 0x00,
1949 0x00, 0x99, 0xCC, 0x00,
1950 0x00, 0x99, 0x99, 0x00,
1951 0x00, 0x99, 0x66, 0x00,
1952 0x00, 0x99, 0x33, 0x00,
1953 0x00, 0x99, 0x00, 0x00,
1954 0x00, 0x66, 0xFF, 0x00,
1955 0x00, 0x66, 0xCC, 0x00,
1956 0x00, 0x66, 0x99, 0x00,
1957 0x00, 0x66, 0x66, 0x00,
1958 0x00, 0x66, 0x33, 0x00,
1959 0x00, 0x66, 0x00, 0x00,
1960 0x00, 0x33, 0xFF, 0x00,
1961 0x00, 0x33, 0xCC, 0x00,
1962 0x00, 0x33, 0x99, 0x00,
1963 0x00, 0x33, 0x66, 0x00,
1964 0x00, 0x33, 0x33, 0x00,
1965 0x00, 0x33, 0x00, 0x00,
1966 0x00, 0x00, 0xFF, 0x00,
1967 0x00, 0x00, 0xCC, 0x00,
1968 0x00, 0x00, 0x99, 0x00,
1969 0x00, 0x00, 0x66, 0x00,
1970 0x00, 0x00, 0x33, 0x00,
1971 0xEE, 0x00, 0x00, 0x00,
1972 0xDD, 0x00, 0x00, 0x00,
1973 0xBB, 0x00, 0x00, 0x00,
1974 0xAA, 0x00, 0x00, 0x00,
1975 0x88, 0x00, 0x00, 0x00,
1976 0x77, 0x00, 0x00, 0x00,
1977 0x55, 0x00, 0x00, 0x00,
1978 0x44, 0x00, 0x00, 0x00,
1979 0x22, 0x00, 0x00, 0x00,
1980 0x11, 0x00, 0x00, 0x00,
1981 0x00, 0xEE, 0x00, 0x00,
1982 0x00, 0xDD, 0x00, 0x00,
1983 0x00, 0xBB, 0x00, 0x00,
1984 0x00, 0xAA, 0x00, 0x00,
1985 0x00, 0x88, 0x00, 0x00,
1986 0x00, 0x77, 0x00, 0x00,
1987 0x00, 0x55, 0x00, 0x00,
1988 0x00, 0x44, 0x00, 0x00,
1989 0x00, 0x22, 0x00, 0x00,
1990 0x00, 0x11, 0x00, 0x00,
1991 0x00, 0x00, 0xEE, 0x00,
1992 0x00, 0x00, 0xDD, 0x00,
1993 0x00, 0x00, 0xBB, 0x00,
1994 0x00, 0x00, 0xAA, 0x00,
1995 0x00, 0x00, 0x88, 0x00,
1996 0x00, 0x00, 0x77, 0x00,
1997 0x00, 0x00, 0x55, 0x00,
1998 0x00, 0x00, 0x44, 0x00,
1999 0x00, 0x00, 0x22, 0x00,
2000 0x00, 0x00, 0x11, 0x00,
2001 0xEE, 0xEE, 0xEE, 0x00,
2002 0xDD, 0xDD, 0xDD, 0x00,
2003 0xBB, 0xBB, 0xBB, 0x00,
2004 0xAA, 0xAA, 0xAA, 0x00,
2005 0x88, 0x88, 0x88, 0x00,
2006 0x77, 0x77, 0x77, 0x00,
2007 0x55, 0x55, 0x55, 0x00,
2008 0x44, 0x44, 0x44, 0x00,
2009 0x22, 0x22, 0x22, 0x00,
2010 0x11, 0x11, 0x11, 0x00,
2011 0x00, 0x00, 0x00, 0x00
2012 ];
2013
2014 #[cfg(test)]
2015 mod test {
2016 use super::*;
2017 use std::fs::File;
2018
2019 #[test]
2020 fn test_mov_demux() {
2021 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2022 let mut fr = FileReader::new_read(&mut file);
2023 let mut br = ByteReader::new(&mut fr);
2024 let mut dmx = MOVDemuxer::new(&mut br);
2025 let mut sm = StreamManager::new();
2026 let mut si = SeekIndex::new();
2027 dmx.open(&mut sm, &mut si).unwrap();
2028
2029 loop {
2030 let pktres = dmx.get_frame(&mut sm);
2031 if let Err(e) = pktres {
2032 if e == DemuxerError::EOF { break; }
2033 panic!("error");
2034 }
2035 let pkt = pktres.unwrap();
2036 println!("Got {}", pkt);
2037 }
2038 }
2039
2040 #[test]
2041 fn test_dash_demux() {
2042 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2043 let mut fr = FileReader::new_read(&mut file);
2044 let mut br = ByteReader::new(&mut fr);
2045 let mut dmx = MOVDemuxer::new(&mut br);
2046 let mut sm = StreamManager::new();
2047 let mut si = SeekIndex::new();
2048 dmx.open(&mut sm, &mut si).unwrap();
2049
2050 loop {
2051 let pktres = dmx.get_frame(&mut sm);
2052 if let Err(e) = pktres {
2053 if e == DemuxerError::EOF { break; }
2054 panic!("error");
2055 }
2056 let pkt = pktres.unwrap();
2057 println!("Got {}", pkt);
2058 }
2059 }
2060 }