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