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