playa_ffmpeg/codec/
codec.rs

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