Skip to content

Commit e907ee3

Browse files
committed
Add generic ActionType to Codec struct
This allows removing the Encoder/Decoder traits in src/traits.rs.
1 parent 3560290 commit e907ee3

File tree

15 files changed

+200
-265
lines changed

15 files changed

+200
-265
lines changed

examples/remux.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ fn main() {
2929
stream_mapping[ist_index] = ost_index;
3030
ist_time_bases[ist_index] = ist.time_base();
3131
ost_index += 1;
32-
let mut ost = octx.add_stream(encoder::find(codec::Id::None)).unwrap();
32+
let mut ost = octx
33+
.add_stream(encoder::find(codec::Id::None).expect("ID_NONE encoder exists"))
34+
.unwrap();
3335
ost.set_parameters(ist.parameters());
3436
// We need to set codec_tag to 0 lest we run into incompatible codec tag
3537
// issues when muxing into a different container format. Unfortunately

examples/transcode-x264.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ impl Transcoder {
5353
.decoder()
5454
.video()?;
5555

56-
let codec = encoder::find(codec::Id::H264);
56+
let codec = encoder::find(codec::Id::H264).ok_or(ffmpeg::Error::EncoderNotFound)?;
5757
let mut ost = octx.add_stream(codec)?;
5858

59-
let mut encoder = codec::context::Context::new_with_codec(codec.unwrap())
59+
let mut encoder = codec::context::Context::new_with_codec(codec)
6060
.encoder()
6161
.video()?;
6262
ost.set_parameters(Parameters::from(&encoder));
@@ -221,7 +221,9 @@ fn main() {
221221
);
222222
} else {
223223
// Set up for stream copy for non-video stream.
224-
let mut ost = octx.add_stream(encoder::find(codec::Id::None)).unwrap();
224+
let mut ost = octx
225+
.add_stream(encoder::find(codec::Id::None).expect("ID_NONE encoder exists"))
226+
.unwrap();
225227
ost.set_parameters(ist.parameters());
226228
// We need to set codec_tag to 0 lest we run into incompatible codec tag
227229
// issues when muxing into a different container format. Unfortunately

src/codec/codec.rs

Lines changed: 99 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::descriptor::{CodecDescriptor, CodecDescriptorIter};
88
use super::profile::ProfileIter;
99
use super::{Capabilities, Id};
1010
use crate::ffi::*;
11+
use crate::AsPtr;
1112
use crate::{media, utils};
1213

1314
#[cfg(feature = "ffmpeg_7_1")]
@@ -17,18 +18,41 @@ pub fn list_descriptors() -> CodecDescriptorIter {
1718
CodecDescriptorIter::new()
1819
}
1920

20-
pub type Audio = Codec<AudioType>;
21-
pub type Video = Codec<VideoType>;
22-
pub type Data = Codec<DataType>;
23-
pub type Subtitle = Codec<SubtitleType>;
24-
pub type Attachment = Codec<AttachmentType>;
21+
pub type Audio<A> = Codec<A, AudioType>;
22+
pub type Video<A> = Codec<A, VideoType>;
23+
pub type Data<A> = Codec<A, DataType>;
24+
pub type Subtitle<A> = Codec<A, SubtitleType>;
25+
pub type Attachment<A> = Codec<A, AttachmentType>;
26+
27+
pub type Decoder<T> = Codec<DecodingAction, T>;
28+
pub type UnknownDecoder = Codec<DecodingAction, UnknownType>;
29+
pub type AudioDecoder = Codec<DecodingAction, AudioType>;
30+
pub type VideoDecoder = Codec<DecodingAction, VideoType>;
31+
pub type DataDecoder = Codec<DecodingAction, DataType>;
32+
pub type SubtitleDecoder = Codec<DecodingAction, SubtitleType>;
33+
pub type AttachmentDecoder = Codec<DecodingAction, AttachmentType>;
34+
35+
pub type Encoder<T> = Codec<EncodingAction, T>;
36+
pub type UnknownEncoder = Codec<EncodingAction, UnknownType>;
37+
pub type AudioEncoder = Codec<EncodingAction, AudioType>;
38+
pub type VideoEncoder = Codec<EncodingAction, VideoType>;
39+
pub type DataEncoder = Codec<EncodingAction, DataType>;
40+
pub type SubtitleEncoder = Codec<EncodingAction, SubtitleType>;
41+
pub type AttachmentEncoder = Codec<EncodingAction, AttachmentType>;
2542

2643
#[derive(PartialEq, Eq, Copy, Clone)]
27-
pub struct Codec<Type = UnknownType> {
44+
pub struct Codec<Action, Type> {
2845
ptr: NonNull<AVCodec>,
29-
_marker: PhantomData<Type>,
46+
_marker: PhantomData<(Action, Type)>,
3047
}
3148

49+
#[derive(PartialEq, Eq, Copy, Clone)]
50+
pub struct UnknownAction;
51+
#[derive(PartialEq, Eq, Copy, Clone)]
52+
pub struct DecodingAction;
53+
#[derive(PartialEq, Eq, Copy, Clone)]
54+
pub struct EncodingAction;
55+
3256
#[derive(PartialEq, Eq, Copy, Clone)]
3357
pub struct UnknownType;
3458
#[derive(PartialEq, Eq, Copy, Clone)]
@@ -42,10 +66,10 @@ pub struct SubtitleType;
4266
#[derive(PartialEq, Eq, Copy, Clone)]
4367
pub struct AttachmentType;
4468

45-
unsafe impl<T> Send for Codec<T> {}
46-
unsafe impl<T> Sync for Codec<T> {}
69+
unsafe impl<A, T> Send for Codec<A, T> {}
70+
unsafe impl<A, T> Sync for Codec<A, T> {}
4771

48-
impl Codec<UnknownType> {
72+
impl<A, T> Codec<A, T> {
4973
/// Create a new reference to a codec from a raw pointer.
5074
///
5175
/// Returns `None` if `ptr` is null.
@@ -59,84 +83,18 @@ impl Codec<UnknownType> {
5983
// Helper function to easily convert to another codec type.
6084
// TODO: Does this need to be unsafe?
6185
/// Ensure that `self.medium()` is correct for `Codec<U>`.
62-
fn as_other_codec<U>(self) -> Codec<U> {
86+
fn as_other_codec<U, B>(&self) -> Codec<U, B> {
6387
Codec {
6488
ptr: self.ptr,
6589
_marker: PhantomData,
6690
}
6791
}
6892

69-
pub fn is_video(&self) -> bool {
70-
self.medium() == media::Type::Video
71-
}
72-
73-
pub fn video(self) -> Option<Video> {
74-
if self.is_video() {
75-
Some(self.as_other_codec())
76-
} else {
77-
None
78-
}
79-
}
80-
81-
pub fn is_audio(&self) -> bool {
82-
self.medium() == media::Type::Audio
83-
}
84-
85-
pub fn audio(self) -> Option<Audio> {
86-
if self.is_audio() {
87-
Some(self.as_other_codec())
88-
} else {
89-
None
90-
}
91-
}
92-
93-
pub fn is_data(&self) -> bool {
94-
self.medium() == media::Type::Data
95-
}
96-
97-
pub fn data(self) -> Option<Data> {
98-
if self.is_data() {
99-
Some(self.as_other_codec())
100-
} else {
101-
None
102-
}
103-
}
104-
105-
pub fn is_subtitle(&self) -> bool {
106-
self.medium() == media::Type::Subtitle
107-
}
108-
109-
pub fn subtitle(self) -> Option<Subtitle> {
110-
if self.is_subtitle() {
111-
Some(self.as_other_codec())
112-
} else {
113-
None
114-
}
115-
}
116-
117-
pub fn is_attachment(&self) -> bool {
118-
self.medium() == media::Type::Attachment
119-
}
120-
121-
pub fn attachment(self) -> Option<Attachment> {
122-
if self.is_attachment() {
123-
Some(self.as_other_codec())
124-
} else {
125-
None
126-
}
127-
}
128-
}
129-
130-
impl<T> Codec<T> {
131-
pub fn as_ptr(&self) -> *const AVCodec {
132-
self.ptr.as_ptr()
133-
}
134-
135-
pub fn is_encoder(&self) -> bool {
93+
pub fn is_encoder(self) -> bool {
13694
unsafe { av_codec_is_encoder(self.as_ptr()) != 0 }
13795
}
13896

139-
pub fn is_decoder(&self) -> bool {
97+
pub fn is_decoder(self) -> bool {
14098
unsafe { av_codec_is_decoder(self.as_ptr()) != 0 }
14199
}
142100

@@ -182,7 +140,61 @@ impl<T> Codec<T> {
182140
}
183141
}
184142

185-
impl Codec<AudioType> {
143+
impl<A: Copy, T: Copy> Codec<A, T> {
144+
pub fn as_encoder(&self) -> Option<Encoder<T>> {
145+
self.is_encoder().then(|| self.as_other_codec())
146+
}
147+
148+
pub fn as_decoder(&self) -> Option<Decoder<T>> {
149+
self.is_decoder().then(|| self.as_other_codec())
150+
}
151+
}
152+
153+
impl<A> Codec<A, UnknownType> {
154+
pub fn is_video(self) -> bool {
155+
self.medium() == media::Type::Video
156+
}
157+
158+
pub fn is_audio(self) -> bool {
159+
self.medium() == media::Type::Audio
160+
}
161+
162+
pub fn is_data(self) -> bool {
163+
self.medium() == media::Type::Data
164+
}
165+
166+
pub fn is_subtitle(self) -> bool {
167+
self.medium() == media::Type::Subtitle
168+
}
169+
170+
pub fn is_attachment(self) -> bool {
171+
self.medium() == media::Type::Attachment
172+
}
173+
}
174+
175+
impl<A: Copy> Codec<A, UnknownType> {
176+
pub fn video(self) -> Option<Codec<A, VideoType>> {
177+
self.is_video().then(|| self.as_other_codec())
178+
}
179+
180+
pub fn audio(self) -> Option<Codec<A, AudioType>> {
181+
self.is_audio().then(|| self.as_other_codec())
182+
}
183+
184+
pub fn data(self) -> Option<Codec<A, DataType>> {
185+
self.is_data().then(|| self.as_other_codec())
186+
}
187+
188+
pub fn subtitle(self) -> Option<Codec<A, SubtitleType>> {
189+
self.is_subtitle().then(|| self.as_other_codec())
190+
}
191+
192+
pub fn attachment(self) -> Option<Codec<A, AttachmentType>> {
193+
self.is_attachment().then(|| self.as_other_codec())
194+
}
195+
}
196+
197+
impl<A> Codec<A, AudioType> {
186198
/// Checks if the given sample rate is supported by this audio codec.
187199
#[cfg(feature = "ffmpeg_7_1")]
188200
pub fn supports_rate(self, rate: libc::c_int) -> bool {
@@ -228,7 +240,7 @@ impl Codec<AudioType> {
228240
}
229241
}
230242

231-
impl Codec<VideoType> {
243+
impl<A> Codec<A, VideoType> {
232244
/// Checks if the given frame rate is supported by this video codec.
233245
#[cfg(feature = "ffmpeg_7_1")]
234246
pub fn supports_rate(self, rate: crate::Rational) -> bool {
@@ -387,3 +399,9 @@ mod ch_layout {
387399
std::mem::zeroed()
388400
}
389401
}
402+
403+
impl<A, T> AsPtr<AVCodec> for Codec<A, T> {
404+
fn as_ptr(&self) -> *const AVCodec {
405+
self.ptr.as_ptr()
406+
}
407+
}

src/codec/config.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use crate::codec::Context;
55
#[cfg(feature = "ffmpeg_7_1")]
66
use crate::ffi::*;
77
#[cfg(feature = "ffmpeg_7_1")]
8+
use crate::AsPtr;
9+
#[cfg(feature = "ffmpeg_7_1")]
810
use crate::Codec;
911
#[cfg(feature = "ffmpeg_7_1")]
1012
use crate::Error;
@@ -66,12 +68,13 @@ where
6668
}
6769

6870
#[cfg(feature = "ffmpeg_7_1")]
69-
fn supported<WrapperType, AVType, CodecType, I>(
70-
codec: Codec<CodecType>,
71+
fn supported<WrapperType, AVType, C, I>(
72+
codec: C,
7173
ctx: Option<&Context>,
7274
cfg: AVCodecConfig,
7375
) -> Result<Supported<I>, Error>
7476
where
77+
C: AsPtr<AVCodec>,
7578
I: TerminatedPtrIter<AVType, WrapperType>,
7679
AVType: Into<WrapperType>,
7780
{
@@ -157,8 +160,8 @@ macro_rules! impl_config_iter_fn {
157160
/// `avcodec_get_supported_config()`. Consider using one of the convenience methods
158161
/// on the codecs or codec contexts instead.
159162
#[cfg(feature = "ffmpeg_7_1")]
160-
pub fn $fn_name<T>(
161-
codec: Codec<T>,
163+
pub fn $fn_name<A, T>(
164+
codec: Codec<A, T>,
162165
ctx: Option<&Context>,
163166
) -> Result<Supported<$iter>, Error> {
164167
supported(codec, ctx, $codec_cfg)

src/codec/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::rc::Rc;
55
use super::decoder::Decoder;
66
use super::encoder::Encoder;
77
use super::{threading, Compliance, Debug, Flags, Id};
8+
use crate::codec::codec::{UnknownAction, UnknownType};
89
use crate::ffi::*;
910
use crate::media;
1011
use crate::option;
@@ -43,7 +44,7 @@ impl Context {
4344
}
4445
}
4546

46-
pub fn new_with_codec(codec: Codec) -> Self {
47+
pub fn new_with_codec<A, T>(codec: Codec<A, T>) -> Self {
4748
unsafe {
4849
Context {
4950
ptr: avcodec_alloc_context3(codec.as_ptr()),
@@ -71,7 +72,7 @@ impl Context {
7172
Encoder(self)
7273
}
7374

74-
pub fn codec(&self) -> Option<Codec> {
75+
pub fn codec(&self) -> Option<Codec<UnknownAction, UnknownType>> {
7576
unsafe { Codec::from_raw((*self.as_ptr()).codec) }
7677
}
7778

0 commit comments

Comments
 (0)