X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fdemuxers%2Fmov.rs;h=e147757fcac92e985b948eb1e15cb1d797c02cce;hb=592d288947c53bae97b76985c70f37e2b0ff820f;hp=63280375ad59e1eb20e590b6171475fe559dcec6;hpb=58309c73093e56494720028a2feddb11ceb2c0bc;p=nihav.git diff --git a/nihav-commonfmt/src/demuxers/mov.rs b/nihav-commonfmt/src/demuxers/mov.rs index 6328037..e147757 100644 --- a/nihav-commonfmt/src/demuxers/mov.rs +++ b/nihav-commonfmt/src/demuxers/mov.rs @@ -40,6 +40,25 @@ fn read_chunk_header(br: &mut ByteReader) -> DemuxerResult<(u32, u64)> { } } +fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult { + let _seed = br.read_u32be()?; + let _flags = br.read_u16be()?; + let palsize = (br.read_u16be()? as usize) + 1; + validate!(palsize <= 256); + validate!((palsize as u64) * 8 + 8 == size); + for i in 0..palsize { + let a = br.read_u16be()?; + let r = br.read_u16be()?; + let g = br.read_u16be()?; + let b = br.read_u16be()?; + pal[i * 4] = (r >> 8) as u8; + pal[i * 4 + 1] = (g >> 8) as u8; + pal[i * 4 + 2] = (b >> 8) as u8; + pal[i * 4 + 3] = (a >> 8) as u8; + } + Ok(size) +} + struct RootChunkHandler { ctype: u32, parse: fn(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult, @@ -55,6 +74,7 @@ const IGNORED_CHUNKS: &[u32] = &[ ]; const ROOT_CHUNK_HANDLERS: &[RootChunkHandler] = &[ + RootChunkHandler { ctype: mktag!(b"ftyp"), parse: read_ftyp }, RootChunkHandler { ctype: mktag!(b"mdat"), parse: read_mdat }, RootChunkHandler { ctype: mktag!(b"moov"), parse: read_moov }, ]; @@ -130,6 +150,11 @@ fn skip_chunk(_track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResu Ok(size) } +fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult { + dmx.src.skip64(size)?; + Ok(size) +} + fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult { dmx.mdat_pos = dmx.src.tell(); dmx.mdat_size = size; @@ -144,7 +169,9 @@ fn read_moov(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> Dem const MOOV_CHUNK_HANDLERS: &[RootChunkHandler] = &[ RootChunkHandler { ctype: mktag!(b"mvhd"), parse: read_mvhd }, + RootChunkHandler { ctype: mktag!(b"ctab"), parse: read_ctab }, RootChunkHandler { ctype: mktag!(b"trak"), parse: read_trak }, + RootChunkHandler { ctype: mktag!(b"meta"), parse: read_meta }, ]; fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult { @@ -175,6 +202,18 @@ fn read_mvhd(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> De Ok(KNOWN_MVHD_SIZE) } +fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult { + let mut pal = [0; 1024]; + let size = read_palette(&mut dmx.src, size, &mut pal)?; + dmx.pal = Some(Arc::new(pal)); + Ok(size) +} + +fn read_meta(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult { + dmx.src.skip64(size)?; + Ok(size) +} + fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult { let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den); track.read_trak(&mut dmx.src, size)?; @@ -268,7 +307,7 @@ fn read_hdlr(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult println!("Unknown stream type"); track.stream_type = StreamType::Data; } - + Ok(KNOWN_HDLR_SIZE) } @@ -382,9 +421,50 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult br.read_skip(31)?; // actual compressor name let depth = br.read_u16be()?; let ctable_id = br.read_u16be()?; - validate!((depth <= 8) || (ctable_id == 0xFFFF)); + let grayscale = depth > 0x20 || depth == 1; + let depth = if grayscale { depth & 0x1F } else { depth }; + validate!(depth <= 8 || (ctable_id == 0xFFFF)); if ctable_id == 0 { -unimplemented!(); + let max_pal_size = start_pos + size - br.tell(); + let mut pal = [0; 1024]; + read_palette(br, max_pal_size, &mut pal)?; + track.pal = Some(Arc::new(pal)); + } else if (depth <= 8) && !grayscale { + match depth & 0x1F { + 2 => { + let mut pal = [0; 1024]; + (&mut pal[..4 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_2BIT); + track.pal = Some(Arc::new(pal)); + }, + 4 => { + let mut pal = [0; 1024]; + (&mut pal[..16 * 4]).copy_from_slice(&MOV_DEFAULT_PAL_4BIT); + track.pal = Some(Arc::new(pal)); + }, + 8 => { + track.pal = Some(Arc::new(MOV_DEFAULT_PAL_8BIT)); + }, + _ => {}, + }; + } else if grayscale && ctable_id != 0xFFFF { + let mut pal = [0; 1024]; + let cdepth = depth & 0x1F; + let size = 1 << cdepth; + for i in 0..size { + let mut clr = ((size - 1 - i) as u8) << (8 - cdepth); + let mut off = 8 - cdepth; + while off >= cdepth { + clr |= clr >> (8 - off); + off -= cdepth; + } + if off > 0 { + clr |= clr >> (8 - off); + } + pal[i * 4] = clr; + pal[i * 4 + 1] = clr; + pal[i * 4 + 2] = clr; + } + track.pal = Some(Arc::new(pal)); } // todo other atoms, put as extradata let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) { @@ -395,7 +475,8 @@ unimplemented!(); "unknown" }; let format = if depth > 8 { RGB24_FORMAT } else { PAL8_FORMAT }; - let vhdr = NAVideoInfo::new(width, height, false, format); + let mut vhdr = NAVideoInfo::new(width, height, false, format); + vhdr.bits = depth as u8; let edata; if br.tell() - start_pos + 4 < size { //todo skip various common atoms @@ -534,6 +615,7 @@ struct MOVDemuxer<'a> { cur_track: usize, tb_den: u32, duration: u32, + pal: Option>, } struct Track { @@ -560,6 +642,7 @@ struct Track { cur_sample: usize, samples_left: usize, last_offset: u64, + pal: Option>, } impl Track { @@ -588,6 +671,7 @@ impl Track { cur_sample: 0, samples_left: 0, last_offset: 0, + pal: None, } } read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS); @@ -754,12 +838,17 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> { } let track = &mut self.tracks[self.cur_track]; self.cur_track += 1; + let first = track.cur_sample == 0; if let Some((pts, offset, size)) = track.get_next_chunk() { let str = strmgr.get_stream(track.track_str_id); if str.is_none() { return Err(DemuxerError::InvalidData); } let stream = str.unwrap(); self.src.seek(SeekFrom::Start(offset))?; - let pkt = self.src.read_packet(stream, pts, false, size)?; + let mut pkt = self.src.read_packet(stream, pts, false, size)?; + if let Some(ref pal) = track.pal { + let side_data = NASideData::Palette(first, pal.clone()); + pkt.add_side_data(side_data); + } return Ok(pkt); } } @@ -779,6 +868,12 @@ impl<'a> DemuxCore<'a> for MOVDemuxer<'a> { } } +impl<'a> NAOptionHandler for MOVDemuxer<'a> { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + impl<'a> MOVDemuxer<'a> { fn new(io: &'a mut ByteReader<'a>) -> Self { MOVDemuxer { @@ -790,6 +885,7 @@ impl<'a> MOVDemuxer<'a> { cur_track: 0, tb_den: 0, duration: 0, + pal: None, } } fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> { @@ -828,6 +924,289 @@ impl DemuxerCreator for MOVDemuxerCreator { fn get_name(&self) -> &'static str { "mov" } } +const MOV_DEFAULT_PAL_2BIT: [u8; 4 * 4] = [ + 0x93, 0x65, 0x5E, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, + 0xDF, 0xD0, 0xAB, 0x00, + 0x00, 0x00, 0x00, 0x00 +]; +const MOV_DEFAULT_PAL_4BIT: [u8; 16 * 4] = [ + 0xFF, 0xFB, 0xFF, 0x00, + 0xEF, 0xD9, 0xBB, 0x00, + 0xE8, 0xC9, 0xB1, 0x00, + 0x93, 0x65, 0x5E, 0x00, + 0xFC, 0xDE, 0xE8, 0x00, + 0x9D, 0x88, 0x91, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, + 0x47, 0x48, 0x37, 0x00, + 0x7A, 0x5E, 0x55, 0x00, + 0xDF, 0xD0, 0xAB, 0x00, + 0xFF, 0xFB, 0xF9, 0x00, + 0xE8, 0xCA, 0xC5, 0x00, + 0x8A, 0x7C, 0x77, 0x00, + 0x00, 0x00, 0x00, 0x00 +]; +const MOV_DEFAULT_PAL_8BIT: [u8; 256 * 4] = [ + 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0xFF, 0xCC, 0x00, + 0xFF, 0xFF, 0x99, 0x00, + 0xFF, 0xFF, 0x66, 0x00, + 0xFF, 0xFF, 0x33, 0x00, + 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xCC, 0xFF, 0x00, + 0xFF, 0xCC, 0xCC, 0x00, + 0xFF, 0xCC, 0x99, 0x00, + 0xFF, 0xCC, 0x66, 0x00, + 0xFF, 0xCC, 0x33, 0x00, + 0xFF, 0xCC, 0x00, 0x00, + 0xFF, 0x99, 0xFF, 0x00, + 0xFF, 0x99, 0xCC, 0x00, + 0xFF, 0x99, 0x99, 0x00, + 0xFF, 0x99, 0x66, 0x00, + 0xFF, 0x99, 0x33, 0x00, + 0xFF, 0x99, 0x00, 0x00, + 0xFF, 0x66, 0xFF, 0x00, + 0xFF, 0x66, 0xCC, 0x00, + 0xFF, 0x66, 0x99, 0x00, + 0xFF, 0x66, 0x66, 0x00, + 0xFF, 0x66, 0x33, 0x00, + 0xFF, 0x66, 0x00, 0x00, + 0xFF, 0x33, 0xFF, 0x00, + 0xFF, 0x33, 0xCC, 0x00, + 0xFF, 0x33, 0x99, 0x00, + 0xFF, 0x33, 0x66, 0x00, + 0xFF, 0x33, 0x33, 0x00, + 0xFF, 0x33, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xCC, 0x00, + 0xFF, 0x00, 0x99, 0x00, + 0xFF, 0x00, 0x66, 0x00, + 0xFF, 0x00, 0x33, 0x00, + 0xFF, 0x00, 0x00, 0x00, + 0xCC, 0xFF, 0xFF, 0x00, + 0xCC, 0xFF, 0xCC, 0x00, + 0xCC, 0xFF, 0x99, 0x00, + 0xCC, 0xFF, 0x66, 0x00, + 0xCC, 0xFF, 0x33, 0x00, + 0xCC, 0xFF, 0x00, 0x00, + 0xCC, 0xCC, 0xFF, 0x00, + 0xCC, 0xCC, 0xCC, 0x00, + 0xCC, 0xCC, 0x99, 0x00, + 0xCC, 0xCC, 0x66, 0x00, + 0xCC, 0xCC, 0x33, 0x00, + 0xCC, 0xCC, 0x00, 0x00, + 0xCC, 0x99, 0xFF, 0x00, + 0xCC, 0x99, 0xCC, 0x00, + 0xCC, 0x99, 0x99, 0x00, + 0xCC, 0x99, 0x66, 0x00, + 0xCC, 0x99, 0x33, 0x00, + 0xCC, 0x99, 0x00, 0x00, + 0xCC, 0x66, 0xFF, 0x00, + 0xCC, 0x66, 0xCC, 0x00, + 0xCC, 0x66, 0x99, 0x00, + 0xCC, 0x66, 0x66, 0x00, + 0xCC, 0x66, 0x33, 0x00, + 0xCC, 0x66, 0x00, 0x00, + 0xCC, 0x33, 0xFF, 0x00, + 0xCC, 0x33, 0xCC, 0x00, + 0xCC, 0x33, 0x99, 0x00, + 0xCC, 0x33, 0x66, 0x00, + 0xCC, 0x33, 0x33, 0x00, + 0xCC, 0x33, 0x00, 0x00, + 0xCC, 0x00, 0xFF, 0x00, + 0xCC, 0x00, 0xCC, 0x00, + 0xCC, 0x00, 0x99, 0x00, + 0xCC, 0x00, 0x66, 0x00, + 0xCC, 0x00, 0x33, 0x00, + 0xCC, 0x00, 0x00, 0x00, + 0x99, 0xFF, 0xFF, 0x00, + 0x99, 0xFF, 0xCC, 0x00, + 0x99, 0xFF, 0x99, 0x00, + 0x99, 0xFF, 0x66, 0x00, + 0x99, 0xFF, 0x33, 0x00, + 0x99, 0xFF, 0x00, 0x00, + 0x99, 0xCC, 0xFF, 0x00, + 0x99, 0xCC, 0xCC, 0x00, + 0x99, 0xCC, 0x99, 0x00, + 0x99, 0xCC, 0x66, 0x00, + 0x99, 0xCC, 0x33, 0x00, + 0x99, 0xCC, 0x00, 0x00, + 0x99, 0x99, 0xFF, 0x00, + 0x99, 0x99, 0xCC, 0x00, + 0x99, 0x99, 0x99, 0x00, + 0x99, 0x99, 0x66, 0x00, + 0x99, 0x99, 0x33, 0x00, + 0x99, 0x99, 0x00, 0x00, + 0x99, 0x66, 0xFF, 0x00, + 0x99, 0x66, 0xCC, 0x00, + 0x99, 0x66, 0x99, 0x00, + 0x99, 0x66, 0x66, 0x00, + 0x99, 0x66, 0x33, 0x00, + 0x99, 0x66, 0x00, 0x00, + 0x99, 0x33, 0xFF, 0x00, + 0x99, 0x33, 0xCC, 0x00, + 0x99, 0x33, 0x99, 0x00, + 0x99, 0x33, 0x66, 0x00, + 0x99, 0x33, 0x33, 0x00, + 0x99, 0x33, 0x00, 0x00, + 0x99, 0x00, 0xFF, 0x00, + 0x99, 0x00, 0xCC, 0x00, + 0x99, 0x00, 0x99, 0x00, + 0x99, 0x00, 0x66, 0x00, + 0x99, 0x00, 0x33, 0x00, + 0x99, 0x00, 0x00, 0x00, + 0x66, 0xFF, 0xFF, 0x00, + 0x66, 0xFF, 0xCC, 0x00, + 0x66, 0xFF, 0x99, 0x00, + 0x66, 0xFF, 0x66, 0x00, + 0x66, 0xFF, 0x33, 0x00, + 0x66, 0xFF, 0x00, 0x00, + 0x66, 0xCC, 0xFF, 0x00, + 0x66, 0xCC, 0xCC, 0x00, + 0x66, 0xCC, 0x99, 0x00, + 0x66, 0xCC, 0x66, 0x00, + 0x66, 0xCC, 0x33, 0x00, + 0x66, 0xCC, 0x00, 0x00, + 0x66, 0x99, 0xFF, 0x00, + 0x66, 0x99, 0xCC, 0x00, + 0x66, 0x99, 0x99, 0x00, + 0x66, 0x99, 0x66, 0x00, + 0x66, 0x99, 0x33, 0x00, + 0x66, 0x99, 0x00, 0x00, + 0x66, 0x66, 0xFF, 0x00, + 0x66, 0x66, 0xCC, 0x00, + 0x66, 0x66, 0x99, 0x00, + 0x66, 0x66, 0x66, 0x00, + 0x66, 0x66, 0x33, 0x00, + 0x66, 0x66, 0x00, 0x00, + 0x66, 0x33, 0xFF, 0x00, + 0x66, 0x33, 0xCC, 0x00, + 0x66, 0x33, 0x99, 0x00, + 0x66, 0x33, 0x66, 0x00, + 0x66, 0x33, 0x33, 0x00, + 0x66, 0x33, 0x00, 0x00, + 0x66, 0x00, 0xFF, 0x00, + 0x66, 0x00, 0xCC, 0x00, + 0x66, 0x00, 0x99, 0x00, + 0x66, 0x00, 0x66, 0x00, + 0x66, 0x00, 0x33, 0x00, + 0x66, 0x00, 0x00, 0x00, + 0x33, 0xFF, 0xFF, 0x00, + 0x33, 0xFF, 0xCC, 0x00, + 0x33, 0xFF, 0x99, 0x00, + 0x33, 0xFF, 0x66, 0x00, + 0x33, 0xFF, 0x33, 0x00, + 0x33, 0xFF, 0x00, 0x00, + 0x33, 0xCC, 0xFF, 0x00, + 0x33, 0xCC, 0xCC, 0x00, + 0x33, 0xCC, 0x99, 0x00, + 0x33, 0xCC, 0x66, 0x00, + 0x33, 0xCC, 0x33, 0x00, + 0x33, 0xCC, 0x00, 0x00, + 0x33, 0x99, 0xFF, 0x00, + 0x33, 0x99, 0xCC, 0x00, + 0x33, 0x99, 0x99, 0x00, + 0x33, 0x99, 0x66, 0x00, + 0x33, 0x99, 0x33, 0x00, + 0x33, 0x99, 0x00, 0x00, + 0x33, 0x66, 0xFF, 0x00, + 0x33, 0x66, 0xCC, 0x00, + 0x33, 0x66, 0x99, 0x00, + 0x33, 0x66, 0x66, 0x00, + 0x33, 0x66, 0x33, 0x00, + 0x33, 0x66, 0x00, 0x00, + 0x33, 0x33, 0xFF, 0x00, + 0x33, 0x33, 0xCC, 0x00, + 0x33, 0x33, 0x99, 0x00, + 0x33, 0x33, 0x66, 0x00, + 0x33, 0x33, 0x33, 0x00, + 0x33, 0x33, 0x00, 0x00, + 0x33, 0x00, 0xFF, 0x00, + 0x33, 0x00, 0xCC, 0x00, + 0x33, 0x00, 0x99, 0x00, + 0x33, 0x00, 0x66, 0x00, + 0x33, 0x00, 0x33, 0x00, + 0x33, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x00, + 0x00, 0xFF, 0xCC, 0x00, + 0x00, 0xFF, 0x99, 0x00, + 0x00, 0xFF, 0x66, 0x00, + 0x00, 0xFF, 0x33, 0x00, + 0x00, 0xFF, 0x00, 0x00, + 0x00, 0xCC, 0xFF, 0x00, + 0x00, 0xCC, 0xCC, 0x00, + 0x00, 0xCC, 0x99, 0x00, + 0x00, 0xCC, 0x66, 0x00, + 0x00, 0xCC, 0x33, 0x00, + 0x00, 0xCC, 0x00, 0x00, + 0x00, 0x99, 0xFF, 0x00, + 0x00, 0x99, 0xCC, 0x00, + 0x00, 0x99, 0x99, 0x00, + 0x00, 0x99, 0x66, 0x00, + 0x00, 0x99, 0x33, 0x00, + 0x00, 0x99, 0x00, 0x00, + 0x00, 0x66, 0xFF, 0x00, + 0x00, 0x66, 0xCC, 0x00, + 0x00, 0x66, 0x99, 0x00, + 0x00, 0x66, 0x66, 0x00, + 0x00, 0x66, 0x33, 0x00, + 0x00, 0x66, 0x00, 0x00, + 0x00, 0x33, 0xFF, 0x00, + 0x00, 0x33, 0xCC, 0x00, + 0x00, 0x33, 0x99, 0x00, + 0x00, 0x33, 0x66, 0x00, + 0x00, 0x33, 0x33, 0x00, + 0x00, 0x33, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0xCC, 0x00, + 0x00, 0x00, 0x99, 0x00, + 0x00, 0x00, 0x66, 0x00, + 0x00, 0x00, 0x33, 0x00, + 0xEE, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, + 0xBB, 0x00, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, + 0x88, 0x00, 0x00, 0x00, + 0x77, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xDD, 0x00, 0x00, + 0x00, 0xBB, 0x00, 0x00, + 0x00, 0xAA, 0x00, 0x00, + 0x00, 0x88, 0x00, 0x00, + 0x00, 0x77, 0x00, 0x00, + 0x00, 0x55, 0x00, 0x00, + 0x00, 0x44, 0x00, 0x00, + 0x00, 0x22, 0x00, 0x00, + 0x00, 0x11, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, + 0x00, 0x00, 0xDD, 0x00, + 0x00, 0x00, 0xBB, 0x00, + 0x00, 0x00, 0xAA, 0x00, + 0x00, 0x00, 0x88, 0x00, + 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x55, 0x00, + 0x00, 0x00, 0x44, 0x00, + 0x00, 0x00, 0x22, 0x00, + 0x00, 0x00, 0x11, 0x00, + 0xEE, 0xEE, 0xEE, 0x00, + 0xDD, 0xDD, 0xDD, 0x00, + 0xBB, 0xBB, 0xBB, 0x00, + 0xAA, 0xAA, 0xAA, 0x00, + 0x88, 0x88, 0x88, 0x00, + 0x77, 0x77, 0x77, 0x00, + 0x55, 0x55, 0x55, 0x00, + 0x44, 0x44, 0x44, 0x00, + 0x22, 0x22, 0x22, 0x00, + 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00 +]; + #[cfg(test)] mod test { use super::*;