1use std::{
2 borrow::Cow,
3 sync::{Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak},
4};
5#[cfg(any(feature = "audio", feature = "video"))]
6use std::{
7 ops::{Index, IndexMut},
8 slice::{Iter, IterMut},
9};
10
11use aligned_vec::{AVec, ConstAlign};
12#[cfg(any(feature = "audio", feature = "video"))]
13use bytemuck::Pod;
14use num_rational::Rational64;
15#[cfg(any(feature = "audio", feature = "video"))]
16use smallvec::SmallVec;
17
18#[cfg(any(feature = "audio", feature = "video"))]
19use crate::buffer::Buffer;
20#[cfg(any(feature = "audio", feature = "video"))]
21use crate::error::Error;
22#[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
23use crate::video::pixel_buffer::frame::PixelBuffer;
24use crate::{frame_pool::FramePool, variant::Variant, FrameDescriptor, FrameDescriptorSpec, MediaType, Result, DEFAULT_ALIGNMENT};
25
26#[cfg(any(feature = "audio", feature = "video"))]
27const DEFAULT_MAX_PLANES: usize = 8;
28
29#[cfg(any(feature = "audio", feature = "video"))]
30pub enum MappedData<'a> {
31 RefMut(&'a mut [u8]),
32 Ref(&'a [u8]),
33}
34
35#[cfg(any(feature = "audio", feature = "video"))]
36pub enum MappedPlane<'a> {
37 #[cfg(feature = "audio")]
38 Audio { data: MappedData<'a>, actual_bytes: usize },
39 #[cfg(feature = "video")]
40 Video { data: MappedData<'a>, stride: usize, height: u32 },
41}
42
43#[cfg(any(feature = "audio", feature = "video"))]
44impl MappedPlane<'_> {
45 pub fn data(&self) -> Option<&[u8]> {
46 match self {
47 #[cfg(feature = "audio")]
48 MappedPlane::Audio {
49 data, ..
50 } => match data {
51 MappedData::Ref(data) => Some(data),
52 MappedData::RefMut(data) => Some(data),
53 },
54 #[cfg(feature = "video")]
55 MappedPlane::Video {
56 data, ..
57 } => match data {
58 MappedData::Ref(data) => Some(data),
59 MappedData::RefMut(data) => Some(data),
60 },
61 }
62 }
63
64 pub fn data_mut(&mut self) -> Option<&mut [u8]> {
65 match self {
66 #[cfg(feature = "audio")]
67 MappedPlane::Audio {
68 data, ..
69 } => match data {
70 MappedData::Ref(_) => None,
71 MappedData::RefMut(data) => Some(data),
72 },
73 #[cfg(feature = "video")]
74 MappedPlane::Video {
75 data, ..
76 } => match data {
77 MappedData::Ref(_) => None,
78 MappedData::RefMut(data) => Some(data),
79 },
80 }
81 }
82
83 #[cfg(feature = "video")]
84 pub fn stride(&self) -> Option<usize> {
85 #[allow(unreachable_patterns)]
86 match self {
87 MappedPlane::Video {
88 stride, ..
89 } => Some(*stride),
90 _ => None,
91 }
92 }
93
94 #[cfg(feature = "video")]
95 pub fn height(&self) -> Option<u32> {
96 #[allow(unreachable_patterns)]
97 match self {
98 MappedPlane::Video {
99 height, ..
100 } => Some(*height),
101 _ => None,
102 }
103 }
104
105 pub fn as_slice_of<T>(&self) -> Option<&[T]>
106 where
107 T: Pod,
108 {
109 bytemuck::try_cast_slice(self.data()?).ok()
110 }
111
112 pub fn as_mut_slice_of<T>(&mut self) -> Option<&mut [T]>
113 where
114 T: Pod,
115 {
116 bytemuck::try_cast_slice_mut(self.data_mut()?).ok()
117 }
118}
119
120#[cfg(any(feature = "audio", feature = "video"))]
121pub(crate) enum DataRef<'a> {
122 Immutable(&'a dyn DataMappable),
123 Mutable(&'a mut dyn DataMappable),
124}
125
126#[cfg(any(feature = "audio", feature = "video"))]
127pub struct MappedGuard<'a> {
128 pub(crate) data_ref: DataRef<'a>,
129}
130
131#[cfg(any(feature = "audio", feature = "video"))]
132impl Drop for MappedGuard<'_> {
133 fn drop(&mut self) {
134 match &mut self.data_ref {
135 DataRef::Immutable(data) => {
136 data.unmap().ok();
137 }
138 DataRef::Mutable(data) => {
139 data.unmap_mut().ok();
140 }
141 }
142 }
143}
144
145#[cfg(any(feature = "audio", feature = "video"))]
146impl MappedGuard<'_> {
147 pub fn planes(&self) -> Option<MappedPlanes<'_>> {
148 match &self.data_ref {
149 DataRef::Immutable(data) => data.planes(),
150 DataRef::Mutable(data) => data.planes(),
151 }
152 }
153
154 pub fn planes_mut(&mut self) -> Option<MappedPlanes<'_>> {
155 match &mut self.data_ref {
156 DataRef::Immutable(_) => None,
157 DataRef::Mutable(data) => data.planes_mut(),
158 }
159 }
160}
161
162#[cfg(any(feature = "audio", feature = "video"))]
163type PlaneArray<'a> = [MappedPlane<'a>; DEFAULT_MAX_PLANES];
164
165#[cfg(any(feature = "audio", feature = "video"))]
166pub struct MappedPlanes<'a> {
167 pub(crate) planes: SmallVec<PlaneArray<'a>>,
168}
169
170#[cfg(any(feature = "audio", feature = "video"))]
171impl<'a> IntoIterator for MappedPlanes<'a> {
172 type Item = MappedPlane<'a>;
173 type IntoIter = smallvec::IntoIter<PlaneArray<'a>>;
174
175 fn into_iter(self) -> Self::IntoIter {
176 self.planes.into_iter()
177 }
178}
179
180#[cfg(any(feature = "audio", feature = "video"))]
181impl<'a> Index<usize> for MappedPlanes<'a> {
182 type Output = MappedPlane<'a>;
183
184 fn index(&self, index: usize) -> &Self::Output {
185 &self.planes[index]
186 }
187}
188
189#[cfg(any(feature = "audio", feature = "video"))]
190impl<'a> IndexMut<usize> for MappedPlanes<'a> {
191 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
192 &mut self.planes[index]
193 }
194}
195
196#[cfg(any(feature = "audio", feature = "video"))]
197impl<'a> MappedPlanes<'a> {
198 pub fn plane_data(&self, index: usize) -> Option<&[u8]> {
199 self.planes.get(index).and_then(|plane| plane.data())
200 }
201
202 pub fn plane_data_mut(&mut self, index: usize) -> Option<&mut [u8]> {
203 self.planes.get_mut(index).and_then(|plane| plane.data_mut())
204 }
205
206 #[cfg(feature = "video")]
207 pub fn plane_stride(&self, index: usize) -> Option<usize> {
208 self.planes.get(index).and_then(|plane| plane.stride())
209 }
210
211 #[cfg(feature = "video")]
212 pub fn plane_height(&self, index: usize) -> Option<u32> {
213 self.planes.get(index).and_then(|plane| plane.height())
214 }
215
216 pub fn is_empty(&self) -> bool {
217 self.planes.is_empty()
218 }
219
220 pub fn len(&self) -> usize {
221 self.planes.len()
222 }
223
224 pub fn iter(&self) -> Iter<'_, MappedPlane<'_>> {
225 self.planes.iter()
226 }
227
228 pub fn iter_mut(&mut self) -> IterMut<'_, MappedPlane<'a>> {
229 self.planes.iter_mut()
230 }
231}
232
233#[cfg(any(feature = "audio", feature = "video"))]
234pub(crate) type PlaneVec<T> = SmallVec<[T; DEFAULT_MAX_PLANES]>;
235
236#[cfg(any(feature = "audio", feature = "video"))]
237#[derive(Copy, Clone)]
238pub(crate) enum PlaneDescriptor {
239 #[cfg(feature = "audio")]
240 Audio(usize, usize), #[cfg(feature = "video")]
242 Video(usize, u32), }
244
245#[derive(Clone)]
246pub(crate) enum Data<'a, T: Clone = u8> {
247 Borrowed(&'a [T]),
248 Owned(AVec<T, ConstAlign<DEFAULT_ALIGNMENT>>),
249}
250
251impl<T: Clone> Data<'_, T> {
252 fn into_owned(self) -> Data<'static, T> {
253 match self {
254 Data::Borrowed(slice) => Data::Owned(AVec::from_slice(DEFAULT_ALIGNMENT, slice)),
255 Data::Owned(vec) => Data::Owned(vec),
256 }
257 }
258
259 #[cfg(any(feature = "audio", feature = "video"))]
260 pub(crate) fn as_ref(&self) -> &[T] {
261 match self {
262 Data::Borrowed(slice) => slice,
263 Data::Owned(vec) => vec.as_slice(),
264 }
265 }
266}
267
268impl<'a, T> From<Cow<'a, [T]>> for Data<'a, T>
269where
270 T: Clone,
271{
272 fn from(cow: Cow<'a, [T]>) -> Self {
273 match cow {
274 Cow::Borrowed(slice) => Data::Borrowed(slice),
275 Cow::Owned(vec) => Data::Owned(AVec::from_slice(DEFAULT_ALIGNMENT, &vec)),
276 }
277 }
278}
279
280#[derive(Clone)]
281pub(crate) struct MemoryData<'a> {
282 pub(crate) data: Data<'a>,
283 #[cfg(any(feature = "audio", feature = "video"))]
284 pub(crate) planes: PlaneVec<PlaneDescriptor>,
285}
286
287impl MemoryData<'_> {
288 fn into_owned(self) -> MemoryData<'static> {
289 MemoryData {
290 data: self.data.into_owned(),
291 #[cfg(any(feature = "audio", feature = "video"))]
292 planes: self.planes,
293 }
294 }
295
296 #[cfg(feature = "audio")]
297 #[allow(unreachable_patterns)]
298 pub(crate) fn truncate(&mut self, len: usize) -> Result<()> {
299 for plane in &mut self.planes {
300 match plane {
301 PlaneDescriptor::Audio(plane_size, actual_bytes) => {
302 if len > *plane_size || len == 0 {
303 return Err(crate::invalid_param_error!(len));
304 }
305
306 *actual_bytes = len;
307 }
308 _ => return Err(Error::Unsupported("truncate for video planes".to_string())),
309 }
310 }
311
312 Ok(())
313 }
314}
315
316#[cfg(feature = "video")]
317#[derive(Clone)]
318pub(crate) struct SeparateMemoryData<'a> {
319 pub(crate) planes: PlaneVec<(&'a [u8], usize, u32)>,
320}
321
322#[cfg(feature = "video")]
323impl SeparateMemoryData<'_> {
324 fn into_owned(self) -> MemoryData<'static> {
325 let mut data = AVec::new(DEFAULT_ALIGNMENT);
326 let mut planes = PlaneVec::<PlaneDescriptor>::new();
327
328 for (slice, stride, height) in self.planes {
329 data.extend_from_slice(slice);
330 planes.push(PlaneDescriptor::Video(stride, height));
331 }
332
333 MemoryData {
334 data: Data::Owned(data),
335 planes,
336 }
337 }
338}
339
340#[cfg(any(feature = "audio", feature = "video"))]
341#[derive(Clone)]
342pub(crate) struct BufferData {
343 pub(crate) data: Arc<Buffer>,
344 pub(crate) planes: PlaneVec<(usize, PlaneDescriptor)>,
345}
346
347#[derive(Clone)]
348pub(crate) enum FrameData<'a> {
349 #[allow(dead_code)]
350 Memory(MemoryData<'a>),
351 #[cfg(feature = "video")]
352 SeparateMemory(SeparateMemoryData<'a>),
353 #[cfg(any(feature = "audio", feature = "video"))]
354 #[allow(dead_code)]
355 Buffer(BufferData),
356 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
357 PixelBuffer(PixelBuffer),
358 Variant(Variant),
359 #[allow(dead_code)]
360 Empty,
361}
362
363impl FrameData<'_> {
364 pub(crate) fn into_owned(self) -> FrameData<'static> {
365 match self {
366 FrameData::Memory(data) => FrameData::Memory(data.into_owned()),
367 #[cfg(feature = "video")]
368 FrameData::SeparateMemory(data) => FrameData::Memory(data.into_owned()),
369 #[cfg(any(feature = "audio", feature = "video"))]
370 FrameData::Buffer(data) => FrameData::Buffer(data),
371 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
372 FrameData::PixelBuffer(pixel_buffer) => FrameData::PixelBuffer(pixel_buffer),
373 FrameData::Variant(variant) => FrameData::Variant(variant),
374 FrameData::Empty => FrameData::Empty,
375 }
376 }
377
378 #[cfg(feature = "audio")]
380 pub(crate) fn truncate(&mut self, len: usize) -> Result<()> {
381 match self {
382 FrameData::Memory(data) => data.truncate(len),
383 _ => Err(Error::Unsupported("truncate for non-memory data".to_string())),
384 }
385 }
386}
387
388#[cfg(any(feature = "audio", feature = "video"))]
389pub trait DataMappable: Send + Sync {
390 fn map(&self) -> Result<MappedGuard<'_>>;
391 fn map_mut(&mut self) -> Result<MappedGuard<'_>>;
392 fn unmap(&self) -> Result<()>;
393 fn unmap_mut(&mut self) -> Result<()>;
394 fn planes(&self) -> Option<MappedPlanes<'_>>;
395 fn planes_mut(&mut self) -> Option<MappedPlanes<'_>>;
396}
397
398#[cfg(any(feature = "audio", feature = "video"))]
399impl DataMappable for MemoryData<'_> {
400 fn map(&self) -> Result<MappedGuard<'_>> {
401 Ok(MappedGuard {
402 data_ref: DataRef::Immutable(self),
403 })
404 }
405
406 fn map_mut(&mut self) -> Result<MappedGuard<'_>> {
407 Ok(MappedGuard {
408 data_ref: DataRef::Mutable(self),
409 })
410 }
411
412 fn unmap(&self) -> Result<()> {
413 Ok(())
414 }
415
416 fn unmap_mut(&mut self) -> Result<()> {
417 Ok(())
418 }
419
420 fn planes(&self) -> Option<MappedPlanes<'_>> {
421 let mut data_slice = self.data.as_ref();
422 let mut planes = SmallVec::with_capacity(DEFAULT_MAX_PLANES);
423
424 for plane in &self.planes {
425 let plane_size = match plane {
426 #[cfg(feature = "audio")]
427 PlaneDescriptor::Audio(plane_size, _) => *plane_size,
428 #[cfg(feature = "video")]
429 PlaneDescriptor::Video(stride, height) => stride * (*height as usize),
430 };
431
432 if plane_size > data_slice.len() || plane_size == 0 {
433 return None;
434 }
435
436 let (plane_data, rest) = data_slice.split_at(plane_size);
437
438 let mapped_plane = match plane {
439 #[cfg(feature = "audio")]
440 PlaneDescriptor::Audio(_, actual_bytes) => MappedPlane::Audio {
441 data: MappedData::Ref(&plane_data[..*actual_bytes]),
442 actual_bytes: *actual_bytes,
443 },
444 #[cfg(feature = "video")]
445 PlaneDescriptor::Video(stride, height) => MappedPlane::Video {
446 data: MappedData::Ref(plane_data),
447 stride: *stride,
448 height: *height,
449 },
450 };
451
452 planes.push(mapped_plane);
453 data_slice = rest;
454 }
455
456 Some(MappedPlanes {
457 planes,
458 })
459 }
460
461 fn planes_mut(&mut self) -> Option<MappedPlanes<'_>> {
462 let mut data_slice = match &mut self.data {
463 Data::Owned(vec) => vec.as_mut_slice(),
464 Data::Borrowed(_) => return None,
465 };
466 let mut planes = SmallVec::with_capacity(DEFAULT_MAX_PLANES);
467
468 for plane in &self.planes {
469 let plane_size = match plane {
470 #[cfg(feature = "audio")]
471 PlaneDescriptor::Audio(plane_size, _) => *plane_size,
472 #[cfg(feature = "video")]
473 PlaneDescriptor::Video(stride, height) => stride * (*height as usize),
474 };
475
476 if plane_size > data_slice.len() {
477 return None;
478 }
479
480 let (plane_data, rest) = data_slice.split_at_mut(plane_size);
481
482 let mapped_plane = match plane {
483 #[cfg(feature = "audio")]
484 PlaneDescriptor::Audio(_, actual_bytes) => MappedPlane::Audio {
485 data: MappedData::RefMut(&mut plane_data[..*actual_bytes]),
486 actual_bytes: *actual_bytes,
487 },
488 #[cfg(feature = "video")]
489 PlaneDescriptor::Video(stride, height) => MappedPlane::Video {
490 data: MappedData::RefMut(plane_data),
491 stride: *stride,
492 height: *height,
493 },
494 };
495
496 planes.push(mapped_plane);
497 data_slice = rest;
498 }
499
500 Some(MappedPlanes {
501 planes,
502 })
503 }
504}
505
506#[cfg(feature = "video")]
507impl DataMappable for SeparateMemoryData<'_> {
508 fn map(&self) -> Result<MappedGuard<'_>> {
509 Ok(MappedGuard {
510 data_ref: DataRef::Immutable(self),
511 })
512 }
513
514 fn map_mut(&mut self) -> Result<MappedGuard<'_>> {
515 Err(Error::Unsupported("map".to_string()))
516 }
517
518 fn unmap(&self) -> Result<()> {
519 Ok(())
520 }
521
522 fn unmap_mut(&mut self) -> Result<()> {
523 Err(Error::Unsupported("unmap".to_string()))
524 }
525
526 fn planes(&self) -> Option<MappedPlanes<'_>> {
527 let mut planes = SmallVec::with_capacity(DEFAULT_MAX_PLANES);
528
529 for (slice, stride, height) in &self.planes {
530 let mapped_plane = MappedPlane::Video {
531 data: MappedData::Ref(slice),
532 stride: *stride,
533 height: *height,
534 };
535 planes.push(mapped_plane);
536 }
537
538 Some(MappedPlanes {
539 planes,
540 })
541 }
542
543 fn planes_mut(&mut self) -> Option<MappedPlanes<'_>> {
544 None
545 }
546}
547
548#[cfg(any(feature = "audio", feature = "video"))]
549impl DataMappable for BufferData {
550 fn map(&self) -> Result<MappedGuard<'_>> {
551 Ok(MappedGuard {
552 data_ref: DataRef::Immutable(self),
553 })
554 }
555
556 fn map_mut(&mut self) -> Result<MappedGuard<'_>> {
557 Err(Error::Unsupported("map".to_string()))
558 }
559
560 fn unmap(&self) -> Result<()> {
561 Ok(())
562 }
563
564 fn unmap_mut(&mut self) -> Result<()> {
565 Err(Error::Unsupported("unmap".to_string()))
566 }
567
568 fn planes(&self) -> Option<MappedPlanes<'_>> {
569 let data = self.data.data();
570 let mut planes = SmallVec::with_capacity(DEFAULT_MAX_PLANES);
571
572 for plane in &self.planes {
573 let (offset, plane_size) = match plane.1 {
574 #[cfg(feature = "audio")]
575 PlaneDescriptor::Audio(plane_size, _) => (plane.0, plane_size),
576 #[cfg(feature = "video")]
577 PlaneDescriptor::Video(stride, height) => (plane.0, stride * (height as usize)),
578 };
579
580 if plane_size > data.len() || plane_size == 0 {
581 return None;
582 }
583
584 #[allow(unused_variables)]
585 let plane_data = &data[offset..offset + plane_size];
586
587 let mapped_plane = match plane.1 {
588 #[cfg(feature = "audio")]
589 PlaneDescriptor::Audio(_, actual_bytes) => MappedPlane::Audio {
590 data: MappedData::Ref(&plane_data[..actual_bytes]),
591 actual_bytes,
592 },
593 #[cfg(feature = "video")]
594 PlaneDescriptor::Video(stride, height) => MappedPlane::Video {
595 data: MappedData::Ref(plane_data),
596 stride,
597 height,
598 },
599 };
600
601 planes.push(mapped_plane);
602 }
603
604 Some(MappedPlanes {
605 planes,
606 })
607 }
608
609 fn planes_mut(&mut self) -> Option<MappedPlanes<'_>> {
610 None
611 }
612}
613
614#[cfg(any(feature = "audio", feature = "video"))]
615impl DataMappable for FrameData<'_> {
616 fn map(&self) -> Result<MappedGuard<'_>> {
617 match self {
618 FrameData::Memory(data) => data.map(),
619 #[cfg(feature = "video")]
620 FrameData::SeparateMemory(data) => data.map(),
621 FrameData::Buffer(data) => data.map(),
622 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
623 FrameData::PixelBuffer(data) => data.map(),
624 _ => Err(Error::Unsupported("frame data".to_string())),
625 }
626 }
627
628 fn map_mut(&mut self) -> Result<MappedGuard<'_>> {
629 match self {
630 FrameData::Memory(data) => data.map_mut(),
631 #[cfg(feature = "video")]
632 FrameData::SeparateMemory(data) => data.map_mut(),
633 FrameData::Buffer(data) => data.map_mut(),
634 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
635 FrameData::PixelBuffer(data) => data.map_mut(),
636 _ => Err(Error::Unsupported("frame data".to_string())),
637 }
638 }
639
640 fn unmap(&self) -> Result<()> {
641 match self {
642 FrameData::Memory(data) => data.unmap(),
643 #[cfg(feature = "video")]
644 FrameData::SeparateMemory(data) => data.unmap(),
645 FrameData::Buffer(data) => data.unmap(),
646 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
647 FrameData::PixelBuffer(data) => data.unmap(),
648 _ => Err(Error::Unsupported("frame data".to_string())),
649 }
650 }
651
652 fn unmap_mut(&mut self) -> Result<()> {
653 match self {
654 FrameData::Memory(data) => data.unmap_mut(),
655 #[cfg(feature = "video")]
656 FrameData::SeparateMemory(data) => data.unmap_mut(),
657 FrameData::Buffer(data) => data.unmap_mut(),
658 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
659 FrameData::PixelBuffer(data) => data.unmap_mut(),
660 _ => Err(Error::Unsupported("frame data".to_string())),
661 }
662 }
663
664 fn planes(&self) -> Option<MappedPlanes<'_>> {
665 match self {
666 FrameData::Memory(data) => data.planes(),
667 #[cfg(feature = "video")]
668 FrameData::SeparateMemory(data) => data.planes(),
669 FrameData::Buffer(data) => data.planes(),
670 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
671 FrameData::PixelBuffer(data) => data.planes(),
672 _ => None,
673 }
674 }
675
676 fn planes_mut(&mut self) -> Option<MappedPlanes<'_>> {
677 match self {
678 FrameData::Memory(data) => data.planes_mut(),
679 #[cfg(feature = "video")]
680 FrameData::SeparateMemory(_) => None,
681 FrameData::Buffer(_) => None,
682 #[cfg(all(feature = "video", any(target_os = "macos", target_os = "ios")))]
683 FrameData::PixelBuffer(data) => data.planes_mut(),
684 _ => None,
685 }
686 }
687}
688
689pub trait FrameSpec<D: FrameDescriptorSpec> {
690 fn new_with_descriptor(desc: D) -> Result<Frame<'static, D>>;
691 fn media_type(&self) -> MediaType;
692}
693
694#[derive(Clone)]
695pub struct Frame<'a, D: FrameDescriptorSpec = FrameDescriptor> {
696 pub(crate) desc: D,
697 pub source: Option<String>,
698 pub pts: Option<i64>,
699 pub dts: Option<i64>,
700 pub duration: Option<i64>,
701 pub time_base: Option<Rational64>,
702 pub metadata: Option<Variant>,
703 pub(crate) data: FrameData<'a>,
704}
705
706impl Frame<'_, FrameDescriptor> {
707 pub fn new_with_generic_descriptor<D>(desc: D) -> Result<Frame<'static>>
708 where
709 D: Into<FrameDescriptor> + Clone,
710 {
711 let desc = desc.into();
712 match desc {
713 #[cfg(feature = "audio")]
714 FrameDescriptor::Audio(audio_desc) => Self::audio_creator().create_with_descriptor(audio_desc),
715 #[cfg(feature = "video")]
716 FrameDescriptor::Video(video_desc) => Self::video_creator().create_with_descriptor(video_desc),
717 FrameDescriptor::Data(data_desc) => Self::data_creator().create_with_descriptor(data_desc),
718 }
719 }
720
721 pub(crate) fn from_data<'a>(desc: FrameDescriptor, data: FrameData<'a>) -> Frame<'a> {
722 Frame {
723 desc,
724 source: None,
725 pts: None,
726 dts: None,
727 duration: None,
728 time_base: None,
729 metadata: None,
730 data,
731 }
732 }
733
734 pub fn media_type(&self) -> MediaType {
735 self.desc.media_type()
736 }
737
738 #[cfg(any(feature = "audio", feature = "video"))]
739 pub fn convert_to(&self, dst: &mut Frame) -> Result<()> {
740 match self.media_type() {
741 #[cfg(feature = "audio")]
742 MediaType::Audio => self.convert_audio_to(dst),
743 #[cfg(feature = "video")]
744 MediaType::Video => self.convert_video_to(dst),
745 _ => Err(Error::Unsupported("media type".to_string())),
746 }
747 }
748}
749
750impl<D: FrameDescriptorSpec> Frame<'_, D> {
751 pub(crate) fn from_data_with_generic_descriptor<'a>(desc: D, data: FrameData<'a>) -> Frame<'a, D> {
752 Frame {
753 desc,
754 source: None,
755 pts: None,
756 dts: None,
757 duration: None,
758 time_base: None,
759 metadata: None,
760 data,
761 }
762 }
763
764 pub fn descriptor(&self) -> &D {
765 &self.desc
766 }
767
768 pub fn into_owned(self) -> Frame<'static, D> {
769 Frame {
770 desc: self.desc,
771 source: self.source,
772 pts: self.pts,
773 dts: self.dts,
774 duration: self.duration,
775 time_base: self.time_base,
776 metadata: self.metadata,
777 data: self.data.into_owned(),
778 }
779 }
780
781 #[cfg(any(feature = "audio", feature = "video"))]
782 pub fn map(&self) -> Result<MappedGuard<'_>> {
783 self.data.map()
784 }
785
786 #[cfg(any(feature = "audio", feature = "video"))]
787 pub fn map_mut(&mut self) -> Result<MappedGuard<'_>> {
788 self.data.map_mut()
789 }
790}
791
792impl FrameSpec<FrameDescriptor> for Frame<'_, FrameDescriptor> {
793 fn new_with_descriptor(desc: FrameDescriptor) -> Result<Frame<'static>> {
794 Frame::new_with_generic_descriptor(desc)
795 }
796
797 fn media_type(&self) -> MediaType {
798 self.media_type()
799 }
800}
801
802pub trait SharedFrameInner {
803 type Descriptor: FrameDescriptorSpec;
804}
805
806impl<D: FrameDescriptorSpec> SharedFrameInner for RwLock<Frame<'_, D>> {
807 type Descriptor = D;
808}
809
810impl<D: FrameDescriptorSpec> SharedFrameInner for Frame<'_, D> {
811 type Descriptor = D;
812}
813
814#[derive(Clone)]
815pub struct SharedFrame<F: SharedFrameInner = RwLock<Frame<'static>>> {
816 inner: Arc<F>,
817 pub(crate) pool: Option<Weak<FramePool<F>>>,
818}
819
820impl<D: FrameDescriptorSpec> SharedFrame<RwLock<Frame<'static, D>>> {
821 pub fn new(frame: Frame<'_, D>) -> Self {
822 Self {
823 inner: Arc::new(RwLock::new(frame.into_owned())),
824 pool: None,
825 }
826 }
827
828 pub fn read(&self) -> LockResult<RwLockReadGuard<'_, Frame<'static, D>>> {
829 self.inner.read()
830 }
831
832 pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, Frame<'static, D>>> {
833 self.inner.write()
834 }
835}
836
837impl<D: FrameDescriptorSpec> SharedFrame<Frame<'static, D>> {
838 pub fn new(frame: Frame<'_, D>) -> Self {
839 Self {
840 inner: Arc::new(frame.into_owned()),
841 pool: None,
842 }
843 }
844
845 pub fn read(&self) -> &Frame<'static, D> {
846 &self.inner
847 }
848
849 pub fn write(&mut self) -> Option<&mut Frame<'static, D>> {
850 Arc::get_mut(&mut self.inner)
851 }
852}
853
854impl<F: SharedFrameInner> Drop for SharedFrame<F> {
855 fn drop(&mut self) {
856 if let Some(pool) = &self.pool {
857 if let Some(pool) = pool.upgrade() {
858 let cloned = SharedFrame {
859 inner: Arc::clone(&self.inner),
860 pool: None,
861 };
862 pool.recycle_frame(cloned);
863 }
864 }
865 }
866}