mov: mark segments start as seeking points
[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()?;
692 let nchannels = br.read_u16be()?;
693 validate!(nchannels <= 64);
694 let sample_size = br.read_u16be()?;
695 validate!(sample_size <= 128);
696 let _compr_id = br.read_u16be()?;
697 let packet_size = br.read_u16be()? as usize;
698 validate!(packet_size == 0);
699 let sample_rate = br.read_u32be()?;
7afec34d 700 validate!(sample_rate > (1 << 16));
58309c73
KS
701 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
702 name
703 } 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]))) {
704 name
705 } else {
706 "unknown"
707 };
e5d3fef5
KS
708 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
709 if &fcc == b"raw " && sample_size == 8 {
710 soniton.signed = false;
711 }
58309c73 712 let block_align = 1;
89b16ac8 713 if sver == 1 {
b0e12d42 714 let samples_per_packet = br.read_u32be()?;
89b16ac8 715 let _bytes_per_packet = br.read_u32be()?;
9efec4ed 716 let bytes_per_frame = br.read_u32be()?;
89b16ac8 717 let _bytes_per_sample = br.read_u32be()?;
9efec4ed 718 track.bsize = bytes_per_frame as usize;
b0e12d42 719 track.frame_samples = samples_per_packet as usize;
7afec34d 720 track.tb_num = samples_per_packet;
9efec4ed 721 } else {
7afec34d 722 track.bsize = (sample_size / 8) as usize;
89b16ac8 723 }
7afec34d
KS
724 track.tb_den = sample_rate >> 16;
725 track.raw_audio = match &fcc {
726 b"NONE" | b"raw " | b"twos" | b"sowt" |
727 b"in24" | b"in32" | b"fl32" | b"fl64" |
728 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
729 b"alaw" | b"ulaw" |
730 b"MAC3" | b"MAC6" => true,
731 _ => false,
732 };
58309c73 733 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
89b16ac8 734 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
735 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
736 track.channels = nchannels as usize;
737 track.bits = sample_size as usize;
738 },
739 StreamType::None => {
740 return Err(DemuxerError::InvalidData);
741 },
742 _ => {
743//todo put it all into extradata
744 let edata = None;
745 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
746 },
747 };
748 let read_size = br.tell() - start_pos;
749 validate!(read_size <= size);
7afec34d 750 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
751 track.stsd_found = true;
752 Ok(read_size)
753}
754
bbbf86dd 755fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
d4809976 756 validate!(size >= 8);
bbbf86dd
KS
757 let start_pos = br.tell();
758 let version = br.read_byte()?;
759 validate!(version == 0);
760 let _flags = br.read_u24be()?;
761 let entries = br.read_u32be()? as usize;
762 validate!(entries as u64 <= (size - 8) / 8);
d4809976
KS
763 if entries == 0 {
764 } else if entries == 1 {
bbbf86dd
KS
765 let _count = br.read_u32be()?;
766 let tb_num = br.read_u32be()?;
4e7deeda 767 validate!(tb_num != 0);
0a0456a8 768 track.rescale(tb_num);
bbbf86dd
KS
769 } else {
770 track.time_to_sample.truncate(0);
771 track.time_to_sample.reserve(entries);
772 for _ in 0..entries {
773 let count = br.read_u32be()?;
774 let mult = br.read_u32be()?;
775 track.time_to_sample.push((count, mult));
776 }
777 }
778 let read_size = br.tell() - start_pos;
779 validate!(read_size <= size);
780 Ok(read_size)
781}
782
58309c73
KS
783fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
784 let version = br.read_byte()?;
785 validate!(version == 0);
786 let _flags = br.read_u24be()?;
787 let entries = br.read_u32be()? as usize;
788 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
789 validate!((entries * 4 + 8) as u64 == size);
790 track.keyframes = Vec::with_capacity(entries);
791 let mut last_sample_no = 0;
792 for _ in 0..entries {
793 let sample_no = br.read_u32be()?;
794 validate!(sample_no > last_sample_no);
795 track.keyframes.push(sample_no);
796 last_sample_no = sample_no;
797 }
798 Ok(size)
799}
800
801fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
802 let version = br.read_byte()?;
803 validate!(version == 0);
804 let _flags = br.read_u24be()?;
805 let entries = br.read_u32be()? as usize;
806 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
807 validate!((entries * 12 + 8) as u64 == size);
808 track.sample_map = Vec::with_capacity(entries);
809 let mut last_sample_no = 0;
810 for _i in 0..entries {
811 let sample_no = br.read_u32be()?;
812 validate!(sample_no > last_sample_no);
813 let nsamples = br.read_u32be()?;
814 let _sample_desc = br.read_u32be()?;
815 track.sample_map.push((sample_no, nsamples));
816 last_sample_no = sample_no;
817 }
818 Ok(size)
819}
820
821fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
822 let version = br.read_byte()?;
823 validate!(version == 0);
824 let _flags = br.read_u24be()?;
825 let sample_size = br.read_u32be()?;
826 if sample_size != 0 {
827 track.sample_size = sample_size;
9efec4ed
KS
828 if track.sample_size != 1 || track.bsize == 0 {
829 track.bsize = sample_size as usize;
830 }
58309c73
KS
831 Ok(8)
832 } else {
833 let entries = br.read_u32be()? as usize;
834 validate!((entries * 4 + 12) as u64 == size);
835 track.chunk_sizes = Vec::with_capacity(entries);
836 for _ in 0..entries {
837 let sample_size = br.read_u32be()?;
838 track.chunk_sizes.push(sample_size);
839 }
840 Ok(size)
841 }
842}
843
844fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
845 let version = br.read_byte()?;
846 validate!(version == 0);
847 let _flags = br.read_u24be()?;
848 let entries = br.read_u32be()? as usize;
849 validate!((entries * 4 + 8) as u64 == size);
850 track.chunk_offsets = Vec::with_capacity(entries);
851 for _i in 0..entries {
852 let sample_offset = br.read_u32be()?;
853 track.chunk_offsets.push(u64::from(sample_offset));
854 }
855 Ok(size)
856}
857
4e7deeda
KS
858fn read_ctts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
859 validate!(size >= 8);
860 let version = br.read_byte()?;
861 let _flags = br.read_u24be()?;
862 if version > 1 {
863 return Err(DemuxerError::NotImplemented);
864 }
865 let entries = br.read_u32be()? as usize;
866 track.ctts_version = version;
867 track.ctts_map.resize(entries);
868 match version {
869 0 | 1 => {
870 validate!(size == (entries as u64) * 8 + 8);
871 for _ in 0..entries {
872 let samp_count = br.read_u32be()?;
873 let samp_offset = br.read_u32be()?;
874 track.ctts_map.add(samp_count, samp_offset / track.tb_div);
875 }
876 },
877 _ => unreachable!(),
878 };
879 track.ctts_map.reset();
880
881 Ok(size)
882}
883
0a0456a8
KS
884const TRAF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
885 TrackChunkHandler { ctype: mktag!(b"tfhd"), parse: read_tfhd },
886 TrackChunkHandler { ctype: mktag!(b"trun"), parse: read_trun },
887 TrackChunkHandler { ctype: mktag!(b"sbgp"), parse: skip_chunk },
888 TrackChunkHandler { ctype: mktag!(b"sgpd"), parse: skip_chunk },
889 TrackChunkHandler { ctype: mktag!(b"subs"), parse: skip_chunk },
890 TrackChunkHandler { ctype: mktag!(b"saiz"), parse: skip_chunk },
891 TrackChunkHandler { ctype: mktag!(b"saio"), parse: skip_chunk },
892 TrackChunkHandler { ctype: mktag!(b"tfdt"), parse: skip_chunk },
893 TrackChunkHandler { ctype: mktag!(b"meta"), parse: skip_chunk },
894];
895
896fn read_tfhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
897 validate!(size >= 8);
898 let start = br.tell();
899 let _version = br.read_byte()?;
900 let flags = br.read_u24be()?;
901 let _track_id = br.read_u32be()?;
902 if (flags & 0x000001) != 0 {
903 let base_offset = br.read_u64be()?;
904 track.moof_off = base_offset;
905 }
906 if (flags & 0x000002) != 0 {
907 let _sample_description_index = br.read_u32be()?;
908 }
909 if (flags & 0x000008) != 0 {
910 let default_sample_duration = br.read_u32be()?;
911 if track.tb_div == 1 {
912 track.rescale(default_sample_duration);
913 }
914 }
915 if (flags & 0x000010) != 0 {
916 let _default_sample_size = br.read_u32be()?;
917 }
918 if (flags & 0x000020) != 0 {
919 let _default_sample_flags = br.read_u32be()?;
920 }
921 if (flags & 0x010000) != 0 {
922 }
923 /*if (flags & 0x020000) != 0 { // base offset is moof start
924 }*/
925 Ok(br.tell() - start)
926}
927
928fn read_trun(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
929 validate!(size >= 8);
930 let version = br.read_byte()?;
931 let flags = br.read_u24be()?;
932 let data_off_present = (flags & 0x000001) != 0;
933 let first_sample_flags = (flags & 0x000004) != 0;
934 let sample_duration_present = (flags & 0x000100) != 0;
935 let sample_size_present = (flags & 0x000200) != 0;
936 let sample_flags_present = (flags & 0x000400) != 0;
937 let sample_ct_off_present = (flags & 0x000800) != 0;
938
939 let sample_count = br.read_u32be()? as usize;
940
941 let mut hdr_size = 8;
942 let mut arr_size = 0;
943 if data_off_present {
944 hdr_size += 4;
945 }
946 if first_sample_flags {
947 hdr_size += 4;
948 }
949 if sample_duration_present {
950 arr_size += 4;
951 }
952 if sample_size_present {
953 arr_size += 4;
954 }
955 if sample_flags_present {
956 arr_size += 4;
957 }
958 if sample_ct_off_present {
959 arr_size += 4;
960 }
961 validate!(size == hdr_size + arr_size * (sample_count as u64));
962
963 let mut data_off = if data_off_present {
964 let off = br.read_u32be()? as i32;
965 let new_off = (track.moof_off as i64) + i64::from(off);
966 validate!(new_off > 0);
967 new_off as u64
968 } else {
969 track.moof_off
970 };
971 if first_sample_flags {
972 let _flags = br.read_u32be()?;
973 }
974
975 if sample_size_present {
976 track.chunk_sizes.reserve(sample_count);
977 track.chunk_offsets.reserve(sample_count);
978 }
979
980 if sample_ct_off_present {
981 if track.ctts_version != version {
982 track.ctts_version = version;
983 }
984 track.ctts_map.reserve(sample_count);
985 }
986
6bb26927
KS
987 if track.chunk_offsets.len() < (std::u32::MAX as usize) {
988 track.keyframes.push((track.chunk_offsets.len() + 1) as u32);
989 }
0a0456a8
KS
990 for _ in 0..sample_count {
991 if sample_duration_present {
992 let _duration = br.read_u32be()?;
993 }
994 if sample_size_present {
995 let ssize = br.read_u32be()?;
996 track.chunk_sizes.push(ssize);
997 track.chunk_offsets.push(data_off);
998 data_off += u64::from(ssize);
999 }
1000 if sample_flags_present {
1001 let _flags = br.read_u32be()?;
1002 }
1003 if sample_ct_off_present {
1004 let samp_offset = br.read_u32be()?;
1005 if version == 0 {
1006 track.ctts_map.add(1, samp_offset / track.tb_div);
1007 } else {
1008 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1009 }
1010 }
1011 }
1012
1013 Ok(size)
1014}
1015
58309c73
KS
1016struct MOVDemuxer<'a> {
1017 src: &'a mut ByteReader<'a>,
1018 depth: usize,
1019 mdat_pos: u64,
1020 mdat_size: u64,
1021 tracks: Vec<Track>,
1022 cur_track: usize,
1023 tb_den: u32,
1024 duration: u32,
58cd51fa 1025 pal: Option<Arc<[u8; 1024]>>,
650d7bfb 1026
0a0456a8
KS
1027 moof_off: u64,
1028
650d7bfb 1029 print_chunks: bool,
58309c73
KS
1030}
1031
1032struct Track {
1033 track_id: u32,
1034 track_str_id: usize,
1035 track_no: u32,
bbbf86dd 1036 tb_num: u32,
58309c73 1037 tb_den: u32,
4e7deeda 1038 tb_div: u32,
7afec34d
KS
1039 raw_audio: bool,
1040 raw_apos: u64,
a480a0de 1041 duration: u32,
58309c73
KS
1042 depth: u8,
1043 tkhd_found: bool,
1044 stsd_found: bool,
1045 stream_type: StreamType,
1046 width: usize,
1047 height: usize,
1048 channels: usize,
1049 bits: usize,
9efec4ed 1050 bsize: usize,
58309c73
KS
1051 fcc: [u8; 4],
1052 keyframes: Vec<u32>,
1053 chunk_sizes: Vec<u32>,
1054 chunk_offsets: Vec<u64>,
bbbf86dd 1055 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
1056 sample_map: Vec<(u32, u32)>,
1057 sample_size: u32,
b0e12d42 1058 frame_samples: usize,
4e7deeda
KS
1059 ctts_map: RLESearcher<u32>,
1060 ctts_version: u8,
58309c73
KS
1061 stream: Option<NAStream>,
1062 cur_chunk: usize,
1063 cur_sample: usize,
07972bf3 1064 cur_ts: Option<u64>,
58309c73
KS
1065 samples_left: usize,
1066 last_offset: u64,
58cd51fa 1067 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 1068 timesearch: TimeSearcher,
650d7bfb 1069
0a0456a8
KS
1070 moof_off: u64,
1071
650d7bfb 1072 print_chunks: bool,
bbbf86dd
KS
1073}
1074
1075#[derive(Default)]
1076struct TimeSearcher {
1077 idx: usize,
1078 base: u64,
1079 sbase: u32,
1080 cur_len: u32,
1081 cur_mul: u32,
1082}
1083
1084impl TimeSearcher {
1085 fn new() -> Self { Self::default() }
1086 fn reset(&mut self) {
1087 *self = Self::default();
1088 }
b7c882c1 1089 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
bbbf86dd
KS
1090 if tts.is_empty() {
1091 u64::from(sample)
1092 } else if sample >= self.sbase {
1093 let mut sample = sample - self.sbase;
1094 if self.idx == 0 {
1095 let (cur_len, cur_mul) = tts[0];
1096 self.cur_len = cur_len;
1097 self.cur_mul = cur_mul;
1098 self.idx += 1;
1099 }
1100 while self.idx < tts.len() && sample > self.cur_len {
1101 sample -= self.cur_len;
1102 self.sbase += self.cur_len;
1103 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1104 self.cur_len = tts[self.idx].0;
1105 self.cur_mul = tts[self.idx].1;
1106 self.idx += 1;
1107 }
1108 self.base + u64::from(sample) * u64::from(self.cur_mul)
1109 } else {
1110 self.reset();
1111 self.map_time(sample, tts)
1112 }
1113 }
58309c73
KS
1114}
1115
4e7deeda
KS
1116#[derive(Default)]
1117struct RLESearcher<T> {
1118 array: Vec<(u32, T)>,
1119 idx: usize,
1120 start: u64,
1121 next: u64,
1122}
1123
1124impl<T:Default+Copy> RLESearcher<T> {
1125 fn new() -> Self { Self::default() }
1126 fn resize(&mut self, size: usize) {
1127 self.array.truncate(0);
1128 self.array.reserve(size);
1129 }
0a0456a8
KS
1130 fn reserve(&mut self, size: usize) {
1131 self.array.reserve(size);
1132 }
4e7deeda
KS
1133 fn add(&mut self, len: u32, val: T) {
1134 self.array.push((len, val));
1135 }
1136 fn reset(&mut self) {
1137 self.start = 0;
1138 if !self.array.is_empty() {
1139 self.idx = 0;
1140 self.next = u64::from(self.array[0].0);
1141 } else {
1142 self.idx = self.array.len();
1143 self.next = 0;
1144 }
1145 }
1146 fn map(&mut self, sample: u64) -> Option<T> {
1147 if sample < self.start {
1148 self.reset();
1149 }
1150 if self.idx < self.array.len() {
1151 if sample < self.next {
1152 Some(self.array[self.idx].1)
1153 } else {
1154 while (self.idx < self.array.len()) && (sample >= self.next) {
1155 self.start = self.next;
1156 self.idx += 1;
1157 if self.idx < self.array.len() {
1158 self.next += u64::from(self.array[self.idx].0);
1159 }
1160 }
1161 if self.idx < self.array.len() {
1162 Some(self.array[self.idx].1)
1163 } else {
1164 None
1165 }
1166 }
1167 } else {
1168 None
1169 }
1170 }
1171}
1172
58309c73
KS
1173impl Track {
1174 fn new(track_no: u32, tb_den: u32) -> Self {
1175 Self {
1176 tkhd_found: false,
1177 stsd_found: false,
1178 track_id: 0,
1179 track_str_id: 0,
1180 track_no,
bbbf86dd 1181 tb_num: 1,
58309c73 1182 tb_den,
4e7deeda 1183 tb_div: 1,
7afec34d
KS
1184 raw_audio: false,
1185 raw_apos: 0,
a480a0de 1186 duration: 0,
58309c73
KS
1187 stream_type: StreamType::None,
1188 width: 0,
1189 height: 0,
1190 channels: 0,
1191 bits: 0,
9efec4ed 1192 bsize: 0,
58309c73
KS
1193 fcc: [0; 4],
1194 keyframes: Vec::new(),
1195 chunk_sizes: Vec::new(),
1196 chunk_offsets: Vec::new(),
bbbf86dd 1197 time_to_sample: Vec::new(),
58309c73
KS
1198 sample_map: Vec::new(),
1199 sample_size: 0,
b0e12d42 1200 frame_samples: 0,
4e7deeda
KS
1201 ctts_map: RLESearcher::new(),
1202 ctts_version: 0,
58309c73
KS
1203 stream: None,
1204 depth: 0,
1205 cur_chunk: 0,
1206 cur_sample: 0,
07972bf3 1207 cur_ts: None,
58309c73
KS
1208 samples_left: 0,
1209 last_offset: 0,
58cd51fa 1210 pal: None,
bbbf86dd 1211 timesearch: TimeSearcher::new(),
650d7bfb 1212
0a0456a8
KS
1213 moof_off: 0,
1214
650d7bfb 1215 print_chunks: false,
58309c73
KS
1216 }
1217 }
1218 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1219 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1220 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1221 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
0a0456a8
KS
1222 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1223 fn rescale(&mut self, tb_num: u32) {
1224 self.tb_div = tb_num;
1225 if let Some(ref mut stream) = self.stream {
1226 let tb_den = stream.tb_den;
1227 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1228 stream.duration /= u64::from(self.tb_div);
1229 stream.tb_num = tb_num;
1230 stream.tb_den = tb_den;
1231 self.tb_num = tb_num;
1232 self.tb_den = tb_den;
1233 self.duration /= self.tb_div;
1234 }
1235 }
58309c73 1236 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 1237 if !self.keyframes.is_empty() {
58309c73
KS
1238 seek_index.mode = SeekIndexMode::Present;
1239 }
bbbf86dd 1240 let mut tsearch = TimeSearcher::new();
58309c73 1241 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
1242 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1243 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1244 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
1245 }
1246 }
1247 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1248 if nsamp == 0 {
9efec4ed 1249 self.bsize
58309c73
KS
1250 } else {
1251 match &self.fcc {
1252 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1253 (nsamp * self.bits * self.channels + 7) >> 3
1254 },
1255 b"ima4" => {
1256 let nblocks = (nsamp + 63) >> 6;
1257 nblocks * 34 * self.channels
1258 },
1259 b"MAC3" => {
1260 (nsamp + 5) / 6 * 2 * self.channels
1261 },
1262 b"MAC6" => {
1263 (nsamp + 5) / 6 * self.channels
1264 },
1265 b"in24" => nsamp * 3 * self.channels,
1266 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1267 b"fl64" => nsamp * 8 * self.channels,
1268 b"ulaw" | b"alaw" => nsamp,
1269 b"ms\x00\x02" => { //MS ADPCM
1270 ((nsamp - 1) / 2 + 7) * self.channels
1271 },
1272 b"ms\x00\x21" => { //IMA ADPCM
1273 (nsamp / 2 + 4) * self.channels
1274 },
9efec4ed 1275 _ => self.bsize,
58309c73
KS
1276 }
1277 }
1278 }
1279 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 1280 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
4e7deeda
KS
1281 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1282 let dts = match self.ctts_version {
1283 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1284 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1285 _ => unimplemented!(),
1286 };
1287 if (dts as i64) < 0 {
1288 None
1289 } else {
1290 Some(dts)
1291 }
1292 } else {
1293 None
1294 };
1295 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
58309c73
KS
1296 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1297 if self.cur_sample >= self.chunk_sizes.len() {
1298 return None;
1299 }
1300 let offset = self.chunk_offsets[self.cur_sample];
1301 let size = self.chunk_sizes[self.cur_sample] as usize;
1302 self.cur_sample += 1;
1303 Some((pts, offset, size))
1304 } else {
1305 if self.samples_left == 0 {
1306 if self.cur_chunk >= self.chunk_offsets.len() {
1307 return None;
1308 }
1309 for (idx, samples) in self.sample_map.iter() {
1310 if *idx as usize <= self.cur_chunk + 1 {
1311 self.samples_left = *samples as usize;
1312 } else {
1313 break;
1314 }
1315 }
1316 self.last_offset = self.chunk_offsets[self.cur_chunk];
1317 self.cur_chunk += 1;
1318 }
1319 let offset = self.last_offset;
1320 let size = self.get_size(self.cur_sample);
1321 self.last_offset += size as u64;
1322 if self.stream_type == StreamType::Video {
1323 self.samples_left -= 1;
d940f0c2
KS
1324 } else if self.frame_samples != 0 && self.bsize != 0 {
1325 let nblocks = size / self.bsize;
7afec34d
KS
1326 if self.raw_audio {
1327 pts.pts = Some(self.raw_apos);
1328 pts.duration = Some(nblocks as u64);
1329 self.raw_apos += nblocks as u64;
1330 }
d940f0c2
KS
1331 if nblocks > 0 {
1332 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1333 self.samples_left -= consumed;
1334 } else {
1335 self.samples_left = 0;
1336 }
7afec34d
KS
1337 } else if !self.raw_audio {
1338 self.samples_left -= 1;
58309c73 1339 } else {
7afec34d
KS
1340 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1341 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1342 let cur_size = self.calculate_chunk_size(self.samples_left);
1343 let add_off = (size - cur_size) as u64;
1344 let dsize = cur_size.min(max_size);
1345 if self.samples_left >= BLOCK_SAMPLES {
1346 self.cur_sample += BLOCK_SAMPLES;
1347 self.samples_left -= BLOCK_SAMPLES;
1348 self.last_offset -= size as u64;
1349 } else {
1350 self.cur_sample += self.samples_left;
1351 self.samples_left = 0;
1352 }
1353 return Some((pts, offset + add_off, dsize));
58309c73
KS
1354 }
1355 self.cur_sample += 1;
1356 Some((pts, offset, size))
1357 }
1358 }
1359 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1360 if !self.chunk_sizes.is_empty() {
58309c73 1361 self.chunk_sizes[sample_no] as usize
61cab15b 1362 } else if !self.sample_map.is_empty() {
58309c73
KS
1363 let mut nsamp = 0;
1364 for (idx, samples) in self.sample_map.iter() {
1365 if *idx as usize <= self.cur_chunk {
1366 nsamp = *samples;
1367 } else {
1368 break;
1369 }
1370 }
1371 self.calculate_chunk_size(nsamp as usize)
1372 } else {
9efec4ed 1373 self.bsize
58309c73
KS
1374 }
1375 }
b7c882c1 1376 #[allow(clippy::collapsible_if)]
7afec34d 1377 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
58309c73
KS
1378 self.cur_sample = pts as usize;
1379 self.samples_left = 0;
07972bf3 1380 self.cur_ts = None;
58309c73 1381 if self.stream_type == StreamType::Audio {
7afec34d
KS
1382 if let NATimePoint::Milliseconds(ms) = tpoint {
1383 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1384 if self.raw_audio {
1385 if self.frame_samples != 0 {
1386 self.raw_apos = exp_pts / (self.frame_samples as u64);
1387 let mut apos = 0;
1388 self.cur_sample = 0;
1389 self.cur_chunk = 0;
1390 let mut cmap = self.sample_map.iter();
1391 let mut cur_samps = 0;
1392 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1393 loop {
1394 if self.cur_chunk + 1 == next_idx as usize {
1395 self.samples_left = cur_samps;
1396 cur_samps = next_samples as usize;
1397 if let Some((new_idx, new_samples)) = cmap.next() {
1398 next_idx = *new_idx;
1399 next_samples = *new_samples;
1400 }
1401 }
1402 self.raw_apos = apos;
1403 apos += (cur_samps / self.frame_samples) as u64;
1404 if apos > exp_pts {
1405 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1406 if self.cur_chunk >= self.chunk_offsets.len() {
1407 return Err(DemuxerError::SeekError);
1408 }
1409 self.last_offset = self.chunk_offsets[self.cur_chunk];
1410 break;
1411 }
1412 }
1413 self.cur_chunk += 1;
1414 }
1415 self.samples_left = cur_samps;
1416 self.cur_chunk += 1;
1417 } else {
1418 self.raw_apos = exp_pts;
1419 self.cur_sample = exp_pts as usize;
1420 let mut csamp = 0;
1421 self.cur_chunk = 0;
1422 let mut cmap = self.sample_map.iter();
1423 let mut cur_samps = 0;
1424 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1425 loop {
1426 if self.cur_chunk + 1 == next_idx as usize {
1427 self.samples_left = cur_samps;
1428 cur_samps = next_samples as usize;
1429 if let Some((new_idx, new_samples)) = cmap.next() {
1430 next_idx = *new_idx;
1431 next_samples = *new_samples;
1432 }
1433 }
1434 csamp += cur_samps;
1435 if csamp > self.cur_sample {
1436 if self.cur_chunk >= self.chunk_offsets.len() {
1437 return Err(DemuxerError::SeekError);
1438 }
1439 self.last_offset = self.chunk_offsets[self.cur_chunk];
1440 break;
1441 }
1442 self.cur_chunk += 1;
1443 }
1444 self.samples_left = csamp - self.cur_sample;
1445 self.cur_chunk += 1;
1446 }
5317ee9c 1447 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
7afec34d 1448 self.cur_chunk = self.cur_sample;
5317ee9c
KS
1449 } else {
1450 let mut csamp = 0;
1451 self.cur_chunk = 0;
1452 let mut cmap = self.sample_map.iter();
1453 let mut cur_samps = 0;
1454 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1455 loop {
1456 if self.cur_chunk + 1 == next_idx as usize {
1457 self.samples_left = cur_samps;
1458 cur_samps = next_samples as usize;
1459 if let Some((new_idx, new_samples)) = cmap.next() {
1460 next_idx = *new_idx;
1461 next_samples = *new_samples;
1462 }
1463 }
1464 csamp += cur_samps;
1465 if csamp > self.cur_sample {
1466 if self.cur_chunk >= self.chunk_offsets.len() {
1467 return Err(DemuxerError::SeekError);
1468 }
1469 self.last_offset = self.chunk_offsets[self.cur_chunk];
1470 break;
1471 }
1472 self.cur_chunk += 1;
1473 }
1474 self.cur_sample = csamp - cur_samps;
1475 self.samples_left = cur_samps;
1476 self.last_offset = self.chunk_offsets[self.cur_chunk];
1477 self.cur_chunk += 1;
7afec34d
KS
1478 }
1479 } else {
1480 self.cur_chunk = self.cur_sample;
1481 }
61cab15b 1482 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1483 let mut csamp = 0;
1484 self.cur_chunk = 0;
1485 let mut cmap = self.sample_map.iter();
1486 let mut cur_samps = 0;
1487 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1488 loop {
bbbf86dd 1489 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1490 self.samples_left = cur_samps;
1491 cur_samps = next_samples as usize;
1492 if let Some((new_idx, new_samples)) = cmap.next() {
1493 next_idx = *new_idx;
1494 next_samples = *new_samples;
1495 }
1496 }
1497 csamp += cur_samps;
1498 if csamp >= self.cur_sample {
7afec34d
KS
1499 if self.cur_chunk >= self.chunk_offsets.len() {
1500 return Err(DemuxerError::SeekError);
1501 }
58309c73
KS
1502 self.last_offset = self.chunk_offsets[self.cur_chunk];
1503 break;
1504 }
1505 self.cur_chunk += 1;
1506 }
1507 csamp -= cur_samps;
bbbf86dd 1508 for sample_no in csamp..self.cur_sample {
58309c73
KS
1509 self.last_offset += self.get_size(sample_no) as u64;
1510 }
bbbf86dd
KS
1511 self.samples_left = csamp + cur_samps - self.cur_sample;
1512 self.cur_chunk += 1;
58309c73 1513 }
7afec34d 1514 Ok(())
58309c73
KS
1515 }
1516}
1517
07972bf3
KS
1518fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1519 if let Some(cpts) = pts.get_pts() {
1520 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1521 track.cur_ts = Some(ts);
1522 } else {
1523 track.cur_ts = None;
1524 }
1525 let str = strmgr.get_stream(track.track_str_id);
1526 if str.is_none() { return Err(DemuxerError::InvalidData); }
1527 let stream = str.unwrap();
1528 src.seek(SeekFrom::Start(offset))?;
1529 let mut pkt = src.read_packet(stream, pts, false, size)?;
1530 if let Some(ref pal) = track.pal {
1531 let side_data = NASideData::Palette(first, pal.clone());
1532 pkt.add_side_data(side_data);
1533 }
1534 Ok(pkt)
1535}
1536
58309c73
KS
1537impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1538 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1539 self.read_root(strmgr)?;
1540 validate!(self.mdat_pos > 0);
61cab15b 1541 validate!(!self.tracks.is_empty());
0a0456a8
KS
1542 for track in self.tracks.iter_mut() {
1543 let mut str = None;
1544 std::mem::swap(&mut track.stream, &mut str);
1545 if let Some(stream) = str {
1546 let str_id = strmgr.add_stream(stream).unwrap();
1547 track.track_str_id = str_id;
1548 }
1549 }
58309c73
KS
1550 for track in self.tracks.iter() {
1551 track.fill_seek_index(seek_index);
1552 }
1553 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1554 self.cur_track = 0;
1555 Ok(())
1556 }
1557
1558 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1559 if self.tracks.is_empty() {
58309c73
KS
1560 return Err(DemuxerError::EOF);
1561 }
07972bf3
KS
1562 let mut has_all_time = true;
1563 let mut min_ts = std::u64::MAX;
1564 for trk in self.tracks.iter() {
1565 if let Some(ts) = trk.cur_ts {
1566 min_ts = min_ts.min(ts);
1567 } else {
1568 has_all_time = false;
1569 break;
1570 }
1571 }
1572 if has_all_time {
1573 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1574 if let Some(ts) = track.cur_ts {
1575 if ts == min_ts {
1576 let first = track.cur_sample == 0;
1577 if let Some((pts, offset, size)) = track.get_next_chunk() {
1578 self.cur_track = trk_no + 1;
1579 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1580 }
1581 }
1582 }
1583 }
1584 }
1585
58309c73
KS
1586 for _ in 0..self.tracks.len() {
1587 if self.cur_track >= self.tracks.len() {
1588 self.cur_track = 0;
1589 }
1590 let track = &mut self.tracks[self.cur_track];
1591 self.cur_track += 1;
58cd51fa 1592 let first = track.cur_sample == 0;
58309c73 1593 if let Some((pts, offset, size)) = track.get_next_chunk() {
07972bf3 1594 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
58309c73
KS
1595 }
1596 }
61cab15b 1597 Err(DemuxerError::EOF)
58309c73
KS
1598 }
1599
24d99894 1600 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1601 let ret = seek_index.find_pos(time);
1602 if ret.is_none() {
5317ee9c
KS
1603 if let NATimePoint::Milliseconds(_) = time {
1604 let mut aonly = true;
1605 for track in self.tracks.iter() {
1606 if track.stream_type != StreamType::Audio || !track.raw_audio {
1607 aonly = false;
1608 break;
1609 }
1610 }
1611 if aonly {
1612 for track in self.tracks.iter_mut() {
1613 track.seek(0, time)?;
1614 }
1615 return Ok(());
1616 }
1617 }
58309c73
KS
1618 return Err(DemuxerError::SeekError);
1619 }
1620 let seek_info = ret.unwrap();
5317ee9c
KS
1621 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1622 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
58309c73 1623 for track in self.tracks.iter_mut() {
5317ee9c
KS
1624 let cur_pts = if track.track_id == seek_info.str_id {
1625 seek_info.pts
1626 } else {
1627 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1628 };
1629 track.seek(cur_pts, time)?;
58309c73
KS
1630 }
1631 Ok(())
1632 }
a480a0de
KS
1633 fn get_duration(&self) -> u64 {
1634 if self.tb_den != 0 {
1635 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1636 } else {
1637 0
1638 }
1639 }
58309c73
KS
1640}
1641
650d7bfb
KS
1642const PRINT_CHUNKS: &str = "print_chunks";
1643
1644const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1645 NAOptionDefinition {
1646 name: PRINT_CHUNKS,
1647 description: "Print parsed file structure",
1648 opt_type: NAOptionDefinitionType::Bool },
1649];
1650
787b8d03 1651impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb 1652 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
b7c882c1 1653 #[allow(clippy::single_match)]
650d7bfb
KS
1654 fn set_options(&mut self, options: &[NAOption]) {
1655 for option in options.iter() {
1656 for opt_def in DEMUXER_OPTIONS.iter() {
1657 if opt_def.check(option).is_ok() {
1658 match (option.name, &option.value) {
1659 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1660 self.print_chunks = *val;
1661 },
1662 _ => {},
1663 }
1664 }
1665 }
1666 }
1667 }
1668 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1669 match name {
1670 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1671 _ => None,
1672 }
1673 }
787b8d03
KS
1674}
1675
58309c73
KS
1676impl<'a> MOVDemuxer<'a> {
1677 fn new(io: &'a mut ByteReader<'a>) -> Self {
1678 MOVDemuxer {
1679 src: io,
1680 depth: 0,
1681 mdat_pos: 0,
1682 mdat_size: 0,
1683 tracks: Vec::with_capacity(2),
1684 cur_track: 0,
1685 tb_den: 0,
1686 duration: 0,
58cd51fa 1687 pal: None,
650d7bfb 1688
0a0456a8
KS
1689 moof_off: 0,
1690
650d7bfb 1691 print_chunks: false,
58309c73
KS
1692 }
1693 }
1694 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1695 self.depth = 0;
1696 while self.src.left() != 0 {
1697 let ret = read_chunk_header(&mut self.src);
1698 if ret.is_err() { break; }
1699 let (ctype, size) = ret.unwrap();
0a0456a8
KS
1700 if self.print_chunks {
1701 print_cname(ctype, size, self.src.tell(), 0);
1702 }
58309c73
KS
1703 if IGNORED_CHUNKS.contains(&ctype) {
1704 self.src.skip64(size)?;
1705 continue;
1706 }
1707 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1708 let read_size;
1709 if let Some(ref handler) = handler {
1710 read_size = (handler.parse)(self, strmgr, size)?;
1711 } else {
1712 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1713 read_size = 0;
1714 }
1715 validate!(read_size <= size);
1716 self.src.skip64(size - read_size)?;
1717 }
1718//todo check if all needed chunks are found
1719 Ok(())
1720 }
1721 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
0a0456a8 1722 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
58309c73
KS
1723}
1724
1725pub struct MOVDemuxerCreator { }
1726
1727impl DemuxerCreator for MOVDemuxerCreator {
1728 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1729 Box::new(MOVDemuxer::new(br))
1730 }
1731 fn get_name(&self) -> &'static str { "mov" }
1732}
1733
2736c15a
KS
1734const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1735 0x93, 0x65, 0x5E, 0x00,
1736 0xFF, 0xFF, 0xFF, 0x00,
1737 0xDF, 0xD0, 0xAB, 0x00,
1738 0x00, 0x00, 0x00, 0x00
1739];
1740const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1741 0xFF, 0xFB, 0xFF, 0x00,
1742 0xEF, 0xD9, 0xBB, 0x00,
1743 0xE8, 0xC9, 0xB1, 0x00,
1744 0x93, 0x65, 0x5E, 0x00,
1745 0xFC, 0xDE, 0xE8, 0x00,
1746 0x9D, 0x88, 0x91, 0x00,
1747 0xFF, 0xFF, 0xFF, 0x00,
1748 0xFF, 0xFF, 0xFF, 0x00,
1749 0xFF, 0xFF, 0xFF, 0x00,
1750 0x47, 0x48, 0x37, 0x00,
1751 0x7A, 0x5E, 0x55, 0x00,
1752 0xDF, 0xD0, 0xAB, 0x00,
1753 0xFF, 0xFB, 0xF9, 0x00,
1754 0xE8, 0xCA, 0xC5, 0x00,
1755 0x8A, 0x7C, 0x77, 0x00,
1756 0x00, 0x00, 0x00, 0x00
1757];
1758const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1759 0xFF, 0xFF, 0xFF, 0x00,
1760 0xFF, 0xFF, 0xCC, 0x00,
1761 0xFF, 0xFF, 0x99, 0x00,
1762 0xFF, 0xFF, 0x66, 0x00,
1763 0xFF, 0xFF, 0x33, 0x00,
1764 0xFF, 0xFF, 0x00, 0x00,
1765 0xFF, 0xCC, 0xFF, 0x00,
1766 0xFF, 0xCC, 0xCC, 0x00,
1767 0xFF, 0xCC, 0x99, 0x00,
1768 0xFF, 0xCC, 0x66, 0x00,
1769 0xFF, 0xCC, 0x33, 0x00,
1770 0xFF, 0xCC, 0x00, 0x00,
1771 0xFF, 0x99, 0xFF, 0x00,
1772 0xFF, 0x99, 0xCC, 0x00,
1773 0xFF, 0x99, 0x99, 0x00,
1774 0xFF, 0x99, 0x66, 0x00,
1775 0xFF, 0x99, 0x33, 0x00,
1776 0xFF, 0x99, 0x00, 0x00,
1777 0xFF, 0x66, 0xFF, 0x00,
1778 0xFF, 0x66, 0xCC, 0x00,
1779 0xFF, 0x66, 0x99, 0x00,
1780 0xFF, 0x66, 0x66, 0x00,
1781 0xFF, 0x66, 0x33, 0x00,
1782 0xFF, 0x66, 0x00, 0x00,
1783 0xFF, 0x33, 0xFF, 0x00,
1784 0xFF, 0x33, 0xCC, 0x00,
1785 0xFF, 0x33, 0x99, 0x00,
1786 0xFF, 0x33, 0x66, 0x00,
1787 0xFF, 0x33, 0x33, 0x00,
1788 0xFF, 0x33, 0x00, 0x00,
1789 0xFF, 0x00, 0xFF, 0x00,
1790 0xFF, 0x00, 0xCC, 0x00,
1791 0xFF, 0x00, 0x99, 0x00,
1792 0xFF, 0x00, 0x66, 0x00,
1793 0xFF, 0x00, 0x33, 0x00,
1794 0xFF, 0x00, 0x00, 0x00,
1795 0xCC, 0xFF, 0xFF, 0x00,
1796 0xCC, 0xFF, 0xCC, 0x00,
1797 0xCC, 0xFF, 0x99, 0x00,
1798 0xCC, 0xFF, 0x66, 0x00,
1799 0xCC, 0xFF, 0x33, 0x00,
1800 0xCC, 0xFF, 0x00, 0x00,
1801 0xCC, 0xCC, 0xFF, 0x00,
1802 0xCC, 0xCC, 0xCC, 0x00,
1803 0xCC, 0xCC, 0x99, 0x00,
1804 0xCC, 0xCC, 0x66, 0x00,
1805 0xCC, 0xCC, 0x33, 0x00,
1806 0xCC, 0xCC, 0x00, 0x00,
1807 0xCC, 0x99, 0xFF, 0x00,
1808 0xCC, 0x99, 0xCC, 0x00,
1809 0xCC, 0x99, 0x99, 0x00,
1810 0xCC, 0x99, 0x66, 0x00,
1811 0xCC, 0x99, 0x33, 0x00,
1812 0xCC, 0x99, 0x00, 0x00,
1813 0xCC, 0x66, 0xFF, 0x00,
1814 0xCC, 0x66, 0xCC, 0x00,
1815 0xCC, 0x66, 0x99, 0x00,
1816 0xCC, 0x66, 0x66, 0x00,
1817 0xCC, 0x66, 0x33, 0x00,
1818 0xCC, 0x66, 0x00, 0x00,
1819 0xCC, 0x33, 0xFF, 0x00,
1820 0xCC, 0x33, 0xCC, 0x00,
1821 0xCC, 0x33, 0x99, 0x00,
1822 0xCC, 0x33, 0x66, 0x00,
1823 0xCC, 0x33, 0x33, 0x00,
1824 0xCC, 0x33, 0x00, 0x00,
1825 0xCC, 0x00, 0xFF, 0x00,
1826 0xCC, 0x00, 0xCC, 0x00,
1827 0xCC, 0x00, 0x99, 0x00,
1828 0xCC, 0x00, 0x66, 0x00,
1829 0xCC, 0x00, 0x33, 0x00,
1830 0xCC, 0x00, 0x00, 0x00,
1831 0x99, 0xFF, 0xFF, 0x00,
1832 0x99, 0xFF, 0xCC, 0x00,
1833 0x99, 0xFF, 0x99, 0x00,
1834 0x99, 0xFF, 0x66, 0x00,
1835 0x99, 0xFF, 0x33, 0x00,
1836 0x99, 0xFF, 0x00, 0x00,
1837 0x99, 0xCC, 0xFF, 0x00,
1838 0x99, 0xCC, 0xCC, 0x00,
1839 0x99, 0xCC, 0x99, 0x00,
1840 0x99, 0xCC, 0x66, 0x00,
1841 0x99, 0xCC, 0x33, 0x00,
1842 0x99, 0xCC, 0x00, 0x00,
1843 0x99, 0x99, 0xFF, 0x00,
1844 0x99, 0x99, 0xCC, 0x00,
1845 0x99, 0x99, 0x99, 0x00,
1846 0x99, 0x99, 0x66, 0x00,
1847 0x99, 0x99, 0x33, 0x00,
1848 0x99, 0x99, 0x00, 0x00,
1849 0x99, 0x66, 0xFF, 0x00,
1850 0x99, 0x66, 0xCC, 0x00,
1851 0x99, 0x66, 0x99, 0x00,
1852 0x99, 0x66, 0x66, 0x00,
1853 0x99, 0x66, 0x33, 0x00,
1854 0x99, 0x66, 0x00, 0x00,
1855 0x99, 0x33, 0xFF, 0x00,
1856 0x99, 0x33, 0xCC, 0x00,
1857 0x99, 0x33, 0x99, 0x00,
1858 0x99, 0x33, 0x66, 0x00,
1859 0x99, 0x33, 0x33, 0x00,
1860 0x99, 0x33, 0x00, 0x00,
1861 0x99, 0x00, 0xFF, 0x00,
1862 0x99, 0x00, 0xCC, 0x00,
1863 0x99, 0x00, 0x99, 0x00,
1864 0x99, 0x00, 0x66, 0x00,
1865 0x99, 0x00, 0x33, 0x00,
1866 0x99, 0x00, 0x00, 0x00,
1867 0x66, 0xFF, 0xFF, 0x00,
1868 0x66, 0xFF, 0xCC, 0x00,
1869 0x66, 0xFF, 0x99, 0x00,
1870 0x66, 0xFF, 0x66, 0x00,
1871 0x66, 0xFF, 0x33, 0x00,
1872 0x66, 0xFF, 0x00, 0x00,
1873 0x66, 0xCC, 0xFF, 0x00,
1874 0x66, 0xCC, 0xCC, 0x00,
1875 0x66, 0xCC, 0x99, 0x00,
1876 0x66, 0xCC, 0x66, 0x00,
1877 0x66, 0xCC, 0x33, 0x00,
1878 0x66, 0xCC, 0x00, 0x00,
1879 0x66, 0x99, 0xFF, 0x00,
1880 0x66, 0x99, 0xCC, 0x00,
1881 0x66, 0x99, 0x99, 0x00,
1882 0x66, 0x99, 0x66, 0x00,
1883 0x66, 0x99, 0x33, 0x00,
1884 0x66, 0x99, 0x00, 0x00,
1885 0x66, 0x66, 0xFF, 0x00,
1886 0x66, 0x66, 0xCC, 0x00,
1887 0x66, 0x66, 0x99, 0x00,
1888 0x66, 0x66, 0x66, 0x00,
1889 0x66, 0x66, 0x33, 0x00,
1890 0x66, 0x66, 0x00, 0x00,
1891 0x66, 0x33, 0xFF, 0x00,
1892 0x66, 0x33, 0xCC, 0x00,
1893 0x66, 0x33, 0x99, 0x00,
1894 0x66, 0x33, 0x66, 0x00,
1895 0x66, 0x33, 0x33, 0x00,
1896 0x66, 0x33, 0x00, 0x00,
1897 0x66, 0x00, 0xFF, 0x00,
1898 0x66, 0x00, 0xCC, 0x00,
1899 0x66, 0x00, 0x99, 0x00,
1900 0x66, 0x00, 0x66, 0x00,
1901 0x66, 0x00, 0x33, 0x00,
1902 0x66, 0x00, 0x00, 0x00,
1903 0x33, 0xFF, 0xFF, 0x00,
1904 0x33, 0xFF, 0xCC, 0x00,
1905 0x33, 0xFF, 0x99, 0x00,
1906 0x33, 0xFF, 0x66, 0x00,
1907 0x33, 0xFF, 0x33, 0x00,
1908 0x33, 0xFF, 0x00, 0x00,
1909 0x33, 0xCC, 0xFF, 0x00,
1910 0x33, 0xCC, 0xCC, 0x00,
1911 0x33, 0xCC, 0x99, 0x00,
1912 0x33, 0xCC, 0x66, 0x00,
1913 0x33, 0xCC, 0x33, 0x00,
1914 0x33, 0xCC, 0x00, 0x00,
1915 0x33, 0x99, 0xFF, 0x00,
1916 0x33, 0x99, 0xCC, 0x00,
1917 0x33, 0x99, 0x99, 0x00,
1918 0x33, 0x99, 0x66, 0x00,
1919 0x33, 0x99, 0x33, 0x00,
1920 0x33, 0x99, 0x00, 0x00,
1921 0x33, 0x66, 0xFF, 0x00,
1922 0x33, 0x66, 0xCC, 0x00,
1923 0x33, 0x66, 0x99, 0x00,
1924 0x33, 0x66, 0x66, 0x00,
1925 0x33, 0x66, 0x33, 0x00,
1926 0x33, 0x66, 0x00, 0x00,
1927 0x33, 0x33, 0xFF, 0x00,
1928 0x33, 0x33, 0xCC, 0x00,
1929 0x33, 0x33, 0x99, 0x00,
1930 0x33, 0x33, 0x66, 0x00,
1931 0x33, 0x33, 0x33, 0x00,
1932 0x33, 0x33, 0x00, 0x00,
1933 0x33, 0x00, 0xFF, 0x00,
1934 0x33, 0x00, 0xCC, 0x00,
1935 0x33, 0x00, 0x99, 0x00,
1936 0x33, 0x00, 0x66, 0x00,
1937 0x33, 0x00, 0x33, 0x00,
1938 0x33, 0x00, 0x00, 0x00,
1939 0x00, 0xFF, 0xFF, 0x00,
1940 0x00, 0xFF, 0xCC, 0x00,
1941 0x00, 0xFF, 0x99, 0x00,
1942 0x00, 0xFF, 0x66, 0x00,
1943 0x00, 0xFF, 0x33, 0x00,
1944 0x00, 0xFF, 0x00, 0x00,
1945 0x00, 0xCC, 0xFF, 0x00,
1946 0x00, 0xCC, 0xCC, 0x00,
1947 0x00, 0xCC, 0x99, 0x00,
1948 0x00, 0xCC, 0x66, 0x00,
1949 0x00, 0xCC, 0x33, 0x00,
1950 0x00, 0xCC, 0x00, 0x00,
1951 0x00, 0x99, 0xFF, 0x00,
1952 0x00, 0x99, 0xCC, 0x00,
1953 0x00, 0x99, 0x99, 0x00,
1954 0x00, 0x99, 0x66, 0x00,
1955 0x00, 0x99, 0x33, 0x00,
1956 0x00, 0x99, 0x00, 0x00,
1957 0x00, 0x66, 0xFF, 0x00,
1958 0x00, 0x66, 0xCC, 0x00,
1959 0x00, 0x66, 0x99, 0x00,
1960 0x00, 0x66, 0x66, 0x00,
1961 0x00, 0x66, 0x33, 0x00,
1962 0x00, 0x66, 0x00, 0x00,
1963 0x00, 0x33, 0xFF, 0x00,
1964 0x00, 0x33, 0xCC, 0x00,
1965 0x00, 0x33, 0x99, 0x00,
1966 0x00, 0x33, 0x66, 0x00,
1967 0x00, 0x33, 0x33, 0x00,
1968 0x00, 0x33, 0x00, 0x00,
1969 0x00, 0x00, 0xFF, 0x00,
1970 0x00, 0x00, 0xCC, 0x00,
1971 0x00, 0x00, 0x99, 0x00,
1972 0x00, 0x00, 0x66, 0x00,
1973 0x00, 0x00, 0x33, 0x00,
1974 0xEE, 0x00, 0x00, 0x00,
1975 0xDD, 0x00, 0x00, 0x00,
1976 0xBB, 0x00, 0x00, 0x00,
1977 0xAA, 0x00, 0x00, 0x00,
1978 0x88, 0x00, 0x00, 0x00,
1979 0x77, 0x00, 0x00, 0x00,
1980 0x55, 0x00, 0x00, 0x00,
1981 0x44, 0x00, 0x00, 0x00,
1982 0x22, 0x00, 0x00, 0x00,
1983 0x11, 0x00, 0x00, 0x00,
1984 0x00, 0xEE, 0x00, 0x00,
1985 0x00, 0xDD, 0x00, 0x00,
1986 0x00, 0xBB, 0x00, 0x00,
1987 0x00, 0xAA, 0x00, 0x00,
1988 0x00, 0x88, 0x00, 0x00,
1989 0x00, 0x77, 0x00, 0x00,
1990 0x00, 0x55, 0x00, 0x00,
1991 0x00, 0x44, 0x00, 0x00,
1992 0x00, 0x22, 0x00, 0x00,
1993 0x00, 0x11, 0x00, 0x00,
1994 0x00, 0x00, 0xEE, 0x00,
1995 0x00, 0x00, 0xDD, 0x00,
1996 0x00, 0x00, 0xBB, 0x00,
1997 0x00, 0x00, 0xAA, 0x00,
1998 0x00, 0x00, 0x88, 0x00,
1999 0x00, 0x00, 0x77, 0x00,
2000 0x00, 0x00, 0x55, 0x00,
2001 0x00, 0x00, 0x44, 0x00,
2002 0x00, 0x00, 0x22, 0x00,
2003 0x00, 0x00, 0x11, 0x00,
2004 0xEE, 0xEE, 0xEE, 0x00,
2005 0xDD, 0xDD, 0xDD, 0x00,
2006 0xBB, 0xBB, 0xBB, 0x00,
2007 0xAA, 0xAA, 0xAA, 0x00,
2008 0x88, 0x88, 0x88, 0x00,
2009 0x77, 0x77, 0x77, 0x00,
2010 0x55, 0x55, 0x55, 0x00,
2011 0x44, 0x44, 0x44, 0x00,
2012 0x22, 0x22, 0x22, 0x00,
2013 0x11, 0x11, 0x11, 0x00,
2014 0x00, 0x00, 0x00, 0x00
2015];
2016
58309c73
KS
2017#[cfg(test)]
2018mod test {
2019 use super::*;
2020 use std::fs::File;
2021
2022 #[test]
2023 fn test_mov_demux() {
2024 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2025 let mut fr = FileReader::new_read(&mut file);
2026 let mut br = ByteReader::new(&mut fr);
2027 let mut dmx = MOVDemuxer::new(&mut br);
2028 let mut sm = StreamManager::new();
2029 let mut si = SeekIndex::new();
2030 dmx.open(&mut sm, &mut si).unwrap();
2031
2032 loop {
2033 let pktres = dmx.get_frame(&mut sm);
2034 if let Err(e) = pktres {
2035 if e == DemuxerError::EOF { break; }
2036 panic!("error");
2037 }
2038 let pkt = pktres.unwrap();
2039 println!("Got {}", pkt);
2040 }
2041 }
0a0456a8
KS
2042
2043 #[test]
2044 fn test_dash_demux() {
2045 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2046 let mut fr = FileReader::new_read(&mut file);
2047 let mut br = ByteReader::new(&mut fr);
2048 let mut dmx = MOVDemuxer::new(&mut br);
2049 let mut sm = StreamManager::new();
2050 let mut si = SeekIndex::new();
2051 dmx.open(&mut sm, &mut si).unwrap();
2052
2053 loop {
2054 let pktres = dmx.get_frame(&mut sm);
2055 if let Err(e) = pktres {
2056 if e == DemuxerError::EOF { break; }
2057 panic!("error");
2058 }
2059 let pkt = pktres.unwrap();
2060 println!("Got {}", pkt);
2061 }
2062 }
58309c73 2063}