playa_ffmpeg/codec/
context.rs

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