media_core/
frame.rs

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), // plane_size, actual_bytes
241    #[cfg(feature = "video")]
242    Video(usize, u32), // stride, height
243}
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    // Truncate audio frame data to the specified length
379    #[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}