1use crate::{
4 common::f16,
5 output::{VideoOutputInfo, Yc48},
6};
7use std::{
8 ops::Deref,
9 sync::{Arc, atomic::AtomicUsize},
10};
11
12pub trait FromRawVideoFrame {
15 const FORMAT: u32;
17
18 fn check(video: &VideoOutputInfo) -> Result<(), String>;
22
23 unsafe fn from_raw(
28 video: &VideoOutputInfo,
29 frame_data_ptr: *const u8,
30 last_frame_id: Arc<AtomicUsize>,
31 frame_id: usize,
32 ) -> Self;
33}
34
35duplicate::duplicate! {
36 [
37 Name Type Doc;
38 [RgbVideoFrame] [(u8, u8, u8)] ["(u8, u8, u8) で表されるRGBの動画フレーム。"];
39 [Yuy2VideoFrame] [(u8, u8, u8, u8)] ["(u8, u8, u8, u8) で表されるYUV 4:2:2の動画フレーム。"];
40 [Hf64VideoFrame] [(f16, f16, f16, f16)] ["(f16, f16, f16, f16) で表されるRGBAの動画フレーム。"];
41 [Yc48VideoFrame] [Yc48] ["YC48形式の動画フレーム。"];
42 [Pa64VideoFrame] [(u16, u16, u16, u16)] ["(u16, u16, u16, u16) で表されるRGBAの動画フレーム。"];
43
44 [RawBgrVideoFrame] [u8] ["生のBGR24形式の動画フレームデータ。"];
45 [RawYuy2VideoFrame] [u8] ["生のYUV 4:2:2形式の動画フレームデータ。"];
46 [RawHf64VideoFrame] [f16] ["生のDXGI_FORMAT_R16G16B16A16_FLOAT(乗算済みα)形式の動画フレームデータ。"];
47 [RawYc48VideoFrame] [i16] ["生のYC48形式の動画フレームデータ。"];
48 [RawPa64VideoFrame] [u16] ["生のDXGI_FORMAT_R16G16B16A16_UNORM(乗算済みα)形式の動画フレームデータ。"];
49 ]
50 #[doc = Doc]
51 #[derive(Debug, Clone)]
52 pub struct Name {
53 pub data: Vec<Type>,
54 }
55 impl Deref for Name {
56 type Target = [Type];
57
58 fn deref(&self) -> &Self::Target {
59 &self.data
60 }
61 }
62}
63
64duplicate::duplicate! {
65 [
66 Name OwnedName ParsedName Type Doc;
67 [BorrowedRawBgrVideoFrame] [RawBgrVideoFrame] [RgbVideoFrame] [u8] ["生のBGR24形式の動画フレームデータ。"];
68 [BorrowedRawYuy2VideoFrame] [RawYuy2VideoFrame] [Yuy2VideoFrame] [u8] ["生のYUV 4:2:2形式の動画フレームデータ。"];
69 [BorrowedRawHf64VideoFrame] [RawHf64VideoFrame] [Hf64VideoFrame] [f16] ["生のDXGI_FORMAT_R16G16B16A16_FLOAT(乗算済みα)形式の動画フレームデータ。"];
70 [BorrowedRawYc48VideoFrame] [RawYc48VideoFrame] [Yc48VideoFrame] [i16] ["生のYC48形式の動画フレームデータ。"];
71 [BorrowedRawPa64VideoFrame] [RawPa64VideoFrame] [Pa64VideoFrame] [u16] ["生のDXGI_FORMAT_R16G16B16A16_UNORM(乗算済みα)形式の動画フレームデータ。"];
72 ]
73 #[doc = Doc]
74 #[doc = concat!("[`", stringify!(OwnedName), "`]や[`", stringify!(ParsedName), "`]とは違い、フレームデータを所有しません。")]
75 #[derive(Debug)]
76 pub struct Name {
77 data: *const Type,
78 length: usize,
79
80 last_frame_id: Arc<AtomicUsize>,
81 frame_id: usize,
82
83 info: VideoOutputInfo,
84 }
85 impl Name {
86 pub fn len(&self) -> usize {
88 self.length
89 }
90
91 pub fn is_empty(&self) -> bool {
97 false
98 }
99
100 pub fn as_ptr(&self) -> *const Type {
102 self.data
103 }
104
105 pub fn is_valid(&self) -> bool {
107 self.last_frame_id.load(std::sync::atomic::Ordering::SeqCst) == self.frame_id
108 }
109
110 pub fn as_slice(&self) -> &[Type] {
116 assert!(
117 self.is_valid(),
118 "The frame data has been invalidated. This can happen if a new frame is fetched"
119 );
120 unsafe { self.as_slice_unchecked() }
121 }
122
123 pub unsafe fn as_slice_unchecked(&self) -> &[Type] {
129 unsafe { std::slice::from_raw_parts(self.data, self.length) }
130 }
131
132 pub fn to_owned(&self) -> OwnedName {
138 assert!(
139 self.is_valid(),
140 "The frame data has been invalidated. This can happen if a new frame is fetched"
141 );
142 unsafe { self.to_owned_unchecked() }
143 }
144
145 pub unsafe fn to_owned_unchecked(&self) -> OwnedName {
151 OwnedName {
152 data: unsafe { std::slice::from_raw_parts(self.data, self.length).to_vec() },
153 }
154 }
155
156 pub fn to_parsed(&self) -> ParsedName {
162 assert!(
163 self.is_valid(),
164 "The frame data has been invalidated. This can happen if a new frame is fetched"
165 );
166 unsafe { self.to_parsed_unchecked() }
167 }
168
169 pub unsafe fn to_parsed_unchecked(&self) -> ParsedName {
175 #[allow(clippy::unnecessary_cast)]
176 unsafe { ParsedName::from_raw(&self.info, self.data as *const u8, self.last_frame_id.clone(), self.frame_id)}
177 }
178 }
179}
180
181impl FromRawVideoFrame for RgbVideoFrame {
182 const FORMAT: u32 = aviutl2_sys::common::BI_RGB;
183
184 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
185 Ok(())
186 }
187 unsafe fn from_raw(
188 video: &VideoOutputInfo,
189 frame_data_ptr: *const u8,
190 _last_frame_id: Arc<AtomicUsize>,
191 _frame_id: usize,
192 ) -> Self {
193 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
194 let frame_data_writer = frame_buffer.spare_capacity_mut();
195 for y in 0..video.height as usize {
196 for x in 0..video.width as usize {
197 let i = y * video.width as usize + x;
198 let pixel_r = unsafe { *frame_data_ptr.add(i * 3 + 2) };
200 let pixel_g = unsafe { *frame_data_ptr.add(i * 3 + 1) };
201 let pixel_b = unsafe { *frame_data_ptr.add(i * 3) };
202 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
203 .write((pixel_r, pixel_g, pixel_b));
204 }
205 }
206 unsafe {
207 frame_buffer.set_len((video.width * video.height) as usize);
208 }
209
210 Self { data: frame_buffer }
211 }
212}
213impl FromRawVideoFrame for Yuy2VideoFrame {
214 const FORMAT: u32 = aviutl2_sys::common::BI_YUY2;
215
216 fn check(video: &VideoOutputInfo) -> Result<(), String> {
217 if !video.width.is_multiple_of(2) || !video.height.is_multiple_of(2) {
218 return Err("YUY2 format requires even width and height".to_string());
219 }
220 Ok(())
221 }
222 unsafe fn from_raw(
223 video: &VideoOutputInfo,
224 frame_data_ptr: *const u8,
225 _last_frame_id: Arc<AtomicUsize>,
226 _frame_id: usize,
227 ) -> Self {
228 let mut frame_buffer = Vec::with_capacity((video.width * video.height / 2) as usize);
229 let frame_data_writer = frame_buffer.spare_capacity_mut();
230 for y in 0..video.height as usize {
231 for x in 0..(video.width / 2) as usize {
232 let i = y * video.width as usize + x;
233 let d_y1 = unsafe { *frame_data_ptr.add(i * 4) };
235 let d_u = unsafe { *frame_data_ptr.add(i * 4 + 1) };
236 let d_y2 = unsafe { *frame_data_ptr.add(i * 4 + 2) };
237 let d_v = unsafe { *frame_data_ptr.add(i * 4 + 3) };
238
239 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
240 .write((d_y1, d_u, d_y2, d_v));
241 }
242 }
243 unsafe {
244 frame_buffer.set_len((video.width * video.height * 2) as usize);
245 }
246
247 Self { data: frame_buffer }
248 }
249}
250
251impl FromRawVideoFrame for Hf64VideoFrame {
252 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
253
254 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
255 Ok(())
256 }
257 unsafe fn from_raw(
258 video: &VideoOutputInfo,
259 frame_data_ptr: *const u8,
260 _last_frame_id: Arc<AtomicUsize>,
261 _frame_id: usize,
262 ) -> Self {
263 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
264 let frame_data_writer = frame_buffer.spare_capacity_mut();
265 let frame_data_ptr = frame_data_ptr as *const u16;
266 for y in 0..video.height as usize {
267 for x in 0..video.width as usize {
268 let i = y * video.width as usize + x;
269 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
271 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
272 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
273 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
274 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
275 .write((
276 f16::from_bits(pixel_r),
277 f16::from_bits(pixel_g),
278 f16::from_bits(pixel_b),
279 f16::from_bits(pixel_a),
280 ));
281 }
282 }
283 unsafe {
284 frame_buffer.set_len((video.width * video.height) as usize);
285 }
286
287 Self { data: frame_buffer }
288 }
289}
290impl FromRawVideoFrame for Yc48VideoFrame {
291 const FORMAT: u32 = aviutl2_sys::common::BI_YC48;
292
293 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
294 Ok(())
295 }
296 unsafe fn from_raw(
297 video: &VideoOutputInfo,
298 frame_data_ptr: *const u8,
299 _last_frame_id: Arc<AtomicUsize>,
300 _frame_id: usize,
301 ) -> Self {
302 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
303 let frame_data_writer = frame_buffer.spare_capacity_mut();
304 let frame_data_ptr = frame_data_ptr as *const i16;
305 for y in 0..video.height as usize {
306 for x in 0..video.width as usize {
307 let i = y * video.width as usize + x;
308 let pixel_y = unsafe { *frame_data_ptr.add(i * 3) };
310 let pixel_cr = unsafe { *frame_data_ptr.add(i * 3 + 1) };
311 let pixel_cb = unsafe { *frame_data_ptr.add(i * 3 + 2) };
312 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
313 .write(Yc48 {
314 y: pixel_y,
315 cr: pixel_cr,
316 cb: pixel_cb,
317 });
318 }
319 }
320 unsafe {
321 frame_buffer.set_len((video.width * video.height) as usize);
322 }
323
324 Self { data: frame_buffer }
325 }
326}
327impl FromRawVideoFrame for Pa64VideoFrame {
328 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
329
330 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
331 Ok(())
332 }
333 unsafe fn from_raw(
334 video: &VideoOutputInfo,
335 frame_data_ptr: *const u8,
336 _last_frame_id: Arc<AtomicUsize>,
337 _frame_id: usize,
338 ) -> Self {
339 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
340 let frame_data_writer = frame_buffer.spare_capacity_mut();
341 let frame_data_ptr = frame_data_ptr as *const u16;
342 for y in 0..video.height as usize {
343 for x in 0..video.width as usize {
344 let i = y * video.width as usize + x;
345 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
347 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
348 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
349 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
350 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
351 .write((pixel_r, pixel_g, pixel_b, pixel_a));
352 }
353 }
354 unsafe {
355 frame_buffer.set_len((video.width * video.height) as usize);
356 }
357
358 Self { data: frame_buffer }
359 }
360}
361
362#[duplicate::duplicate_item(
363 Name Type elms FMT;
364 [RawBgrVideoFrame] [u8] [3] [aviutl2_sys::common::BI_RGB];
365 [RawYuy2VideoFrame] [u8] [2] [aviutl2_sys::common::BI_YUY2];
366 [RawHf64VideoFrame] [f16] [4] [aviutl2_sys::common::BI_HF64];
367 [RawYc48VideoFrame] [i16] [3] [aviutl2_sys::common::BI_YC48];
368 [RawPa64VideoFrame] [u16] [4] [aviutl2_sys::common::BI_PA64];
369)]
370impl FromRawVideoFrame for Name {
371 const FORMAT: u32 = FMT;
372
373 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
374 Ok(())
375 }
376 unsafe fn from_raw(
377 video: &VideoOutputInfo,
378 frame_data_ptr: *const u8,
379 _last_frame_id: Arc<AtomicUsize>,
380 _frame_id: usize,
381 ) -> Self {
382 let frame_buffer = unsafe {
383 #[allow(clippy::unnecessary_cast)]
384 std::slice::from_raw_parts(
385 frame_data_ptr as *const Type,
386 (video.width * video.height * elms) as usize,
387 )
388 .to_owned()
389 };
390
391 Self { data: frame_buffer }
392 }
393}
394
395#[duplicate::duplicate_item(
396 Name Type elms FMT;
397 [BorrowedRawBgrVideoFrame] [u8] [3] [aviutl2_sys::common::BI_RGB];
398 [BorrowedRawYuy2VideoFrame] [u8] [2] [aviutl2_sys::common::BI_YUY2];
399 [BorrowedRawHf64VideoFrame] [f16] [4] [aviutl2_sys::common::BI_HF64];
400 [BorrowedRawYc48VideoFrame] [i16] [3] [aviutl2_sys::common::BI_YC48];
401 [BorrowedRawPa64VideoFrame] [u16] [4] [aviutl2_sys::common::BI_PA64];
402)]
403impl FromRawVideoFrame for Name {
404 const FORMAT: u32 = FMT;
405
406 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
407 Ok(())
408 }
409 unsafe fn from_raw(
410 video: &VideoOutputInfo,
411 frame_data_ptr: *const u8,
412 last_frame_id: Arc<AtomicUsize>,
413 frame_id: usize,
414 ) -> Self {
415 let length = (video.width * video.height * elms) as usize;
416
417 Self {
418 data: frame_data_ptr as _,
419 length,
420 info: video.clone(),
421 last_frame_id,
422 frame_id,
423 }
424 }
425}
426
427#[cfg(feature = "image")]
428impl FromRawVideoFrame for image::RgbImage {
429 const FORMAT: u32 = aviutl2_sys::common::BI_RGB;
430
431 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
432 Ok(())
433 }
434 unsafe fn from_raw(
435 video: &VideoOutputInfo,
436 frame_data_ptr: *const u8,
437 _last_frame_id: Arc<AtomicUsize>,
438 _frame_id: usize,
439 ) -> Self {
440 let mut buffer = unsafe {
441 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 3) as usize)
442 .to_owned()
443 };
444 crate::utils::bgr_to_rgb_bytes(&mut buffer);
445 crate::utils::flip_vertical(&mut buffer, video.width as usize * 3, video.height as usize);
446 image::RgbImage::from_raw(video.width, video.height, buffer).unwrap()
447 }
448}
449
450#[cfg(feature = "image")]
451impl FromRawVideoFrame for image::ImageBuffer<image::Rgba<u16>, Vec<u16>> {
452 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
453
454 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
455 Ok(())
456 }
457 unsafe fn from_raw(
458 video: &VideoOutputInfo,
459 frame_data_ptr: *const u8,
460 _last_frame_id: Arc<AtomicUsize>,
461 _frame_id: usize,
462 ) -> Self {
463 let frame_data_ptr = frame_data_ptr as *const u16;
464 let buffer = unsafe {
465 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
466 .to_owned()
467 };
468 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
469 }
470}
471
472#[cfg(feature = "image")]
473impl FromRawVideoFrame for image::Rgba32FImage {
474 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
475
476 fn check(_video: &VideoOutputInfo) -> Result<(), String> {
477 Ok(())
478 }
479 unsafe fn from_raw(
480 video: &VideoOutputInfo,
481 frame_data_ptr: *const u8,
482 _last_frame_id: Arc<AtomicUsize>,
483 _frame_id: usize,
484 ) -> Self {
485 let frame_data_ptr = frame_data_ptr as *const f16;
486 let buffer = unsafe {
487 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
488 .iter()
489 .map(|&v| v.to_f32())
490 .collect::<Vec<_>>()
491 };
492 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
493 }
494}