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