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<()>;
51 packetiser: Box<dyn RMStreamWriter>,
61 index: Vec<IndexEntry>,
65 fn new(strno: usize, stream: &NAStream) -> MuxerResult<Self> {
66 let packetiser = match stream.get_media_type() {
67 StreamType::Video => create_video_stream(stream)?,
68 StreamType::Audio => create_audio_stream(stream)?,
69 _ => Box::new(DummyStreamWriter{}),
73 stream_id: strno as u16,
85 fn write_mdpr(&mut self, bw: &mut ByteWriter, strm: &NAStream) -> MuxerResult<()> {
86 self.mdpr_pos = bw.tell();
88 bw.write_chunk(b"MDPR", 0, 0)?;
89 bw.write_u16be(self.stream_id as u16)?;
90 bw.write_u32be(0)?; //max br
91 bw.write_u32be(0)?; //avg br
92 bw.write_u32be(0)?; //max ps
93 bw.write_u32be(0)?; //avg ps
94 bw.write_u32be(0)?; //num packets
95 bw.write_u32be(0)?; //duration
96 bw.write_u32be(0)?; //preroll
98 match strm.get_media_type() {
99 StreamType::Video => {
100 bw.write_string(b"The Video Stream")?;
101 bw.write_string(b"video/x-pn-realvideo")?;
103 StreamType::Audio => {
104 bw.write_string(b"The Audio Stream")?;
105 bw.write_string(b"audio/x-pn-realaudio")?;
109 bw.write_string(b"some other stream")?;
110 bw.write_string(b"data")?;
113 bw.write_u32be(0)?; //extradata size
114 let edata_start = bw.tell();
115 self.packetiser.write_header(bw, strm)?;
116 let edata_end = bw.tell();
117 bw.patch_value((edata_end - edata_start) as u32, edata_start - 4)?;
119 patch_size(bw, self.mdpr_pos)?;
123 fn write_packet(&mut self, bw: &mut ByteWriter, pkt: NAPacket, pkt_no: &mut u32) -> MuxerResult<()> {
124 if let Some(pts) = pkt.get_pts() {
125 let (tb_num, tb_den) = pkt.get_stream().get_timebase();
126 let ms = NATimeInfo::ts_to_time(pts, 1000, tb_num, tb_den) as u32;
127 self.time = self.time.max(ms);
130 self.keyframe = pkt.keyframe || self.audio;
131 self.packetiser.queue_packet(pkt, self.cur_time);
132 self.write_packets(bw, pkt_no)
134 fn write_packets(&mut self, bw: &mut ByteWriter, pkt_no: &mut u32) -> MuxerResult<()> {
135 while let Some((data, ts, first)) = self.packetiser.get_packet() {
136 validate!(data.len() < 65000);
137 if self.keyframe && first {
138 self.index.push(IndexEntry{ time: ts, pos: bw.tell(), pkt_no: *pkt_no });
140 let is_keyframe = self.keyframe && (!self.audio || first);
141 bw.write_u16be(0)?; //version;
142 bw.write_u16be((data.len() + 12) as u16)?;
143 bw.write_u16be(self.stream_id)?;
145 bw.write_byte(0)?; //packet group
146 bw.write_byte(if is_keyframe { 0x2 } else { 0x0 })?;
147 bw.write_buf(&data)?;
150 self.data_size += data.len();
156 fn finish(&mut self, bw: &mut ByteWriter, pkt_no: &mut u32) -> MuxerResult<()> {
157 self.packetiser.flush();
158 self.write_packets(bw, pkt_no)?;
161 bw.seek(SeekFrom::Start(self.mdpr_pos + 12))?;
162 bw.write_u32be(if self.time > 0 { (self.data_size * 1000 / (self.time as usize)) as u32 } else { 0 })?;
163 bw.write_u32be(if self.time > 0 { (self.data_size * 1000 / (self.time as usize)) as u32 } else { 0 })?;
164 bw.write_u32be(self.max_pkt_size as u32)?;
165 bw.write_u32be(if self.npkts > 0 { (self.data_size / self.npkts) as u32 } else { 0 })?;
166 bw.seek(SeekFrom::Current(8))?;
167 bw.write_u32be(self.time)?;
169 bw.seek(SeekFrom::Start(pos))?;
175 bw: &'a mut ByteWriter<'a>,
176 streams: Vec<RMStream>,
182 impl<'a> RMMuxer<'a> {
183 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
192 fn write_index(&mut self) -> MuxerResult<()> {
193 let mut indx_pos = 0x38;
195 for stream in self.streams.iter() {
196 let cur_pos = self.bw.tell();
197 self.bw.patch_value(cur_pos as u32, indx_pos)?;
198 indx_pos = cur_pos + 16;
200 let idx_size = 10 + 10 + stream.index.len() * 14;
201 self.bw.write_chunk(b"INDX", idx_size as u32, 0)?;
202 self.bw.write_u32be(stream.index.len() as u32)?;
203 self.bw.write_u16be(stream.stream_id)?;
204 self.bw.write_u32be(0)?; // next index position
205 for entry in stream.index.iter() {
206 self.bw.write_u16be(0)?; // version
207 self.bw.write_u32be(entry.time)?;
208 self.bw.write_u32be(entry.pos as u32)?;
209 self.bw.write_u32be(entry.pkt_no)?;
212 self.num_chunks += 1;
217 fn update_prop(&mut self) -> MuxerResult<()> {
218 let mut data_size = 0;
220 let mut max_pkt_size = 0;
223 for stream in self.streams.iter() {
224 data_size += stream.data_size;
225 time = time.max(stream.time);
226 npkts += stream.npkts;
227 max_pkt_size = max_pkt_size.max(stream.max_pkt_size);
230 if npkts > 0 && time > 0 {
231 let cur_pos = self.bw.tell();
233 let bitrate = (data_size * 1000 / (time as usize)) as u32;
234 self.bw.seek(SeekFrom::Start(28))?;
235 self.bw.write_u32be(bitrate)?;
236 self.bw.write_u32be(bitrate)?;
237 self.bw.write_u32be(max_pkt_size as u32)?;
238 self.bw.write_u32be((data_size / npkts) as u32)?;
239 self.bw.write_u32be(npkts as u32)?;
240 self.bw.write_u32be(time)?;
242 self.bw.seek(SeekFrom::Start(cur_pos))?;
245 self.bw.patch_value(self.data_pos as u32, 0x3C)?;
251 fn patch_size(bw: &mut ByteWriter, pos: u64) -> MuxerResult<()> {
253 bw.patch_value((end - pos) as u32, pos + 4)
256 impl<'a> MuxCore<'a> for RMMuxer<'a> {
257 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
258 if strmgr.get_num_streams() == 0 {
259 return Err(MuxerError::InvalidArgument);
261 if strmgr.get_num_streams() > 100 {
262 return Err(MuxerError::UnsupportedFormat);
265 self.bw.write_chunk(b".RMF", 18, 0)?;
266 self.bw.write_u32be(0)?; // container version
267 self.bw.write_u32be(0)?; // number of chunks
270 let prop_start = self.bw.tell();
271 self.bw.write_chunk(b"PROP", 0, 0)?;
272 self.bw.write_u32be(0)?; //max br
273 self.bw.write_u32be(0)?; //avg br
274 self.bw.write_u32be(0)?; //max ps
275 self.bw.write_u32be(0)?; //avg ps
276 self.bw.write_u32be(0)?; //num packets
277 self.bw.write_u32be(0)?; //duration
278 self.bw.write_u32be(0)?; //preroll
279 self.bw.write_u32be(0)?; //index offset
280 self.bw.write_u32be(0)?; //data offset
281 self.bw.write_u16be(strmgr.get_num_streams() as u16)?;
282 self.bw.write_u16be(0)?; // flags
283 patch_size(self.bw, prop_start)?;
285 self.streams.clear();
286 for (strno, strm) in strmgr.iter().enumerate() {
287 let mut swriter = RMStream::new(strno, &strm)?;
288 swriter.write_mdpr(self.bw, &strm)?;
289 self.streams.push(swriter);
290 self.num_chunks += 1;
293 self.data_pos = self.bw.tell();
294 self.bw.write_chunk(b"DATA", 0, 0)?;
295 self.bw.write_u32be(0)?; //num packets
296 self.bw.write_u32be(0)?; //next data chunk
297 self.num_chunks += 1;
301 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
302 if self.data_pos == 0 {
303 return Err(MuxerError::NotCreated);
305 let stream = pkt.get_stream();
306 let str_num = stream.get_num();
307 if str_num > self.streams.len() {
308 return Err(MuxerError::UnsupportedFormat);
310 self.streams[str_num].write_packet(self.bw, pkt, &mut self.cur_packet)?;
314 fn flush(&mut self) -> MuxerResult<()> {
317 fn end(&mut self) -> MuxerResult<()> {
318 if self.data_pos == 0 {
319 return Err(MuxerError::NotCreated);
321 let mut tot_npkts = 0;
322 for stream in self.streams.iter_mut() {
323 stream.finish(self.bw, &mut self.cur_packet)?;
324 tot_npkts += stream.npkts;
327 let data_size = self.bw.tell() - self.data_pos;
328 self.bw.patch_value(data_size as u32, self.data_pos + 4)?;
329 self.bw.patch_value(tot_npkts as u32, self.data_pos + 10)?;
334 self.bw.patch_value(self.num_chunks, 14)?;
339 impl<'a> NAOptionHandler for RMMuxer<'a> {
340 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
341 fn set_options(&mut self, _options: &[NAOption]) { }
342 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
345 pub struct RealMediaMuxerCreator {}
347 impl MuxerCreator for RealMediaMuxerCreator {
348 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
349 Box::new(RMMuxer::new(bw))
351 fn get_name(&self) -> &'static str { "realmedia" }
352 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::Universal }
356 bw: &'a mut ByteWriter<'a>,
357 sw: Option<Box<dyn RMStreamWriter>>,
360 impl<'a> RAMuxer<'a> {
361 fn new(bw: &'a mut ByteWriter<'a>) -> Self {
369 impl<'a> MuxCore<'a> for RAMuxer<'a> {
370 fn create(&mut self, strmgr: &StreamManager) -> MuxerResult<()> {
371 if strmgr.get_num_streams() != 1 {
372 return Err(MuxerError::InvalidArgument);
374 let astream = strmgr.get_stream(0).unwrap();
375 if astream.get_media_type() != StreamType::Audio {
376 return Err(MuxerError::InvalidArgument);
378 self.sw = Some(create_audio_stream(&astream)?);
379 if let Some(ref mut sw) = self.sw {
380 sw.write_header(self.bw, &astream)?;
384 fn mux_frame(&mut self, _strmgr: &StreamManager, pkt: NAPacket) -> MuxerResult<()> {
385 if let Some(ref mut sw) = self.sw {
386 sw.queue_packet(pkt, 0);
387 while let Some((data, _, _)) = sw.get_packet() {
388 self.bw.write_buf(&data)?;
392 Err(MuxerError::NotCreated)
395 fn flush(&mut self) -> MuxerResult<()> {
398 fn end(&mut self) -> MuxerResult<()> {
399 if let Some(ref mut sw) = self.sw {
400 sw.finish(&mut self.bw)?;
406 impl<'a> NAOptionHandler for RAMuxer<'a> {
407 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
408 fn set_options(&mut self, _options: &[NAOption]) { }
409 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
412 pub struct RealAudioMuxerCreator {}
414 impl MuxerCreator for RealAudioMuxerCreator {
415 fn new_muxer<'a>(&self, bw: &'a mut ByteWriter<'a>) -> Box<dyn MuxCore<'a> + 'a> {
416 Box::new(RAMuxer::new(bw))
418 fn get_name(&self) -> &'static str { "realaudio" }
419 fn get_capabilities(&self) -> MuxerCapabilities { MuxerCapabilities::SingleAudio("any") }
424 use nihav_core::codecs::*;
425 use nihav_core::demuxers::*;
426 use nihav_core::muxers::*;
427 use nihav_codec_support::test::enc_video::*;
432 let mut dmx_reg = RegisteredDemuxers::new();
433 realmedia_register_all_demuxers(&mut dmx_reg);
434 // sample from a private collection
435 let dec_config = DecoderTestParams {
436 demuxer: "realmedia",
437 in_name: "assets/RV/rv30_weighted_mc.rm",
439 stream_type: StreamType::None,
440 dmx_reg, dec_reg: RegisteredDecoders::new(),
442 let mut mux_reg = RegisteredMuxers::new();
443 realmedia_register_all_muxers(&mut mux_reg);
444 /*let enc_config = EncoderTestParams {
447 out_name: "muxed.rm",
448 mux_reg, enc_reg: RegisteredEncoders::new(),
450 test_remuxing(&dec_config, &enc_config);*/
451 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
452 [0x26422839, 0xa2d7bdd1, 0xd6ea2a78, 0x1b58033a]);
456 fn test_ra_muxer_v3() {
457 let mut dmx_reg = RegisteredDemuxers::new();
458 realmedia_register_all_demuxers(&mut dmx_reg);
459 //test sample: https://samples.mplayerhq.hu/real/RA/14_4/drummers.14.ra
460 let dec_config = DecoderTestParams {
461 demuxer: "realaudio",
462 in_name: "assets/RV/drummers.14.ra",
464 stream_type: StreamType::None,
465 dmx_reg, dec_reg: RegisteredDecoders::new(),
467 let mut mux_reg = RegisteredMuxers::new();
468 realmedia_register_all_muxers(&mut mux_reg);
469 /*let enc_config = EncoderTestParams {
473 mux_reg, enc_reg: RegisteredEncoders::new(),
475 test_remuxing(&dec_config, &enc_config);*/
476 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
477 [0x8101a484, 0xf5d80805, 0x24577596, 0x9b27262f]);
480 fn test_ra_muxer_v4() {
481 let mut dmx_reg = RegisteredDemuxers::new();
482 realmedia_register_all_demuxers(&mut dmx_reg);
483 //test sample: https://samples.mplayerhq.hu/real//RA/ra_with_comment_field/diemusik.ra
484 let dec_config = DecoderTestParams {
485 demuxer: "realaudio",
486 in_name: "assets/RV/diemusik.ra",
488 stream_type: StreamType::None,
489 dmx_reg, dec_reg: RegisteredDecoders::new(),
491 let mut mux_reg = RegisteredMuxers::new();
492 realmedia_register_all_muxers(&mut mux_reg);
493 /*let enc_config = EncoderTestParams {
497 mux_reg, enc_reg: RegisteredEncoders::new(),
499 test_remuxing(&dec_config, &enc_config);*/
500 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
501 [0x33665ec3, 0x69b68ea2, 0x08d4b138, 0x318e305f]);
504 fn test_ra_muxer_sipro() {
505 let mut dmx_reg = RegisteredDemuxers::new();
506 realmedia_register_all_demuxers(&mut dmx_reg);
507 //test sample: https://samples.mplayerhq.hu/real/AC-sipr/autahi-vox.rm
508 let dec_config = DecoderTestParams {
509 demuxer: "realmedia",
510 in_name: "assets/RV/autahi-vox.rm",
512 stream_type: StreamType::None,
513 dmx_reg, dec_reg: RegisteredDecoders::new(),
515 let mut mux_reg = RegisteredMuxers::new();
516 realmedia_register_all_muxers(&mut mux_reg);
517 /*let enc_config = EncoderTestParams {
520 out_name: "v4-sipro.ra",
521 mux_reg, enc_reg: RegisteredEncoders::new(),
523 test_remuxing(&dec_config, &enc_config);*/
524 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
525 [0x08bd496d, 0x5f35d7ae, 0xe9c93c50, 0x9e803f76]);
528 fn test_ra_muxer_v5() {
529 let mut dmx_reg = RegisteredDemuxers::new();
530 realmedia_register_all_demuxers(&mut dmx_reg);
531 //test sample: https://samples.mplayerhq.hu/real/AC-cook/cook_5.1/multichannel.rma
532 let dec_config = DecoderTestParams {
533 demuxer: "realmedia",
534 in_name: "assets/RV/multichannel.rma",
536 stream_type: StreamType::None,
537 dmx_reg, dec_reg: RegisteredDecoders::new(),
539 let mut mux_reg = RegisteredMuxers::new();
540 realmedia_register_all_muxers(&mut mux_reg);
541 /*let enc_config = EncoderTestParams {
545 mux_reg, enc_reg: RegisteredEncoders::new(),
547 test_remuxing(&dec_config, &enc_config);*/
548 test_remuxing_md5(&dec_config, "realaudio", &mux_reg,
549 [0x52f42c49, 0x90ac79a7, 0x275a465f, 0x7a6f3659]);
552 fn test_rm_muxer_aac() {
553 let mut dmx_reg = RegisteredDemuxers::new();
554 realmedia_register_all_demuxers(&mut dmx_reg);
555 //sample from a private collection
556 let dec_config = DecoderTestParams {
557 demuxer: "realmedia",
558 in_name: "assets/RV/rv40_weighted_mc_2.rmvb",
560 stream_type: StreamType::None,
561 dmx_reg, dec_reg: RegisteredDecoders::new(),
563 let mut mux_reg = RegisteredMuxers::new();
564 realmedia_register_all_muxers(&mut mux_reg);
565 /*let enc_config = EncoderTestParams {
569 mux_reg, enc_reg: RegisteredEncoders::new(),
571 test_remuxing(&dec_config, &enc_config);*/
572 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
573 [0xcfa1a27b, 0x78314fa7, 0xeb90c31c, 0x7eafeaa8]);
576 fn test_rm_muxer_ralf() {
577 let mut dmx_reg = RegisteredDemuxers::new();
578 realmedia_register_all_demuxers(&mut dmx_reg);
579 //sample from a private collection
580 let dec_config = DecoderTestParams {
581 demuxer: "realmedia",
582 in_name: "assets/RV/rv40_ralf.rmvb",
584 stream_type: StreamType::None,
585 dmx_reg, dec_reg: RegisteredDecoders::new(),
587 let mut mux_reg = RegisteredMuxers::new();
588 realmedia_register_all_muxers(&mut mux_reg);
589 /*let enc_config = EncoderTestParams {
592 out_name: "ralf.ram",
593 mux_reg, enc_reg: RegisteredEncoders::new(),
595 test_remuxing(&dec_config, &enc_config);*/
596 test_remuxing_md5(&dec_config, "realmedia", &mux_reg,
597 [0xa0c336d1, 0x76221455, 0x75252067, 0x6189d4af]);