| 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, _ms: u32) -> bool { |
| 21 | true |
| 22 | } |
| 23 | fn get_packet(&mut self) -> Option<(Vec<u8>, u32, 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 | time: u32, |
| 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 | } |
| 79 | fn queue_packet(&mut self, pkt: NAPacket, ms: u32) -> bool { |
| 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); |
| 88 | self.time = ms; |
| 89 | } |
| 90 | true |
| 91 | } else { |
| 92 | false |
| 93 | } |
| 94 | } |
| 95 | fn get_packet(&mut self) -> Option<(Vec<u8>, u32, bool)> { |
| 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 | } |
| 143 | Some((ret, self.time, first)) |
| 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, |
| 166 | time: 0, |
| 167 | })); |
| 168 | } |
| 169 | } |
| 170 | Err(MuxerError::UnsupportedFormat) |
| 171 | } |