mov: introduce an option to print file structure
[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] = &[
346 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
347 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
348 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
349];
350
351fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
352 const KNOWN_HDLR_SIZE: u64 = 24;
353 validate!(size >= KNOWN_HDLR_SIZE);
354 let version = br.read_byte()?;
355 validate!(version == 0);
356 let flags = br.read_u24be()?;
357 validate!(flags == 0);
358 let comp_type = br.read_u32be()?;
359 let comp_subtype = br.read_u32be()?;
360 let _comp_manufacturer = br.read_u32be()?;
361 let _comp_flags = br.read_u32be()?;
362 let _comp_flags_mask = br.read_u32be()?;
363
d4809976 364 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
58309c73
KS
365 if comp_subtype == mktag!(b"vide") {
366 track.stream_type = StreamType::Video;
367 } else if comp_subtype == mktag!(b"soun") {
368 track.stream_type = StreamType::Audio;
369 } else {
370 track.stream_type = StreamType::Data;
371 }
372 } else if comp_type == mktag!(b"dhlr") {
373 track.stream_type = StreamType::Data;
374 } else {
375 println!("Unknown stream type");
376 track.stream_type = StreamType::Data;
377 }
c8db9313 378
58309c73
KS
379 Ok(KNOWN_HDLR_SIZE)
380}
381
382fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
383 track.read_minf(br, size)?;
384 Ok(size)
385}
386
387const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
388 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
389 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
390 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
391 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
392 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
393 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
394 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
395];
396
397fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
398 const KNOWN_VMHD_SIZE: u64 = 12;
399 validate!(track.stream_type == StreamType::Video);
400 validate!(size >= KNOWN_VMHD_SIZE);
401 let version = br.read_byte()?;
402 validate!(version == 0);
403 let _flags = br.read_u24be()?;
404 br.read_skip(2)?; // graphics mode
405 br.read_skip(6)?; // opcolor
406 Ok(KNOWN_VMHD_SIZE)
407}
408
409fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
410 const KNOWN_SMHD_SIZE: u64 = 8;
411 validate!(track.stream_type == StreamType::Audio);
412 validate!(size >= KNOWN_SMHD_SIZE);
413 let version = br.read_byte()?;
414 validate!(version == 0);
415 let _flags = br.read_u24be()?;
416 br.read_skip(2)?; // balance
417 br.read_skip(2)?;
418 Ok(KNOWN_SMHD_SIZE)
419}
420
421fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
422 validate!(track.stream_type == StreamType::Data);
423 Ok(0)
424}
425
426fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
427 validate!(track.stream_type == StreamType::Data);
428 const KNOWN_GMIN_SIZE: u64 = 16;
429 validate!(size >= KNOWN_GMIN_SIZE);
430 let version = br.read_byte()?;
431 validate!(version == 0);
432 let _flags = br.read_u24be()?;
433 br.read_skip(2)?; // graphics mode
434 br.read_skip(6)?; // opcolor
435 br.read_skip(2)?; // balance
436 br.read_skip(2)?;
437 Ok(KNOWN_GMIN_SIZE)
438}
439
440fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
441 track.read_stbl(br, size)?;
442 Ok(size)
443}
444
445const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
446 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
bbbf86dd 447 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
58309c73
KS
448 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
449 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
450 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
451 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
452 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
453];
454
89b16ac8
KS
455fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
456 let read_part = br.tell() - start_pos;
457 if read_part + 8 < size {
9aa783a0
KS
458 let mut buf = [0; 8];
459 br.peek_buf(&mut buf)?;
460 if &buf[4..8] != b"wave" {
461 let mut buf = vec![0; (size - read_part) as usize];
462 br.read_buf(&mut buf)?;
463 return Ok(Some(buf));
464 }
465
89b16ac8
KS
466 let csize = br.read_u32be()? as u64;
467 let ctag = br.read_u32be()?;
468 validate!(read_part + csize <= size);
469 validate!(ctag == mktag!(b"wave"));
470 if csize == 8 {
471 return Ok(None);
472 }
473 let mut buf = [0; 8];
474 br.peek_buf(&mut buf)?;
475 if &buf[4..8] == b"frma" {
476 br.read_skip(12)?;
477 if csize > 20 {
478 let mut buf = vec![0; (csize - 20) as usize];
479 br.read_buf(&mut buf)?;
480 Ok(Some(buf))
481 } else {
482 Ok(None)
483 }
484 } else if csize > 8 {
485 let mut buf = vec![0; (csize as usize) - 8];
486 br.read_buf(&mut buf)?;
487 Ok(Some(buf))
488 } else {
489 Ok(None)
490 }
491 } else {
492 Ok(None)
493 }
494}
495
58309c73
KS
496fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
497 const KNOWN_STSD_SIZE: u64 = 24;
498 validate!(size >= KNOWN_STSD_SIZE);
499 let start_pos = br.tell();
500 let version = br.read_byte()?;
501 validate!(version == 0);
502 let _flags = br.read_u24be()?;
503 let entries = br.read_u32be()?;
504 validate!(entries > 0);
61cab15b 505 let esize = u64::from(br.read_u32be()?);
58309c73
KS
506 validate!(esize + 8 <= size);
507 let mut fcc = [0u8; 4];
508 br.read_buf(&mut fcc)?;
509 br.read_skip(6)?;
510 let _data_ref = br.read_u16be()?;
511
512 track.fcc = fcc;
513
514 let codec_info;
515 match track.stream_type {
516 StreamType::Video => {
517 let _ver = br.read_u16be()?;
518 let _revision = br.read_u16le()?;
519 let _vendor = br.read_u32be()?;
520 let _temp_quality = br.read_u32be()?;
521 let _spat_quality = br.read_u32be()?;
522 let width = br.read_u16be()? as usize;
523 let height = br.read_u16be()? as usize;
524 let _hor_res = br.read_u32be()?;
525 let _vert_res = br.read_u32be()?;
526 let data_size = br.read_u32be()?;
527 validate!(data_size == 0);
528 let _frame_count = br.read_u16be()? as usize;
529 let _cname_len = br.read_byte()? as usize;
530 br.read_skip(31)?; // actual compressor name
531 let depth = br.read_u16be()?;
532 let ctable_id = br.read_u16be()?;
8019c866
KS
533 let grayscale = depth > 0x20 || depth == 1;
534 let depth = if grayscale { depth & 0x1F } else { depth };
535 validate!(depth <= 8 || (ctable_id == 0xFFFF));
58309c73 536 if ctable_id == 0 {
00333698 537 let max_pal_size = start_pos + size - br.tell();
58cd51fa
KS
538 let mut pal = [0; 1024];
539 read_palette(br, max_pal_size, &mut pal)?;
540 track.pal = Some(Arc::new(pal));
8019c866 541 } else if (depth <= 8) && !grayscale {
2736c15a
KS
542 match depth & 0x1F {
543 2 => {
544 let mut pal = [0; 1024];
545 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
546 track.pal = Some(Arc::new(pal));
547 },
548 4 => {
549 let mut pal = [0; 1024];
550 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
551 track.pal = Some(Arc::new(pal));
552 },
553 8 => {
554 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
555 },
556 _ => {},
557 };
2949bcfa 558 } else if grayscale && ctable_id != 0xFFFF {
2736c15a
KS
559 let mut pal = [0; 1024];
560 let cdepth = depth & 0x1F;
561 let size = 1 << cdepth;
562 for i in 0..size {
8019c866 563 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
2736c15a
KS
564 let mut off = 8 - cdepth;
565 while off >= cdepth {
566 clr |= clr >> (8 - off);
567 off -= cdepth;
568 }
569 if off > 0 {
570 clr |= clr >> (8 - off);
571 }
572 pal[i * 4] = clr;
573 pal[i * 4 + 1] = clr;
574 pal[i * 4 + 2] = clr;
575 }
576 track.pal = Some(Arc::new(pal));
58309c73
KS
577 }
578// todo other atoms, put as extradata
579 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
580 name
581 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
582 name
583 } else {
584 "unknown"
585 };
586 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
8019c866
KS
587 let mut vhdr = NAVideoInfo::new(width, height, false, format);
588 vhdr.bits = depth as u8;
61cab15b 589 let edata = if br.tell() - start_pos + 4 < size {
58309c73 590//todo skip various common atoms
61cab15b 591 let edata_size = br.read_u32be()? as usize;
d341f57a
KS
592 validate!(edata_size >= 4);
593 let mut buf = vec![0; edata_size - 4];
58309c73 594 br.read_buf(buf.as_mut_slice())?;
61cab15b
KS
595 Some(buf)
596 } else {
597 None
598 };
58309c73
KS
599 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
600 },
601 StreamType::Audio => {
89b16ac8 602 let sver = br.read_u16be()?;
58309c73
KS
603 let _revision = br.read_u16le()?;
604 let _vendor = br.read_u32be()?;
605 let nchannels = br.read_u16be()?;
606 validate!(nchannels <= 64);
607 let sample_size = br.read_u16be()?;
608 validate!(sample_size <= 128);
609 let _compr_id = br.read_u16be()?;
610 let packet_size = br.read_u16be()? as usize;
611 validate!(packet_size == 0);
612 let sample_rate = br.read_u32be()?;
7afec34d 613 validate!(sample_rate > (1 << 16));
58309c73
KS
614 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
615 name
616 } 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]))) {
617 name
618 } else {
619 "unknown"
620 };
e5d3fef5
KS
621 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
622 if &fcc == b"raw " && sample_size == 8 {
623 soniton.signed = false;
624 }
58309c73 625 let block_align = 1;
89b16ac8 626 if sver == 1 {
b0e12d42 627 let samples_per_packet = br.read_u32be()?;
89b16ac8 628 let _bytes_per_packet = br.read_u32be()?;
9efec4ed 629 let bytes_per_frame = br.read_u32be()?;
89b16ac8 630 let _bytes_per_sample = br.read_u32be()?;
9efec4ed 631 track.bsize = bytes_per_frame as usize;
b0e12d42 632 track.frame_samples = samples_per_packet as usize;
7afec34d 633 track.tb_num = samples_per_packet;
9efec4ed 634 } else {
7afec34d 635 track.bsize = (sample_size / 8) as usize;
89b16ac8 636 }
7afec34d
KS
637 track.tb_den = sample_rate >> 16;
638 track.raw_audio = match &fcc {
639 b"NONE" | b"raw " | b"twos" | b"sowt" |
640 b"in24" | b"in32" | b"fl32" | b"fl64" |
641 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
642 b"alaw" | b"ulaw" |
643 b"MAC3" | b"MAC6" => true,
644 _ => false,
645 };
58309c73 646 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
89b16ac8 647 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
648 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
649 track.channels = nchannels as usize;
650 track.bits = sample_size as usize;
651 },
652 StreamType::None => {
653 return Err(DemuxerError::InvalidData);
654 },
655 _ => {
656//todo put it all into extradata
657 let edata = None;
658 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
659 },
660 };
661 let read_size = br.tell() - start_pos;
662 validate!(read_size <= size);
7afec34d 663 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
664 track.stsd_found = true;
665 Ok(read_size)
666}
667
bbbf86dd 668fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
d4809976 669 validate!(size >= 8);
bbbf86dd
KS
670 let start_pos = br.tell();
671 let version = br.read_byte()?;
672 validate!(version == 0);
673 let _flags = br.read_u24be()?;
674 let entries = br.read_u32be()? as usize;
675 validate!(entries as u64 <= (size - 8) / 8);
d4809976
KS
676 if entries == 0 {
677 } else if entries == 1 {
bbbf86dd
KS
678 let _count = br.read_u32be()?;
679 let tb_num = br.read_u32be()?;
680 if let Some(ref mut stream) = track.stream {
681 let tb_den = stream.tb_den;
7afec34d 682 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
bbbf86dd
KS
683 stream.duration /= u64::from(stream.tb_den / tb_den);
684 stream.tb_num = tb_num;
685 stream.tb_den = tb_den;
686 track.tb_num = tb_num;
687 track.tb_den = tb_den;
688 }
689 } else {
690 track.time_to_sample.truncate(0);
691 track.time_to_sample.reserve(entries);
692 for _ in 0..entries {
693 let count = br.read_u32be()?;
694 let mult = br.read_u32be()?;
695 track.time_to_sample.push((count, mult));
696 }
697 }
698 let read_size = br.tell() - start_pos;
699 validate!(read_size <= size);
700 Ok(read_size)
701}
702
58309c73
KS
703fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
704 let version = br.read_byte()?;
705 validate!(version == 0);
706 let _flags = br.read_u24be()?;
707 let entries = br.read_u32be()? as usize;
708 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
709 validate!((entries * 4 + 8) as u64 == size);
710 track.keyframes = Vec::with_capacity(entries);
711 let mut last_sample_no = 0;
712 for _ in 0..entries {
713 let sample_no = br.read_u32be()?;
714 validate!(sample_no > last_sample_no);
715 track.keyframes.push(sample_no);
716 last_sample_no = sample_no;
717 }
718 Ok(size)
719}
720
721fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
722 let version = br.read_byte()?;
723 validate!(version == 0);
724 let _flags = br.read_u24be()?;
725 let entries = br.read_u32be()? as usize;
726 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
727 validate!((entries * 12 + 8) as u64 == size);
728 track.sample_map = Vec::with_capacity(entries);
729 let mut last_sample_no = 0;
730 for _i in 0..entries {
731 let sample_no = br.read_u32be()?;
732 validate!(sample_no > last_sample_no);
733 let nsamples = br.read_u32be()?;
734 let _sample_desc = br.read_u32be()?;
735 track.sample_map.push((sample_no, nsamples));
736 last_sample_no = sample_no;
737 }
738 Ok(size)
739}
740
741fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
742 let version = br.read_byte()?;
743 validate!(version == 0);
744 let _flags = br.read_u24be()?;
745 let sample_size = br.read_u32be()?;
746 if sample_size != 0 {
747 track.sample_size = sample_size;
9efec4ed
KS
748 if track.sample_size != 1 || track.bsize == 0 {
749 track.bsize = sample_size as usize;
750 }
58309c73
KS
751 Ok(8)
752 } else {
753 let entries = br.read_u32be()? as usize;
754 validate!((entries * 4 + 12) as u64 == size);
755 track.chunk_sizes = Vec::with_capacity(entries);
756 for _ in 0..entries {
757 let sample_size = br.read_u32be()?;
758 track.chunk_sizes.push(sample_size);
759 }
760 Ok(size)
761 }
762}
763
764fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
765 let version = br.read_byte()?;
766 validate!(version == 0);
767 let _flags = br.read_u24be()?;
768 let entries = br.read_u32be()? as usize;
769 validate!((entries * 4 + 8) as u64 == size);
770 track.chunk_offsets = Vec::with_capacity(entries);
771 for _i in 0..entries {
772 let sample_offset = br.read_u32be()?;
773 track.chunk_offsets.push(u64::from(sample_offset));
774 }
775 Ok(size)
776}
777
778struct MOVDemuxer<'a> {
779 src: &'a mut ByteReader<'a>,
780 depth: usize,
781 mdat_pos: u64,
782 mdat_size: u64,
783 tracks: Vec<Track>,
784 cur_track: usize,
785 tb_den: u32,
786 duration: u32,
58cd51fa 787 pal: Option<Arc<[u8; 1024]>>,
650d7bfb
KS
788
789 print_chunks: bool,
58309c73
KS
790}
791
792struct Track {
793 track_id: u32,
794 track_str_id: usize,
795 track_no: u32,
bbbf86dd 796 tb_num: u32,
58309c73 797 tb_den: u32,
7afec34d
KS
798 raw_audio: bool,
799 raw_apos: u64,
a480a0de 800 duration: u32,
58309c73
KS
801 depth: u8,
802 tkhd_found: bool,
803 stsd_found: bool,
804 stream_type: StreamType,
805 width: usize,
806 height: usize,
807 channels: usize,
808 bits: usize,
9efec4ed 809 bsize: usize,
58309c73
KS
810 fcc: [u8; 4],
811 keyframes: Vec<u32>,
812 chunk_sizes: Vec<u32>,
813 chunk_offsets: Vec<u64>,
bbbf86dd 814 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
815 sample_map: Vec<(u32, u32)>,
816 sample_size: u32,
b0e12d42 817 frame_samples: usize,
58309c73
KS
818 stream: Option<NAStream>,
819 cur_chunk: usize,
820 cur_sample: usize,
821 samples_left: usize,
822 last_offset: u64,
58cd51fa 823 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 824 timesearch: TimeSearcher,
650d7bfb
KS
825
826 print_chunks: bool,
bbbf86dd
KS
827}
828
829#[derive(Default)]
830struct TimeSearcher {
831 idx: usize,
832 base: u64,
833 sbase: u32,
834 cur_len: u32,
835 cur_mul: u32,
836}
837
838impl TimeSearcher {
839 fn new() -> Self { Self::default() }
840 fn reset(&mut self) {
841 *self = Self::default();
842 }
843 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
844 if tts.is_empty() {
845 u64::from(sample)
846 } else if sample >= self.sbase {
847 let mut sample = sample - self.sbase;
848 if self.idx == 0 {
849 let (cur_len, cur_mul) = tts[0];
850 self.cur_len = cur_len;
851 self.cur_mul = cur_mul;
852 self.idx += 1;
853 }
854 while self.idx < tts.len() && sample > self.cur_len {
855 sample -= self.cur_len;
856 self.sbase += self.cur_len;
857 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
858 self.cur_len = tts[self.idx].0;
859 self.cur_mul = tts[self.idx].1;
860 self.idx += 1;
861 }
862 self.base + u64::from(sample) * u64::from(self.cur_mul)
863 } else {
864 self.reset();
865 self.map_time(sample, tts)
866 }
867 }
58309c73
KS
868}
869
870impl Track {
871 fn new(track_no: u32, tb_den: u32) -> Self {
872 Self {
873 tkhd_found: false,
874 stsd_found: false,
875 track_id: 0,
876 track_str_id: 0,
877 track_no,
bbbf86dd 878 tb_num: 1,
58309c73 879 tb_den,
7afec34d
KS
880 raw_audio: false,
881 raw_apos: 0,
a480a0de 882 duration: 0,
58309c73
KS
883 stream_type: StreamType::None,
884 width: 0,
885 height: 0,
886 channels: 0,
887 bits: 0,
9efec4ed 888 bsize: 0,
58309c73
KS
889 fcc: [0; 4],
890 keyframes: Vec::new(),
891 chunk_sizes: Vec::new(),
892 chunk_offsets: Vec::new(),
bbbf86dd 893 time_to_sample: Vec::new(),
58309c73
KS
894 sample_map: Vec::new(),
895 sample_size: 0,
b0e12d42 896 frame_samples: 0,
58309c73
KS
897 stream: None,
898 depth: 0,
899 cur_chunk: 0,
900 cur_sample: 0,
901 samples_left: 0,
902 last_offset: 0,
58cd51fa 903 pal: None,
bbbf86dd 904 timesearch: TimeSearcher::new(),
650d7bfb
KS
905
906 print_chunks: false,
58309c73
KS
907 }
908 }
909 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
910 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
911 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
912 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
913 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 914 if !self.keyframes.is_empty() {
58309c73
KS
915 seek_index.mode = SeekIndexMode::Present;
916 }
bbbf86dd 917 let mut tsearch = TimeSearcher::new();
58309c73 918 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
919 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
920 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
921 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
922 }
923 }
924 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
925 if nsamp == 0 {
9efec4ed 926 self.bsize
58309c73
KS
927 } else {
928 match &self.fcc {
929 b"NONE" | b"raw " | b"twos" | b"sowt" => {
930 (nsamp * self.bits * self.channels + 7) >> 3
931 },
932 b"ima4" => {
933 let nblocks = (nsamp + 63) >> 6;
934 nblocks * 34 * self.channels
935 },
936 b"MAC3" => {
937 (nsamp + 5) / 6 * 2 * self.channels
938 },
939 b"MAC6" => {
940 (nsamp + 5) / 6 * self.channels
941 },
942 b"in24" => nsamp * 3 * self.channels,
943 b"in32" | b"fl32" => nsamp * 4 * self.channels,
944 b"fl64" => nsamp * 8 * self.channels,
945 b"ulaw" | b"alaw" => nsamp,
946 b"ms\x00\x02" => { //MS ADPCM
947 ((nsamp - 1) / 2 + 7) * self.channels
948 },
949 b"ms\x00\x21" => { //IMA ADPCM
950 (nsamp / 2 + 4) * self.channels
951 },
9efec4ed 952 _ => self.bsize,
58309c73
KS
953 }
954 }
955 }
956 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 957 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
7afec34d 958 let mut pts = NATimeInfo::new(Some(pts_val), None, None, self.tb_num, self.tb_den);
58309c73
KS
959//todo dts decoding
960 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
961 if self.cur_sample >= self.chunk_sizes.len() {
962 return None;
963 }
964 let offset = self.chunk_offsets[self.cur_sample];
965 let size = self.chunk_sizes[self.cur_sample] as usize;
966 self.cur_sample += 1;
967 Some((pts, offset, size))
968 } else {
969 if self.samples_left == 0 {
970 if self.cur_chunk >= self.chunk_offsets.len() {
971 return None;
972 }
973 for (idx, samples) in self.sample_map.iter() {
974 if *idx as usize <= self.cur_chunk + 1 {
975 self.samples_left = *samples as usize;
976 } else {
977 break;
978 }
979 }
980 self.last_offset = self.chunk_offsets[self.cur_chunk];
981 self.cur_chunk += 1;
982 }
983 let offset = self.last_offset;
984 let size = self.get_size(self.cur_sample);
985 self.last_offset += size as u64;
986 if self.stream_type == StreamType::Video {
987 self.samples_left -= 1;
d940f0c2
KS
988 } else if self.frame_samples != 0 && self.bsize != 0 {
989 let nblocks = size / self.bsize;
7afec34d
KS
990 if self.raw_audio {
991 pts.pts = Some(self.raw_apos);
992 pts.duration = Some(nblocks as u64);
993 self.raw_apos += nblocks as u64;
994 }
d940f0c2
KS
995 if nblocks > 0 {
996 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
997 self.samples_left -= consumed;
998 } else {
999 self.samples_left = 0;
1000 }
7afec34d
KS
1001 } else if !self.raw_audio {
1002 self.samples_left -= 1;
58309c73 1003 } else {
7afec34d
KS
1004 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1005 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1006 let cur_size = self.calculate_chunk_size(self.samples_left);
1007 let add_off = (size - cur_size) as u64;
1008 let dsize = cur_size.min(max_size);
1009 if self.samples_left >= BLOCK_SAMPLES {
1010 self.cur_sample += BLOCK_SAMPLES;
1011 self.samples_left -= BLOCK_SAMPLES;
1012 self.last_offset -= size as u64;
1013 } else {
1014 self.cur_sample += self.samples_left;
1015 self.samples_left = 0;
1016 }
1017 return Some((pts, offset + add_off, dsize));
58309c73
KS
1018 }
1019 self.cur_sample += 1;
1020 Some((pts, offset, size))
1021 }
1022 }
1023 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1024 if !self.chunk_sizes.is_empty() {
58309c73 1025 self.chunk_sizes[sample_no] as usize
61cab15b 1026 } else if !self.sample_map.is_empty() {
58309c73
KS
1027 let mut nsamp = 0;
1028 for (idx, samples) in self.sample_map.iter() {
1029 if *idx as usize <= self.cur_chunk {
1030 nsamp = *samples;
1031 } else {
1032 break;
1033 }
1034 }
1035 self.calculate_chunk_size(nsamp as usize)
1036 } else {
9efec4ed 1037 self.bsize
58309c73
KS
1038 }
1039 }
7afec34d 1040 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
58309c73
KS
1041 self.cur_sample = pts as usize;
1042 self.samples_left = 0;
1043 if self.stream_type == StreamType::Audio {
7afec34d
KS
1044 if let NATimePoint::Milliseconds(ms) = tpoint {
1045 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1046 if self.raw_audio {
1047 if self.frame_samples != 0 {
1048 self.raw_apos = exp_pts / (self.frame_samples as u64);
1049 let mut apos = 0;
1050 self.cur_sample = 0;
1051 self.cur_chunk = 0;
1052 let mut cmap = self.sample_map.iter();
1053 let mut cur_samps = 0;
1054 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1055 loop {
1056 if self.cur_chunk + 1 == next_idx as usize {
1057 self.samples_left = cur_samps;
1058 cur_samps = next_samples as usize;
1059 if let Some((new_idx, new_samples)) = cmap.next() {
1060 next_idx = *new_idx;
1061 next_samples = *new_samples;
1062 }
1063 }
1064 self.raw_apos = apos;
1065 apos += (cur_samps / self.frame_samples) as u64;
1066 if apos > exp_pts {
1067 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1068 if self.cur_chunk >= self.chunk_offsets.len() {
1069 return Err(DemuxerError::SeekError);
1070 }
1071 self.last_offset = self.chunk_offsets[self.cur_chunk];
1072 break;
1073 }
1074 }
1075 self.cur_chunk += 1;
1076 }
1077 self.samples_left = cur_samps;
1078 self.cur_chunk += 1;
1079 } else {
1080 self.raw_apos = exp_pts;
1081 self.cur_sample = exp_pts as usize;
1082 let mut csamp = 0;
1083 self.cur_chunk = 0;
1084 let mut cmap = self.sample_map.iter();
1085 let mut cur_samps = 0;
1086 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1087 loop {
1088 if self.cur_chunk + 1 == next_idx as usize {
1089 self.samples_left = cur_samps;
1090 cur_samps = next_samples as usize;
1091 if let Some((new_idx, new_samples)) = cmap.next() {
1092 next_idx = *new_idx;
1093 next_samples = *new_samples;
1094 }
1095 }
1096 csamp += cur_samps;
1097 if csamp > self.cur_sample {
1098 if self.cur_chunk >= self.chunk_offsets.len() {
1099 return Err(DemuxerError::SeekError);
1100 }
1101 self.last_offset = self.chunk_offsets[self.cur_chunk];
1102 break;
1103 }
1104 self.cur_chunk += 1;
1105 }
1106 self.samples_left = csamp - self.cur_sample;
1107 self.cur_chunk += 1;
1108 }
1109 } else {
1110 self.cur_chunk = self.cur_sample;
1111 }
1112 } else {
1113 self.cur_chunk = self.cur_sample;
1114 }
61cab15b 1115 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1116 let mut csamp = 0;
1117 self.cur_chunk = 0;
1118 let mut cmap = self.sample_map.iter();
1119 let mut cur_samps = 0;
1120 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1121 loop {
bbbf86dd 1122 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1123 self.samples_left = cur_samps;
1124 cur_samps = next_samples as usize;
1125 if let Some((new_idx, new_samples)) = cmap.next() {
1126 next_idx = *new_idx;
1127 next_samples = *new_samples;
1128 }
1129 }
1130 csamp += cur_samps;
1131 if csamp >= self.cur_sample {
7afec34d
KS
1132 if self.cur_chunk >= self.chunk_offsets.len() {
1133 return Err(DemuxerError::SeekError);
1134 }
58309c73
KS
1135 self.last_offset = self.chunk_offsets[self.cur_chunk];
1136 break;
1137 }
1138 self.cur_chunk += 1;
1139 }
1140 csamp -= cur_samps;
bbbf86dd 1141 for sample_no in csamp..self.cur_sample {
58309c73
KS
1142 self.last_offset += self.get_size(sample_no) as u64;
1143 }
bbbf86dd
KS
1144 self.samples_left = csamp + cur_samps - self.cur_sample;
1145 self.cur_chunk += 1;
58309c73 1146 }
7afec34d 1147 Ok(())
58309c73
KS
1148 }
1149}
1150
1151impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1152 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1153 self.read_root(strmgr)?;
1154 validate!(self.mdat_pos > 0);
61cab15b 1155 validate!(!self.tracks.is_empty());
58309c73
KS
1156 for track in self.tracks.iter() {
1157 track.fill_seek_index(seek_index);
1158 }
1159 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1160 self.cur_track = 0;
1161 Ok(())
1162 }
1163
1164 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1165 if self.tracks.is_empty() {
58309c73
KS
1166 return Err(DemuxerError::EOF);
1167 }
1168 for _ in 0..self.tracks.len() {
1169 if self.cur_track >= self.tracks.len() {
1170 self.cur_track = 0;
1171 }
1172 let track = &mut self.tracks[self.cur_track];
1173 self.cur_track += 1;
58cd51fa 1174 let first = track.cur_sample == 0;
58309c73
KS
1175 if let Some((pts, offset, size)) = track.get_next_chunk() {
1176 let str = strmgr.get_stream(track.track_str_id);
1177 if str.is_none() { return Err(DemuxerError::InvalidData); }
1178 let stream = str.unwrap();
1179 self.src.seek(SeekFrom::Start(offset))?;
58cd51fa
KS
1180 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1181 if let Some(ref pal) = track.pal {
1182 let side_data = NASideData::Palette(first, pal.clone());
1183 pkt.add_side_data(side_data);
1184 }
58309c73
KS
1185 return Ok(pkt);
1186 }
1187 }
61cab15b 1188 Err(DemuxerError::EOF)
58309c73
KS
1189 }
1190
24d99894 1191 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1192 let ret = seek_index.find_pos(time);
1193 if ret.is_none() {
1194 return Err(DemuxerError::SeekError);
1195 }
1196 let seek_info = ret.unwrap();
1197 for track in self.tracks.iter_mut() {
7afec34d 1198 track.seek(seek_info.pts, time)?;
58309c73
KS
1199 }
1200 Ok(())
1201 }
a480a0de
KS
1202 fn get_duration(&self) -> u64 {
1203 if self.tb_den != 0 {
1204 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1205 } else {
1206 0
1207 }
1208 }
58309c73
KS
1209}
1210
650d7bfb
KS
1211const PRINT_CHUNKS: &str = "print_chunks";
1212
1213const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1214 NAOptionDefinition {
1215 name: PRINT_CHUNKS,
1216 description: "Print parsed file structure",
1217 opt_type: NAOptionDefinitionType::Bool },
1218];
1219
787b8d03 1220impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb
KS
1221 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
1222 fn set_options(&mut self, options: &[NAOption]) {
1223 for option in options.iter() {
1224 for opt_def in DEMUXER_OPTIONS.iter() {
1225 if opt_def.check(option).is_ok() {
1226 match (option.name, &option.value) {
1227 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1228 self.print_chunks = *val;
1229 },
1230 _ => {},
1231 }
1232 }
1233 }
1234 }
1235 }
1236 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1237 match name {
1238 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1239 _ => None,
1240 }
1241 }
787b8d03
KS
1242}
1243
58309c73
KS
1244impl<'a> MOVDemuxer<'a> {
1245 fn new(io: &'a mut ByteReader<'a>) -> Self {
1246 MOVDemuxer {
1247 src: io,
1248 depth: 0,
1249 mdat_pos: 0,
1250 mdat_size: 0,
1251 tracks: Vec::with_capacity(2),
1252 cur_track: 0,
1253 tb_den: 0,
1254 duration: 0,
58cd51fa 1255 pal: None,
650d7bfb
KS
1256
1257 print_chunks: false,
58309c73
KS
1258 }
1259 }
1260 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1261 self.depth = 0;
1262 while self.src.left() != 0 {
1263 let ret = read_chunk_header(&mut self.src);
1264 if ret.is_err() { break; }
1265 let (ctype, size) = ret.unwrap();
1266 if IGNORED_CHUNKS.contains(&ctype) {
1267 self.src.skip64(size)?;
1268 continue;
1269 }
1270 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1271 let read_size;
1272 if let Some(ref handler) = handler {
1273 read_size = (handler.parse)(self, strmgr, size)?;
1274 } else {
1275 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1276 read_size = 0;
1277 }
1278 validate!(read_size <= size);
1279 self.src.skip64(size - read_size)?;
1280 }
1281//todo check if all needed chunks are found
1282 Ok(())
1283 }
1284 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1285}
1286
1287pub struct MOVDemuxerCreator { }
1288
1289impl DemuxerCreator for MOVDemuxerCreator {
1290 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1291 Box::new(MOVDemuxer::new(br))
1292 }
1293 fn get_name(&self) -> &'static str { "mov" }
1294}
1295
2736c15a
KS
1296const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1297 0x93, 0x65, 0x5E, 0x00,
1298 0xFF, 0xFF, 0xFF, 0x00,
1299 0xDF, 0xD0, 0xAB, 0x00,
1300 0x00, 0x00, 0x00, 0x00
1301];
1302const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1303 0xFF, 0xFB, 0xFF, 0x00,
1304 0xEF, 0xD9, 0xBB, 0x00,
1305 0xE8, 0xC9, 0xB1, 0x00,
1306 0x93, 0x65, 0x5E, 0x00,
1307 0xFC, 0xDE, 0xE8, 0x00,
1308 0x9D, 0x88, 0x91, 0x00,
1309 0xFF, 0xFF, 0xFF, 0x00,
1310 0xFF, 0xFF, 0xFF, 0x00,
1311 0xFF, 0xFF, 0xFF, 0x00,
1312 0x47, 0x48, 0x37, 0x00,
1313 0x7A, 0x5E, 0x55, 0x00,
1314 0xDF, 0xD0, 0xAB, 0x00,
1315 0xFF, 0xFB, 0xF9, 0x00,
1316 0xE8, 0xCA, 0xC5, 0x00,
1317 0x8A, 0x7C, 0x77, 0x00,
1318 0x00, 0x00, 0x00, 0x00
1319];
1320const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1321 0xFF, 0xFF, 0xFF, 0x00,
1322 0xFF, 0xFF, 0xCC, 0x00,
1323 0xFF, 0xFF, 0x99, 0x00,
1324 0xFF, 0xFF, 0x66, 0x00,
1325 0xFF, 0xFF, 0x33, 0x00,
1326 0xFF, 0xFF, 0x00, 0x00,
1327 0xFF, 0xCC, 0xFF, 0x00,
1328 0xFF, 0xCC, 0xCC, 0x00,
1329 0xFF, 0xCC, 0x99, 0x00,
1330 0xFF, 0xCC, 0x66, 0x00,
1331 0xFF, 0xCC, 0x33, 0x00,
1332 0xFF, 0xCC, 0x00, 0x00,
1333 0xFF, 0x99, 0xFF, 0x00,
1334 0xFF, 0x99, 0xCC, 0x00,
1335 0xFF, 0x99, 0x99, 0x00,
1336 0xFF, 0x99, 0x66, 0x00,
1337 0xFF, 0x99, 0x33, 0x00,
1338 0xFF, 0x99, 0x00, 0x00,
1339 0xFF, 0x66, 0xFF, 0x00,
1340 0xFF, 0x66, 0xCC, 0x00,
1341 0xFF, 0x66, 0x99, 0x00,
1342 0xFF, 0x66, 0x66, 0x00,
1343 0xFF, 0x66, 0x33, 0x00,
1344 0xFF, 0x66, 0x00, 0x00,
1345 0xFF, 0x33, 0xFF, 0x00,
1346 0xFF, 0x33, 0xCC, 0x00,
1347 0xFF, 0x33, 0x99, 0x00,
1348 0xFF, 0x33, 0x66, 0x00,
1349 0xFF, 0x33, 0x33, 0x00,
1350 0xFF, 0x33, 0x00, 0x00,
1351 0xFF, 0x00, 0xFF, 0x00,
1352 0xFF, 0x00, 0xCC, 0x00,
1353 0xFF, 0x00, 0x99, 0x00,
1354 0xFF, 0x00, 0x66, 0x00,
1355 0xFF, 0x00, 0x33, 0x00,
1356 0xFF, 0x00, 0x00, 0x00,
1357 0xCC, 0xFF, 0xFF, 0x00,
1358 0xCC, 0xFF, 0xCC, 0x00,
1359 0xCC, 0xFF, 0x99, 0x00,
1360 0xCC, 0xFF, 0x66, 0x00,
1361 0xCC, 0xFF, 0x33, 0x00,
1362 0xCC, 0xFF, 0x00, 0x00,
1363 0xCC, 0xCC, 0xFF, 0x00,
1364 0xCC, 0xCC, 0xCC, 0x00,
1365 0xCC, 0xCC, 0x99, 0x00,
1366 0xCC, 0xCC, 0x66, 0x00,
1367 0xCC, 0xCC, 0x33, 0x00,
1368 0xCC, 0xCC, 0x00, 0x00,
1369 0xCC, 0x99, 0xFF, 0x00,
1370 0xCC, 0x99, 0xCC, 0x00,
1371 0xCC, 0x99, 0x99, 0x00,
1372 0xCC, 0x99, 0x66, 0x00,
1373 0xCC, 0x99, 0x33, 0x00,
1374 0xCC, 0x99, 0x00, 0x00,
1375 0xCC, 0x66, 0xFF, 0x00,
1376 0xCC, 0x66, 0xCC, 0x00,
1377 0xCC, 0x66, 0x99, 0x00,
1378 0xCC, 0x66, 0x66, 0x00,
1379 0xCC, 0x66, 0x33, 0x00,
1380 0xCC, 0x66, 0x00, 0x00,
1381 0xCC, 0x33, 0xFF, 0x00,
1382 0xCC, 0x33, 0xCC, 0x00,
1383 0xCC, 0x33, 0x99, 0x00,
1384 0xCC, 0x33, 0x66, 0x00,
1385 0xCC, 0x33, 0x33, 0x00,
1386 0xCC, 0x33, 0x00, 0x00,
1387 0xCC, 0x00, 0xFF, 0x00,
1388 0xCC, 0x00, 0xCC, 0x00,
1389 0xCC, 0x00, 0x99, 0x00,
1390 0xCC, 0x00, 0x66, 0x00,
1391 0xCC, 0x00, 0x33, 0x00,
1392 0xCC, 0x00, 0x00, 0x00,
1393 0x99, 0xFF, 0xFF, 0x00,
1394 0x99, 0xFF, 0xCC, 0x00,
1395 0x99, 0xFF, 0x99, 0x00,
1396 0x99, 0xFF, 0x66, 0x00,
1397 0x99, 0xFF, 0x33, 0x00,
1398 0x99, 0xFF, 0x00, 0x00,
1399 0x99, 0xCC, 0xFF, 0x00,
1400 0x99, 0xCC, 0xCC, 0x00,
1401 0x99, 0xCC, 0x99, 0x00,
1402 0x99, 0xCC, 0x66, 0x00,
1403 0x99, 0xCC, 0x33, 0x00,
1404 0x99, 0xCC, 0x00, 0x00,
1405 0x99, 0x99, 0xFF, 0x00,
1406 0x99, 0x99, 0xCC, 0x00,
1407 0x99, 0x99, 0x99, 0x00,
1408 0x99, 0x99, 0x66, 0x00,
1409 0x99, 0x99, 0x33, 0x00,
1410 0x99, 0x99, 0x00, 0x00,
1411 0x99, 0x66, 0xFF, 0x00,
1412 0x99, 0x66, 0xCC, 0x00,
1413 0x99, 0x66, 0x99, 0x00,
1414 0x99, 0x66, 0x66, 0x00,
1415 0x99, 0x66, 0x33, 0x00,
1416 0x99, 0x66, 0x00, 0x00,
1417 0x99, 0x33, 0xFF, 0x00,
1418 0x99, 0x33, 0xCC, 0x00,
1419 0x99, 0x33, 0x99, 0x00,
1420 0x99, 0x33, 0x66, 0x00,
1421 0x99, 0x33, 0x33, 0x00,
1422 0x99, 0x33, 0x00, 0x00,
1423 0x99, 0x00, 0xFF, 0x00,
1424 0x99, 0x00, 0xCC, 0x00,
1425 0x99, 0x00, 0x99, 0x00,
1426 0x99, 0x00, 0x66, 0x00,
1427 0x99, 0x00, 0x33, 0x00,
1428 0x99, 0x00, 0x00, 0x00,
1429 0x66, 0xFF, 0xFF, 0x00,
1430 0x66, 0xFF, 0xCC, 0x00,
1431 0x66, 0xFF, 0x99, 0x00,
1432 0x66, 0xFF, 0x66, 0x00,
1433 0x66, 0xFF, 0x33, 0x00,
1434 0x66, 0xFF, 0x00, 0x00,
1435 0x66, 0xCC, 0xFF, 0x00,
1436 0x66, 0xCC, 0xCC, 0x00,
1437 0x66, 0xCC, 0x99, 0x00,
1438 0x66, 0xCC, 0x66, 0x00,
1439 0x66, 0xCC, 0x33, 0x00,
1440 0x66, 0xCC, 0x00, 0x00,
1441 0x66, 0x99, 0xFF, 0x00,
1442 0x66, 0x99, 0xCC, 0x00,
1443 0x66, 0x99, 0x99, 0x00,
1444 0x66, 0x99, 0x66, 0x00,
1445 0x66, 0x99, 0x33, 0x00,
1446 0x66, 0x99, 0x00, 0x00,
1447 0x66, 0x66, 0xFF, 0x00,
1448 0x66, 0x66, 0xCC, 0x00,
1449 0x66, 0x66, 0x99, 0x00,
1450 0x66, 0x66, 0x66, 0x00,
1451 0x66, 0x66, 0x33, 0x00,
1452 0x66, 0x66, 0x00, 0x00,
1453 0x66, 0x33, 0xFF, 0x00,
1454 0x66, 0x33, 0xCC, 0x00,
1455 0x66, 0x33, 0x99, 0x00,
1456 0x66, 0x33, 0x66, 0x00,
1457 0x66, 0x33, 0x33, 0x00,
1458 0x66, 0x33, 0x00, 0x00,
1459 0x66, 0x00, 0xFF, 0x00,
1460 0x66, 0x00, 0xCC, 0x00,
1461 0x66, 0x00, 0x99, 0x00,
1462 0x66, 0x00, 0x66, 0x00,
1463 0x66, 0x00, 0x33, 0x00,
1464 0x66, 0x00, 0x00, 0x00,
1465 0x33, 0xFF, 0xFF, 0x00,
1466 0x33, 0xFF, 0xCC, 0x00,
1467 0x33, 0xFF, 0x99, 0x00,
1468 0x33, 0xFF, 0x66, 0x00,
1469 0x33, 0xFF, 0x33, 0x00,
1470 0x33, 0xFF, 0x00, 0x00,
1471 0x33, 0xCC, 0xFF, 0x00,
1472 0x33, 0xCC, 0xCC, 0x00,
1473 0x33, 0xCC, 0x99, 0x00,
1474 0x33, 0xCC, 0x66, 0x00,
1475 0x33, 0xCC, 0x33, 0x00,
1476 0x33, 0xCC, 0x00, 0x00,
1477 0x33, 0x99, 0xFF, 0x00,
1478 0x33, 0x99, 0xCC, 0x00,
1479 0x33, 0x99, 0x99, 0x00,
1480 0x33, 0x99, 0x66, 0x00,
1481 0x33, 0x99, 0x33, 0x00,
1482 0x33, 0x99, 0x00, 0x00,
1483 0x33, 0x66, 0xFF, 0x00,
1484 0x33, 0x66, 0xCC, 0x00,
1485 0x33, 0x66, 0x99, 0x00,
1486 0x33, 0x66, 0x66, 0x00,
1487 0x33, 0x66, 0x33, 0x00,
1488 0x33, 0x66, 0x00, 0x00,
1489 0x33, 0x33, 0xFF, 0x00,
1490 0x33, 0x33, 0xCC, 0x00,
1491 0x33, 0x33, 0x99, 0x00,
1492 0x33, 0x33, 0x66, 0x00,
1493 0x33, 0x33, 0x33, 0x00,
1494 0x33, 0x33, 0x00, 0x00,
1495 0x33, 0x00, 0xFF, 0x00,
1496 0x33, 0x00, 0xCC, 0x00,
1497 0x33, 0x00, 0x99, 0x00,
1498 0x33, 0x00, 0x66, 0x00,
1499 0x33, 0x00, 0x33, 0x00,
1500 0x33, 0x00, 0x00, 0x00,
1501 0x00, 0xFF, 0xFF, 0x00,
1502 0x00, 0xFF, 0xCC, 0x00,
1503 0x00, 0xFF, 0x99, 0x00,
1504 0x00, 0xFF, 0x66, 0x00,
1505 0x00, 0xFF, 0x33, 0x00,
1506 0x00, 0xFF, 0x00, 0x00,
1507 0x00, 0xCC, 0xFF, 0x00,
1508 0x00, 0xCC, 0xCC, 0x00,
1509 0x00, 0xCC, 0x99, 0x00,
1510 0x00, 0xCC, 0x66, 0x00,
1511 0x00, 0xCC, 0x33, 0x00,
1512 0x00, 0xCC, 0x00, 0x00,
1513 0x00, 0x99, 0xFF, 0x00,
1514 0x00, 0x99, 0xCC, 0x00,
1515 0x00, 0x99, 0x99, 0x00,
1516 0x00, 0x99, 0x66, 0x00,
1517 0x00, 0x99, 0x33, 0x00,
1518 0x00, 0x99, 0x00, 0x00,
1519 0x00, 0x66, 0xFF, 0x00,
1520 0x00, 0x66, 0xCC, 0x00,
1521 0x00, 0x66, 0x99, 0x00,
1522 0x00, 0x66, 0x66, 0x00,
1523 0x00, 0x66, 0x33, 0x00,
1524 0x00, 0x66, 0x00, 0x00,
1525 0x00, 0x33, 0xFF, 0x00,
1526 0x00, 0x33, 0xCC, 0x00,
1527 0x00, 0x33, 0x99, 0x00,
1528 0x00, 0x33, 0x66, 0x00,
1529 0x00, 0x33, 0x33, 0x00,
1530 0x00, 0x33, 0x00, 0x00,
1531 0x00, 0x00, 0xFF, 0x00,
1532 0x00, 0x00, 0xCC, 0x00,
1533 0x00, 0x00, 0x99, 0x00,
1534 0x00, 0x00, 0x66, 0x00,
1535 0x00, 0x00, 0x33, 0x00,
1536 0xEE, 0x00, 0x00, 0x00,
1537 0xDD, 0x00, 0x00, 0x00,
1538 0xBB, 0x00, 0x00, 0x00,
1539 0xAA, 0x00, 0x00, 0x00,
1540 0x88, 0x00, 0x00, 0x00,
1541 0x77, 0x00, 0x00, 0x00,
1542 0x55, 0x00, 0x00, 0x00,
1543 0x44, 0x00, 0x00, 0x00,
1544 0x22, 0x00, 0x00, 0x00,
1545 0x11, 0x00, 0x00, 0x00,
1546 0x00, 0xEE, 0x00, 0x00,
1547 0x00, 0xDD, 0x00, 0x00,
1548 0x00, 0xBB, 0x00, 0x00,
1549 0x00, 0xAA, 0x00, 0x00,
1550 0x00, 0x88, 0x00, 0x00,
1551 0x00, 0x77, 0x00, 0x00,
1552 0x00, 0x55, 0x00, 0x00,
1553 0x00, 0x44, 0x00, 0x00,
1554 0x00, 0x22, 0x00, 0x00,
1555 0x00, 0x11, 0x00, 0x00,
1556 0x00, 0x00, 0xEE, 0x00,
1557 0x00, 0x00, 0xDD, 0x00,
1558 0x00, 0x00, 0xBB, 0x00,
1559 0x00, 0x00, 0xAA, 0x00,
1560 0x00, 0x00, 0x88, 0x00,
1561 0x00, 0x00, 0x77, 0x00,
1562 0x00, 0x00, 0x55, 0x00,
1563 0x00, 0x00, 0x44, 0x00,
1564 0x00, 0x00, 0x22, 0x00,
1565 0x00, 0x00, 0x11, 0x00,
1566 0xEE, 0xEE, 0xEE, 0x00,
1567 0xDD, 0xDD, 0xDD, 0x00,
1568 0xBB, 0xBB, 0xBB, 0x00,
1569 0xAA, 0xAA, 0xAA, 0x00,
1570 0x88, 0x88, 0x88, 0x00,
1571 0x77, 0x77, 0x77, 0x00,
1572 0x55, 0x55, 0x55, 0x00,
1573 0x44, 0x44, 0x44, 0x00,
1574 0x22, 0x22, 0x22, 0x00,
1575 0x11, 0x11, 0x11, 0x00,
1576 0x00, 0x00, 0x00, 0x00
1577];
1578
58309c73
KS
1579#[cfg(test)]
1580mod test {
1581 use super::*;
1582 use std::fs::File;
1583
1584 #[test]
1585 fn test_mov_demux() {
1586 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1587 let mut fr = FileReader::new_read(&mut file);
1588 let mut br = ByteReader::new(&mut fr);
1589 let mut dmx = MOVDemuxer::new(&mut br);
1590 let mut sm = StreamManager::new();
1591 let mut si = SeekIndex::new();
1592 dmx.open(&mut sm, &mut si).unwrap();
1593
1594 loop {
1595 let pktres = dmx.get_frame(&mut sm);
1596 if let Err(e) = pktres {
1597 if e == DemuxerError::EOF { break; }
1598 panic!("error");
1599 }
1600 let pkt = pktres.unwrap();
1601 println!("Got {}", pkt);
1602 }
1603 }
1604}