Skip to main content

libav_ng/avcodec/
mod.rs

1/// This module represents (almost) safe binding to AVCodecContext
2use 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
23/// AVCodecContext wrapper
24pub struct CodecContext {
25    _codec: *const AVCodec,
26    _codec_ctx: *mut AVCodecContext,
27}
28
29impl CodecContext {
30    /// Creates CodecContext from encoder ID
31    ///
32    /// Returns Some(CodecContext) on success, None on error.
33    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    /// Opens a codec
80    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    /// Set size of codec picture size
95    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    /// Get size of codec picture size
105    pub fn get_size(&self) -> (i32, i32) {
106        unsafe { ((*self._codec_ctx).width, (*self._codec_ctx).height) }
107    }
108
109    /// Set bitrate
110    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    /// Get bitrate
119    pub fn get_bitrate(&self) -> i64 {
120        unsafe {
121            (*self._codec_ctx).bit_rate
122        }
123    }
124
125    /// Set framerate (this also sets `time_base` but in inverse order)
126    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    /// Get framerate
139    pub fn get_framerate(&self) -> AVRational {
140        unsafe {
141            (*self._codec_ctx).framerate
142        }
143    }
144
145    /// Get time base
146    pub fn get_time_base(&self) -> AVRational {
147        unsafe {
148            (*self._codec_ctx).time_base
149        }
150    }
151
152    /// Set pixel format
153    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    /// Get pixel format
162    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    /// Fills parameters from codec into `params`
191    pub fn fill_parameters(&self, params: &mut CodecParameters) {
192        unsafe {
193            avcodec_parameters_from_context(params._p, self._codec_ctx);
194        }
195    }
196
197    /// Fills codec parameters from `params`
198    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    /// Set codec flags
211    pub fn set_flags(&mut self, flags: i32) {
212        unsafe {
213            (*self._codec_ctx).flags = flags;
214        }
215    }
216
217    /// Get codec flags
218    pub fn get_flags(&self) -> i32 {
219        unsafe {
220            (*self._codec_ctx).flags
221        }
222    }
223
224    /// Receive packet from codec to `out`
225    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    /// Returns true if codec is opened.
234    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    /// Frees context on drop
251    fn drop(&mut self) {
252        unsafe {
253            avcodec_free_context(&mut self._codec_ctx);
254        }
255    }
256}