1 | use std::any::Any; |
2 | use std::ptr; |
3 | use std::rc::Rc; |
4 | |
5 | use super::decoder::Decoder; |
6 | use super::encoder::Encoder; |
7 | use super::{threading, Compliance, Debug, Flags, Id, Parameters}; |
8 | use ffi::*; |
9 | use libc::c_int; |
10 | use media; |
11 | use {Codec, Error}; |
12 | |
13 | pub struct Context { |
14 | ptr: *mut AVCodecContext, |
15 | owner: Option<Rc<dyn Any>>, |
16 | } |
17 | |
18 | unsafe impl Send for Context {} |
19 | |
20 | impl 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 | |
34 | impl 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 | |
134 | impl Default for Context { |
135 | fn default() -> Self { |
136 | Self::new() |
137 | } |
138 | } |
139 | |
140 | impl 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" ))] |
151 | impl 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 | |