media_core/video/
frame.rs

1use std::{borrow::Cow, num::NonZeroU32, sync::Arc};
2
3use aligned_vec::avec;
4
5use super::video::{PixelFormat, VideoFrameDescriptor};
6use crate::{
7    buffer::Buffer,
8    error::Error,
9    frame::{BufferData, Data, Frame, FrameData, FrameSpec, MemoryData, PlaneDescriptor, PlaneVec, SeparateMemoryData},
10    invalid_param_error, FrameDescriptor, MediaType, Result, DEFAULT_ALIGNMENT,
11};
12
13pub type VideoFrame<'a> = Frame<'a, VideoFrameDescriptor>;
14
15pub struct VideoDataCreator;
16
17impl VideoDataCreator {
18    fn create(format: PixelFormat, width: NonZeroU32, height: NonZeroU32) -> Result<MemoryData<'static>> {
19        let (size, planes) = format.calc_data_size(width.get(), height.get(), DEFAULT_ALIGNMENT as u32);
20
21        Ok(MemoryData {
22            data: Data::Owned(avec![[DEFAULT_ALIGNMENT]| 0u8; size]),
23            planes,
24        })
25    }
26
27    fn create_from_buffer<'a, T>(format: PixelFormat, width: NonZeroU32, height: NonZeroU32, buffer: T) -> Result<MemoryData<'a>>
28    where
29        T: Into<Cow<'a, [u8]>>,
30    {
31        let (size, planes) = format.calc_data_size(width.get(), height.get(), 1);
32        let buffer = buffer.into();
33
34        if buffer.len() != size {
35            return Err(Error::Invalid("buffer size".to_string()));
36        }
37
38        Ok(MemoryData {
39            data: buffer.into(),
40            planes,
41        })
42    }
43
44    fn create_from_aligned_buffer<'a, T>(format: PixelFormat, height: NonZeroU32, stride: NonZeroU32, buffer: T) -> Result<MemoryData<'a>>
45    where
46        T: Into<Cow<'a, [u8]>>,
47    {
48        let (size, planes) = format.calc_data_size_with_stride(height.get(), stride.get());
49        let buffer = buffer.into();
50
51        if buffer.len() != size {
52            return Err(Error::Invalid("buffer size".to_string()));
53        }
54
55        let data = MemoryData {
56            data: buffer.into(),
57            planes,
58        };
59
60        Ok(data)
61    }
62
63    fn create_from_packed_buffer<'a, T>(format: PixelFormat, height: NonZeroU32, stride: NonZeroU32, buffer: T) -> Result<MemoryData<'a>>
64    where
65        T: Into<Cow<'a, [u8]>>,
66    {
67        if !format.is_packed() {
68            return Err(Error::Unsupported("format".to_string()));
69        }
70
71        let buffer = buffer.into();
72
73        if buffer.len() != (stride.get() * height.get()) as usize {
74            return Err(Error::Invalid("buffer size".to_string()));
75        }
76
77        let planes = PlaneVec::from_slice(&[PlaneDescriptor::Video(stride.get() as usize, height.get())]);
78
79        let data = MemoryData {
80            data: buffer.into(),
81            planes,
82        };
83
84        Ok(data)
85    }
86
87    fn create_from_shared_buffer(
88        format: PixelFormat,
89        height: NonZeroU32,
90        buffer: Arc<Buffer>,
91        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
92    ) -> Result<BufferData> {
93        let mut planes = PlaneVec::with_capacity(buffer_planes.len());
94
95        for (i, (offset, stride)) in buffer_planes.iter().enumerate() {
96            let height = format.calc_plane_height(i, height.get());
97
98            if *offset + (*stride as usize * height as usize) > buffer.len() {
99                return Err(Error::Invalid("buffer length".to_string()));
100            }
101
102            planes.push((*offset, PlaneDescriptor::Video(*stride as usize, height)));
103        }
104
105        Ok(BufferData {
106            data: buffer.clone(),
107            planes,
108        })
109    }
110}
111
112impl BufferData {
113    fn attach_video_buffer(
114        &mut self,
115        format: PixelFormat,
116        height: NonZeroU32,
117        buffer: Arc<Buffer>,
118        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
119    ) -> Result<()> {
120        let mut planes = PlaneVec::with_capacity(buffer_planes.len());
121
122        for (i, (offset, stride)) in buffer_planes.iter().enumerate() {
123            let height = format.calc_plane_height(i, height.get());
124
125            if *offset + (*stride as usize * height as usize) > buffer.len() {
126                return Err(Error::Invalid("buffer length".to_string()));
127            }
128
129            planes.push((*offset, PlaneDescriptor::Video(*stride as usize, height)));
130        }
131
132        self.data = buffer;
133        self.planes = planes;
134
135        Ok(())
136    }
137}
138
139pub struct VideoFrameCreator;
140
141impl VideoFrameCreator {
142    pub fn create(&self, format: PixelFormat, width: u32, height: u32) -> Result<Frame<'static>> {
143        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
144
145        self.create_with_descriptor(desc)
146    }
147
148    pub fn create_with_descriptor(&self, desc: VideoFrameDescriptor) -> Result<Frame<'static>> {
149        let data = VideoDataCreator::create(desc.format, desc.width(), desc.height())?;
150
151        Ok(Self::create_from_data(desc, data))
152    }
153
154    pub fn create_from_buffer<'a, T>(&self, format: PixelFormat, width: u32, height: u32, buffer: T) -> Result<Frame<'a>>
155    where
156        T: Into<Cow<'a, [u8]>>,
157    {
158        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
159
160        self.create_from_buffer_with_descriptor(desc, buffer)
161    }
162
163    pub fn create_from_buffer_with_descriptor<'a, T>(&self, desc: VideoFrameDescriptor, buffer: T) -> Result<Frame<'a>>
164    where
165        T: Into<Cow<'a, [u8]>>,
166    {
167        let data = VideoDataCreator::create_from_buffer(desc.format, desc.width(), desc.height(), buffer)?;
168
169        Ok(Self::create_from_data(desc, data))
170    }
171
172    pub fn create_from_aligned_buffer<'a, T>(&self, format: PixelFormat, width: u32, height: u32, stride: u32, buffer: T) -> Result<Frame<'a>>
173    where
174        T: Into<Cow<'a, [u8]>>,
175    {
176        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
177        let stride = NonZeroU32::new(stride).ok_or_else(|| invalid_param_error!(stride))?;
178
179        self.create_from_aligned_buffer_with_descriptor(desc, stride, buffer)
180    }
181
182    pub fn create_from_aligned_buffer_with_descriptor<'a, T>(&self, desc: VideoFrameDescriptor, stride: NonZeroU32, buffer: T) -> Result<Frame<'a>>
183    where
184        T: Into<Cow<'a, [u8]>>,
185    {
186        let data = VideoDataCreator::create_from_aligned_buffer(desc.format, desc.height(), stride, buffer)?;
187
188        Ok(Self::create_from_data(desc, data))
189    }
190
191    pub fn create_from_packed_buffer<'a, T>(&self, format: PixelFormat, width: u32, height: u32, stride: u32, buffer: T) -> Result<Frame<'a>>
192    where
193        T: Into<Cow<'a, [u8]>>,
194    {
195        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
196        let stride = NonZeroU32::new(stride).ok_or_else(|| invalid_param_error!(stride))?;
197
198        self.create_from_packed_buffer_with_descriptor(desc, stride, buffer)
199    }
200
201    pub fn create_from_packed_buffer_with_descriptor<'a, T>(&self, desc: VideoFrameDescriptor, stride: NonZeroU32, buffer: T) -> Result<Frame<'a>>
202    where
203        T: Into<Cow<'a, [u8]>>,
204    {
205        let data = VideoDataCreator::create_from_packed_buffer(desc.format, desc.height(), stride, buffer)?;
206
207        Ok(Self::create_from_data(desc, data))
208    }
209
210    pub fn create_from_buffers<'a>(&self, format: PixelFormat, width: u32, height: u32, buffers: &[(&'a [u8], u32)]) -> Result<Frame<'a>> {
211        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
212
213        self.create_from_buffers_with_descriptor(desc, buffers)
214    }
215
216    pub fn create_from_buffers_with_descriptor<'a>(&self, desc: VideoFrameDescriptor, buffers: &[(&'a [u8], u32)]) -> Result<Frame<'a>> {
217        let data = SeparateMemoryData::from_buffers(desc.format, desc.height(), buffers)?;
218
219        Ok(Frame::from_data(FrameDescriptor::Video(desc), FrameData::SeparateMemory(data)))
220    }
221
222    pub fn create_from_shared_buffer(
223        &self,
224        format: PixelFormat,
225        width: u32,
226        height: u32,
227        buffer: Arc<Buffer>,
228        planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
229    ) -> Result<Frame<'static>> {
230        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
231
232        self.create_from_shared_buffer_with_descriptor(desc, buffer, planes)
233    }
234
235    pub fn create_from_shared_buffer_with_descriptor(
236        &self,
237        desc: VideoFrameDescriptor,
238        buffer: Arc<Buffer>,
239        planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
240    ) -> Result<Frame<'static>> {
241        let data = VideoDataCreator::create_from_shared_buffer(desc.format, desc.height(), buffer, planes)?;
242
243        Ok(Frame::from_data(FrameDescriptor::Video(desc), FrameData::Buffer(data)))
244    }
245
246    pub fn create_empty(&self, format: PixelFormat, width: u32, height: u32) -> Result<Frame<'static>> {
247        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
248
249        self.create_empty_with_descriptor(desc)
250    }
251
252    pub fn create_empty_with_descriptor(&self, desc: VideoFrameDescriptor) -> Result<Frame<'static>> {
253        let data = FrameData::Empty;
254
255        Ok(Frame::from_data(FrameDescriptor::Video(desc), data))
256    }
257
258    fn create_from_data(desc: VideoFrameDescriptor, data: MemoryData<'_>) -> Frame<'_> {
259        Frame::from_data(FrameDescriptor::Video(desc), FrameData::Memory(data))
260    }
261}
262
263impl<'a> SeparateMemoryData<'a> {
264    fn from_buffers(format: PixelFormat, height: NonZeroU32, buffers: &[(&'a [u8], u32)]) -> Result<Self> {
265        let mut data_vec = PlaneVec::with_capacity(buffers.len());
266
267        for (i, (buffer, stride)) in buffers.iter().enumerate() {
268            let height = format.calc_plane_height(i, height.get());
269
270            if buffer.len() != (*stride as usize * height as usize) {
271                return Err(Error::Invalid("buffer size".to_string()));
272            }
273
274            data_vec.push((*buffer, *stride as usize, height));
275        }
276
277        Ok(Self {
278            planes: data_vec,
279        })
280    }
281}
282
283impl Frame<'_> {
284    pub fn video_creator() -> VideoFrameCreator {
285        VideoFrameCreator
286    }
287
288    pub fn video_descriptor(&self) -> Option<&VideoFrameDescriptor> {
289        if let FrameDescriptor::Video(desc) = &self.desc {
290            Some(desc)
291        } else {
292            None
293        }
294    }
295
296    pub fn is_video(&self) -> bool {
297        self.desc.is_video()
298    }
299
300    pub fn attach_video_shared_buffer(
301        &mut self,
302        format: PixelFormat,
303        width: u32,
304        height: u32,
305        buffer: Arc<Buffer>,
306        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
307    ) -> Result<()> {
308        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
309
310        self.attach_video_shared_buffer_with_descriptor(desc, buffer, buffer_planes)
311    }
312
313    pub fn attach_video_shared_buffer_with_descriptor(
314        &mut self,
315        desc: VideoFrameDescriptor,
316        buffer: Arc<Buffer>,
317        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
318    ) -> Result<()> {
319        match &mut self.data {
320            FrameData::Buffer(data) => {
321                data.attach_video_buffer(desc.format, desc.height(), buffer, buffer_planes)?;
322            }
323            FrameData::Empty => {
324                let buffer_data = VideoDataCreator::create_from_shared_buffer(desc.format, desc.height(), buffer, buffer_planes)?;
325                self.data = FrameData::Buffer(buffer_data);
326            }
327            _ => {
328                return Err(Error::Invalid("frame data type".to_string()));
329            }
330        }
331
332        self.desc = FrameDescriptor::Video(desc);
333
334        Ok(())
335    }
336}
337
338impl VideoFrame<'_> {
339    pub fn new(format: PixelFormat, width: u32, height: u32) -> Result<Self> {
340        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
341
342        Self::new_with_descriptor(desc)
343    }
344
345    pub fn new_with_descriptor(desc: VideoFrameDescriptor) -> Result<Self> {
346        let data = VideoDataCreator::create(desc.format, desc.width(), desc.height())?;
347
348        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
349    }
350
351    pub fn from_buffer<'a, T>(format: PixelFormat, width: u32, height: u32, buffer: T) -> Result<VideoFrame<'a>>
352    where
353        T: Into<Cow<'a, [u8]>>,
354    {
355        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
356
357        Self::from_buffer_with_descriptor(desc, buffer)
358    }
359
360    pub fn from_buffer_with_descriptor<'a, T>(desc: VideoFrameDescriptor, buffer: T) -> Result<VideoFrame<'a>>
361    where
362        T: Into<Cow<'a, [u8]>>,
363    {
364        let data = VideoDataCreator::create_from_buffer(desc.format, desc.width(), desc.height(), buffer)?;
365
366        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
367    }
368
369    pub fn from_aligned_buffer<'a, T>(format: PixelFormat, width: u32, height: u32, stride: u32, buffer: T) -> Result<VideoFrame<'a>>
370    where
371        T: Into<Cow<'a, [u8]>>,
372    {
373        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
374        let stride = NonZeroU32::new(stride).ok_or_else(|| invalid_param_error!(stride))?;
375
376        Self::from_aligned_buffer_with_descriptor(desc, stride, buffer)
377    }
378
379    pub fn from_aligned_buffer_with_descriptor<'a, T>(desc: VideoFrameDescriptor, stride: NonZeroU32, buffer: T) -> Result<VideoFrame<'a>>
380    where
381        T: Into<Cow<'a, [u8]>>,
382    {
383        let data = VideoDataCreator::create_from_aligned_buffer(desc.format, desc.height(), stride, buffer)?;
384
385        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
386    }
387
388    pub fn from_packed_buffer<'a, T>(format: PixelFormat, width: u32, height: u32, stride: u32, buffer: T) -> Result<VideoFrame<'a>>
389    where
390        T: Into<Cow<'a, [u8]>>,
391    {
392        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
393        let stride = NonZeroU32::new(stride).ok_or_else(|| invalid_param_error!(stride))?;
394
395        Self::from_packed_buffer_with_descriptor(desc, stride, buffer)
396    }
397
398    pub fn from_packed_buffer_with_descriptor<'a, T>(desc: VideoFrameDescriptor, stride: NonZeroU32, buffer: T) -> Result<VideoFrame<'a>>
399    where
400        T: Into<Cow<'a, [u8]>>,
401    {
402        let data = VideoDataCreator::create_from_packed_buffer(desc.format, desc.height(), stride, buffer)?;
403
404        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Memory(data)))
405    }
406
407    pub fn from_buffers<'a>(format: PixelFormat, width: u32, height: u32, buffers: &[(&'a [u8], u32)]) -> Result<VideoFrame<'a>> {
408        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
409
410        Self::from_buffers_with_descriptor(desc, buffers)
411    }
412
413    pub fn from_buffers_with_descriptor<'a>(desc: VideoFrameDescriptor, buffers: &[(&'a [u8], u32)]) -> Result<VideoFrame<'a>> {
414        let data = SeparateMemoryData::from_buffers(desc.format, desc.height(), buffers)?;
415
416        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::SeparateMemory(data)))
417    }
418
419    pub fn from_shared_buffer(
420        format: PixelFormat,
421        width: u32,
422        height: u32,
423        buffer: Arc<Buffer>,
424        planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
425    ) -> Result<VideoFrame<'static>> {
426        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
427
428        Self::from_shared_buffer_with_descriptor(desc, buffer, planes)
429    }
430
431    pub fn from_shared_buffer_with_descriptor(
432        desc: VideoFrameDescriptor,
433        buffer: Arc<Buffer>,
434        planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
435    ) -> Result<VideoFrame<'static>> {
436        let data = VideoDataCreator::create_from_shared_buffer(desc.format, desc.height(), buffer, planes)?;
437
438        Ok(Frame::from_data_with_generic_descriptor(desc, FrameData::Buffer(data)))
439    }
440
441    pub fn new_empty(format: PixelFormat, width: u32, height: u32) -> Result<VideoFrame<'static>> {
442        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
443
444        Self::new_empty_with_descriptor(desc)
445    }
446
447    pub fn new_empty_with_descriptor(desc: VideoFrameDescriptor) -> Result<VideoFrame<'static>> {
448        let data = FrameData::Empty;
449
450        Ok(Frame::from_data_with_generic_descriptor(desc, data))
451    }
452
453    pub fn attach_shared_buffer(
454        &mut self,
455        format: PixelFormat,
456        width: u32,
457        height: u32,
458        buffer: Arc<Buffer>,
459        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
460    ) -> Result<()> {
461        let desc = VideoFrameDescriptor::try_new(format, width, height)?;
462
463        self.attach_shared_buffer_with_descriptor(desc, buffer, buffer_planes)
464    }
465
466    pub fn attach_shared_buffer_with_descriptor(
467        &mut self,
468        desc: VideoFrameDescriptor,
469        buffer: Arc<Buffer>,
470        buffer_planes: &[(usize, u32)], // (offset, stride), offset from the start of the Buffer
471    ) -> Result<()> {
472        match &mut self.data {
473            FrameData::Buffer(data) => {
474                data.attach_video_buffer(desc.format, desc.height(), buffer, buffer_planes)?;
475            }
476            FrameData::Empty => {
477                let buffer_data = VideoDataCreator::create_from_shared_buffer(desc.format, desc.height(), buffer, buffer_planes)?;
478                self.data = FrameData::Buffer(buffer_data);
479            }
480            _ => {
481                return Err(Error::Invalid("frame data type".to_string()));
482            }
483        }
484
485        self.desc = desc;
486
487        Ok(())
488    }
489}
490
491impl<'a> From<VideoFrame<'a>> for Frame<'a> {
492    fn from(frame: VideoFrame<'a>) -> Self {
493        Frame {
494            desc: FrameDescriptor::Video(frame.desc),
495            source: frame.source,
496            pts: frame.pts,
497            dts: frame.dts,
498            duration: frame.duration,
499            time_base: frame.time_base,
500            metadata: frame.metadata,
501            data: frame.data,
502        }
503    }
504}
505
506impl<'a> TryFrom<Frame<'a>> for VideoFrame<'a> {
507    type Error = Error;
508
509    fn try_from(frame: Frame<'a>) -> Result<Self> {
510        if let FrameDescriptor::Video(desc) = frame.desc {
511            Ok(Frame {
512                desc,
513                source: frame.source,
514                pts: frame.pts,
515                dts: frame.dts,
516                duration: frame.duration,
517                time_base: frame.time_base,
518                metadata: frame.metadata,
519                data: frame.data,
520            })
521        } else {
522            Err(Error::Invalid("not video frame".to_string()))
523        }
524    }
525}
526
527impl FrameSpec<VideoFrameDescriptor> for VideoFrame<'_> {
528    fn new_with_descriptor(desc: VideoFrameDescriptor) -> Result<Frame<'static, VideoFrameDescriptor>> {
529        VideoFrame::new_with_descriptor(desc)
530    }
531
532    fn media_type(&self) -> MediaType {
533        MediaType::Video
534    }
535}