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