]>
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, |
9dc1fb4b KS |
39 | } |
40 | ||
41 | impl RMStreamWriter for VideoStreamWriter { | |
42 | fn write_header(&mut self, bw: &mut ByteWriter, vstream: &NAStream) -> MuxerResult<()> { | |
43 | let info = vstream.get_info().get_properties().get_video_info().unwrap(); | |
44 | let start = bw.tell(); | |
45 | ||
46 | bw.write_u32be(0)?; // header size | |
47 | bw.write_buf(b"VIDO")?; | |
48 | bw.write_buf(&self.fcc)?; | |
49 | bw.write_u16be(info.width as u16)?; | |
50 | bw.write_u16be(info.height as u16)?; | |
51 | bw.write_u16be(12)?; // bpp | |
52 | bw.write_u16be(0)?; // aligned width | |
53 | bw.write_u16be(0)?; // aligned height | |
54 | let (tb_num, tb_den) = vstream.get_timebase(); | |
55 | if tb_num != 0 && tb_den != 0 { | |
56 | bw.write_u16be((tb_den / tb_num) as u16)?; | |
57 | let mut fps_frac = tb_den % tb_num; | |
58 | let mut div = tb_num; | |
59 | while div >= 0x10000 { | |
60 | fps_frac >>= 1; | |
61 | div >>= 1; | |
62 | } | |
63 | fps_frac = (fps_frac << 16) / div; | |
64 | bw.write_u16le(fps_frac as u16)?; | |
65 | } else { | |
66 | bw.write_u16be(0)?; | |
67 | bw.write_u16be(0)?; | |
68 | } | |
69 | ||
70 | if let Some(edata) = vstream.get_info().get_extradata() { | |
71 | bw.write_buf(&edata)?; | |
72 | } | |
73 | let end = bw.tell(); | |
74 | bw.seek(SeekFrom::Start(start))?; | |
75 | bw.write_u32be((end - start) as u32)?; | |
76 | bw.seek(SeekFrom::Start(end))?; | |
77 | Ok(()) | |
78 | } | |
c5963b17 | 79 | fn queue_packet(&mut self, pkt: NAPacket, ms: u32) -> bool { |
9dc1fb4b KS |
80 | if self.nslices == 0 { |
81 | let src = pkt.get_buffer(); | |
82 | let nslices = usize::from(src[0]) + 1; | |
83 | if src.len() > nslices * 8 + 1 { | |
84 | self.nslices = nslices; | |
85 | self.cur_slice = 0; | |
86 | self.buf.resize(src.len(), 0); | |
87 | self.buf.copy_from_slice(&src); | |
c5963b17 | 88 | self.time = ms; |
9dc1fb4b KS |
89 | } |
90 | true | |
91 | } else { | |
92 | false | |
93 | } | |
94 | } | |
c5963b17 | 95 | fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)> { |
9dc1fb4b KS |
96 | if self.cur_slice < self.nslices { |
97 | let first = self.cur_slice == 0; | |
98 | let hdr_size = self.nslices * 8 + 1; | |
99 | let cur_off = (read_u32be(&self.buf[self.cur_slice * 8 + 5..]).unwrap_or(0) as usize) + hdr_size; | |
100 | let next_off = if self.cur_slice + 1 < self.nslices { | |
101 | (read_u32be(&self.buf[self.cur_slice * 8 + 13..]).unwrap_or(0) as usize) + hdr_size | |
102 | } else { | |
103 | self.buf.len() | |
104 | }; | |
105 | let next_off = next_off.max(cur_off); | |
106 | let src = &self.buf[cur_off..next_off]; | |
107 | let ret = if self.nslices == 1 { | |
108 | let mut dst = vec![0; src.len() + 2]; | |
109 | dst[0] = 0x40; | |
110 | dst[1] = self.seq_no; | |
111 | dst[2..].copy_from_slice(src); | |
112 | dst | |
113 | } else { | |
114 | let mut dst = Vec::with_capacity(src.len() + 11); | |
115 | let mut gw = GrowableMemoryWriter::new_write(&mut dst); | |
116 | let mut bw = ByteWriter::new(&mut gw); | |
117 | ||
118 | let hdr = ((self.nslices as u16) << 7) | ((self.cur_slice + 1) as u16); | |
119 | bw.write_u16be(hdr).unwrap(); | |
120 | ||
121 | let full_size = self.buf.len() - hdr_size; | |
122 | if full_size < (1 << 14) { | |
123 | bw.write_u16be(0xC000 | (full_size as u16)).unwrap(); | |
124 | } else { | |
125 | bw.write_u32be(0x80000000 | (full_size as u32)).unwrap(); | |
126 | } | |
127 | let coff = cur_off - hdr_size; | |
128 | if coff < (1 << 14) { | |
129 | bw.write_u16be(0x4000 | (coff as u16)).unwrap(); | |
130 | } else { | |
131 | bw.write_u32be(coff as u32).unwrap(); | |
132 | } | |
133 | bw.write_byte(self.seq_no).unwrap(); | |
134 | bw.write_buf(src).unwrap(); | |
135 | dst | |
136 | }; | |
137 | self.cur_slice += 1; | |
138 | if self.cur_slice == self.nslices { | |
139 | self.nslices = 0; | |
140 | self.cur_slice = 0; | |
141 | self.seq_no = self.seq_no.wrapping_add(1); | |
142 | } | |
c5963b17 | 143 | Some((ret, self.time, first)) |
9dc1fb4b KS |
144 | } else { |
145 | None | |
146 | } | |
147 | } | |
148 | fn flush(&mut self) { } | |
149 | fn finish(&mut self, _bw: &mut ByteWriter) -> MuxerResult<()> { | |
150 | Ok(()) | |
151 | } | |
152 | } | |
153 | ||
154 | pub fn create_video_stream(stream: &NAStream) -> MuxerResult<Box<dyn RMStreamWriter>> { | |
155 | let info = stream.get_info(); | |
156 | let cname = info.get_name(); | |
157 | ||
158 | for &(fcc, name) in VIDEO_CODEC_REGISTRY.iter() { | |
159 | if name == cname { | |
160 | return Ok(Box::new(VideoStreamWriter { | |
161 | fcc: *fcc, | |
162 | buf: Vec::new(), | |
163 | nslices: 0, | |
164 | cur_slice: 0, | |
165 | seq_no: 0, | |
c5963b17 | 166 | time: 0, |
9dc1fb4b KS |
167 | })); |
168 | } | |
169 | } | |
170 | Err(MuxerError::UnsupportedFormat) | |
171 | } |