1use std::{
4 ffi::{CStr, CString},
5 fmt::{self, Display, Formatter},
6 marker::PhantomData,
7 ops::{Deref, DerefMut},
8 os::raw::{c_char, c_int, c_void},
9 ptr,
10 slice::{self, Chunks, ChunksMut},
11 str::FromStr,
12};
13
14use crate::time::{TimeBase, Timestamp};
15
16extern "C" {
17 fn ffw_get_pixel_format_by_name(name: *const c_char) -> c_int;
18 fn ffw_pixel_format_is_none(format: c_int) -> c_int;
19 fn ffw_get_pixel_format_name(format: c_int) -> *const c_char;
20
21 fn ffw_frame_new_black(pixel_format: c_int, width: c_int, height: c_int) -> *mut c_void;
22 fn ffw_frame_get_format(frame: *const c_void) -> c_int;
23 fn ffw_frame_get_width(frame: *const c_void) -> c_int;
24 fn ffw_frame_get_height(frame: *const c_void) -> c_int;
25 fn ffw_frame_get_best_effort_timestamp(frame: *const c_void) -> i64;
26 fn ffw_frame_get_pts(frame: *const c_void) -> i64;
27 fn ffw_frame_set_pts(frame: *mut c_void, pts: i64);
28 fn ffw_frame_get_plane_data(frame: *mut c_void, index: usize) -> *mut u8;
29 fn ffw_frame_get_line_size(frame: *const c_void, plane: usize) -> usize;
30 fn ffw_frame_get_line_count(frame: *const c_void, plane: usize) -> usize;
31 fn ffw_frame_clone(frame: *const c_void) -> *mut c_void;
32 fn ffw_frame_free(frame: *mut c_void);
33 fn ffw_frame_is_writable(frame: *const c_void) -> c_int;
34 fn ffw_frame_make_writable(frame: *mut c_void) -> c_int;
35 fn ffw_frame_get_picture_type(frame: *const c_void) -> c_int;
36 fn ffw_frame_set_picture_type(frame: *mut c_void, picture_type: c_int);
37}
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
40pub enum PictureType {
41 None = 0,
42 I = 1,
44 P = 2,
46 B = 3,
48 S = 4,
50 Si = 5,
52 Sp = 6,
54 Bi = 7,
56}
57
58impl PictureType {
59 pub(crate) fn from_raw(value: c_int) -> Self {
60 match value {
61 1 => PictureType::I,
62 2 => PictureType::P,
63 3 => PictureType::B,
64 4 => PictureType::S,
65 5 => PictureType::Si,
66 6 => PictureType::Sp,
67 7 => PictureType::Bi,
68 _ => PictureType::None,
69 }
70 }
71}
72
73#[derive(Debug, Copy, Clone)]
75pub struct UnknownPixelFormat;
76
77impl Display for UnknownPixelFormat {
78 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
79 f.write_str("unknown pixel format")
80 }
81}
82
83impl std::error::Error for UnknownPixelFormat {}
84
85#[derive(Copy, Clone, Eq, PartialEq)]
87pub struct PixelFormat(c_int);
88
89impl PixelFormat {
90 pub(crate) fn from_raw(v: c_int) -> Self {
92 Self(v)
93 }
94
95 pub(crate) fn into_raw(self) -> c_int {
97 let Self(format) = self;
98
99 format
100 }
101
102 pub fn name(self) -> &'static str {
104 unsafe {
105 let ptr = ffw_get_pixel_format_name(self.into_raw());
106
107 if ptr.is_null() {
108 panic!("invalid pixel format");
109 }
110
111 let name = CStr::from_ptr(ptr as _);
112
113 name.to_str().unwrap()
114 }
115 }
116}
117
118impl FromStr for PixelFormat {
119 type Err = UnknownPixelFormat;
120
121 fn from_str(s: &str) -> Result<Self, Self::Err> {
122 let name = CString::new(s).expect("invalid pixel format name");
123
124 unsafe {
125 let format = ffw_get_pixel_format_by_name(name.as_ptr() as _);
126
127 if ffw_pixel_format_is_none(format) == 0 {
128 Ok(Self(format))
129 } else {
130 Err(UnknownPixelFormat)
131 }
132 }
133 }
134}
135
136pub fn get_pixel_format(name: &str) -> PixelFormat {
138 PixelFormat::from_str(name).unwrap()
139}
140
141pub struct Plane<'a> {
143 frame: *mut c_void,
144 index: usize,
145 phantom: PhantomData<&'a ()>,
146}
147
148impl Plane<'_> {
149 fn new(frame: *mut c_void, index: usize) -> Self {
151 Self {
152 frame,
153 index,
154 phantom: PhantomData,
155 }
156 }
157
158 pub fn data(&self) -> &[u8] {
160 let line_size = self.line_size();
161 let line_count = self.line_count();
162
163 unsafe {
164 let data = ffw_frame_get_plane_data(self.frame, self.index as _);
165
166 slice::from_raw_parts(data, line_size * line_count)
167 }
168 }
169
170 pub fn data_mut(&mut self) -> &mut [u8] {
172 let line_size = self.line_size();
173 let line_count = self.line_count();
174
175 unsafe {
176 let data = ffw_frame_get_plane_data(self.frame, self.index as _);
177
178 slice::from_raw_parts_mut(data, line_size * line_count)
179 }
180 }
181
182 pub fn line(&self, index: usize) -> Option<&[u8]> {
184 if index < self.line_count() {
185 let line_size = self.line_size();
186 let data = self.data();
187 let offset = index * line_size;
188
189 Some(&data[offset..offset + line_size])
190 } else {
191 None
192 }
193 }
194
195 pub fn line_mut(&mut self, index: usize) -> Option<&mut [u8]> {
197 if index < self.line_count() {
198 let line_size = self.line_size();
199 let data = self.data_mut();
200 let offset = index * line_size;
201
202 Some(&mut data[offset..offset + line_size])
203 } else {
204 None
205 }
206 }
207
208 pub fn lines(&self) -> LinesIter {
210 let line_size = self.line_size();
211 let data = self.data();
212
213 LinesIter::new(data.chunks(line_size))
214 }
215
216 pub fn lines_mut(&mut self) -> LinesIterMut {
218 let line_size = self.line_size();
219 let data = self.data_mut();
220
221 LinesIterMut::new(data.chunks_mut(line_size))
222 }
223
224 pub fn line_size(&self) -> usize {
226 unsafe { ffw_frame_get_line_size(self.frame, self.index as _) as _ }
227 }
228
229 pub fn line_count(&self) -> usize {
232 unsafe { ffw_frame_get_line_count(self.frame, self.index as _) as _ }
233 }
234}
235
236pub struct LinesIter<'a> {
238 inner: Chunks<'a, u8>,
239}
240
241impl<'a> LinesIter<'a> {
242 fn new(chunks: Chunks<'a, u8>) -> Self {
244 Self { inner: chunks }
245 }
246}
247
248impl<'a> Iterator for LinesIter<'a> {
249 type Item = &'a [u8];
250
251 fn next(&mut self) -> Option<Self::Item> {
252 self.inner.next()
253 }
254}
255
256pub struct LinesIterMut<'a> {
258 inner: ChunksMut<'a, u8>,
259}
260
261impl<'a> LinesIterMut<'a> {
262 fn new(chunks: ChunksMut<'a, u8>) -> Self {
264 Self { inner: chunks }
265 }
266}
267
268impl<'a> Iterator for LinesIterMut<'a> {
269 type Item = &'a mut [u8];
270
271 fn next(&mut self) -> Option<Self::Item> {
272 self.inner.next()
273 }
274}
275
276pub struct Planes<'a> {
278 inner: [Plane<'a>; 4],
279}
280
281impl<'a> From<&'a VideoFrame> for Planes<'a> {
282 fn from(frame: &'a VideoFrame) -> Self {
283 let inner = [
284 Plane::new(frame.ptr, 0),
285 Plane::new(frame.ptr, 1),
286 Plane::new(frame.ptr, 2),
287 Plane::new(frame.ptr, 3),
288 ];
289
290 Self { inner }
291 }
292}
293
294impl<'a> From<&'a VideoFrameMut> for Planes<'a> {
295 fn from(frame: &'a VideoFrameMut) -> Self {
296 let inner = [
297 Plane::new(frame.ptr, 0),
298 Plane::new(frame.ptr, 1),
299 Plane::new(frame.ptr, 2),
300 Plane::new(frame.ptr, 3),
301 ];
302
303 Self { inner }
304 }
305}
306
307impl<'a> Deref for Planes<'a> {
308 type Target = [Plane<'a>];
309
310 #[inline]
311 fn deref(&self) -> &Self::Target {
312 &self.inner
313 }
314}
315
316pub struct PlanesMut<'a> {
318 inner: [Plane<'a>; 4],
319}
320
321impl<'a> From<&'a mut VideoFrameMut> for PlanesMut<'a> {
322 fn from(frame: &'a mut VideoFrameMut) -> Self {
323 let inner = [
326 Plane::new(frame.ptr, 0),
327 Plane::new(frame.ptr, 1),
328 Plane::new(frame.ptr, 2),
329 Plane::new(frame.ptr, 3),
330 ];
331
332 Self { inner }
333 }
334}
335
336impl<'a> Deref for PlanesMut<'a> {
337 type Target = [Plane<'a>];
338
339 #[inline]
340 fn deref(&self) -> &Self::Target {
341 &self.inner
342 }
343}
344
345impl DerefMut for PlanesMut<'_> {
346 #[inline]
347 fn deref_mut(&mut self) -> &mut Self::Target {
348 &mut self.inner
349 }
350}
351
352pub struct VideoFrameMut {
354 ptr: *mut c_void,
355 time_base: TimeBase,
356}
357
358impl VideoFrameMut {
359 pub fn black(pixel_format: PixelFormat, width: usize, height: usize) -> Self {
362 let ptr = unsafe { ffw_frame_new_black(pixel_format.into_raw(), width as _, height as _) };
363
364 if ptr.is_null() {
365 panic!("unable to allocate a video frame");
366 }
367
368 VideoFrameMut {
369 ptr,
370 time_base: TimeBase::MICROSECONDS,
371 }
372 }
373
374 pub fn pixel_format(&self) -> PixelFormat {
376 unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
377 }
378
379 pub fn width(&self) -> usize {
381 unsafe { ffw_frame_get_width(self.ptr) as _ }
382 }
383
384 pub fn height(&self) -> usize {
386 unsafe { ffw_frame_get_height(self.ptr) as _ }
387 }
388
389 #[inline]
391 pub fn time_base(&self) -> TimeBase {
392 self.time_base
393 }
394
395 pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
398 let new_pts = self.pts().with_time_base(time_base);
399
400 unsafe {
401 ffw_frame_set_pts(self.ptr, new_pts.timestamp());
402 }
403
404 self.time_base = time_base;
405
406 self
407 }
408
409 pub fn pts(&self) -> Timestamp {
411 let pts = unsafe { ffw_frame_get_pts(self.ptr) };
412
413 Timestamp::new(pts, self.time_base)
414 }
415
416 pub fn with_pts(self, pts: Timestamp) -> Self {
418 let pts = pts.with_time_base(self.time_base);
419
420 unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
421
422 self
423 }
424
425 pub fn picture_type(&self) -> PictureType {
427 unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
428 }
429
430 pub fn with_picture_type(self, picture_type: PictureType) -> Self {
432 unsafe { ffw_frame_set_picture_type(self.ptr, picture_type as c_int) };
433 self
434 }
435
436 pub fn planes(&self) -> Planes {
438 Planes::from(self)
439 }
440
441 pub fn planes_mut(&mut self) -> PlanesMut {
443 PlanesMut::from(self)
444 }
445
446 pub fn freeze(mut self) -> VideoFrame {
448 let ptr = self.ptr;
449
450 self.ptr = ptr::null_mut();
451
452 VideoFrame {
453 ptr,
454 time_base: self.time_base,
455 }
456 }
457}
458
459impl Drop for VideoFrameMut {
460 fn drop(&mut self) {
461 unsafe { ffw_frame_free(self.ptr) }
462 }
463}
464
465unsafe impl Send for VideoFrameMut {}
466unsafe impl Sync for VideoFrameMut {}
467
468pub struct VideoFrame {
470 ptr: *mut c_void,
471 time_base: TimeBase,
472}
473
474impl VideoFrame {
475 pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
477 Self { ptr, time_base }
478 }
479
480 pub fn pixel_format(&self) -> PixelFormat {
482 unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
483 }
484
485 pub fn width(&self) -> usize {
487 unsafe { ffw_frame_get_width(self.ptr) as _ }
488 }
489
490 pub fn height(&self) -> usize {
492 unsafe { ffw_frame_get_height(self.ptr) as _ }
493 }
494
495 pub fn planes(&self) -> Planes {
497 Planes::from(self)
498 }
499
500 #[inline]
502 pub fn time_base(&self) -> TimeBase {
503 self.time_base
504 }
505
506 pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
509 let new_pts = self.pts().with_time_base(time_base);
510
511 unsafe {
512 ffw_frame_set_pts(self.ptr, new_pts.timestamp());
513 }
514
515 self.time_base = time_base;
516
517 self
518 }
519
520 pub fn best_effort_timestamp(&self) -> Timestamp {
522 let pts = unsafe { ffw_frame_get_best_effort_timestamp(self.ptr) };
523
524 Timestamp::new(pts, self.time_base)
525 }
526
527 pub fn pts(&self) -> Timestamp {
529 let pts = unsafe { ffw_frame_get_pts(self.ptr) };
530
531 Timestamp::new(pts, self.time_base)
532 }
533
534 pub fn with_pts(self, pts: Timestamp) -> Self {
536 let pts = pts.with_time_base(self.time_base);
537
538 unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
539
540 self
541 }
542
543 pub fn picture_type(&self) -> PictureType {
545 unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
546 }
547
548 pub(crate) fn as_ptr(&self) -> *const c_void {
550 self.ptr
551 }
552
553 pub fn try_into_mut(self) -> Result<VideoFrameMut, VideoFrame> {
556 let res = unsafe { ffw_frame_is_writable(self.ptr) };
557 if res > 0 {
558 Ok(self.into_mut())
559 } else {
560 Err(self)
561 }
562 }
563
564 pub fn into_mut(mut self) -> VideoFrameMut {
567 let res = unsafe { ffw_frame_make_writable(self.ptr) };
568
569 if res < 0 {
570 panic!("unable to make the frame mutable");
571 }
572
573 let ptr = self.ptr;
574
575 self.ptr = ptr::null_mut();
576
577 VideoFrameMut {
578 ptr,
579 time_base: self.time_base,
580 }
581 }
582}
583
584impl Clone for VideoFrame {
585 fn clone(&self) -> Self {
586 let ptr = unsafe { ffw_frame_clone(self.ptr) };
587
588 if ptr.is_null() {
589 panic!("unable to clone a frame");
590 }
591
592 Self {
593 ptr,
594 time_base: self.time_base,
595 }
596 }
597}
598
599impl Drop for VideoFrame {
600 fn drop(&mut self) {
601 unsafe { ffw_frame_free(self.ptr) }
602 }
603}
604
605unsafe impl Send for VideoFrame {}
606unsafe impl Sync for VideoFrame {}