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 fn deref(&self) -> &Self::Target {
311 &self.inner
312 }
313}
314
315pub struct PlanesMut<'a> {
317 inner: [Plane<'a>; 4],
318}
319
320impl<'a> From<&'a mut VideoFrameMut> for PlanesMut<'a> {
321 fn from(frame: &'a mut VideoFrameMut) -> Self {
322 let inner = [
325 Plane::new(frame.ptr, 0),
326 Plane::new(frame.ptr, 1),
327 Plane::new(frame.ptr, 2),
328 Plane::new(frame.ptr, 3),
329 ];
330
331 Self { inner }
332 }
333}
334
335impl<'a> Deref for PlanesMut<'a> {
336 type Target = [Plane<'a>];
337
338 fn deref(&self) -> &Self::Target {
339 &self.inner
340 }
341}
342
343impl<'a> DerefMut for PlanesMut<'a> {
344 fn deref_mut(&mut self) -> &mut Self::Target {
345 &mut self.inner
346 }
347}
348
349pub struct VideoFrameMut {
351 ptr: *mut c_void,
352 time_base: TimeBase,
353}
354
355impl VideoFrameMut {
356 pub fn black(pixel_format: PixelFormat, width: usize, height: usize) -> Self {
359 let ptr = unsafe { ffw_frame_new_black(pixel_format.into_raw(), width as _, height as _) };
360
361 if ptr.is_null() {
362 panic!("unable to allocate a video frame");
363 }
364
365 VideoFrameMut {
366 ptr,
367 time_base: TimeBase::MICROSECONDS,
368 }
369 }
370
371 pub fn pixel_format(&self) -> PixelFormat {
373 unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
374 }
375
376 pub fn width(&self) -> usize {
378 unsafe { ffw_frame_get_width(self.ptr) as _ }
379 }
380
381 pub fn height(&self) -> usize {
383 unsafe { ffw_frame_get_height(self.ptr) as _ }
384 }
385
386 pub fn time_base(&self) -> TimeBase {
388 self.time_base
389 }
390
391 pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
394 let new_pts = self.pts().with_time_base(time_base);
395
396 unsafe {
397 ffw_frame_set_pts(self.ptr, new_pts.timestamp());
398 }
399
400 self.time_base = time_base;
401
402 self
403 }
404
405 pub fn pts(&self) -> Timestamp {
407 let pts = unsafe { ffw_frame_get_pts(self.ptr) };
408
409 Timestamp::new(pts, self.time_base)
410 }
411
412 pub fn with_pts(self, pts: Timestamp) -> Self {
414 let pts = pts.with_time_base(self.time_base);
415
416 unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
417
418 self
419 }
420
421 pub fn picture_type(&self) -> PictureType {
423 unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
424 }
425
426 pub fn with_picture_type(self, picture_type: PictureType) -> Self {
428 unsafe { ffw_frame_set_picture_type(self.ptr, picture_type as c_int) };
429 self
430 }
431
432 pub fn planes(&self) -> Planes {
434 Planes::from(self)
435 }
436
437 pub fn planes_mut(&mut self) -> PlanesMut {
439 PlanesMut::from(self)
440 }
441
442 pub fn freeze(mut self) -> VideoFrame {
444 let ptr = self.ptr;
445
446 self.ptr = ptr::null_mut();
447
448 VideoFrame {
449 ptr,
450 time_base: self.time_base,
451 }
452 }
453}
454
455impl Drop for VideoFrameMut {
456 fn drop(&mut self) {
457 unsafe { ffw_frame_free(self.ptr) }
458 }
459}
460
461unsafe impl Send for VideoFrameMut {}
462unsafe impl Sync for VideoFrameMut {}
463
464pub struct VideoFrame {
466 ptr: *mut c_void,
467 time_base: TimeBase,
468}
469
470impl VideoFrame {
471 pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
473 Self { ptr, time_base }
474 }
475
476 pub fn pixel_format(&self) -> PixelFormat {
478 unsafe { PixelFormat::from_raw(ffw_frame_get_format(self.ptr)) }
479 }
480
481 pub fn width(&self) -> usize {
483 unsafe { ffw_frame_get_width(self.ptr) as _ }
484 }
485
486 pub fn height(&self) -> usize {
488 unsafe { ffw_frame_get_height(self.ptr) as _ }
489 }
490
491 pub fn planes(&self) -> Planes {
493 Planes::from(self)
494 }
495
496 pub fn time_base(&self) -> TimeBase {
498 self.time_base
499 }
500
501 pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
504 let new_pts = self.pts().with_time_base(time_base);
505
506 unsafe {
507 ffw_frame_set_pts(self.ptr, new_pts.timestamp());
508 }
509
510 self.time_base = time_base;
511
512 self
513 }
514
515 pub fn best_effort_timestamp(&self) -> Timestamp {
517 let pts = unsafe { ffw_frame_get_best_effort_timestamp(self.ptr) };
518
519 Timestamp::new(pts, self.time_base)
520 }
521
522 pub fn pts(&self) -> Timestamp {
524 let pts = unsafe { ffw_frame_get_pts(self.ptr) };
525
526 Timestamp::new(pts, self.time_base)
527 }
528
529 pub fn with_pts(self, pts: Timestamp) -> Self {
531 let pts = pts.with_time_base(self.time_base);
532
533 unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
534
535 self
536 }
537
538 pub fn picture_type(&self) -> PictureType {
540 unsafe { PictureType::from_raw(ffw_frame_get_picture_type(self.ptr)) }
541 }
542
543 pub(crate) fn as_ptr(&self) -> *const c_void {
545 self.ptr
546 }
547
548 pub fn try_into_mut(self) -> Result<VideoFrameMut, VideoFrame> {
551 let res = unsafe { ffw_frame_is_writable(self.ptr) };
552 if res > 0 {
553 Ok(self.into_mut())
554 } else {
555 Err(self)
556 }
557 }
558
559 pub fn into_mut(mut self) -> VideoFrameMut {
562 let res = unsafe { ffw_frame_make_writable(self.ptr) };
563
564 if res < 0 {
565 panic!("unable to make the frame mutable");
566 }
567
568 let ptr = self.ptr;
569
570 self.ptr = ptr::null_mut();
571
572 VideoFrameMut {
573 ptr,
574 time_base: self.time_base,
575 }
576 }
577}
578
579impl Clone for VideoFrame {
580 fn clone(&self) -> Self {
581 let ptr = unsafe { ffw_frame_clone(self.ptr) };
582
583 if ptr.is_null() {
584 panic!("unable to clone a frame");
585 }
586
587 Self {
588 ptr,
589 time_base: self.time_base,
590 }
591 }
592}
593
594impl Drop for VideoFrame {
595 fn drop(&mut self) {
596 unsafe { ffw_frame_free(self.ptr) }
597 }
598}
599
600unsafe impl Send for VideoFrame {}
601unsafe impl Sync for VideoFrame {}