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};
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 from_parameters<P: Into<Parameters>>(parameters: P) -> Result<Self, Error> {
45 let parameters = parameters.into();
46 let mut context = Self::new();
47
48 unsafe {
49 match avcodec_parameters_to_context(context.as_mut_ptr(), parameters.as_ptr()) {
50 e if e < 0 => Err(Error::from(e)),
51 _ => Ok(context),
52 }
53 }
54 }
55
56 pub fn decoder(self) -> Decoder {
57 Decoder(self)
58 }
59
60 pub fn encoder(self) -> Encoder {
61 Encoder(self)
62 }
63
64 pub fn codec(&self) -> Option<Codec> {
65 unsafe {
66 if (*self.as_ptr()).codec.is_null() {
67 None
68 } else {
69 Some(Codec::wrap((*self.as_ptr()).codec as *mut _))
70 }
71 }
72 }
73
74 pub fn medium(&self) -> media::Type {
75 unsafe { media::Type::from((*self.as_ptr()).codec_type) }
76 }
77
78 pub fn set_flags(&mut self, value: Flags) {
79 unsafe {
80 (*self.as_mut_ptr()).flags = value.bits() as c_int;
81 }
82 }
83
84 pub fn id(&self) -> Id {
85 unsafe { Id::from((*self.as_ptr()).codec_id) }
86 }
87
88 pub fn compliance(&mut self, value: Compliance) {
89 unsafe {
90 (*self.as_mut_ptr()).strict_std_compliance = value.into();
91 }
92 }
93
94 pub fn debug(&mut self, value: Debug) {
95 unsafe {
96 (*self.as_mut_ptr()).debug = value.bits();
97 }
98 }
99
100 pub fn set_threading(&mut self, config: threading::Config) {
101 unsafe {
102 (*self.as_mut_ptr()).thread_type = config.kind.into();
103 (*self.as_mut_ptr()).thread_count = config.count as c_int;
104 #[cfg(not(feature = "ffmpeg_6_0"))]
105 {
106 (*self.as_mut_ptr()).thread_safe_callbacks = if config.safe { 1 } else { 0 };
107 }
108 }
109 }
110
111 pub fn threading(&self) -> threading::Config {
112 unsafe {
113 threading::Config {
114 kind: threading::Type::from((*self.as_ptr()).active_thread_type),
115 count: (*self.as_ptr()).thread_count as usize,
116 #[cfg(not(feature = "ffmpeg_6_0"))]
117 safe: (*self.as_ptr()).thread_safe_callbacks != 0,
118 }
119 }
120 }
121
122 pub fn set_parameters<P: Into<Parameters>>(&mut self, parameters: P) -> Result<(), Error> {
123 let parameters = parameters.into();
124
125 unsafe {
126 match avcodec_parameters_to_context(self.as_mut_ptr(), parameters.as_ptr()) {
127 e if e < 0 => Err(Error::from(e)),
128 _ => Ok(()),
129 }
130 }
131 }
132}
133
134impl Default for Context {
135 fn default() -> Self {
136 Self::new()
137 }
138}
139
140impl Drop for Context {
141 fn drop(&mut self) {
142 unsafe {
143 if self.owner.is_none() {
144 avcodec_free_context(&mut self.as_mut_ptr());
145 }
146 }
147 }
148}
149
150#[cfg(not(feature = "ffmpeg_5_0"))]
151impl Clone for Context {
152 fn clone(&self) -> Self {
153 let mut ctx: Context = Context::new();
154 ctx.clone_from(self);
155
156 ctx
157 }
158
159 fn clone_from(&mut self, source: &Self) {
160 unsafe {
161 // Removed in ffmpeg >= 5.0.
162 avcodec_copy_context(self.as_mut_ptr(), source.as_ptr());
163 }
164 }
165}
166