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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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)], ) -> 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}