introduce raw video "codec"
[nihav.git] / nihav-commonfmt / src / codecs / rawvideo.rs
1 use nihav_core::codecs::*;
2
3 struct RawDecoder {
4 info: NACodecInfoRef,
5 }
6
7 impl RawDecoder {
8 fn new() -> Self {
9 Self {
10 info: NACodecInfo::new_dummy(),
11 }
12 }
13 }
14
15 impl NADecoder for RawDecoder {
16 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
17 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
18 self.info = info.clone();
19 Ok(())
20 } else {
21 Err(DecoderError::InvalidData)
22 }
23 }
24 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
25 if let NACodecTypeInfo::Video(ref vinfo) = self.info.get_properties() {
26 let src = pkt.get_buffer();
27 let width = vinfo.width;
28 let height = vinfo.height;
29 let ncomp = vinfo.format.components as usize;
30 let buf = if vinfo.format.is_unpacked() && vinfo.format.get_max_depth() == 8 {
31 let mut offs = vec![0; ncomp];
32 let mut strides = Vec::with_capacity(ncomp);
33 let mut sizes = Vec::with_capacity(ncomp);
34 for chr in vinfo.format.comp_info[..ncomp].iter() {
35 if let Some(chromaton) = chr {
36 let stride = chromaton.get_linesize(width);
37 let size = stride * chromaton.get_height(height);
38 sizes.push(size);
39 strides.push(stride);
40 } else {
41 return Err(DecoderError::InvalidData);
42 }
43 }
44 let mut off = 0;
45 for i in 0..ncomp {
46 for (cno, chr) in vinfo.format.comp_info[..ncomp].iter().enumerate() {
47 if let Some(chromaton) = chr {
48 let comp_off = chromaton.comp_offs as usize;
49 validate!(comp_off < ncomp);
50 if comp_off != i {
51 continue;
52 }
53 offs[cno] = off;
54 off += sizes[i];
55 }
56 }
57 }
58 validate!(off == src.len());
59
60 NABufferType::Video(NAVideoBuffer::from_raw_parts(vinfo.clone(), src.clone(), offs, strides).into_ref())
61 } else {
62 let offs = vec![0; ncomp];
63 let strides = vec![0; ncomp];
64 NABufferType::VideoPacked(NAVideoBuffer::from_raw_parts(vinfo.clone(), src.clone(), offs, strides).into_ref())
65 };
66
67 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buf);
68 frm.set_keyframe(true);
69 frm.set_frame_type(FrameType::I);
70 Ok(frm.into_ref())
71 } else {
72 Err(DecoderError::Bug)
73 }
74 }
75 fn flush(&mut self) {}
76 }
77
78
79 impl NAOptionHandler for RawDecoder {
80 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
81 fn set_options(&mut self, _options: &[NAOption]) { }
82 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
83 }
84
85 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
86 Box::new(RawDecoder::new())
87 }
88
89 #[cfg(test)]
90 mod test {
91 use nihav_core::codecs::RegisteredDecoders;
92 use nihav_core::demuxers::RegisteredDemuxers;
93 use nihav_codec_support::test::dec_video::*;
94 use crate::generic_register_all_decoders;
95 use crate::generic_register_all_demuxers;
96 #[test]
97 fn test_rawvideo() {
98 let mut dmx_reg = RegisteredDemuxers::new();
99 generic_register_all_demuxers(&mut dmx_reg);
100 let mut dec_reg = RegisteredDecoders::new();
101 generic_register_all_decoders(&mut dec_reg);
102 test_decoding("yuv4mpeg", "rawvideo", "assets/Misc/test.y4m", None, &dmx_reg,
103 &dec_reg, ExpectedTestResult::MD5Frames(vec![
104 [0xd58326b0, 0xdbfc1dcc, 0x6d66a04c, 0x08a21bbb],
105 [0x9b2cb5c5, 0x69b5f261, 0xcaccaaaf, 0xff2a807d]]));
106 }
107 }