playa_ffmpeg/codec/
codec.rs1use 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}