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