]>
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 | }, | |
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 | ||
100 | impl 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 | ||
106 | pub fn get_encoder() -> Box<dyn NAEncoder + Send> { | |
107 | Box::new(RawEncoder::new()) | |
108 | } |