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