mov: serve packets with equal timestamps if possible
[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
987 for _ in 0..sample_count {
988 if sample_duration_present {
989 let _duration = br.read_u32be()?;
990 }
991 if sample_size_present {
992 let ssize = br.read_u32be()?;
993 track.chunk_sizes.push(ssize);
994 track.chunk_offsets.push(data_off);
995 data_off += u64::from(ssize);
996 }
997 if sample_flags_present {
998 let _flags = br.read_u32be()?;
999 }
1000 if sample_ct_off_present {
1001 let samp_offset = br.read_u32be()?;
1002 if version == 0 {
1003 track.ctts_map.add(1, samp_offset / track.tb_div);
1004 } else {
1005 track.ctts_map.add(1, ((samp_offset as i32) / (track.tb_div as i32)) as u32);
1006 }
1007 }
1008 }
1009
1010 Ok(size)
1011}
1012
58309c73
KS
1013struct MOVDemuxer<'a> {
1014 src: &'a mut ByteReader<'a>,
1015 depth: usize,
1016 mdat_pos: u64,
1017 mdat_size: u64,
1018 tracks: Vec<Track>,
1019 cur_track: usize,
1020 tb_den: u32,
1021 duration: u32,
58cd51fa 1022 pal: Option<Arc<[u8; 1024]>>,
650d7bfb 1023
0a0456a8
KS
1024 moof_off: u64,
1025
650d7bfb 1026 print_chunks: bool,
58309c73
KS
1027}
1028
1029struct Track {
1030 track_id: u32,
1031 track_str_id: usize,
1032 track_no: u32,
bbbf86dd 1033 tb_num: u32,
58309c73 1034 tb_den: u32,
4e7deeda 1035 tb_div: u32,
7afec34d
KS
1036 raw_audio: bool,
1037 raw_apos: u64,
a480a0de 1038 duration: u32,
58309c73
KS
1039 depth: u8,
1040 tkhd_found: bool,
1041 stsd_found: bool,
1042 stream_type: StreamType,
1043 width: usize,
1044 height: usize,
1045 channels: usize,
1046 bits: usize,
9efec4ed 1047 bsize: usize,
58309c73
KS
1048 fcc: [u8; 4],
1049 keyframes: Vec<u32>,
1050 chunk_sizes: Vec<u32>,
1051 chunk_offsets: Vec<u64>,
bbbf86dd 1052 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
1053 sample_map: Vec<(u32, u32)>,
1054 sample_size: u32,
b0e12d42 1055 frame_samples: usize,
4e7deeda
KS
1056 ctts_map: RLESearcher<u32>,
1057 ctts_version: u8,
58309c73
KS
1058 stream: Option<NAStream>,
1059 cur_chunk: usize,
1060 cur_sample: usize,
07972bf3 1061 cur_ts: Option<u64>,
58309c73
KS
1062 samples_left: usize,
1063 last_offset: u64,
58cd51fa 1064 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd 1065 timesearch: TimeSearcher,
650d7bfb 1066
0a0456a8
KS
1067 moof_off: u64,
1068
650d7bfb 1069 print_chunks: bool,
bbbf86dd
KS
1070}
1071
1072#[derive(Default)]
1073struct TimeSearcher {
1074 idx: usize,
1075 base: u64,
1076 sbase: u32,
1077 cur_len: u32,
1078 cur_mul: u32,
1079}
1080
1081impl TimeSearcher {
1082 fn new() -> Self { Self::default() }
1083 fn reset(&mut self) {
1084 *self = Self::default();
1085 }
b7c882c1 1086 fn map_time(&mut self, sample: u32, tts: &[(u32, u32)]) -> u64 {
bbbf86dd
KS
1087 if tts.is_empty() {
1088 u64::from(sample)
1089 } else if sample >= self.sbase {
1090 let mut sample = sample - self.sbase;
1091 if self.idx == 0 {
1092 let (cur_len, cur_mul) = tts[0];
1093 self.cur_len = cur_len;
1094 self.cur_mul = cur_mul;
1095 self.idx += 1;
1096 }
1097 while self.idx < tts.len() && sample > self.cur_len {
1098 sample -= self.cur_len;
1099 self.sbase += self.cur_len;
1100 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
1101 self.cur_len = tts[self.idx].0;
1102 self.cur_mul = tts[self.idx].1;
1103 self.idx += 1;
1104 }
1105 self.base + u64::from(sample) * u64::from(self.cur_mul)
1106 } else {
1107 self.reset();
1108 self.map_time(sample, tts)
1109 }
1110 }
58309c73
KS
1111}
1112
4e7deeda
KS
1113#[derive(Default)]
1114struct RLESearcher<T> {
1115 array: Vec<(u32, T)>,
1116 idx: usize,
1117 start: u64,
1118 next: u64,
1119}
1120
1121impl<T:Default+Copy> RLESearcher<T> {
1122 fn new() -> Self { Self::default() }
1123 fn resize(&mut self, size: usize) {
1124 self.array.truncate(0);
1125 self.array.reserve(size);
1126 }
0a0456a8
KS
1127 fn reserve(&mut self, size: usize) {
1128 self.array.reserve(size);
1129 }
4e7deeda
KS
1130 fn add(&mut self, len: u32, val: T) {
1131 self.array.push((len, val));
1132 }
1133 fn reset(&mut self) {
1134 self.start = 0;
1135 if !self.array.is_empty() {
1136 self.idx = 0;
1137 self.next = u64::from(self.array[0].0);
1138 } else {
1139 self.idx = self.array.len();
1140 self.next = 0;
1141 }
1142 }
1143 fn map(&mut self, sample: u64) -> Option<T> {
1144 if sample < self.start {
1145 self.reset();
1146 }
1147 if self.idx < self.array.len() {
1148 if sample < self.next {
1149 Some(self.array[self.idx].1)
1150 } else {
1151 while (self.idx < self.array.len()) && (sample >= self.next) {
1152 self.start = self.next;
1153 self.idx += 1;
1154 if self.idx < self.array.len() {
1155 self.next += u64::from(self.array[self.idx].0);
1156 }
1157 }
1158 if self.idx < self.array.len() {
1159 Some(self.array[self.idx].1)
1160 } else {
1161 None
1162 }
1163 }
1164 } else {
1165 None
1166 }
1167 }
1168}
1169
58309c73
KS
1170impl Track {
1171 fn new(track_no: u32, tb_den: u32) -> Self {
1172 Self {
1173 tkhd_found: false,
1174 stsd_found: false,
1175 track_id: 0,
1176 track_str_id: 0,
1177 track_no,
bbbf86dd 1178 tb_num: 1,
58309c73 1179 tb_den,
4e7deeda 1180 tb_div: 1,
7afec34d
KS
1181 raw_audio: false,
1182 raw_apos: 0,
a480a0de 1183 duration: 0,
58309c73
KS
1184 stream_type: StreamType::None,
1185 width: 0,
1186 height: 0,
1187 channels: 0,
1188 bits: 0,
9efec4ed 1189 bsize: 0,
58309c73
KS
1190 fcc: [0; 4],
1191 keyframes: Vec::new(),
1192 chunk_sizes: Vec::new(),
1193 chunk_offsets: Vec::new(),
bbbf86dd 1194 time_to_sample: Vec::new(),
58309c73
KS
1195 sample_map: Vec::new(),
1196 sample_size: 0,
b0e12d42 1197 frame_samples: 0,
4e7deeda
KS
1198 ctts_map: RLESearcher::new(),
1199 ctts_version: 0,
58309c73
KS
1200 stream: None,
1201 depth: 0,
1202 cur_chunk: 0,
1203 cur_sample: 0,
07972bf3 1204 cur_ts: None,
58309c73
KS
1205 samples_left: 0,
1206 last_offset: 0,
58cd51fa 1207 pal: None,
bbbf86dd 1208 timesearch: TimeSearcher::new(),
650d7bfb 1209
0a0456a8
KS
1210 moof_off: 0,
1211
650d7bfb 1212 print_chunks: false,
58309c73
KS
1213 }
1214 }
1215 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
1216 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
1217 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
1218 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
0a0456a8
KS
1219 read_chunk_list!(track; "traf", read_traf, TRAF_CHUNK_HANDLERS);
1220 fn rescale(&mut self, tb_num: u32) {
1221 self.tb_div = tb_num;
1222 if let Some(ref mut stream) = self.stream {
1223 let tb_den = stream.tb_den;
1224 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
1225 stream.duration /= u64::from(self.tb_div);
1226 stream.tb_num = tb_num;
1227 stream.tb_den = tb_den;
1228 self.tb_num = tb_num;
1229 self.tb_den = tb_den;
1230 self.duration /= self.tb_div;
1231 }
1232 }
58309c73 1233 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 1234 if !self.keyframes.is_empty() {
58309c73
KS
1235 seek_index.mode = SeekIndexMode::Present;
1236 }
bbbf86dd 1237 let mut tsearch = TimeSearcher::new();
58309c73 1238 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
1239 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
1240 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
1241 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
1242 }
1243 }
1244 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
1245 if nsamp == 0 {
9efec4ed 1246 self.bsize
58309c73
KS
1247 } else {
1248 match &self.fcc {
1249 b"NONE" | b"raw " | b"twos" | b"sowt" => {
1250 (nsamp * self.bits * self.channels + 7) >> 3
1251 },
1252 b"ima4" => {
1253 let nblocks = (nsamp + 63) >> 6;
1254 nblocks * 34 * self.channels
1255 },
1256 b"MAC3" => {
1257 (nsamp + 5) / 6 * 2 * self.channels
1258 },
1259 b"MAC6" => {
1260 (nsamp + 5) / 6 * self.channels
1261 },
1262 b"in24" => nsamp * 3 * self.channels,
1263 b"in32" | b"fl32" => nsamp * 4 * self.channels,
1264 b"fl64" => nsamp * 8 * self.channels,
1265 b"ulaw" | b"alaw" => nsamp,
1266 b"ms\x00\x02" => { //MS ADPCM
1267 ((nsamp - 1) / 2 + 7) * self.channels
1268 },
1269 b"ms\x00\x21" => { //IMA ADPCM
1270 (nsamp / 2 + 4) * self.channels
1271 },
9efec4ed 1272 _ => self.bsize,
58309c73
KS
1273 }
1274 }
1275 }
1276 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd 1277 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
4e7deeda
KS
1278 let dts = if let Some(dts_corr) = self.ctts_map.map(self.cur_sample as u64) {
1279 let dts = match self.ctts_version {
1280 0 => pts_val.wrapping_add(u64::from(dts_corr)),
1281 1 => pts_val.wrapping_add(i64::from(dts_corr as i32) as u64),
1282 _ => unimplemented!(),
1283 };
1284 if (dts as i64) < 0 {
1285 None
1286 } else {
1287 Some(dts)
1288 }
1289 } else {
1290 None
1291 };
1292 let mut pts = NATimeInfo::new(Some(pts_val), dts, None, self.tb_num, self.tb_den);
58309c73
KS
1293 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
1294 if self.cur_sample >= self.chunk_sizes.len() {
1295 return None;
1296 }
1297 let offset = self.chunk_offsets[self.cur_sample];
1298 let size = self.chunk_sizes[self.cur_sample] as usize;
1299 self.cur_sample += 1;
1300 Some((pts, offset, size))
1301 } else {
1302 if self.samples_left == 0 {
1303 if self.cur_chunk >= self.chunk_offsets.len() {
1304 return None;
1305 }
1306 for (idx, samples) in self.sample_map.iter() {
1307 if *idx as usize <= self.cur_chunk + 1 {
1308 self.samples_left = *samples as usize;
1309 } else {
1310 break;
1311 }
1312 }
1313 self.last_offset = self.chunk_offsets[self.cur_chunk];
1314 self.cur_chunk += 1;
1315 }
1316 let offset = self.last_offset;
1317 let size = self.get_size(self.cur_sample);
1318 self.last_offset += size as u64;
1319 if self.stream_type == StreamType::Video {
1320 self.samples_left -= 1;
d940f0c2
KS
1321 } else if self.frame_samples != 0 && self.bsize != 0 {
1322 let nblocks = size / self.bsize;
7afec34d
KS
1323 if self.raw_audio {
1324 pts.pts = Some(self.raw_apos);
1325 pts.duration = Some(nblocks as u64);
1326 self.raw_apos += nblocks as u64;
1327 }
d940f0c2
KS
1328 if nblocks > 0 {
1329 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
1330 self.samples_left -= consumed;
1331 } else {
1332 self.samples_left = 0;
1333 }
7afec34d
KS
1334 } else if !self.raw_audio {
1335 self.samples_left -= 1;
58309c73 1336 } else {
7afec34d
KS
1337 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
1338 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
1339 let cur_size = self.calculate_chunk_size(self.samples_left);
1340 let add_off = (size - cur_size) as u64;
1341 let dsize = cur_size.min(max_size);
1342 if self.samples_left >= BLOCK_SAMPLES {
1343 self.cur_sample += BLOCK_SAMPLES;
1344 self.samples_left -= BLOCK_SAMPLES;
1345 self.last_offset -= size as u64;
1346 } else {
1347 self.cur_sample += self.samples_left;
1348 self.samples_left = 0;
1349 }
1350 return Some((pts, offset + add_off, dsize));
58309c73
KS
1351 }
1352 self.cur_sample += 1;
1353 Some((pts, offset, size))
1354 }
1355 }
1356 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 1357 if !self.chunk_sizes.is_empty() {
58309c73 1358 self.chunk_sizes[sample_no] as usize
61cab15b 1359 } else if !self.sample_map.is_empty() {
58309c73
KS
1360 let mut nsamp = 0;
1361 for (idx, samples) in self.sample_map.iter() {
1362 if *idx as usize <= self.cur_chunk {
1363 nsamp = *samples;
1364 } else {
1365 break;
1366 }
1367 }
1368 self.calculate_chunk_size(nsamp as usize)
1369 } else {
9efec4ed 1370 self.bsize
58309c73
KS
1371 }
1372 }
b7c882c1 1373 #[allow(clippy::collapsible_if)]
7afec34d 1374 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
58309c73
KS
1375 self.cur_sample = pts as usize;
1376 self.samples_left = 0;
07972bf3 1377 self.cur_ts = None;
58309c73 1378 if self.stream_type == StreamType::Audio {
7afec34d
KS
1379 if let NATimePoint::Milliseconds(ms) = tpoint {
1380 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1381 if self.raw_audio {
1382 if self.frame_samples != 0 {
1383 self.raw_apos = exp_pts / (self.frame_samples as u64);
1384 let mut apos = 0;
1385 self.cur_sample = 0;
1386 self.cur_chunk = 0;
1387 let mut cmap = self.sample_map.iter();
1388 let mut cur_samps = 0;
1389 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1390 loop {
1391 if self.cur_chunk + 1 == next_idx as usize {
1392 self.samples_left = cur_samps;
1393 cur_samps = next_samples as usize;
1394 if let Some((new_idx, new_samples)) = cmap.next() {
1395 next_idx = *new_idx;
1396 next_samples = *new_samples;
1397 }
1398 }
1399 self.raw_apos = apos;
1400 apos += (cur_samps / self.frame_samples) as u64;
1401 if apos > exp_pts {
1402 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1403 if self.cur_chunk >= self.chunk_offsets.len() {
1404 return Err(DemuxerError::SeekError);
1405 }
1406 self.last_offset = self.chunk_offsets[self.cur_chunk];
1407 break;
1408 }
1409 }
1410 self.cur_chunk += 1;
1411 }
1412 self.samples_left = cur_samps;
1413 self.cur_chunk += 1;
1414 } else {
1415 self.raw_apos = exp_pts;
1416 self.cur_sample = exp_pts as usize;
1417 let mut csamp = 0;
1418 self.cur_chunk = 0;
1419 let mut cmap = self.sample_map.iter();
1420 let mut cur_samps = 0;
1421 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1422 loop {
1423 if self.cur_chunk + 1 == next_idx as usize {
1424 self.samples_left = cur_samps;
1425 cur_samps = next_samples as usize;
1426 if let Some((new_idx, new_samples)) = cmap.next() {
1427 next_idx = *new_idx;
1428 next_samples = *new_samples;
1429 }
1430 }
1431 csamp += cur_samps;
1432 if csamp > self.cur_sample {
1433 if self.cur_chunk >= self.chunk_offsets.len() {
1434 return Err(DemuxerError::SeekError);
1435 }
1436 self.last_offset = self.chunk_offsets[self.cur_chunk];
1437 break;
1438 }
1439 self.cur_chunk += 1;
1440 }
1441 self.samples_left = csamp - self.cur_sample;
1442 self.cur_chunk += 1;
1443 }
5317ee9c 1444 } else if self.chunk_offsets.len() == self.chunk_sizes.len() {
7afec34d 1445 self.cur_chunk = self.cur_sample;
5317ee9c
KS
1446 } else {
1447 let mut csamp = 0;
1448 self.cur_chunk = 0;
1449 let mut cmap = self.sample_map.iter();
1450 let mut cur_samps = 0;
1451 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1452 loop {
1453 if self.cur_chunk + 1 == next_idx as usize {
1454 self.samples_left = cur_samps;
1455 cur_samps = next_samples as usize;
1456 if let Some((new_idx, new_samples)) = cmap.next() {
1457 next_idx = *new_idx;
1458 next_samples = *new_samples;
1459 }
1460 }
1461 csamp += cur_samps;
1462 if csamp > self.cur_sample {
1463 if self.cur_chunk >= self.chunk_offsets.len() {
1464 return Err(DemuxerError::SeekError);
1465 }
1466 self.last_offset = self.chunk_offsets[self.cur_chunk];
1467 break;
1468 }
1469 self.cur_chunk += 1;
1470 }
1471 self.cur_sample = csamp - cur_samps;
1472 self.samples_left = cur_samps;
1473 self.last_offset = self.chunk_offsets[self.cur_chunk];
1474 self.cur_chunk += 1;
7afec34d
KS
1475 }
1476 } else {
1477 self.cur_chunk = self.cur_sample;
1478 }
61cab15b 1479 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
1480 let mut csamp = 0;
1481 self.cur_chunk = 0;
1482 let mut cmap = self.sample_map.iter();
1483 let mut cur_samps = 0;
1484 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1485 loop {
bbbf86dd 1486 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
1487 self.samples_left = cur_samps;
1488 cur_samps = next_samples as usize;
1489 if let Some((new_idx, new_samples)) = cmap.next() {
1490 next_idx = *new_idx;
1491 next_samples = *new_samples;
1492 }
1493 }
1494 csamp += cur_samps;
1495 if csamp >= self.cur_sample {
7afec34d
KS
1496 if self.cur_chunk >= self.chunk_offsets.len() {
1497 return Err(DemuxerError::SeekError);
1498 }
58309c73
KS
1499 self.last_offset = self.chunk_offsets[self.cur_chunk];
1500 break;
1501 }
1502 self.cur_chunk += 1;
1503 }
1504 csamp -= cur_samps;
bbbf86dd 1505 for sample_no in csamp..self.cur_sample {
58309c73
KS
1506 self.last_offset += self.get_size(sample_no) as u64;
1507 }
bbbf86dd
KS
1508 self.samples_left = csamp + cur_samps - self.cur_sample;
1509 self.cur_chunk += 1;
58309c73 1510 }
7afec34d 1511 Ok(())
58309c73
KS
1512 }
1513}
1514
07972bf3
KS
1515fn process_packet(src: &mut ByteReader, strmgr: &StreamManager, track: &mut Track, pts: NATimeInfo, offset: u64, size: usize, first: bool) -> DemuxerResult<NAPacket> {
1516 if let Some(cpts) = pts.get_pts() {
1517 let ts = NATimeInfo::ts_to_time(cpts, 1000, pts.tb_num, pts.tb_den);
1518 track.cur_ts = Some(ts);
1519 } else {
1520 track.cur_ts = None;
1521 }
1522 let str = strmgr.get_stream(track.track_str_id);
1523 if str.is_none() { return Err(DemuxerError::InvalidData); }
1524 let stream = str.unwrap();
1525 src.seek(SeekFrom::Start(offset))?;
1526 let mut pkt = src.read_packet(stream, pts, false, size)?;
1527 if let Some(ref pal) = track.pal {
1528 let side_data = NASideData::Palette(first, pal.clone());
1529 pkt.add_side_data(side_data);
1530 }
1531 Ok(pkt)
1532}
1533
58309c73
KS
1534impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1535 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1536 self.read_root(strmgr)?;
1537 validate!(self.mdat_pos > 0);
61cab15b 1538 validate!(!self.tracks.is_empty());
0a0456a8
KS
1539 for track in self.tracks.iter_mut() {
1540 let mut str = None;
1541 std::mem::swap(&mut track.stream, &mut str);
1542 if let Some(stream) = str {
1543 let str_id = strmgr.add_stream(stream).unwrap();
1544 track.track_str_id = str_id;
1545 }
1546 }
58309c73
KS
1547 for track in self.tracks.iter() {
1548 track.fill_seek_index(seek_index);
1549 }
1550 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1551 self.cur_track = 0;
1552 Ok(())
1553 }
1554
1555 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1556 if self.tracks.is_empty() {
58309c73
KS
1557 return Err(DemuxerError::EOF);
1558 }
07972bf3
KS
1559 let mut has_all_time = true;
1560 let mut min_ts = std::u64::MAX;
1561 for trk in self.tracks.iter() {
1562 if let Some(ts) = trk.cur_ts {
1563 min_ts = min_ts.min(ts);
1564 } else {
1565 has_all_time = false;
1566 break;
1567 }
1568 }
1569 if has_all_time {
1570 for (trk_no, track) in self.tracks.iter_mut().enumerate() {
1571 if let Some(ts) = track.cur_ts {
1572 if ts == min_ts {
1573 let first = track.cur_sample == 0;
1574 if let Some((pts, offset, size)) = track.get_next_chunk() {
1575 self.cur_track = trk_no + 1;
1576 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
1577 }
1578 }
1579 }
1580 }
1581 }
1582
58309c73
KS
1583 for _ in 0..self.tracks.len() {
1584 if self.cur_track >= self.tracks.len() {
1585 self.cur_track = 0;
1586 }
1587 let track = &mut self.tracks[self.cur_track];
1588 self.cur_track += 1;
58cd51fa 1589 let first = track.cur_sample == 0;
58309c73 1590 if let Some((pts, offset, size)) = track.get_next_chunk() {
07972bf3 1591 return process_packet(&mut self.src, strmgr, track, pts, offset, size, first);
58309c73
KS
1592 }
1593 }
61cab15b 1594 Err(DemuxerError::EOF)
58309c73
KS
1595 }
1596
24d99894 1597 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1598 let ret = seek_index.find_pos(time);
1599 if ret.is_none() {
5317ee9c
KS
1600 if let NATimePoint::Milliseconds(_) = time {
1601 let mut aonly = true;
1602 for track in self.tracks.iter() {
1603 if track.stream_type != StreamType::Audio || !track.raw_audio {
1604 aonly = false;
1605 break;
1606 }
1607 }
1608 if aonly {
1609 for track in self.tracks.iter_mut() {
1610 track.seek(0, time)?;
1611 }
1612 return Ok(());
1613 }
1614 }
58309c73
KS
1615 return Err(DemuxerError::SeekError);
1616 }
1617 let seek_info = ret.unwrap();
5317ee9c
KS
1618 let tbn = self.tracks[seek_info.str_id as usize].tb_num;
1619 let tbd = self.tracks[seek_info.str_id as usize].tb_den;
58309c73 1620 for track in self.tracks.iter_mut() {
5317ee9c
KS
1621 let cur_pts = if track.track_id == seek_info.str_id {
1622 seek_info.pts
1623 } else {
1624 seek_info.pts * u64::from(tbn) * u64::from(track.tb_den) / (u64::from(tbd) * u64::from(track.tb_num))
1625 };
1626 track.seek(cur_pts, time)?;
58309c73
KS
1627 }
1628 Ok(())
1629 }
a480a0de
KS
1630 fn get_duration(&self) -> u64 {
1631 if self.tb_den != 0 {
1632 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1633 } else {
1634 0
1635 }
1636 }
58309c73
KS
1637}
1638
650d7bfb
KS
1639const PRINT_CHUNKS: &str = "print_chunks";
1640
1641const DEMUXER_OPTIONS: &[NAOptionDefinition] = &[
1642 NAOptionDefinition {
1643 name: PRINT_CHUNKS,
1644 description: "Print parsed file structure",
1645 opt_type: NAOptionDefinitionType::Bool },
1646];
1647
787b8d03 1648impl<'a> NAOptionHandler for MOVDemuxer<'a> {
650d7bfb 1649 fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTIONS }
b7c882c1 1650 #[allow(clippy::single_match)]
650d7bfb
KS
1651 fn set_options(&mut self, options: &[NAOption]) {
1652 for option in options.iter() {
1653 for opt_def in DEMUXER_OPTIONS.iter() {
1654 if opt_def.check(option).is_ok() {
1655 match (option.name, &option.value) {
1656 (PRINT_CHUNKS, NAValue::Bool(val)) => {
1657 self.print_chunks = *val;
1658 },
1659 _ => {},
1660 }
1661 }
1662 }
1663 }
1664 }
1665 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1666 match name {
1667 PRINT_CHUNKS => Some(NAValue::Bool(self.print_chunks)),
1668 _ => None,
1669 }
1670 }
787b8d03
KS
1671}
1672
58309c73
KS
1673impl<'a> MOVDemuxer<'a> {
1674 fn new(io: &'a mut ByteReader<'a>) -> Self {
1675 MOVDemuxer {
1676 src: io,
1677 depth: 0,
1678 mdat_pos: 0,
1679 mdat_size: 0,
1680 tracks: Vec::with_capacity(2),
1681 cur_track: 0,
1682 tb_den: 0,
1683 duration: 0,
58cd51fa 1684 pal: None,
650d7bfb 1685
0a0456a8
KS
1686 moof_off: 0,
1687
650d7bfb 1688 print_chunks: false,
58309c73
KS
1689 }
1690 }
1691 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1692 self.depth = 0;
1693 while self.src.left() != 0 {
1694 let ret = read_chunk_header(&mut self.src);
1695 if ret.is_err() { break; }
1696 let (ctype, size) = ret.unwrap();
0a0456a8
KS
1697 if self.print_chunks {
1698 print_cname(ctype, size, self.src.tell(), 0);
1699 }
58309c73
KS
1700 if IGNORED_CHUNKS.contains(&ctype) {
1701 self.src.skip64(size)?;
1702 continue;
1703 }
1704 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1705 let read_size;
1706 if let Some(ref handler) = handler {
1707 read_size = (handler.parse)(self, strmgr, size)?;
1708 } else {
1709 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1710 read_size = 0;
1711 }
1712 validate!(read_size <= size);
1713 self.src.skip64(size - read_size)?;
1714 }
1715//todo check if all needed chunks are found
1716 Ok(())
1717 }
1718 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
0a0456a8 1719 read_chunk_list!(root; "moof", read_moof, MOOF_CHUNK_HANDLERS);
58309c73
KS
1720}
1721
1722pub struct MOVDemuxerCreator { }
1723
1724impl DemuxerCreator for MOVDemuxerCreator {
1725 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1726 Box::new(MOVDemuxer::new(br))
1727 }
1728 fn get_name(&self) -> &'static str { "mov" }
1729}
1730
2736c15a
KS
1731const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1732 0x93, 0x65, 0x5E, 0x00,
1733 0xFF, 0xFF, 0xFF, 0x00,
1734 0xDF, 0xD0, 0xAB, 0x00,
1735 0x00, 0x00, 0x00, 0x00
1736];
1737const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1738 0xFF, 0xFB, 0xFF, 0x00,
1739 0xEF, 0xD9, 0xBB, 0x00,
1740 0xE8, 0xC9, 0xB1, 0x00,
1741 0x93, 0x65, 0x5E, 0x00,
1742 0xFC, 0xDE, 0xE8, 0x00,
1743 0x9D, 0x88, 0x91, 0x00,
1744 0xFF, 0xFF, 0xFF, 0x00,
1745 0xFF, 0xFF, 0xFF, 0x00,
1746 0xFF, 0xFF, 0xFF, 0x00,
1747 0x47, 0x48, 0x37, 0x00,
1748 0x7A, 0x5E, 0x55, 0x00,
1749 0xDF, 0xD0, 0xAB, 0x00,
1750 0xFF, 0xFB, 0xF9, 0x00,
1751 0xE8, 0xCA, 0xC5, 0x00,
1752 0x8A, 0x7C, 0x77, 0x00,
1753 0x00, 0x00, 0x00, 0x00
1754];
1755const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1756 0xFF, 0xFF, 0xFF, 0x00,
1757 0xFF, 0xFF, 0xCC, 0x00,
1758 0xFF, 0xFF, 0x99, 0x00,
1759 0xFF, 0xFF, 0x66, 0x00,
1760 0xFF, 0xFF, 0x33, 0x00,
1761 0xFF, 0xFF, 0x00, 0x00,
1762 0xFF, 0xCC, 0xFF, 0x00,
1763 0xFF, 0xCC, 0xCC, 0x00,
1764 0xFF, 0xCC, 0x99, 0x00,
1765 0xFF, 0xCC, 0x66, 0x00,
1766 0xFF, 0xCC, 0x33, 0x00,
1767 0xFF, 0xCC, 0x00, 0x00,
1768 0xFF, 0x99, 0xFF, 0x00,
1769 0xFF, 0x99, 0xCC, 0x00,
1770 0xFF, 0x99, 0x99, 0x00,
1771 0xFF, 0x99, 0x66, 0x00,
1772 0xFF, 0x99, 0x33, 0x00,
1773 0xFF, 0x99, 0x00, 0x00,
1774 0xFF, 0x66, 0xFF, 0x00,
1775 0xFF, 0x66, 0xCC, 0x00,
1776 0xFF, 0x66, 0x99, 0x00,
1777 0xFF, 0x66, 0x66, 0x00,
1778 0xFF, 0x66, 0x33, 0x00,
1779 0xFF, 0x66, 0x00, 0x00,
1780 0xFF, 0x33, 0xFF, 0x00,
1781 0xFF, 0x33, 0xCC, 0x00,
1782 0xFF, 0x33, 0x99, 0x00,
1783 0xFF, 0x33, 0x66, 0x00,
1784 0xFF, 0x33, 0x33, 0x00,
1785 0xFF, 0x33, 0x00, 0x00,
1786 0xFF, 0x00, 0xFF, 0x00,
1787 0xFF, 0x00, 0xCC, 0x00,
1788 0xFF, 0x00, 0x99, 0x00,
1789 0xFF, 0x00, 0x66, 0x00,
1790 0xFF, 0x00, 0x33, 0x00,
1791 0xFF, 0x00, 0x00, 0x00,
1792 0xCC, 0xFF, 0xFF, 0x00,
1793 0xCC, 0xFF, 0xCC, 0x00,
1794 0xCC, 0xFF, 0x99, 0x00,
1795 0xCC, 0xFF, 0x66, 0x00,
1796 0xCC, 0xFF, 0x33, 0x00,
1797 0xCC, 0xFF, 0x00, 0x00,
1798 0xCC, 0xCC, 0xFF, 0x00,
1799 0xCC, 0xCC, 0xCC, 0x00,
1800 0xCC, 0xCC, 0x99, 0x00,
1801 0xCC, 0xCC, 0x66, 0x00,
1802 0xCC, 0xCC, 0x33, 0x00,
1803 0xCC, 0xCC, 0x00, 0x00,
1804 0xCC, 0x99, 0xFF, 0x00,
1805 0xCC, 0x99, 0xCC, 0x00,
1806 0xCC, 0x99, 0x99, 0x00,
1807 0xCC, 0x99, 0x66, 0x00,
1808 0xCC, 0x99, 0x33, 0x00,
1809 0xCC, 0x99, 0x00, 0x00,
1810 0xCC, 0x66, 0xFF, 0x00,
1811 0xCC, 0x66, 0xCC, 0x00,
1812 0xCC, 0x66, 0x99, 0x00,
1813 0xCC, 0x66, 0x66, 0x00,
1814 0xCC, 0x66, 0x33, 0x00,
1815 0xCC, 0x66, 0x00, 0x00,
1816 0xCC, 0x33, 0xFF, 0x00,
1817 0xCC, 0x33, 0xCC, 0x00,
1818 0xCC, 0x33, 0x99, 0x00,
1819 0xCC, 0x33, 0x66, 0x00,
1820 0xCC, 0x33, 0x33, 0x00,
1821 0xCC, 0x33, 0x00, 0x00,
1822 0xCC, 0x00, 0xFF, 0x00,
1823 0xCC, 0x00, 0xCC, 0x00,
1824 0xCC, 0x00, 0x99, 0x00,
1825 0xCC, 0x00, 0x66, 0x00,
1826 0xCC, 0x00, 0x33, 0x00,
1827 0xCC, 0x00, 0x00, 0x00,
1828 0x99, 0xFF, 0xFF, 0x00,
1829 0x99, 0xFF, 0xCC, 0x00,
1830 0x99, 0xFF, 0x99, 0x00,
1831 0x99, 0xFF, 0x66, 0x00,
1832 0x99, 0xFF, 0x33, 0x00,
1833 0x99, 0xFF, 0x00, 0x00,
1834 0x99, 0xCC, 0xFF, 0x00,
1835 0x99, 0xCC, 0xCC, 0x00,
1836 0x99, 0xCC, 0x99, 0x00,
1837 0x99, 0xCC, 0x66, 0x00,
1838 0x99, 0xCC, 0x33, 0x00,
1839 0x99, 0xCC, 0x00, 0x00,
1840 0x99, 0x99, 0xFF, 0x00,
1841 0x99, 0x99, 0xCC, 0x00,
1842 0x99, 0x99, 0x99, 0x00,
1843 0x99, 0x99, 0x66, 0x00,
1844 0x99, 0x99, 0x33, 0x00,
1845 0x99, 0x99, 0x00, 0x00,
1846 0x99, 0x66, 0xFF, 0x00,
1847 0x99, 0x66, 0xCC, 0x00,
1848 0x99, 0x66, 0x99, 0x00,
1849 0x99, 0x66, 0x66, 0x00,
1850 0x99, 0x66, 0x33, 0x00,
1851 0x99, 0x66, 0x00, 0x00,
1852 0x99, 0x33, 0xFF, 0x00,
1853 0x99, 0x33, 0xCC, 0x00,
1854 0x99, 0x33, 0x99, 0x00,
1855 0x99, 0x33, 0x66, 0x00,
1856 0x99, 0x33, 0x33, 0x00,
1857 0x99, 0x33, 0x00, 0x00,
1858 0x99, 0x00, 0xFF, 0x00,
1859 0x99, 0x00, 0xCC, 0x00,
1860 0x99, 0x00, 0x99, 0x00,
1861 0x99, 0x00, 0x66, 0x00,
1862 0x99, 0x00, 0x33, 0x00,
1863 0x99, 0x00, 0x00, 0x00,
1864 0x66, 0xFF, 0xFF, 0x00,
1865 0x66, 0xFF, 0xCC, 0x00,
1866 0x66, 0xFF, 0x99, 0x00,
1867 0x66, 0xFF, 0x66, 0x00,
1868 0x66, 0xFF, 0x33, 0x00,
1869 0x66, 0xFF, 0x00, 0x00,
1870 0x66, 0xCC, 0xFF, 0x00,
1871 0x66, 0xCC, 0xCC, 0x00,
1872 0x66, 0xCC, 0x99, 0x00,
1873 0x66, 0xCC, 0x66, 0x00,
1874 0x66, 0xCC, 0x33, 0x00,
1875 0x66, 0xCC, 0x00, 0x00,
1876 0x66, 0x99, 0xFF, 0x00,
1877 0x66, 0x99, 0xCC, 0x00,
1878 0x66, 0x99, 0x99, 0x00,
1879 0x66, 0x99, 0x66, 0x00,
1880 0x66, 0x99, 0x33, 0x00,
1881 0x66, 0x99, 0x00, 0x00,
1882 0x66, 0x66, 0xFF, 0x00,
1883 0x66, 0x66, 0xCC, 0x00,
1884 0x66, 0x66, 0x99, 0x00,
1885 0x66, 0x66, 0x66, 0x00,
1886 0x66, 0x66, 0x33, 0x00,
1887 0x66, 0x66, 0x00, 0x00,
1888 0x66, 0x33, 0xFF, 0x00,
1889 0x66, 0x33, 0xCC, 0x00,
1890 0x66, 0x33, 0x99, 0x00,
1891 0x66, 0x33, 0x66, 0x00,
1892 0x66, 0x33, 0x33, 0x00,
1893 0x66, 0x33, 0x00, 0x00,
1894 0x66, 0x00, 0xFF, 0x00,
1895 0x66, 0x00, 0xCC, 0x00,
1896 0x66, 0x00, 0x99, 0x00,
1897 0x66, 0x00, 0x66, 0x00,
1898 0x66, 0x00, 0x33, 0x00,
1899 0x66, 0x00, 0x00, 0x00,
1900 0x33, 0xFF, 0xFF, 0x00,
1901 0x33, 0xFF, 0xCC, 0x00,
1902 0x33, 0xFF, 0x99, 0x00,
1903 0x33, 0xFF, 0x66, 0x00,
1904 0x33, 0xFF, 0x33, 0x00,
1905 0x33, 0xFF, 0x00, 0x00,
1906 0x33, 0xCC, 0xFF, 0x00,
1907 0x33, 0xCC, 0xCC, 0x00,
1908 0x33, 0xCC, 0x99, 0x00,
1909 0x33, 0xCC, 0x66, 0x00,
1910 0x33, 0xCC, 0x33, 0x00,
1911 0x33, 0xCC, 0x00, 0x00,
1912 0x33, 0x99, 0xFF, 0x00,
1913 0x33, 0x99, 0xCC, 0x00,
1914 0x33, 0x99, 0x99, 0x00,
1915 0x33, 0x99, 0x66, 0x00,
1916 0x33, 0x99, 0x33, 0x00,
1917 0x33, 0x99, 0x00, 0x00,
1918 0x33, 0x66, 0xFF, 0x00,
1919 0x33, 0x66, 0xCC, 0x00,
1920 0x33, 0x66, 0x99, 0x00,
1921 0x33, 0x66, 0x66, 0x00,
1922 0x33, 0x66, 0x33, 0x00,
1923 0x33, 0x66, 0x00, 0x00,
1924 0x33, 0x33, 0xFF, 0x00,
1925 0x33, 0x33, 0xCC, 0x00,
1926 0x33, 0x33, 0x99, 0x00,
1927 0x33, 0x33, 0x66, 0x00,
1928 0x33, 0x33, 0x33, 0x00,
1929 0x33, 0x33, 0x00, 0x00,
1930 0x33, 0x00, 0xFF, 0x00,
1931 0x33, 0x00, 0xCC, 0x00,
1932 0x33, 0x00, 0x99, 0x00,
1933 0x33, 0x00, 0x66, 0x00,
1934 0x33, 0x00, 0x33, 0x00,
1935 0x33, 0x00, 0x00, 0x00,
1936 0x00, 0xFF, 0xFF, 0x00,
1937 0x00, 0xFF, 0xCC, 0x00,
1938 0x00, 0xFF, 0x99, 0x00,
1939 0x00, 0xFF, 0x66, 0x00,
1940 0x00, 0xFF, 0x33, 0x00,
1941 0x00, 0xFF, 0x00, 0x00,
1942 0x00, 0xCC, 0xFF, 0x00,
1943 0x00, 0xCC, 0xCC, 0x00,
1944 0x00, 0xCC, 0x99, 0x00,
1945 0x00, 0xCC, 0x66, 0x00,
1946 0x00, 0xCC, 0x33, 0x00,
1947 0x00, 0xCC, 0x00, 0x00,
1948 0x00, 0x99, 0xFF, 0x00,
1949 0x00, 0x99, 0xCC, 0x00,
1950 0x00, 0x99, 0x99, 0x00,
1951 0x00, 0x99, 0x66, 0x00,
1952 0x00, 0x99, 0x33, 0x00,
1953 0x00, 0x99, 0x00, 0x00,
1954 0x00, 0x66, 0xFF, 0x00,
1955 0x00, 0x66, 0xCC, 0x00,
1956 0x00, 0x66, 0x99, 0x00,
1957 0x00, 0x66, 0x66, 0x00,
1958 0x00, 0x66, 0x33, 0x00,
1959 0x00, 0x66, 0x00, 0x00,
1960 0x00, 0x33, 0xFF, 0x00,
1961 0x00, 0x33, 0xCC, 0x00,
1962 0x00, 0x33, 0x99, 0x00,
1963 0x00, 0x33, 0x66, 0x00,
1964 0x00, 0x33, 0x33, 0x00,
1965 0x00, 0x33, 0x00, 0x00,
1966 0x00, 0x00, 0xFF, 0x00,
1967 0x00, 0x00, 0xCC, 0x00,
1968 0x00, 0x00, 0x99, 0x00,
1969 0x00, 0x00, 0x66, 0x00,
1970 0x00, 0x00, 0x33, 0x00,
1971 0xEE, 0x00, 0x00, 0x00,
1972 0xDD, 0x00, 0x00, 0x00,
1973 0xBB, 0x00, 0x00, 0x00,
1974 0xAA, 0x00, 0x00, 0x00,
1975 0x88, 0x00, 0x00, 0x00,
1976 0x77, 0x00, 0x00, 0x00,
1977 0x55, 0x00, 0x00, 0x00,
1978 0x44, 0x00, 0x00, 0x00,
1979 0x22, 0x00, 0x00, 0x00,
1980 0x11, 0x00, 0x00, 0x00,
1981 0x00, 0xEE, 0x00, 0x00,
1982 0x00, 0xDD, 0x00, 0x00,
1983 0x00, 0xBB, 0x00, 0x00,
1984 0x00, 0xAA, 0x00, 0x00,
1985 0x00, 0x88, 0x00, 0x00,
1986 0x00, 0x77, 0x00, 0x00,
1987 0x00, 0x55, 0x00, 0x00,
1988 0x00, 0x44, 0x00, 0x00,
1989 0x00, 0x22, 0x00, 0x00,
1990 0x00, 0x11, 0x00, 0x00,
1991 0x00, 0x00, 0xEE, 0x00,
1992 0x00, 0x00, 0xDD, 0x00,
1993 0x00, 0x00, 0xBB, 0x00,
1994 0x00, 0x00, 0xAA, 0x00,
1995 0x00, 0x00, 0x88, 0x00,
1996 0x00, 0x00, 0x77, 0x00,
1997 0x00, 0x00, 0x55, 0x00,
1998 0x00, 0x00, 0x44, 0x00,
1999 0x00, 0x00, 0x22, 0x00,
2000 0x00, 0x00, 0x11, 0x00,
2001 0xEE, 0xEE, 0xEE, 0x00,
2002 0xDD, 0xDD, 0xDD, 0x00,
2003 0xBB, 0xBB, 0xBB, 0x00,
2004 0xAA, 0xAA, 0xAA, 0x00,
2005 0x88, 0x88, 0x88, 0x00,
2006 0x77, 0x77, 0x77, 0x00,
2007 0x55, 0x55, 0x55, 0x00,
2008 0x44, 0x44, 0x44, 0x00,
2009 0x22, 0x22, 0x22, 0x00,
2010 0x11, 0x11, 0x11, 0x00,
2011 0x00, 0x00, 0x00, 0x00
2012];
2013
58309c73
KS
2014#[cfg(test)]
2015mod test {
2016 use super::*;
2017 use std::fs::File;
2018
2019 #[test]
2020 fn test_mov_demux() {
2021 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
2022 let mut fr = FileReader::new_read(&mut file);
2023 let mut br = ByteReader::new(&mut fr);
2024 let mut dmx = MOVDemuxer::new(&mut br);
2025 let mut sm = StreamManager::new();
2026 let mut si = SeekIndex::new();
2027 dmx.open(&mut sm, &mut si).unwrap();
2028
2029 loop {
2030 let pktres = dmx.get_frame(&mut sm);
2031 if let Err(e) = pktres {
2032 if e == DemuxerError::EOF { break; }
2033 panic!("error");
2034 }
2035 let pkt = pktres.unwrap();
2036 println!("Got {}", pkt);
2037 }
2038 }
0a0456a8
KS
2039
2040 #[test]
2041 fn test_dash_demux() {
2042 let mut file = File::open("assets/ITU/dash.m4a").unwrap();
2043 let mut fr = FileReader::new_read(&mut file);
2044 let mut br = ByteReader::new(&mut fr);
2045 let mut dmx = MOVDemuxer::new(&mut br);
2046 let mut sm = StreamManager::new();
2047 let mut si = SeekIndex::new();
2048 dmx.open(&mut sm, &mut si).unwrap();
2049
2050 loop {
2051 let pktres = dmx.get_frame(&mut sm);
2052 if let Err(e) = pktres {
2053 if e == DemuxerError::EOF { break; }
2054 panic!("error");
2055 }
2056 let pkt = pktres.unwrap();
2057 println!("Got {}", pkt);
2058 }
2059 }
58309c73 2060}