mov: hopefully fix audio PTS and seeking
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
1 use nihav_core::demuxers::*;
2 use nihav_registry::register::*;
3 use nihav_core::compr::deflate::*;
4
5 macro_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
14 trait Skip64 {
15 fn skip64(&mut self, size: u64) -> ByteIOResult<()>;
16 }
17
18 impl<'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
29 fn 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
44 fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
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);
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()?;
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;
59 }
60 Ok(size)
61 }
62
63 struct RootChunkHandler {
64 ctype: u32,
65 parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64>,
66 }
67
68 struct TrackChunkHandler {
69 ctype: u32,
70 parse: fn(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64>,
71 }
72
73 const IGNORED_CHUNKS: &[u32] = &[
74 mktag!(b"free"), mktag!(b"skip"), mktag!(b"udta"), mktag!(b"wide")
75 ];
76
77 const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[
78 RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp },
79 RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat },
80 RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov },
81 ];
82
83 macro_rules! read_chunk_list {
84 (root; $name: expr, $fname: ident, $handlers: ident) => {
85 fn $fname(&mut self, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<()> {
86 self.depth += 1;
87 validate!(self.depth < 32);
88 let list_end = self.src.tell() + size;
89 while self.src.tell() < list_end {
90 let ret = read_chunk_header(&mut self.src);
91 if ret.is_err() { break; }
92 let (ctype, size) = ret.unwrap();
93 if self.src.tell() + size > list_end {
94 break;
95 }
96 if IGNORED_CHUNKS.contains(&ctype) {
97 self.src.skip64(size)?;
98 continue;
99 }
100 let handler = $handlers.iter().find(|x| x.ctype == ctype);
101 let read_size;
102 if let Some(ref handler) = handler {
103 read_size = (handler.parse)(self, strmgr, size)?;
104 } else {
105 println!("skipping unknown chunk {:08X} size {}", ctype, size);
106 read_size = 0;
107 }
108 validate!(read_size <= size);
109 self.src.skip64(size - read_size)?;
110 }
111 self.depth -= 1;
112 validate!(self.src.tell() == list_end);
113 Ok(())
114 }
115 };
116 (track; $name: expr, $fname: ident, $handlers: ident) => {
117 fn $fname(&mut self, br: &mut ByteReader, size: u64) -> DemuxerResult<()> {
118 self.depth += 1;
119 validate!(self.depth < 32);
120 let list_end = br.tell() + size;
121 while br.tell() < list_end {
122 let ret = read_chunk_header(br);
123 if ret.is_err() { break; }
124 let (ctype, size) = ret.unwrap();
125 if br.tell() + size > list_end {
126 break;
127 }
128 if IGNORED_CHUNKS.contains(&ctype) {
129 br.skip64(size)?;
130 continue;
131 }
132 let handler = $handlers.iter().find(|x| x.ctype == ctype);
133 let read_size;
134 if let Some(ref handler) = handler {
135 read_size = (handler.parse)(self, br, size)?;
136 } else {
137 read_size = 0;
138 }
139 validate!(read_size <= size);
140 br.skip64(size - read_size)?;
141 }
142 self.depth -= 1;
143 validate!(br.tell() == list_end);
144 Ok(())
145 }
146 }
147 }
148
149 fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
150 br.skip64(size)?;
151 Ok(size)
152 }
153
154 fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
155 dmx.src.skip64(size)?;
156 Ok(size)
157 }
158
159 fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
160 dmx.mdat_pos = dmx.src.tell();
161 dmx.mdat_size = size;
162 dmx.src.skip64(size)?;
163 Ok(size)
164 }
165
166 fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
167 dmx.read_moov(strmgr, size)?;
168 Ok(size)
169 }
170
171 const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[
172 RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd },
173 RootChunkHandler { ctype: mktag!(b"cmov"), parse: read_cmov },
174 RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab },
175 RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak },
176 RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta },
177 ];
178
179 fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
180 const KNOWN_MVHD_SIZE: u64 = 100;
181 let br = &mut dmx.src;
182 validate!(size >= KNOWN_MVHD_SIZE);
183 let version = br.read_byte()?;
184 validate!(version == 0);
185 let _flags = br.read_u24be()?;
186 let _ctime = br.read_u32be()?;
187 let _mtime = br.read_u32be()?;
188 let tscale = br.read_u32be()?;
189 let duration = br.read_u32be()?;
190 let _pref_rate = br.read_u32be()?;
191 let _pref_volume = br.read_u16be()?;
192 br.read_skip(10)?;
193 br.read_skip(36)?; // matrix
194 let _preview_time = br.read_u32be()?;
195 let _preview_duration = br.read_u32be()?;
196 let _poster_time = br.read_u32be()?;
197 let _sel_time = br.read_u32be()?;
198 let _sel_duration = br.read_u32be()?;
199 let _cur_time = br.read_u32be()?;
200 let _next_track_id = br.read_u32be()?;
201 dmx.duration = duration;
202 dmx.tb_den = tscale;
203
204 Ok(KNOWN_MVHD_SIZE)
205 }
206
207 fn read_cmov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
208 let br = &mut dmx.src;
209 validate!(size > 24);
210 let dcom_size = br.read_u32be()?;
211 let dcom_tag = br.read_tag()?;
212 let compr_type = br.read_tag()?;
213 validate!(&dcom_tag == b"dcom" && dcom_size == 12);
214 if &compr_type != b"zlib" {
215 return Err(DemuxerError::NotImplemented);
216 }
217 let cmvd_size = u64::from(br.read_u32be()?);
218 let cmvd_tag = br.read_tag()?;
219 validate!(&cmvd_tag == b"cmvd" && cmvd_size > 14 && cmvd_size == size - 12);
220 let comp_size = (cmvd_size - 12) as usize;
221 let uncomp_size = br.read_u32be()? as usize;
222 validate!(uncomp_size > 8);
223 let mut sbuf = vec![0; comp_size];
224 let mut dbuf = vec![0; uncomp_size];
225 br.read_buf(sbuf.as_mut_slice())?;
226 let ret = Inflate::uncompress(sbuf.as_slice(), dbuf.as_mut_slice());
227 if ret.is_err() {
228 return Err(DemuxerError::InvalidData);
229 }
230 let len = ret.unwrap();
231 validate!(len == uncomp_size);
232 let mut mr = MemoryReader::new_read(dbuf.as_slice());
233 let mut br = ByteReader::new(&mut mr);
234 let (ctype, csize) = read_chunk_header(&mut br)?;
235 validate!(ctype == mktag!(b"moov"));
236 let mut ddmx = MOVDemuxer::new(&mut br);
237 ddmx.read_moov(strmgr, csize)?;
238 std::mem::swap(&mut dmx.tracks, &mut ddmx.tracks);
239 dmx.duration = ddmx.duration;
240 dmx.tb_den = ddmx.tb_den;
241 std::mem::swap(&mut dmx.pal, &mut ddmx.pal);
242
243 Ok(size)
244 }
245
246 fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
247 let mut pal = [0; 1024];
248 let size = read_palette(&mut dmx.src, size, &mut pal)?;
249 dmx.pal = Some(Arc::new(pal));
250 Ok(size)
251 }
252
253 fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
254 dmx.src.skip64(size)?;
255 Ok(size)
256 }
257
258 fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
259 let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
260 track.read_trak(&mut dmx.src, size)?;
261 validate!(track.tkhd_found && track.stsd_found);
262 validate!(strmgr.get_stream_by_id(track.track_id).is_none());
263 dmx.cur_track += 1;
264 let mut str = None;
265 std::mem::swap(&mut track.stream, &mut str);
266 if let Some(stream) = str {
267 let str_id = strmgr.add_stream(stream).unwrap();
268 track.track_str_id = str_id;
269 }
270 dmx.tracks.push(track);
271 Ok(size)
272 }
273
274 const TRAK_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
275 TrackChunkHandler { ctype: mktag!(b"clip"), parse: skip_chunk },
276 TrackChunkHandler { ctype: mktag!(b"matt"), parse: skip_chunk },
277 TrackChunkHandler { ctype: mktag!(b"edts"), parse: skip_chunk },
278 TrackChunkHandler { ctype: mktag!(b"tref"), parse: skip_chunk },
279 TrackChunkHandler { ctype: mktag!(b"load"), parse: skip_chunk },
280 TrackChunkHandler { ctype: mktag!(b"imap"), parse: skip_chunk },
281 TrackChunkHandler { ctype: mktag!(b"tkhd"), parse: read_tkhd },
282 TrackChunkHandler { ctype: mktag!(b"mdia"), parse: read_mdia },
283 ];
284
285 fn read_tkhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
286 const KNOWN_TKHD_SIZE: u64 = 84;
287 validate!(size >= KNOWN_TKHD_SIZE);
288 let version = br.read_byte()?;
289 validate!(version == 0);
290 let _flags = br.read_u24be()?;
291 let _ctime = br.read_u32be()?;
292 let _mtime = br.read_u32be()?;
293 let track_id = br.read_u32be()?;
294 br.read_skip(4)?;
295 let duration = br.read_u32be()?;
296 br.read_skip(8)?;
297 let _layer = br.read_u16be()?;
298 let _alt_group = br.read_u16be()?;
299 let _volume = br.read_u16be()?;
300 br.read_skip(2)?;
301 br.read_skip(36)?; // matrix
302 let width = br.read_u32be()? as usize;
303 let height = br.read_u32be()? as usize;
304 track.width = width >> 16;
305 track.height = height >> 16;
306 track.track_id = track_id;
307 track.duration = duration;
308
309 track.tkhd_found = true;
310 Ok(KNOWN_TKHD_SIZE)
311 }
312
313 fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
314 track.stream_type = StreamType::None;
315 track.read_mdia(br, size)?;
316 Ok(size)
317 }
318
319 const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
320 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
321 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
322 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
323 ];
324
325 fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
326 const KNOWN_HDLR_SIZE: u64 = 24;
327 validate!(size >= KNOWN_HDLR_SIZE);
328 let version = br.read_byte()?;
329 validate!(version == 0);
330 let flags = br.read_u24be()?;
331 validate!(flags == 0);
332 let comp_type = br.read_u32be()?;
333 let comp_subtype = br.read_u32be()?;
334 let _comp_manufacturer = br.read_u32be()?;
335 let _comp_flags = br.read_u32be()?;
336 let _comp_flags_mask = br.read_u32be()?;
337
338 if comp_type == mktag!(b"mhlr") || comp_type == 0 {
339 if comp_subtype == mktag!(b"vide") {
340 track.stream_type = StreamType::Video;
341 } else if comp_subtype == mktag!(b"soun") {
342 track.stream_type = StreamType::Audio;
343 } else {
344 track.stream_type = StreamType::Data;
345 }
346 } else if comp_type == mktag!(b"dhlr") {
347 track.stream_type = StreamType::Data;
348 } else {
349 println!("Unknown stream type");
350 track.stream_type = StreamType::Data;
351 }
352
353 Ok(KNOWN_HDLR_SIZE)
354 }
355
356 fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
357 track.read_minf(br, size)?;
358 Ok(size)
359 }
360
361 const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
362 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
364 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
365 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
366 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
367 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
368 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
369 ];
370
371 fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
372 const KNOWN_VMHD_SIZE: u64 = 12;
373 validate!(track.stream_type == StreamType::Video);
374 validate!(size >= KNOWN_VMHD_SIZE);
375 let version = br.read_byte()?;
376 validate!(version == 0);
377 let _flags = br.read_u24be()?;
378 br.read_skip(2)?; // graphics mode
379 br.read_skip(6)?; // opcolor
380 Ok(KNOWN_VMHD_SIZE)
381 }
382
383 fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
384 const KNOWN_SMHD_SIZE: u64 = 8;
385 validate!(track.stream_type == StreamType::Audio);
386 validate!(size >= KNOWN_SMHD_SIZE);
387 let version = br.read_byte()?;
388 validate!(version == 0);
389 let _flags = br.read_u24be()?;
390 br.read_skip(2)?; // balance
391 br.read_skip(2)?;
392 Ok(KNOWN_SMHD_SIZE)
393 }
394
395 fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
396 validate!(track.stream_type == StreamType::Data);
397 Ok(0)
398 }
399
400 fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 validate!(track.stream_type == StreamType::Data);
402 const KNOWN_GMIN_SIZE: u64 = 16;
403 validate!(size >= KNOWN_GMIN_SIZE);
404 let version = br.read_byte()?;
405 validate!(version == 0);
406 let _flags = br.read_u24be()?;
407 br.read_skip(2)?; // graphics mode
408 br.read_skip(6)?; // opcolor
409 br.read_skip(2)?; // balance
410 br.read_skip(2)?;
411 Ok(KNOWN_GMIN_SIZE)
412 }
413
414 fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
415 track.read_stbl(br, size)?;
416 Ok(size)
417 }
418
419 const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
420 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
421 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
422 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
423 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
424 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
425 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
426 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
427 ];
428
429 fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
430 let read_part = br.tell() - start_pos;
431 if read_part + 8 < size {
432 let mut buf = [0; 8];
433 br.peek_buf(&mut buf)?;
434 if &buf[4..8] != b"wave" {
435 let mut buf = vec![0; (size - read_part) as usize];
436 br.read_buf(&mut buf)?;
437 return Ok(Some(buf));
438 }
439
440 let csize = br.read_u32be()? as u64;
441 let ctag = br.read_u32be()?;
442 validate!(read_part + csize <= size);
443 validate!(ctag == mktag!(b"wave"));
444 if csize == 8 {
445 return Ok(None);
446 }
447 let mut buf = [0; 8];
448 br.peek_buf(&mut buf)?;
449 if &buf[4..8] == b"frma" {
450 br.read_skip(12)?;
451 if csize > 20 {
452 let mut buf = vec![0; (csize - 20) as usize];
453 br.read_buf(&mut buf)?;
454 Ok(Some(buf))
455 } else {
456 Ok(None)
457 }
458 } else if csize > 8 {
459 let mut buf = vec![0; (csize as usize) - 8];
460 br.read_buf(&mut buf)?;
461 Ok(Some(buf))
462 } else {
463 Ok(None)
464 }
465 } else {
466 Ok(None)
467 }
468 }
469
470 fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
471 const KNOWN_STSD_SIZE: u64 = 24;
472 validate!(size >= KNOWN_STSD_SIZE);
473 let start_pos = br.tell();
474 let version = br.read_byte()?;
475 validate!(version == 0);
476 let _flags = br.read_u24be()?;
477 let entries = br.read_u32be()?;
478 validate!(entries > 0);
479 let esize = u64::from(br.read_u32be()?);
480 validate!(esize + 8 <= size);
481 let mut fcc = [0u8; 4];
482 br.read_buf(&mut fcc)?;
483 br.read_skip(6)?;
484 let _data_ref = br.read_u16be()?;
485
486 track.fcc = fcc;
487
488 let codec_info;
489 match track.stream_type {
490 StreamType::Video => {
491 let _ver = br.read_u16be()?;
492 let _revision = br.read_u16le()?;
493 let _vendor = br.read_u32be()?;
494 let _temp_quality = br.read_u32be()?;
495 let _spat_quality = br.read_u32be()?;
496 let width = br.read_u16be()? as usize;
497 let height = br.read_u16be()? as usize;
498 let _hor_res = br.read_u32be()?;
499 let _vert_res = br.read_u32be()?;
500 let data_size = br.read_u32be()?;
501 validate!(data_size == 0);
502 let _frame_count = br.read_u16be()? as usize;
503 let _cname_len = br.read_byte()? as usize;
504 br.read_skip(31)?; // actual compressor name
505 let depth = br.read_u16be()?;
506 let ctable_id = br.read_u16be()?;
507 let grayscale = depth > 0x20 || depth == 1;
508 let depth = if grayscale { depth & 0x1F } else { depth };
509 validate!(depth <= 8 || (ctable_id == 0xFFFF));
510 if ctable_id == 0 {
511 let max_pal_size = start_pos + size - br.tell();
512 let mut pal = [0; 1024];
513 read_palette(br, max_pal_size, &mut pal)?;
514 track.pal = Some(Arc::new(pal));
515 } else if (depth <= 8) && !grayscale {
516 match depth & 0x1F {
517 2 => {
518 let mut pal = [0; 1024];
519 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
520 track.pal = Some(Arc::new(pal));
521 },
522 4 => {
523 let mut pal = [0; 1024];
524 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
525 track.pal = Some(Arc::new(pal));
526 },
527 8 => {
528 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
529 },
530 _ => {},
531 };
532 } else if grayscale && ctable_id != 0xFFFF {
533 let mut pal = [0; 1024];
534 let cdepth = depth & 0x1F;
535 let size = 1 << cdepth;
536 for i in 0..size {
537 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
538 let mut off = 8 - cdepth;
539 while off >= cdepth {
540 clr |= clr >> (8 - off);
541 off -= cdepth;
542 }
543 if off > 0 {
544 clr |= clr >> (8 - off);
545 }
546 pal[i * 4] = clr;
547 pal[i * 4 + 1] = clr;
548 pal[i * 4 + 2] = clr;
549 }
550 track.pal = Some(Arc::new(pal));
551 }
552 // todo other atoms, put as extradata
553 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
554 name
555 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
556 name
557 } else {
558 "unknown"
559 };
560 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
561 let mut vhdr = NAVideoInfo::new(width, height, false, format);
562 vhdr.bits = depth as u8;
563 let edata = if br.tell() - start_pos + 4 < size {
564 //todo skip various common atoms
565 let edata_size = br.read_u32be()? as usize;
566 validate!(edata_size >= 4);
567 let mut buf = vec![0; edata_size - 4];
568 br.read_buf(buf.as_mut_slice())?;
569 Some(buf)
570 } else {
571 None
572 };
573 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
574 },
575 StreamType::Audio => {
576 let sver = br.read_u16be()?;
577 let _revision = br.read_u16le()?;
578 let _vendor = br.read_u32be()?;
579 let nchannels = br.read_u16be()?;
580 validate!(nchannels <= 64);
581 let sample_size = br.read_u16be()?;
582 validate!(sample_size <= 128);
583 let _compr_id = br.read_u16be()?;
584 let packet_size = br.read_u16be()? as usize;
585 validate!(packet_size == 0);
586 let sample_rate = br.read_u32be()?;
587 validate!(sample_rate > (1 << 16));
588 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
589 name
590 } 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]))) {
591 name
592 } else {
593 "unknown"
594 };
595 let mut soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
596 if &fcc == b"raw " && sample_size == 8 {
597 soniton.signed = false;
598 }
599 let block_align = 1;
600 if sver == 1 {
601 let samples_per_packet = br.read_u32be()?;
602 let _bytes_per_packet = br.read_u32be()?;
603 let bytes_per_frame = br.read_u32be()?;
604 let _bytes_per_sample = br.read_u32be()?;
605 track.bsize = bytes_per_frame as usize;
606 track.frame_samples = samples_per_packet as usize;
607 track.tb_num = samples_per_packet;
608 } else {
609 track.bsize = (sample_size / 8) as usize;
610 }
611 track.tb_den = sample_rate >> 16;
612 track.raw_audio = match &fcc {
613 b"NONE" | b"raw " | b"twos" | b"sowt" |
614 b"in24" | b"in32" | b"fl32" | b"fl64" |
615 b"ima4" | b"ms\x00\x02" | b"ms\x00\x21" |
616 b"alaw" | b"ulaw" |
617 b"MAC3" | b"MAC6" => true,
618 _ => false,
619 };
620 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
621 let edata = parse_audio_edata(br, start_pos, size)?;
622 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
623 track.channels = nchannels as usize;
624 track.bits = sample_size as usize;
625 },
626 StreamType::None => {
627 return Err(DemuxerError::InvalidData);
628 },
629 _ => {
630 //todo put it all into extradata
631 let edata = None;
632 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
633 },
634 };
635 let read_size = br.tell() - start_pos;
636 validate!(read_size <= size);
637 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, track.tb_num, track.tb_den, u64::from(track.duration)));
638 track.stsd_found = true;
639 Ok(read_size)
640 }
641
642 fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
643 validate!(size >= 8);
644 let start_pos = br.tell();
645 let version = br.read_byte()?;
646 validate!(version == 0);
647 let _flags = br.read_u24be()?;
648 let entries = br.read_u32be()? as usize;
649 validate!(entries as u64 <= (size - 8) / 8);
650 if entries == 0 {
651 } else if entries == 1 {
652 let _count = br.read_u32be()?;
653 let tb_num = br.read_u32be()?;
654 if let Some(ref mut stream) = track.stream {
655 let tb_den = stream.tb_den;
656 let (tb_num, tb_den) = reduce_timebase(tb_num * stream.tb_num, tb_den);
657 stream.duration /= u64::from(stream.tb_den / tb_den);
658 stream.tb_num = tb_num;
659 stream.tb_den = tb_den;
660 track.tb_num = tb_num;
661 track.tb_den = tb_den;
662 }
663 } else {
664 track.time_to_sample.truncate(0);
665 track.time_to_sample.reserve(entries);
666 for _ in 0..entries {
667 let count = br.read_u32be()?;
668 let mult = br.read_u32be()?;
669 track.time_to_sample.push((count, mult));
670 }
671 }
672 let read_size = br.tell() - start_pos;
673 validate!(read_size <= size);
674 Ok(read_size)
675 }
676
677 fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
678 let version = br.read_byte()?;
679 validate!(version == 0);
680 let _flags = br.read_u24be()?;
681 let entries = br.read_u32be()? as usize;
682 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
683 validate!((entries * 4 + 8) as u64 == size);
684 track.keyframes = Vec::with_capacity(entries);
685 let mut last_sample_no = 0;
686 for _ in 0..entries {
687 let sample_no = br.read_u32be()?;
688 validate!(sample_no > last_sample_no);
689 track.keyframes.push(sample_no);
690 last_sample_no = sample_no;
691 }
692 Ok(size)
693 }
694
695 fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
696 let version = br.read_byte()?;
697 validate!(version == 0);
698 let _flags = br.read_u24be()?;
699 let entries = br.read_u32be()? as usize;
700 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
701 validate!((entries * 12 + 8) as u64 == size);
702 track.sample_map = Vec::with_capacity(entries);
703 let mut last_sample_no = 0;
704 for _i in 0..entries {
705 let sample_no = br.read_u32be()?;
706 validate!(sample_no > last_sample_no);
707 let nsamples = br.read_u32be()?;
708 let _sample_desc = br.read_u32be()?;
709 track.sample_map.push((sample_no, nsamples));
710 last_sample_no = sample_no;
711 }
712 Ok(size)
713 }
714
715 fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
716 let version = br.read_byte()?;
717 validate!(version == 0);
718 let _flags = br.read_u24be()?;
719 let sample_size = br.read_u32be()?;
720 if sample_size != 0 {
721 track.sample_size = sample_size;
722 if track.sample_size != 1 || track.bsize == 0 {
723 track.bsize = sample_size as usize;
724 }
725 Ok(8)
726 } else {
727 let entries = br.read_u32be()? as usize;
728 validate!((entries * 4 + 12) as u64 == size);
729 track.chunk_sizes = Vec::with_capacity(entries);
730 for _ in 0..entries {
731 let sample_size = br.read_u32be()?;
732 track.chunk_sizes.push(sample_size);
733 }
734 Ok(size)
735 }
736 }
737
738 fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
739 let version = br.read_byte()?;
740 validate!(version == 0);
741 let _flags = br.read_u24be()?;
742 let entries = br.read_u32be()? as usize;
743 validate!((entries * 4 + 8) as u64 == size);
744 track.chunk_offsets = Vec::with_capacity(entries);
745 for _i in 0..entries {
746 let sample_offset = br.read_u32be()?;
747 track.chunk_offsets.push(u64::from(sample_offset));
748 }
749 Ok(size)
750 }
751
752 struct MOVDemuxer<'a> {
753 src: &'a mut ByteReader<'a>,
754 depth: usize,
755 mdat_pos: u64,
756 mdat_size: u64,
757 tracks: Vec<Track>,
758 cur_track: usize,
759 tb_den: u32,
760 duration: u32,
761 pal: Option<Arc<[u8; 1024]>>,
762 }
763
764 struct Track {
765 track_id: u32,
766 track_str_id: usize,
767 track_no: u32,
768 tb_num: u32,
769 tb_den: u32,
770 raw_audio: bool,
771 raw_apos: u64,
772 duration: u32,
773 depth: u8,
774 tkhd_found: bool,
775 stsd_found: bool,
776 stream_type: StreamType,
777 width: usize,
778 height: usize,
779 channels: usize,
780 bits: usize,
781 bsize: usize,
782 fcc: [u8; 4],
783 keyframes: Vec<u32>,
784 chunk_sizes: Vec<u32>,
785 chunk_offsets: Vec<u64>,
786 time_to_sample: Vec<(u32, u32)>,
787 sample_map: Vec<(u32, u32)>,
788 sample_size: u32,
789 frame_samples: usize,
790 stream: Option<NAStream>,
791 cur_chunk: usize,
792 cur_sample: usize,
793 samples_left: usize,
794 last_offset: u64,
795 pal: Option<Arc<[u8; 1024]>>,
796 timesearch: TimeSearcher,
797 }
798
799 #[derive(Default)]
800 struct TimeSearcher {
801 idx: usize,
802 base: u64,
803 sbase: u32,
804 cur_len: u32,
805 cur_mul: u32,
806 }
807
808 impl TimeSearcher {
809 fn new() -> Self { Self::default() }
810 fn reset(&mut self) {
811 *self = Self::default();
812 }
813 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
814 if tts.is_empty() {
815 u64::from(sample)
816 } else if sample >= self.sbase {
817 let mut sample = sample - self.sbase;
818 if self.idx == 0 {
819 let (cur_len, cur_mul) = tts[0];
820 self.cur_len = cur_len;
821 self.cur_mul = cur_mul;
822 self.idx += 1;
823 }
824 while self.idx < tts.len() && sample > self.cur_len {
825 sample -= self.cur_len;
826 self.sbase += self.cur_len;
827 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
828 self.cur_len = tts[self.idx].0;
829 self.cur_mul = tts[self.idx].1;
830 self.idx += 1;
831 }
832 self.base + u64::from(sample) * u64::from(self.cur_mul)
833 } else {
834 self.reset();
835 self.map_time(sample, tts)
836 }
837 }
838 }
839
840 impl Track {
841 fn new(track_no: u32, tb_den: u32) -> Self {
842 Self {
843 tkhd_found: false,
844 stsd_found: false,
845 track_id: 0,
846 track_str_id: 0,
847 track_no,
848 tb_num: 1,
849 tb_den,
850 raw_audio: false,
851 raw_apos: 0,
852 duration: 0,
853 stream_type: StreamType::None,
854 width: 0,
855 height: 0,
856 channels: 0,
857 bits: 0,
858 bsize: 0,
859 fcc: [0; 4],
860 keyframes: Vec::new(),
861 chunk_sizes: Vec::new(),
862 chunk_offsets: Vec::new(),
863 time_to_sample: Vec::new(),
864 sample_map: Vec::new(),
865 sample_size: 0,
866 frame_samples: 0,
867 stream: None,
868 depth: 0,
869 cur_chunk: 0,
870 cur_sample: 0,
871 samples_left: 0,
872 last_offset: 0,
873 pal: None,
874 timesearch: TimeSearcher::new(),
875 }
876 }
877 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
878 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
879 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
880 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
881 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
882 if !self.keyframes.is_empty() {
883 seek_index.mode = SeekIndexMode::Present;
884 }
885 let mut tsearch = TimeSearcher::new();
886 for kf_time in self.keyframes.iter() {
887 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
888 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
889 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
890 }
891 }
892 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
893 if nsamp == 0 {
894 self.bsize
895 } else {
896 match &self.fcc {
897 b"NONE" | b"raw " | b"twos" | b"sowt" => {
898 (nsamp * self.bits * self.channels + 7) >> 3
899 },
900 b"ima4" => {
901 let nblocks = (nsamp + 63) >> 6;
902 nblocks * 34 * self.channels
903 },
904 b"MAC3" => {
905 (nsamp + 5) / 6 * 2 * self.channels
906 },
907 b"MAC6" => {
908 (nsamp + 5) / 6 * self.channels
909 },
910 b"in24" => nsamp * 3 * self.channels,
911 b"in32" | b"fl32" => nsamp * 4 * self.channels,
912 b"fl64" => nsamp * 8 * self.channels,
913 b"ulaw" | b"alaw" => nsamp,
914 b"ms\x00\x02" => { //MS ADPCM
915 ((nsamp - 1) / 2 + 7) * self.channels
916 },
917 b"ms\x00\x21" => { //IMA ADPCM
918 (nsamp / 2 + 4) * self.channels
919 },
920 _ => self.bsize,
921 }
922 }
923 }
924 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
925 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
926 let mut pts = NATimeInfo::new(Some(pts_val), None, None, self.tb_num, self.tb_den);
927 //todo dts decoding
928 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
929 if self.cur_sample >= self.chunk_sizes.len() {
930 return None;
931 }
932 let offset = self.chunk_offsets[self.cur_sample];
933 let size = self.chunk_sizes[self.cur_sample] as usize;
934 self.cur_sample += 1;
935 Some((pts, offset, size))
936 } else {
937 if self.samples_left == 0 {
938 if self.cur_chunk >= self.chunk_offsets.len() {
939 return None;
940 }
941 for (idx, samples) in self.sample_map.iter() {
942 if *idx as usize <= self.cur_chunk + 1 {
943 self.samples_left = *samples as usize;
944 } else {
945 break;
946 }
947 }
948 self.last_offset = self.chunk_offsets[self.cur_chunk];
949 self.cur_chunk += 1;
950 }
951 let offset = self.last_offset;
952 let size = self.get_size(self.cur_sample);
953 self.last_offset += size as u64;
954 if self.stream_type == StreamType::Video {
955 self.samples_left -= 1;
956 } else if self.frame_samples != 0 && self.bsize != 0 {
957 let nblocks = size / self.bsize;
958 if self.raw_audio {
959 pts.pts = Some(self.raw_apos);
960 pts.duration = Some(nblocks as u64);
961 self.raw_apos += nblocks as u64;
962 }
963 if nblocks > 0 {
964 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
965 self.samples_left -= consumed;
966 } else {
967 self.samples_left = 0;
968 }
969 } else if !self.raw_audio {
970 self.samples_left -= 1;
971 } else {
972 const BLOCK_SAMPLES: usize = 1024 * 6; // should be multiple of 64 and 6 to fit both IMA ADPCM and MACE 6:1 blocks
973 let max_size = self.calculate_chunk_size(BLOCK_SAMPLES);
974 let cur_size = self.calculate_chunk_size(self.samples_left);
975 let add_off = (size - cur_size) as u64;
976 let dsize = cur_size.min(max_size);
977 if self.samples_left >= BLOCK_SAMPLES {
978 self.cur_sample += BLOCK_SAMPLES;
979 self.samples_left -= BLOCK_SAMPLES;
980 self.last_offset -= size as u64;
981 } else {
982 self.cur_sample += self.samples_left;
983 self.samples_left = 0;
984 }
985 return Some((pts, offset + add_off, dsize));
986 }
987 self.cur_sample += 1;
988 Some((pts, offset, size))
989 }
990 }
991 fn get_size(&self, sample_no: usize) -> usize {
992 if !self.chunk_sizes.is_empty() {
993 self.chunk_sizes[sample_no] as usize
994 } else if !self.sample_map.is_empty() {
995 let mut nsamp = 0;
996 for (idx, samples) in self.sample_map.iter() {
997 if *idx as usize <= self.cur_chunk {
998 nsamp = *samples;
999 } else {
1000 break;
1001 }
1002 }
1003 self.calculate_chunk_size(nsamp as usize)
1004 } else {
1005 self.bsize
1006 }
1007 }
1008 fn seek(&mut self, pts: u64, tpoint: NATimePoint) -> DemuxerResult<()> {
1009 self.cur_sample = pts as usize;
1010 self.samples_left = 0;
1011 if self.stream_type == StreamType::Audio {
1012 if let NATimePoint::Milliseconds(ms) = tpoint {
1013 let exp_pts = NATimeInfo::time_to_ts(ms, 1000, self.tb_num, self.tb_den);
1014 if self.raw_audio {
1015 if self.frame_samples != 0 {
1016 self.raw_apos = exp_pts / (self.frame_samples as u64);
1017 let mut apos = 0;
1018 self.cur_sample = 0;
1019 self.cur_chunk = 0;
1020 let mut cmap = self.sample_map.iter();
1021 let mut cur_samps = 0;
1022 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1023 loop {
1024 if self.cur_chunk + 1 == next_idx as usize {
1025 self.samples_left = cur_samps;
1026 cur_samps = next_samples as usize;
1027 if let Some((new_idx, new_samples)) = cmap.next() {
1028 next_idx = *new_idx;
1029 next_samples = *new_samples;
1030 }
1031 }
1032 self.raw_apos = apos;
1033 apos += (cur_samps / self.frame_samples) as u64;
1034 if apos > exp_pts {
1035 if cur_samps == self.frame_samples || apos > exp_pts + 1 {
1036 if self.cur_chunk >= self.chunk_offsets.len() {
1037 return Err(DemuxerError::SeekError);
1038 }
1039 self.last_offset = self.chunk_offsets[self.cur_chunk];
1040 break;
1041 }
1042 }
1043 self.cur_chunk += 1;
1044 }
1045 self.samples_left = cur_samps;
1046 self.cur_chunk += 1;
1047 } else {
1048 self.raw_apos = exp_pts;
1049 self.cur_sample = exp_pts as usize;
1050 let mut csamp = 0;
1051 self.cur_chunk = 0;
1052 let mut cmap = self.sample_map.iter();
1053 let mut cur_samps = 0;
1054 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1055 loop {
1056 if self.cur_chunk + 1 == next_idx as usize {
1057 self.samples_left = cur_samps;
1058 cur_samps = next_samples as usize;
1059 if let Some((new_idx, new_samples)) = cmap.next() {
1060 next_idx = *new_idx;
1061 next_samples = *new_samples;
1062 }
1063 }
1064 csamp += cur_samps;
1065 if csamp > self.cur_sample {
1066 if self.cur_chunk >= self.chunk_offsets.len() {
1067 return Err(DemuxerError::SeekError);
1068 }
1069 self.last_offset = self.chunk_offsets[self.cur_chunk];
1070 break;
1071 }
1072 self.cur_chunk += 1;
1073 }
1074 self.samples_left = csamp - self.cur_sample;
1075 self.cur_chunk += 1;
1076 }
1077 } else {
1078 self.cur_chunk = self.cur_sample;
1079 }
1080 } else {
1081 self.cur_chunk = self.cur_sample;
1082 }
1083 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
1084 let mut csamp = 0;
1085 self.cur_chunk = 0;
1086 let mut cmap = self.sample_map.iter();
1087 let mut cur_samps = 0;
1088 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
1089 loop {
1090 if self.cur_chunk + 1 == next_idx as usize {
1091 self.samples_left = cur_samps;
1092 cur_samps = next_samples as usize;
1093 if let Some((new_idx, new_samples)) = cmap.next() {
1094 next_idx = *new_idx;
1095 next_samples = *new_samples;
1096 }
1097 }
1098 csamp += cur_samps;
1099 if csamp >= self.cur_sample {
1100 if self.cur_chunk >= self.chunk_offsets.len() {
1101 return Err(DemuxerError::SeekError);
1102 }
1103 self.last_offset = self.chunk_offsets[self.cur_chunk];
1104 break;
1105 }
1106 self.cur_chunk += 1;
1107 }
1108 csamp -= cur_samps;
1109 for sample_no in csamp..self.cur_sample {
1110 self.last_offset += self.get_size(sample_no) as u64;
1111 }
1112 self.samples_left = csamp + cur_samps - self.cur_sample;
1113 self.cur_chunk += 1;
1114 }
1115 Ok(())
1116 }
1117 }
1118
1119 impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1120 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1121 self.read_root(strmgr)?;
1122 validate!(self.mdat_pos > 0);
1123 validate!(!self.tracks.is_empty());
1124 for track in self.tracks.iter() {
1125 track.fill_seek_index(seek_index);
1126 }
1127 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1128 self.cur_track = 0;
1129 Ok(())
1130 }
1131
1132 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
1133 if self.tracks.is_empty() {
1134 return Err(DemuxerError::EOF);
1135 }
1136 for _ in 0..self.tracks.len() {
1137 if self.cur_track >= self.tracks.len() {
1138 self.cur_track = 0;
1139 }
1140 let track = &mut self.tracks[self.cur_track];
1141 self.cur_track += 1;
1142 let first = track.cur_sample == 0;
1143 if let Some((pts, offset, size)) = track.get_next_chunk() {
1144 let str = strmgr.get_stream(track.track_str_id);
1145 if str.is_none() { return Err(DemuxerError::InvalidData); }
1146 let stream = str.unwrap();
1147 self.src.seek(SeekFrom::Start(offset))?;
1148 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1149 if let Some(ref pal) = track.pal {
1150 let side_data = NASideData::Palette(first, pal.clone());
1151 pkt.add_side_data(side_data);
1152 }
1153 return Ok(pkt);
1154 }
1155 }
1156 Err(DemuxerError::EOF)
1157 }
1158
1159 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
1160 let ret = seek_index.find_pos(time);
1161 if ret.is_none() {
1162 return Err(DemuxerError::SeekError);
1163 }
1164 let seek_info = ret.unwrap();
1165 for track in self.tracks.iter_mut() {
1166 track.seek(seek_info.pts, time)?;
1167 }
1168 Ok(())
1169 }
1170 fn get_duration(&self) -> u64 {
1171 if self.tb_den != 0 {
1172 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1173 } else {
1174 0
1175 }
1176 }
1177 }
1178
1179 impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1180 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
1181 fn set_options(&mut self, _options: &[NAOption]) { }
1182 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
1183 }
1184
1185 impl<'a> MOVDemuxer<'a> {
1186 fn new(io: &'a mut ByteReader<'a>) -> Self {
1187 MOVDemuxer {
1188 src: io,
1189 depth: 0,
1190 mdat_pos: 0,
1191 mdat_size: 0,
1192 tracks: Vec::with_capacity(2),
1193 cur_track: 0,
1194 tb_den: 0,
1195 duration: 0,
1196 pal: None,
1197 }
1198 }
1199 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1200 self.depth = 0;
1201 while self.src.left() != 0 {
1202 let ret = read_chunk_header(&mut self.src);
1203 if ret.is_err() { break; }
1204 let (ctype, size) = ret.unwrap();
1205 if IGNORED_CHUNKS.contains(&ctype) {
1206 self.src.skip64(size)?;
1207 continue;
1208 }
1209 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1210 let read_size;
1211 if let Some(ref handler) = handler {
1212 read_size = (handler.parse)(self, strmgr, size)?;
1213 } else {
1214 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1215 read_size = 0;
1216 }
1217 validate!(read_size <= size);
1218 self.src.skip64(size - read_size)?;
1219 }
1220 //todo check if all needed chunks are found
1221 Ok(())
1222 }
1223 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1224 }
1225
1226 pub struct MOVDemuxerCreator { }
1227
1228 impl DemuxerCreator for MOVDemuxerCreator {
1229 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1230 Box::new(MOVDemuxer::new(br))
1231 }
1232 fn get_name(&self) -> &'static str { "mov" }
1233 }
1234
1235 const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1236 0x93, 0x65, 0x5E, 0x00,
1237 0xFF, 0xFF, 0xFF, 0x00,
1238 0xDF, 0xD0, 0xAB, 0x00,
1239 0x00, 0x00, 0x00, 0x00
1240 ];
1241 const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1242 0xFF, 0xFB, 0xFF, 0x00,
1243 0xEF, 0xD9, 0xBB, 0x00,
1244 0xE8, 0xC9, 0xB1, 0x00,
1245 0x93, 0x65, 0x5E, 0x00,
1246 0xFC, 0xDE, 0xE8, 0x00,
1247 0x9D, 0x88, 0x91, 0x00,
1248 0xFF, 0xFF, 0xFF, 0x00,
1249 0xFF, 0xFF, 0xFF, 0x00,
1250 0xFF, 0xFF, 0xFF, 0x00,
1251 0x47, 0x48, 0x37, 0x00,
1252 0x7A, 0x5E, 0x55, 0x00,
1253 0xDF, 0xD0, 0xAB, 0x00,
1254 0xFF, 0xFB, 0xF9, 0x00,
1255 0xE8, 0xCA, 0xC5, 0x00,
1256 0x8A, 0x7C, 0x77, 0x00,
1257 0x00, 0x00, 0x00, 0x00
1258 ];
1259 const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1260 0xFF, 0xFF, 0xFF, 0x00,
1261 0xFF, 0xFF, 0xCC, 0x00,
1262 0xFF, 0xFF, 0x99, 0x00,
1263 0xFF, 0xFF, 0x66, 0x00,
1264 0xFF, 0xFF, 0x33, 0x00,
1265 0xFF, 0xFF, 0x00, 0x00,
1266 0xFF, 0xCC, 0xFF, 0x00,
1267 0xFF, 0xCC, 0xCC, 0x00,
1268 0xFF, 0xCC, 0x99, 0x00,
1269 0xFF, 0xCC, 0x66, 0x00,
1270 0xFF, 0xCC, 0x33, 0x00,
1271 0xFF, 0xCC, 0x00, 0x00,
1272 0xFF, 0x99, 0xFF, 0x00,
1273 0xFF, 0x99, 0xCC, 0x00,
1274 0xFF, 0x99, 0x99, 0x00,
1275 0xFF, 0x99, 0x66, 0x00,
1276 0xFF, 0x99, 0x33, 0x00,
1277 0xFF, 0x99, 0x00, 0x00,
1278 0xFF, 0x66, 0xFF, 0x00,
1279 0xFF, 0x66, 0xCC, 0x00,
1280 0xFF, 0x66, 0x99, 0x00,
1281 0xFF, 0x66, 0x66, 0x00,
1282 0xFF, 0x66, 0x33, 0x00,
1283 0xFF, 0x66, 0x00, 0x00,
1284 0xFF, 0x33, 0xFF, 0x00,
1285 0xFF, 0x33, 0xCC, 0x00,
1286 0xFF, 0x33, 0x99, 0x00,
1287 0xFF, 0x33, 0x66, 0x00,
1288 0xFF, 0x33, 0x33, 0x00,
1289 0xFF, 0x33, 0x00, 0x00,
1290 0xFF, 0x00, 0xFF, 0x00,
1291 0xFF, 0x00, 0xCC, 0x00,
1292 0xFF, 0x00, 0x99, 0x00,
1293 0xFF, 0x00, 0x66, 0x00,
1294 0xFF, 0x00, 0x33, 0x00,
1295 0xFF, 0x00, 0x00, 0x00,
1296 0xCC, 0xFF, 0xFF, 0x00,
1297 0xCC, 0xFF, 0xCC, 0x00,
1298 0xCC, 0xFF, 0x99, 0x00,
1299 0xCC, 0xFF, 0x66, 0x00,
1300 0xCC, 0xFF, 0x33, 0x00,
1301 0xCC, 0xFF, 0x00, 0x00,
1302 0xCC, 0xCC, 0xFF, 0x00,
1303 0xCC, 0xCC, 0xCC, 0x00,
1304 0xCC, 0xCC, 0x99, 0x00,
1305 0xCC, 0xCC, 0x66, 0x00,
1306 0xCC, 0xCC, 0x33, 0x00,
1307 0xCC, 0xCC, 0x00, 0x00,
1308 0xCC, 0x99, 0xFF, 0x00,
1309 0xCC, 0x99, 0xCC, 0x00,
1310 0xCC, 0x99, 0x99, 0x00,
1311 0xCC, 0x99, 0x66, 0x00,
1312 0xCC, 0x99, 0x33, 0x00,
1313 0xCC, 0x99, 0x00, 0x00,
1314 0xCC, 0x66, 0xFF, 0x00,
1315 0xCC, 0x66, 0xCC, 0x00,
1316 0xCC, 0x66, 0x99, 0x00,
1317 0xCC, 0x66, 0x66, 0x00,
1318 0xCC, 0x66, 0x33, 0x00,
1319 0xCC, 0x66, 0x00, 0x00,
1320 0xCC, 0x33, 0xFF, 0x00,
1321 0xCC, 0x33, 0xCC, 0x00,
1322 0xCC, 0x33, 0x99, 0x00,
1323 0xCC, 0x33, 0x66, 0x00,
1324 0xCC, 0x33, 0x33, 0x00,
1325 0xCC, 0x33, 0x00, 0x00,
1326 0xCC, 0x00, 0xFF, 0x00,
1327 0xCC, 0x00, 0xCC, 0x00,
1328 0xCC, 0x00, 0x99, 0x00,
1329 0xCC, 0x00, 0x66, 0x00,
1330 0xCC, 0x00, 0x33, 0x00,
1331 0xCC, 0x00, 0x00, 0x00,
1332 0x99, 0xFF, 0xFF, 0x00,
1333 0x99, 0xFF, 0xCC, 0x00,
1334 0x99, 0xFF, 0x99, 0x00,
1335 0x99, 0xFF, 0x66, 0x00,
1336 0x99, 0xFF, 0x33, 0x00,
1337 0x99, 0xFF, 0x00, 0x00,
1338 0x99, 0xCC, 0xFF, 0x00,
1339 0x99, 0xCC, 0xCC, 0x00,
1340 0x99, 0xCC, 0x99, 0x00,
1341 0x99, 0xCC, 0x66, 0x00,
1342 0x99, 0xCC, 0x33, 0x00,
1343 0x99, 0xCC, 0x00, 0x00,
1344 0x99, 0x99, 0xFF, 0x00,
1345 0x99, 0x99, 0xCC, 0x00,
1346 0x99, 0x99, 0x99, 0x00,
1347 0x99, 0x99, 0x66, 0x00,
1348 0x99, 0x99, 0x33, 0x00,
1349 0x99, 0x99, 0x00, 0x00,
1350 0x99, 0x66, 0xFF, 0x00,
1351 0x99, 0x66, 0xCC, 0x00,
1352 0x99, 0x66, 0x99, 0x00,
1353 0x99, 0x66, 0x66, 0x00,
1354 0x99, 0x66, 0x33, 0x00,
1355 0x99, 0x66, 0x00, 0x00,
1356 0x99, 0x33, 0xFF, 0x00,
1357 0x99, 0x33, 0xCC, 0x00,
1358 0x99, 0x33, 0x99, 0x00,
1359 0x99, 0x33, 0x66, 0x00,
1360 0x99, 0x33, 0x33, 0x00,
1361 0x99, 0x33, 0x00, 0x00,
1362 0x99, 0x00, 0xFF, 0x00,
1363 0x99, 0x00, 0xCC, 0x00,
1364 0x99, 0x00, 0x99, 0x00,
1365 0x99, 0x00, 0x66, 0x00,
1366 0x99, 0x00, 0x33, 0x00,
1367 0x99, 0x00, 0x00, 0x00,
1368 0x66, 0xFF, 0xFF, 0x00,
1369 0x66, 0xFF, 0xCC, 0x00,
1370 0x66, 0xFF, 0x99, 0x00,
1371 0x66, 0xFF, 0x66, 0x00,
1372 0x66, 0xFF, 0x33, 0x00,
1373 0x66, 0xFF, 0x00, 0x00,
1374 0x66, 0xCC, 0xFF, 0x00,
1375 0x66, 0xCC, 0xCC, 0x00,
1376 0x66, 0xCC, 0x99, 0x00,
1377 0x66, 0xCC, 0x66, 0x00,
1378 0x66, 0xCC, 0x33, 0x00,
1379 0x66, 0xCC, 0x00, 0x00,
1380 0x66, 0x99, 0xFF, 0x00,
1381 0x66, 0x99, 0xCC, 0x00,
1382 0x66, 0x99, 0x99, 0x00,
1383 0x66, 0x99, 0x66, 0x00,
1384 0x66, 0x99, 0x33, 0x00,
1385 0x66, 0x99, 0x00, 0x00,
1386 0x66, 0x66, 0xFF, 0x00,
1387 0x66, 0x66, 0xCC, 0x00,
1388 0x66, 0x66, 0x99, 0x00,
1389 0x66, 0x66, 0x66, 0x00,
1390 0x66, 0x66, 0x33, 0x00,
1391 0x66, 0x66, 0x00, 0x00,
1392 0x66, 0x33, 0xFF, 0x00,
1393 0x66, 0x33, 0xCC, 0x00,
1394 0x66, 0x33, 0x99, 0x00,
1395 0x66, 0x33, 0x66, 0x00,
1396 0x66, 0x33, 0x33, 0x00,
1397 0x66, 0x33, 0x00, 0x00,
1398 0x66, 0x00, 0xFF, 0x00,
1399 0x66, 0x00, 0xCC, 0x00,
1400 0x66, 0x00, 0x99, 0x00,
1401 0x66, 0x00, 0x66, 0x00,
1402 0x66, 0x00, 0x33, 0x00,
1403 0x66, 0x00, 0x00, 0x00,
1404 0x33, 0xFF, 0xFF, 0x00,
1405 0x33, 0xFF, 0xCC, 0x00,
1406 0x33, 0xFF, 0x99, 0x00,
1407 0x33, 0xFF, 0x66, 0x00,
1408 0x33, 0xFF, 0x33, 0x00,
1409 0x33, 0xFF, 0x00, 0x00,
1410 0x33, 0xCC, 0xFF, 0x00,
1411 0x33, 0xCC, 0xCC, 0x00,
1412 0x33, 0xCC, 0x99, 0x00,
1413 0x33, 0xCC, 0x66, 0x00,
1414 0x33, 0xCC, 0x33, 0x00,
1415 0x33, 0xCC, 0x00, 0x00,
1416 0x33, 0x99, 0xFF, 0x00,
1417 0x33, 0x99, 0xCC, 0x00,
1418 0x33, 0x99, 0x99, 0x00,
1419 0x33, 0x99, 0x66, 0x00,
1420 0x33, 0x99, 0x33, 0x00,
1421 0x33, 0x99, 0x00, 0x00,
1422 0x33, 0x66, 0xFF, 0x00,
1423 0x33, 0x66, 0xCC, 0x00,
1424 0x33, 0x66, 0x99, 0x00,
1425 0x33, 0x66, 0x66, 0x00,
1426 0x33, 0x66, 0x33, 0x00,
1427 0x33, 0x66, 0x00, 0x00,
1428 0x33, 0x33, 0xFF, 0x00,
1429 0x33, 0x33, 0xCC, 0x00,
1430 0x33, 0x33, 0x99, 0x00,
1431 0x33, 0x33, 0x66, 0x00,
1432 0x33, 0x33, 0x33, 0x00,
1433 0x33, 0x33, 0x00, 0x00,
1434 0x33, 0x00, 0xFF, 0x00,
1435 0x33, 0x00, 0xCC, 0x00,
1436 0x33, 0x00, 0x99, 0x00,
1437 0x33, 0x00, 0x66, 0x00,
1438 0x33, 0x00, 0x33, 0x00,
1439 0x33, 0x00, 0x00, 0x00,
1440 0x00, 0xFF, 0xFF, 0x00,
1441 0x00, 0xFF, 0xCC, 0x00,
1442 0x00, 0xFF, 0x99, 0x00,
1443 0x00, 0xFF, 0x66, 0x00,
1444 0x00, 0xFF, 0x33, 0x00,
1445 0x00, 0xFF, 0x00, 0x00,
1446 0x00, 0xCC, 0xFF, 0x00,
1447 0x00, 0xCC, 0xCC, 0x00,
1448 0x00, 0xCC, 0x99, 0x00,
1449 0x00, 0xCC, 0x66, 0x00,
1450 0x00, 0xCC, 0x33, 0x00,
1451 0x00, 0xCC, 0x00, 0x00,
1452 0x00, 0x99, 0xFF, 0x00,
1453 0x00, 0x99, 0xCC, 0x00,
1454 0x00, 0x99, 0x99, 0x00,
1455 0x00, 0x99, 0x66, 0x00,
1456 0x00, 0x99, 0x33, 0x00,
1457 0x00, 0x99, 0x00, 0x00,
1458 0x00, 0x66, 0xFF, 0x00,
1459 0x00, 0x66, 0xCC, 0x00,
1460 0x00, 0x66, 0x99, 0x00,
1461 0x00, 0x66, 0x66, 0x00,
1462 0x00, 0x66, 0x33, 0x00,
1463 0x00, 0x66, 0x00, 0x00,
1464 0x00, 0x33, 0xFF, 0x00,
1465 0x00, 0x33, 0xCC, 0x00,
1466 0x00, 0x33, 0x99, 0x00,
1467 0x00, 0x33, 0x66, 0x00,
1468 0x00, 0x33, 0x33, 0x00,
1469 0x00, 0x33, 0x00, 0x00,
1470 0x00, 0x00, 0xFF, 0x00,
1471 0x00, 0x00, 0xCC, 0x00,
1472 0x00, 0x00, 0x99, 0x00,
1473 0x00, 0x00, 0x66, 0x00,
1474 0x00, 0x00, 0x33, 0x00,
1475 0xEE, 0x00, 0x00, 0x00,
1476 0xDD, 0x00, 0x00, 0x00,
1477 0xBB, 0x00, 0x00, 0x00,
1478 0xAA, 0x00, 0x00, 0x00,
1479 0x88, 0x00, 0x00, 0x00,
1480 0x77, 0x00, 0x00, 0x00,
1481 0x55, 0x00, 0x00, 0x00,
1482 0x44, 0x00, 0x00, 0x00,
1483 0x22, 0x00, 0x00, 0x00,
1484 0x11, 0x00, 0x00, 0x00,
1485 0x00, 0xEE, 0x00, 0x00,
1486 0x00, 0xDD, 0x00, 0x00,
1487 0x00, 0xBB, 0x00, 0x00,
1488 0x00, 0xAA, 0x00, 0x00,
1489 0x00, 0x88, 0x00, 0x00,
1490 0x00, 0x77, 0x00, 0x00,
1491 0x00, 0x55, 0x00, 0x00,
1492 0x00, 0x44, 0x00, 0x00,
1493 0x00, 0x22, 0x00, 0x00,
1494 0x00, 0x11, 0x00, 0x00,
1495 0x00, 0x00, 0xEE, 0x00,
1496 0x00, 0x00, 0xDD, 0x00,
1497 0x00, 0x00, 0xBB, 0x00,
1498 0x00, 0x00, 0xAA, 0x00,
1499 0x00, 0x00, 0x88, 0x00,
1500 0x00, 0x00, 0x77, 0x00,
1501 0x00, 0x00, 0x55, 0x00,
1502 0x00, 0x00, 0x44, 0x00,
1503 0x00, 0x00, 0x22, 0x00,
1504 0x00, 0x00, 0x11, 0x00,
1505 0xEE, 0xEE, 0xEE, 0x00,
1506 0xDD, 0xDD, 0xDD, 0x00,
1507 0xBB, 0xBB, 0xBB, 0x00,
1508 0xAA, 0xAA, 0xAA, 0x00,
1509 0x88, 0x88, 0x88, 0x00,
1510 0x77, 0x77, 0x77, 0x00,
1511 0x55, 0x55, 0x55, 0x00,
1512 0x44, 0x44, 0x44, 0x00,
1513 0x22, 0x22, 0x22, 0x00,
1514 0x11, 0x11, 0x11, 0x00,
1515 0x00, 0x00, 0x00, 0x00
1516 ];
1517
1518 #[cfg(test)]
1519 mod test {
1520 use super::*;
1521 use std::fs::File;
1522
1523 #[test]
1524 fn test_mov_demux() {
1525 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1526 let mut fr = FileReader::new_read(&mut file);
1527 let mut br = ByteReader::new(&mut fr);
1528 let mut dmx = MOVDemuxer::new(&mut br);
1529 let mut sm = StreamManager::new();
1530 let mut si = SeekIndex::new();
1531 dmx.open(&mut sm, &mut si).unwrap();
1532
1533 loop {
1534 let pktres = dmx.get_frame(&mut sm);
1535 if let Err(e) = pktres {
1536 if e == DemuxerError::EOF { break; }
1537 panic!("error");
1538 }
1539 let pkt = pktres.unwrap();
1540 println!("Got {}", pkt);
1541 }
1542 }
1543 }