ffmpeg_rs/codec/
codec.rs

1use std::ffi::CStr;
2use std::str::from_utf8_unchecked;
3
4use super::{Audio, Capabilities, Id, Profile, Video};
5use ffi::*;
6use {media, Error};
7
8#[derive(PartialEq, Eq, Copy, Clone)]
9pub struct Codec {
10    ptr: *mut AVCodec,
11}
12
13unsafe impl Send for Codec {}
14unsafe impl Sync for Codec {}
15
16impl Codec {
17    pub unsafe fn wrap(ptr: *mut AVCodec) -> Self {
18        Codec { ptr }
19    }
20
21    pub unsafe fn as_ptr(&self) -> *const AVCodec {
22        self.ptr as *const _
23    }
24
25    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodec {
26        self.ptr
27    }
28}
29
30impl Codec {
31    pub fn is_encoder(&self) -> bool {
32        unsafe { av_codec_is_encoder(self.as_ptr()) != 0 }
33    }
34
35    pub fn is_decoder(&self) -> bool {
36        unsafe { av_codec_is_decoder(self.as_ptr()) != 0 }
37    }
38
39    pub fn name(&self) -> &str {
40        unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
41    }
42
43    pub fn description(&self) -> &str {
44        unsafe {
45            let long_name = (*self.as_ptr()).long_name;
46            if long_name.is_null() {
47                ""
48            } else {
49                from_utf8_unchecked(CStr::from_ptr(long_name).to_bytes())
50            }
51        }
52    }
53
54    pub fn medium(&self) -> media::Type {
55        unsafe { media::Type::from((*self.as_ptr()).type_) }
56    }
57
58    pub fn id(&self) -> Id {
59        unsafe { Id::from((*self.as_ptr()).id) }
60    }
61
62    pub fn is_video(&self) -> bool {
63        self.medium() == media::Type::Video
64    }
65
66    pub fn video(self) -> Result<Video, Error> {
67        unsafe {
68            if self.medium() == media::Type::Video {
69                Ok(Video::new(self))
70            } else {
71                Err(Error::InvalidData)
72            }
73        }
74    }
75
76    pub fn is_audio(&self) -> bool {
77        self.medium() == media::Type::Audio
78    }
79
80    pub fn audio(self) -> Result<Audio, Error> {
81        unsafe {
82            if self.medium() == media::Type::Audio {
83                Ok(Audio::new(self))
84            } else {
85                Err(Error::InvalidData)
86            }
87        }
88    }
89
90    pub fn max_lowres(&self) -> i32 {
91        unsafe { (*self.as_ptr()).max_lowres.into() }
92    }
93
94    pub fn capabilities(&self) -> Capabilities {
95        unsafe { Capabilities::from_bits_truncate((*self.as_ptr()).capabilities as u32) }
96    }
97
98    pub fn profiles(&self) -> Option<ProfileIter> {
99        unsafe {
100            if (*self.as_ptr()).profiles.is_null() {
101                None
102            } else {
103                Some(ProfileIter::new(self.id(), (*self.as_ptr()).profiles))
104            }
105        }
106    }
107}
108
109pub struct ProfileIter {
110    id: Id,
111    ptr: *const AVProfile,
112}
113
114impl ProfileIter {
115    pub fn new(id: Id, ptr: *const AVProfile) -> Self {
116        ProfileIter { id, ptr }
117    }
118}
119
120impl Iterator for ProfileIter {
121    type Item = Profile;
122
123    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
124        unsafe {
125            if (*self.ptr).profile == FF_PROFILE_UNKNOWN {
126                return None;
127            }
128
129            let profile = Profile::from((self.id, (*self.ptr).profile));
130            self.ptr = self.ptr.offset(1);
131
132            Some(profile)
133        }
134    }
135}