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