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