1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 pub mod decoders;
6 pub mod utils;
7
8 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
9 pub struct Resolution {
10 pub width: u32,
11 pub height: u32,
12 }
13
14 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
15 pub enum DecodedFormat {
16 NV12,
17 I420,
18 }
19
20 /// Copies `src` into `dst` as NV12, removing any extra padding.
nv12_copy( src: &[u8], mut dst: &mut [u8], width: u32, height: u32, strides: [u32; 3], offsets: [u32; 3], )21 pub fn nv12_copy(
22 src: &[u8],
23 mut dst: &mut [u8],
24 width: u32,
25 height: u32,
26 strides: [u32; 3],
27 offsets: [u32; 3],
28 ) {
29 let width = width.try_into().unwrap();
30 let height = height.try_into().unwrap();
31 let data = src;
32
33 let mut src = &data[offsets[0] as usize..];
34
35 // Copy luma
36 for _ in 0..height {
37 dst[..width].copy_from_slice(&src[..width]);
38 dst = &mut dst[width..];
39 src = &src[strides[0] as usize..];
40 }
41
42 // Advance to the offset of the chroma plane
43 let mut src = &data[offsets[1] as usize..];
44
45 // Copy chroma
46 for _ in 0..height / 2 {
47 dst[..width].copy_from_slice(&src[..width]);
48 dst = &mut dst[width..];
49 src = &src[strides[1] as usize..];
50 }
51 }
52
53 /// Copies `src` into `dst` as I420, removing any extra padding.
i420_copy( src: &[u8], mut dst: &mut [u8], width: u32, height: u32, strides: [u32; 3], offsets: [u32; 3], )54 pub fn i420_copy(
55 src: &[u8],
56 mut dst: &mut [u8],
57 width: u32,
58 height: u32,
59 strides: [u32; 3],
60 offsets: [u32; 3],
61 ) {
62 let width = width.try_into().unwrap();
63 let height = height.try_into().unwrap();
64 let data = src;
65
66 let mut src = &data[offsets[0] as usize..];
67
68 // Copy luma
69 for _ in 0..height {
70 dst[..width].copy_from_slice(&src[..width]);
71 dst = &mut dst[width..];
72 src = &src[strides[0] as usize..];
73 }
74
75 // Advance to the offset of the U plane
76 let mut src = &data[offsets[1] as usize..];
77
78 // Copy U
79 for _ in 0..height / 2 {
80 dst[..width].copy_from_slice(&src[..width]);
81 dst = &mut dst[width..];
82 src = &src[strides[1] as usize..];
83 }
84
85 // Advance to the offset of the V plane
86 let mut src = &data[offsets[2] as usize..];
87
88 // Copy V
89 for _ in 0..height / 2 {
90 dst[..width].copy_from_slice(&src[..width]);
91 dst = &mut dst[width..];
92 src = &src[strides[2] as usize..];
93 }
94 }
95
96 /// Returns the size required to store a frame of `format` with size `width`x`height`, without any
97 /// padding. This is the minimum size of the destination buffer passed to `nv12_copy` or
98 /// `i420_copy`.
decoded_frame_size(format: DecodedFormat, width: u16, height: u16) -> usize99 pub fn decoded_frame_size(format: DecodedFormat, width: u16, height: u16) -> usize {
100 match format {
101 DecodedFormat::I420 | DecodedFormat::NV12 => width as usize * height as usize * 3 / 2,
102 }
103 }
104