X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-commonfmt%2Fsrc%2Fcodecs%2Frawvideoenc.rs;fp=nihav-commonfmt%2Fsrc%2Fcodecs%2Frawvideoenc.rs;h=8847520829f0a328466f15700ee619dfddf1eb6d;hp=0000000000000000000000000000000000000000;hb=b36906e8e9b22a1321de11ad9b6668a800acac90;hpb=1ee737a48ec7a767c64bd72e67313ef67cfcc367 diff --git a/nihav-commonfmt/src/codecs/rawvideoenc.rs b/nihav-commonfmt/src/codecs/rawvideoenc.rs new file mode 100644 index 0000000..8847520 --- /dev/null +++ b/nihav-commonfmt/src/codecs/rawvideoenc.rs @@ -0,0 +1,100 @@ +use nihav_core::codecs::*; + +struct RawEncoder { + stream: Option, + pkt: Option, +} + +impl RawEncoder { + fn new() -> Self { + Self { + stream: None, + pkt: None, + } + } +} + +impl NAEncoder for RawEncoder { + fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult { + match encinfo.format { + NACodecTypeInfo::None => { + Ok(EncodeParameters { + format: NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT)), + ..Default::default() + }) + }, + NACodecTypeInfo::Video(_) => Ok(*encinfo), + NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError), + } + } + fn get_capabilities(&self) -> u64 { ENC_CAPS_CBR } + fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult { + match encinfo.format { + NACodecTypeInfo::None => Err(EncoderError::FormatError), + NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError), + NACodecTypeInfo::Video(_) => { + let info = NACodecInfo::new("rawvideo", encinfo.format, None); + let mut stream = NAStream::new(StreamType::Video, stream_id, info, encinfo.tb_num, encinfo.tb_den, 0); + stream.set_num(stream_id as usize); + let stream = stream.into_ref(); + self.stream = Some(stream.clone()); + Ok(stream) + } + } + } + fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> { + let buf = frm.get_buffer(); + let mut dbuf; + match buf { + NABufferType::Video(ref vbuf) => { + let vinfo = vbuf.get_info(); + if !vinfo.format.model.is_yuv() || !vinfo.format.is_unpacked() { + return Err(EncoderError::NotImplemented); + } + + let src = vbuf.get_data(); + dbuf = Vec::with_capacity(src.len()); + for (comp, cinfo) in vinfo.format.comp_info.iter().enumerate() { + if cinfo.is_none() { + continue; + } + let (width, height) = vbuf.get_dimensions(comp); + let off = vbuf.get_offset(comp); + let stride = vbuf.get_stride(comp); + + for line in src[off..].chunks(stride).take(height) { + dbuf.extend_from_slice(&line[..width]); + } + } + }, + NABufferType::VideoPacked(ref _vbuf) => return Err(EncoderError::NotImplemented), + NABufferType::Video16(ref _vbuf) => return Err(EncoderError::NotImplemented), + NABufferType::Video32(ref _vbuf) => return Err(EncoderError::NotImplemented), + NABufferType::None => { + self.pkt = None; + return Ok(()); + }, + _ => return Err(EncoderError::FormatError), + }; + self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, true, dbuf)); + Ok(()) + } + fn get_packet(&mut self) -> EncoderResult> { + let mut npkt = None; + std::mem::swap(&mut self.pkt, &mut npkt); + Ok(npkt) + } + fn flush(&mut self) -> EncoderResult<()> { + Ok(()) + } +} + +impl NAOptionHandler for RawEncoder { + fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } + fn set_options(&mut self, _options: &[NAOption]) { } + fn query_option_value(&self, _name: &str) -> Option { None } +} + +pub fn get_encoder() -> Box { + Box::new(RawEncoder::new()) +}