1use libav_sys_ng::{
3 avcodec_alloc_context3, avcodec_find_decoder,
4 avcodec_find_encoder, avcodec_free_context, avcodec_is_open, avcodec_open2,
5 avcodec_parameters_from_context, avcodec_parameters_to_context,
6 avcodec_receive_packet, avcodec_send_packet, AVCodec, AVCodecContext,
7 AVCodecID, AVDictionary, AVPixelFormat, AVRational,
8};
9
10use crate::{
11 avcodec::{
12 codec_parameters::CodecParameters,
13 encoder_decoder::{Decoder, Encoder},
14 },
15 avdictionary::Dictionary,
16 avpacket::Packet,
17 avstream::Stream,
18};
19
20pub mod codec_parameters;
21pub mod encoder_decoder;
22
23pub struct CodecContext {
25 _codec: *const AVCodec,
26 _codec_ctx: *mut AVCodecContext,
27}
28
29impl CodecContext {
30 pub fn from_encoder_id(id: AVCodecID) -> Option<Encoder> {
34 unsafe {
35 let codec = avcodec_find_encoder(id);
36
37 if codec.is_null() {
38 return None;
39 }
40
41 let codec_ctx = avcodec_alloc_context3(codec);
42
43 if codec_ctx.is_null() {
44 return None;
45 }
46
47 Some(Encoder {
48 ctx: CodecContext {
49 _codec: codec,
50 _codec_ctx: codec_ctx,
51 },
52 })
53 }
54 }
55
56 pub fn from_decoder_id(id: AVCodecID) -> Option<Decoder> {
57 unsafe {
58 let codec = avcodec_find_decoder(id);
59
60 if codec.is_null() {
61 return None;
62 }
63
64 let codec_ctx = avcodec_alloc_context3(codec);
65
66 if codec_ctx.is_null() {
67 return None;
68 }
69
70 Some(Decoder {
71 ctx: CodecContext {
72 _codec: codec,
73 _codec_ctx: codec_ctx,
74 },
75 })
76 }
77 }
78
79 pub fn open(&mut self, options: Option<&mut Dictionary>) -> Result<(), i32> {
81 let raw_options = match options {
82 Some(opt) => (unsafe { &mut opt.raw() }) as *mut *mut AVDictionary,
83 None => core::ptr::null_mut(),
84 };
85 let code = unsafe { avcodec_open2(self._codec_ctx, self._codec, raw_options) };
86
87 if code < 0 {
88 return Err(code);
89 }
90
91 Ok(())
92 }
93
94 pub fn set_size(&mut self, width: i32, height: i32) -> &mut Self {
96 unsafe {
97 (*self._codec_ctx).width = width;
98 (*self._codec_ctx).height = height;
99 }
100
101 self
102 }
103
104 pub fn get_size(&self) -> (i32, i32) {
106 unsafe { ((*self._codec_ctx).width, (*self._codec_ctx).height) }
107 }
108
109 pub fn set_bitrate(&mut self, bitrate: i64) -> &mut CodecContext {
111 unsafe {
112 (*self._codec_ctx).bit_rate = bitrate;
113 }
114
115 self
116 }
117
118 pub fn get_bitrate(&self) -> i64 {
120 unsafe {
121 (*self._codec_ctx).bit_rate
122 }
123 }
124
125 pub fn set_framerate(&mut self, fps: i32) -> &mut CodecContext {
127 unsafe {
128 (*self._codec_ctx).time_base.num = 1;
129 (*self._codec_ctx).time_base.den = fps;
130
131 (*self._codec_ctx).framerate.num = fps;
132 (*self._codec_ctx).framerate.den = 1;
133 }
134
135 self
136 }
137
138 pub fn get_framerate(&self) -> AVRational {
140 unsafe {
141 (*self._codec_ctx).framerate
142 }
143 }
144
145 pub fn get_time_base(&self) -> AVRational {
147 unsafe {
148 (*self._codec_ctx).time_base
149 }
150 }
151
152 pub fn set_pixel_format(&mut self, fmt: AVPixelFormat) -> &mut CodecContext {
154 unsafe {
155 (*self._codec_ctx).pix_fmt = fmt;
156 }
157
158 self
159 }
160
161 pub fn get_pixel_format(&self) -> AVPixelFormat {
163 unsafe {
164 (*self._codec_ctx).pix_fmt
165 }
166 }
167
168 pub fn set_gop_size(&mut self, gop_size: i32) -> &mut CodecContext {
169 unsafe {
170 (*self._codec_ctx).gop_size = gop_size;
171 }
172
173 self
174 }
175
176 pub fn get_gop_size(&self) -> i32 {
177 unsafe {
178 (*self._codec_ctx).gop_size
179 }
180 }
181
182 pub fn set_max_b_frames(&mut self, max_b_frames: i32) -> &mut CodecContext {
183 unsafe {
184 (*self._codec_ctx).max_b_frames = max_b_frames;
185 }
186
187 self
188 }
189
190 pub fn fill_parameters(&self, params: &mut CodecParameters) {
192 unsafe {
193 avcodec_parameters_from_context(params._p, self._codec_ctx);
194 }
195 }
196
197 pub fn fill_from_parameters(&self, params: &CodecParameters) {
199 unsafe {
200 avcodec_parameters_to_context(self._codec_ctx, params._p);
201 }
202 }
203
204 pub fn fill_stream_parameters(&self, stream: &Stream) {
205 unsafe {
206 avcodec_parameters_from_context(stream.raw().codecpar, self._codec_ctx);
207 }
208 }
209
210 pub fn set_flags(&mut self, flags: i32) {
212 unsafe {
213 (*self._codec_ctx).flags = flags;
214 }
215 }
216
217 pub fn get_flags(&self) -> i32 {
219 unsafe {
220 (*self._codec_ctx).flags
221 }
222 }
223
224 pub fn receive_packet(&mut self, out: &mut Packet) -> i32 {
226 unsafe { avcodec_receive_packet(self._codec_ctx, out.raw_mut()) }
227 }
228
229 pub fn send_packet(&mut self, packet: &Packet) -> i32 {
230 unsafe { avcodec_send_packet(self._codec_ctx, packet.raw()) }
231 }
232
233 pub fn is_open(&self) -> bool {
235 unsafe {
236 avcodec_is_open(self._codec_ctx) != 0
237 }
238 }
239
240 pub unsafe fn raw_codec(&self) -> *const AVCodec {
241 self._codec
242 }
243
244 pub unsafe fn raw_codec_context(&self) -> *const AVCodecContext {
245 self._codec_ctx
246 }
247}
248
249impl Drop for CodecContext {
250 fn drop(&mut self) {
252 unsafe {
253 avcodec_free_context(&mut self._codec_ctx);
254 }
255 }
256}