X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fmuxers%2Favi.rs;h=ac09974d7eef7a02de10533cac2e39a2dad9bdbf;hb=6f2630992fe340ad1a122ec10c649f756e478185;hp=2c541188be6a653315fb3c50cf60a7bd7c54fb0f;hpb=61cab15b810434b8e62234ab5cdfcb17ec2d566d;p=nihav.git diff --git a/nihav-commonfmt/src/muxers/avi.rs b/nihav-commonfmt/src/muxers/avi.rs index 2c54118..ac09974 100644 --- a/nihav-commonfmt/src/muxers/avi.rs +++ b/nihav-commonfmt/src/muxers/avi.rs @@ -25,6 +25,7 @@ struct AVIMuxer<'a> { video_id: u32, data_pos: u64, stream_info: Vec, + pal_pos: Vec, } 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), } } } @@ -107,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 @@ -167,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()); @@ -183,10 +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 -println!("pal?"); + 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 @@ -222,10 +224,10 @@ println!("pal?"); }, _ => unreachable!(), }; - patch_size(&mut self.bw, strf_pos)?; - patch_size(&mut self.bw, strl_pos)?; + patch_size(self.bw, strf_pos)?; + patch_size(self.bw, strl_pos)?; } - patch_size(&mut self.bw, hdrl_pos)?; + patch_size(self.bw, hdrl_pos)?; self.data_pos = self.bw.tell() + 8; self.bw.write_buf(b"LIST\0\0\0\0movi")?; @@ -244,16 +246,47 @@ println!("pal?"); 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(), key: pkt.keyframe, pos: self.bw.tell() as u32, len: chunk_len }); - write_chunk_hdr(&mut self.bw, str.get_media_type(), str_num as u32)?; + write_chunk_hdr(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 { @@ -265,18 +298,18 @@ println!("pal?"); Ok(()) } fn end(&mut self) -> MuxerResult<()> { - patch_size(&mut self.bw, self.data_pos)?; + patch_size(self.bw, self.data_pos)?; 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() { - write_chunk_hdr(&mut self.bw, item.stype, item.stream)?; + write_chunk_hdr(self.bw, item.stype, item.stream)?; self.bw.write_u32le(if item.key { 0x10 } else { 0 })?; self.bw.write_u32le(item.pos)?; self.bw.write_u32le(item.len)?; } } - patch_size(&mut self.bw, 8)?; + patch_size(self.bw, 8)?; let mut max_frames = 0; let mut max_size = 0; for stri in self.stream_info.iter() { @@ -322,6 +355,7 @@ mod test { fn test_avi_muxer() { let mut dmx_reg = RegisteredDemuxers::new(); generic_register_all_demuxers(&mut dmx_reg); + //test sample: https://samples.mplayerhq.hu/V-codecs/RT21/320x240/laser05.avi let dec_config = DecoderTestParams { demuxer: "avi", in_name: "assets/Indeo/laser05.avi",