mov: fix track duration rescaling
[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
650d7bfb
KS
83fn print_cname(ctype: u32, size: u64, off: u64, depth: u8) {
84 for _ in 0..depth { print!(" "); }
85 let tag = [(ctype >> 24) as u8, (ctype >> 16) as u8, (ctype >> 8) as u8, ctype as u8];
86 let mut printable = true;
87 for &ch in tag.iter() {
88 if ch < 0x20 || ch > 0x7F {
89 printable = false;
90 break;
91 }
92 }
93 if printable {
94 print!(" '{}{}{}{}'", tag[0] as char, tag[1] as char, tag[2] as char, tag[3] as char);
95 } else {
96 print!(" {:08X}", ctype);
97 }
98 println!(" size {} @ {:X}", size, off);
99}
100
58309c73
KS
101macro_rules! read_chunk_list {
102 (root; $name: expr, $fname: ident, $handlers: ident) => {
103 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
104 self.depth += 1;
105 validate!(self.depth < 32);
106 let list_end = self.src.tell() + size;
107 while self.src.tell() < list_end {
108 let ret = read_chunk_header(&mut self.src);
109 if ret.is_err() { break; }
110 let (ctype, size) = ret.unwrap();
650d7bfb
KS
111 if self.print_chunks {
112 print_cname(ctype, size, self.src.tell(), self.depth as u8);
113 }
58309c73
KS
114 if self.src.tell() + size > list_end {
115 break;
116 }
117 if IGNORED_CHUNKS.contains(&ctype) {
118 self.src.skip64(size)?;
119 continue;
120 }
121 let handler = $handlers.iter().find(|x| x.ctype == ctype);
122 let read_size;
123 if let Some(ref handler) = handler {
124 read_size = (handler.parse)(self, strmgr, size)?;
125 } else {
126 println!("skipping unknown chunk {:08X} size {}", ctype, size);
127 read_size = 0;
128 }
129 validate!(read_size <= size);
130 self.src.skip64(size - read_size)?;
131 }
132 self.depth -= 1;
133 validate!(self.src.tell() == list_end);
134 Ok(())
135 }
136 };
137 (track; $name: expr, $fname: ident, $handlers: ident) => {
138 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
139 self.depth += 1;
140 validate!(self.depth < 32);
141 let list_end = br.tell() + size;
142 while br.tell() < list_end {
143 let ret = read_chunk_header(br);
144 if ret.is_err() { break; }
145 let (ctype, size) = ret.unwrap();
650d7bfb
KS
146 if self.print_chunks {
147 print_cname(ctype, size, br.tell(), self.depth + 1);
148 }
58309c73
KS
149 if br.tell() + size > list_end {
150 break;
151 }
152 if IGNORED_CHUNKS.contains(&ctype) {
153 br.skip64(size)?;
154 continue;
155 }
156 let handler = $handlers.iter().find(|x| x.ctype == ctype);
157 let read_size;
158 if let Some(ref handler) = handler {
159 read_size = (handler.parse)(self, br, size)?;
160 } else {
161 read_size = 0;
162 }
163 validate!(read_size <= size);
164 br.skip64(size - read_size)?;
165 }
166 self.depth -= 1;
167 validate!(br.tell() == list_end);
168 Ok(())
169 }
170 }
171}
172
173fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
174 br.skip64(size)?;
175 Ok(size)
176}
177
7e19285f
KS
178fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
179 dmx.src.skip64(size)?;
180 Ok(size)
181}
182
58309c73
KS
183fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
184 dmx.mdat_pos = dmx.src.tell();
185 dmx.mdat_size = size;
186 dmx.src.skip64(size)?;
187 Ok(size)
188}
189
190fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
191 dmx.read_moov(strmgr, size)?;
192 Ok(size)
193}
194
195const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
196 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
fbf1f900 197 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
00333698 198 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
58309c73 199 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
7e19285f 200 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
58309c73
KS
201];
202
203fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
204 const KNOWN_MVHD_SIZE: u64 = 100;
205 let br = &mut dmx.src;
206 validate!(size >= KNOWN_MVHD_SIZE);
207 let version = br.read_byte()?;
208 validate!(version == 0);
209 let _flags = br.read_u24be()?;
210 let _ctime = br.read_u32be()?;
211 let _mtime = br.read_u32be()?;
212 let tscale = br.read_u32be()?;
213 let duration = br.read_u32be()?;
214 let _pref_rate = br.read_u32be()?;
215 let _pref_volume = br.read_u16be()?;
216 br.read_skip(10)?;
217 br.read_skip(36)?; // matrix
218 let _preview_time = br.read_u32be()?;
219 let _preview_duration = br.read_u32be()?;
220 let _poster_time = br.read_u32be()?;
221 let _sel_time = br.read_u32be()?;
222 let _sel_duration = br.read_u32be()?;
223 let _cur_time = br.read_u32be()?;
224 let _next_track_id = br.read_u32be()?;
225 dmx.duration = duration;
226 dmx.tb_den = tscale;
227
228 Ok(KNOWN_MVHD_SIZE)
229}
230
fbf1f900
KS
231fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
232 let br = &mut dmx.src;
233 validate!(size > 24);
234 let dcom_size = br.read_u32be()?;
235 let dcom_tag = br.read_tag()?;
236 let compr_type = br.read_tag()?;
237 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
238 if &compr_type != b"zlib" {
239 return Err(DemuxerError::NotImplemented);
240 }
241 let cmvd_size = u64::from(br.read_u32be()?);
242 let cmvd_tag = br.read_tag()?;
243 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
244 let comp_size = (cmvd_size - 12) as usize;
245 let uncomp_size = br.read_u32be()? as usize;
246 validate!(uncomp_size > 8);
247 let mut sbuf = vec![0; comp_size];
248 let mut dbuf = vec![0; uncomp_size];
249 br.read_buf(sbuf.as_mut_slice())?;
61a228ff 250 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
fbf1f900
KS
251 if ret.is_err() {
252 return Err(DemuxerError::InvalidData);
253 }
254 let len = ret.unwrap();
255 validate!(len == uncomp_size);
256 let mut mr = MemoryReader::new_read(dbuf.as_slice());
257 let mut br = ByteReader::new(&mut mr);
258 let (ctype, csize) = read_chunk_header(&mut br)?;
259 validate!(ctype == mktag!(b"moov"));
260 let mut ddmx = MOVDemuxer::new(&mut br);
650d7bfb 261 ddmx.print_chunks = dmx.print_chunks;
fbf1f900
KS
262 ddmx.read_moov(strmgr, csize)?;
263 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
264 dmx.duration = ddmx.duration;
265 dmx.tb_den = ddmx.tb_den;
266 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
237cc1f9 267
fbf1f900
KS
268 Ok(size)
269}
270
00333698 271fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
58cd51fa
KS
272 let mut pal = [0; 1024];
273 let size = read_palette(&mut dmx.src, size, &mut pal)?;
274 dmx.pal = Some(Arc::new(pal));
275 Ok(size)
00333698
KS
276}
277
7e19285f
KS
278fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
279 dmx.src.skip64(size)?;
280 Ok(size)
281}
282
58309c73
KS
283fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
284 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
650d7bfb 285 track.print_chunks = dmx.print_chunks;
58309c73
KS
286 track.read_trak(&mut dmx.src, size)?;
287 validate!(track.tkhd_found && track.stsd_found);
288 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
289 dmx.cur_track += 1;
290 let mut str = None;
291 std::mem::swap(&mut track.stream, &mut str);
292 if let Some(stream) = str {
293 let str_id = strmgr.add_stream(stream).unwrap();
294 track.track_str_id = str_id;
295 }
296 dmx.tracks.push(track);
297 Ok(size)
298}
299
300const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
301 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
302 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
303 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
304 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
305 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
306 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
307 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
308 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
309];
310
311fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
312 const KNOWN_TKHD_SIZE: u64 = 84;
313 validate!(size >= KNOWN_TKHD_SIZE);
314 let version = br.read_byte()?;
315 validate!(version == 0);
316 let _flags = br.read_u24be()?;
317 let _ctime = br.read_u32be()?;
318 let _mtime = br.read_u32be()?;
319 let track_id = br.read_u32be()?;
320 br.read_skip(4)?;
a480a0de 321 let duration = br.read_u32be()?;
58309c73
KS
322 br.read_skip(8)?;
323 let _layer = br.read_u16be()?;
324 let _alt_group = br.read_u16be()?;
325 let _volume = br.read_u16be()?;
326 br.read_skip(2)?;
327 br.read_skip(36)?; // matrix
328 let width = br.read_u32be()? as usize;
329 let height = br.read_u32be()? as usize;
330 track.width = width >> 16;
331 track.height = height >> 16;
332 track.track_id = track_id;
a480a0de 333 track.duration = duration;
58309c73
KS
334
335 track.tkhd_found = true;
336 Ok(KNOWN_TKHD_SIZE)
337}
338
339fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
340 track.stream_type = StreamType::None;
341 track.read_mdia(br, size)?;
342 Ok(size)
343}
344
345const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
079fff1d 346 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: read_mdhd },
58309c73
KS
347 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
348 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
349];
350
079fff1d
KS
351fn read_mdhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
352 const KNOWN_MDHD_SIZE: u64 = 24;
353 validate!(size >= KNOWN_MDHD_SIZE);
354 let version = br.read_byte()?;
355 validate!(version == 0);
356 let flags = br.read_u24be()?;
357 validate!(flags == 0);
358 let _ctime = br.read_u32be()?;
359 let _mtime = br.read_u32be()?;
360 track.tb_den = br.read_u32be()?;
361 validate!(track.tb_den != 0);
362 track.duration = br.read_u32be()?;
363 let _language = br.read_u16be()?;
364 let _quality = br.read_u16be()?;
365
366 Ok(KNOWN_MDHD_SIZE)
367}
368
58309c73
KS
369fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
370 const KNOWN_HDLR_SIZE: u64 = 24;
371 validate!(size >= KNOWN_HDLR_SIZE);
372 let version = br.read_byte()?;
373 validate!(version == 0);
374 let flags = br.read_u24be()?;
375 validate!(flags == 0);
376 let comp_type = br.read_u32be()?;
377 let comp_subtype = br.read_u32be()?;
378 let _comp_manufacturer = br.read_u32be()?;
379 let _comp_flags = br.read_u32be()?;
380 let _comp_flags_mask = br.read_u32be()?;
381
d4809976 382 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
58309c73
KS
383 if comp_subtype == mktag!(b"vide") {
384 track.stream_type = StreamType::Video;
385 } else if comp_subtype == mktag!(b"soun") {
386 track.stream_type = StreamType::Audio;
387 } else {
388 track.stream_type = StreamType::Data;
389 }
390 } else if comp_type == mktag!(b"dhlr") {
391 track.stream_type = StreamType::Data;
392 } else {
393 println!("Unknown stream type");
394 track.stream_type = StreamType::Data;
395 }
c8db9313 396
58309c73
KS
397 Ok(KNOWN_HDLR_SIZE)
398}
399
400fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 track.read_minf(br, size)?;
402 Ok(size)
403}
404
405const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
406 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
407 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
408 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
409 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
410 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
411 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
412 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
413];
414
415fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
416 const KNOWN_VMHD_SIZE: u64 = 12;
417 validate!(track.stream_type == StreamType::Video);
418 validate!(size >= KNOWN_VMHD_SIZE);
419 let version = br.read_byte()?;
420 validate!(version == 0);
421 let _flags = br.read_u24be()?;
422 br.read_skip(2)?; // graphics mode
423 br.read_skip(6)?; // opcolor
424 Ok(KNOWN_VMHD_SIZE)
425}
426
427fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
428 const KNOWN_SMHD_SIZE: u64 = 8;
429 validate!(track.stream_type == StreamType::Audio);
430 validate!(size >= KNOWN_SMHD_SIZE);
431 let version = br.read_byte()?;
432 validate!(version == 0);
433 let _flags = br.read_u24be()?;
434 br.read_skip(2)?; // balance
435 br.read_skip(2)?;
436 Ok(KNOWN_SMHD_SIZE)
437}
438
439fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
440 validate!(track.stream_type == StreamType::Data);
441 Ok(0)
442}
443
444fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
445 validate!(track.stream_type == StreamType::Data);
446 const KNOWN_GMIN_SIZE: u64 = 16;
447 validate!(size >= KNOWN_GMIN_SIZE);
448 let version = br.read_byte()?;
449 validate!(version == 0);
450 let _flags = br.read_u24be()?;
451 br.read_skip(2)?; // graphics mode
452 br.read_skip(6)?; // opcolor
453 br.read_skip(2)?; // balance
454 br.read_skip(2)?;
455 Ok(KNOWN_GMIN_SIZE)
456}
457
458fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
459 track.read_stbl(br, size)?;
460 Ok(size)
461}
462
463const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
464 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
bbbf86dd 465 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
58309c73
KS
466 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
467 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
468 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
469 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
470 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
4e7deeda 471 TrackChunkHandler { ctype: mktag!(b"ctts"), parse: read_ctts },
58309c73
KS
472];
473
89b16ac8
KS
474fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
475 let read_part = br.tell() - start_pos;
476 if read_part + 8 < size {
9aa783a0
KS
477 let mut buf = [0; 8];
478 br.peek_buf(&mut buf)?;
479 if &buf[4..8] != b"wave" {
480 let mut buf = vec![0; (size - read_part) as usize];
481 br.read_buf(&mut buf)?;
482 return Ok(Some(buf));
483 }
484
89b16ac8
KS
485 let csize = br.read_u32be()? as u64;
486 let ctag = br.read_u32be()?;
487 validate!(read_part + csize <= size);
488 validate!(ctag == mktag!(b"wave"));
489 if csize == 8 {
490 return Ok(None);
491 }
492 let mut buf = [0; 8];
493 br.peek_buf(&mut buf)?;
494 if &buf[4..8] == b"frma" {
495 br.read_skip(12)?;
496 if csize > 20 {
497 let mut buf = vec![0; (csize - 20) as usize];
498 br.read_buf(&mut buf)?;
499 Ok(Some(buf))
500 } else {
501 Ok(None)
502 }
503 } else if csize > 8 {
504 let mut buf = vec![0; (csize as usize) - 8];
505 br.read_buf(&mut buf)?;
506 Ok(Some(buf))
507 } else {
508 Ok(None)
509 }
510 } else {
511 Ok(None)
512 }
513}
514
58309c73
KS
515fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
516 const KNOWN_STSD_SIZE: u64 = 24;
517 validate!(size >= KNOWN_STSD_SIZE);
518 let start_pos = br.tell();
519 let version = br.read_byte()?;
520 validate!(version == 0);
521 let _flags = br.read_u24be()?;
522 let entries = br.read_u32be()?;
523 validate!(entries > 0);
61cab15b 524 let esize = u64::from(br.read_u32be()?);
58309c73
KS
525 validate!(esize + 8 <= size);
526 let mut fcc = [0u8; 4];
527 br.read_buf(&mut fcc)?;
528 br.read_skip(6)?;
529 let _data_ref = br.read_u16be()?;
530
531 track.fcc = fcc;
532
533 let codec_info;
534 match track.stream_type {
535 StreamType::Video => {
536 let _ver = br.read_u16be()?;
537 let _revision = br.read_u16le()?;
538 let _vendor = br.read_u32be()?;
539 let _temp_quality = br.read_u32be()?;
540 let _spat_quality = br.read_u32be()?;
541 let width = br.read_u16be()? as usize;
542 let height = br.read_u16be()? as usize;
543 let _hor_res = br.read_u32be()?;
544 let _vert_res = br.read_u32be()?;
545 let data_size = br.read_u32be()?;
546 validate!(data_size == 0);
547 let _frame_count = br.read_u16be()? as usize;
548 let _cname_len = br.read_byte()? as usize;
549 br.read_skip(31)?; // actual compressor name
550 let depth = br.read_u16be()?;
551 let ctable_id = br.read_u16be()?;
8019c866
KS
552 let grayscale = depth > 0x20 || depth == 1;
553 let depth = if grayscale { depth & 0x1F } else { depth };
554 validate!(depth <= 8 || (ctable_id == 0xFFFF));
58309c73 555 if ctable_id == 0 {
00333698 556 let max_pal_size = start_pos + size - br.tell();
58cd51fa
KS
557 let mut pal = [0; 1024];
558 read_palette(br, max_pal_size, &mut pal)?;
559 track.pal = Some(Arc::new(pal));
8019c866 560 } else if (depth <= 8) && !grayscale {
2736c15a
KS
561 match depth & 0x1F {
562 2 => {
563 let mut pal = [0; 1024];
564 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
565 track.pal = Some(Arc::new(pal));
566 },
567 4 => {
568 let mut pal = [0; 1024];
569 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
570 track.pal = Some(Arc::new(pal));
571 },
572 8 => {
573 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
574 },
575 _ => {},
576 };
2949bcfa 577 } else if grayscale && ctable_id != 0xFFFF {
2736c15a
KS
578 let mut pal = [0; 1024];
579 let cdepth = depth & 0x1F;
580 let size = 1 << cdepth;
581 for i in 0..size {
8019c866 582 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
2736c15a
KS
583 let mut off = 8 - cdepth;
584 while off >= cdepth {
585 clr |= clr >> (8 - off);
586 off -= cdepth;
587 }
588 if off > 0 {
589 clr |= clr >> (8 - off);
590 }
591 pal[i * 4] = clr;
592 pal[i * 4 + 1] = clr;
593 pal[i * 4 + 2] = clr;
594 }
595 track.pal = Some(Arc::new(pal));
58309c73
KS
596 }
597// todo other atoms, put as extradata
598 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
599 name
600 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
601 name
602 } else {
603 "unknown"
604 };
605 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
8019c866
KS
606 let mut vhdr = NAVideoInfo::new(width, height, false, format);
607 vhdr.bits = depth as u8;
61cab15b 608 let edata = if br.tell() - start_pos + 4 < size {
58309c73 609//todo skip various common atoms
61cab15b 610 let edata_size = br.read_u32be()? as usize;
d341f57a
KS
611 validate!(edata_size >= 4);
612 let mut buf = vec![0; edata_size - 4];
58309c73 613 br.read_buf(buf.as_mut_slice())?;
61cab15b
KS
614 Some(buf)
615 } else {
616 None
617 };
58309c73
KS
618 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
619 },
620 StreamType::Audio => {
89b16ac8 621 let sver = br.read_u16be()?;
58309c73
KS
622 let _revision = br.read_u16le()?;
623 let _vendor = br.read_u32be()?;
624 let nchannels = br.read_u16be()?;
625 validate!(nchannels <= 64);
626 let sample_size = br.read_u16be()?;
627 validate!(sample_size <= 128);
628 let _compr_id = br.read_u16be()?;
629 let packet_size = br.read_u16be()? as usize;
630 validate!(packet_size == 0);
631 let sample_rate = br.read_u32be()?;
7afec34d 632 validate!(sample_rate > (1 << 16));
58309c73
KS
633 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
634 name
635 } 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]))) {
636 name
637 } else {
638 "unknown"
639 };
e5d3fef5
KS
640 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
641 if &fcc == b"raw " && sample_size == 8 {
642 soniton.signed = false;
643 }
58309c73 644 let block_align = 1;
89b16ac8 645 if sver == 1 {
b0e12d42 646 let samples_per_packet = br.read_u32be()?;
89b16ac8 647 let _bytes_per_packet = br.read_u32be()?;
9efec4ed 648 let bytes_per_frame = br.read_u32be()?;
89b16ac8 649 let _bytes_per_sample = br.read_u32be()?;
9efec4ed 650 track.bsize = bytes_per_frame as usize;
b0e12d42 651 track.frame_samples = samples_per_packet as usize;
7afec34d 652 track.tb_num = samples_per_packet;
9efec4ed 653 } else {
7afec34d 654 track.bsize = (sample_size / 8) as usize;
89b16ac8 655 }
7afec34d
KS
656 track.tb_den = sample_rate >> 16;
657 track.raw_audio = match &fcc {
658 b"NONE" | b"raw " | b"twos" | b"sowt" |
659 b"in24" | b"in32" | b"fl32" | b"fl64" |
660 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
661 b"alaw" | b"ulaw" |
662 b"MAC3" | b"MAC6" => true,
663 _ => false,
664 };
58309c73 665 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
89b16ac8 666 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
667 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
668 track.channels = nchannels as usize;
669 track.bits = sample_size as usize;
670 },
671 StreamType::None => {
672 return Err(DemuxerError::InvalidData);
673 },
674 _ => {
675//todo put it all into extradata
676 let edata = None;
677 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
678 },
679 };
680 let read_size = br.tell() - start_pos;
681 validate!(read_size <= size);
7afec34d 682 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
58309c73
KS
683 track.stsd_found = true;
684 Ok(read_size)
685}
686
bbbf86dd 687fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
d4809976 688 validate!(size >= 8);
bbbf86dd
KS
689 let start_pos = br.tell();
690 let version = br.read_byte()?;
691 validate!(version == 0);
692 let _flags = br.read_u24be()?;
693 let entries = br.read_u32be()? as usize;
694 validate!(entries as u64 <= (size - 8) / 8);
d4809976
KS
695 if entries == 0 {
696 } else if entries == 1 {
bbbf86dd
KS
697 let _count = br.read_u32be()?;
698 let tb_num = br.read_u32be()?;
4e7deeda
KS
699 validate!(tb_num != 0);
700 track.tb_div = tb_num;
bbbf86dd
KS
701 if let Some(ref mut stream) = track.stream {
702 let tb_den = stream.tb_den;
7afec34d 703 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
15395de6 704 stream.duration /= u64::from(track.tb_div);
bbbf86dd
KS
705 stream.tb_num = tb_num;
706 stream.tb_den = tb_den;
707 track.tb_num = tb_num;
708 track.tb_den = tb_den;
15395de6 709 track.duration /= track.tb_div;
bbbf86dd
KS
710 }
711 } else {
712 track.time_to_sample.truncate(0);
713 track.time_to_sample.reserve(entries);
714 for _ in 0..entries {
715 let count = br.read_u32be()?;
716 let mult = br.read_u32be()?;
717 track.time_to_sample.push((count, mult));
718 }
719 }
720 let read_size = br.tell() - start_pos;
721 validate!(read_size <= size);
722 Ok(read_size)
723}
724
58309c73
KS
725fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
726 let version = br.read_byte()?;
727 validate!(version == 0);
728 let _flags = br.read_u24be()?;
729 let entries = br.read_u32be()? as usize;
730 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
731 validate!((entries * 4 + 8) as u64 == size);
732 track.keyframes = Vec::with_capacity(entries);
733 let mut last_sample_no = 0;
734 for _ in 0..entries {
735 let sample_no = br.read_u32be()?;
736 validate!(sample_no > last_sample_no);
737 track.keyframes.push(sample_no);
738 last_sample_no = sample_no;
739 }
740 Ok(size)
741}
742
743fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
744 let version = br.read_byte()?;
745 validate!(version == 0);
746 let _flags = br.read_u24be()?;
747 let entries = br.read_u32be()? as usize;
748 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
749 validate!((entries * 12 + 8) as u64 == size);
750 track.sample_map = Vec::with_capacity(entries);
751 let mut last_sample_no = 0;
752 for _i in 0..entries {
753 let sample_no = br.read_u32be()?;
754 validate!(sample_no > last_sample_no);
755 let nsamples = br.read_u32be()?;
756 let _sample_desc = br.read_u32be()?;
757 track.sample_map.push((sample_no, nsamples));
758 last_sample_no = sample_no;
759 }
760 Ok(size)
761}
762
763fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
764 let version = br.read_byte()?;
765 validate!(version == 0);
766 let _flags = br.read_u24be()?;
767 let sample_size = br.read_u32be()?;
768 if sample_size != 0 {
769 track.sample_size = sample_size;
9efec4ed
KS
770 if track.sample_size != 1 || track.bsize == 0 {
771 track.bsize = sample_size as usize;
772 }
58309c73
KS
773 Ok(8)
774 } else {
775 let entries = br.read_u32be()? as usize;
776 validate!((entries * 4 + 12) as u64 == size);
777 track.chunk_sizes = Vec::with_capacity(entries);
778 for _ in 0..entries {
779 let sample_size = br.read_u32be()?;
780 track.chunk_sizes.push(sample_size);
781 }
782 Ok(size)
783 }
784}
785
786fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
787 let version = br.read_byte()?;
788 validate!(version == 0);
789 let _flags = br.read_u24be()?;
790 let entries = br.read_u32be()? as usize;
791 validate!((entries * 4 + 8) as u64 == size);
792 track.chunk_offsets = Vec::with_capacity(entries);
793 for _i in 0..entries {
794 let sample_offset = br.read_u32be()?;
795 track.chunk_offsets.push(u64::from(sample_offset));
796 }
797 Ok(size)
798}
799
4e7deeda
KS
800fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
801 validate!(size >= 8);
802 let version = br.read_byte()?;
803 let _flags = br.read_u24be()?;
804 if version > 1 {
805 return Err(DemuxerError::NotImplemented);
806 }
807 let entries = br.read_u32be()? as usize;
808 track.ctts_version = version;
809 track.ctts_map.resize(entries);
810 match version {
811 0 | 1 => {
812 validate!(size == (entries as u64) * 8 + 8);
813 for _ in 0..entries {
814 let samp_count = br.read_u32be()?;
815 let samp_offset = br.read_u32be()?;
816 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
817 }
818 },
819 _ => unreachable!(),
820 };
821 track.ctts_map.reset();
822
823 Ok(size)
824}
825
58309c73
KS
826struct MOVDemuxer<'a> {
827 src: &'a mut ByteReader<'a>,
828 depth: usize,
829 mdat_pos: u64,
830 mdat_size: u64,
831 tracks: Vec<Track>,
832 cur_track: usize,
833 tb_den: u32,
834 duration: u32,
58cd51fa 835 pal: Option<Arc<[u8; 1024]>>,
650d7bfb
KS
836
837 print_chunks: bool,
58309c73
KS
838}
839
840struct Track {
841 track_id: u32,
842 track_str_id: usize,
843 track_no: u32,
bbbf86dd 844 tb_num: u32,
58309c73 845 tb_den: u32,
4e7deeda 846 tb_div: u32,
7afec34d
KS
847 raw_audio: bool,
848 raw_apos: u64,
a480a0de 849 duration: u32,
58309c73
KS
850 depth: u8,
851 tkhd_found: bool,
852 stsd_found: bool,
853 stream_type: StreamType,
854 width: usize,
855 height: usize,
856 channels: usize,
857 bits: usize,
9efec4ed 858 bsize: usize,
58309c73
KS
859 fcc: [u8; 4],
860 keyframes: Vec<u32>,
861 chunk_sizes: Vec<u32>,
862 chunk_offsets: Vec<u64>,
bbbf86dd 863 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
864 sample_map: Vec<(u32, u32)>,
865 sample_size: u32,
b0e12d42 866 frame_samples: usize,
4e7deeda
KS
867 ctts_map: RLESearcher<u32>,
868 ctts_version: u8,
58309c73
KS
869 stream: Option<NAStream>,
870 cur_chunk: usize,
871 cur_sample: usize,
872 samples_left: usize,
873 last_offset: u64,
58cd51fa 874 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 875 timesearch: TimeSearcher,
650d7bfb
KS
876
877 print_chunks: bool,
bbbf86dd
KS
878}
879
880#[derive(Default)]
881struct TimeSearcher {
882 idx: usize,
883 base: u64,
884 sbase: u32,
885 cur_len: u32,
886 cur_mul: u32,
887}
888
889impl TimeSearcher {
890 fn new() -> Self { Self::default() }
891 fn reset(&mut self) {
892 *self = Self::default();
893 }
894 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
895 if tts.is_empty() {
896 u64::from(sample)
897 } else if sample >= self.sbase {
898 let mut sample = sample - self.sbase;
899 if self.idx == 0 {
900 let (cur_len, cur_mul) = tts[0];
901 self.cur_len = cur_len;
902 self.cur_mul = cur_mul;
903 self.idx += 1;
904 }
905 while self.idx < tts.len() && sample > self.cur_len {
906 sample -= self.cur_len;
907 self.sbase += self.cur_len;
908 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
909 self.cur_len = tts[self.idx].0;
910 self.cur_mul = tts[self.idx].1;
911 self.idx += 1;
912 }
913 self.base + u64::from(sample) * u64::from(self.cur_mul)
914 } else {
915 self.reset();
916 self.map_time(sample, tts)
917 }
918 }
58309c73
KS
919}
920
4e7deeda
KS
921#[derive(Default)]
922struct RLESearcher<T> {
923 array: Vec<(u32, T)>,
924 idx: usize,
925 start: u64,
926 next: u64,
927}
928
929impl<T:Default+Copy> RLESearcher<T> {
930 fn new() -> Self { Self::default() }
931 fn resize(&mut self, size: usize) {
932 self.array.truncate(0);
933 self.array.reserve(size);
934 }
935 fn add(&mut self, len: u32, val: T) {
936 self.array.push((len, val));
937 }
938 fn reset(&mut self) {
939 self.start = 0;
940 if !self.array.is_empty() {
941 self.idx = 0;
942 self.next = u64::from(self.array[0].0);
943 } else {
944 self.idx = self.array.len();
945 self.next = 0;
946 }
947 }
948 fn map(&mut self, sample: u64) -> Option<T> {
949 if sample < self.start {
950 self.reset();
951 }
952 if self.idx < self.array.len() {
953 if sample < self.next {
954 Some(self.array[self.idx].1)
955 } else {
956 while (self.idx < self.array.len()) && (sample >= self.next) {
957 self.start = self.next;
958 self.idx += 1;
959 if self.idx < self.array.len() {
960 self.next += u64::from(self.array[self.idx].0);
961 }
962 }
963 if self.idx < self.array.len() {
964 Some(self.array[self.idx].1)
965 } else {
966 None
967 }
968 }
969 } else {
970 None
971 }
972 }
973}
974
58309c73
KS
975impl Track {
976 fn new(track_no: u32, tb_den: u32) -> Self {
977 Self {
978 tkhd_found: false,
979 stsd_found: false,
980 track_id: 0,
981 track_str_id: 0,
982 track_no,
bbbf86dd 983 tb_num: 1,
58309c73 984 tb_den,
4e7deeda 985 tb_div: 1,
7afec34d
KS
986 raw_audio: false,
987 raw_apos: 0,
a480a0de 988 duration: 0,
58309c73
KS
989 stream_type: StreamType::None,
990 width: 0,
991 height: 0,
992 channels: 0,
993 bits: 0,
9efec4ed 994 bsize: 0,
58309c73
KS
995 fcc: [0; 4],
996 keyframes: Vec::new(),
997 chunk_sizes: Vec::new(),
998 chunk_offsets: Vec::new(),
bbbf86dd 999 time_to_sample: Vec::new(),
58309c73
KS
1000 sample_map: Vec::new(),
1001 sample_size: 0,
b0e12d42 1002 frame_samples: 0,
4e7deeda
KS
1003 ctts_map: RLESearcher::new(),
1004 ctts_version: 0,
58309c73
KS
1005 stream: None,
1006 depth: 0,
1007 cur_chunk: 0,
1008 cur_sample: 0,
1009 samples_left: 0,
1010 last_offset: 0,
58cd51fa 1011 pal: None,
bbbf86dd 1012 timesearch: TimeSearcher::new(),
650d7bfb
KS
1013
1014 print_chunks: false,
58309c73
KS
1015 }
1016 }
1017 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1018 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1019 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1020 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
1021 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 1022 if !self.keyframes.is_empty() {
58309c73
KS
1023 seek_index.mode = SeekIndexMode::Present;
1024 }
bbbf86dd 1025 let mut tsearch = TimeSearcher::new();
58309c73 1026 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
1027 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1028 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1029 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
1030 }
1031 }
1032 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1033 if nsamp == 0 {
9efec4ed 1034 self.bsize
58309c73
KS
1035 } else {
1036 match &self.fcc {
1037 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1038 (nsamp * self.bits * self.channels + 7) >> 3
1039 },
1040 b"ima4" => {
1041 let nblocks = (nsamp + 63) >> 6;
1042 nblocks * 34 * self.channels
1043 },
1044 b"MAC3" => {
1045 (nsamp + 5) / 6 * 2 * self.channels
1046 },
1047 b"MAC6" => {
1048 (nsamp + 5) / 6 * self.channels
1049 },
1050 b"in24" => nsamp * 3 * self.channels,
1051 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1052 b"fl64" => nsamp * 8 * self.channels,
1053 b"ulaw" | b"alaw" => nsamp,
1054 b"ms\x00\x02" => { //MS ADPCM
1055 ((nsamp - 1) / 2 + 7) * self.channels
1056 },
1057 b"ms\x00\x21" => { //IMA ADPCM
1058 (nsamp / 2 + 4) * self.channels
1059 },
9efec4ed 1060 _ => self.bsize,
58309c73
KS
1061 }
1062 }
1063 }
1064 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 1065 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
4e7deeda
KS
1066 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1067 let dts = match self.ctts_version {
1068 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1069 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1070 _ => unimplemented!(),
1071 };
1072 if (dts as i64) < 0 {
1073 None
1074 } else {
1075 Some(dts)
1076 }
1077 } else {
1078 None
1079 };
1080 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
58309c73
KS
1081 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1082 if self.cur_sample >= self.chunk_sizes.len() {
1083 return None;
1084 }
1085 let offset = self.chunk_offsets[self.cur_sample];
1086 let size = self.chunk_sizes[self.cur_sample] as usize;
1087 self.cur_sample += 1;
1088 Some((pts, offset, size))
1089 } else {
1090 if self.samples_left == 0 {
1091 if self.cur_chunk >= self.chunk_offsets.len() {
1092 return None;
1093 }
1094 for (idx, samples) in self.sample_map.iter() {
1095 if *idx as usize <= self.cur_chunk + 1 {
1096 self.samples_left = *samples as usize;
1097 } else {
1098 break;
1099 }
1100 }
1101 self.last_offset = self.chunk_offsets[self.cur_chunk];
1102 self.cur_chunk += 1;
1103 }
1104 let offset = self.last_offset;
1105 let size = self.get_size(self.cur_sample);
1106 self.last_offset += size as u64;
1107 if self.stream_type == StreamType::Video {
1108 self.samples_left -= 1;
d940f0c2
KS
1109 } else if self.frame_samples != 0 && self.bsize != 0 {
1110 let nblocks = size / self.bsize;
7afec34d
KS
1111 if self.raw_audio {
1112 pts.pts = Some(self.raw_apos);
1113 pts.duration = Some(nblocks as u64);
1114 self.raw_apos += nblocks as u64;
1115 }
d940f0c2
KS
1116 if nblocks > 0 {
1117 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1118 self.samples_left -= consumed;
1119 } else {
1120 self.samples_left = 0;
1121 }
7afec34d
KS
1122 } else if !self.raw_audio {
1123 self.samples_left -= 1;
58309c73 1124 } else {
7afec34d
KS
1125 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1126 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1127 let cur_size = self.calculate_chunk_size(self.samples_left);
1128 let add_off = (size - cur_size) as u64;
1129 let dsize = cur_size.min(max_size);
1130 if self.samples_left >= BLOCK_SAMPLES {
1131 self.cur_sample += BLOCK_SAMPLES;
1132 self.samples_left -= BLOCK_SAMPLES;
1133 self.last_offset -= size as u64;
1134 } else {
1135 self.cur_sample += self.samples_left;
1136 self.samples_left = 0;
1137 }
1138 return Some((pts, offset + add_off, dsize));
58309c73
KS
1139 }
1140 self.cur_sample += 1;
1141 Some((pts, offset, size))
1142 }
1143 }
1144 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1145 if !self.chunk_sizes.is_empty() {
58309c73 1146 self.chunk_sizes[sample_no] as usize
61cab15b 1147 } else if !self.sample_map.is_empty() {
58309c73
KS
1148 let mut nsamp = 0;
1149 for (idx, samples) in self.sample_map.iter() {
1150 if *idx as usize <= self.cur_chunk {
1151 nsamp = *samples;
1152 } else {
1153 break;
1154 }
1155 }
1156 self.calculate_chunk_size(nsamp as usize)
1157 } else {
9efec4ed 1158 self.bsize
58309c73
KS
1159 }
1160 }
7afec34d 1161 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
58309c73
KS
1162 self.cur_sample = pts as usize;
1163 self.samples_left = 0;
1164 if self.stream_type == StreamType::Audio {
7afec34d
KS
1165 if let NATimePoint::Milliseconds(ms) = tpoint {
1166 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1167 if self.raw_audio {
1168 if self.frame_samples != 0 {
1169 self.raw_apos = exp_pts / (self.frame_samples as u64);
1170 let mut apos = 0;
1171 self.cur_sample = 0;
1172 self.cur_chunk = 0;
1173 let mut cmap = self.sample_map.iter();
1174 let mut cur_samps = 0;
1175 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1176 loop {
1177 if self.cur_chunk + 1 == next_idx as usize {
1178 self.samples_left = cur_samps;
1179 cur_samps = next_samples as usize;
1180 if let Some((new_idx, new_samples)) = cmap.next() {
1181 next_idx = *new_idx;
1182 next_samples = *new_samples;
1183 }
1184 }
1185 self.raw_apos = apos;
1186 apos += (cur_samps / self.frame_samples) as u64;
1187 if apos > exp_pts {
1188 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1189 if self.cur_chunk >= self.chunk_offsets.len() {
1190 return Err(DemuxerError::SeekError);
1191 }
1192 self.last_offset = self.chunk_offsets[self.cur_chunk];
1193 break;
1194 }
1195 }
1196 self.cur_chunk += 1;
1197 }
1198 self.samples_left = cur_samps;
1199 self.cur_chunk += 1;
1200 } else {
1201 self.raw_apos = exp_pts;
1202 self.cur_sample = exp_pts as usize;
1203 let mut csamp = 0;
1204 self.cur_chunk = 0;
1205 let mut cmap = self.sample_map.iter();
1206 let mut cur_samps = 0;
1207 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1208 loop {
1209 if self.cur_chunk + 1 == next_idx as usize {
1210 self.samples_left = cur_samps;
1211 cur_samps = next_samples as usize;
1212 if let Some((new_idx, new_samples)) = cmap.next() {
1213 next_idx = *new_idx;
1214 next_samples = *new_samples;
1215 }
1216 }
1217 csamp += cur_samps;
1218 if csamp > self.cur_sample {
1219 if self.cur_chunk >= self.chunk_offsets.len() {
1220 return Err(DemuxerError::SeekError);
1221 }
1222 self.last_offset = self.chunk_offsets[self.cur_chunk];
1223 break;
1224 }
1225 self.cur_chunk += 1;
1226 }
1227 self.samples_left = csamp - self.cur_sample;
1228 self.cur_chunk += 1;
1229 }
1230 } else {
1231 self.cur_chunk = self.cur_sample;
1232 }
1233 } else {
1234 self.cur_chunk = self.cur_sample;
1235 }
61cab15b 1236 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1237 let mut csamp = 0;
1238 self.cur_chunk = 0;
1239 let mut cmap = self.sample_map.iter();
1240 let mut cur_samps = 0;
1241 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1242 loop {
bbbf86dd 1243 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1244 self.samples_left = cur_samps;
1245 cur_samps = next_samples as usize;
1246 if let Some((new_idx, new_samples)) = cmap.next() {
1247 next_idx = *new_idx;
1248 next_samples = *new_samples;
1249 }
1250 }
1251 csamp += cur_samps;
1252 if csamp >= self.cur_sample {
7afec34d
KS
1253 if self.cur_chunk >= self.chunk_offsets.len() {
1254 return Err(DemuxerError::SeekError);
1255 }
58309c73
KS
1256 self.last_offset = self.chunk_offsets[self.cur_chunk];
1257 break;
1258 }
1259 self.cur_chunk += 1;
1260 }
1261 csamp -= cur_samps;
bbbf86dd 1262 for sample_no in csamp..self.cur_sample {
58309c73
KS
1263 self.last_offset += self.get_size(sample_no) as u64;
1264 }
bbbf86dd
KS
1265 self.samples_left = csamp + cur_samps - self.cur_sample;
1266 self.cur_chunk += 1;
58309c73 1267 }
7afec34d 1268 Ok(())
58309c73
KS
1269 }
1270}
1271
1272impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1273 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1274 self.read_root(strmgr)?;
1275 validate!(self.mdat_pos > 0);
61cab15b 1276 validate!(!self.tracks.is_empty());
58309c73
KS
1277 for track in self.tracks.iter() {
1278 track.fill_seek_index(seek_index);
1279 }
1280 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1281 self.cur_track = 0;
1282 Ok(())
1283 }
1284
1285 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1286 if self.tracks.is_empty() {
58309c73
KS
1287 return Err(DemuxerError::EOF);
1288 }
1289 for _ in 0..self.tracks.len() {
1290 if self.cur_track >= self.tracks.len() {
1291 self.cur_track = 0;
1292 }
1293 let track = &mut self.tracks[self.cur_track];
1294 self.cur_track += 1;
58cd51fa 1295 let first = track.cur_sample == 0;
58309c73
KS
1296 if let Some((pts, offset, size)) = track.get_next_chunk() {
1297 let str = strmgr.get_stream(track.track_str_id);
1298 if str.is_none() { return Err(DemuxerError::InvalidData); }
1299 let stream = str.unwrap();
1300 self.src.seek(SeekFrom::Start(offset))?;
58cd51fa
KS
1301 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1302 if let Some(ref pal) = track.pal {
1303 let side_data = NASideData::Palette(first, pal.clone());
1304 pkt.add_side_data(side_data);
1305 }
58309c73
KS
1306 return Ok(pkt);
1307 }
1308 }
61cab15b 1309 Err(DemuxerError::EOF)
58309c73
KS
1310 }
1311
24d99894 1312 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1313 let ret = seek_index.find_pos(time);
1314 if ret.is_none() {
1315 return Err(DemuxerError::SeekError);
1316 }
1317 let seek_info = ret.unwrap();
1318 for track in self.tracks.iter_mut() {
7afec34d 1319 track.seek(seek_info.pts, time)?;
58309c73
KS
1320 }
1321 Ok(())
1322 }
a480a0de
KS
1323 fn get_duration(&self) -> u64 {
1324 if self.tb_den != 0 {
1325 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1326 } else {
1327 0
1328 }
1329 }
58309c73
KS
1330}
1331
650d7bfb
KS
1332const PRINT_CHUNKS: &str = "print_chunks";
1333
1334const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1335 NAOptionDefinition {
1336 name: PRINT_CHUNKS,
1337 description: "Print parsed file structure",
1338 opt_type: NAOptionDefinitionType::Bool },
1339];
1340
787b8d03 1341impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb
KS
1342 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1343 fn set_options(&mut self, options: &[NAOption]) {
1344 for option in options.iter() {
1345 for opt_def in DEMUXER_OPTIONS.iter() {
1346 if opt_def.check(option).is_ok() {
1347 match (option.name, &option.value) {
1348 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1349 self.print_chunks = *val;
1350 },
1351 _ => {},
1352 }
1353 }
1354 }
1355 }
1356 }
1357 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1358 match name {
1359 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1360 _ => None,
1361 }
1362 }
787b8d03
KS
1363}
1364
58309c73
KS
1365impl<'a> MOVDemuxer<'a> {
1366 fn new(io: &'a mut ByteReader<'a>) -> Self {
1367 MOVDemuxer {
1368 src: io,
1369 depth: 0,
1370 mdat_pos: 0,
1371 mdat_size: 0,
1372 tracks: Vec::with_capacity(2),
1373 cur_track: 0,
1374 tb_den: 0,
1375 duration: 0,
58cd51fa 1376 pal: None,
650d7bfb
KS
1377
1378 print_chunks: false,
58309c73
KS
1379 }
1380 }
1381 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1382 self.depth = 0;
1383 while self.src.left() != 0 {
1384 let ret = read_chunk_header(&mut self.src);
1385 if ret.is_err() { break; }
1386 let (ctype, size) = ret.unwrap();
1387 if IGNORED_CHUNKS.contains(&ctype) {
1388 self.src.skip64(size)?;
1389 continue;
1390 }
1391 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1392 let read_size;
1393 if let Some(ref handler) = handler {
1394 read_size = (handler.parse)(self, strmgr, size)?;
1395 } else {
1396 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1397 read_size = 0;
1398 }
1399 validate!(read_size <= size);
1400 self.src.skip64(size - read_size)?;
1401 }
1402//todo check if all needed chunks are found
1403 Ok(())
1404 }
1405 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1406}
1407
1408pub struct MOVDemuxerCreator { }
1409
1410impl DemuxerCreator for MOVDemuxerCreator {
1411 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1412 Box::new(MOVDemuxer::new(br))
1413 }
1414 fn get_name(&self) -> &'static str { "mov" }
1415}
1416
2736c15a
KS
1417const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1418 0x93, 0x65, 0x5E, 0x00,
1419 0xFF, 0xFF, 0xFF, 0x00,
1420 0xDF, 0xD0, 0xAB, 0x00,
1421 0x00, 0x00, 0x00, 0x00
1422];
1423const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1424 0xFF, 0xFB, 0xFF, 0x00,
1425 0xEF, 0xD9, 0xBB, 0x00,
1426 0xE8, 0xC9, 0xB1, 0x00,
1427 0x93, 0x65, 0x5E, 0x00,
1428 0xFC, 0xDE, 0xE8, 0x00,
1429 0x9D, 0x88, 0x91, 0x00,
1430 0xFF, 0xFF, 0xFF, 0x00,
1431 0xFF, 0xFF, 0xFF, 0x00,
1432 0xFF, 0xFF, 0xFF, 0x00,
1433 0x47, 0x48, 0x37, 0x00,
1434 0x7A, 0x5E, 0x55, 0x00,
1435 0xDF, 0xD0, 0xAB, 0x00,
1436 0xFF, 0xFB, 0xF9, 0x00,
1437 0xE8, 0xCA, 0xC5, 0x00,
1438 0x8A, 0x7C, 0x77, 0x00,
1439 0x00, 0x00, 0x00, 0x00
1440];
1441const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1442 0xFF, 0xFF, 0xFF, 0x00,
1443 0xFF, 0xFF, 0xCC, 0x00,
1444 0xFF, 0xFF, 0x99, 0x00,
1445 0xFF, 0xFF, 0x66, 0x00,
1446 0xFF, 0xFF, 0x33, 0x00,
1447 0xFF, 0xFF, 0x00, 0x00,
1448 0xFF, 0xCC, 0xFF, 0x00,
1449 0xFF, 0xCC, 0xCC, 0x00,
1450 0xFF, 0xCC, 0x99, 0x00,
1451 0xFF, 0xCC, 0x66, 0x00,
1452 0xFF, 0xCC, 0x33, 0x00,
1453 0xFF, 0xCC, 0x00, 0x00,
1454 0xFF, 0x99, 0xFF, 0x00,
1455 0xFF, 0x99, 0xCC, 0x00,
1456 0xFF, 0x99, 0x99, 0x00,
1457 0xFF, 0x99, 0x66, 0x00,
1458 0xFF, 0x99, 0x33, 0x00,
1459 0xFF, 0x99, 0x00, 0x00,
1460 0xFF, 0x66, 0xFF, 0x00,
1461 0xFF, 0x66, 0xCC, 0x00,
1462 0xFF, 0x66, 0x99, 0x00,
1463 0xFF, 0x66, 0x66, 0x00,
1464 0xFF, 0x66, 0x33, 0x00,
1465 0xFF, 0x66, 0x00, 0x00,
1466 0xFF, 0x33, 0xFF, 0x00,
1467 0xFF, 0x33, 0xCC, 0x00,
1468 0xFF, 0x33, 0x99, 0x00,
1469 0xFF, 0x33, 0x66, 0x00,
1470 0xFF, 0x33, 0x33, 0x00,
1471 0xFF, 0x33, 0x00, 0x00,
1472 0xFF, 0x00, 0xFF, 0x00,
1473 0xFF, 0x00, 0xCC, 0x00,
1474 0xFF, 0x00, 0x99, 0x00,
1475 0xFF, 0x00, 0x66, 0x00,
1476 0xFF, 0x00, 0x33, 0x00,
1477 0xFF, 0x00, 0x00, 0x00,
1478 0xCC, 0xFF, 0xFF, 0x00,
1479 0xCC, 0xFF, 0xCC, 0x00,
1480 0xCC, 0xFF, 0x99, 0x00,
1481 0xCC, 0xFF, 0x66, 0x00,
1482 0xCC, 0xFF, 0x33, 0x00,
1483 0xCC, 0xFF, 0x00, 0x00,
1484 0xCC, 0xCC, 0xFF, 0x00,
1485 0xCC, 0xCC, 0xCC, 0x00,
1486 0xCC, 0xCC, 0x99, 0x00,
1487 0xCC, 0xCC, 0x66, 0x00,
1488 0xCC, 0xCC, 0x33, 0x00,
1489 0xCC, 0xCC, 0x00, 0x00,
1490 0xCC, 0x99, 0xFF, 0x00,
1491 0xCC, 0x99, 0xCC, 0x00,
1492 0xCC, 0x99, 0x99, 0x00,
1493 0xCC, 0x99, 0x66, 0x00,
1494 0xCC, 0x99, 0x33, 0x00,
1495 0xCC, 0x99, 0x00, 0x00,
1496 0xCC, 0x66, 0xFF, 0x00,
1497 0xCC, 0x66, 0xCC, 0x00,
1498 0xCC, 0x66, 0x99, 0x00,
1499 0xCC, 0x66, 0x66, 0x00,
1500 0xCC, 0x66, 0x33, 0x00,
1501 0xCC, 0x66, 0x00, 0x00,
1502 0xCC, 0x33, 0xFF, 0x00,
1503 0xCC, 0x33, 0xCC, 0x00,
1504 0xCC, 0x33, 0x99, 0x00,
1505 0xCC, 0x33, 0x66, 0x00,
1506 0xCC, 0x33, 0x33, 0x00,
1507 0xCC, 0x33, 0x00, 0x00,
1508 0xCC, 0x00, 0xFF, 0x00,
1509 0xCC, 0x00, 0xCC, 0x00,
1510 0xCC, 0x00, 0x99, 0x00,
1511 0xCC, 0x00, 0x66, 0x00,
1512 0xCC, 0x00, 0x33, 0x00,
1513 0xCC, 0x00, 0x00, 0x00,
1514 0x99, 0xFF, 0xFF, 0x00,
1515 0x99, 0xFF, 0xCC, 0x00,
1516 0x99, 0xFF, 0x99, 0x00,
1517 0x99, 0xFF, 0x66, 0x00,
1518 0x99, 0xFF, 0x33, 0x00,
1519 0x99, 0xFF, 0x00, 0x00,
1520 0x99, 0xCC, 0xFF, 0x00,
1521 0x99, 0xCC, 0xCC, 0x00,
1522 0x99, 0xCC, 0x99, 0x00,
1523 0x99, 0xCC, 0x66, 0x00,
1524 0x99, 0xCC, 0x33, 0x00,
1525 0x99, 0xCC, 0x00, 0x00,
1526 0x99, 0x99, 0xFF, 0x00,
1527 0x99, 0x99, 0xCC, 0x00,
1528 0x99, 0x99, 0x99, 0x00,
1529 0x99, 0x99, 0x66, 0x00,
1530 0x99, 0x99, 0x33, 0x00,
1531 0x99, 0x99, 0x00, 0x00,
1532 0x99, 0x66, 0xFF, 0x00,
1533 0x99, 0x66, 0xCC, 0x00,
1534 0x99, 0x66, 0x99, 0x00,
1535 0x99, 0x66, 0x66, 0x00,
1536 0x99, 0x66, 0x33, 0x00,
1537 0x99, 0x66, 0x00, 0x00,
1538 0x99, 0x33, 0xFF, 0x00,
1539 0x99, 0x33, 0xCC, 0x00,
1540 0x99, 0x33, 0x99, 0x00,
1541 0x99, 0x33, 0x66, 0x00,
1542 0x99, 0x33, 0x33, 0x00,
1543 0x99, 0x33, 0x00, 0x00,
1544 0x99, 0x00, 0xFF, 0x00,
1545 0x99, 0x00, 0xCC, 0x00,
1546 0x99, 0x00, 0x99, 0x00,
1547 0x99, 0x00, 0x66, 0x00,
1548 0x99, 0x00, 0x33, 0x00,
1549 0x99, 0x00, 0x00, 0x00,
1550 0x66, 0xFF, 0xFF, 0x00,
1551 0x66, 0xFF, 0xCC, 0x00,
1552 0x66, 0xFF, 0x99, 0x00,
1553 0x66, 0xFF, 0x66, 0x00,
1554 0x66, 0xFF, 0x33, 0x00,
1555 0x66, 0xFF, 0x00, 0x00,
1556 0x66, 0xCC, 0xFF, 0x00,
1557 0x66, 0xCC, 0xCC, 0x00,
1558 0x66, 0xCC, 0x99, 0x00,
1559 0x66, 0xCC, 0x66, 0x00,
1560 0x66, 0xCC, 0x33, 0x00,
1561 0x66, 0xCC, 0x00, 0x00,
1562 0x66, 0x99, 0xFF, 0x00,
1563 0x66, 0x99, 0xCC, 0x00,
1564 0x66, 0x99, 0x99, 0x00,
1565 0x66, 0x99, 0x66, 0x00,
1566 0x66, 0x99, 0x33, 0x00,
1567 0x66, 0x99, 0x00, 0x00,
1568 0x66, 0x66, 0xFF, 0x00,
1569 0x66, 0x66, 0xCC, 0x00,
1570 0x66, 0x66, 0x99, 0x00,
1571 0x66, 0x66, 0x66, 0x00,
1572 0x66, 0x66, 0x33, 0x00,
1573 0x66, 0x66, 0x00, 0x00,
1574 0x66, 0x33, 0xFF, 0x00,
1575 0x66, 0x33, 0xCC, 0x00,
1576 0x66, 0x33, 0x99, 0x00,
1577 0x66, 0x33, 0x66, 0x00,
1578 0x66, 0x33, 0x33, 0x00,
1579 0x66, 0x33, 0x00, 0x00,
1580 0x66, 0x00, 0xFF, 0x00,
1581 0x66, 0x00, 0xCC, 0x00,
1582 0x66, 0x00, 0x99, 0x00,
1583 0x66, 0x00, 0x66, 0x00,
1584 0x66, 0x00, 0x33, 0x00,
1585 0x66, 0x00, 0x00, 0x00,
1586 0x33, 0xFF, 0xFF, 0x00,
1587 0x33, 0xFF, 0xCC, 0x00,
1588 0x33, 0xFF, 0x99, 0x00,
1589 0x33, 0xFF, 0x66, 0x00,
1590 0x33, 0xFF, 0x33, 0x00,
1591 0x33, 0xFF, 0x00, 0x00,
1592 0x33, 0xCC, 0xFF, 0x00,
1593 0x33, 0xCC, 0xCC, 0x00,
1594 0x33, 0xCC, 0x99, 0x00,
1595 0x33, 0xCC, 0x66, 0x00,
1596 0x33, 0xCC, 0x33, 0x00,
1597 0x33, 0xCC, 0x00, 0x00,
1598 0x33, 0x99, 0xFF, 0x00,
1599 0x33, 0x99, 0xCC, 0x00,
1600 0x33, 0x99, 0x99, 0x00,
1601 0x33, 0x99, 0x66, 0x00,
1602 0x33, 0x99, 0x33, 0x00,
1603 0x33, 0x99, 0x00, 0x00,
1604 0x33, 0x66, 0xFF, 0x00,
1605 0x33, 0x66, 0xCC, 0x00,
1606 0x33, 0x66, 0x99, 0x00,
1607 0x33, 0x66, 0x66, 0x00,
1608 0x33, 0x66, 0x33, 0x00,
1609 0x33, 0x66, 0x00, 0x00,
1610 0x33, 0x33, 0xFF, 0x00,
1611 0x33, 0x33, 0xCC, 0x00,
1612 0x33, 0x33, 0x99, 0x00,
1613 0x33, 0x33, 0x66, 0x00,
1614 0x33, 0x33, 0x33, 0x00,
1615 0x33, 0x33, 0x00, 0x00,
1616 0x33, 0x00, 0xFF, 0x00,
1617 0x33, 0x00, 0xCC, 0x00,
1618 0x33, 0x00, 0x99, 0x00,
1619 0x33, 0x00, 0x66, 0x00,
1620 0x33, 0x00, 0x33, 0x00,
1621 0x33, 0x00, 0x00, 0x00,
1622 0x00, 0xFF, 0xFF, 0x00,
1623 0x00, 0xFF, 0xCC, 0x00,
1624 0x00, 0xFF, 0x99, 0x00,
1625 0x00, 0xFF, 0x66, 0x00,
1626 0x00, 0xFF, 0x33, 0x00,
1627 0x00, 0xFF, 0x00, 0x00,
1628 0x00, 0xCC, 0xFF, 0x00,
1629 0x00, 0xCC, 0xCC, 0x00,
1630 0x00, 0xCC, 0x99, 0x00,
1631 0x00, 0xCC, 0x66, 0x00,
1632 0x00, 0xCC, 0x33, 0x00,
1633 0x00, 0xCC, 0x00, 0x00,
1634 0x00, 0x99, 0xFF, 0x00,
1635 0x00, 0x99, 0xCC, 0x00,
1636 0x00, 0x99, 0x99, 0x00,
1637 0x00, 0x99, 0x66, 0x00,
1638 0x00, 0x99, 0x33, 0x00,
1639 0x00, 0x99, 0x00, 0x00,
1640 0x00, 0x66, 0xFF, 0x00,
1641 0x00, 0x66, 0xCC, 0x00,
1642 0x00, 0x66, 0x99, 0x00,
1643 0x00, 0x66, 0x66, 0x00,
1644 0x00, 0x66, 0x33, 0x00,
1645 0x00, 0x66, 0x00, 0x00,
1646 0x00, 0x33, 0xFF, 0x00,
1647 0x00, 0x33, 0xCC, 0x00,
1648 0x00, 0x33, 0x99, 0x00,
1649 0x00, 0x33, 0x66, 0x00,
1650 0x00, 0x33, 0x33, 0x00,
1651 0x00, 0x33, 0x00, 0x00,
1652 0x00, 0x00, 0xFF, 0x00,
1653 0x00, 0x00, 0xCC, 0x00,
1654 0x00, 0x00, 0x99, 0x00,
1655 0x00, 0x00, 0x66, 0x00,
1656 0x00, 0x00, 0x33, 0x00,
1657 0xEE, 0x00, 0x00, 0x00,
1658 0xDD, 0x00, 0x00, 0x00,
1659 0xBB, 0x00, 0x00, 0x00,
1660 0xAA, 0x00, 0x00, 0x00,
1661 0x88, 0x00, 0x00, 0x00,
1662 0x77, 0x00, 0x00, 0x00,
1663 0x55, 0x00, 0x00, 0x00,
1664 0x44, 0x00, 0x00, 0x00,
1665 0x22, 0x00, 0x00, 0x00,
1666 0x11, 0x00, 0x00, 0x00,
1667 0x00, 0xEE, 0x00, 0x00,
1668 0x00, 0xDD, 0x00, 0x00,
1669 0x00, 0xBB, 0x00, 0x00,
1670 0x00, 0xAA, 0x00, 0x00,
1671 0x00, 0x88, 0x00, 0x00,
1672 0x00, 0x77, 0x00, 0x00,
1673 0x00, 0x55, 0x00, 0x00,
1674 0x00, 0x44, 0x00, 0x00,
1675 0x00, 0x22, 0x00, 0x00,
1676 0x00, 0x11, 0x00, 0x00,
1677 0x00, 0x00, 0xEE, 0x00,
1678 0x00, 0x00, 0xDD, 0x00,
1679 0x00, 0x00, 0xBB, 0x00,
1680 0x00, 0x00, 0xAA, 0x00,
1681 0x00, 0x00, 0x88, 0x00,
1682 0x00, 0x00, 0x77, 0x00,
1683 0x00, 0x00, 0x55, 0x00,
1684 0x00, 0x00, 0x44, 0x00,
1685 0x00, 0x00, 0x22, 0x00,
1686 0x00, 0x00, 0x11, 0x00,
1687 0xEE, 0xEE, 0xEE, 0x00,
1688 0xDD, 0xDD, 0xDD, 0x00,
1689 0xBB, 0xBB, 0xBB, 0x00,
1690 0xAA, 0xAA, 0xAA, 0x00,
1691 0x88, 0x88, 0x88, 0x00,
1692 0x77, 0x77, 0x77, 0x00,
1693 0x55, 0x55, 0x55, 0x00,
1694 0x44, 0x44, 0x44, 0x00,
1695 0x22, 0x22, 0x22, 0x00,
1696 0x11, 0x11, 0x11, 0x00,
1697 0x00, 0x00, 0x00, 0x00
1698];
1699
58309c73
KS
1700#[cfg(test)]
1701mod test {
1702 use super::*;
1703 use std::fs::File;
1704
1705 #[test]
1706 fn test_mov_demux() {
1707 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1708 let mut fr = FileReader::new_read(&mut file);
1709 let mut br = ByteReader::new(&mut fr);
1710 let mut dmx = MOVDemuxer::new(&mut br);
1711 let mut sm = StreamManager::new();
1712 let mut si = SeekIndex::new();
1713 dmx.open(&mut sm, &mut si).unwrap();
1714
1715 loop {
1716 let pktres = dmx.get_frame(&mut sm);
1717 if let Err(e) = pktres {
1718 if e == DemuxerError::EOF { break; }
1719 panic!("error");
1720 }
1721 let pkt = pktres.unwrap();
1722 println!("Got {}", pkt);
1723 }
1724 }
1725}