| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| pub mod decoders; |
| pub mod utils; |
| |
| #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] |
| pub struct Resolution { |
| pub width: u32, |
| pub height: u32, |
| } |
| |
| #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] |
| pub enum DecodedFormat { |
| NV12, |
| I420, |
| } |
| |
| /// Copies `src` into `dst` as NV12, removing any extra padding. |
| pub fn nv12_copy( |
| src: &[u8], |
| mut dst: &mut [u8], |
| width: u32, |
| height: u32, |
| strides: [u32; 3], |
| offsets: [u32; 3], |
| ) { |
| let width = width.try_into().unwrap(); |
| let height = height.try_into().unwrap(); |
| let data = src; |
| |
| let mut src = &data[offsets[0] as usize..]; |
| |
| // Copy luma |
| for _ in 0..height { |
| dst[..width].copy_from_slice(&src[..width]); |
| dst = &mut dst[width..]; |
| src = &src[strides[0] as usize..]; |
| } |
| |
| // Advance to the offset of the chroma plane |
| let mut src = &data[offsets[1] as usize..]; |
| |
| // Copy chroma |
| for _ in 0..height / 2 { |
| dst[..width].copy_from_slice(&src[..width]); |
| dst = &mut dst[width..]; |
| src = &src[strides[1] as usize..]; |
| } |
| } |
| |
| /// Copies `src` into `dst` as I420, removing any extra padding. |
| pub fn i420_copy( |
| src: &[u8], |
| mut dst: &mut [u8], |
| width: u32, |
| height: u32, |
| strides: [u32; 3], |
| offsets: [u32; 3], |
| ) { |
| let width = width.try_into().unwrap(); |
| let height = height.try_into().unwrap(); |
| let data = src; |
| |
| let mut src = &data[offsets[0] as usize..]; |
| |
| // Copy luma |
| for _ in 0..height { |
| dst[..width].copy_from_slice(&src[..width]); |
| dst = &mut dst[width..]; |
| src = &src[strides[0] as usize..]; |
| } |
| |
| // Advance to the offset of the U plane |
| let mut src = &data[offsets[1] as usize..]; |
| |
| // Copy U |
| for _ in 0..height / 2 { |
| dst[..width].copy_from_slice(&src[..width]); |
| dst = &mut dst[width..]; |
| src = &src[strides[1] as usize..]; |
| } |
| |
| // Advance to the offset of the V plane |
| let mut src = &data[offsets[2] as usize..]; |
| |
| // Copy V |
| for _ in 0..height / 2 { |
| dst[..width].copy_from_slice(&src[..width]); |
| dst = &mut dst[width..]; |
| src = &src[strides[2] as usize..]; |
| } |
| } |
| |
| /// Returns the size required to store a frame of `format` with size `width`x`height`, without any |
| /// padding. This is the minimum size of the destination buffer passed to `nv12_copy` or |
| /// `i420_copy`. |
| pub fn decoded_frame_size(format: DecodedFormat, width: u16, height: u16) -> usize { |
| match format { |
| DecodedFormat::I420 | DecodedFormat::NV12 => width as usize * height as usize * 3 / 2, |
| } |
| } |