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