1 use nihav_core::muxers::*;
8 fn write_chunk(&mut self, id: &[u8], size: u32, version: u16) -> MuxerResult<()>;
9 fn write_string(&mut self, data: &[u8]) -> MuxerResult<()>;
10 fn patch_value(&mut self, val: u32, off: u64) -> MuxerResult<()>;
13 impl<'a> RMWriterHelper for ByteWriter<'a> {
14 fn write_chunk(&mut self, id: &[u8], size: u32, version: u16) -> MuxerResult<()> {
16 self.write_u32be(size)?;
17 self.write_u16be(version)?;
20 fn write_string(&mut self, data: &[u8]) -> MuxerResult<()> {
21 validate!(data.len() < 256);
22 self.write_byte(data.len() as u8)?;
23 self.write_buf(data)?;
26 fn patch_value(&mut self, val: u32, off: u64) -> MuxerResult<()> {
27 let cur_pos = self.tell();
28 self.seek(SeekFrom::Start(off))?;
29 self.write_u32be(val)?;
30 self.seek(SeekFrom::Start(cur_pos))?;
35 pub trait RMStreamWriter {
36 fn write_header(&mut self, bw: &mut ByteWriter, astream: &NAStream) -> MuxerResult<()>;
37 fn queue_packet(&mut self, pkt: NAPacket, ms: u32) -> bool;
38 fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)>;
40 fn finish(&mut self, bw: &mut ByteWriter) -> MuxerResult<()>;
41 fn set_pkt_size(&mut self, pkt_size: usize);
52 packetiser: Box<dyn RMStreamWriter>,
62 index: Vec<IndexEntry>,
67 fn new(strno: usize, stream: &NAStream, pkt_size: usize) -> MuxerResult<Self> {
68 let packetiser = match stream.get_media_type() {
69 StreamType::Video => create_video_stream(stream, pkt_size)?,
70 StreamType::Audio => create_audio_stream(stream)?,
71 _ => Box::new(DummyStreamWriter{}),
75 stream_id: strno as u16,
88 fn write_mdpr(&mut self, bw: &mut ByteWriter, strm: &NAStream) -> MuxerResult<()> {
89 self.mdpr_pos = bw.tell();
91 bw.write_chunk(b"MDPR", 0, 0)?;
92 bw.write_u16be(self.stream_id as u16)?;
93 bw.write_u32be(0)?; //max br
94 bw.write_u32be(0)?; //avg br
95 bw.write_u32be(0)?; //max ps
96 bw.write_u32be(0)?; //avg ps
97 bw.write_u32be(0)?; //num packets
98 bw.write_u32be(0)?; //duration
99 bw.write_u32be(0)?; //preroll
101 match strm.get_media_type() {
102 StreamType::Video => {
103 bw.write_string(b"The Video Stream")?;
104 bw.write_string(b"video/x-pn-realvideo")?;
106 StreamType::Audio => {
107 bw.write_string(b"The Audio Stream")?;
108 bw.write_string(b"audio/x-pn-realaudio")?;
112 bw.write_string(b"some other stream")?;
113 bw.write_string(b"data")?;
116 bw.write_u32be(0)?; //extradata size
117 let edata_start = bw.tell();
118 self.packetiser.write_header(bw, strm)?;
119 let edata_end = bw.tell();
120 bw.patch_value((edata_end - edata_start) as u32, edata_start - 4)?;
122 patch_size(bw, self.mdpr_pos)?;
126 fn write_packet(&mut self, bw: &mut ByteWriter, pkt: NAPacket, pkt_no: &mut u32) -> MuxerResult<()> {
127 if let Some(pts) = pkt.get_pts() {
128 let (tb_num, tb_den) = pkt.get_stream().get_timebase();
129 let ms = NATimeInfo::ts_to_time(pts, 1000, tb_num, tb_den) as u32;
130 self.time = self.time.max(ms);
133 self.keyframe = pkt.keyframe || self.audio;
134 self.packetiser.queue_packet(pkt, self.cur_time);
135 self.write_packets(bw, pkt_no)
137 fn write_packets(&mut self, bw: &mut ByteWriter, pkt_no: &mut u32) -> MuxerResult<()> {
138 while let Some((data, ts, first)) = self.packetiser.get_packet() {
139 validate!(data.len() < 65000);
140 if self.keyframe && first {
141 self.index.push(IndexEntry{ time: ts, pos: bw.tell(), pkt_no: *pkt_no });
143 let is_keyframe = self.keyframe && (!self.audio || first);
145 println!(" writing packet for stream {} size {}{}", self.stream_id, data.len(), if is_keyframe { " kf" } else { "" });
147 bw.write_u16be(0)?; //version;
148 bw.write_u16be((data.len() + 12) as u16)?;
149 bw.write_u16be(self.stream_id)?;
151 bw.write_byte(0)?; //packet group
152 bw.write_byte(if is_keyframe { 0x2 } else { 0x0 })?;
153 bw.write_buf(&data)?;
156 self.data_size += data.len();
162 fn finish(&mut self, bw: &mut ByteWriter, pkt_no: &mut u32) -> MuxerResult<()> {
163 self.packetiser.flush();
164 self.write_packets(bw, pkt_no)?;
167 bw.seek(SeekFrom::Start(self.mdpr_pos + 12))?;
168 bw.write_u32be(if self.time > 0 { (self.data_size * 1000 / (self.time as usize)) as u32 } else { 0 })?;
169 bw.write_u32be(if self.time > 0 { (self.data_size * 1000 / (self.time as usize)) as u32 } else { 0 })?;
170 bw.write_u32be(self.max_pkt_size as u32)?;
171 bw.write_u32be(if self.npkts > 0 { (self.data_size / self.npkts) as u32 } else { 0 })?;
172 bw.seek(SeekFrom::Current(8))?;
173 bw.write_u32be(self.time)?;
175 bw.seek(SeekFrom::Start(pos))?;
181 bw: &'a mut ByteWriter<'a>,
182 streams: Vec<RMStream>,
191 impl<'a> RMMuxer<'a> {
192 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
204 fn write_index(&mut self) -> MuxerResult<()> {
205 let mut indx_pos = 0x38;
207 for stream in self.streams.iter() {
208 let cur_pos = self.bw.tell();
209 self.bw.patch_value(cur_pos as u32, indx_pos)?;
210 indx_pos = cur_pos + 16;
212 let idx_size = 10 + 10 + stream.index.len() * 14;
213 self.bw.write_chunk(b"INDX", idx_size as u32, 0)?;
214 self.bw.write_u32be(stream.index.len() as u32)?;
215 self.bw.write_u16be(stream.stream_id)?;
216 self.bw.write_u32be(0)?; // next index position
217 for entry in stream.index.iter() {
218 self.bw.write_u16be(0)?; // version
219 self.bw.write_u32be(entry.time)?;
220 self.bw.write_u32be(entry.pos as u32)?;
221 self.bw.write_u32be(entry.pkt_no)?;
224 self.num_chunks += 1;
229 fn update_prop(&mut self) -> MuxerResult<()> {
230 let mut data_size = 0;
232 let mut max_pkt_size = 0;
235 for stream in self.streams.iter() {
236 data_size += stream.data_size;
237 time = time.max(stream.time);
238 npkts += stream.npkts;
239 max_pkt_size = max_pkt_size.max(stream.max_pkt_size);
242 if npkts > 0 && time > 0 {
243 let cur_pos = self.bw.tell();
245 let bitrate = (data_size * 1000 / (time as usize)) as u32;
246 self.bw.seek(SeekFrom::Start(28))?;
247 self.bw.write_u32be(bitrate)?;
248 self.bw.write_u32be(bitrate)?;
249 self.bw.write_u32be(max_pkt_size as u32)?;
250 self.bw.write_u32be((data_size / npkts) as u32)?;
251 self.bw.write_u32be(npkts as u32)?;
252 self.bw.write_u32be(time)?;
254 self.bw.seek(SeekFrom::Start(cur_pos))?;
257 self.bw.patch_value(self.data_pos as u32, 0x3C)?;
263 fn patch_size(bw: &mut ByteWriter, pos: u64) -> MuxerResult<()> {
265 bw.patch_value((end - pos) as u32, pos + 4)
268 impl<'a> MuxCore<'a> for RMMuxer<'a> {
269 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
270 if strmgr.get_num_streams() == 0 {
271 return Err(MuxerError::InvalidArgument);
273 if strmgr.get_num_streams() > 100 {
274 return Err(MuxerError::UnsupportedFormat);
277 self.bw.write_chunk(b".RMF", 18, 0)?;
278 self.bw.write_u32be(0)?; // container version
279 self.bw.write_u32be(0)?; // number of chunks
282 let prop_start = self.bw.tell();
283 self.bw.write_chunk(b"PROP", 0, 0)?;
284 self.bw.write_u32be(0)?; //max br
285 self.bw.write_u32be(0)?; //avg br
286 self.bw.write_u32be(0)?; //max ps
287 self.bw.write_u32be(0)?; //avg ps
288 self.bw.write_u32be(0)?; //num packets
289 self.bw.write_u32be(0)?; //duration
290 self.bw.write_u32be(0)?; //preroll
291 self.bw.write_u32be(0)?; //index offset
292 self.bw.write_u32be(0)?; //data offset
293 self.bw.write_u16be(strmgr.get_num_streams() as u16)?;
294 self.bw.write_u16be(0)?; // flags
295 patch_size(self.bw, prop_start)?;
297 self.streams.clear();
298 for (strno, strm) in strmgr.iter().enumerate() {
299 let mut swriter = RMStream::new(strno, &strm, self.vpkt_size)?;
300 swriter.write_mdpr(self.bw, &strm)?;
301 self.streams.push(swriter);
302 self.num_chunks += 1;
305 self.data_pos = self.bw.tell();
306 self.bw.write_chunk(b"DATA", 0, 0)?;
307 self.bw.write_u32be(0)?; //num packets
308 self.bw.write_u32be(0)?; //next data chunk
309 self.num_chunks += 1;
313 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
314 if self.data_pos == 0 {
315 return Err(MuxerError::NotCreated);
317 let stream = pkt.get_stream();
318 let str_num = stream.get_num();
319 if str_num > self.streams.len() {
320 return Err(MuxerError::UnsupportedFormat);
322 self.streams[str_num].write_packet(self.bw, pkt, &mut self.cur_packet)?;
326 fn flush(&mut self) -> MuxerResult<()> {
329 fn end(&mut self) -> MuxerResult<()> {
330 if self.data_pos == 0 {
331 return Err(MuxerError::NotCreated);
333 let mut tot_npkts = 0;
334 for stream in self.streams.iter_mut() {
335 stream.finish(self.bw, &mut self.cur_packet)?;
336 tot_npkts += stream.npkts;
339 let data_size = self.bw.tell() - self.data_pos;
340 self.bw.patch_value(data_size as u32, self.data_pos + 4)?;
341 self.bw.patch_value(tot_npkts as u32, self.data_pos + 10)?;
346 self.bw.patch_value(self.num_chunks, 14)?;
351 const DEBUG_OPTION: &str = "debug";
352 const VPKT_SIZE_OPTION: &str = "vpkt_size";
354 const MUXER_OPTIONS: &[NAOptionDefinition] = &[
356 name: DEBUG_OPTION, description: "print some muxer statistics",
357 opt_type: NAOptionDefinitionType::Bool },
359 name: VPKT_SIZE_OPTION, description: "video packet maximum size",
360 opt_type: NAOptionDefinitionType::Int(Some(1024), Some(14800)) },
363 impl<'a> NAOptionHandler for RMMuxer<'a> {
364 fn get_supported_options(&self) -> &[NAOptionDefinition] { MUXER_OPTIONS }
365 fn set_options(&mut self, options: &[NAOption]) {
366 for option in options.iter() {
367 for opt_def in MUXER_OPTIONS.iter() {
368 if opt_def.check(option).is_ok() {
371 if let NAValue::Bool(val) = option.value {
373 for stream in self.streams.iter_mut() {
378 VPKT_SIZE_OPTION => {
379 if let NAValue::Int(intval) = option.value {
380 self.vpkt_size = intval as usize;
381 for stream in self.streams.iter_mut() {
382 stream.packetiser.set_pkt_size(self.vpkt_size);
392 fn query_option_value(&self, name: &str) -> Option<NAValue> {
394 DEBUG_OPTION => Some(NAValue::Bool(self.debug)),
395 VPKT_SIZE_OPTION => Some(NAValue::Int(self.vpkt_size as i64)),
401 pub struct RealMediaMuxerCreator {}
403 impl MuxerCreator for RealMediaMuxerCreator {
404 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
405 Box::new(RMMuxer::new(bw))
407 fn get_name(&self) -> &'static str { "realmedia" }
408 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::Universal }
412 bw: &'a mut ByteWriter<'a>,
413 sw: Option<Box<dyn RMStreamWriter>>,
416 impl<'a> RAMuxer<'a> {
417 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
425 impl<'a> MuxCore<'a> for RAMuxer<'a> {
426 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
427 if strmgr.get_num_streams() != 1 {
428 return Err(MuxerError::InvalidArgument);
430 let astream = strmgr.get_stream(0).unwrap();
431 if astream.get_media_type() != StreamType::Audio {
432 return Err(MuxerError::InvalidArgument);
434 self.sw = Some(create_audio_stream(&astream)?);
435 if let Some(ref mut sw) = self.sw {
436 sw.write_header(self.bw, &astream)?;
440 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
441 if let Some(ref mut sw) = self.sw {
442 sw.queue_packet(pkt, 0);
443 while let Some((data, _, _)) = sw.get_packet() {
444 self.bw.write_buf(&data)?;
448 Err(MuxerError::NotCreated)
451 fn flush(&mut self) -> MuxerResult<()> {
454 fn end(&mut self) -> MuxerResult<()> {
455 if let Some(ref mut sw) = self.sw {
456 sw.finish(&mut self.bw)?;
462 impl<'a> NAOptionHandler for RAMuxer<'a> {
463 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
464 fn set_options(&mut self, _options: &[NAOption]) { }
465 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
468 pub struct RealAudioMuxerCreator {}
470 impl MuxerCreator for RealAudioMuxerCreator {
471 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
472 Box::new(RAMuxer::new(bw))
474 fn get_name(&self) -> &'static str { "realaudio" }
475 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::SingleAudio("any") }
480 use nihav_core::codecs::*;
481 use nihav_core::demuxers::*;
482 use nihav_core::muxers::*;
483 use nihav_codec_support::test::enc_video::*;
488 let mut dmx_reg = RegisteredDemuxers::new();
489 realmedia_register_all_demuxers(&mut dmx_reg);
490 // sample from a private collection
491 let dec_config = DecoderTestParams {
492 demuxer: "realmedia",
493 in_name: "assets/RV/rv30_weighted_mc.rm",
495 stream_type: StreamType::None,
496 dmx_reg, dec_reg: RegisteredDecoders::new(),
498 let mut mux_reg = RegisteredMuxers::new();
499 realmedia_register_all_muxers(&mut mux_reg);
500 /*let enc_config = EncoderTestParams {
503 out_name: "muxed.rm",
504 mux_reg, enc_reg: RegisteredEncoders::new(),
506 test_remuxing(&dec_config, &enc_config);*/
507 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
508 [0x9bc90ab0, 0x6b8c42f7, 0xaf81e8bf, 0x7c76ec57]);
512 fn test_ra_muxer_v3() {
513 let mut dmx_reg = RegisteredDemuxers::new();
514 realmedia_register_all_demuxers(&mut dmx_reg);
515 //test sample: https://samples.mplayerhq.hu/real/RA/14_4/drummers.14.ra
516 let dec_config = DecoderTestParams {
517 demuxer: "realaudio",
518 in_name: "assets/RV/drummers.14.ra",
520 stream_type: StreamType::None,
521 dmx_reg, dec_reg: RegisteredDecoders::new(),
523 let mut mux_reg = RegisteredMuxers::new();
524 realmedia_register_all_muxers(&mut mux_reg);
525 /*let enc_config = EncoderTestParams {
529 mux_reg, enc_reg: RegisteredEncoders::new(),
531 test_remuxing(&dec_config, &enc_config);*/
532 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
533 [0x8101a484, 0xf5d80805, 0x24577596, 0x9b27262f]);
536 fn test_ra_muxer_v4() {
537 let mut dmx_reg = RegisteredDemuxers::new();
538 realmedia_register_all_demuxers(&mut dmx_reg);
539 //test sample: https://samples.mplayerhq.hu/real//RA/ra_with_comment_field/diemusik.ra
540 let dec_config = DecoderTestParams {
541 demuxer: "realaudio",
542 in_name: "assets/RV/diemusik.ra",
544 stream_type: StreamType::None,
545 dmx_reg, dec_reg: RegisteredDecoders::new(),
547 let mut mux_reg = RegisteredMuxers::new();
548 realmedia_register_all_muxers(&mut mux_reg);
549 /*let enc_config = EncoderTestParams {
553 mux_reg, enc_reg: RegisteredEncoders::new(),
555 test_remuxing(&dec_config, &enc_config);*/
556 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
557 [0x33665ec3, 0x69b68ea2, 0x08d4b138, 0x318e305f]);
560 fn test_ra_muxer_sipro() {
561 let mut dmx_reg = RegisteredDemuxers::new();
562 realmedia_register_all_demuxers(&mut dmx_reg);
563 //test sample: https://samples.mplayerhq.hu/real/AC-sipr/autahi-vox.rm
564 let dec_config = DecoderTestParams {
565 demuxer: "realmedia",
566 in_name: "assets/RV/autahi-vox.rm",
568 stream_type: StreamType::None,
569 dmx_reg, dec_reg: RegisteredDecoders::new(),
571 let mut mux_reg = RegisteredMuxers::new();
572 realmedia_register_all_muxers(&mut mux_reg);
573 /*let enc_config = EncoderTestParams {
576 out_name: "v4-sipro.ra",
577 mux_reg, enc_reg: RegisteredEncoders::new(),
579 test_remuxing(&dec_config, &enc_config);*/
580 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
581 [0x08bd496d, 0x5f35d7ae, 0xe9c93c50, 0x9e803f76]);
584 fn test_ra_muxer_v5() {
585 let mut dmx_reg = RegisteredDemuxers::new();
586 realmedia_register_all_demuxers(&mut dmx_reg);
587 //test sample: https://samples.mplayerhq.hu/real/AC-cook/cook_5.1/multichannel.rma
588 let dec_config = DecoderTestParams {
589 demuxer: "realmedia",
590 in_name: "assets/RV/multichannel.rma",
592 stream_type: StreamType::None,
593 dmx_reg, dec_reg: RegisteredDecoders::new(),
595 let mut mux_reg = RegisteredMuxers::new();
596 realmedia_register_all_muxers(&mut mux_reg);
597 /*let enc_config = EncoderTestParams {
601 mux_reg, enc_reg: RegisteredEncoders::new(),
603 test_remuxing(&dec_config, &enc_config);*/
604 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
605 [0x52f42c49, 0x90ac79a7, 0x275a465f, 0x7a6f3659]);
608 fn test_rm_muxer_aac() {
609 let mut dmx_reg = RegisteredDemuxers::new();
610 realmedia_register_all_demuxers(&mut dmx_reg);
611 //sample from a private collection
612 let dec_config = DecoderTestParams {
613 demuxer: "realmedia",
614 in_name: "assets/RV/rv40_weighted_mc_2.rmvb",
616 stream_type: StreamType::None,
617 dmx_reg, dec_reg: RegisteredDecoders::new(),
619 let mut mux_reg = RegisteredMuxers::new();
620 realmedia_register_all_muxers(&mut mux_reg);
621 /*let enc_config = EncoderTestParams {
625 mux_reg, enc_reg: RegisteredEncoders::new(),
627 test_remuxing(&dec_config, &enc_config);*/
628 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
629 [0x8392bb8c, 0xeb8f4d04, 0x25262829, 0x63b2fda7]);
632 fn test_rm_muxer_ralf() {
633 let mut dmx_reg = RegisteredDemuxers::new();
634 realmedia_register_all_demuxers(&mut dmx_reg);
635 //sample from a private collection
636 let dec_config = DecoderTestParams {
637 demuxer: "realmedia",
638 in_name: "assets/RV/rv40_ralf.rmvb",
640 stream_type: StreamType::None,
641 dmx_reg, dec_reg: RegisteredDecoders::new(),
643 let mut mux_reg = RegisteredMuxers::new();
644 realmedia_register_all_muxers(&mut mux_reg);
645 /*let enc_config = EncoderTestParams {
648 out_name: "ralf.ram",
649 mux_reg, enc_reg: RegisteredEncoders::new(),
651 test_remuxing(&dec_config, &enc_config);*/
652 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
653 [0xe90893eb, 0x8634642c, 0xef679ac4, 0x2e89314a]);