rawvideoenc: suggest YUV during format negotiation
[nihav.git] / nihav-commonfmt / src / codecs / rawvideoenc.rs
CommitLineData
b36906e8
KS
1use nihav_core::codecs::*;
2
3struct RawEncoder {
4 stream: Option<NAStreamRef>,
5 pkt: Option<NAPacket>,
6}
7
8impl RawEncoder {
9 fn new() -> Self {
10 Self {
11 stream: None,
12 pkt: None,
13 }
14 }
15}
16
17impl NAEncoder for RawEncoder {
18 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
19 match encinfo.format {
20 NACodecTypeInfo::None => {
21 Ok(EncodeParameters {
22 format: NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, YUV420_FORMAT)),
23 ..Default::default()
24 })
25 },
e9aa1a76
KS
26 NACodecTypeInfo::Video(_) => {
27 let mut new_info = *encinfo;
28 if let NACodecTypeInfo::Video(ref mut vinfo) = new_info.format {
29 if !vinfo.format.model.is_yuv() {
30 vinfo.format = YUV420_FORMAT;
31 }
32 }
33 Ok(new_info)
34 },
b36906e8
KS
35 NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError),
36 }
37 }
38 fn get_capabilities(&self) -> u64 { ENC_CAPS_CBR }
39 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
40 match encinfo.format {
41 NACodecTypeInfo::None => Err(EncoderError::FormatError),
42 NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError),
43 NACodecTypeInfo::Video(_) => {
44 let info = NACodecInfo::new("rawvideo", encinfo.format, None);
45 let mut stream = NAStream::new(StreamType::Video, stream_id, info, encinfo.tb_num, encinfo.tb_den, 0);
46 stream.set_num(stream_id as usize);
47 let stream = stream.into_ref();
48 self.stream = Some(stream.clone());
49 Ok(stream)
50 }
51 }
52 }
53 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
54 let buf = frm.get_buffer();
55 let mut dbuf;
56 match buf {
57 NABufferType::Video(ref vbuf) => {
58 let vinfo = vbuf.get_info();
59 if !vinfo.format.model.is_yuv() || !vinfo.format.is_unpacked() {
60 return Err(EncoderError::NotImplemented);
61 }
62
63 let src = vbuf.get_data();
64 dbuf = Vec::with_capacity(src.len());
65 for (comp, cinfo) in vinfo.format.comp_info.iter().enumerate() {
66 if cinfo.is_none() {
67 continue;
68 }
69 let (width, height) = vbuf.get_dimensions(comp);
70 let off = vbuf.get_offset(comp);
71 let stride = vbuf.get_stride(comp);
72
73 for line in src[off..].chunks(stride).take(height) {
74 dbuf.extend_from_slice(&line[..width]);
75 }
76 }
77 },
78 NABufferType::VideoPacked(ref _vbuf) => return Err(EncoderError::NotImplemented),
79 NABufferType::Video16(ref _vbuf) => return Err(EncoderError::NotImplemented),
80 NABufferType::Video32(ref _vbuf) => return Err(EncoderError::NotImplemented),
81 NABufferType::None => {
82 self.pkt = None;
83 return Ok(());
84 },
85 _ => return Err(EncoderError::FormatError),
86 };
87 self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, true, dbuf));
88 Ok(())
89 }
90 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
91 let mut npkt = None;
92 std::mem::swap(&mut self.pkt, &mut npkt);
93 Ok(npkt)
94 }
95 fn flush(&mut self) -> EncoderResult<()> {
96 Ok(())
97 }
98}
99
100impl NAOptionHandler for RawEncoder {
101 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
102 fn set_options(&mut self, _options: &[NAOption]) { }
103 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
104}
105
106pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
107 Box::new(RawEncoder::new())
108}