ffmpeg_the_third/codec/
context.rs

1use std::any::Any;
2use std::ptr;
3use std::rc::Rc;
4
5use super::decoder::Decoder;
6use super::encoder::Encoder;
7use super::{threading, Compliance, Debug, Flags, Id};
8use crate::ffi::*;
9use crate::media;
10use crate::option;
11use crate::{AsMutPtr, AsPtr};
12use crate::{Codec, Error};
13use libc::c_int;
14
15pub struct Context {
16    ptr: *mut AVCodecContext,
17    owner: Option<Rc<dyn Any>>,
18}
19
20unsafe impl Send for Context {}
21
22impl Context {
23    pub unsafe fn wrap(ptr: *mut AVCodecContext, owner: Option<Rc<dyn Any>>) -> Self {
24        Context { ptr, owner }
25    }
26
27    pub unsafe fn as_ptr(&self) -> *const AVCodecContext {
28        self.ptr as *const _
29    }
30
31    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecContext {
32        self.ptr
33    }
34}
35
36impl Context {
37    pub fn new() -> Self {
38        unsafe {
39            Context {
40                ptr: avcodec_alloc_context3(ptr::null()),
41                owner: None,
42            }
43        }
44    }
45
46    pub fn new_with_codec(codec: Codec) -> Self {
47        unsafe {
48            Context {
49                ptr: avcodec_alloc_context3(codec.as_ptr()),
50                owner: None,
51            }
52        }
53    }
54
55    pub fn from_parameters<P: AsPtr<AVCodecParameters>>(parameters: P) -> Result<Self, Error> {
56        let mut context = Self::new();
57
58        unsafe {
59            match avcodec_parameters_to_context(context.as_mut_ptr(), parameters.as_ptr()) {
60                e if e < 0 => Err(Error::from(e)),
61                _ => Ok(context),
62            }
63        }
64    }
65
66    pub fn decoder(self) -> Decoder {
67        Decoder(self)
68    }
69
70    pub fn encoder(self) -> Encoder {
71        Encoder(self)
72    }
73
74    pub fn codec(&self) -> Option<Codec> {
75        unsafe { Codec::from_raw((*self.as_ptr()).codec) }
76    }
77
78    pub fn medium(&self) -> media::Type {
79        unsafe { media::Type::from((*self.as_ptr()).codec_type) }
80    }
81
82    pub fn set_flags(&mut self, value: Flags) {
83        unsafe {
84            (*self.as_mut_ptr()).flags = value.bits() as c_int;
85        }
86    }
87
88    pub fn id(&self) -> Id {
89        unsafe { Id::from((*self.as_ptr()).codec_id) }
90    }
91
92    pub fn compliance(&mut self, value: Compliance) {
93        unsafe {
94            (*self.as_mut_ptr()).strict_std_compliance = value.into();
95        }
96    }
97
98    pub fn debug(&mut self, value: Debug) {
99        unsafe {
100            (*self.as_mut_ptr()).debug = value.bits();
101        }
102    }
103
104    pub fn set_threading(&mut self, config: threading::Config) {
105        unsafe {
106            (*self.as_mut_ptr()).thread_type = config.kind.into();
107            (*self.as_mut_ptr()).thread_count = config.count as c_int;
108            #[cfg(not(feature = "ffmpeg_6_0"))]
109            {
110                (*self.as_mut_ptr()).thread_safe_callbacks = i32::from(config.safe);
111            }
112        }
113    }
114
115    pub fn threading(&self) -> threading::Config {
116        unsafe {
117            threading::Config {
118                kind: threading::Type::from((*self.as_ptr()).active_thread_type),
119                count: (*self.as_ptr()).thread_count as usize,
120                #[cfg(not(feature = "ffmpeg_6_0"))]
121                safe: (*self.as_ptr()).thread_safe_callbacks != 0,
122            }
123        }
124    }
125
126    pub fn set_parameters<P: AsPtr<AVCodecParameters>>(
127        &mut self,
128        parameters: P,
129    ) -> Result<(), Error> {
130        unsafe {
131            match avcodec_parameters_to_context(self.as_mut_ptr(), parameters.as_ptr()) {
132                e if e < 0 => Err(Error::from(e)),
133                _ => Ok(()),
134            }
135        }
136    }
137}
138
139impl Default for Context {
140    fn default() -> Self {
141        Self::new()
142    }
143}
144
145impl Drop for Context {
146    fn drop(&mut self) {
147        unsafe {
148            if self.owner.is_none() {
149                avcodec_free_context(&mut self.as_mut_ptr());
150            }
151        }
152    }
153}
154
155#[cfg(not(feature = "ffmpeg_5_0"))]
156impl Clone for Context {
157    fn clone(&self) -> Self {
158        let mut ctx = Context::new();
159        ctx.clone_from(self);
160
161        ctx
162    }
163
164    fn clone_from(&mut self, source: &Self) {
165        unsafe {
166            // Removed in ffmpeg >= 5.0.
167            avcodec_copy_context(self.as_mut_ptr(), source.as_ptr());
168        }
169    }
170}
171
172/// `AVCodecContext` in `Context` is the target of `option` operations.
173impl AsPtr<AVCodecContext> for Context {
174    fn as_ptr(&self) -> *const AVCodecContext {
175        self.ptr as *const _
176    }
177}
178
179impl AsMutPtr<AVCodecContext> for Context {
180    fn as_mut_ptr(&mut self) -> *mut AVCodecContext {
181        self.ptr as *mut _
182    }
183}
184
185impl option::Settable<AVCodecContext> for Context {}