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