1 use nihav_core::muxers::*;
2 use nihav_registry::register::*;
22 bw: &'a mut ByteWriter<'a>,
24 video_str: Option<usize>,
27 stream_info: Vec<AVIStream>,
30 impl<'a> AVIMuxer<'a> {
31 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
38 stream_info: Vec::with_capacity(2),
43 fn patch_size(bw: &mut ByteWriter, pos: u64) -> MuxerResult<()> {
44 let size = bw.tell() - pos;
45 bw.seek(SeekFrom::Current(-((size + 4) as i64)))?;
46 bw.write_u32le(size as u32)?;
47 bw.seek(SeekFrom::End(0))?;
51 fn write_chunk_hdr(bw: &mut ByteWriter, stype: StreamType, str_no: u32) -> MuxerResult<()> {
52 bw.write_byte(b'0' + ((str_no / 10) as u8))?;
53 bw.write_byte(b'0' + ((str_no % 10) as u8))?;
55 StreamType::Video => { bw.write_buf(b"dc")?; },
56 StreamType::Audio => { bw.write_buf(b"wb")?; },
57 StreamType::Subtitles => { bw.write_buf(b"tx")?; },
58 _ => return Err(MuxerError::UnsupportedFormat),
63 impl<'a> MuxCore<'a> for AVIMuxer<'a> {
64 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
65 if strmgr.get_num_streams() == 0 {
66 return Err(MuxerError::InvalidArgument);
68 if strmgr.get_num_streams() > 99 {
69 return Err(MuxerError::UnsupportedFormat);
71 for (str_no, str) in strmgr.iter().enumerate() {
72 if str.get_media_type() == StreamType::Video {
73 self.video_str = Some(str_no);
74 self.video_id = str.id;
78 let (vinfo, tb_num, tb_den) = if let Some(str_id) = self.video_str {
79 let vstr = strmgr.get_stream(str_id).unwrap();
80 (vstr.get_info(), vstr.tb_num, vstr.tb_den)
82 (NACodecInfo::new_dummy(), 0, 1)
84 let hdrl_pos = self.bw.tell() + 20;
85 self.bw.write_buf(b"RIFF\0\0\0\0AVI LIST\0\0\0\0hdrlavih")?;
86 self.bw.write_u32le(56)?; // avih size
87 let ms_per_frame = NATimeInfo::ts_to_time(1, 1000000, tb_num, tb_den);
88 self.bw.write_u32le(ms_per_frame as u32)?;
89 self.bw.write_u32le(0)?; // max transfer rate
90 self.bw.write_u32le(0)?; // padding granularity
91 self.bw.write_u32le(0)?; // flags
92 self.bw.write_u32le(0)?; // total frames
93 self.bw.write_u32le(0)?; // initial frames
94 self.bw.write_u32le(strmgr.get_num_streams() as u32)?;
95 self.bw.write_u32le(0)?; // suggested buffer size
96 if let NACodecTypeInfo::Video(ref vinfo) = vinfo.get_properties() {
97 self.bw.write_u32le(vinfo.width as u32)?;
98 self.bw.write_u32le(vinfo.height as u32)?;
100 self.bw.write_u32le(0)?;
101 self.bw.write_u32le(0)?;
103 self.bw.write_u32le(0)?; // reserved
104 self.bw.write_u32le(0)?; // reserved
105 self.bw.write_u32le(0)?; // reserved
106 self.bw.write_u32le(0)?; // reserved
108 for str in strmgr.iter() {
109 let strl_pos = self.bw.tell() + 8;
110 self.bw.write_buf(b"LIST\0\0\0\0strlstrh")?;
111 self.bw.write_u32le(56)?; // strh size
113 match str.get_media_type() {
114 StreamType::Video => {
115 self.bw.write_buf(b"vids")?;
116 let fcc = find_avi_fourcc(str.get_info().get_name());
118 return Err(MuxerError::UnsupportedFormat);
120 self.bw.write_buf(&fcc.unwrap_or([0; 4]))?;
121 let vinfo = str.get_info().get_properties().get_video_info().unwrap();
122 if vinfo.width >= (1 << 16) || vinfo.height >= (1 << 16) {
123 return Err(MuxerError::UnsupportedFormat);
126 StreamType::Audio => {
127 self.bw.write_buf(b"auds")?;
128 self.bw.write_u32le(0)?;
130 StreamType::Subtitles => {
131 self.bw.write_buf(b"txts")?;
132 self.bw.write_u32le(0)?;
134 _ => return Err(MuxerError::UnsupportedFormat),
136 self.stream_info.push(AVIStream {
137 strh_pos: self.bw.tell(),
138 is_video: str.get_media_type() == StreamType::Video,
143 self.bw.write_u32le(0)?; // flags
144 self.bw.write_u16le(0)?; // priority
145 self.bw.write_u16le(0)?; // language
146 self.bw.write_u32le(0)?; // initial frames
147 self.bw.write_u32le(str.tb_num)?;
148 self.bw.write_u32le(str.tb_den)?;
149 self.bw.write_u32le(0)?; // start
150 self.bw.write_u32le(0)?; // length
151 self.bw.write_u32le(0)?; // suggested buffer size
152 self.bw.write_u32le(0)?; // quality
153 self.bw.write_u32le(0)?; // sample_size
154 self.bw.write_u16le(0)?; // x
155 self.bw.write_u16le(0)?; // y
156 self.bw.write_u16le(0)?; // w
157 self.bw.write_u16le(0)?; // h
159 self.bw.write_buf(b"strf")?;
160 self.bw.write_u32le(0)?;
161 let strf_pos = self.bw.tell();
162 match str.get_media_type() {
163 StreamType::Video => {
164 let vinfo = str.get_info().get_properties().get_video_info().unwrap();
165 let hdr_pos = self.bw.tell();
166 self.bw.write_u32le(0)?;
167 self.bw.write_u32le(vinfo.width as u32)?;
169 self.bw.write_u32le((-(vinfo.height as i32)) as u32)?;
171 self.bw.write_u32le(vinfo.height as u32)?;
173 self.bw.write_u16le(vinfo.format.components as u16)?;
174 self.bw.write_u16le(vinfo.format.get_total_depth() as u16)?;
175 let fcc = find_avi_fourcc(str.get_info().get_name());
177 return Err(MuxerError::UnsupportedFormat);
179 self.bw.write_buf(&fcc.unwrap_or([0; 4]))?;
180 self.bw.write_u32le(0)?; // image size
181 self.bw.write_u32le(0)?; // x dpi
182 self.bw.write_u32le(0)?; // y dpi
183 if vinfo.format.palette {
185 self.bw.write_u32le(0)?; // total colors
186 self.bw.write_u32le(0)?; // important colors
188 self.bw.write_u32le(0)?; // total colors
189 self.bw.write_u32le(0)?; // important colors
191 if let Some(ref edata) = str.get_info().get_extradata() {
192 self.bw.write_buf(edata.as_slice())?;
194 let bisize = self.bw.tell() - hdr_pos;
195 self.bw.seek(SeekFrom::Current(-(bisize as i64)))?;
196 self.bw.write_u32le(bisize as u32)?;
197 self.bw.seek(SeekFrom::End(0))?;
199 StreamType::Audio => {
200 let ainfo = str.get_info().get_properties().get_audio_info().unwrap();
201 let twocc = find_wav_twocc(str.get_info().get_name());
203 return Err(MuxerError::UnsupportedFormat);
205 let twocc = twocc.unwrap_or(0);
206 self.bw.write_u16le(if twocc == 0 { 1 } else { twocc })?; // PCM hack
207 self.bw.write_u16le(ainfo.channels as u16)?;
208 self.bw.write_u32le(ainfo.sample_rate)?;
209 self.bw.write_u32le(0)?; // avg bytes per second
210 self.bw.write_u16le(ainfo.block_len as u16)?;
211 self.bw.write_u16le(ainfo.format.bits as u16)?;
212 if let Some(ref edata) = str.get_info().get_extradata() {
213 self.bw.write_buf(edata.as_slice())?;
216 StreamType::Subtitles => {
217 if let Some(ref edata) = str.get_info().get_extradata() {
218 self.bw.write_buf(edata.as_slice())?;
223 patch_size(&mut self.bw, strf_pos)?;
224 patch_size(&mut self.bw, strl_pos)?;
226 patch_size(&mut self.bw, hdrl_pos)?;
228 self.data_pos = self.bw.tell() + 8;
229 self.bw.write_buf(b"LIST\0\0\0\0movi")?;
233 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
234 if self.data_pos == 0 {
235 return Err(MuxerError::NotCreated);
237 let str = pkt.get_stream();
238 let str_num = str.get_num();
239 if str_num > 99 || str_num >= self.stream_info.len() {
240 return Err(MuxerError::UnsupportedFormat);
243 let chunk_len = pkt.get_buffer().len() as u32;
245 self.stream_info[str_num].nframes += 1;
246 self.stream_info[str_num].max_size = self.stream_info[str_num].max_size.max(chunk_len);
248 self.index.push(IdxEntry {
249 stream: str_num as u32,
250 stype: str.get_media_type(),
252 pos: self.bw.tell() as u32,
254 write_chunk_hdr(&mut self.bw, str.get_media_type(), str_num as u32)?;
255 self.bw.write_u32le(chunk_len)?;
256 self.bw.write_buf(pkt.get_buffer().as_slice())?;
259 fn flush(&mut self) -> MuxerResult<()> {
262 fn end(&mut self) -> MuxerResult<()> {
263 patch_size(&mut self.bw, self.data_pos)?;
264 if self.index.len() > 0 {
265 self.bw.write_buf(b"idx1")?;
266 self.bw.write_u32le((self.index.len() * 16) as u32)?;
267 for item in self.index.iter() {
268 write_chunk_hdr(&mut self.bw, item.stype, item.stream)?;
269 self.bw.write_u32le(if item.key { 0x10 } else { 0 })?;
270 self.bw.write_u32le(item.pos)?;
271 self.bw.write_u32le(item.len)?;
274 patch_size(&mut self.bw, 8)?;
275 let mut max_frames = 0;
276 let mut max_size = 0;
277 for stri in self.stream_info.iter() {
278 max_frames = max_frames.max(stri.nframes);
279 max_size = max_size.max(stri.max_size);
280 self.bw.seek(SeekFrom::Start(stri.strh_pos + 0x18))?;
281 self.bw.write_u32le(if stri.is_video { stri.nframes } else { 0 })?;
282 self.bw.write_u32le(stri.max_size)?;
284 self.bw.seek(SeekFrom::Start(0x30))?;
285 self.bw.write_u32le(max_frames)?;
286 self.bw.seek(SeekFrom::Current(8))?;
287 self.bw.write_u32le(max_size)?;
292 pub struct AVIMuxerCreator {}
294 impl MuxerCreator for AVIMuxerCreator {
295 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
296 Box::new(AVIMuxer::new(bw))
298 fn get_name(&self) -> &'static str { "avi" }
305 use nihav_core::demuxers::*;
306 use crate::demuxers::*;
309 fn test_avi_muxer() {
310 let mut dmx_reg = RegisteredDemuxers::new();
311 generic_register_all_demuxers(&mut dmx_reg);
312 let mut file = File::open("assets/Indeo/laser05.avi").unwrap();
313 let mut fr = FileReader::new_read(&mut file);
314 let mut br = ByteReader::new(&mut fr);
315 let dmx_f = dmx_reg.find_demuxer("avi").unwrap();
316 let mut dmx = create_demuxer(dmx_f, &mut br).unwrap();
318 let ofile = File::create("assets/test_out/muxed.avi").unwrap();
319 let mut fw = FileWriter::new_write(ofile);
320 let mut bw = ByteWriter::new(&mut fw);
321 let mut mux = AVIMuxer::new(&mut bw);
323 mux.create(dmx.get_stream_manager()).unwrap();
326 let pktres = dmx.get_frame();
327 if let Err(e) = pktres {
328 if e == DemuxerError::EOF { break; }
331 let pkt = pktres.unwrap();
332 println!("Got {}", pkt);
333 mux.mux_frame(dmx.get_stream_manager(), pkt).unwrap();