mov: fix track duration rescaling
[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 let edata = if br.tell() - start_pos + 4 < size {
609 //todo skip various common atoms
610 let edata_size = br.read_u32be()? as usize;
611 validate!(edata_size >= 4);
612 let mut buf = vec![0; edata_size - 4];
613 br.read_buf(buf.as_mut_slice())?;
614 Some(buf)
615 } else {
616 None
617 };
618 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
619 },
620 StreamType::Audio => {
621 let sver = br.read_u16be()?;
622 let _revision = br.read_u16le()?;
623 let _vendor = br.read_u32be()?;
624 let nchannels = br.read_u16be()?;
625 validate!(nchannels <= 64);
626 let sample_size = br.read_u16be()?;
627 validate!(sample_size <= 128);
628 let _compr_id = br.read_u16be()?;
629 let packet_size = br.read_u16be()? as usize;
630 validate!(packet_size == 0);
631 let sample_rate = br.read_u32be()?;
632 validate!(sample_rate > (1 << 16));
633 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
634 name
635 } 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]))) {
636 name
637 } else {
638 "unknown"
639 };
640 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
641 if &fcc == b"raw " && sample_size == 8 {
642 soniton.signed = false;
643 }
644 let block_align = 1;
645 if sver == 1 {
646 let samples_per_packet = br.read_u32be()?;
647 let _bytes_per_packet = br.read_u32be()?;
648 let bytes_per_frame = br.read_u32be()?;
649 let _bytes_per_sample = br.read_u32be()?;
650 track.bsize = bytes_per_frame as usize;
651 track.frame_samples = samples_per_packet as usize;
652 track.tb_num = samples_per_packet;
653 } else {
654 track.bsize = (sample_size / 8) as usize;
655 }
656 track.tb_den = sample_rate >> 16;
657 track.raw_audio = match &fcc {
658 b"NONE" | b"raw " | b"twos" | b"sowt" |
659 b"in24" | b"in32" | b"fl32" | b"fl64" |
660 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
661 b"alaw" | b"ulaw" |
662 b"MAC3" | b"MAC6" => true,
663 _ => false,
664 };
665 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
666 let edata = parse_audio_edata(br, start_pos, size)?;
667 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
668 track.channels = nchannels as usize;
669 track.bits = sample_size as usize;
670 },
671 StreamType::None => {
672 return Err(DemuxerError::InvalidData);
673 },
674 _ => {
675 //todo put it all into extradata
676 let edata = None;
677 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
678 },
679 };
680 let read_size = br.tell() - start_pos;
681 validate!(read_size <= size);
682 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
683 track.stsd_found = true;
684 Ok(read_size)
685 }
686
687 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
688 validate!(size >= 8);
689 let start_pos = br.tell();
690 let version = br.read_byte()?;
691 validate!(version == 0);
692 let _flags = br.read_u24be()?;
693 let entries = br.read_u32be()? as usize;
694 validate!(entries as u64 <= (size - 8) / 8);
695 if entries == 0 {
696 } else if entries == 1 {
697 let _count = br.read_u32be()?;
698 let tb_num = br.read_u32be()?;
699 validate!(tb_num != 0);
700 track.tb_div = tb_num;
701 if let Some(ref mut stream) = track.stream {
702 let tb_den = stream.tb_den;
703 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
704 stream.duration /= u64::from(track.tb_div);
705 stream.tb_num = tb_num;
706 stream.tb_den = tb_den;
707 track.tb_num = tb_num;
708 track.tb_den = tb_den;
709 track.duration /= track.tb_div;
710 }
711 } else {
712 track.time_to_sample.truncate(0);
713 track.time_to_sample.reserve(entries);
714 for _ in 0..entries {
715 let count = br.read_u32be()?;
716 let mult = br.read_u32be()?;
717 track.time_to_sample.push((count, mult));
718 }
719 }
720 let read_size = br.tell() - start_pos;
721 validate!(read_size <= size);
722 Ok(read_size)
723 }
724
725 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
726 let version = br.read_byte()?;
727 validate!(version == 0);
728 let _flags = br.read_u24be()?;
729 let entries = br.read_u32be()? as usize;
730 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
731 validate!((entries * 4 + 8) as u64 == size);
732 track.keyframes = Vec::with_capacity(entries);
733 let mut last_sample_no = 0;
734 for _ in 0..entries {
735 let sample_no = br.read_u32be()?;
736 validate!(sample_no > last_sample_no);
737 track.keyframes.push(sample_no);
738 last_sample_no = sample_no;
739 }
740 Ok(size)
741 }
742
743 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
744 let version = br.read_byte()?;
745 validate!(version == 0);
746 let _flags = br.read_u24be()?;
747 let entries = br.read_u32be()? as usize;
748 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
749 validate!((entries * 12 + 8) as u64 == size);
750 track.sample_map = Vec::with_capacity(entries);
751 let mut last_sample_no = 0;
752 for _i in 0..entries {
753 let sample_no = br.read_u32be()?;
754 validate!(sample_no > last_sample_no);
755 let nsamples = br.read_u32be()?;
756 let _sample_desc = br.read_u32be()?;
757 track.sample_map.push((sample_no, nsamples));
758 last_sample_no = sample_no;
759 }
760 Ok(size)
761 }
762
763 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
764 let version = br.read_byte()?;
765 validate!(version == 0);
766 let _flags = br.read_u24be()?;
767 let sample_size = br.read_u32be()?;
768 if sample_size != 0 {
769 track.sample_size = sample_size;
770 if track.sample_size != 1 || track.bsize == 0 {
771 track.bsize = sample_size as usize;
772 }
773 Ok(8)
774 } else {
775 let entries = br.read_u32be()? as usize;
776 validate!((entries * 4 + 12) as u64 == size);
777 track.chunk_sizes = Vec::with_capacity(entries);
778 for _ in 0..entries {
779 let sample_size = br.read_u32be()?;
780 track.chunk_sizes.push(sample_size);
781 }
782 Ok(size)
783 }
784 }
785
786 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
787 let version = br.read_byte()?;
788 validate!(version == 0);
789 let _flags = br.read_u24be()?;
790 let entries = br.read_u32be()? as usize;
791 validate!((entries * 4 + 8) as u64 == size);
792 track.chunk_offsets = Vec::with_capacity(entries);
793 for _i in 0..entries {
794 let sample_offset = br.read_u32be()?;
795 track.chunk_offsets.push(u64::from(sample_offset));
796 }
797 Ok(size)
798 }
799
800 fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
801 validate!(size >= 8);
802 let version = br.read_byte()?;
803 let _flags = br.read_u24be()?;
804 if version > 1 {
805 return Err(DemuxerError::NotImplemented);
806 }
807 let entries = br.read_u32be()? as usize;
808 track.ctts_version = version;
809 track.ctts_map.resize(entries);
810 match version {
811 0 | 1 => {
812 validate!(size == (entries as u64) * 8 + 8);
813 for _ in 0..entries {
814 let samp_count = br.read_u32be()?;
815 let samp_offset = br.read_u32be()?;
816 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
817 }
818 },
819 _ => unreachable!(),
820 };
821 track.ctts_map.reset();
822
823 Ok(size)
824 }
825
826 struct MOVDemuxer<'a> {
827 src: &'a mut ByteReader<'a>,
828 depth: usize,
829 mdat_pos: u64,
830 mdat_size: u64,
831 tracks: Vec<Track>,
832 cur_track: usize,
833 tb_den: u32,
834 duration: u32,
835 pal: Option<Arc<[u8; 1024]>>,
836
837 print_chunks: bool,
838 }
839
840 struct Track {
841 track_id: u32,
842 track_str_id: usize,
843 track_no: u32,
844 tb_num: u32,
845 tb_den: u32,
846 tb_div: u32,
847 raw_audio: bool,
848 raw_apos: u64,
849 duration: u32,
850 depth: u8,
851 tkhd_found: bool,
852 stsd_found: bool,
853 stream_type: StreamType,
854 width: usize,
855 height: usize,
856 channels: usize,
857 bits: usize,
858 bsize: usize,
859 fcc: [u8; 4],
860 keyframes: Vec<u32>,
861 chunk_sizes: Vec<u32>,
862 chunk_offsets: Vec<u64>,
863 time_to_sample: Vec<(u32, u32)>,
864 sample_map: Vec<(u32, u32)>,
865 sample_size: u32,
866 frame_samples: usize,
867 ctts_map: RLESearcher<u32>,
868 ctts_version: u8,
869 stream: Option<NAStream>,
870 cur_chunk: usize,
871 cur_sample: usize,
872 samples_left: usize,
873 last_offset: u64,
874 pal: Option<Arc<[u8; 1024]>>,
875 timesearch: TimeSearcher,
876
877 print_chunks: bool,
878 }
879
880 #[derive(Default)]
881 struct TimeSearcher {
882 idx: usize,
883 base: u64,
884 sbase: u32,
885 cur_len: u32,
886 cur_mul: u32,
887 }
888
889 impl TimeSearcher {
890 fn new() -> Self { Self::default() }
891 fn reset(&mut self) {
892 *self = Self::default();
893 }
894 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
895 if tts.is_empty() {
896 u64::from(sample)
897 } else if sample >= self.sbase {
898 let mut sample = sample - self.sbase;
899 if self.idx == 0 {
900 let (cur_len, cur_mul) = tts[0];
901 self.cur_len = cur_len;
902 self.cur_mul = cur_mul;
903 self.idx += 1;
904 }
905 while self.idx < tts.len() && sample > self.cur_len {
906 sample -= self.cur_len;
907 self.sbase += self.cur_len;
908 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
909 self.cur_len = tts[self.idx].0;
910 self.cur_mul = tts[self.idx].1;
911 self.idx += 1;
912 }
913 self.base + u64::from(sample) * u64::from(self.cur_mul)
914 } else {
915 self.reset();
916 self.map_time(sample, tts)
917 }
918 }
919 }
920
921 #[derive(Default)]
922 struct RLESearcher<T> {
923 array: Vec<(u32, T)>,
924 idx: usize,
925 start: u64,
926 next: u64,
927 }
928
929 impl<T:Default+Copy> RLESearcher<T> {
930 fn new() -> Self { Self::default() }
931 fn resize(&mut self, size: usize) {
932 self.array.truncate(0);
933 self.array.reserve(size);
934 }
935 fn add(&mut self, len: u32, val: T) {
936 self.array.push((len, val));
937 }
938 fn reset(&mut self) {
939 self.start = 0;
940 if !self.array.is_empty() {
941 self.idx = 0;
942 self.next = u64::from(self.array[0].0);
943 } else {
944 self.idx = self.array.len();
945 self.next = 0;
946 }
947 }
948 fn map(&mut self, sample: u64) -> Option<T> {
949 if sample < self.start {
950 self.reset();
951 }
952 if self.idx < self.array.len() {
953 if sample < self.next {
954 Some(self.array[self.idx].1)
955 } else {
956 while (self.idx < self.array.len()) && (sample >= self.next) {
957 self.start = self.next;
958 self.idx += 1;
959 if self.idx < self.array.len() {
960 self.next += u64::from(self.array[self.idx].0);
961 }
962 }
963 if self.idx < self.array.len() {
964 Some(self.array[self.idx].1)
965 } else {
966 None
967 }
968 }
969 } else {
970 None
971 }
972 }
973 }
974
975 impl Track {
976 fn new(track_no: u32, tb_den: u32) -> Self {
977 Self {
978 tkhd_found: false,
979 stsd_found: false,
980 track_id: 0,
981 track_str_id: 0,
982 track_no,
983 tb_num: 1,
984 tb_den,
985 tb_div: 1,
986 raw_audio: false,
987 raw_apos: 0,
988 duration: 0,
989 stream_type: StreamType::None,
990 width: 0,
991 height: 0,
992 channels: 0,
993 bits: 0,
994 bsize: 0,
995 fcc: [0; 4],
996 keyframes: Vec::new(),
997 chunk_sizes: Vec::new(),
998 chunk_offsets: Vec::new(),
999 time_to_sample: Vec::new(),
1000 sample_map: Vec::new(),
1001 sample_size: 0,
1002 frame_samples: 0,
1003 ctts_map: RLESearcher::new(),
1004 ctts_version: 0,
1005 stream: None,
1006 depth: 0,
1007 cur_chunk: 0,
1008 cur_sample: 0,
1009 samples_left: 0,
1010 last_offset: 0,
1011 pal: None,
1012 timesearch: TimeSearcher::new(),
1013
1014 print_chunks: false,
1015 }
1016 }
1017 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1018 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1019 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1020 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1021 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
1022 if !self.keyframes.is_empty() {
1023 seek_index.mode = SeekIndexMode::Present;
1024 }
1025 let mut tsearch = TimeSearcher::new();
1026 for kf_time in self.keyframes.iter() {
1027 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1028 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1029 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
1030 }
1031 }
1032 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1033 if nsamp == 0 {
1034 self.bsize
1035 } else {
1036 match &self.fcc {
1037 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1038 (nsamp * self.bits * self.channels + 7) >> 3
1039 },
1040 b"ima4" => {
1041 let nblocks = (nsamp + 63) >> 6;
1042 nblocks * 34 * self.channels
1043 },
1044 b"MAC3" => {
1045 (nsamp + 5) / 6 * 2 * self.channels
1046 },
1047 b"MAC6" => {
1048 (nsamp + 5) / 6 * self.channels
1049 },
1050 b"in24" => nsamp * 3 * self.channels,
1051 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1052 b"fl64" => nsamp * 8 * self.channels,
1053 b"ulaw" | b"alaw" => nsamp,
1054 b"ms\x00\x02" => { //MS ADPCM
1055 ((nsamp - 1) / 2 + 7) * self.channels
1056 },
1057 b"ms\x00\x21" => { //IMA ADPCM
1058 (nsamp / 2 + 4) * self.channels
1059 },
1060 _ => self.bsize,
1061 }
1062 }
1063 }
1064 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
1065 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
1066 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1067 let dts = match self.ctts_version {
1068 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1069 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1070 _ => unimplemented!(),
1071 };
1072 if (dts as i64) < 0 {
1073 None
1074 } else {
1075 Some(dts)
1076 }
1077 } else {
1078 None
1079 };
1080 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
1081 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1082 if self.cur_sample >= self.chunk_sizes.len() {
1083 return None;
1084 }
1085 let offset = self.chunk_offsets[self.cur_sample];
1086 let size = self.chunk_sizes[self.cur_sample] as usize;
1087 self.cur_sample += 1;
1088 Some((pts, offset, size))
1089 } else {
1090 if self.samples_left == 0 {
1091 if self.cur_chunk >= self.chunk_offsets.len() {
1092 return None;
1093 }
1094 for (idx, samples) in self.sample_map.iter() {
1095 if *idx as usize <= self.cur_chunk + 1 {
1096 self.samples_left = *samples as usize;
1097 } else {
1098 break;
1099 }
1100 }
1101 self.last_offset = self.chunk_offsets[self.cur_chunk];
1102 self.cur_chunk += 1;
1103 }
1104 let offset = self.last_offset;
1105 let size = self.get_size(self.cur_sample);
1106 self.last_offset += size as u64;
1107 if self.stream_type == StreamType::Video {
1108 self.samples_left -= 1;
1109 } else if self.frame_samples != 0 && self.bsize != 0 {
1110 let nblocks = size / self.bsize;
1111 if self.raw_audio {
1112 pts.pts = Some(self.raw_apos);
1113 pts.duration = Some(nblocks as u64);
1114 self.raw_apos += nblocks as u64;
1115 }
1116 if nblocks > 0 {
1117 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1118 self.samples_left -= consumed;
1119 } else {
1120 self.samples_left = 0;
1121 }
1122 } else if !self.raw_audio {
1123 self.samples_left -= 1;
1124 } else {
1125 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1126 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1127 let cur_size = self.calculate_chunk_size(self.samples_left);
1128 let add_off = (size - cur_size) as u64;
1129 let dsize = cur_size.min(max_size);
1130 if self.samples_left >= BLOCK_SAMPLES {
1131 self.cur_sample += BLOCK_SAMPLES;
1132 self.samples_left -= BLOCK_SAMPLES;
1133 self.last_offset -= size as u64;
1134 } else {
1135 self.cur_sample += self.samples_left;
1136 self.samples_left = 0;
1137 }
1138 return Some((pts, offset + add_off, dsize));
1139 }
1140 self.cur_sample += 1;
1141 Some((pts, offset, size))
1142 }
1143 }
1144 fn get_size(&self, sample_no: usize) -> usize {
1145 if !self.chunk_sizes.is_empty() {
1146 self.chunk_sizes[sample_no] as usize
1147 } else if !self.sample_map.is_empty() {
1148 let mut nsamp = 0;
1149 for (idx, samples) in self.sample_map.iter() {
1150 if *idx as usize <= self.cur_chunk {
1151 nsamp = *samples;
1152 } else {
1153 break;
1154 }
1155 }
1156 self.calculate_chunk_size(nsamp as usize)
1157 } else {
1158 self.bsize
1159 }
1160 }
1161 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1162 self.cur_sample = pts as usize;
1163 self.samples_left = 0;
1164 if self.stream_type == StreamType::Audio {
1165 if let NATimePoint::Milliseconds(ms) = tpoint {
1166 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1167 if self.raw_audio {
1168 if self.frame_samples != 0 {
1169 self.raw_apos = exp_pts / (self.frame_samples as u64);
1170 let mut apos = 0;
1171 self.cur_sample = 0;
1172 self.cur_chunk = 0;
1173 let mut cmap = self.sample_map.iter();
1174 let mut cur_samps = 0;
1175 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1176 loop {
1177 if self.cur_chunk + 1 == next_idx as usize {
1178 self.samples_left = cur_samps;
1179 cur_samps = next_samples as usize;
1180 if let Some((new_idx, new_samples)) = cmap.next() {
1181 next_idx = *new_idx;
1182 next_samples = *new_samples;
1183 }
1184 }
1185 self.raw_apos = apos;
1186 apos += (cur_samps / self.frame_samples) as u64;
1187 if apos > exp_pts {
1188 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1189 if self.cur_chunk >= self.chunk_offsets.len() {
1190 return Err(DemuxerError::SeekError);
1191 }
1192 self.last_offset = self.chunk_offsets[self.cur_chunk];
1193 break;
1194 }
1195 }
1196 self.cur_chunk += 1;
1197 }
1198 self.samples_left = cur_samps;
1199 self.cur_chunk += 1;
1200 } else {
1201 self.raw_apos = exp_pts;
1202 self.cur_sample = exp_pts as usize;
1203 let mut csamp = 0;
1204 self.cur_chunk = 0;
1205 let mut cmap = self.sample_map.iter();
1206 let mut cur_samps = 0;
1207 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1208 loop {
1209 if self.cur_chunk + 1 == next_idx as usize {
1210 self.samples_left = cur_samps;
1211 cur_samps = next_samples as usize;
1212 if let Some((new_idx, new_samples)) = cmap.next() {
1213 next_idx = *new_idx;
1214 next_samples = *new_samples;
1215 }
1216 }
1217 csamp += cur_samps;
1218 if csamp > self.cur_sample {
1219 if self.cur_chunk >= self.chunk_offsets.len() {
1220 return Err(DemuxerError::SeekError);
1221 }
1222 self.last_offset = self.chunk_offsets[self.cur_chunk];
1223 break;
1224 }
1225 self.cur_chunk += 1;
1226 }
1227 self.samples_left = csamp - self.cur_sample;
1228 self.cur_chunk += 1;
1229 }
1230 } else {
1231 self.cur_chunk = self.cur_sample;
1232 }
1233 } else {
1234 self.cur_chunk = self.cur_sample;
1235 }
1236 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1237 let mut csamp = 0;
1238 self.cur_chunk = 0;
1239 let mut cmap = self.sample_map.iter();
1240 let mut cur_samps = 0;
1241 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1242 loop {
1243 if self.cur_chunk + 1 == next_idx as usize {
1244 self.samples_left = cur_samps;
1245 cur_samps = next_samples as usize;
1246 if let Some((new_idx, new_samples)) = cmap.next() {
1247 next_idx = *new_idx;
1248 next_samples = *new_samples;
1249 }
1250 }
1251 csamp += cur_samps;
1252 if csamp >= self.cur_sample {
1253 if self.cur_chunk >= self.chunk_offsets.len() {
1254 return Err(DemuxerError::SeekError);
1255 }
1256 self.last_offset = self.chunk_offsets[self.cur_chunk];
1257 break;
1258 }
1259 self.cur_chunk += 1;
1260 }
1261 csamp -= cur_samps;
1262 for sample_no in csamp..self.cur_sample {
1263 self.last_offset += self.get_size(sample_no) as u64;
1264 }
1265 self.samples_left = csamp + cur_samps - self.cur_sample;
1266 self.cur_chunk += 1;
1267 }
1268 Ok(())
1269 }
1270 }
1271
1272 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1273 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1274 self.read_root(strmgr)?;
1275 validate!(self.mdat_pos > 0);
1276 validate!(!self.tracks.is_empty());
1277 for track in self.tracks.iter() {
1278 track.fill_seek_index(seek_index);
1279 }
1280 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1281 self.cur_track = 0;
1282 Ok(())
1283 }
1284
1285 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1286 if self.tracks.is_empty() {
1287 return Err(DemuxerError::EOF);
1288 }
1289 for _ in 0..self.tracks.len() {
1290 if self.cur_track >= self.tracks.len() {
1291 self.cur_track = 0;
1292 }
1293 let track = &mut self.tracks[self.cur_track];
1294 self.cur_track += 1;
1295 let first = track.cur_sample == 0;
1296 if let Some((pts, offset, size)) = track.get_next_chunk() {
1297 let str = strmgr.get_stream(track.track_str_id);
1298 if str.is_none() { return Err(DemuxerError::InvalidData); }
1299 let stream = str.unwrap();
1300 self.src.seek(SeekFrom::Start(offset))?;
1301 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1302 if let Some(ref pal) = track.pal {
1303 let side_data = NASideData::Palette(first, pal.clone());
1304 pkt.add_side_data(side_data);
1305 }
1306 return Ok(pkt);
1307 }
1308 }
1309 Err(DemuxerError::EOF)
1310 }
1311
1312 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1313 let ret = seek_index.find_pos(time);
1314 if ret.is_none() {
1315 return Err(DemuxerError::SeekError);
1316 }
1317 let seek_info = ret.unwrap();
1318 for track in self.tracks.iter_mut() {
1319 track.seek(seek_info.pts, time)?;
1320 }
1321 Ok(())
1322 }
1323 fn get_duration(&self) -> u64 {
1324 if self.tb_den != 0 {
1325 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1326 } else {
1327 0
1328 }
1329 }
1330 }
1331
1332 const PRINT_CHUNKS: &str = "print_chunks";
1333
1334 const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1335 NAOptionDefinition {
1336 name: PRINT_CHUNKS,
1337 description: "Print parsed file structure",
1338 opt_type: NAOptionDefinitionType::Bool },
1339 ];
1340
1341 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1342 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1343 fn set_options(&mut self, options: &[NAOption]) {
1344 for option in options.iter() {
1345 for opt_def in DEMUXER_OPTIONS.iter() {
1346 if opt_def.check(option).is_ok() {
1347 match (option.name, &option.value) {
1348 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1349 self.print_chunks = *val;
1350 },
1351 _ => {},
1352 }
1353 }
1354 }
1355 }
1356 }
1357 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1358 match name {
1359 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1360 _ => None,
1361 }
1362 }
1363 }
1364
1365 impl<'a> MOVDemuxer<'a> {
1366 fn new(io: &'a mut ByteReader<'a>) -> Self {
1367 MOVDemuxer {
1368 src: io,
1369 depth: 0,
1370 mdat_pos: 0,
1371 mdat_size: 0,
1372 tracks: Vec::with_capacity(2),
1373 cur_track: 0,
1374 tb_den: 0,
1375 duration: 0,
1376 pal: None,
1377
1378 print_chunks: false,
1379 }
1380 }
1381 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1382 self.depth = 0;
1383 while self.src.left() != 0 {
1384 let ret = read_chunk_header(&mut self.src);
1385 if ret.is_err() { break; }
1386 let (ctype, size) = ret.unwrap();
1387 if IGNORED_CHUNKS.contains(&ctype) {
1388 self.src.skip64(size)?;
1389 continue;
1390 }
1391 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1392 let read_size;
1393 if let Some(ref handler) = handler {
1394 read_size = (handler.parse)(self, strmgr, size)?;
1395 } else {
1396 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1397 read_size = 0;
1398 }
1399 validate!(read_size <= size);
1400 self.src.skip64(size - read_size)?;
1401 }
1402 //todo check if all needed chunks are found
1403 Ok(())
1404 }
1405 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1406 }
1407
1408 pub struct MOVDemuxerCreator { }
1409
1410 impl DemuxerCreator for MOVDemuxerCreator {
1411 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1412 Box::new(MOVDemuxer::new(br))
1413 }
1414 fn get_name(&self) -> &'static str { "mov" }
1415 }
1416
1417 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1418 0x93, 0x65, 0x5E, 0x00,
1419 0xFF, 0xFF, 0xFF, 0x00,
1420 0xDF, 0xD0, 0xAB, 0x00,
1421 0x00, 0x00, 0x00, 0x00
1422 ];
1423 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1424 0xFF, 0xFB, 0xFF, 0x00,
1425 0xEF, 0xD9, 0xBB, 0x00,
1426 0xE8, 0xC9, 0xB1, 0x00,
1427 0x93, 0x65, 0x5E, 0x00,
1428 0xFC, 0xDE, 0xE8, 0x00,
1429 0x9D, 0x88, 0x91, 0x00,
1430 0xFF, 0xFF, 0xFF, 0x00,
1431 0xFF, 0xFF, 0xFF, 0x00,
1432 0xFF, 0xFF, 0xFF, 0x00,
1433 0x47, 0x48, 0x37, 0x00,
1434 0x7A, 0x5E, 0x55, 0x00,
1435 0xDF, 0xD0, 0xAB, 0x00,
1436 0xFF, 0xFB, 0xF9, 0x00,
1437 0xE8, 0xCA, 0xC5, 0x00,
1438 0x8A, 0x7C, 0x77, 0x00,
1439 0x00, 0x00, 0x00, 0x00
1440 ];
1441 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1442 0xFF, 0xFF, 0xFF, 0x00,
1443 0xFF, 0xFF, 0xCC, 0x00,
1444 0xFF, 0xFF, 0x99, 0x00,
1445 0xFF, 0xFF, 0x66, 0x00,
1446 0xFF, 0xFF, 0x33, 0x00,
1447 0xFF, 0xFF, 0x00, 0x00,
1448 0xFF, 0xCC, 0xFF, 0x00,
1449 0xFF, 0xCC, 0xCC, 0x00,
1450 0xFF, 0xCC, 0x99, 0x00,
1451 0xFF, 0xCC, 0x66, 0x00,
1452 0xFF, 0xCC, 0x33, 0x00,
1453 0xFF, 0xCC, 0x00, 0x00,
1454 0xFF, 0x99, 0xFF, 0x00,
1455 0xFF, 0x99, 0xCC, 0x00,
1456 0xFF, 0x99, 0x99, 0x00,
1457 0xFF, 0x99, 0x66, 0x00,
1458 0xFF, 0x99, 0x33, 0x00,
1459 0xFF, 0x99, 0x00, 0x00,
1460 0xFF, 0x66, 0xFF, 0x00,
1461 0xFF, 0x66, 0xCC, 0x00,
1462 0xFF, 0x66, 0x99, 0x00,
1463 0xFF, 0x66, 0x66, 0x00,
1464 0xFF, 0x66, 0x33, 0x00,
1465 0xFF, 0x66, 0x00, 0x00,
1466 0xFF, 0x33, 0xFF, 0x00,
1467 0xFF, 0x33, 0xCC, 0x00,
1468 0xFF, 0x33, 0x99, 0x00,
1469 0xFF, 0x33, 0x66, 0x00,
1470 0xFF, 0x33, 0x33, 0x00,
1471 0xFF, 0x33, 0x00, 0x00,
1472 0xFF, 0x00, 0xFF, 0x00,
1473 0xFF, 0x00, 0xCC, 0x00,
1474 0xFF, 0x00, 0x99, 0x00,
1475 0xFF, 0x00, 0x66, 0x00,
1476 0xFF, 0x00, 0x33, 0x00,
1477 0xFF, 0x00, 0x00, 0x00,
1478 0xCC, 0xFF, 0xFF, 0x00,
1479 0xCC, 0xFF, 0xCC, 0x00,
1480 0xCC, 0xFF, 0x99, 0x00,
1481 0xCC, 0xFF, 0x66, 0x00,
1482 0xCC, 0xFF, 0x33, 0x00,
1483 0xCC, 0xFF, 0x00, 0x00,
1484 0xCC, 0xCC, 0xFF, 0x00,
1485 0xCC, 0xCC, 0xCC, 0x00,
1486 0xCC, 0xCC, 0x99, 0x00,
1487 0xCC, 0xCC, 0x66, 0x00,
1488 0xCC, 0xCC, 0x33, 0x00,
1489 0xCC, 0xCC, 0x00, 0x00,
1490 0xCC, 0x99, 0xFF, 0x00,
1491 0xCC, 0x99, 0xCC, 0x00,
1492 0xCC, 0x99, 0x99, 0x00,
1493 0xCC, 0x99, 0x66, 0x00,
1494 0xCC, 0x99, 0x33, 0x00,
1495 0xCC, 0x99, 0x00, 0x00,
1496 0xCC, 0x66, 0xFF, 0x00,
1497 0xCC, 0x66, 0xCC, 0x00,
1498 0xCC, 0x66, 0x99, 0x00,
1499 0xCC, 0x66, 0x66, 0x00,
1500 0xCC, 0x66, 0x33, 0x00,
1501 0xCC, 0x66, 0x00, 0x00,
1502 0xCC, 0x33, 0xFF, 0x00,
1503 0xCC, 0x33, 0xCC, 0x00,
1504 0xCC, 0x33, 0x99, 0x00,
1505 0xCC, 0x33, 0x66, 0x00,
1506 0xCC, 0x33, 0x33, 0x00,
1507 0xCC, 0x33, 0x00, 0x00,
1508 0xCC, 0x00, 0xFF, 0x00,
1509 0xCC, 0x00, 0xCC, 0x00,
1510 0xCC, 0x00, 0x99, 0x00,
1511 0xCC, 0x00, 0x66, 0x00,
1512 0xCC, 0x00, 0x33, 0x00,
1513 0xCC, 0x00, 0x00, 0x00,
1514 0x99, 0xFF, 0xFF, 0x00,
1515 0x99, 0xFF, 0xCC, 0x00,
1516 0x99, 0xFF, 0x99, 0x00,
1517 0x99, 0xFF, 0x66, 0x00,
1518 0x99, 0xFF, 0x33, 0x00,
1519 0x99, 0xFF, 0x00, 0x00,
1520 0x99, 0xCC, 0xFF, 0x00,
1521 0x99, 0xCC, 0xCC, 0x00,
1522 0x99, 0xCC, 0x99, 0x00,
1523 0x99, 0xCC, 0x66, 0x00,
1524 0x99, 0xCC, 0x33, 0x00,
1525 0x99, 0xCC, 0x00, 0x00,
1526 0x99, 0x99, 0xFF, 0x00,
1527 0x99, 0x99, 0xCC, 0x00,
1528 0x99, 0x99, 0x99, 0x00,
1529 0x99, 0x99, 0x66, 0x00,
1530 0x99, 0x99, 0x33, 0x00,
1531 0x99, 0x99, 0x00, 0x00,
1532 0x99, 0x66, 0xFF, 0x00,
1533 0x99, 0x66, 0xCC, 0x00,
1534 0x99, 0x66, 0x99, 0x00,
1535 0x99, 0x66, 0x66, 0x00,
1536 0x99, 0x66, 0x33, 0x00,
1537 0x99, 0x66, 0x00, 0x00,
1538 0x99, 0x33, 0xFF, 0x00,
1539 0x99, 0x33, 0xCC, 0x00,
1540 0x99, 0x33, 0x99, 0x00,
1541 0x99, 0x33, 0x66, 0x00,
1542 0x99, 0x33, 0x33, 0x00,
1543 0x99, 0x33, 0x00, 0x00,
1544 0x99, 0x00, 0xFF, 0x00,
1545 0x99, 0x00, 0xCC, 0x00,
1546 0x99, 0x00, 0x99, 0x00,
1547 0x99, 0x00, 0x66, 0x00,
1548 0x99, 0x00, 0x33, 0x00,
1549 0x99, 0x00, 0x00, 0x00,
1550 0x66, 0xFF, 0xFF, 0x00,
1551 0x66, 0xFF, 0xCC, 0x00,
1552 0x66, 0xFF, 0x99, 0x00,
1553 0x66, 0xFF, 0x66, 0x00,
1554 0x66, 0xFF, 0x33, 0x00,
1555 0x66, 0xFF, 0x00, 0x00,
1556 0x66, 0xCC, 0xFF, 0x00,
1557 0x66, 0xCC, 0xCC, 0x00,
1558 0x66, 0xCC, 0x99, 0x00,
1559 0x66, 0xCC, 0x66, 0x00,
1560 0x66, 0xCC, 0x33, 0x00,
1561 0x66, 0xCC, 0x00, 0x00,
1562 0x66, 0x99, 0xFF, 0x00,
1563 0x66, 0x99, 0xCC, 0x00,
1564 0x66, 0x99, 0x99, 0x00,
1565 0x66, 0x99, 0x66, 0x00,
1566 0x66, 0x99, 0x33, 0x00,
1567 0x66, 0x99, 0x00, 0x00,
1568 0x66, 0x66, 0xFF, 0x00,
1569 0x66, 0x66, 0xCC, 0x00,
1570 0x66, 0x66, 0x99, 0x00,
1571 0x66, 0x66, 0x66, 0x00,
1572 0x66, 0x66, 0x33, 0x00,
1573 0x66, 0x66, 0x00, 0x00,
1574 0x66, 0x33, 0xFF, 0x00,
1575 0x66, 0x33, 0xCC, 0x00,
1576 0x66, 0x33, 0x99, 0x00,
1577 0x66, 0x33, 0x66, 0x00,
1578 0x66, 0x33, 0x33, 0x00,
1579 0x66, 0x33, 0x00, 0x00,
1580 0x66, 0x00, 0xFF, 0x00,
1581 0x66, 0x00, 0xCC, 0x00,
1582 0x66, 0x00, 0x99, 0x00,
1583 0x66, 0x00, 0x66, 0x00,
1584 0x66, 0x00, 0x33, 0x00,
1585 0x66, 0x00, 0x00, 0x00,
1586 0x33, 0xFF, 0xFF, 0x00,
1587 0x33, 0xFF, 0xCC, 0x00,
1588 0x33, 0xFF, 0x99, 0x00,
1589 0x33, 0xFF, 0x66, 0x00,
1590 0x33, 0xFF, 0x33, 0x00,
1591 0x33, 0xFF, 0x00, 0x00,
1592 0x33, 0xCC, 0xFF, 0x00,
1593 0x33, 0xCC, 0xCC, 0x00,
1594 0x33, 0xCC, 0x99, 0x00,
1595 0x33, 0xCC, 0x66, 0x00,
1596 0x33, 0xCC, 0x33, 0x00,
1597 0x33, 0xCC, 0x00, 0x00,
1598 0x33, 0x99, 0xFF, 0x00,
1599 0x33, 0x99, 0xCC, 0x00,
1600 0x33, 0x99, 0x99, 0x00,
1601 0x33, 0x99, 0x66, 0x00,
1602 0x33, 0x99, 0x33, 0x00,
1603 0x33, 0x99, 0x00, 0x00,
1604 0x33, 0x66, 0xFF, 0x00,
1605 0x33, 0x66, 0xCC, 0x00,
1606 0x33, 0x66, 0x99, 0x00,
1607 0x33, 0x66, 0x66, 0x00,
1608 0x33, 0x66, 0x33, 0x00,
1609 0x33, 0x66, 0x00, 0x00,
1610 0x33, 0x33, 0xFF, 0x00,
1611 0x33, 0x33, 0xCC, 0x00,
1612 0x33, 0x33, 0x99, 0x00,
1613 0x33, 0x33, 0x66, 0x00,
1614 0x33, 0x33, 0x33, 0x00,
1615 0x33, 0x33, 0x00, 0x00,
1616 0x33, 0x00, 0xFF, 0x00,
1617 0x33, 0x00, 0xCC, 0x00,
1618 0x33, 0x00, 0x99, 0x00,
1619 0x33, 0x00, 0x66, 0x00,
1620 0x33, 0x00, 0x33, 0x00,
1621 0x33, 0x00, 0x00, 0x00,
1622 0x00, 0xFF, 0xFF, 0x00,
1623 0x00, 0xFF, 0xCC, 0x00,
1624 0x00, 0xFF, 0x99, 0x00,
1625 0x00, 0xFF, 0x66, 0x00,
1626 0x00, 0xFF, 0x33, 0x00,
1627 0x00, 0xFF, 0x00, 0x00,
1628 0x00, 0xCC, 0xFF, 0x00,
1629 0x00, 0xCC, 0xCC, 0x00,
1630 0x00, 0xCC, 0x99, 0x00,
1631 0x00, 0xCC, 0x66, 0x00,
1632 0x00, 0xCC, 0x33, 0x00,
1633 0x00, 0xCC, 0x00, 0x00,
1634 0x00, 0x99, 0xFF, 0x00,
1635 0x00, 0x99, 0xCC, 0x00,
1636 0x00, 0x99, 0x99, 0x00,
1637 0x00, 0x99, 0x66, 0x00,
1638 0x00, 0x99, 0x33, 0x00,
1639 0x00, 0x99, 0x00, 0x00,
1640 0x00, 0x66, 0xFF, 0x00,
1641 0x00, 0x66, 0xCC, 0x00,
1642 0x00, 0x66, 0x99, 0x00,
1643 0x00, 0x66, 0x66, 0x00,
1644 0x00, 0x66, 0x33, 0x00,
1645 0x00, 0x66, 0x00, 0x00,
1646 0x00, 0x33, 0xFF, 0x00,
1647 0x00, 0x33, 0xCC, 0x00,
1648 0x00, 0x33, 0x99, 0x00,
1649 0x00, 0x33, 0x66, 0x00,
1650 0x00, 0x33, 0x33, 0x00,
1651 0x00, 0x33, 0x00, 0x00,
1652 0x00, 0x00, 0xFF, 0x00,
1653 0x00, 0x00, 0xCC, 0x00,
1654 0x00, 0x00, 0x99, 0x00,
1655 0x00, 0x00, 0x66, 0x00,
1656 0x00, 0x00, 0x33, 0x00,
1657 0xEE, 0x00, 0x00, 0x00,
1658 0xDD, 0x00, 0x00, 0x00,
1659 0xBB, 0x00, 0x00, 0x00,
1660 0xAA, 0x00, 0x00, 0x00,
1661 0x88, 0x00, 0x00, 0x00,
1662 0x77, 0x00, 0x00, 0x00,
1663 0x55, 0x00, 0x00, 0x00,
1664 0x44, 0x00, 0x00, 0x00,
1665 0x22, 0x00, 0x00, 0x00,
1666 0x11, 0x00, 0x00, 0x00,
1667 0x00, 0xEE, 0x00, 0x00,
1668 0x00, 0xDD, 0x00, 0x00,
1669 0x00, 0xBB, 0x00, 0x00,
1670 0x00, 0xAA, 0x00, 0x00,
1671 0x00, 0x88, 0x00, 0x00,
1672 0x00, 0x77, 0x00, 0x00,
1673 0x00, 0x55, 0x00, 0x00,
1674 0x00, 0x44, 0x00, 0x00,
1675 0x00, 0x22, 0x00, 0x00,
1676 0x00, 0x11, 0x00, 0x00,
1677 0x00, 0x00, 0xEE, 0x00,
1678 0x00, 0x00, 0xDD, 0x00,
1679 0x00, 0x00, 0xBB, 0x00,
1680 0x00, 0x00, 0xAA, 0x00,
1681 0x00, 0x00, 0x88, 0x00,
1682 0x00, 0x00, 0x77, 0x00,
1683 0x00, 0x00, 0x55, 0x00,
1684 0x00, 0x00, 0x44, 0x00,
1685 0x00, 0x00, 0x22, 0x00,
1686 0x00, 0x00, 0x11, 0x00,
1687 0xEE, 0xEE, 0xEE, 0x00,
1688 0xDD, 0xDD, 0xDD, 0x00,
1689 0xBB, 0xBB, 0xBB, 0x00,
1690 0xAA, 0xAA, 0xAA, 0x00,
1691 0x88, 0x88, 0x88, 0x00,
1692 0x77, 0x77, 0x77, 0x00,
1693 0x55, 0x55, 0x55, 0x00,
1694 0x44, 0x44, 0x44, 0x00,
1695 0x22, 0x22, 0x22, 0x00,
1696 0x11, 0x11, 0x11, 0x00,
1697 0x00, 0x00, 0x00, 0x00
1698 ];
1699
1700 #[cfg(test)]
1701 mod test {
1702 use super::*;
1703 use std::fs::File;
1704
1705 #[test]
1706 fn test_mov_demux() {
1707 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1708 let mut fr = FileReader::new_read(&mut file);
1709 let mut br = ByteReader::new(&mut fr);
1710 let mut dmx = MOVDemuxer::new(&mut br);
1711 let mut sm = StreamManager::new();
1712 let mut si = SeekIndex::new();
1713 dmx.open(&mut sm, &mut si).unwrap();
1714
1715 loop {
1716 let pktres = dmx.get_frame(&mut sm);
1717 if let Err(e) = pktres {
1718 if e == DemuxerError::EOF { break; }
1719 panic!("error");
1720 }
1721 let pkt = pktres.unwrap();
1722 println!("Got {}", pkt);
1723 }
1724 }
1725 }