]>
Commit | Line | Data |
---|---|---|
9dc1fb4b KS |
1 | use nihav_core::frame::*; |
2 | use nihav_core::muxers::*; | |
3 | use super::RMStreamWriter; | |
4 | ||
5 | static 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 | ||
15 | pub struct DummyStreamWriter {} | |
16 | impl 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 | ||
32 | struct 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 | ||
42 | impl 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 | ||
158 | pub 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 | } |