vapoursynth4_rs/
frame.rs

1/*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5*/
6
7use 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        // safety: `vf` is valid if the node is a video node
102        unsafe { &*(self.api.getVideoFrameFormat)(self.as_ptr()) }
103    }
104
105    #[must_use]
106    pub fn get_audio_format(&self) -> &AudioFormat {
107        // safety: `af` is valid if the node is an audio node
108        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;