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