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