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形式の動画フレームデータ。下の行から順に並び、各行は4バイト境界に揃えるパディングを含みます。行のバイト数は [`crate::utils::bgr_stride`] で取得できます。"];
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形式の動画フレームデータ。下の行から順に並び、各行は4バイト境界に揃えるパディングを含みます。パディングを除いた各行は [`Self::rows`] で取得できます。"];
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 BorrowedRawBgrVideoFrame {
182 pub fn rows(&self) -> impl DoubleEndedIterator<Item = &[u8]> + ExactSizeIterator {
188 let data = self.as_slice();
189 let row_bytes = self.info.width as usize * 3;
190 let stride = crate::utils::bgr_stride(self.info.width as usize);
191 (0..self.info.height as usize).map(move |y| {
192 assert!(
193 self.is_valid(),
194 "The frame data has been invalidated. This can happen if a new frame is fetched"
195 );
196 &data[y * stride..y * stride + row_bytes]
197 })
198 }
199}
200
201impl FromRawVideoFrame for RgbVideoFrame {
202 const FORMAT: u32 = aviutl2_sys::common::BI_RGB;
203
204 fn check(video: &VideoOutputInfo) -> Result<(), String> {
205 let _ = video;
206 Ok(())
207 }
208 unsafe fn from_raw(
209 video: &VideoOutputInfo,
210 frame_data_ptr: *const u8,
211 last_frame_id: Arc<AtomicUsize>,
212 frame_id: usize,
213 ) -> Self {
214 let _ = (last_frame_id, frame_id);
215 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
216 let frame_data_writer = frame_buffer.spare_capacity_mut();
217 let stride = crate::utils::bgr_stride(video.width as usize);
218 for y in 0..video.height as usize {
219 for x in 0..video.width as usize {
220 let i = y * stride + x * 3;
221 let pixel_r = unsafe { *frame_data_ptr.add(i + 2) };
223 let pixel_g = unsafe { *frame_data_ptr.add(i + 1) };
224 let pixel_b = unsafe { *frame_data_ptr.add(i) };
225 frame_data_writer[(video.height as usize - 1 - y) * video.width as usize + x]
226 .write((pixel_r, pixel_g, pixel_b));
227 }
228 }
229 unsafe {
230 frame_buffer.set_len((video.width * video.height) as usize);
231 }
232
233 Self { data: frame_buffer }
234 }
235}
236impl FromRawVideoFrame for Yuy2VideoFrame {
237 const FORMAT: u32 = aviutl2_sys::common::BI_YUY2;
238
239 fn check(video: &VideoOutputInfo) -> Result<(), String> {
240 if !video.width.is_multiple_of(2) || !video.height.is_multiple_of(2) {
241 return Err("YUY2 format requires even width and height".to_string());
242 }
243 Ok(())
244 }
245 unsafe fn from_raw(
246 video: &VideoOutputInfo,
247 frame_data_ptr: *const u8,
248 last_frame_id: Arc<AtomicUsize>,
249 frame_id: usize,
250 ) -> Self {
251 let _ = (last_frame_id, frame_id);
252 let mut frame_buffer = Vec::with_capacity((video.width * video.height / 2) as usize);
253 let frame_data_writer = frame_buffer.spare_capacity_mut();
254 for y in 0..video.height as usize {
255 for x in 0..(video.width / 2) as usize {
256 let i = y * video.width as usize + x;
257 let d_y1 = unsafe { *frame_data_ptr.add(i * 4) };
259 let d_u = unsafe { *frame_data_ptr.add(i * 4 + 1) };
260 let d_y2 = unsafe { *frame_data_ptr.add(i * 4 + 2) };
261 let d_v = unsafe { *frame_data_ptr.add(i * 4 + 3) };
262
263 frame_data_writer[y * (video.width as usize / 2) + x].write((d_y1, d_u, d_y2, d_v));
264 }
265 }
266 unsafe {
267 frame_buffer.set_len((video.width * video.height * 2) as usize);
268 }
269
270 Self { data: frame_buffer }
271 }
272}
273
274impl FromRawVideoFrame for Hf64VideoFrame {
275 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
276
277 fn check(video: &VideoOutputInfo) -> Result<(), String> {
278 let _ = video;
279 Ok(())
280 }
281 unsafe fn from_raw(
282 video: &VideoOutputInfo,
283 frame_data_ptr: *const u8,
284 last_frame_id: Arc<AtomicUsize>,
285 frame_id: usize,
286 ) -> Self {
287 let _ = (last_frame_id, frame_id);
288 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
289 let frame_data_writer = frame_buffer.spare_capacity_mut();
290 let frame_data_ptr = frame_data_ptr as *const u16;
291 for y in 0..video.height as usize {
292 for x in 0..video.width as usize {
293 let i = y * video.width as usize + x;
294 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
296 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
297 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
298 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
299 frame_data_writer[y * video.width as usize + x].write((
300 f16::from_bits(pixel_r),
301 f16::from_bits(pixel_g),
302 f16::from_bits(pixel_b),
303 f16::from_bits(pixel_a),
304 ));
305 }
306 }
307 unsafe {
308 frame_buffer.set_len((video.width * video.height) as usize);
309 }
310
311 Self { data: frame_buffer }
312 }
313}
314impl FromRawVideoFrame for Yc48VideoFrame {
315 const FORMAT: u32 = aviutl2_sys::common::BI_YC48;
316
317 fn check(video: &VideoOutputInfo) -> Result<(), String> {
318 let _ = video;
319 Ok(())
320 }
321 unsafe fn from_raw(
322 video: &VideoOutputInfo,
323 frame_data_ptr: *const u8,
324 last_frame_id: Arc<AtomicUsize>,
325 frame_id: usize,
326 ) -> Self {
327 let _ = (last_frame_id, frame_id);
328 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
329 let frame_data_writer = frame_buffer.spare_capacity_mut();
330 let frame_data_ptr = frame_data_ptr as *const i16;
331 for y in 0..video.height as usize {
332 for x in 0..video.width as usize {
333 let i = y * video.width as usize + x;
334 let pixel_y = unsafe { *frame_data_ptr.add(i * 3) };
336 let pixel_cr = unsafe { *frame_data_ptr.add(i * 3 + 1) };
337 let pixel_cb = unsafe { *frame_data_ptr.add(i * 3 + 2) };
338 frame_data_writer[y * video.width as usize + x].write(Yc48 {
339 y: pixel_y,
340 cr: pixel_cr,
341 cb: pixel_cb,
342 });
343 }
344 }
345 unsafe {
346 frame_buffer.set_len((video.width * video.height) as usize);
347 }
348
349 Self { data: frame_buffer }
350 }
351}
352impl FromRawVideoFrame for Pa64VideoFrame {
353 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
354
355 fn check(video: &VideoOutputInfo) -> Result<(), String> {
356 let _ = video;
357 Ok(())
358 }
359 unsafe fn from_raw(
360 video: &VideoOutputInfo,
361 frame_data_ptr: *const u8,
362 last_frame_id: Arc<AtomicUsize>,
363 frame_id: usize,
364 ) -> Self {
365 let _ = (last_frame_id, frame_id);
366 let mut frame_buffer = Vec::with_capacity((video.width * video.height) as usize);
367 let frame_data_writer = frame_buffer.spare_capacity_mut();
368 let frame_data_ptr = frame_data_ptr as *const u16;
369 for y in 0..video.height as usize {
370 for x in 0..video.width as usize {
371 let i = y * video.width as usize + x;
372 let pixel_r = unsafe { *frame_data_ptr.add(i * 4) };
374 let pixel_g = unsafe { *frame_data_ptr.add(i * 4 + 1) };
375 let pixel_b = unsafe { *frame_data_ptr.add(i * 4 + 2) };
376 let pixel_a = unsafe { *frame_data_ptr.add(i * 4 + 3) };
377 frame_data_writer[y * video.width as usize + x]
378 .write((pixel_r, pixel_g, pixel_b, pixel_a));
379 }
380 }
381 unsafe {
382 frame_buffer.set_len((video.width * video.height) as usize);
383 }
384
385 Self { data: frame_buffer }
386 }
387}
388
389#[duplicate::duplicate_item(
390 Name Type row_len(width) FMT;
391 [RawBgrVideoFrame] [u8] [crate::utils::bgr_stride(width)] [aviutl2_sys::common::BI_RGB];
392 [RawYuy2VideoFrame] [u8] [width * 2] [aviutl2_sys::common::BI_YUY2];
393 [RawHf64VideoFrame] [f16] [width * 4] [aviutl2_sys::common::BI_HF64];
394 [RawYc48VideoFrame] [i16] [width * 3] [aviutl2_sys::common::BI_YC48];
395 [RawPa64VideoFrame] [u16] [width * 4] [aviutl2_sys::common::BI_PA64];
396)]
397impl FromRawVideoFrame for Name {
398 const FORMAT: u32 = FMT;
399
400 fn check(video: &VideoOutputInfo) -> Result<(), String> {
401 let _ = video;
402 Ok(())
403 }
404 unsafe fn from_raw(
405 video: &VideoOutputInfo,
406 frame_data_ptr: *const u8,
407 last_frame_id: Arc<AtomicUsize>,
408 frame_id: usize,
409 ) -> Self {
410 let _ = (last_frame_id, frame_id);
411 let frame_buffer = unsafe {
412 #[allow(clippy::unnecessary_cast)]
413 std::slice::from_raw_parts(
414 frame_data_ptr as *const Type,
415 row_len([video.width as usize]) * video.height as usize,
416 )
417 .to_owned()
418 };
419
420 Self { data: frame_buffer }
421 }
422}
423
424#[duplicate::duplicate_item(
425 Name Type row_len(width) FMT;
426 [BorrowedRawBgrVideoFrame] [u8] [crate::utils::bgr_stride(width)] [aviutl2_sys::common::BI_RGB];
427 [BorrowedRawYuy2VideoFrame] [u8] [width * 2] [aviutl2_sys::common::BI_YUY2];
428 [BorrowedRawHf64VideoFrame] [f16] [width * 4] [aviutl2_sys::common::BI_HF64];
429 [BorrowedRawYc48VideoFrame] [i16] [width * 3] [aviutl2_sys::common::BI_YC48];
430 [BorrowedRawPa64VideoFrame] [u16] [width * 4] [aviutl2_sys::common::BI_PA64];
431)]
432impl FromRawVideoFrame for Name {
433 const FORMAT: u32 = FMT;
434
435 fn check(video: &VideoOutputInfo) -> Result<(), String> {
436 let _ = video;
437 Ok(())
438 }
439 unsafe fn from_raw(
440 video: &VideoOutputInfo,
441 frame_data_ptr: *const u8,
442 last_frame_id: Arc<AtomicUsize>,
443 frame_id: usize,
444 ) -> Self {
445 let length = row_len([video.width as usize]) * video.height as usize;
446
447 Self {
448 data: frame_data_ptr as _,
449 length,
450 info: video.clone(),
451 last_frame_id,
452 frame_id,
453 }
454 }
455}
456
457#[cfg(feature = "image")]
458impl FromRawVideoFrame for image::RgbImage {
459 const FORMAT: u32 = aviutl2_sys::common::BI_RGB;
460
461 fn check(video: &VideoOutputInfo) -> Result<(), String> {
462 let _ = video;
463 Ok(())
464 }
465 unsafe fn from_raw(
466 video: &VideoOutputInfo,
467 frame_data_ptr: *const u8,
468 last_frame_id: Arc<AtomicUsize>,
469 frame_id: usize,
470 ) -> Self {
471 let frame = unsafe {
472 BorrowedRawBgrVideoFrame::from_raw(video, frame_data_ptr, last_frame_id, frame_id)
473 };
474 let mut buffer = Vec::with_capacity(video.width as usize * video.height as usize * 3);
475 for row in frame.rows().rev() {
476 buffer.extend_from_slice(row);
477 }
478 crate::utils::bgr_to_rgb_bytes(&mut buffer);
479 image::RgbImage::from_raw(video.width, video.height, buffer).unwrap()
480 }
481}
482
483#[cfg(feature = "image")]
484impl FromRawVideoFrame for image::ImageBuffer<image::Rgba<u16>, Vec<u16>> {
485 const FORMAT: u32 = aviutl2_sys::common::BI_PA64;
486
487 fn check(video: &VideoOutputInfo) -> Result<(), String> {
488 let _ = video;
489 Ok(())
490 }
491 unsafe fn from_raw(
492 video: &VideoOutputInfo,
493 frame_data_ptr: *const u8,
494 last_frame_id: Arc<AtomicUsize>,
495 frame_id: usize,
496 ) -> Self {
497 let _ = (last_frame_id, frame_id);
498 let frame_data_ptr = frame_data_ptr as *const u16;
499 let buffer = unsafe {
500 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
501 .to_owned()
502 };
503 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
504 }
505}
506
507#[cfg(feature = "image")]
508impl FromRawVideoFrame for image::Rgba32FImage {
509 const FORMAT: u32 = aviutl2_sys::common::BI_HF64;
510
511 fn check(video: &VideoOutputInfo) -> Result<(), String> {
512 let _ = video;
513 Ok(())
514 }
515 unsafe fn from_raw(
516 video: &VideoOutputInfo,
517 frame_data_ptr: *const u8,
518 last_frame_id: Arc<AtomicUsize>,
519 frame_id: usize,
520 ) -> Self {
521 let _ = (last_frame_id, frame_id);
522 let frame_data_ptr = frame_data_ptr as *const f16;
523 let buffer = unsafe {
524 std::slice::from_raw_parts(frame_data_ptr, (video.width * video.height * 4) as usize)
525 .iter()
526 .map(|&v| v.to_f32())
527 .collect::<Vec<_>>()
528 };
529 image::ImageBuffer::from_raw(video.width, video.height, buffer).unwrap()
530 }
531}