rmmux: generate monotone timestamps for video stream
[nihav.git] / nihav-realmedia / src / muxers / rmvb / videostream.rs
CommitLineData
9dc1fb4b
KS
1use nihav_core::frame::*;
2use nihav_core::muxers::*;
3use super::RMStreamWriter;
4
5static VIDEO_CODEC_REGISTRY: &[(&[u8;4], &str)] = &[
6 (b"RV10", "realvideo1"),
7 (b"RV20", "realvideo2"),
8 (b"RVTR", "realvideo2"),
9 (b"RV30", "realvideo3"),
10 (b"RV40", "realvideo4"),
11 (b"RV60", "realvideo6"),
12 (b"CLV1", "clearvideo_rm"),
13];
14
15pub struct DummyStreamWriter {}
16impl RMStreamWriter for DummyStreamWriter {
17 fn write_header(&mut self, _bw: &mut ByteWriter, _stream: &NAStream) -> MuxerResult<()> {
18 Ok(())
19 }
c5963b17 20 fn queue_packet(&mut self, _pkt: NAPacket, _ms: u32) -> bool {
9dc1fb4b
KS
21 true
22 }
c5963b17 23 fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)> {
9dc1fb4b
KS
24 None
25 }
26 fn flush(&mut self) { }
27 fn finish(&mut self, _bw: &mut ByteWriter) -> MuxerResult<()> {
28 Ok(())
29 }
30}
31
32struct VideoStreamWriter {
33 fcc: [u8; 4],
34 buf: Vec<u8>,
35 nslices: usize,
36 cur_slice: usize,
37 seq_no: u8,
c5963b17 38 time: u32,
e0d229ca 39 mi_time: u32,
9dc1fb4b
KS
40}
41
42impl RMStreamWriter for VideoStreamWriter {
43 fn write_header(&mut self, bw: &mut ByteWriter, vstream: &NAStream) -> MuxerResult<()> {
44 let info = vstream.get_info().get_properties().get_video_info().unwrap();
45 let start = bw.tell();
46
47 bw.write_u32be(0)?; // header size
48 bw.write_buf(b"VIDO")?;
49 bw.write_buf(&self.fcc)?;
50 bw.write_u16be(info.width as u16)?;
51 bw.write_u16be(info.height as u16)?;
52 bw.write_u16be(12)?; // bpp
53 bw.write_u16be(0)?; // aligned width
54 bw.write_u16be(0)?; // aligned height
55 let (tb_num, tb_den) = vstream.get_timebase();
56 if tb_num != 0 && tb_den != 0 {
57 bw.write_u16be((tb_den / tb_num) as u16)?;
58 let mut fps_frac = tb_den % tb_num;
59 let mut div = tb_num;
60 while div >= 0x10000 {
61 fps_frac >>= 1;
62 div >>= 1;
63 }
64 fps_frac = (fps_frac << 16) / div;
65 bw.write_u16le(fps_frac as u16)?;
66 } else {
67 bw.write_u16be(0)?;
68 bw.write_u16be(0)?;
69 }
70
71 if let Some(edata) = vstream.get_info().get_extradata() {
72 bw.write_buf(&edata)?;
73 }
74 let end = bw.tell();
75 bw.seek(SeekFrom::Start(start))?;
76 bw.write_u32be((end - start) as u32)?;
77 bw.seek(SeekFrom::Start(end))?;
78 Ok(())
79 }
c5963b17 80 fn queue_packet(&mut self, pkt: NAPacket, ms: u32) -> bool {
9dc1fb4b
KS
81 if self.nslices == 0 {
82 let src = pkt.get_buffer();
83 let nslices = usize::from(src[0]) + 1;
84 if src.len() > nslices * 8 + 1 {
85 self.nslices = nslices;
86 self.cur_slice = 0;
87 self.buf.resize(src.len(), 0);
88 self.buf.copy_from_slice(&src);
c5963b17 89 self.time = ms;
e0d229ca
KS
90 if ms > 0 {
91 self.mi_time = ms.max(self.mi_time + 1);
92 }
9dc1fb4b
KS
93 }
94 true
95 } else {
96 false
97 }
98 }
c5963b17 99 fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)> {
9dc1fb4b
KS
100 if self.cur_slice < self.nslices {
101 let first = self.cur_slice == 0;
102 let hdr_size = self.nslices * 8 + 1;
103 let cur_off = (read_u32be(&self.buf[self.cur_slice * 8 + 5..]).unwrap_or(0) as usize) + hdr_size;
104 let next_off = if self.cur_slice + 1 < self.nslices {
105 (read_u32be(&self.buf[self.cur_slice * 8 + 13..]).unwrap_or(0) as usize) + hdr_size
106 } else {
107 self.buf.len()
108 };
109 let next_off = next_off.max(cur_off);
110 let src = &self.buf[cur_off..next_off];
111 let ret = if self.nslices == 1 {
112 let mut dst = vec![0; src.len() + 2];
113 dst[0] = 0x40;
114 dst[1] = self.seq_no;
115 dst[2..].copy_from_slice(src);
116 dst
117 } else {
118 let mut dst = Vec::with_capacity(src.len() + 11);
119 let mut gw = GrowableMemoryWriter::new_write(&mut dst);
120 let mut bw = ByteWriter::new(&mut gw);
121
122 let hdr = ((self.nslices as u16) << 7) | ((self.cur_slice + 1) as u16);
123 bw.write_u16be(hdr).unwrap();
124
125 let full_size = self.buf.len() - hdr_size;
126 if full_size < (1 << 14) {
127 bw.write_u16be(0xC000 | (full_size as u16)).unwrap();
128 } else {
129 bw.write_u32be(0x80000000 | (full_size as u32)).unwrap();
130 }
131 let coff = cur_off - hdr_size;
132 if coff < (1 << 14) {
133 bw.write_u16be(0x4000 | (coff as u16)).unwrap();
134 } else {
135 bw.write_u32be(coff as u32).unwrap();
136 }
137 bw.write_byte(self.seq_no).unwrap();
138 bw.write_buf(src).unwrap();
139 dst
140 };
141 self.cur_slice += 1;
142 if self.cur_slice == self.nslices {
143 self.nslices = 0;
144 self.cur_slice = 0;
145 self.seq_no = self.seq_no.wrapping_add(1);
146 }
e0d229ca 147 Some((ret, self.mi_time, first))
9dc1fb4b
KS
148 } else {
149 None
150 }
151 }
152 fn flush(&mut self) { }
153 fn finish(&mut self, _bw: &mut ByteWriter) -> MuxerResult<()> {
154 Ok(())
155 }
156}
157
158pub fn create_video_stream(stream: &NAStream) -> MuxerResult<Box<dyn RMStreamWriter>> {
159 let info = stream.get_info();
160 let cname = info.get_name();
161
162 for &(fcc, name) in VIDEO_CODEC_REGISTRY.iter() {
163 if name == cname {
164 return Ok(Box::new(VideoStreamWriter {
165 fcc: *fcc,
166 buf: Vec::new(),
167 nslices: 0,
168 cur_slice: 0,
169 seq_no: 0,
c5963b17 170 time: 0,
e0d229ca 171 mi_time: 0,
9dc1fb4b
KS
172 }));
173 }
174 }
175 Err(MuxerError::UnsupportedFormat)
176}