remove trailing whitespaces
[nihav.git] / nihav-commonfmt / src / demuxers / mov.rs
index 63280375ad59e1eb20e590b6171475fe559dcec6..5d661745e12648bd448b17cc559b3a1f1a1c7ed5 100644 (file)
@@ -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<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>,
@@ -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<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;
@@ -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<u64> {
@@ -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<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)?;
@@ -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)
 }
 
@@ -384,7 +423,10 @@ fn read_stsd(track: &mut Track, br: &mut ByteReader, size: u64) -> DemuxerResult
             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) {
@@ -534,6 +576,7 @@ struct MOVDemuxer<'a> {
     cur_track:      usize,
     tb_den:         u32,
     duration:       u32,
+    pal:            Option<Arc<[u8; 1024]>>,
 }
 
 struct Track {
@@ -560,6 +603,7 @@ struct Track {
     cur_sample:     usize,
     samples_left:   usize,
     last_offset:    u64,
+    pal:            Option<Arc<[u8; 1024]>>,
 }
 
 impl Track {
@@ -588,6 +632,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 +799,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 +829,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<NAValue> { None }
+}
+
 impl<'a> MOVDemuxer<'a> {
     fn new(io: &'a mut ByteReader<'a>) -> Self {
         MOVDemuxer {
@@ -790,6 +846,7 @@ impl<'a> MOVDemuxer<'a> {
             cur_track:      0,
             tb_den:         0,
             duration:       0,
+            pal:            None,
         }
     }
     fn read_root(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {