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