1use crate::{api::Api, ffi, map::MapRef};
8
9mod context;
10mod format;
11
12pub use context::*;
13pub use format::*;
14
15pub trait Frame: Sized + Send + 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
71unsafe impl Send for VideoFrame {}
72
73impl Frame for VideoFrame {
74 #[inline]
75 fn api(&self) -> Api {
76 self.api
77 }
78
79 #[inline]
80 fn as_ptr(&self) -> *mut ffi::VSFrame {
81 self.handle.cast_mut()
82 }
83}
84
85impl VideoFrame {
86 #[must_use]
87 pub fn stride(&self, plane: i32) -> isize {
88 unsafe { (self.api.getStride)(self.as_ptr(), plane) }
89 }
90
91 #[must_use]
92 pub fn plane(&self, plane: i32) -> *const u8 {
93 unsafe { (self.api.getReadPtr)(self.as_ptr(), plane) }
94 }
95
96 #[must_use]
97 pub fn plane_mut(&mut self, plane: i32) -> *mut u8 {
98 unsafe { (self.api.getWritePtr)(self.as_ptr(), plane) }
99 }
100
101 #[must_use]
102 pub fn get_video_format(&self) -> &VideoFormat {
103 unsafe { &*(self.api.getVideoFrameFormat)(self.as_ptr()) }
105 }
106
107 #[must_use]
108 pub fn get_type(&self) -> MediaType {
109 unsafe { (self.api.getFrameType)(self.as_ptr()) }
110 }
111
112 #[must_use]
113 pub fn frame_width(&self, plane: i32) -> i32 {
114 unsafe { (self.api.getFrameWidth)(self.as_ptr(), plane) }
115 }
116
117 #[must_use]
118 pub fn frame_height(&self, plane: i32) -> i32 {
119 unsafe { (self.api.getFrameHeight)(self.as_ptr(), plane) }
120 }
121}
122
123impl Clone for VideoFrame {
124 fn clone(&self) -> Self {
125 unsafe { Self::from_ptr((self.api.addFrameRef)(self.handle), self.api) }
126 }
127}
128
129impl Drop for VideoFrame {
130 fn drop(&mut self) {
131 unsafe { (self.api.freeFrame)(self.handle) }
132 }
133}
134
135#[derive(Debug, PartialEq, Eq, Hash)]
136pub struct AudioFrame {
137 handle: *const ffi::VSFrame,
138 api: Api,
139}
140
141unsafe impl Send for AudioFrame {}
142
143impl Frame for AudioFrame {
144 fn api(&self) -> Api {
145 self.api
146 }
147
148 fn as_ptr(&self) -> *mut ffi::VSFrame {
149 self.handle.cast_mut()
150 }
151}
152
153impl AudioFrame {
154 #[must_use]
155 pub fn channel(&self, channel: i32) -> *const u8 {
156 unsafe { (self.api.getReadPtr)(self.as_ptr(), channel) }
157 }
158
159 #[must_use]
160 pub fn channel_mut(&mut self, channel: i32) -> *mut u8 {
161 unsafe { (self.api.getWritePtr)(self.as_ptr(), channel) }
162 }
163
164 #[must_use]
166 pub fn get_audio_format(&self) -> &AudioFormat {
167 unsafe { &*(self.api.getAudioFrameFormat)(self.as_ptr()) }
168 }
169
170 #[must_use]
171 pub fn frame_length(&self) -> i32 {
172 unsafe { (self.api.getFrameLength)(self.as_ptr()) }
173 }
174}
175
176impl Clone for AudioFrame {
177 fn clone(&self) -> Self {
178 unsafe { Self::from_ptr((self.api.addFrameRef)(self.handle), self.api) }
179 }
180}
181
182impl Drop for AudioFrame {
183 fn drop(&mut self) {
184 unsafe { (self.api.freeFrame)(self.handle) }
185 }
186}
187
188pub type MediaType = ffi::VSMediaType;