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