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