libde265_rs/
decoder.rs

1use std::ptr::NonNull;
2use std::rc::Rc;
3
4use libde265_sys::*;
5
6use crate::{DeError, Image, Result};
7
8/// Create a new decoder.
9pub fn new_decoder() -> Result<(DecoderInput, DecoderOutput)> {
10    let decoder_context_ptr = unsafe { de265_new_decoder() };
11    if decoder_context_ptr.is_null() {
12        return Err(DeError::ErrorLibraryInitializationFailed);
13    }
14    let context = Rc::new(DecoderContext {
15        inner: decoder_context_ptr,
16    });
17    Ok((
18        DecoderInput {
19            context: context.clone(),
20        },
21        DecoderOutput { context },
22    ))
23}
24
25#[derive(Debug, Copy, Clone)]
26#[non_exhaustive]
27pub enum ParamI32 {
28    /// Dump SPS headers to a specified file-descriptor.
29    DumpSpsHeaders = de265_param::DE265_DECODER_PARAM_DUMP_SPS_HEADERS as _,
30    /// Dump VPS headers to a specified file-descriptor.
31    DumpVpsHeaders = de265_param::DE265_DECODER_PARAM_DUMP_VPS_HEADERS as _,
32    /// Dump PPS headers to a specified file-descriptor.
33    DumpPpsHeaders = de265_param::DE265_DECODER_PARAM_DUMP_PPS_HEADERS as _,
34    /// Dump Slice headers to a specified file-descriptor.
35    DumpSliceHeaders = de265_param::DE265_DECODER_PARAM_DUMP_SLICE_HEADERS as _,
36}
37
38#[derive(Debug, Copy, Clone)]
39#[non_exhaustive]
40pub enum ParamBool {
41    /// Perform SEI hash check on decoded pictures.
42    SeiCheckHash = de265_param::DE265_DECODER_PARAM_BOOL_SEI_CHECK_HASH as _,
43    /// Do not output frames with decoding errors, default: `false` (output all images)
44    SuppressFaultyPictures = de265_param::DE265_DECODER_PARAM_SUPPRESS_FAULTY_PICTURES as _,
45    /// Disable deblocking
46    DisableDeblocking = de265_param::DE265_DECODER_PARAM_DISABLE_DEBLOCKING as _,
47    /// Disable SAO filter
48    DisableSAO = de265_param::DE265_DECODER_PARAM_DISABLE_SAO as _,
49}
50
51/// Sorted such that a large ID includes all optimizations from lower IDs
52#[derive(Debug, Copy, Clone)]
53#[non_exhaustive]
54pub enum Acceleration {
55    /// only fallback implementation
56    Scalar = de265_acceleration::de265_acceleration_SCALAR as _,
57    MMS = de265_acceleration::de265_acceleration_MMX as _,
58    SSE = de265_acceleration::de265_acceleration_SSE as _,
59    SSE2 = de265_acceleration::de265_acceleration_SSE2 as _,
60    SSE4 = de265_acceleration::de265_acceleration_SSE4 as _,
61    /// not implemented yet
62    AVX = de265_acceleration::de265_acceleration_AVX as _,
63    /// not implemented yet
64    AVX2 = de265_acceleration::de265_acceleration_AVX2 as _,
65    ARM = de265_acceleration::de265_acceleration_ARM as _,
66    NEON = de265_acceleration::de265_acceleration_NEON as _,
67    Auto = de265_acceleration::de265_acceleration_AUTO as _,
68}
69
70pub(crate) struct DecoderContext {
71    pub(crate) inner: *mut de265_decoder_context,
72}
73
74impl Drop for DecoderContext {
75    fn drop(&mut self) {
76        if !self.inner.is_null() {
77            unsafe { de265_free_decoder(self.inner) };
78        }
79    }
80}
81
82pub enum DecodeResult {
83    /// The decoding process was finished.
84    Done,
85    /// The decoding process isn't yet finished,
86    /// and the [`DecoderInput::decode()`] method must be called again.
87    CallAgain,
88}
89
90/// Instance of this type is used to push input data for the decoder.
91pub struct DecoderInput {
92    context: Rc<DecoderContext>,
93}
94
95impl DecoderInput {
96    #[inline(always)]
97    fn inner(&self) -> *mut de265_decoder_context {
98        self.context.inner
99    }
100
101    /// Initialize background decoding threads.
102    ///
103    /// If this function is not called, all decoding is done in
104    /// the main thread (no multi-threading).
105    pub fn start_worker_threads(&mut self, num_threads: u32) -> Result<()> {
106        let result = unsafe {
107            de265_start_worker_threads(self.inner(), num_threads.min(i32::MAX as _) as _)
108        };
109        DeError::from_raw(result)
110    }
111
112    /// Push more data into the decoder.
113    ///
114    /// Tha data must be a raw h265 bytestream with startcodes.
115    /// The PTS (presentation time stamp) is assigned to all NALs whose
116    /// start-code 0x000001 is contained in the data.
117    /// The bytestream must contain all stuffing-bytes.
118    /// This function only pushes data into the decoder, nothing will be decoded.
119    pub fn push_data(&mut self, data: &[u8], pts: i64, user_data: usize) -> Result<()> {
120        let result = unsafe {
121            de265_push_data(
122                self.inner(),
123                data.as_ptr() as _,
124                data.len() as _,
125                pts,
126                user_data as _,
127            )
128        };
129        DeError::from_raw(result)
130    }
131
132    /// Indicate that the `push_data` method has just received data until the end of a NAL.
133    /// The remaining pending input data is put into a NAL package and forwarded to the decoder.
134    pub fn push_end_of_nal(&mut self) {
135        unsafe { de265_push_end_of_NAL(self.inner()) };
136    }
137
138    /// Indicate that the `push_data` method has just received data until the end of a frame.
139    ///
140    /// All data pending at the decoder input will be pushed into the decoder,
141    /// and the decoded picture is pushed to the output queue.
142    pub fn push_end_of_frame(&mut self) {
143        unsafe { de265_push_end_of_frame(self.inner()) };
144    }
145
146    /// Push a complete NAL unit without startcode into the decoder.
147    ///
148    /// The data must still contain all stuffing-bytes.
149    /// This function only pushes data into the decoder, nothing will be decoded.
150    pub fn push_nal(&mut self, data: &[u8], pts: i64, user_data: usize) -> Result<()> {
151        let result = unsafe {
152            de265_push_NAL(
153                self.inner(),
154                data.as_ptr() as _,
155                data.len() as _,
156                pts,
157                user_data as _,
158            )
159        };
160        DeError::from_raw(result)
161    }
162
163    /// Indicate the end-of-stream.
164    ///
165    /// All data pending at the decoder input will be pushed into the decoder,
166    /// and the decoded picture queue will be completely emptied.
167    pub fn flush_data(&mut self) -> Result<()> {
168        let result = unsafe { de265_flush_data(self.inner()) };
169        DeError::from_raw(result)
170    }
171
172    /// Return the number of bytes pending at the decoder input.
173    ///
174    /// Can be used to avoid overflowing the decoder with too much data.
175    pub fn number_of_input_bytes_pending(&self) -> usize {
176        let value = unsafe { de265_get_number_of_input_bytes_pending(self.inner()) };
177        value.max(0) as _
178    }
179
180    /// Return the number of NAL units pending at the decoder input.
181    ///
182    /// Can be used to avoid overflowing the decoder with too much data.
183    pub fn number_of_nal_units_pending(&self) -> usize {
184        let value = unsafe { de265_get_number_of_NAL_units_pending(self.inner()) };
185        value.max(0) as _
186    }
187
188    /// Do some decoding.
189    ///
190    /// Returns status whether it did perform some decoding or why it could not do so.
191    ///
192    /// The result can be one of the following values:
193    /// - [`DecodeResult::Done`] - decoding was finished;
194    /// - [`DecodeResult::CallAgain`] - the decoding process isn't yet finished,
195    ///   and the [`DecoderInput::decode()`] method must be called again.
196    ///
197    /// There are a few errors that indicate that this method should be called again
198    /// (possibly after resolving the indicated problem).
199    /// - [`DeError::ErrorImageBufferFull`] - the decoded picture buffer is full,
200    ///   extract some images before continuing;
201    /// - [`DeError::ErrorWaitingForInputData`] - insert more data
202    ///   before continuing.
203    pub fn decode(&mut self) -> Result<DecodeResult> {
204        let mut more = 0;
205        let result = unsafe { de265_decode(self.inner(), &mut more) };
206        DeError::from_raw(result).map(|_| {
207            if more > 0 {
208                DecodeResult::CallAgain
209            } else {
210                DecodeResult::Done
211            }
212        })
213    }
214
215    /// Push more data into the decoder.
216    ///
217    /// The data must be raw h265 bytestream.
218    /// All complete images in the data will be decoded, hence, do not push
219    /// too much data at once to prevent image buffer overflows.
220    /// The end of a picture can only be detected when the succeeding start-code
221    /// is read from the data.
222    /// If you want to flush the data and force decoding of the data so far
223    /// (e.g. at the end of a file), call `decode_data()` with an empty slice as
224    /// the `data` argument.
225    #[deprecated(note = "you should use `push_data` or `push_nal` and `decode` methods instead.")]
226    pub fn decode_data(&mut self, data: &[u8]) -> Result<()> {
227        let result =
228            unsafe { de265_decode_data(self.inner(), data.as_ptr() as _, data.len() as _) };
229        DeError::from_raw(result)
230    }
231
232    /// Clear decoder state. Call this when skipping in the stream.
233    pub fn reset(&mut self) {
234        unsafe { de265_reset(self.inner()) };
235    }
236
237    pub fn get_warning(&self) -> Result<()> {
238        let result = unsafe { de265_get_warning(self.inner()) };
239        DeError::from_raw(result)
240    }
241
242    /// Returns the maximum layer ID in the stream.
243    ///
244    /// Note that the maximum layer ID can change throughout the stream.
245    pub fn highest_tid(&self) -> u32 {
246        unsafe { de265_get_highest_TID(self.inner()).max(0) as _ }
247    }
248
249    /// Returns an ID of the currently decoded temporal substream.
250    pub fn current_tid(&self) -> u32 {
251        unsafe { de265_get_current_TID(self.inner()).max(0) as _ }
252    }
253
254    /// Limits decoding to a maximum temporal layer (TID).
255    pub fn set_limit_tid(&mut self, max_tid: u32) {
256        unsafe { de265_set_limit_TID(self.inner(), max_tid.min(i32::MAX as _) as _) };
257    }
258
259    /// It is used for a fine-grained selection of the frame-rate.
260    ///
261    /// A percentage of 100% will decode all frames in all temporal layers. A lower percentage
262    /// will drop approximately as many frames. Note that this is only accurate if the frames
263    /// are distributed evenly among the layers. Otherwise, the mapping is non-linear.
264    ///
265    /// The TID limit has a higher precedence than the framerate ratio. Hence, setting a higher
266    /// framerate ratio will decode at TID limit without dropping.
267    pub fn set_framerate_ratio(&mut self, percent: u8) {
268        unsafe { de265_set_framerate_ratio(self.inner(), percent as _) };
269    }
270
271    /// Increase or decrease the output frame-rate to some
272    /// discrete preferable value. Currently, these are non-dropped decoding at various
273    /// TID layers.
274    ///
275    /// The `more_vs_less` argument can be one of [-1, 0, 1].
276    ///
277    /// Returns the corresponding framerate ratio.
278    pub fn change_framerate(&mut self, more_vs_less: i8) -> u32 {
279        unsafe {
280            de265_change_framerate(self.inner(), more_vs_less.clamp(-1, 1) as i32).max(0) as _
281        }
282    }
283
284    /// Set an integer decoding parameter.
285    pub fn set_parameter_i32(&mut self, param: ParamI32, val: i32) {
286        unsafe {
287            de265_set_parameter_int(self.inner(), param as de265_param::Type, val);
288        }
289    }
290
291    /// Set a bool decoding parameter.
292    pub fn set_parameter_bool(&mut self, param: ParamBool, val: bool) {
293        unsafe {
294            de265_set_parameter_bool(
295                self.inner(),
296                param as de265_param::Type,
297                if val { 1 } else { 0 },
298            );
299        }
300    }
301
302    /// Set acceleration method, default: [`Acceleration::Auto`]
303    pub fn set_acceleration(&mut self, val: Acceleration) {
304        unsafe {
305            de265_set_parameter_int(
306                self.inner(),
307                de265_param::DE265_DECODER_PARAM_ACCELERATION_CODE,
308                val as i32,
309            );
310        }
311    }
312
313    /// Get a bool decoding parameter.
314    pub fn get_parameter_bool(&self, param: ParamBool) -> bool {
315        unsafe { de265_get_parameter_bool(self.inner(), param as de265_param::Type) != 0 }
316    }
317}
318
319/// Instance of this type is used to receive decoded pictures.
320pub struct DecoderOutput {
321    context: Rc<DecoderContext>,
322}
323
324impl DecoderOutput {
325    #[inline(always)]
326    pub(crate) fn inner(&self) -> *mut de265_decoder_context {
327        self.context.inner
328    }
329
330    /// Return the next decoded picture if there is any.
331    pub fn next_picture(&mut self) -> Option<Image<'_>> {
332        let image_ptr = unsafe { de265_peek_next_picture(self.inner()) };
333        NonNull::new(image_ptr as _).map(|p| Image::new(self.context.as_ref(), p))
334    }
335}