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