1use crate::{api::Api, ffi, map::MapRef};
8
9mod context;
10mod format;
11
12pub use context::*;
13pub use format::*;
14
15pub trait Frame: Sized + internal::FrameFromPtr {
16 fn api(&self) -> Api;
17
18 #[must_use]
19 fn as_ptr(&self) -> *mut ffi::VSFrame;
20
21 #[must_use]
22 #[inline]
23 fn properties(&self) -> Option<MapRef> {
24 unsafe {
25 let ptr = (self.api().getFramePropertiesRO)(self.as_ptr());
26 ptr.is_null().then_some(MapRef::from_ptr(ptr, self.api()))
27 }
28 }
29
30 #[must_use]
31 #[inline]
32 fn properties_mut(&mut self) -> Option<MapRef> {
33 unsafe {
34 let ptr = (self.api().getFramePropertiesRW)(self.as_ptr());
35 ptr.is_null().then_some(MapRef::from_ptr(ptr, self.api()))
36 }
37 }
38}
39
40pub(crate) mod internal {
41 use super::{Api, AudioFrame, VideoFrame, ffi};
42
43 pub trait FrameFromPtr {
44 unsafe fn from_ptr(ptr: *const ffi::VSFrame, api: Api) -> Self;
45 }
46
47 impl FrameFromPtr for VideoFrame {
48 #[inline]
49 unsafe fn from_ptr(ptr: *const ffi::VSFrame, api: Api) -> Self {
50 VideoFrame {
51 handle: ptr.cast_mut(),
52 api,
53 }
54 }
55 }
56
57 impl FrameFromPtr for AudioFrame {
58 unsafe fn from_ptr(ptr: *const ffi::VSFrame, api: Api) -> Self {
59 AudioFrame { handle: ptr, api }
60 }
61 }
62}
63use internal::FrameFromPtr;
64
65#[derive(Debug, PartialEq, Eq, Hash)]
66pub struct VideoFrame {
67 handle: *const ffi::VSFrame,
68 api: Api,
69}
70
71impl Frame for VideoFrame {
72 #[inline]
73 fn api(&self) -> Api {
74 self.api
75 }
76
77 #[inline]
78 fn as_ptr(&self) -> *mut ffi::VSFrame {
79 self.handle.cast_mut()
80 }
81}
82
83impl VideoFrame {
84 #[must_use]
85 pub fn stride(&self, plane: i32) -> isize {
86 unsafe { (self.api.getStride)(self.as_ptr(), plane) }
87 }
88
89 #[must_use]
90 pub fn plane(&self, plane: i32) -> *const u8 {
91 unsafe { (self.api.getReadPtr)(self.as_ptr(), plane) }
92 }
93
94 #[must_use]
95 pub fn plane_mut(&mut self, plane: i32) -> *mut u8 {
96 unsafe { (self.api.getWritePtr)(self.as_ptr(), plane) }
97 }
98
99 #[must_use]
100 pub fn get_video_format(&self) -> &VideoFormat {
101 unsafe { &*(self.api.getVideoFrameFormat)(self.as_ptr()) }
103 }
104
105 #[must_use]
106 pub fn get_audio_format(&self) -> &AudioFormat {
107 unsafe { &*(self.api.getAudioFrameFormat)(self.as_ptr()) }
109 }
110
111 #[must_use]
112 pub fn get_type(&self) -> MediaType {
113 unsafe { (self.api.getFrameType)(self.as_ptr()) }
114 }
115
116 #[must_use]
117 pub fn frame_width(&self, plane: i32) -> i32 {
118 unsafe { (self.api.getFrameWidth)(self.as_ptr(), plane) }
119 }
120
121 #[must_use]
122 pub fn frame_height(&self, plane: i32) -> i32 {
123 unsafe { (self.api.getFrameHeight)(self.as_ptr(), plane) }
124 }
125}
126
127impl Clone for VideoFrame {
128 fn clone(&self) -> Self {
129 unsafe { Self::from_ptr((self.api.addFrameRef)(self.handle), self.api) }
130 }
131}
132
133impl Drop for VideoFrame {
134 fn drop(&mut self) {
135 unsafe { (self.api.freeFrame)(self.handle) }
136 }
137}
138
139#[derive(Debug, PartialEq, Eq, Hash)]
140pub struct AudioFrame {
141 handle: *const ffi::VSFrame,
142 api: Api,
143}
144
145impl Frame for AudioFrame {
146 fn api(&self) -> Api {
147 self.api
148 }
149
150 fn as_ptr(&self) -> *mut ffi::VSFrame {
151 self.handle.cast_mut()
152 }
153}
154
155impl AudioFrame {
156 #[must_use]
157 pub fn channel(&self, channel: i32) -> *const u8 {
158 unsafe { (self.api.getReadPtr)(self.as_ptr(), channel) }
159 }
160
161 #[must_use]
162 pub fn channel_mut(&mut self, channel: i32) -> *mut u8 {
163 unsafe { (self.api.getWritePtr)(self.as_ptr(), channel) }
164 }
165
166 #[must_use]
167 pub fn frame_length(&self) -> i32 {
168 unsafe { (self.api.getFrameLength)(self.as_ptr()) }
169 }
170}
171
172impl Clone for AudioFrame {
173 fn clone(&self) -> Self {
174 unsafe { Self::from_ptr((self.api.addFrameRef)(self.handle), self.api) }
175 }
176}
177
178impl Drop for AudioFrame {
179 fn drop(&mut self) {
180 unsafe { (self.api.freeFrame)(self.handle) }
181 }
182}
183
184pub type MediaType = ffi::VSMediaType;