mirror_common/frame.rs
1//! Describe the structure of audio and video data
2//!
3//! It should be noted that pointers to internal data are temporary. If you need
4//! to hold them for a long time, you need to actively copy the data pointed to
5//! by the pointer. Therefore, the passed VideoFrame or AudioFrame are temporary
6//! references, and there will be no situation where a static structure is
7//! passed.
8//!
9//! # Audio
10//!
11//! Pulse-code modulation
12//!
13//! Pulse-code modulation (PCM) is a method used to digitally represent analog
14//! signals. It is the standard form of digital audio in computers, compact
15//! discs, digital telephony and other digital audio applications. In a PCM
16//! stream, the amplitude of the analog signal is sampled at uniform intervals,
17//! and each sample is quantized to the nearest value within a range of digital
18//! steps.
19//!
20//! Linear pulse-code modulation (LPCM) is a specific type of PCM in which the
21//! quantization levels are linearly uniform. This is in contrast to PCM
22//! encodings in which quantization levels vary as a function of amplitude (as
23//! with the A-law algorithm or the μ-law algorithm). Though PCM is a more
24//! general term, it is often used to describe data encoded as LPCM.
25//!
26//! A PCM stream has two basic properties that determine the stream's fidelity
27//! to the original analog signal: the sampling rate, which is the number of
28//! times per second that samples are taken; and the bit depth, which determines
29//! the number of possible digital values that can be used to represent each
30//! sample.
31//!
32//! # Video
33//!
34//! YCbCr (NV12)
35//!
36//! YCbCr, Y′CbCr, or Y Pb/Cb Pr/Cr, also written as YCBCR or Y′CBCR, is a
37//! family of color spaces used as a part of the color image pipeline in video
38//! and digital photography systems. Y′ is the luma component and CB and CR are
39//! the blue-difference and red-difference chroma components. Y′ (with prime) is
40//! distinguished from Y, which is luminance, meaning that light intensity is
41//! nonlinearly encoded based on gamma corrected RGB primaries.
42//!
43//! Y′CbCr color spaces are defined by a mathematical coordinate transformation
44//! from an associated RGB primaries and white point. If the underlying RGB
45//! color space is absolute, the Y′CbCr color space is an absolute color space
46//! as well; conversely, if the RGB space is ill-defined, so is Y′CbCr. The
47//! transformation is defined in equations 32, 33 in ITU-T H.273. Nevertheless
48//! that rule does not apply to P3-D65 primaries used by Netflix with
49//! BT.2020-NCL matrix, so that means matrix was not derived from primaries, but
50//! now Netflix allows BT.2020 primaries (since 2021). The same happens with
51//! JPEG: it has BT.601 matrix derived from System M primaries, yet the
52//! primaries of most images are BT.709.
53
54use std::{ffi::c_void, ptr::null};
55
56/// A sample from the audio stream.
57#[repr(C)]
58#[derive(Debug)]
59pub struct AudioFrame {
60 pub sample_rate: u32,
61 /// The number of samples in the current audio frame.
62 pub frames: u32,
63 /// Pointer to the sample raw buffer.
64 pub data: *const i16,
65}
66
67unsafe impl Sync for AudioFrame {}
68unsafe impl Send for AudioFrame {}
69
70impl Default for AudioFrame {
71 fn default() -> Self {
72 Self {
73 frames: 0,
74 data: null(),
75 sample_rate: 0,
76 }
77 }
78}
79
80#[repr(C)]
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum VideoFormat {
83 BGRA,
84 RGBA,
85 NV12,
86 I420,
87}
88
89#[repr(C)]
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
91pub enum VideoSubFormat {
92 /// This video frame is from Core video, a type exclusive to the Macos
93 /// platform.
94 CvPixelBufferRef,
95 /// Inside this video frame is ID3D11Texture2D.
96 D3D11,
97 /// Video frames contain buffers that can be accessed directly through
98 /// software.
99 SW,
100}
101
102/// A frame in a video stream.
103#[repr(C)]
104#[derive(Debug)]
105pub struct VideoFrame {
106 pub format: VideoFormat,
107 pub sub_format: VideoSubFormat,
108 pub width: u32,
109 pub height: u32,
110 /// If the subformat is SW, the data layout is determined according to the
111 /// format and the data corresponds to the plane of the corresponding
112 /// format, All other sub formats use `data[0]`.
113 pub data: [*const c_void; 3],
114 pub linesize: [usize; 3],
115}
116
117unsafe impl Sync for VideoFrame {}
118unsafe impl Send for VideoFrame {}
119
120impl Default for VideoFrame {
121 fn default() -> Self {
122 Self {
123 width: 0,
124 height: 0,
125 linesize: [0, 0, 0],
126 data: [null(), null(), null()],
127 format: VideoFormat::RGBA,
128 sub_format: VideoSubFormat::SW,
129 }
130 }
131}