X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fmuxers%2Favi.rs;h=d8e1f739bf735d14445e81c3ad8ff8134efc2416;hb=04fafc56d5f430ae289eaeabec24e2831e92d191;hp=5e98ed998e3673e109e2aabd97199083fabaf7c7;hpb=817e487223b28379176a533f09485c27a68443f8;p=nihav.git diff --git a/nihav-commonfmt/src/muxers/avi.rs b/nihav-commonfmt/src/muxers/avi.rs index 5e98ed9..d8e1f73 100644 --- a/nihav-commonfmt/src/muxers/avi.rs +++ b/nihav-commonfmt/src/muxers/avi.rs @@ -16,6 +16,7 @@ struct AVIStream { nframes: u32, is_video: bool, max_size: u32, + pal_change: bool, } struct AVIMuxer<'a> { @@ -72,10 +73,10 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { if strmgr.get_num_streams() > 99 { return Err(MuxerError::UnsupportedFormat); } - for (str_no, str) in strmgr.iter().enumerate() { - if str.get_media_type() == StreamType::Video { + for (str_no, strm) in strmgr.iter().enumerate() { + if strm.get_media_type() == StreamType::Video { self.video_str = Some(str_no); - self.video_id = str.id; + self.video_id = strm.id; break; } } @@ -111,20 +112,20 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { self.pal_pos.clear(); self.pal_pos.resize(strmgr.get_num_streams(), 0); - for (strno, str) in strmgr.iter().enumerate() { + for (strno, strm) 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 - match str.get_media_type() { + match strm.get_media_type() { StreamType::Video => { self.bw.write_buf(b"vids")?; - let fcc = find_avi_fourcc(str.get_info().get_name()); + let fcc = find_avi_fourcc(strm.get_info().get_name()); if fcc.is_none() { return Err(MuxerError::UnsupportedFormat); } self.bw.write_buf(&fcc.unwrap_or([0; 4]))?; - let vinfo = str.get_info().get_properties().get_video_info().unwrap(); + let vinfo = strm.get_info().get_properties().get_video_info().unwrap(); if vinfo.width >= (1 << 16) || vinfo.height >= (1 << 16) { return Err(MuxerError::UnsupportedFormat); } @@ -141,17 +142,18 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { }; self.stream_info.push(AVIStream { strh_pos: self.bw.tell(), - is_video: str.get_media_type() == StreamType::Video, + is_video: strm.get_media_type() == StreamType::Video, nframes: 0, max_size: 0, + pal_change: false, }); self.bw.write_u32le(0)?; // flags self.bw.write_u16le(0)?; // priority self.bw.write_u16le(0)?; // language self.bw.write_u32le(0)?; // initial frames - self.bw.write_u32le(str.tb_num)?; - self.bw.write_u32le(str.tb_den)?; + self.bw.write_u32le(strm.tb_num)?; + self.bw.write_u32le(strm.tb_den)?; self.bw.write_u32le(0)?; // start self.bw.write_u32le(0)?; // length self.bw.write_u32le(0)?; // suggested buffer size @@ -165,16 +167,21 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { self.bw.write_buf(b"strf")?; self.bw.write_u32le(0)?; let strf_pos = self.bw.tell(); - match str.get_media_type() { + match strm.get_media_type() { StreamType::Video => { - let vinfo = str.get_info().get_properties().get_video_info().unwrap(); + let vinfo = strm.get_info().get_properties().get_video_info().unwrap(); let hdr_pos = self.bw.tell(); self.bw.write_u32le(0)?; self.bw.write_u32le(vinfo.width 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()); + if !vinfo.format.palette { + self.bw.write_u16le(vinfo.format.components as u16)?; + self.bw.write_u16le(vinfo.format.get_total_depth() as u16)?; + } else { + self.bw.write_u16le(1)?; + self.bw.write_u16le(8)?; + } + let fcc = find_avi_fourcc(strm.get_info().get_name()); if fcc.is_none() { return Err(MuxerError::UnsupportedFormat); } @@ -193,7 +200,7 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { self.bw.write_u32le(0)?; // total colors self.bw.write_u32le(0)?; // important colors } - if let Some(ref edata) = str.get_info().get_extradata() { + if let Some(ref edata) = strm.get_info().get_extradata() { self.bw.write_buf(edata.as_slice())?; } let bisize = self.bw.tell() - hdr_pos; @@ -202,8 +209,8 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { self.bw.seek(SeekFrom::End(0))?; }, StreamType::Audio => { - let ainfo = str.get_info().get_properties().get_audio_info().unwrap(); - let twocc = find_wav_twocc(str.get_info().get_name()); + let ainfo = strm.get_info().get_properties().get_audio_info().unwrap(); + let twocc = find_wav_twocc(strm.get_info().get_name()); if twocc.is_none() { return Err(MuxerError::UnsupportedFormat); } @@ -213,12 +220,12 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { self.bw.write_u32le(0)?; // avg bytes per second self.bw.write_u16le(ainfo.block_len as u16)?; self.bw.write_u16le(ainfo.format.bits as u16)?; - if let Some(ref edata) = str.get_info().get_extradata() { + if let Some(ref edata) = strm.get_info().get_extradata() { self.bw.write_buf(edata.as_slice())?; } }, StreamType::Subtitles => { - if let Some(ref edata) = str.get_info().get_extradata() { + if let Some(ref edata) = strm.get_info().get_extradata() { self.bw.write_buf(edata.as_slice())?; } }, @@ -251,7 +258,12 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { 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())?; + for quad in pal.chunks(4) { + self.bw.write_byte(quad[2])?; + self.bw.write_byte(quad[1])?; + self.bw.write_byte(quad[0])?; + self.bw.write_byte(0)?; + } self.bw.seek(SeekFrom::Start(cur_pos))?; self.pal_pos[str_num] = 0; break; @@ -273,6 +285,7 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { 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].pal_change = true; } } } @@ -315,6 +328,10 @@ impl<'a> MuxCore<'a> for AVIMuxer<'a> { for stri in self.stream_info.iter() { max_frames = max_frames.max(stri.nframes); max_size = max_size.max(stri.max_size); + if stri.pal_change { + self.bw.seek(SeekFrom::Start(stri.strh_pos))?; + self.bw.write_u32le(0x00010000)?; + } self.bw.seek(SeekFrom::Start(stri.strh_pos + 0x18))?; self.bw.write_u32le(if stri.is_video { stri.nframes } else { 0 })?; self.bw.write_u32le(stri.max_size)?;