Commit | Line | Data |
---|---|---|
a715e99f KS |
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 | } |