replace vec.truncate(0) with vec.clear()
[nihav.git] / nihav-commonfmt / src / muxers / avi.rs
index 25831098d318d3e513bd9c55fa647362e13cbb1b..cd75942f5a75bfffe135cb4c077751ef5df6e052 100644 (file)
@@ -25,6 +25,7 @@ struct AVIMuxer<'a> {
     video_id:       u32,
     data_pos:       u64,
     stream_info:    Vec<AVIStream>,
+    pal_pos:        Vec<u32>,
 }
 
 impl<'a> AVIMuxer<'a> {
@@ -36,6 +37,7 @@ impl<'a> AVIMuxer<'a> {
             video_id:       0,
             data_pos:       0,
             stream_info:    Vec::with_capacity(2),
+            pal_pos:        Vec::with_capacity(2),
         }
     }
 }
@@ -61,6 +63,8 @@ fn write_chunk_hdr(bw: &mut ByteWriter, stype: StreamType, str_no: u32) -> Muxer
 }
 
 impl<'a> MuxCore<'a> for AVIMuxer<'a> {
+    #[allow(clippy::unreadable_literal)]
+    #[allow(clippy::cast_lossless)]
     fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
         if strmgr.get_num_streams() == 0 {
             return Err(MuxerError::InvalidArgument);
@@ -105,7 +109,9 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
         self.bw.write_u32le(0)?; // reserved
         self.bw.write_u32le(0)?; // reserved
 
-        for str in strmgr.iter() {
+        self.pal_pos.clear();
+        self.pal_pos.resize(strmgr.get_num_streams(), 0);
+        for (strno, str) in strmgr.iter().enumerate() {
             let strl_pos = self.bw.tell() + 8;
             self.bw.write_buf(b"LIST\0\0\0\0strlstrh")?;
             self.bw.write_u32le(56)?; // strh size
@@ -165,11 +171,7 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
                     let hdr_pos = self.bw.tell();
                     self.bw.write_u32le(0)?;
                     self.bw.write_u32le(vinfo.width as u32)?;
-                    if vinfo.flipped {
-                        self.bw.write_u32le((-(vinfo.height as i32)) as u32)?;
-                    } else {
-                        self.bw.write_u32le(vinfo.height as u32)?;
-                    }
+                    self.bw.write_u32le(vinfo.height as u32)?;
                     self.bw.write_u16le(vinfo.format.components as u16)?;
                     self.bw.write_u16le(vinfo.format.get_total_depth() as u16)?;
                     let fcc = find_avi_fourcc(str.get_info().get_name());
@@ -181,9 +183,12 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
                     self.bw.write_u32le(0)?; // x dpi
                     self.bw.write_u32le(0)?; // y dpi
                     if vinfo.format.palette {
-//                        unimplemented!();
-                        self.bw.write_u32le(0)?; // total colors
+                        self.bw.write_u32le(256)?; // total colors
                         self.bw.write_u32le(0)?; // important colors
+                        self.pal_pos[strno] = self.bw.tell() as u32;
+                        for _ in 0..256 {
+                            self.bw.write_u32le(0)?;
+                        }
                     } else {
                         self.bw.write_u32le(0)?; // total colors
                         self.bw.write_u32le(0)?; // important colors
@@ -241,9 +246,40 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
 
         let chunk_len = pkt.get_buffer().len() as u32;
 
+        if self.pal_pos[str_num] != 0 {
+            for sdata in pkt.side_data.iter() {
+                if let NASideData::Palette(_, ref pal) = sdata {
+                    let cur_pos = self.bw.tell();
+                    self.bw.seek(SeekFrom::Start(u64::from(self.pal_pos[str_num])))?;
+                    self.bw.write_buf(pal.as_ref())?;
+                    self.bw.seek(SeekFrom::Start(cur_pos))?;
+                    self.pal_pos[str_num] = 0;
+                    break;
+                }
+            }
+        } else {
+            for sdata in pkt.side_data.iter() {
+                if let NASideData::Palette(true, ref pal) = sdata {
+                    //todo search for changed region
+                    let start_clr = 0usize;
+                    let end_clr = 256usize;
+                    if start_clr < end_clr {
+                        let chunk_len = ((end_clr - start_clr) as u32) * 4 + 4;
+                        self.bw.write_byte(b'0' + ((str_num / 10) as u8))?;
+                        self.bw.write_byte(b'0' + ((str_num % 10) as u8))?;
+                        self.bw.write_buf(b"pc")?;
+                        self.bw.write_u32le(chunk_len)?;
+                        self.bw.write_byte(start_clr as u8)?;
+                        self.bw.write_byte((end_clr - start_clr) as u8)?;
+                        self.bw.write_u16le(0)?; //flags
+                        self.bw.write_buf(&pal[start_clr * 4..end_clr * 4])?;
+                    }
+                }
+            }
+        }
+
         self.stream_info[str_num].nframes += 1;
         self.stream_info[str_num].max_size = self.stream_info[str_num].max_size.max(chunk_len);
-// todo palchange
         self.index.push(IdxEntry {
                 stream: str_num as u32,
                 stype:  str.get_media_type(),
@@ -253,6 +289,9 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
         write_chunk_hdr(&mut self.bw, str.get_media_type(), str_num as u32)?;
         self.bw.write_u32le(chunk_len)?;
         self.bw.write_buf(pkt.get_buffer().as_slice())?;
+        if (self.bw.tell() & 1) != 0 {
+            self.bw.write_byte(0)?;
+        }
         Ok(())
     }
     fn flush(&mut self) -> MuxerResult<()> {
@@ -260,7 +299,7 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> {
     }
     fn end(&mut self) -> MuxerResult<()> {
         patch_size(&mut self.bw, self.data_pos)?;
-        if self.index.len() > 0 {
+        if !self.index.is_empty() {
             self.bw.write_buf(b"idx1")?;
             self.bw.write_u32le((self.index.len() * 16) as u32)?;
             for item in self.index.iter() {