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