Skip to main content

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 + 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        // safety: `vf` is valid if the node is a video node
104        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    /// Returns the format of this audio frame.
165    #[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;