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