/src/mp4san/webpsan/src/parse/vp8l.rs
Line | Count | Source |
1 | | #![allow(missing_docs)] |
2 | | |
3 | | use std::fmt::Debug; |
4 | | use std::io::{Cursor, Read}; |
5 | | use std::num::NonZeroU16; |
6 | | use std::result::Result as StdResult; |
7 | | |
8 | | use bitstream_io::{BitRead, BitReader, LE}; |
9 | | use bytes::{Buf, BytesMut}; |
10 | | use derive_more::Display; |
11 | | use mediasan_common::ensure_attach; |
12 | | use mediasan_common::parse::FourCC; |
13 | | use mediasan_common::Result; |
14 | | |
15 | | use crate::Error; |
16 | | |
17 | | use super::bitstream::BitBufReader; |
18 | | use super::chunk_type::VP8L; |
19 | | use super::lossless::LosslessImage; |
20 | | use super::{ParseChunk, ParseError}; |
21 | | |
22 | | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
23 | | pub struct Vp8lChunk { |
24 | | width: NonZeroU16, |
25 | | height: NonZeroU16, |
26 | | pub alpha_is_used: bool, |
27 | | } |
28 | | |
29 | | // |
30 | | // private types |
31 | | // |
32 | | |
33 | | #[derive(Clone, Copy, Debug, Display)] |
34 | | #[display("invalid VP8L signature `0x{_0:x}` != `0x{}`", Vp8lChunk::SIGNATURE)] |
35 | | struct InvalidSignature(u8); |
36 | | |
37 | | // |
38 | | // Vp8lChunk impls |
39 | | // |
40 | | |
41 | | impl Vp8lChunk { |
42 | | const SIGNATURE: u8 = 0x2F; |
43 | | |
44 | 3.93k | pub fn width(&self) -> NonZeroU16 { |
45 | 3.93k | self.width |
46 | 3.93k | } |
47 | | |
48 | 3.93k | pub fn height(&self) -> NonZeroU16 { |
49 | 3.93k | self.height |
50 | 3.93k | } |
51 | | |
52 | 3.40k | pub fn sanitize_image_data<R: Read>(&self, input: R) -> StdResult<(), Error> { |
53 | 3.40k | let mut reader = BitBufReader::<_, LE>::with_capacity(input, 4096); |
54 | 3.40k | let _image = LosslessImage::read(&mut reader, self.width.into(), self.height.into())?; |
55 | 318 | Ok(()) |
56 | 3.40k | } |
57 | | } |
58 | | |
59 | | impl ParseChunk for Vp8lChunk { |
60 | | const NAME: FourCC = VP8L; |
61 | | |
62 | | const ENCODED_LEN: u32 = 5; |
63 | | |
64 | 3.50k | fn parse(buf: &mut BytesMut) -> Result<Self, ParseError> { |
65 | 3.50k | let mut header = [0; Self::ENCODED_LEN as usize]; |
66 | 3.50k | buf.copy_to_slice(&mut header); |
67 | 3.50k | let mut reader = BitReader::<_, LE>::new(Cursor::new(header)); |
68 | 3.50k | |
69 | 3.50k | let signature = reader.read(8).unwrap(); |
70 | 3.50k | |
71 | 3.50k | ensure_attach!( |
72 | 3.50k | signature == Self::SIGNATURE, |
73 | 14 | ParseError::InvalidInput, |
74 | 14 | InvalidSignature(signature) |
75 | | ); |
76 | | |
77 | 3.49k | let width = NonZeroU16::MIN.saturating_add(reader.read(14).unwrap()); |
78 | 3.49k | let height = NonZeroU16::MIN.saturating_add(reader.read(14).unwrap()); |
79 | 3.49k | let alpha_is_used = reader.read_bit().unwrap(); |
80 | 3.49k | let version = reader.read(3).unwrap(); |
81 | 3.49k | |
82 | 3.49k | ensure_attach!(version == 0, ParseError::UnsupportedVp8lVersion(version)); |
83 | | |
84 | 3.49k | Ok(Self { width, height, alpha_is_used }) |
85 | 3.50k | } |
86 | | } |