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