}
}
+fn read_palette(br: &mut ByteReader, size: u64, pal: &mut [u8; 1024]) -> DemuxerResult<u64> {
+ 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<u64>,
];
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 },
];
Ok(size)
}
+fn read_ftyp(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
+ dmx.src.skip64(size)?;
+ Ok(size)
+}
+
fn read_mdat(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
dmx.mdat_pos = dmx.src.tell();
dmx.mdat_size = size;
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<u64> {
Ok(KNOWN_MVHD_SIZE)
}
+fn read_ctab(dmx: &mut MOVDemuxer, _strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
+ 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<u64> {
+ dmx.src.skip64(size)?;
+ Ok(size)
+}
+
fn read_trak(dmx: &mut MOVDemuxer, strmgr: &mut StreamManager, size: u64) -> DemuxerResult<u64> {
let mut track = Track::new(dmx.cur_track as u32, dmx.tb_den);
track.read_trak(&mut dmx.src, size)?;
let ctable_id = br.read_u16be()?;
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));
}
// todo other atoms, put as extradata
let cname = if let Some(name) = find_codec_from_mov_video_fourcc(&fcc) {
cur_track: usize,
tb_den: u32,
duration: u32,
+ pal: Option<Arc<[u8; 1024]>>,
}
struct Track {
cur_sample: usize,
samples_left: usize,
last_offset: u64,
+ pal: Option<Arc<[u8; 1024]>>,
}
impl Track {
cur_sample: 0,
samples_left: 0,
last_offset: 0,
+ pal: None,
}
}
read_chunk_list!(track; "trak", read_trak, TRAK_CHUNK_HANDLERS);
}
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);
}
}
}
}
+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<NAValue> { None }
+}
+
impl<'a> MOVDemuxer<'a> {
fn new(io: &'a mut ByteReader<'a>) -> Self {
MOVDemuxer {
cur_track: 0,
tb_den: 0,
duration: 0,
+ pal: None,
}
}
fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {