mov: parse stts chunk and fix seeking
[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);
237cc1f9 242
fbf1f900
KS
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)?;
a480a0de 295 let duration = br.read_u32be()?;
58309c73
KS
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;
a480a0de 307 track.duration = duration;
58309c73
KS
308
309 track.tkhd_found = true;
310 Ok(KNOWN_TKHD_SIZE)
311}
312
313fn read_mdia(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
314 track.stream_type = StreamType::None;
315 track.read_mdia(br, size)?;
316 Ok(size)
317}
318
319const MDIA_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
320 TrackChunkHandler { ctype: mktag!(b"mdhd"), parse: skip_chunk },
321 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: read_hdlr },
322 TrackChunkHandler { ctype: mktag!(b"minf"), parse: read_minf },
323];
324
325fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
326 const KNOWN_HDLR_SIZE: u64 = 24;
327 validate!(size >= KNOWN_HDLR_SIZE);
328 let version = br.read_byte()?;
329 validate!(version == 0);
330 let flags = br.read_u24be()?;
331 validate!(flags == 0);
332 let comp_type = br.read_u32be()?;
333 let comp_subtype = br.read_u32be()?;
334 let _comp_manufacturer = br.read_u32be()?;
335 let _comp_flags = br.read_u32be()?;
336 let _comp_flags_mask = br.read_u32be()?;
337
338 if comp_type == mktag!(b"mhlr") {
339 if comp_subtype == mktag!(b"vide") {
340 track.stream_type = StreamType::Video;
341 } else if comp_subtype == mktag!(b"soun") {
342 track.stream_type = StreamType::Audio;
343 } else {
344 track.stream_type = StreamType::Data;
345 }
346 } else if comp_type == mktag!(b"dhlr") {
347 track.stream_type = StreamType::Data;
348 } else {
349 println!("Unknown stream type");
350 track.stream_type = StreamType::Data;
351 }
c8db9313 352
58309c73
KS
353 Ok(KNOWN_HDLR_SIZE)
354}
355
356fn read_minf(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
357 track.read_minf(br, size)?;
358 Ok(size)
359}
360
361const MINF_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
362 TrackChunkHandler { ctype: mktag!(b"hdlr"), parse: skip_chunk },
363 TrackChunkHandler { ctype: mktag!(b"dinf"), parse: skip_chunk },
364 TrackChunkHandler { ctype: mktag!(b"vmhd"), parse: read_vmhd },
365 TrackChunkHandler { ctype: mktag!(b"smhd"), parse: read_smhd },
366 TrackChunkHandler { ctype: mktag!(b"gmhd"), parse: read_gmhd },
367 TrackChunkHandler { ctype: mktag!(b"gmin"), parse: read_gmin },
368 TrackChunkHandler { ctype: mktag!(b"stbl"), parse: read_stbl },
369];
370
371fn read_vmhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
372 const KNOWN_VMHD_SIZE: u64 = 12;
373 validate!(track.stream_type == StreamType::Video);
374 validate!(size >= KNOWN_VMHD_SIZE);
375 let version = br.read_byte()?;
376 validate!(version == 0);
377 let _flags = br.read_u24be()?;
378 br.read_skip(2)?; // graphics mode
379 br.read_skip(6)?; // opcolor
380 Ok(KNOWN_VMHD_SIZE)
381}
382
383fn read_smhd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
384 const KNOWN_SMHD_SIZE: u64 = 8;
385 validate!(track.stream_type == StreamType::Audio);
386 validate!(size >= KNOWN_SMHD_SIZE);
387 let version = br.read_byte()?;
388 validate!(version == 0);
389 let _flags = br.read_u24be()?;
390 br.read_skip(2)?; // balance
391 br.read_skip(2)?;
392 Ok(KNOWN_SMHD_SIZE)
393}
394
395fn read_gmhd(track: &mut Track, _br: &mut ByteReader, _size: u64) -> DemuxerResult<u64> {
396 validate!(track.stream_type == StreamType::Data);
397 Ok(0)
398}
399
400fn read_gmin(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
401 validate!(track.stream_type == StreamType::Data);
402 const KNOWN_GMIN_SIZE: u64 = 16;
403 validate!(size >= KNOWN_GMIN_SIZE);
404 let version = br.read_byte()?;
405 validate!(version == 0);
406 let _flags = br.read_u24be()?;
407 br.read_skip(2)?; // graphics mode
408 br.read_skip(6)?; // opcolor
409 br.read_skip(2)?; // balance
410 br.read_skip(2)?;
411 Ok(KNOWN_GMIN_SIZE)
412}
413
414fn read_stbl(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
415 track.read_stbl(br, size)?;
416 Ok(size)
417}
418
419const STBL_CHUNK_HANDLERS: &[TrackChunkHandler] = &[
420 TrackChunkHandler { ctype: mktag!(b"stsd"), parse: read_stsd },
bbbf86dd 421 TrackChunkHandler { ctype: mktag!(b"stts"), parse: read_stts },
58309c73
KS
422 TrackChunkHandler { ctype: mktag!(b"stss"), parse: read_stss },
423 TrackChunkHandler { ctype: mktag!(b"stsc"), parse: read_stsc },
424 TrackChunkHandler { ctype: mktag!(b"stsz"), parse: read_stsz },
425 TrackChunkHandler { ctype: mktag!(b"stco"), parse: read_stco },
426 TrackChunkHandler { ctype: mktag!(b"stsh"), parse: skip_chunk },
427];
428
89b16ac8
KS
429fn parse_audio_edata(br: &mut ByteReader, start_pos: u64, size: u64) -> DemuxerResult<Option<Vec<u8>>> {
430 let read_part = br.tell() - start_pos;
431 if read_part + 8 < size {
9aa783a0
KS
432 let mut buf = [0; 8];
433 br.peek_buf(&mut buf)?;
434 if &buf[4..8] != b"wave" {
435 let mut buf = vec![0; (size - read_part) as usize];
436 br.read_buf(&mut buf)?;
437 return Ok(Some(buf));
438 }
439
89b16ac8
KS
440 let csize = br.read_u32be()? as u64;
441 let ctag = br.read_u32be()?;
442 validate!(read_part + csize <= size);
443 validate!(ctag == mktag!(b"wave"));
444 if csize == 8 {
445 return Ok(None);
446 }
447 let mut buf = [0; 8];
448 br.peek_buf(&mut buf)?;
449 if &buf[4..8] == b"frma" {
450 br.read_skip(12)?;
451 if csize > 20 {
452 let mut buf = vec![0; (csize - 20) as usize];
453 br.read_buf(&mut buf)?;
454 Ok(Some(buf))
455 } else {
456 Ok(None)
457 }
458 } else if csize > 8 {
459 let mut buf = vec![0; (csize as usize) - 8];
460 br.read_buf(&mut buf)?;
461 Ok(Some(buf))
462 } else {
463 Ok(None)
464 }
465 } else {
466 Ok(None)
467 }
468}
469
58309c73
KS
470fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
471 const KNOWN_STSD_SIZE: u64 = 24;
472 validate!(size >= KNOWN_STSD_SIZE);
473 let start_pos = br.tell();
474 let version = br.read_byte()?;
475 validate!(version == 0);
476 let _flags = br.read_u24be()?;
477 let entries = br.read_u32be()?;
478 validate!(entries > 0);
61cab15b 479 let esize = u64::from(br.read_u32be()?);
58309c73
KS
480 validate!(esize + 8 <= size);
481 let mut fcc = [0u8; 4];
482 br.read_buf(&mut fcc)?;
483 br.read_skip(6)?;
484 let _data_ref = br.read_u16be()?;
485
486 track.fcc = fcc;
487
488 let codec_info;
489 match track.stream_type {
490 StreamType::Video => {
491 let _ver = br.read_u16be()?;
492 let _revision = br.read_u16le()?;
493 let _vendor = br.read_u32be()?;
494 let _temp_quality = br.read_u32be()?;
495 let _spat_quality = br.read_u32be()?;
496 let width = br.read_u16be()? as usize;
497 let height = br.read_u16be()? as usize;
498 let _hor_res = br.read_u32be()?;
499 let _vert_res = br.read_u32be()?;
500 let data_size = br.read_u32be()?;
501 validate!(data_size == 0);
502 let _frame_count = br.read_u16be()? as usize;
503 let _cname_len = br.read_byte()? as usize;
504 br.read_skip(31)?; // actual compressor name
505 let depth = br.read_u16be()?;
506 let ctable_id = br.read_u16be()?;
8019c866
KS
507 let grayscale = depth > 0x20 || depth == 1;
508 let depth = if grayscale { depth & 0x1F } else { depth };
509 validate!(depth <= 8 || (ctable_id == 0xFFFF));
58309c73 510 if ctable_id == 0 {
00333698 511 let max_pal_size = start_pos + size - br.tell();
58cd51fa
KS
512 let mut pal = [0; 1024];
513 read_palette(br, max_pal_size, &mut pal)?;
514 track.pal = Some(Arc::new(pal));
8019c866 515 } else if (depth <= 8) && !grayscale {
2736c15a
KS
516 match depth & 0x1F {
517 2 => {
518 let mut pal = [0; 1024];
519 (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT);
520 track.pal = Some(Arc::new(pal));
521 },
522 4 => {
523 let mut pal = [0; 1024];
524 (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT);
525 track.pal = Some(Arc::new(pal));
526 },
527 8 => {
528 track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT));
529 },
530 _ => {},
531 };
2949bcfa 532 } else if grayscale && ctable_id != 0xFFFF {
2736c15a
KS
533 let mut pal = [0; 1024];
534 let cdepth = depth & 0x1F;
535 let size = 1 << cdepth;
536 for i in 0..size {
8019c866 537 let mut clr = ((size - 1 - i) as u8) << (8 - cdepth);
2736c15a
KS
538 let mut off = 8 - cdepth;
539 while off >= cdepth {
540 clr |= clr >> (8 - off);
541 off -= cdepth;
542 }
543 if off > 0 {
544 clr |= clr >> (8 - off);
545 }
546 pal[i * 4] = clr;
547 pal[i * 4 + 1] = clr;
548 pal[i * 4 + 2] = clr;
549 }
550 track.pal = Some(Arc::new(pal));
58309c73
KS
551 }
552// todo other atoms, put as extradata
553 let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
554 name
555 } else if let Some(name) = find_codec_from_avi_fourcc(&fcc) {
556 name
557 } else {
558 "unknown"
559 };
560 let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT };
8019c866
KS
561 let mut vhdr = NAVideoInfo::new(width, height, false, format);
562 vhdr.bits = depth as u8;
61cab15b 563 let edata = if br.tell() - start_pos + 4 < size {
58309c73 564//todo skip various common atoms
61cab15b 565 let edata_size = br.read_u32be()? as usize;
d341f57a
KS
566 validate!(edata_size >= 4);
567 let mut buf = vec![0; edata_size - 4];
58309c73 568 br.read_buf(buf.as_mut_slice())?;
61cab15b
KS
569 Some(buf)
570 } else {
571 None
572 };
58309c73
KS
573 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Video(vhdr), edata);
574 },
575 StreamType::Audio => {
89b16ac8 576 let sver = br.read_u16be()?;
58309c73
KS
577 let _revision = br.read_u16le()?;
578 let _vendor = br.read_u32be()?;
579 let nchannels = br.read_u16be()?;
580 validate!(nchannels <= 64);
581 let sample_size = br.read_u16be()?;
582 validate!(sample_size <= 128);
583 let _compr_id = br.read_u16be()?;
584 let packet_size = br.read_u16be()? as usize;
585 validate!(packet_size == 0);
586 let sample_rate = br.read_u32be()?;
587 validate!(sample_rate > 0);
588 let cname = if let Some(name) = find_codec_from_mov_audio_fourcc(&fcc) {
589 name
590 } else if let (true, Some(name)) = ((fcc[0] == b'm' && fcc[1] == b's'), find_codec_from_wav_twocc(u16::from(fcc[2]) * 256 + u16::from(fcc[3]))) {
591 name
592 } else {
593 "unknown"
594 };
595//todo adjust format for various PCM kinds
596 let soniton = NASoniton::new(sample_size as u8, SONITON_FLAG_SIGNED | SONITON_FLAG_BE);
597 let block_align = 1;
89b16ac8 598 if sver == 1 {
b0e12d42 599 let samples_per_packet = br.read_u32be()?;
89b16ac8 600 let _bytes_per_packet = br.read_u32be()?;
9efec4ed 601 let bytes_per_frame = br.read_u32be()?;
89b16ac8 602 let _bytes_per_sample = br.read_u32be()?;
9efec4ed 603 track.bsize = bytes_per_frame as usize;
b0e12d42 604 track.frame_samples = samples_per_packet as usize;
9efec4ed
KS
605 } else {
606 track.bsize = sample_size as usize;
89b16ac8 607 }
58309c73 608 let ahdr = NAAudioInfo::new(sample_rate >> 16, nchannels as u8, soniton, block_align);
89b16ac8 609 let edata = parse_audio_edata(br, start_pos, size)?;
58309c73
KS
610 codec_info = NACodecInfo::new(cname, NACodecTypeInfo::Audio(ahdr), edata);
611 track.channels = nchannels as usize;
612 track.bits = sample_size as usize;
613 },
614 StreamType::None => {
615 return Err(DemuxerError::InvalidData);
616 },
617 _ => {
618//todo put it all into extradata
619 let edata = None;
620 codec_info = NACodecInfo::new("unknown", NACodecTypeInfo::None, edata);
621 },
622 };
623 let read_size = br.tell() - start_pos;
624 validate!(read_size <= size);
a480a0de 625 track.stream = Some(NAStream::new(track.stream_type, track.track_no, codec_info, 1, track.tb_den, u64::from(track.duration)));
58309c73
KS
626 track.stsd_found = true;
627 Ok(read_size)
628}
629
bbbf86dd
KS
630fn read_stts(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
631 validate!(size >= 16);
632 let start_pos = br.tell();
633 let version = br.read_byte()?;
634 validate!(version == 0);
635 let _flags = br.read_u24be()?;
636 let entries = br.read_u32be()? as usize;
637 validate!(entries as u64 <= (size - 8) / 8);
638 if entries == 1 {
639 let _count = br.read_u32be()?;
640 let tb_num = br.read_u32be()?;
641 if let Some(ref mut stream) = track.stream {
642 let tb_den = stream.tb_den;
643 let (tb_num, tb_den) = reduce_timebase(tb_num, tb_den);
644 stream.duration /= u64::from(stream.tb_den / tb_den);
645 stream.tb_num = tb_num;
646 stream.tb_den = tb_den;
647 track.tb_num = tb_num;
648 track.tb_den = tb_den;
649 }
650 } else {
651 track.time_to_sample.truncate(0);
652 track.time_to_sample.reserve(entries);
653 for _ in 0..entries {
654 let count = br.read_u32be()?;
655 let mult = br.read_u32be()?;
656 track.time_to_sample.push((count, mult));
657 }
658 }
659 let read_size = br.tell() - start_pos;
660 validate!(read_size <= size);
661 Ok(read_size)
662}
663
58309c73
KS
664fn read_stss(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
665 let version = br.read_byte()?;
666 validate!(version == 0);
667 let _flags = br.read_u24be()?;
668 let entries = br.read_u32be()? as usize;
669 validate!(entries < ((std::u32::MAX >> 2) - 8) as usize);
670 validate!((entries * 4 + 8) as u64 == size);
671 track.keyframes = Vec::with_capacity(entries);
672 let mut last_sample_no = 0;
673 for _ in 0..entries {
674 let sample_no = br.read_u32be()?;
675 validate!(sample_no > last_sample_no);
676 track.keyframes.push(sample_no);
677 last_sample_no = sample_no;
678 }
679 Ok(size)
680}
681
682fn read_stsc(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
683 let version = br.read_byte()?;
684 validate!(version == 0);
685 let _flags = br.read_u24be()?;
686 let entries = br.read_u32be()? as usize;
687 validate!(entries < ((std::u32::MAX / 12) - 8) as usize);
688 validate!((entries * 12 + 8) as u64 == size);
689 track.sample_map = Vec::with_capacity(entries);
690 let mut last_sample_no = 0;
691 for _i in 0..entries {
692 let sample_no = br.read_u32be()?;
693 validate!(sample_no > last_sample_no);
694 let nsamples = br.read_u32be()?;
695 let _sample_desc = br.read_u32be()?;
696 track.sample_map.push((sample_no, nsamples));
697 last_sample_no = sample_no;
698 }
699 Ok(size)
700}
701
702fn read_stsz(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
703 let version = br.read_byte()?;
704 validate!(version == 0);
705 let _flags = br.read_u24be()?;
706 let sample_size = br.read_u32be()?;
707 if sample_size != 0 {
708 track.sample_size = sample_size;
9efec4ed
KS
709 if track.sample_size != 1 || track.bsize == 0 {
710 track.bsize = sample_size as usize;
711 }
58309c73
KS
712 Ok(8)
713 } else {
714 let entries = br.read_u32be()? as usize;
715 validate!((entries * 4 + 12) as u64 == size);
716 track.chunk_sizes = Vec::with_capacity(entries);
717 for _ in 0..entries {
718 let sample_size = br.read_u32be()?;
719 track.chunk_sizes.push(sample_size);
720 }
721 Ok(size)
722 }
723}
724
725fn read_stco(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult<u64> {
726 let version = br.read_byte()?;
727 validate!(version == 0);
728 let _flags = br.read_u24be()?;
729 let entries = br.read_u32be()? as usize;
730 validate!((entries * 4 + 8) as u64 == size);
731 track.chunk_offsets = Vec::with_capacity(entries);
732 for _i in 0..entries {
733 let sample_offset = br.read_u32be()?;
734 track.chunk_offsets.push(u64::from(sample_offset));
735 }
736 Ok(size)
737}
738
739struct MOVDemuxer<'a> {
740 src: &'a mut ByteReader<'a>,
741 depth: usize,
742 mdat_pos: u64,
743 mdat_size: u64,
744 tracks: Vec<Track>,
745 cur_track: usize,
746 tb_den: u32,
747 duration: u32,
58cd51fa 748 pal: Option<Arc<[u8; 1024]>>,
58309c73
KS
749}
750
751struct Track {
752 track_id: u32,
753 track_str_id: usize,
754 track_no: u32,
bbbf86dd 755 tb_num: u32,
58309c73 756 tb_den: u32,
a480a0de 757 duration: u32,
58309c73
KS
758 depth: u8,
759 tkhd_found: bool,
760 stsd_found: bool,
761 stream_type: StreamType,
762 width: usize,
763 height: usize,
764 channels: usize,
765 bits: usize,
9efec4ed 766 bsize: usize,
58309c73
KS
767 fcc: [u8; 4],
768 keyframes: Vec<u32>,
769 chunk_sizes: Vec<u32>,
770 chunk_offsets: Vec<u64>,
bbbf86dd 771 time_to_sample: Vec<(u32, u32)>,
58309c73
KS
772 sample_map: Vec<(u32, u32)>,
773 sample_size: u32,
b0e12d42 774 frame_samples: usize,
58309c73
KS
775 stream: Option<NAStream>,
776 cur_chunk: usize,
777 cur_sample: usize,
778 samples_left: usize,
779 last_offset: u64,
58cd51fa 780 pal: Option<Arc<[u8; 1024]>>,
bbbf86dd
KS
781 timesearch: TimeSearcher,
782}
783
784#[derive(Default)]
785struct TimeSearcher {
786 idx: usize,
787 base: u64,
788 sbase: u32,
789 cur_len: u32,
790 cur_mul: u32,
791}
792
793impl TimeSearcher {
794 fn new() -> Self { Self::default() }
795 fn reset(&mut self) {
796 *self = Self::default();
797 }
798 fn map_time(&mut self, sample: u32, tts: &Vec<(u32, u32)>) -> u64 {
799 if tts.is_empty() {
800 u64::from(sample)
801 } else if sample >= self.sbase {
802 let mut sample = sample - self.sbase;
803 if self.idx == 0 {
804 let (cur_len, cur_mul) = tts[0];
805 self.cur_len = cur_len;
806 self.cur_mul = cur_mul;
807 self.idx += 1;
808 }
809 while self.idx < tts.len() && sample > self.cur_len {
810 sample -= self.cur_len;
811 self.sbase += self.cur_len;
812 self.base += u64::from(self.cur_len) * u64::from(self.cur_mul);
813 self.cur_len = tts[self.idx].0;
814 self.cur_mul = tts[self.idx].1;
815 self.idx += 1;
816 }
817 self.base + u64::from(sample) * u64::from(self.cur_mul)
818 } else {
819 self.reset();
820 self.map_time(sample, tts)
821 }
822 }
58309c73
KS
823}
824
825impl Track {
826 fn new(track_no: u32, tb_den: u32) -> Self {
827 Self {
828 tkhd_found: false,
829 stsd_found: false,
830 track_id: 0,
831 track_str_id: 0,
832 track_no,
bbbf86dd 833 tb_num: 1,
58309c73 834 tb_den,
a480a0de 835 duration: 0,
58309c73
KS
836 stream_type: StreamType::None,
837 width: 0,
838 height: 0,
839 channels: 0,
840 bits: 0,
9efec4ed 841 bsize: 0,
58309c73
KS
842 fcc: [0; 4],
843 keyframes: Vec::new(),
844 chunk_sizes: Vec::new(),
845 chunk_offsets: Vec::new(),
bbbf86dd 846 time_to_sample: Vec::new(),
58309c73
KS
847 sample_map: Vec::new(),
848 sample_size: 0,
b0e12d42 849 frame_samples: 0,
58309c73
KS
850 stream: None,
851 depth: 0,
852 cur_chunk: 0,
853 cur_sample: 0,
854 samples_left: 0,
855 last_offset: 0,
58cd51fa 856 pal: None,
bbbf86dd 857 timesearch: TimeSearcher::new(),
58309c73
KS
858 }
859 }
860 read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
861 read_chunk_list!(track; "mdia", read_mdia, MDIA_CHUNK_HANDLERS);
862 read_chunk_list!(track; "minf", read_minf, MINF_CHUNK_HANDLERS);
863 read_chunk_list!(track; "stbl", read_stbl, STBL_CHUNK_HANDLERS);
864 fn fill_seek_index(&self, seek_index: &mut SeekIndex) {
61cab15b 865 if !self.keyframes.is_empty() {
58309c73
KS
866 seek_index.mode = SeekIndexMode::Present;
867 }
bbbf86dd 868 let mut tsearch = TimeSearcher::new();
58309c73 869 for kf_time in self.keyframes.iter() {
bbbf86dd
KS
870 let pts = tsearch.map_time(*kf_time - 1, &self.time_to_sample);
871 let time = NATimeInfo::ts_to_time(pts, 1000, self.tb_num, self.tb_den);
872 seek_index.add_entry(self.track_no as u32, SeekEntry { time, pts: u64::from(*kf_time - 1), pos: 0 });
58309c73
KS
873 }
874 }
875 fn calculate_chunk_size(&self, nsamp: usize) -> usize {
876 if nsamp == 0 {
9efec4ed 877 self.bsize
58309c73
KS
878 } else {
879 match &self.fcc {
880 b"NONE" | b"raw " | b"twos" | b"sowt" => {
881 (nsamp * self.bits * self.channels + 7) >> 3
882 },
883 b"ima4" => {
884 let nblocks = (nsamp + 63) >> 6;
885 nblocks * 34 * self.channels
886 },
887 b"MAC3" => {
888 (nsamp + 5) / 6 * 2 * self.channels
889 },
890 b"MAC6" => {
891 (nsamp + 5) / 6 * self.channels
892 },
893 b"in24" => nsamp * 3 * self.channels,
894 b"in32" | b"fl32" => nsamp * 4 * self.channels,
895 b"fl64" => nsamp * 8 * self.channels,
896 b"ulaw" | b"alaw" => nsamp,
897 b"ms\x00\x02" => { //MS ADPCM
898 ((nsamp - 1) / 2 + 7) * self.channels
899 },
900 b"ms\x00\x21" => { //IMA ADPCM
901 (nsamp / 2 + 4) * self.channels
902 },
9efec4ed 903 _ => self.bsize,
58309c73
KS
904 }
905 }
906 }
907 fn get_next_chunk(&mut self) -> Option<(NATimeInfo, u64, usize)> {
bbbf86dd
KS
908 let pts_val = self.timesearch.map_time(self.cur_sample as u32, &self.time_to_sample);
909 let pts = NATimeInfo::new(Some(pts_val), None, None, 1, self.tb_den);
58309c73
KS
910//todo dts decoding
911 if self.chunk_offsets.len() == self.chunk_sizes.len() { // simple one-to-one mapping
912 if self.cur_sample >= self.chunk_sizes.len() {
913 return None;
914 }
915 let offset = self.chunk_offsets[self.cur_sample];
916 let size = self.chunk_sizes[self.cur_sample] as usize;
917 self.cur_sample += 1;
918 Some((pts, offset, size))
919 } else {
920 if self.samples_left == 0 {
921 if self.cur_chunk >= self.chunk_offsets.len() {
922 return None;
923 }
924 for (idx, samples) in self.sample_map.iter() {
925 if *idx as usize <= self.cur_chunk + 1 {
926 self.samples_left = *samples as usize;
927 } else {
928 break;
929 }
930 }
931 self.last_offset = self.chunk_offsets[self.cur_chunk];
932 self.cur_chunk += 1;
933 }
934 let offset = self.last_offset;
935 let size = self.get_size(self.cur_sample);
936 self.last_offset += size as u64;
937 if self.stream_type == StreamType::Video {
938 self.samples_left -= 1;
d940f0c2
KS
939 } else if self.frame_samples != 0 && self.bsize != 0 {
940 let nblocks = size / self.bsize;
941 if nblocks > 0 {
942 let consumed = (nblocks * self.frame_samples).min(self.samples_left);
943 self.samples_left -= consumed;
944 } else {
945 self.samples_left = 0;
946 }
58309c73
KS
947 } else {
948 self.samples_left = 0;
949 }
950 self.cur_sample += 1;
951 Some((pts, offset, size))
952 }
953 }
954 fn get_size(&self, sample_no: usize) -> usize {
61cab15b 955 if !self.chunk_sizes.is_empty() {
58309c73 956 self.chunk_sizes[sample_no] as usize
61cab15b 957 } else if !self.sample_map.is_empty() {
58309c73
KS
958 let mut nsamp = 0;
959 for (idx, samples) in self.sample_map.iter() {
960 if *idx as usize <= self.cur_chunk {
961 nsamp = *samples;
962 } else {
963 break;
964 }
965 }
966 self.calculate_chunk_size(nsamp as usize)
967 } else {
9efec4ed 968 self.bsize
58309c73
KS
969 }
970 }
971 fn seek(&mut self, pts: u64) {
972 self.cur_sample = pts as usize;
973 self.samples_left = 0;
974 if self.stream_type == StreamType::Audio {
975 self.cur_chunk = self.cur_sample;
61cab15b 976 } else if self.chunk_offsets.len() != self.chunk_sizes.len() && !self.sample_map.is_empty() {
58309c73
KS
977 let mut csamp = 0;
978 self.cur_chunk = 0;
979 let mut cmap = self.sample_map.iter();
980 let mut cur_samps = 0;
981 let (mut next_idx, mut next_samples) = cmap.next().unwrap();
982 loop {
bbbf86dd 983 if self.cur_chunk + 1 == next_idx as usize {
58309c73
KS
984 self.samples_left = cur_samps;
985 cur_samps = next_samples as usize;
986 if let Some((new_idx, new_samples)) = cmap.next() {
987 next_idx = *new_idx;
988 next_samples = *new_samples;
989 }
990 }
991 csamp += cur_samps;
992 if csamp >= self.cur_sample {
993 self.last_offset = self.chunk_offsets[self.cur_chunk];
994 break;
995 }
996 self.cur_chunk += 1;
997 }
998 csamp -= cur_samps;
bbbf86dd 999 for sample_no in csamp..self.cur_sample {
58309c73
KS
1000 self.last_offset += self.get_size(sample_no) as u64;
1001 }
bbbf86dd
KS
1002 self.samples_left = csamp + cur_samps - self.cur_sample;
1003 self.cur_chunk += 1;
58309c73
KS
1004 }
1005 }
1006}
1007
1008impl<'a> DemuxCore<'a> for MOVDemuxer<'a> {
1009 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
1010 self.read_root(strmgr)?;
1011 validate!(self.mdat_pos > 0);
61cab15b 1012 validate!(!self.tracks.is_empty());
58309c73
KS
1013 for track in self.tracks.iter() {
1014 track.fill_seek_index(seek_index);
1015 }
1016 self.src.seek(SeekFrom::Start(self.mdat_pos))?;
1017 self.cur_track = 0;
1018 Ok(())
1019 }
1020
1021 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
61cab15b 1022 if self.tracks.is_empty() {
58309c73
KS
1023 return Err(DemuxerError::EOF);
1024 }
1025 for _ in 0..self.tracks.len() {
1026 if self.cur_track >= self.tracks.len() {
1027 self.cur_track = 0;
1028 }
1029 let track = &mut self.tracks[self.cur_track];
1030 self.cur_track += 1;
58cd51fa 1031 let first = track.cur_sample == 0;
58309c73
KS
1032 if let Some((pts, offset, size)) = track.get_next_chunk() {
1033 let str = strmgr.get_stream(track.track_str_id);
1034 if str.is_none() { return Err(DemuxerError::InvalidData); }
1035 let stream = str.unwrap();
1036 self.src.seek(SeekFrom::Start(offset))?;
58cd51fa
KS
1037 let mut pkt = self.src.read_packet(stream, pts, false, size)?;
1038 if let Some(ref pal) = track.pal {
1039 let side_data = NASideData::Palette(first, pal.clone());
1040 pkt.add_side_data(side_data);
1041 }
58309c73
KS
1042 return Ok(pkt);
1043 }
1044 }
61cab15b 1045 Err(DemuxerError::EOF)
58309c73
KS
1046 }
1047
24d99894 1048 fn seek(&mut self, time: NATimePoint, seek_index: &SeekIndex) -> DemuxerResult<()> {
58309c73
KS
1049 let ret = seek_index.find_pos(time);
1050 if ret.is_none() {
1051 return Err(DemuxerError::SeekError);
1052 }
1053 let seek_info = ret.unwrap();
1054 for track in self.tracks.iter_mut() {
1055 track.seek(seek_info.pts);
1056 }
1057 Ok(())
1058 }
a480a0de
KS
1059 fn get_duration(&self) -> u64 {
1060 if self.tb_den != 0 {
1061 u64::from(self.duration) * 1000 / u64::from(self.tb_den)
1062 } else {
1063 0
1064 }
1065 }
58309c73
KS
1066}
1067
787b8d03
KS
1068impl<'a> NAOptionHandler for MOVDemuxer<'a> {
1069 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
1070 fn set_options(&mut self, _options: &[NAOption]) { }
1071 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
1072}
1073
58309c73
KS
1074impl<'a> MOVDemuxer<'a> {
1075 fn new(io: &'a mut ByteReader<'a>) -> Self {
1076 MOVDemuxer {
1077 src: io,
1078 depth: 0,
1079 mdat_pos: 0,
1080 mdat_size: 0,
1081 tracks: Vec::with_capacity(2),
1082 cur_track: 0,
1083 tb_den: 0,
1084 duration: 0,
58cd51fa 1085 pal: None,
58309c73
KS
1086 }
1087 }
1088 fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
1089 self.depth = 0;
1090 while self.src.left() != 0 {
1091 let ret = read_chunk_header(&mut self.src);
1092 if ret.is_err() { break; }
1093 let (ctype, size) = ret.unwrap();
1094 if IGNORED_CHUNKS.contains(&ctype) {
1095 self.src.skip64(size)?;
1096 continue;
1097 }
1098 let handler = ROOT_CHUNK_HANDLERS.iter().find(|x| x.ctype == ctype);
1099 let read_size;
1100 if let Some(ref handler) = handler {
1101 read_size = (handler.parse)(self, strmgr, size)?;
1102 } else {
1103 println!("skipping unknown chunk {:08X} size {}", ctype, size);
1104 read_size = 0;
1105 }
1106 validate!(read_size <= size);
1107 self.src.skip64(size - read_size)?;
1108 }
1109//todo check if all needed chunks are found
1110 Ok(())
1111 }
1112 read_chunk_list!(root; "moov", read_moov, MOOV_CHUNK_HANDLERS);
1113}
1114
1115pub struct MOVDemuxerCreator { }
1116
1117impl DemuxerCreator for MOVDemuxerCreator {
1118 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
1119 Box::new(MOVDemuxer::new(br))
1120 }
1121 fn get_name(&self) -> &'static str { "mov" }
1122}
1123
2736c15a
KS
1124const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [
1125 0x93, 0x65, 0x5E, 0x00,
1126 0xFF, 0xFF, 0xFF, 0x00,
1127 0xDF, 0xD0, 0xAB, 0x00,
1128 0x00, 0x00, 0x00, 0x00
1129];
1130const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [
1131 0xFF, 0xFB, 0xFF, 0x00,
1132 0xEF, 0xD9, 0xBB, 0x00,
1133 0xE8, 0xC9, 0xB1, 0x00,
1134 0x93, 0x65, 0x5E, 0x00,
1135 0xFC, 0xDE, 0xE8, 0x00,
1136 0x9D, 0x88, 0x91, 0x00,
1137 0xFF, 0xFF, 0xFF, 0x00,
1138 0xFF, 0xFF, 0xFF, 0x00,
1139 0xFF, 0xFF, 0xFF, 0x00,
1140 0x47, 0x48, 0x37, 0x00,
1141 0x7A, 0x5E, 0x55, 0x00,
1142 0xDF, 0xD0, 0xAB, 0x00,
1143 0xFF, 0xFB, 0xF9, 0x00,
1144 0xE8, 0xCA, 0xC5, 0x00,
1145 0x8A, 0x7C, 0x77, 0x00,
1146 0x00, 0x00, 0x00, 0x00
1147];
1148const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [
1149 0xFF, 0xFF, 0xFF, 0x00,
1150 0xFF, 0xFF, 0xCC, 0x00,
1151 0xFF, 0xFF, 0x99, 0x00,
1152 0xFF, 0xFF, 0x66, 0x00,
1153 0xFF, 0xFF, 0x33, 0x00,
1154 0xFF, 0xFF, 0x00, 0x00,
1155 0xFF, 0xCC, 0xFF, 0x00,
1156 0xFF, 0xCC, 0xCC, 0x00,
1157 0xFF, 0xCC, 0x99, 0x00,
1158 0xFF, 0xCC, 0x66, 0x00,
1159 0xFF, 0xCC, 0x33, 0x00,
1160 0xFF, 0xCC, 0x00, 0x00,
1161 0xFF, 0x99, 0xFF, 0x00,
1162 0xFF, 0x99, 0xCC, 0x00,
1163 0xFF, 0x99, 0x99, 0x00,
1164 0xFF, 0x99, 0x66, 0x00,
1165 0xFF, 0x99, 0x33, 0x00,
1166 0xFF, 0x99, 0x00, 0x00,
1167 0xFF, 0x66, 0xFF, 0x00,
1168 0xFF, 0x66, 0xCC, 0x00,
1169 0xFF, 0x66, 0x99, 0x00,
1170 0xFF, 0x66, 0x66, 0x00,
1171 0xFF, 0x66, 0x33, 0x00,
1172 0xFF, 0x66, 0x00, 0x00,
1173 0xFF, 0x33, 0xFF, 0x00,
1174 0xFF, 0x33, 0xCC, 0x00,
1175 0xFF, 0x33, 0x99, 0x00,
1176 0xFF, 0x33, 0x66, 0x00,
1177 0xFF, 0x33, 0x33, 0x00,
1178 0xFF, 0x33, 0x00, 0x00,
1179 0xFF, 0x00, 0xFF, 0x00,
1180 0xFF, 0x00, 0xCC, 0x00,
1181 0xFF, 0x00, 0x99, 0x00,
1182 0xFF, 0x00, 0x66, 0x00,
1183 0xFF, 0x00, 0x33, 0x00,
1184 0xFF, 0x00, 0x00, 0x00,
1185 0xCC, 0xFF, 0xFF, 0x00,
1186 0xCC, 0xFF, 0xCC, 0x00,
1187 0xCC, 0xFF, 0x99, 0x00,
1188 0xCC, 0xFF, 0x66, 0x00,
1189 0xCC, 0xFF, 0x33, 0x00,
1190 0xCC, 0xFF, 0x00, 0x00,
1191 0xCC, 0xCC, 0xFF, 0x00,
1192 0xCC, 0xCC, 0xCC, 0x00,
1193 0xCC, 0xCC, 0x99, 0x00,
1194 0xCC, 0xCC, 0x66, 0x00,
1195 0xCC, 0xCC, 0x33, 0x00,
1196 0xCC, 0xCC, 0x00, 0x00,
1197 0xCC, 0x99, 0xFF, 0x00,
1198 0xCC, 0x99, 0xCC, 0x00,
1199 0xCC, 0x99, 0x99, 0x00,
1200 0xCC, 0x99, 0x66, 0x00,
1201 0xCC, 0x99, 0x33, 0x00,
1202 0xCC, 0x99, 0x00, 0x00,
1203 0xCC, 0x66, 0xFF, 0x00,
1204 0xCC, 0x66, 0xCC, 0x00,
1205 0xCC, 0x66, 0x99, 0x00,
1206 0xCC, 0x66, 0x66, 0x00,
1207 0xCC, 0x66, 0x33, 0x00,
1208 0xCC, 0x66, 0x00, 0x00,
1209 0xCC, 0x33, 0xFF, 0x00,
1210 0xCC, 0x33, 0xCC, 0x00,
1211 0xCC, 0x33, 0x99, 0x00,
1212 0xCC, 0x33, 0x66, 0x00,
1213 0xCC, 0x33, 0x33, 0x00,
1214 0xCC, 0x33, 0x00, 0x00,
1215 0xCC, 0x00, 0xFF, 0x00,
1216 0xCC, 0x00, 0xCC, 0x00,
1217 0xCC, 0x00, 0x99, 0x00,
1218 0xCC, 0x00, 0x66, 0x00,
1219 0xCC, 0x00, 0x33, 0x00,
1220 0xCC, 0x00, 0x00, 0x00,
1221 0x99, 0xFF, 0xFF, 0x00,
1222 0x99, 0xFF, 0xCC, 0x00,
1223 0x99, 0xFF, 0x99, 0x00,
1224 0x99, 0xFF, 0x66, 0x00,
1225 0x99, 0xFF, 0x33, 0x00,
1226 0x99, 0xFF, 0x00, 0x00,
1227 0x99, 0xCC, 0xFF, 0x00,
1228 0x99, 0xCC, 0xCC, 0x00,
1229 0x99, 0xCC, 0x99, 0x00,
1230 0x99, 0xCC, 0x66, 0x00,
1231 0x99, 0xCC, 0x33, 0x00,
1232 0x99, 0xCC, 0x00, 0x00,
1233 0x99, 0x99, 0xFF, 0x00,
1234 0x99, 0x99, 0xCC, 0x00,
1235 0x99, 0x99, 0x99, 0x00,
1236 0x99, 0x99, 0x66, 0x00,
1237 0x99, 0x99, 0x33, 0x00,
1238 0x99, 0x99, 0x00, 0x00,
1239 0x99, 0x66, 0xFF, 0x00,
1240 0x99, 0x66, 0xCC, 0x00,
1241 0x99, 0x66, 0x99, 0x00,
1242 0x99, 0x66, 0x66, 0x00,
1243 0x99, 0x66, 0x33, 0x00,
1244 0x99, 0x66, 0x00, 0x00,
1245 0x99, 0x33, 0xFF, 0x00,
1246 0x99, 0x33, 0xCC, 0x00,
1247 0x99, 0x33, 0x99, 0x00,
1248 0x99, 0x33, 0x66, 0x00,
1249 0x99, 0x33, 0x33, 0x00,
1250 0x99, 0x33, 0x00, 0x00,
1251 0x99, 0x00, 0xFF, 0x00,
1252 0x99, 0x00, 0xCC, 0x00,
1253 0x99, 0x00, 0x99, 0x00,
1254 0x99, 0x00, 0x66, 0x00,
1255 0x99, 0x00, 0x33, 0x00,
1256 0x99, 0x00, 0x00, 0x00,
1257 0x66, 0xFF, 0xFF, 0x00,
1258 0x66, 0xFF, 0xCC, 0x00,
1259 0x66, 0xFF, 0x99, 0x00,
1260 0x66, 0xFF, 0x66, 0x00,
1261 0x66, 0xFF, 0x33, 0x00,
1262 0x66, 0xFF, 0x00, 0x00,
1263 0x66, 0xCC, 0xFF, 0x00,
1264 0x66, 0xCC, 0xCC, 0x00,
1265 0x66, 0xCC, 0x99, 0x00,
1266 0x66, 0xCC, 0x66, 0x00,
1267 0x66, 0xCC, 0x33, 0x00,
1268 0x66, 0xCC, 0x00, 0x00,
1269 0x66, 0x99, 0xFF, 0x00,
1270 0x66, 0x99, 0xCC, 0x00,
1271 0x66, 0x99, 0x99, 0x00,
1272 0x66, 0x99, 0x66, 0x00,
1273 0x66, 0x99, 0x33, 0x00,
1274 0x66, 0x99, 0x00, 0x00,
1275 0x66, 0x66, 0xFF, 0x00,
1276 0x66, 0x66, 0xCC, 0x00,
1277 0x66, 0x66, 0x99, 0x00,
1278 0x66, 0x66, 0x66, 0x00,
1279 0x66, 0x66, 0x33, 0x00,
1280 0x66, 0x66, 0x00, 0x00,
1281 0x66, 0x33, 0xFF, 0x00,
1282 0x66, 0x33, 0xCC, 0x00,
1283 0x66, 0x33, 0x99, 0x00,
1284 0x66, 0x33, 0x66, 0x00,
1285 0x66, 0x33, 0x33, 0x00,
1286 0x66, 0x33, 0x00, 0x00,
1287 0x66, 0x00, 0xFF, 0x00,
1288 0x66, 0x00, 0xCC, 0x00,
1289 0x66, 0x00, 0x99, 0x00,
1290 0x66, 0x00, 0x66, 0x00,
1291 0x66, 0x00, 0x33, 0x00,
1292 0x66, 0x00, 0x00, 0x00,
1293 0x33, 0xFF, 0xFF, 0x00,
1294 0x33, 0xFF, 0xCC, 0x00,
1295 0x33, 0xFF, 0x99, 0x00,
1296 0x33, 0xFF, 0x66, 0x00,
1297 0x33, 0xFF, 0x33, 0x00,
1298 0x33, 0xFF, 0x00, 0x00,
1299 0x33, 0xCC, 0xFF, 0x00,
1300 0x33, 0xCC, 0xCC, 0x00,
1301 0x33, 0xCC, 0x99, 0x00,
1302 0x33, 0xCC, 0x66, 0x00,
1303 0x33, 0xCC, 0x33, 0x00,
1304 0x33, 0xCC, 0x00, 0x00,
1305 0x33, 0x99, 0xFF, 0x00,
1306 0x33, 0x99, 0xCC, 0x00,
1307 0x33, 0x99, 0x99, 0x00,
1308 0x33, 0x99, 0x66, 0x00,
1309 0x33, 0x99, 0x33, 0x00,
1310 0x33, 0x99, 0x00, 0x00,
1311 0x33, 0x66, 0xFF, 0x00,
1312 0x33, 0x66, 0xCC, 0x00,
1313 0x33, 0x66, 0x99, 0x00,
1314 0x33, 0x66, 0x66, 0x00,
1315 0x33, 0x66, 0x33, 0x00,
1316 0x33, 0x66, 0x00, 0x00,
1317 0x33, 0x33, 0xFF, 0x00,
1318 0x33, 0x33, 0xCC, 0x00,
1319 0x33, 0x33, 0x99, 0x00,
1320 0x33, 0x33, 0x66, 0x00,
1321 0x33, 0x33, 0x33, 0x00,
1322 0x33, 0x33, 0x00, 0x00,
1323 0x33, 0x00, 0xFF, 0x00,
1324 0x33, 0x00, 0xCC, 0x00,
1325 0x33, 0x00, 0x99, 0x00,
1326 0x33, 0x00, 0x66, 0x00,
1327 0x33, 0x00, 0x33, 0x00,
1328 0x33, 0x00, 0x00, 0x00,
1329 0x00, 0xFF, 0xFF, 0x00,
1330 0x00, 0xFF, 0xCC, 0x00,
1331 0x00, 0xFF, 0x99, 0x00,
1332 0x00, 0xFF, 0x66, 0x00,
1333 0x00, 0xFF, 0x33, 0x00,
1334 0x00, 0xFF, 0x00, 0x00,
1335 0x00, 0xCC, 0xFF, 0x00,
1336 0x00, 0xCC, 0xCC, 0x00,
1337 0x00, 0xCC, 0x99, 0x00,
1338 0x00, 0xCC, 0x66, 0x00,
1339 0x00, 0xCC, 0x33, 0x00,
1340 0x00, 0xCC, 0x00, 0x00,
1341 0x00, 0x99, 0xFF, 0x00,
1342 0x00, 0x99, 0xCC, 0x00,
1343 0x00, 0x99, 0x99, 0x00,
1344 0x00, 0x99, 0x66, 0x00,
1345 0x00, 0x99, 0x33, 0x00,
1346 0x00, 0x99, 0x00, 0x00,
1347 0x00, 0x66, 0xFF, 0x00,
1348 0x00, 0x66, 0xCC, 0x00,
1349 0x00, 0x66, 0x99, 0x00,
1350 0x00, 0x66, 0x66, 0x00,
1351 0x00, 0x66, 0x33, 0x00,
1352 0x00, 0x66, 0x00, 0x00,
1353 0x00, 0x33, 0xFF, 0x00,
1354 0x00, 0x33, 0xCC, 0x00,
1355 0x00, 0x33, 0x99, 0x00,
1356 0x00, 0x33, 0x66, 0x00,
1357 0x00, 0x33, 0x33, 0x00,
1358 0x00, 0x33, 0x00, 0x00,
1359 0x00, 0x00, 0xFF, 0x00,
1360 0x00, 0x00, 0xCC, 0x00,
1361 0x00, 0x00, 0x99, 0x00,
1362 0x00, 0x00, 0x66, 0x00,
1363 0x00, 0x00, 0x33, 0x00,
1364 0xEE, 0x00, 0x00, 0x00,
1365 0xDD, 0x00, 0x00, 0x00,
1366 0xBB, 0x00, 0x00, 0x00,
1367 0xAA, 0x00, 0x00, 0x00,
1368 0x88, 0x00, 0x00, 0x00,
1369 0x77, 0x00, 0x00, 0x00,
1370 0x55, 0x00, 0x00, 0x00,
1371 0x44, 0x00, 0x00, 0x00,
1372 0x22, 0x00, 0x00, 0x00,
1373 0x11, 0x00, 0x00, 0x00,
1374 0x00, 0xEE, 0x00, 0x00,
1375 0x00, 0xDD, 0x00, 0x00,
1376 0x00, 0xBB, 0x00, 0x00,
1377 0x00, 0xAA, 0x00, 0x00,
1378 0x00, 0x88, 0x00, 0x00,
1379 0x00, 0x77, 0x00, 0x00,
1380 0x00, 0x55, 0x00, 0x00,
1381 0x00, 0x44, 0x00, 0x00,
1382 0x00, 0x22, 0x00, 0x00,
1383 0x00, 0x11, 0x00, 0x00,
1384 0x00, 0x00, 0xEE, 0x00,
1385 0x00, 0x00, 0xDD, 0x00,
1386 0x00, 0x00, 0xBB, 0x00,
1387 0x00, 0x00, 0xAA, 0x00,
1388 0x00, 0x00, 0x88, 0x00,
1389 0x00, 0x00, 0x77, 0x00,
1390 0x00, 0x00, 0x55, 0x00,
1391 0x00, 0x00, 0x44, 0x00,
1392 0x00, 0x00, 0x22, 0x00,
1393 0x00, 0x00, 0x11, 0x00,
1394 0xEE, 0xEE, 0xEE, 0x00,
1395 0xDD, 0xDD, 0xDD, 0x00,
1396 0xBB, 0xBB, 0xBB, 0x00,
1397 0xAA, 0xAA, 0xAA, 0x00,
1398 0x88, 0x88, 0x88, 0x00,
1399 0x77, 0x77, 0x77, 0x00,
1400 0x55, 0x55, 0x55, 0x00,
1401 0x44, 0x44, 0x44, 0x00,
1402 0x22, 0x22, 0x22, 0x00,
1403 0x11, 0x11, 0x11, 0x00,
1404 0x00, 0x00, 0x00, 0x00
1405];
1406
58309c73
KS
1407#[cfg(test)]
1408mod test {
1409 use super::*;
1410 use std::fs::File;
1411
1412 #[test]
1413 fn test_mov_demux() {
1414 let mut file = File::open("assets/Indeo/cubes.mov").unwrap();
1415 let mut fr = FileReader::new_read(&mut file);
1416 let mut br = ByteReader::new(&mut fr);
1417 let mut dmx = MOVDemuxer::new(&mut br);
1418 let mut sm = StreamManager::new();
1419 let mut si = SeekIndex::new();
1420 dmx.open(&mut sm, &mut si).unwrap();
1421
1422 loop {
1423 let pktres = dmx.get_frame(&mut sm);
1424 if let Err(e) = pktres {
1425 if e == DemuxerError::EOF { break; }
1426 panic!("error");
1427 }
1428 let pkt = pktres.unwrap();
1429 println!("Got {}", pkt);
1430 }
1431 }
1432}