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