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: &crate::output::VideoOutputInfo) -> Result<(), String>;
22
23 unsafe fn from_raw(
28 video: &crate::output::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 let _ = video;
186 Ok(())
187 }
188 unsafe fn from_raw(
189 video: &VideoOutputInfo,
190 frame_data_ptr: *const u8,
191 last_frame_id: Arc<AtomicUsize>,
192 frame_id: usize,
193 ) -> Self {
194 let _ = (last_frame_id, frame_id);
195 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
196 let frame_data_writer = frame_buffer.spare_capacity_mut();
197 for y in 0..video.height as usize {
198 for x in 0..video.width as usize {
199 let i = y * video.width as usize + x;
200 let pixel_r = unsafe { *frame_data_ptr.add(i * 3 + 2) };
202 let pixel_g = unsafe { *frame_data_ptr.add(i * 3 + 1) };
203 let pixel_b = unsafe { *frame_data_ptr.add(i * 3) };
204 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
205 .write((pixel_r, pixel_g, pixel_b));
206 }
207 }
208 unsafe {
209 frame_buffer.set_len((video.width * video.height) as usize);
210 }
211
212 Self { data: frame_buffer }
213 }
214}
215impl FromRawVideoFrame for Yuy2VideoFrame {
216 const FORMAT: u32 = aviutl2_sys::common::BI_YUY2;
217
218 fn check(video: &VideoOutputInfo) -> Result<(), String> {
219 if !video.width.is_multiple_of(2) || !video.height.is_multiple_of(2) {
220 return Err("YUY2 format requires even width and height".to_string());
221 }
222 Ok(())
223 }
224 unsafe fn from_raw(
225 video: &VideoOutputInfo,
226 frame_data_ptr: *const u8,
227 last_frame_id: Arc<AtomicUsize>,
228 frame_id: usize,
229 ) -> Self {
230 let _ = (last_frame_id, frame_id);
231 let mut frame_buffer = Vec::with_capacity((video.width * video.height / 2) as usize);
232 let frame_data_writer = frame_buffer.spare_capacity_mut();
233 for y in 0..video.height as usize {
234 for x in 0..(video.width / 2) as usize {
235 let i = y * video.width as usize + x;
236 let d_y1 = unsafe { *frame_data_ptr.add(i * 4) };
238 let d_u = unsafe { *frame_data_ptr.add(i * 4 + 1) };
239 let d_y2 = unsafe { *frame_data_ptr.add(i * 4 + 2) };
240 let d_v = unsafe { *frame_data_ptr.add(i * 4 + 3) };
241
242 frame_data_writer[y * (video.width as usize / 2) + x].write((d_y1, d_u, d_y2, d_v));
243 }
244 }
245 unsafe {
246 frame_buffer.set_len((video.width * video.height * 2) as usize);
247 }
248
249 Self { data: frame_buffer }
250 }
251}
252
253impl FromRawVideoFrame for Hf64VideoFrame {
254 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
255
256 fn check(video: &VideoOutputInfo) -> Result<(), String> {
257 let _ = video;
258 Ok(())
259 }
260 unsafe fn from_raw(
261 video: &VideoOutputInfo,
262 frame_data_ptr: *const u8,
263 last_frame_id: Arc<AtomicUsize>,
264 frame_id: usize,
265 ) -> Self {
266 let _ = (last_frame_id, frame_id);
267 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
268 let frame_data_writer = frame_buffer.spare_capacity_mut();
269 let frame_data_ptr = frame_data_ptr as *const u16;
270 for y in 0..video.height as usize {
271 for x in 0..video.width as usize {
272 let i = y * video.width as usize + x;
273 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
275 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
276 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
277 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
278 frame_data_writer[y * video.width as usize + x].write((
279 f16::from_bits(pixel_r),
280 f16::from_bits(pixel_g),
281 f16::from_bits(pixel_b),
282 f16::from_bits(pixel_a),
283 ));
284 }
285 }
286 unsafe {
287 frame_buffer.set_len((video.width * video.height) as usize);
288 }
289
290 Self { data: frame_buffer }
291 }
292}
293impl FromRawVideoFrame for Yc48VideoFrame {
294 const FORMAT: u32 = aviutl2_sys::common::BI_YC48;
295
296 fn check(video: &VideoOutputInfo) -> Result<(), String> {
297 let _ = video;
298 Ok(())
299 }
300 unsafe fn from_raw(
301 video: &VideoOutputInfo,
302 frame_data_ptr: *const u8,
303 last_frame_id: Arc<AtomicUsize>,
304 frame_id: usize,
305 ) -> Self {
306 let _ = (last_frame_id, frame_id);
307 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
308 let frame_data_writer = frame_buffer.spare_capacity_mut();
309 let frame_data_ptr = frame_data_ptr as *const i16;
310 for y in 0..video.height as usize {
311 for x in 0..video.width as usize {
312 let i = y * video.width as usize + x;
313 let pixel_y = unsafe { *frame_data_ptr.add(i * 3) };
315 let pixel_cr = unsafe { *frame_data_ptr.add(i * 3 + 1) };
316 let pixel_cb = unsafe { *frame_data_ptr.add(i * 3 + 2) };
317 frame_data_writer[y * video.width as usize + x].write(Yc48 {
318 y: pixel_y,
319 cr: pixel_cr,
320 cb: pixel_cb,
321 });
322 }
323 }
324 unsafe {
325 frame_buffer.set_len((video.width * video.height) as usize);
326 }
327
328 Self { data: frame_buffer }
329 }
330}
331impl FromRawVideoFrame for Pa64VideoFrame {
332 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
333
334 fn check(video: &VideoOutputInfo) -> Result<(), String> {
335 let _ = video;
336 Ok(())
337 }
338 unsafe fn from_raw(
339 video: &VideoOutputInfo,
340 frame_data_ptr: *const u8,
341 last_frame_id: Arc<AtomicUsize>,
342 frame_id: usize,
343 ) -> Self {
344 let _ = (last_frame_id, frame_id);
345 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
346 let frame_data_writer = frame_buffer.spare_capacity_mut();
347 let frame_data_ptr = frame_data_ptr as *const u16;
348 for y in 0..video.height as usize {
349 for x in 0..video.width as usize {
350 let i = y * video.width as usize + x;
351 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
353 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
354 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
355 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
356 frame_data_writer[y * video.width as usize + x]
357 .write((pixel_r, pixel_g, pixel_b, pixel_a));
358 }
359 }
360 unsafe {
361 frame_buffer.set_len((video.width * video.height) as usize);
362 }
363
364 Self { data: frame_buffer }
365 }
366}
367
368#[duplicate::duplicate_item(
369 Name Type elms FMT;
370 [RawBgrVideoFrame] [u8] [3] [aviutl2_sys::common::BI_RGB];
371 [RawYuy2VideoFrame] [u8] [2] [aviutl2_sys::common::BI_YUY2];
372 [RawHf64VideoFrame] [f16] [4] [aviutl2_sys::common::BI_HF64];
373 [RawYc48VideoFrame] [i16] [3] [aviutl2_sys::common::BI_YC48];
374 [RawPa64VideoFrame] [u16] [4] [aviutl2_sys::common::BI_PA64];
375)]
376impl FromRawVideoFrame for Name {
377 const FORMAT: u32 = FMT;
378
379 fn check(video: &VideoOutputInfo) -> Result<(), String> {
380 let _ = video;
381 Ok(())
382 }
383 unsafe fn from_raw(
384 video: &VideoOutputInfo,
385 frame_data_ptr: *const u8,
386 last_frame_id: Arc<AtomicUsize>,
387 frame_id: usize,
388 ) -> Self {
389 let _ = (last_frame_id, frame_id);
390 let frame_buffer = unsafe {
391 #[allow(clippy::unnecessary_cast)]
392 std::slice::from_raw_parts(
393 frame_data_ptr as *const Type,
394 (video.width * video.height * elms) as usize,
395 )
396 .to_owned()
397 };
398
399 Self { data: frame_buffer }
400 }
401}
402
403#[duplicate::duplicate_item(
404 Name Type elms FMT;
405 [BorrowedRawBgrVideoFrame] [u8] [3] [aviutl2_sys::common::BI_RGB];
406 [BorrowedRawYuy2VideoFrame] [u8] [2] [aviutl2_sys::common::BI_YUY2];
407 [BorrowedRawHf64VideoFrame] [f16] [4] [aviutl2_sys::common::BI_HF64];
408 [BorrowedRawYc48VideoFrame] [i16] [3] [aviutl2_sys::common::BI_YC48];
409 [BorrowedRawPa64VideoFrame] [u16] [4] [aviutl2_sys::common::BI_PA64];
410)]
411impl FromRawVideoFrame for Name {
412 const FORMAT: u32 = FMT;
413
414 fn check(video: &VideoOutputInfo) -> Result<(), String> {
415 let _ = video;
416 Ok(())
417 }
418 unsafe fn from_raw(
419 video: &VideoOutputInfo,
420 frame_data_ptr: *const u8,
421 last_frame_id: Arc<AtomicUsize>,
422 frame_id: usize,
423 ) -> Self {
424 let length = (video.width * video.height * elms) as usize;
425
426 Self {
427 data: frame_data_ptr as _,
428 length,
429 info: video.clone(),
430 last_frame_id,
431 frame_id,
432 }
433 }
434}
435
436#[cfg(feature = "image")]
437impl FromRawVideoFrame for image::RgbImage {
438 const FORMAT: u32 = aviutl2_sys::common::BI_RGB;
439
440 fn check(video: &VideoOutputInfo) -> Result<(), String> {
441 let _ = video;
442 Ok(())
443 }
444 unsafe fn from_raw(
445 video: &VideoOutputInfo,
446 frame_data_ptr: *const u8,
447 last_frame_id: Arc<AtomicUsize>,
448 frame_id: usize,
449 ) -> Self {
450 let _ = (last_frame_id, frame_id);
451 let mut buffer = unsafe {
452 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 3) as usize)
453 .to_owned()
454 };
455 crate::utils::bgr_to_rgb_bytes(&mut buffer);
456 crate::utils::flip_vertical(&mut buffer, video.width as usize * 3, video.height as usize);
457 image::RgbImage::from_raw(video.width, video.height, buffer).unwrap()
458 }
459}
460
461#[cfg(feature = "image")]
462impl FromRawVideoFrame for image::ImageBuffer<image::Rgba<u16>, Vec<u16>> {
463 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
464
465 fn check(video: &VideoOutputInfo) -> Result<(), String> {
466 let _ = video;
467 Ok(())
468 }
469 unsafe fn from_raw(
470 video: &VideoOutputInfo,
471 frame_data_ptr: *const u8,
472 last_frame_id: Arc<AtomicUsize>,
473 frame_id: usize,
474 ) -> Self {
475 let _ = (last_frame_id, frame_id);
476 let frame_data_ptr = frame_data_ptr as *const u16;
477 let buffer = unsafe {
478 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
479 .to_owned()
480 };
481 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
482 }
483}
484
485#[cfg(feature = "image")]
486impl FromRawVideoFrame for image::Rgba32FImage {
487 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
488
489 fn check(video: &VideoOutputInfo) -> Result<(), String> {
490 let _ = video;
491 Ok(())
492 }
493 unsafe fn from_raw(
494 video: &VideoOutputInfo,
495 frame_data_ptr: *const u8,
496 last_frame_id: Arc<AtomicUsize>,
497 frame_id: usize,
498 ) -> Self {
499 let _ = (last_frame_id, frame_id);
500 let frame_data_ptr = frame_data_ptr as *const f16;
501 let buffer = unsafe {
502 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
503 .iter()
504 .map(|&v| v.to_f32())
505 .collect::<Vec<_>>()
506 };
507 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
508 }
509}