4904697e193a901b9b974f518ff90f559b75824f
[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
308 track.tkhd_found = true;
309 Ok(KNOWN_TKHD_SIZE)
310 }
311
312 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
313 track.stream_type = StreamType::None;
314 track.read_mdia(br, size)?;
315 Ok(size)
316 }
317
318 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
319 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
320 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
321 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
322 ];
323
324 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
325 const KNOWN_HDLR_SIZE: u64 = 24;
326 validate!(size >= KNOWN_HDLR_SIZE);
327 let version = br.read_byte()?;
328 validate!(version == 0);
329 let flags = br.read_u24be()?;
330 validate!(flags == 0);
331 let comp_type = br.read_u32be()?;
332 let comp_subtype = br.read_u32be()?;
333 let _comp_manufacturer = br.read_u32be()?;
334 let _comp_flags = br.read_u32be()?;
335 let _comp_flags_mask = br.read_u32be()?;
336
337 if comp_type == mktag!(b"mhlr") {
338 if comp_subtype == mktag!(b"vide") {
339 track.stream_type = StreamType::Video;
340 } else if comp_subtype == mktag!(b"soun") {
341 track.stream_type = StreamType::Audio;
342 } else {
343 track.stream_type = StreamType::Data;
344 }
345 } else if comp_type == mktag!(b"dhlr") {
346 track.stream_type = StreamType::Data;
347 } else {
348 println!("Unknown stream type");
349 track.stream_type = StreamType::Data;
350 }
351
352 Ok(KNOWN_HDLR_SIZE)
353 }
354
355 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
356 track.read_minf(br, size)?;
357 Ok(size)
358 }
359
360 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
361 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
362 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
364 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
365 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
366 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
367 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
368 ];
369
370 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
371 const KNOWN_VMHD_SIZE: u64 = 12;
372 validate!(track.stream_type == StreamType::Video);
373 validate!(size >= KNOWN_VMHD_SIZE);
374 let version = br.read_byte()?;
375 validate!(version == 0);
376 let _flags = br.read_u24be()?;
377 br.read_skip(2)?; // graphics mode
378 br.read_skip(6)?; // opcolor
379 Ok(KNOWN_VMHD_SIZE)
380 }
381
382 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
383 const KNOWN_SMHD_SIZE: u64 = 8;
384 validate!(track.stream_type == StreamType::Audio);
385 validate!(size >= KNOWN_SMHD_SIZE);
386 let version = br.read_byte()?;
387 validate!(version == 0);
388 let _flags = br.read_u24be()?;
389 br.read_skip(2)?; // balance
390 br.read_skip(2)?;
391 Ok(KNOWN_SMHD_SIZE)
392 }
393
394 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
395 validate!(track.stream_type == StreamType::Data);
396 Ok(0)
397 }
398
399 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
400 validate!(track.stream_type == StreamType::Data);
401 const KNOWN_GMIN_SIZE: u64 = 16;
402 validate!(size >= KNOWN_GMIN_SIZE);
403 let version = br.read_byte()?;
404 validate!(version == 0);
405 let _flags = br.read_u24be()?;
406 br.read_skip(2)?; // graphics mode
407 br.read_skip(6)?; // opcolor
408 br.read_skip(2)?; // balance
409 br.read_skip(2)?;
410 Ok(KNOWN_GMIN_SIZE)
411 }
412
413 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
414 track.read_stbl(br, size)?;
415 Ok(size)
416 }
417
418 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
419 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
420 TrackChunkHandler { ctype: mktag!(b"stts"), parse: skip_chunk },
421 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
422 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
423 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
424 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
425 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
426 ];
427
428 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
429 let read_part = br.tell() - start_pos;
430 if read_part + 8 < size {
431 let csize = br.read_u32be()? as u64;
432 let ctag = br.read_u32be()?;
433 validate!(read_part + csize <= size);
434 validate!(ctag == mktag!(b"wave"));
435 if csize == 8 {
436 return Ok(None);
437 }
438 let mut buf = [0; 8];
439 br.peek_buf(&mut buf)?;
440 if &buf[4..8] == b"frma" {
441 br.read_skip(12)?;
442 if csize > 20 {
443 let mut buf = vec![0; (csize - 20) as usize];
444 br.read_buf(&mut buf)?;
445 Ok(Some(buf))
446 } else {
447 Ok(None)
448 }
449 } else if csize > 8 {
450 let mut buf = vec![0; (csize as usize) - 8];
451 br.read_buf(&mut buf)?;
452 Ok(Some(buf))
453 } else {
454 Ok(None)
455 }
456 } else {
457 Ok(None)
458 }
459 }
460
461 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
462 const KNOWN_STSD_SIZE: u64 = 24;
463 validate!(size >= KNOWN_STSD_SIZE);
464 let start_pos = br.tell();
465 let version = br.read_byte()?;
466 validate!(version == 0);
467 let _flags = br.read_u24be()?;
468 let entries = br.read_u32be()?;
469 validate!(entries > 0);
470 let esize = u64::from(br.read_u32be()?);
471 validate!(esize + 8 <= size);
472 let mut fcc = [0u8; 4];
473 br.read_buf(&mut fcc)?;
474 br.read_skip(6)?;
475 let _data_ref = br.read_u16be()?;
476
477 track.fcc = fcc;
478
479 let codec_info;
480 match track.stream_type {
481 StreamType::Video => {
482 let _ver = br.read_u16be()?;
483 let _revision = br.read_u16le()?;
484 let _vendor = br.read_u32be()?;
485 let _temp_quality = br.read_u32be()?;
486 let _spat_quality = br.read_u32be()?;
487 let width = br.read_u16be()? as usize;
488 let height = br.read_u16be()? as usize;
489 let _hor_res = br.read_u32be()?;
490 let _vert_res = br.read_u32be()?;
491 let data_size = br.read_u32be()?;
492 validate!(data_size == 0);
493 let _frame_count = br.read_u16be()? as usize;
494 let _cname_len = br.read_byte()? as usize;
495 br.read_skip(31)?; // actual compressor name
496 let depth = br.read_u16be()?;
497 let ctable_id = br.read_u16be()?;
498 let grayscale = depth > 0x20 || depth == 1;
499 let depth = if grayscale { depth & 0x1F } else { depth };
500 validate!(depth <= 8 || (ctable_id == 0xFFFF));
501 if ctable_id == 0 {
502 let max_pal_size = start_pos + size - br.tell();
503 let mut pal = [0; 1024];
504 read_palette(br, max_pal_size, &mut pal)?;
505 track.pal = Some(Arc::new(pal));
506 } else if (depth <= 8) && !grayscale {
507 match depth & 0x1F {
508 2 => {
509 let mut pal = [0; 1024];
510 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
511 track.pal = Some(Arc::new(pal));
512 },
513 4 => {
514 let mut pal = [0; 1024];
515 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
516 track.pal = Some(Arc::new(pal));
517 },
518 8 => {
519 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
520 },
521 _ => {},
522 };
523 } else if grayscale && ctable_id != 0xFFFF {
524 let mut pal = [0; 1024];
525 let cdepth = depth & 0x1F;
526 let size = 1 << cdepth;
527 for i in 0..size {
528 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
529 let mut off = 8 - cdepth;
530 while off >= cdepth {
531 clr |= clr >> (8 - off);
532 off -= cdepth;
533 }
534 if off > 0 {
535 clr |= clr >> (8 - off);
536 }
537 pal[i * 4] = clr;
538 pal[i * 4 + 1] = clr;
539 pal[i * 4 + 2] = clr;
540 }
541 track.pal = Some(Arc::new(pal));
542 }
543 // todo other atoms, put as extradata
544 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
545 name
546 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
547 name
548 } else {
549 "unknown"
550 };
551 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
552 let mut vhdr = NAVideoInfo::new(width, height, false, format);
553 vhdr.bits = depth as u8;
554 let edata = if br.tell() - start_pos + 4 < size {
555 //todo skip various common atoms
556 let edata_size = br.read_u32be()? as usize;
557 validate!(edata_size >= 4);
558 let mut buf = vec![0; edata_size - 4];
559 br.read_buf(buf.as_mut_slice())?;
560 Some(buf)
561 } else {
562 None
563 };
564 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
565 },
566 StreamType::Audio => {
567 let sver = br.read_u16be()?;
568 let _revision = br.read_u16le()?;
569 let _vendor = br.read_u32be()?;
570 let nchannels = br.read_u16be()?;
571 validate!(nchannels <= 64);
572 let sample_size = br.read_u16be()?;
573 validate!(sample_size <= 128);
574 let _compr_id = br.read_u16be()?;
575 let packet_size = br.read_u16be()? as usize;
576 validate!(packet_size == 0);
577 let sample_rate = br.read_u32be()?;
578 validate!(sample_rate > 0);
579 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
580 name
581 } 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]))) {
582 name
583 } else {
584 "unknown"
585 };
586 //todo adjust format for various PCM kinds
587 let soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
588 let block_align = 1;
589 if sver == 1 {
590 let samples_per_packet = br.read_u32be()?;
591 let _bytes_per_packet = br.read_u32be()?;
592 let bytes_per_frame = br.read_u32be()?;
593 let _bytes_per_sample = br.read_u32be()?;
594 track.bsize = bytes_per_frame as usize;
595 track.frame_samples = samples_per_packet as usize;
596 } else {
597 track.bsize = sample_size as usize;
598 }
599 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
600 let edata = parse_audio_edata(br, start_pos, size)?;
601 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
602 track.channels = nchannels as usize;
603 track.bits = sample_size as usize;
604 },
605 StreamType::None => {
606 return Err(DemuxerError::InvalidData);
607 },
608 _ => {
609 //todo put it all into extradata
610 let edata = None;
611 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
612 },
613 };
614 let read_size = br.tell() - start_pos;
615 validate!(read_size <= size);
616 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den));
617 track.stsd_found = true;
618 Ok(read_size)
619 }
620
621 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
622 let version = br.read_byte()?;
623 validate!(version == 0);
624 let _flags = br.read_u24be()?;
625 let entries = br.read_u32be()? as usize;
626 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
627 validate!((entries * 4 + 8) as u64 == size);
628 track.keyframes = Vec::with_capacity(entries);
629 let mut last_sample_no = 0;
630 for _ in 0..entries {
631 let sample_no = br.read_u32be()?;
632 validate!(sample_no > last_sample_no);
633 track.keyframes.push(sample_no);
634 last_sample_no = sample_no;
635 }
636 Ok(size)
637 }
638
639 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
640 let version = br.read_byte()?;
641 validate!(version == 0);
642 let _flags = br.read_u24be()?;
643 let entries = br.read_u32be()? as usize;
644 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
645 validate!((entries * 12 + 8) as u64 == size);
646 track.sample_map = Vec::with_capacity(entries);
647 let mut last_sample_no = 0;
648 for _i in 0..entries {
649 let sample_no = br.read_u32be()?;
650 validate!(sample_no > last_sample_no);
651 let nsamples = br.read_u32be()?;
652 let _sample_desc = br.read_u32be()?;
653 track.sample_map.push((sample_no, nsamples));
654 last_sample_no = sample_no;
655 }
656 Ok(size)
657 }
658
659 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
660 let version = br.read_byte()?;
661 validate!(version == 0);
662 let _flags = br.read_u24be()?;
663 let sample_size = br.read_u32be()?;
664 if sample_size != 0 {
665 track.sample_size = sample_size;
666 if track.sample_size != 1 || track.bsize == 0 {
667 track.bsize = sample_size as usize;
668 }
669 Ok(8)
670 } else {
671 let entries = br.read_u32be()? as usize;
672 validate!((entries * 4 + 12) as u64 == size);
673 track.chunk_sizes = Vec::with_capacity(entries);
674 for _ in 0..entries {
675 let sample_size = br.read_u32be()?;
676 track.chunk_sizes.push(sample_size);
677 }
678 Ok(size)
679 }
680 }
681
682 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
683 let version = br.read_byte()?;
684 validate!(version == 0);
685 let _flags = br.read_u24be()?;
686 let entries = br.read_u32be()? as usize;
687 validate!((entries * 4 + 8) as u64 == size);
688 track.chunk_offsets = Vec::with_capacity(entries);
689 for _i in 0..entries {
690 let sample_offset = br.read_u32be()?;
691 track.chunk_offsets.push(u64::from(sample_offset));
692 }
693 Ok(size)
694 }
695
696 struct MOVDemuxer<'a> {
697 src: &'a mut ByteReader<'a>,
698 depth: usize,
699 mdat_pos: u64,
700 mdat_size: u64,
701 tracks: Vec<Track>,
702 cur_track: usize,
703 tb_den: u32,
704 duration: u32,
705 pal: Option<Arc<[u8; 1024]>>,
706 }
707
708 struct Track {
709 track_id: u32,
710 track_str_id: usize,
711 track_no: u32,
712 tb_den: u32,
713 depth: u8,
714 tkhd_found: bool,
715 stsd_found: bool,
716 stream_type: StreamType,
717 width: usize,
718 height: usize,
719 channels: usize,
720 bits: usize,
721 bsize: usize,
722 fcc: [u8; 4],
723 keyframes: Vec<u32>,
724 chunk_sizes: Vec<u32>,
725 chunk_offsets: Vec<u64>,
726 sample_map: Vec<(u32, u32)>,
727 sample_size: u32,
728 frame_samples: usize,
729 stream: Option<NAStream>,
730 cur_chunk: usize,
731 cur_sample: usize,
732 samples_left: usize,
733 last_offset: u64,
734 pal: Option<Arc<[u8; 1024]>>,
735 }
736
737 impl Track {
738 fn new(track_no: u32, tb_den: u32) -> Self {
739 Self {
740 tkhd_found: false,
741 stsd_found: false,
742 track_id: 0,
743 track_str_id: 0,
744 track_no,
745 tb_den,
746 stream_type: StreamType::None,
747 width: 0,
748 height: 0,
749 channels: 0,
750 bits: 0,
751 bsize: 0,
752 fcc: [0; 4],
753 keyframes: Vec::new(),
754 chunk_sizes: Vec::new(),
755 chunk_offsets: Vec::new(),
756 sample_map: Vec::new(),
757 sample_size: 0,
758 frame_samples: 0,
759 stream: None,
760 depth: 0,
761 cur_chunk: 0,
762 cur_sample: 0,
763 samples_left: 0,
764 last_offset: 0,
765 pal: None,
766 }
767 }
768 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
769 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
770 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
771 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
772 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
773 if !self.keyframes.is_empty() {
774 seek_index.mode = SeekIndexMode::Present;
775 }
776 for kf_time in self.keyframes.iter() {
777 let pts = u64::from(*kf_time - 1);
778 let time = NATimeInfo::ts_to_time(pts, 1000, 1, self.tb_den);
779 let idx = (*kf_time - 1) as usize;
780 if idx < self.chunk_offsets.len() {
781 let pos = self.chunk_offsets[idx];
782 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts, pos });
783 }
784 }
785 }
786 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
787 if nsamp == 0 {
788 self.bsize
789 } else {
790 match &self.fcc {
791 b"NONE" | b"raw " | b"twos" | b"sowt" => {
792 (nsamp * self.bits * self.channels + 7) >> 3
793 },
794 b"ima4" => {
795 let nblocks = (nsamp + 63) >> 6;
796 nblocks * 34 * self.channels
797 },
798 b"MAC3" => {
799 (nsamp + 5) / 6 * 2 * self.channels
800 },
801 b"MAC6" => {
802 (nsamp + 5) / 6 * self.channels
803 },
804 b"in24" => nsamp * 3 * self.channels,
805 b"in32" | b"fl32" => nsamp * 4 * self.channels,
806 b"fl64" => nsamp * 8 * self.channels,
807 b"ulaw" | b"alaw" => nsamp,
808 b"ms\x00\x02" => { //MS ADPCM
809 ((nsamp - 1) / 2 + 7) * self.channels
810 },
811 b"ms\x00\x21" => { //IMA ADPCM
812 (nsamp / 2 + 4) * self.channels
813 },
814 _ => self.bsize,
815 }
816 }
817 }
818 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
819 let pts = NATimeInfo::new(Some(self.cur_sample as u64), None, None, 1, self.tb_den);
820 //todo dts decoding
821 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
822 if self.cur_sample >= self.chunk_sizes.len() {
823 return None;
824 }
825 let offset = self.chunk_offsets[self.cur_sample];
826 let size = self.chunk_sizes[self.cur_sample] as usize;
827 self.cur_sample += 1;
828 Some((pts, offset, size))
829 } else {
830 if self.samples_left == 0 {
831 if self.cur_chunk >= self.chunk_offsets.len() {
832 return None;
833 }
834 for (idx, samples) in self.sample_map.iter() {
835 if *idx as usize <= self.cur_chunk + 1 {
836 self.samples_left = *samples as usize;
837 } else {
838 break;
839 }
840 }
841 self.last_offset = self.chunk_offsets[self.cur_chunk];
842 self.cur_chunk += 1;
843 }
844 let offset = self.last_offset;
845 let size = self.get_size(self.cur_sample);
846 self.last_offset += size as u64;
847 if self.stream_type == StreamType::Video {
848 self.samples_left -= 1;
849 } else if self.frame_samples != 0 && self.bsize != 0 {
850 let nblocks = size / self.bsize;
851 if nblocks > 0 {
852 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
853 self.samples_left -= consumed;
854 } else {
855 self.samples_left = 0;
856 }
857 } else {
858 self.samples_left = 0;
859 }
860 self.cur_sample += 1;
861 Some((pts, offset, size))
862 }
863 }
864 fn get_size(&self, sample_no: usize) -> usize {
865 if !self.chunk_sizes.is_empty() {
866 self.chunk_sizes[sample_no] as usize
867 } else if !self.sample_map.is_empty() {
868 let mut nsamp = 0;
869 for (idx, samples) in self.sample_map.iter() {
870 if *idx as usize <= self.cur_chunk {
871 nsamp = *samples;
872 } else {
873 break;
874 }
875 }
876 self.calculate_chunk_size(nsamp as usize)
877 } else {
878 self.bsize
879 }
880 }
881 fn seek(&mut self, pts: u64) {
882 self.cur_sample = pts as usize;
883 self.samples_left = 0;
884 if self.stream_type == StreamType::Audio {
885 self.cur_chunk = self.cur_sample;
886 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
887 let mut csamp = 0;
888 self.cur_chunk = 0;
889 let mut cmap = self.sample_map.iter();
890 let mut cur_samps = 0;
891 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
892 loop {
893 if self.cur_chunk == next_idx as usize {
894 self.samples_left = cur_samps;
895 cur_samps = next_samples as usize;
896 if let Some((new_idx, new_samples)) = cmap.next() {
897 next_idx = *new_idx;
898 next_samples = *new_samples;
899 }
900 }
901 csamp += cur_samps;
902 if csamp >= self.cur_sample {
903 self.last_offset = self.chunk_offsets[self.cur_chunk];
904 break;
905 }
906 self.cur_chunk += 1;
907 }
908 csamp -= cur_samps;
909 for sample_no in csamp..self.cur_chunk {
910 self.last_offset += self.get_size(sample_no) as u64;
911 }
912 self.samples_left = self.cur_sample - csamp - cur_samps;
913 }
914 }
915 }
916
917 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
918 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
919 self.read_root(strmgr)?;
920 validate!(self.mdat_pos > 0);
921 validate!(!self.tracks.is_empty());
922 for track in self.tracks.iter() {
923 track.fill_seek_index(seek_index);
924 }
925 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
926 self.cur_track = 0;
927 Ok(())
928 }
929
930 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
931 if self.tracks.is_empty() {
932 return Err(DemuxerError::EOF);
933 }
934 for _ in 0..self.tracks.len() {
935 if self.cur_track >= self.tracks.len() {
936 self.cur_track = 0;
937 }
938 let track = &mut self.tracks[self.cur_track];
939 self.cur_track += 1;
940 let first = track.cur_sample == 0;
941 if let Some((pts, offset, size)) = track.get_next_chunk() {
942 let str = strmgr.get_stream(track.track_str_id);
943 if str.is_none() { return Err(DemuxerError::InvalidData); }
944 let stream = str.unwrap();
945 self.src.seek(SeekFrom::Start(offset))?;
946 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
947 if let Some(ref pal) = track.pal {
948 let side_data = NASideData::Palette(first, pal.clone());
949 pkt.add_side_data(side_data);
950 }
951 return Ok(pkt);
952 }
953 }
954 Err(DemuxerError::EOF)
955 }
956
957 fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {
958 let ret = seek_index.find_pos(time);
959 if ret.is_none() {
960 return Err(DemuxerError::SeekError);
961 }
962 let seek_info = ret.unwrap();
963 for track in self.tracks.iter_mut() {
964 track.seek(seek_info.pts);
965 }
966 Ok(())
967 }
968 }
969
970 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
971 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
972 fn set_options(&mut self, _options: &[NAOption]) { }
973 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
974 }
975
976 impl<'a> MOVDemuxer<'a> {
977 fn new(io: &'a mut ByteReader<'a>) -> Self {
978 MOVDemuxer {
979 src: io,
980 depth: 0,
981 mdat_pos: 0,
982 mdat_size: 0,
983 tracks: Vec::with_capacity(2),
984 cur_track: 0,
985 tb_den: 0,
986 duration: 0,
987 pal: None,
988 }
989 }
990 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
991 self.depth = 0;
992 while self.src.left() != 0 {
993 let ret = read_chunk_header(&mut self.src);
994 if ret.is_err() { break; }
995 let (ctype, size) = ret.unwrap();
996 if IGNORED_CHUNKS.contains(&ctype) {
997 self.src.skip64(size)?;
998 continue;
999 }
1000 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1001 let read_size;
1002 if let Some(ref handler) = handler {
1003 read_size = (handler.parse)(self, strmgr, size)?;
1004 } else {
1005 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1006 read_size = 0;
1007 }
1008 validate!(read_size <= size);
1009 self.src.skip64(size - read_size)?;
1010 }
1011 //todo check if all needed chunks are found
1012 Ok(())
1013 }
1014 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1015 }
1016
1017 pub struct MOVDemuxerCreator { }
1018
1019 impl DemuxerCreator for MOVDemuxerCreator {
1020 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1021 Box::new(MOVDemuxer::new(br))
1022 }
1023 fn get_name(&self) -> &'static str { "mov" }
1024 }
1025
1026 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1027 0x93, 0x65, 0x5E, 0x00,
1028 0xFF, 0xFF, 0xFF, 0x00,
1029 0xDF, 0xD0, 0xAB, 0x00,
1030 0x00, 0x00, 0x00, 0x00
1031 ];
1032 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1033 0xFF, 0xFB, 0xFF, 0x00,
1034 0xEF, 0xD9, 0xBB, 0x00,
1035 0xE8, 0xC9, 0xB1, 0x00,
1036 0x93, 0x65, 0x5E, 0x00,
1037 0xFC, 0xDE, 0xE8, 0x00,
1038 0x9D, 0x88, 0x91, 0x00,
1039 0xFF, 0xFF, 0xFF, 0x00,
1040 0xFF, 0xFF, 0xFF, 0x00,
1041 0xFF, 0xFF, 0xFF, 0x00,
1042 0x47, 0x48, 0x37, 0x00,
1043 0x7A, 0x5E, 0x55, 0x00,
1044 0xDF, 0xD0, 0xAB, 0x00,
1045 0xFF, 0xFB, 0xF9, 0x00,
1046 0xE8, 0xCA, 0xC5, 0x00,
1047 0x8A, 0x7C, 0x77, 0x00,
1048 0x00, 0x00, 0x00, 0x00
1049 ];
1050 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1051 0xFF, 0xFF, 0xFF, 0x00,
1052 0xFF, 0xFF, 0xCC, 0x00,
1053 0xFF, 0xFF, 0x99, 0x00,
1054 0xFF, 0xFF, 0x66, 0x00,
1055 0xFF, 0xFF, 0x33, 0x00,
1056 0xFF, 0xFF, 0x00, 0x00,
1057 0xFF, 0xCC, 0xFF, 0x00,
1058 0xFF, 0xCC, 0xCC, 0x00,
1059 0xFF, 0xCC, 0x99, 0x00,
1060 0xFF, 0xCC, 0x66, 0x00,
1061 0xFF, 0xCC, 0x33, 0x00,
1062 0xFF, 0xCC, 0x00, 0x00,
1063 0xFF, 0x99, 0xFF, 0x00,
1064 0xFF, 0x99, 0xCC, 0x00,
1065 0xFF, 0x99, 0x99, 0x00,
1066 0xFF, 0x99, 0x66, 0x00,
1067 0xFF, 0x99, 0x33, 0x00,
1068 0xFF, 0x99, 0x00, 0x00,
1069 0xFF, 0x66, 0xFF, 0x00,
1070 0xFF, 0x66, 0xCC, 0x00,
1071 0xFF, 0x66, 0x99, 0x00,
1072 0xFF, 0x66, 0x66, 0x00,
1073 0xFF, 0x66, 0x33, 0x00,
1074 0xFF, 0x66, 0x00, 0x00,
1075 0xFF, 0x33, 0xFF, 0x00,
1076 0xFF, 0x33, 0xCC, 0x00,
1077 0xFF, 0x33, 0x99, 0x00,
1078 0xFF, 0x33, 0x66, 0x00,
1079 0xFF, 0x33, 0x33, 0x00,
1080 0xFF, 0x33, 0x00, 0x00,
1081 0xFF, 0x00, 0xFF, 0x00,
1082 0xFF, 0x00, 0xCC, 0x00,
1083 0xFF, 0x00, 0x99, 0x00,
1084 0xFF, 0x00, 0x66, 0x00,
1085 0xFF, 0x00, 0x33, 0x00,
1086 0xFF, 0x00, 0x00, 0x00,
1087 0xCC, 0xFF, 0xFF, 0x00,
1088 0xCC, 0xFF, 0xCC, 0x00,
1089 0xCC, 0xFF, 0x99, 0x00,
1090 0xCC, 0xFF, 0x66, 0x00,
1091 0xCC, 0xFF, 0x33, 0x00,
1092 0xCC, 0xFF, 0x00, 0x00,
1093 0xCC, 0xCC, 0xFF, 0x00,
1094 0xCC, 0xCC, 0xCC, 0x00,
1095 0xCC, 0xCC, 0x99, 0x00,
1096 0xCC, 0xCC, 0x66, 0x00,
1097 0xCC, 0xCC, 0x33, 0x00,
1098 0xCC, 0xCC, 0x00, 0x00,
1099 0xCC, 0x99, 0xFF, 0x00,
1100 0xCC, 0x99, 0xCC, 0x00,
1101 0xCC, 0x99, 0x99, 0x00,
1102 0xCC, 0x99, 0x66, 0x00,
1103 0xCC, 0x99, 0x33, 0x00,
1104 0xCC, 0x99, 0x00, 0x00,
1105 0xCC, 0x66, 0xFF, 0x00,
1106 0xCC, 0x66, 0xCC, 0x00,
1107 0xCC, 0x66, 0x99, 0x00,
1108 0xCC, 0x66, 0x66, 0x00,
1109 0xCC, 0x66, 0x33, 0x00,
1110 0xCC, 0x66, 0x00, 0x00,
1111 0xCC, 0x33, 0xFF, 0x00,
1112 0xCC, 0x33, 0xCC, 0x00,
1113 0xCC, 0x33, 0x99, 0x00,
1114 0xCC, 0x33, 0x66, 0x00,
1115 0xCC, 0x33, 0x33, 0x00,
1116 0xCC, 0x33, 0x00, 0x00,
1117 0xCC, 0x00, 0xFF, 0x00,
1118 0xCC, 0x00, 0xCC, 0x00,
1119 0xCC, 0x00, 0x99, 0x00,
1120 0xCC, 0x00, 0x66, 0x00,
1121 0xCC, 0x00, 0x33, 0x00,
1122 0xCC, 0x00, 0x00, 0x00,
1123 0x99, 0xFF, 0xFF, 0x00,
1124 0x99, 0xFF, 0xCC, 0x00,
1125 0x99, 0xFF, 0x99, 0x00,
1126 0x99, 0xFF, 0x66, 0x00,
1127 0x99, 0xFF, 0x33, 0x00,
1128 0x99, 0xFF, 0x00, 0x00,
1129 0x99, 0xCC, 0xFF, 0x00,
1130 0x99, 0xCC, 0xCC, 0x00,
1131 0x99, 0xCC, 0x99, 0x00,
1132 0x99, 0xCC, 0x66, 0x00,
1133 0x99, 0xCC, 0x33, 0x00,
1134 0x99, 0xCC, 0x00, 0x00,
1135 0x99, 0x99, 0xFF, 0x00,
1136 0x99, 0x99, 0xCC, 0x00,
1137 0x99, 0x99, 0x99, 0x00,
1138 0x99, 0x99, 0x66, 0x00,
1139 0x99, 0x99, 0x33, 0x00,
1140 0x99, 0x99, 0x00, 0x00,
1141 0x99, 0x66, 0xFF, 0x00,
1142 0x99, 0x66, 0xCC, 0x00,
1143 0x99, 0x66, 0x99, 0x00,
1144 0x99, 0x66, 0x66, 0x00,
1145 0x99, 0x66, 0x33, 0x00,
1146 0x99, 0x66, 0x00, 0x00,
1147 0x99, 0x33, 0xFF, 0x00,
1148 0x99, 0x33, 0xCC, 0x00,
1149 0x99, 0x33, 0x99, 0x00,
1150 0x99, 0x33, 0x66, 0x00,
1151 0x99, 0x33, 0x33, 0x00,
1152 0x99, 0x33, 0x00, 0x00,
1153 0x99, 0x00, 0xFF, 0x00,
1154 0x99, 0x00, 0xCC, 0x00,
1155 0x99, 0x00, 0x99, 0x00,
1156 0x99, 0x00, 0x66, 0x00,
1157 0x99, 0x00, 0x33, 0x00,
1158 0x99, 0x00, 0x00, 0x00,
1159 0x66, 0xFF, 0xFF, 0x00,
1160 0x66, 0xFF, 0xCC, 0x00,
1161 0x66, 0xFF, 0x99, 0x00,
1162 0x66, 0xFF, 0x66, 0x00,
1163 0x66, 0xFF, 0x33, 0x00,
1164 0x66, 0xFF, 0x00, 0x00,
1165 0x66, 0xCC, 0xFF, 0x00,
1166 0x66, 0xCC, 0xCC, 0x00,
1167 0x66, 0xCC, 0x99, 0x00,
1168 0x66, 0xCC, 0x66, 0x00,
1169 0x66, 0xCC, 0x33, 0x00,
1170 0x66, 0xCC, 0x00, 0x00,
1171 0x66, 0x99, 0xFF, 0x00,
1172 0x66, 0x99, 0xCC, 0x00,
1173 0x66, 0x99, 0x99, 0x00,
1174 0x66, 0x99, 0x66, 0x00,
1175 0x66, 0x99, 0x33, 0x00,
1176 0x66, 0x99, 0x00, 0x00,
1177 0x66, 0x66, 0xFF, 0x00,
1178 0x66, 0x66, 0xCC, 0x00,
1179 0x66, 0x66, 0x99, 0x00,
1180 0x66, 0x66, 0x66, 0x00,
1181 0x66, 0x66, 0x33, 0x00,
1182 0x66, 0x66, 0x00, 0x00,
1183 0x66, 0x33, 0xFF, 0x00,
1184 0x66, 0x33, 0xCC, 0x00,
1185 0x66, 0x33, 0x99, 0x00,
1186 0x66, 0x33, 0x66, 0x00,
1187 0x66, 0x33, 0x33, 0x00,
1188 0x66, 0x33, 0x00, 0x00,
1189 0x66, 0x00, 0xFF, 0x00,
1190 0x66, 0x00, 0xCC, 0x00,
1191 0x66, 0x00, 0x99, 0x00,
1192 0x66, 0x00, 0x66, 0x00,
1193 0x66, 0x00, 0x33, 0x00,
1194 0x66, 0x00, 0x00, 0x00,
1195 0x33, 0xFF, 0xFF, 0x00,
1196 0x33, 0xFF, 0xCC, 0x00,
1197 0x33, 0xFF, 0x99, 0x00,
1198 0x33, 0xFF, 0x66, 0x00,
1199 0x33, 0xFF, 0x33, 0x00,
1200 0x33, 0xFF, 0x00, 0x00,
1201 0x33, 0xCC, 0xFF, 0x00,
1202 0x33, 0xCC, 0xCC, 0x00,
1203 0x33, 0xCC, 0x99, 0x00,
1204 0x33, 0xCC, 0x66, 0x00,
1205 0x33, 0xCC, 0x33, 0x00,
1206 0x33, 0xCC, 0x00, 0x00,
1207 0x33, 0x99, 0xFF, 0x00,
1208 0x33, 0x99, 0xCC, 0x00,
1209 0x33, 0x99, 0x99, 0x00,
1210 0x33, 0x99, 0x66, 0x00,
1211 0x33, 0x99, 0x33, 0x00,
1212 0x33, 0x99, 0x00, 0x00,
1213 0x33, 0x66, 0xFF, 0x00,
1214 0x33, 0x66, 0xCC, 0x00,
1215 0x33, 0x66, 0x99, 0x00,
1216 0x33, 0x66, 0x66, 0x00,
1217 0x33, 0x66, 0x33, 0x00,
1218 0x33, 0x66, 0x00, 0x00,
1219 0x33, 0x33, 0xFF, 0x00,
1220 0x33, 0x33, 0xCC, 0x00,
1221 0x33, 0x33, 0x99, 0x00,
1222 0x33, 0x33, 0x66, 0x00,
1223 0x33, 0x33, 0x33, 0x00,
1224 0x33, 0x33, 0x00, 0x00,
1225 0x33, 0x00, 0xFF, 0x00,
1226 0x33, 0x00, 0xCC, 0x00,
1227 0x33, 0x00, 0x99, 0x00,
1228 0x33, 0x00, 0x66, 0x00,
1229 0x33, 0x00, 0x33, 0x00,
1230 0x33, 0x00, 0x00, 0x00,
1231 0x00, 0xFF, 0xFF, 0x00,
1232 0x00, 0xFF, 0xCC, 0x00,
1233 0x00, 0xFF, 0x99, 0x00,
1234 0x00, 0xFF, 0x66, 0x00,
1235 0x00, 0xFF, 0x33, 0x00,
1236 0x00, 0xFF, 0x00, 0x00,
1237 0x00, 0xCC, 0xFF, 0x00,
1238 0x00, 0xCC, 0xCC, 0x00,
1239 0x00, 0xCC, 0x99, 0x00,
1240 0x00, 0xCC, 0x66, 0x00,
1241 0x00, 0xCC, 0x33, 0x00,
1242 0x00, 0xCC, 0x00, 0x00,
1243 0x00, 0x99, 0xFF, 0x00,
1244 0x00, 0x99, 0xCC, 0x00,
1245 0x00, 0x99, 0x99, 0x00,
1246 0x00, 0x99, 0x66, 0x00,
1247 0x00, 0x99, 0x33, 0x00,
1248 0x00, 0x99, 0x00, 0x00,
1249 0x00, 0x66, 0xFF, 0x00,
1250 0x00, 0x66, 0xCC, 0x00,
1251 0x00, 0x66, 0x99, 0x00,
1252 0x00, 0x66, 0x66, 0x00,
1253 0x00, 0x66, 0x33, 0x00,
1254 0x00, 0x66, 0x00, 0x00,
1255 0x00, 0x33, 0xFF, 0x00,
1256 0x00, 0x33, 0xCC, 0x00,
1257 0x00, 0x33, 0x99, 0x00,
1258 0x00, 0x33, 0x66, 0x00,
1259 0x00, 0x33, 0x33, 0x00,
1260 0x00, 0x33, 0x00, 0x00,
1261 0x00, 0x00, 0xFF, 0x00,
1262 0x00, 0x00, 0xCC, 0x00,
1263 0x00, 0x00, 0x99, 0x00,
1264 0x00, 0x00, 0x66, 0x00,
1265 0x00, 0x00, 0x33, 0x00,
1266 0xEE, 0x00, 0x00, 0x00,
1267 0xDD, 0x00, 0x00, 0x00,
1268 0xBB, 0x00, 0x00, 0x00,
1269 0xAA, 0x00, 0x00, 0x00,
1270 0x88, 0x00, 0x00, 0x00,
1271 0x77, 0x00, 0x00, 0x00,
1272 0x55, 0x00, 0x00, 0x00,
1273 0x44, 0x00, 0x00, 0x00,
1274 0x22, 0x00, 0x00, 0x00,
1275 0x11, 0x00, 0x00, 0x00,
1276 0x00, 0xEE, 0x00, 0x00,
1277 0x00, 0xDD, 0x00, 0x00,
1278 0x00, 0xBB, 0x00, 0x00,
1279 0x00, 0xAA, 0x00, 0x00,
1280 0x00, 0x88, 0x00, 0x00,
1281 0x00, 0x77, 0x00, 0x00,
1282 0x00, 0x55, 0x00, 0x00,
1283 0x00, 0x44, 0x00, 0x00,
1284 0x00, 0x22, 0x00, 0x00,
1285 0x00, 0x11, 0x00, 0x00,
1286 0x00, 0x00, 0xEE, 0x00,
1287 0x00, 0x00, 0xDD, 0x00,
1288 0x00, 0x00, 0xBB, 0x00,
1289 0x00, 0x00, 0xAA, 0x00,
1290 0x00, 0x00, 0x88, 0x00,
1291 0x00, 0x00, 0x77, 0x00,
1292 0x00, 0x00, 0x55, 0x00,
1293 0x00, 0x00, 0x44, 0x00,
1294 0x00, 0x00, 0x22, 0x00,
1295 0x00, 0x00, 0x11, 0x00,
1296 0xEE, 0xEE, 0xEE, 0x00,
1297 0xDD, 0xDD, 0xDD, 0x00,
1298 0xBB, 0xBB, 0xBB, 0x00,
1299 0xAA, 0xAA, 0xAA, 0x00,
1300 0x88, 0x88, 0x88, 0x00,
1301 0x77, 0x77, 0x77, 0x00,
1302 0x55, 0x55, 0x55, 0x00,
1303 0x44, 0x44, 0x44, 0x00,
1304 0x22, 0x22, 0x22, 0x00,
1305 0x11, 0x11, 0x11, 0x00,
1306 0x00, 0x00, 0x00, 0x00
1307 ];
1308
1309 #[cfg(test)]
1310 mod test {
1311 use super::*;
1312 use std::fs::File;
1313
1314 #[test]
1315 fn test_mov_demux() {
1316 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1317 let mut fr = FileReader::new_read(&mut file);
1318 let mut br = ByteReader::new(&mut fr);
1319 let mut dmx = MOVDemuxer::new(&mut br);
1320 let mut sm = StreamManager::new();
1321 let mut si = SeekIndex::new();
1322 dmx.open(&mut sm, &mut si).unwrap();
1323
1324 loop {
1325 let pktres = dmx.get_frame(&mut sm);
1326 if let Err(e) = pktres {
1327 if e == DemuxerError::EOF { break; }
1328 panic!("error");
1329 }
1330 let pkt = pktres.unwrap();
1331 println!("Got {}", pkt);
1332 }
1333 }
1334 }