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