Skip to main content

gstreamer_pbutils/
functions.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, ptr};
4
5pub use crate::auto::functions::*;
6use crate::ffi;
7use glib::translate::*;
8
9pub unsafe trait CodecTag<'a>: gst::Tag<'a, TagType = &'a str> {}
10
11unsafe impl CodecTag<'_> for gst::tags::ContainerFormat {}
12unsafe impl CodecTag<'_> for gst::tags::AudioCodec {}
13unsafe impl CodecTag<'_> for gst::tags::VideoCodec {}
14unsafe impl CodecTag<'_> for gst::tags::SubtitleCodec {}
15unsafe impl CodecTag<'_> for gst::tags::Codec {}
16
17pub fn pb_utils_add_codec_description_to_tag_list_for_tag<'a, T: CodecTag<'a>>(
18    taglist: &mut gst::TagListRef,
19    caps: &gst::CapsRef,
20) -> Result<(), glib::BoolError> {
21    assert_initialized_main_thread!();
22    T::ensure();
23    let codec_tag = T::TAG_NAME;
24    unsafe {
25        glib::result_from_gboolean!(
26            ffi::gst_pb_utils_add_codec_description_to_tag_list(
27                taglist.as_mut_ptr(),
28                codec_tag.as_ptr(),
29                caps.as_ptr(),
30            ),
31            "Failed to find codec description",
32        )
33    }
34}
35
36#[doc(alias = "gst_pb_utils_add_codec_description_to_tag_list")]
37pub fn pb_utils_add_codec_description_to_tag_list(
38    taglist: &mut gst::TagListRef,
39    caps: &gst::CapsRef,
40) -> Result<(), glib::BoolError> {
41    assert_initialized_main_thread!();
42    unsafe {
43        glib::result_from_gboolean!(
44            ffi::gst_pb_utils_add_codec_description_to_tag_list(
45                taglist.as_mut_ptr(),
46                ptr::null_mut(),
47                caps.as_ptr(),
48            ),
49            "Failed to find codec description",
50        )
51    }
52}
53
54#[doc(alias = "gst_pb_utils_get_encoder_description")]
55pub fn pb_utils_get_encoder_description(caps: &gst::CapsRef) -> glib::GString {
56    assert_initialized_main_thread!();
57    unsafe { from_glib_full(ffi::gst_pb_utils_get_encoder_description(caps.as_ptr())) }
58}
59
60#[doc(alias = "gst_pb_utils_get_decoder_description")]
61pub fn pb_utils_get_decoder_description(caps: &gst::CapsRef) -> glib::GString {
62    assert_initialized_main_thread!();
63    unsafe { from_glib_full(ffi::gst_pb_utils_get_decoder_description(caps.as_ptr())) }
64}
65
66#[doc(alias = "gst_pb_utils_get_codec_description")]
67pub fn pb_utils_get_codec_description(caps: &gst::CapsRef) -> glib::GString {
68    assert_initialized_main_thread!();
69    unsafe { from_glib_full(ffi::gst_pb_utils_get_codec_description(caps.as_ptr())) }
70}
71
72/// Sets the level and profile on `caps` if it can be determined from
73/// `audio_config`. See [`codec_utils_aac_get_level()`][crate::codec_utils_aac_get_level()] and
74/// [`codec_utils_aac_get_profile()`][crate::codec_utils_aac_get_profile()] for more details on the parameters.
75/// `caps` must be audio/mpeg caps with an "mpegversion" field of either 2 or 4.
76/// If mpegversion is 4, the "base-profile" field is also set in `caps`.
77/// ## `caps`
78/// the [`gst::Caps`][crate::gst::Caps] to which level and profile fields are to be added
79/// ## `audio_config`
80/// a pointer to the AudioSpecificConfig
81///  as specified in the Elementary Stream Descriptor (esds)
82///  in ISO/IEC 14496-1. (See below for more details)
83///
84/// # Returns
85///
86/// [`true`] if the level and profile could be set, [`false`] otherwise.
87#[doc(alias = "gst_codec_utils_aac_caps_set_level_and_profile")]
88pub fn codec_utils_aac_caps_set_level_and_profile(
89    caps: &mut gst::CapsRef,
90    audio_config: &[u8],
91) -> Result<(), glib::BoolError> {
92    assert_initialized_main_thread!();
93
94    assert_eq!(caps.size(), 1);
95
96    let s = caps.structure(0).unwrap();
97    assert_eq!(s.name(), "audio/mpeg");
98    assert!(s.get::<i32>("mpegversion").is_ok_and(|v| v == 2 || v == 4));
99
100    let len = audio_config.len() as u32;
101    unsafe {
102        let res: bool = from_glib(ffi::gst_codec_utils_aac_caps_set_level_and_profile(
103            caps.as_mut_ptr(),
104            audio_config.to_glib_none().0,
105            len,
106        ));
107
108        if res {
109            Ok(())
110        } else {
111            Err(glib::bool_error!("Failed to set AAC level/profile to caps"))
112        }
113    }
114}
115
116/// Sets the level and profile in `caps` if it can be determined from `sps`. See
117/// [`codec_utils_h264_get_level()`][crate::codec_utils_h264_get_level()] and [`codec_utils_h264_get_profile()`][crate::codec_utils_h264_get_profile()]
118/// for more details on the parameters.
119/// ## `caps`
120/// the [`gst::Caps`][crate::gst::Caps] to which the level and profile are to be added
121/// ## `sps`
122/// Pointer to the sequence parameter set for the stream.
123///
124/// # Returns
125///
126/// [`true`] if the level and profile could be set, [`false`] otherwise.
127#[doc(alias = "gst_codec_utils_h264_caps_set_level_and_profile")]
128pub fn codec_utils_h264_caps_set_level_and_profile(
129    caps: &mut gst::CapsRef,
130    sps: &[u8],
131) -> Result<(), glib::BoolError> {
132    assert_initialized_main_thread!();
133
134    assert_eq!(caps.size(), 1);
135
136    let s = caps.structure(0).unwrap();
137    assert_eq!(s.name(), "video/x-h264");
138
139    let len = sps.len() as u32;
140    unsafe {
141        let res: bool = from_glib(ffi::gst_codec_utils_h264_caps_set_level_and_profile(
142            caps.as_mut_ptr(),
143            sps.to_glib_none().0,
144            len,
145        ));
146
147        if res {
148            Ok(())
149        } else {
150            Err(glib::bool_error!(
151                "Failed to set H264 level/profile to caps"
152            ))
153        }
154    }
155}
156
157/// Parses profile, flags, and level from a H264 AVCC extradata/sequence_header.
158/// These are most commonly retrieved from a video/x-h264 caps with a codec_data
159/// buffer.
160///
161/// The format of H264 AVCC extradata/sequence_header is documented in the
162/// ITU-T H.264 specification section 7.3.2.1.1 as well as in ISO/IEC 14496-15
163/// section 5.3.3.1.2.
164/// ## `codec_data`
165/// H264 AVCC extradata
166///
167/// # Returns
168///
169/// [`true`] on success, [`false`] on failure
170///
171/// ## `profile`
172/// return location for h264 profile_idc or [`None`]
173///
174/// ## `flags`
175/// return location for h264 constraint set flags or [`None`]
176///
177/// ## `level`
178/// return location h264 level_idc or [`None`]
179#[cfg(feature = "v1_20")]
180#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
181#[doc(alias = "gst_codec_utils_h264_get_profile_flags_level")]
182pub fn codec_utils_h264_get_profile_flags_level(
183    codec_data: &[u8],
184) -> Result<(u8, u8, u8), glib::BoolError> {
185    assert_initialized_main_thread!();
186    let len = codec_data.len() as u32;
187    unsafe {
188        let mut profile = mem::MaybeUninit::uninit();
189        let mut flags = mem::MaybeUninit::uninit();
190        let mut level = mem::MaybeUninit::uninit();
191        glib::result_from_gboolean!(
192            ffi::gst_codec_utils_h264_get_profile_flags_level(
193                codec_data.to_glib_none().0,
194                len,
195                profile.as_mut_ptr(),
196                flags.as_mut_ptr(),
197                level.as_mut_ptr()
198            ),
199            "Failed to get H264 profile, flags and level"
200        )?;
201        let profile = profile.assume_init();
202        let flags = flags.assume_init();
203        let level = level.assume_init();
204        Ok((profile, flags, level))
205    }
206}
207
208/// Sets the level, tier and profile in `caps` if it can be determined from
209/// `profile_tier_level`. See [`codec_utils_h265_get_level()`][crate::codec_utils_h265_get_level()],
210/// [`codec_utils_h265_get_tier()`][crate::codec_utils_h265_get_tier()] and [`codec_utils_h265_get_profile()`][crate::codec_utils_h265_get_profile()]
211/// for more details on the parameters.
212/// ## `caps`
213/// the [`gst::Caps`][crate::gst::Caps] to which the level, tier and profile are to be added
214/// ## `profile_tier_level`
215/// Pointer to the profile_tier_level
216///  struct
217///
218/// # Returns
219///
220/// [`true`] if the level, tier, profile could be set, [`false`] otherwise.
221#[doc(alias = "gst_codec_utils_h265_caps_set_level_tier_and_profile")]
222pub fn codec_utils_h265_caps_set_level_tier_and_profile(
223    caps: &mut gst::CapsRef,
224    profile_tier_level: &[u8],
225) -> Result<(), glib::BoolError> {
226    assert_initialized_main_thread!();
227
228    assert_eq!(caps.size(), 1);
229
230    let s = caps.structure(0).unwrap();
231    assert_eq!(s.name(), "video/x-h265");
232
233    let len = profile_tier_level.len() as u32;
234    unsafe {
235        let res: bool = from_glib(ffi::gst_codec_utils_h265_caps_set_level_tier_and_profile(
236            caps.as_mut_ptr(),
237            profile_tier_level.to_glib_none().0,
238            len,
239        ));
240
241        if res {
242            Ok(())
243        } else {
244            Err(glib::bool_error!(
245                "Failed to set H265 level/tier/profile to caps"
246            ))
247        }
248    }
249}
250
251/// Sets the level and profile in `caps` if it can be determined from
252/// `vis_obj_seq`. See [`codec_utils_mpeg4video_get_level()`][crate::codec_utils_mpeg4video_get_level()] and
253/// [`codec_utils_mpeg4video_get_profile()`][crate::codec_utils_mpeg4video_get_profile()] for more details on the
254/// parameters.
255/// ## `caps`
256/// the [`gst::Caps`][crate::gst::Caps] to which the level and profile are to be added
257/// ## `vis_obj_seq`
258/// Pointer to the visual object
259///  sequence for the stream.
260///
261/// # Returns
262///
263/// [`true`] if the level and profile could be set, [`false`] otherwise.
264#[doc(alias = "gst_codec_utils_mpeg4video_caps_set_level_and_profile")]
265pub fn codec_utils_mpeg4video_caps_set_level_and_profile(
266    caps: &mut gst::CapsRef,
267    vis_obj_seq: &[u8],
268) -> Result<(), glib::BoolError> {
269    assert_initialized_main_thread!();
270
271    assert_eq!(caps.size(), 1);
272
273    let s = caps.structure(0).unwrap();
274    assert_eq!(s.name(), "video/mpeg");
275    assert!(s.get::<i32>("mpegversion").is_ok_and(|v| v == 4));
276
277    let len = vis_obj_seq.len() as u32;
278    unsafe {
279        let res: bool = from_glib(ffi::gst_codec_utils_mpeg4video_caps_set_level_and_profile(
280            caps.as_mut_ptr(),
281            vis_obj_seq.to_glib_none().0,
282            len,
283        ));
284
285        if res {
286            Ok(())
287        } else {
288            Err(glib::bool_error!(
289                "Failed to set MPEG4 video level/profile to caps"
290            ))
291        }
292    }
293}
294
295/// Creates Opus caps from the given parameters.
296/// ## `rate`
297/// the sample rate
298/// ## `channels`
299/// the number of channels
300/// ## `channel_mapping_family`
301/// the channel mapping family
302/// ## `stream_count`
303/// the number of independent streams
304/// ## `coupled_count`
305/// the number of stereo streams
306/// ## `channel_mapping`
307/// the mapping between the streams
308///
309/// # Returns
310///
311/// The [`gst::Caps`][crate::gst::Caps], or [`None`] if the parameters would lead to
312/// invalid Opus caps.
313#[doc(alias = "gst_codec_utils_opus_create_caps")]
314pub fn codec_utils_opus_create_caps(
315    rate: u32,
316    channels: u8,
317    channel_mapping_family: u8,
318    stream_count: u8,
319    coupled_count: u8,
320    channel_mapping: &[u8],
321) -> Result<gst::Caps, glib::BoolError> {
322    assert_initialized_main_thread!();
323
324    assert!(channel_mapping.is_empty() || channel_mapping.len() == channels as usize);
325
326    unsafe {
327        let caps = ffi::gst_codec_utils_opus_create_caps(
328            rate,
329            channels,
330            channel_mapping_family,
331            stream_count,
332            coupled_count,
333            if channel_mapping.is_empty() {
334                ptr::null()
335            } else {
336                channel_mapping.to_glib_none().0
337            },
338        );
339
340        if caps.is_null() {
341            Err(glib::bool_error!(
342                "Failed to create caps from Opus configuration"
343            ))
344        } else {
345            Ok(from_glib_full(caps))
346        }
347    }
348}
349
350/// Creates Opus caps from the given OpusHead `header` and comment header
351/// `comments`.
352/// ## `header`
353/// OpusHead header
354/// ## `comments`
355/// Comment header or NULL
356///
357/// # Returns
358///
359/// The [`gst::Caps`][crate::gst::Caps].
360#[doc(alias = "gst_codec_utils_opus_create_caps_from_header")]
361pub fn codec_utils_opus_create_caps_from_header(
362    header: &gst::BufferRef,
363    comments: Option<&gst::BufferRef>,
364) -> Result<gst::Caps, glib::BoolError> {
365    assert_initialized_main_thread!();
366    unsafe {
367        Option::<_>::from_glib_full(ffi::gst_codec_utils_opus_create_caps_from_header(
368            mut_override(header.as_ptr()),
369            comments
370                .map(|b| mut_override(b.as_ptr()))
371                .unwrap_or(ptr::null_mut()),
372        ))
373        .ok_or_else(|| glib::bool_error!("Failed to create caps from Opus headers"))
374    }
375}
376
377/// Creates OpusHead header from the given parameters.
378/// ## `rate`
379/// the sample rate
380/// ## `channels`
381/// the number of channels
382/// ## `channel_mapping_family`
383/// the channel mapping family
384/// ## `stream_count`
385/// the number of independent streams
386/// ## `coupled_count`
387/// the number of stereo streams
388/// ## `channel_mapping`
389/// the mapping between the streams
390/// ## `pre_skip`
391/// Pre-skip in 48kHz samples or 0
392/// ## `output_gain`
393/// Output gain or 0
394///
395/// # Returns
396///
397/// The [`gst::Buffer`][crate::gst::Buffer] containing the OpusHead.
398#[doc(alias = "gst_codec_utils_opus_create_header")]
399#[allow(clippy::too_many_arguments)]
400pub fn codec_utils_opus_create_header(
401    rate: u32,
402    channels: u8,
403    channel_mapping_family: u8,
404    stream_count: u8,
405    coupled_count: u8,
406    channel_mapping: &[u8],
407    pre_skip: u16,
408    output_gain: i16,
409) -> Result<gst::Buffer, glib::BoolError> {
410    assert_initialized_main_thread!();
411
412    assert!(channel_mapping.is_empty() || channel_mapping.len() == channels as usize);
413
414    unsafe {
415        let header = ffi::gst_codec_utils_opus_create_header(
416            rate,
417            channels,
418            channel_mapping_family,
419            stream_count,
420            coupled_count,
421            if channel_mapping.is_empty() {
422                ptr::null()
423            } else {
424                channel_mapping.to_glib_none().0
425            },
426            pre_skip,
427            output_gain,
428        );
429
430        if header.is_null() {
431            Err(glib::bool_error!(
432                "Failed to create header from Opus configuration"
433            ))
434        } else {
435            Ok(from_glib_full(header))
436        }
437    }
438}
439
440/// Parses Opus caps and fills the different fields with defaults if possible.
441/// ## `caps`
442/// the [`gst::Caps`][crate::gst::Caps] to parse the data from
443///
444/// # Returns
445///
446/// [`true`] if parsing was successful, [`false`] otherwise.
447///
448/// ## `rate`
449/// the sample rate
450///
451/// ## `channels`
452/// the number of channels
453///
454/// ## `channel_mapping_family`
455/// the channel mapping family
456///
457/// ## `stream_count`
458/// the number of independent streams
459///
460/// ## `coupled_count`
461/// the number of stereo streams
462///
463/// ## `channel_mapping`
464/// the mapping between the streams
465#[doc(alias = "gst_codec_utils_opus_parse_caps")]
466pub fn codec_utils_opus_parse_caps(
467    caps: &gst::CapsRef,
468    channel_mapping: Option<&mut [u8; 256]>,
469) -> Result<(u32, u8, u8, u8, u8), glib::BoolError> {
470    assert_initialized_main_thread!();
471
472    unsafe {
473        let mut rate = mem::MaybeUninit::uninit();
474        let mut channels = mem::MaybeUninit::uninit();
475        let mut channel_mapping_family = mem::MaybeUninit::uninit();
476        let mut stream_count = mem::MaybeUninit::uninit();
477        let mut coupled_count = mem::MaybeUninit::uninit();
478
479        let res: bool = from_glib(ffi::gst_codec_utils_opus_parse_caps(
480            mut_override(caps.as_ptr()),
481            rate.as_mut_ptr(),
482            channels.as_mut_ptr(),
483            channel_mapping_family.as_mut_ptr(),
484            stream_count.as_mut_ptr(),
485            coupled_count.as_mut_ptr(),
486            if let Some(channel_mapping) = channel_mapping {
487                channel_mapping.as_mut_ptr() as *mut [u8; 256]
488            } else {
489                ptr::null_mut()
490            },
491        ));
492
493        if res {
494            Ok((
495                rate.assume_init(),
496                channels.assume_init(),
497                channel_mapping_family.assume_init(),
498                stream_count.assume_init(),
499                coupled_count.assume_init(),
500            ))
501        } else {
502            Err(glib::bool_error!("Failed to parse Opus caps"))
503        }
504    }
505}
506
507/// Parses the OpusHead header.
508/// ## `header`
509/// the OpusHead [`gst::Buffer`][crate::gst::Buffer]
510///
511/// # Returns
512///
513/// [`true`] if parsing was successful, [`false`] otherwise.
514///
515/// ## `rate`
516/// the sample rate
517///
518/// ## `channels`
519/// the number of channels
520///
521/// ## `channel_mapping_family`
522/// the channel mapping family
523///
524/// ## `stream_count`
525/// the number of independent streams
526///
527/// ## `coupled_count`
528/// the number of stereo streams
529///
530/// ## `channel_mapping`
531/// the mapping between the streams
532///
533/// ## `pre_skip`
534/// Pre-skip in 48kHz samples or 0
535///
536/// ## `output_gain`
537/// Output gain or 0
538#[doc(alias = "gst_codec_utils_opus_parse_header")]
539#[allow(clippy::type_complexity)]
540pub fn codec_utils_opus_parse_header(
541    header: &gst::BufferRef,
542    channel_mapping: Option<&mut [u8; 256]>,
543) -> Result<(u32, u8, u8, u8, u8, u16, i16), glib::BoolError> {
544    assert_initialized_main_thread!();
545
546    unsafe {
547        let mut rate = mem::MaybeUninit::uninit();
548        let mut channels = mem::MaybeUninit::uninit();
549        let mut channel_mapping_family = mem::MaybeUninit::uninit();
550        let mut stream_count = mem::MaybeUninit::uninit();
551        let mut coupled_count = mem::MaybeUninit::uninit();
552        let mut pre_skip = mem::MaybeUninit::uninit();
553        let mut output_gain = mem::MaybeUninit::uninit();
554
555        let res: bool = from_glib(ffi::gst_codec_utils_opus_parse_header(
556            mut_override(header.as_ptr()),
557            rate.as_mut_ptr(),
558            channels.as_mut_ptr(),
559            channel_mapping_family.as_mut_ptr(),
560            stream_count.as_mut_ptr(),
561            coupled_count.as_mut_ptr(),
562            if let Some(channel_mapping) = channel_mapping {
563                channel_mapping.as_mut_ptr() as *mut [u8; 256]
564            } else {
565                ptr::null_mut()
566            },
567            pre_skip.as_mut_ptr(),
568            output_gain.as_mut_ptr(),
569        ));
570
571        if res {
572            Ok((
573                rate.assume_init(),
574                channels.assume_init(),
575                channel_mapping_family.assume_init(),
576                stream_count.assume_init(),
577                coupled_count.assume_init(),
578                pre_skip.assume_init(),
579                output_gain.assume_init(),
580            ))
581        } else {
582            Err(glib::bool_error!("Failed to parse Opus header"))
583        }
584    }
585}
586
587/// Converts `caps` to a RFC 6381 compatible codec string if possible.
588///
589/// Useful for providing the 'codecs' field inside the 'Content-Type' HTTP
590/// header for containerized formats, such as mp4 or matroska.
591///
592/// Registered codecs can be found at http://mp4ra.org/#/codecs
593/// ## `caps`
594/// A [`gst::Caps`][crate::gst::Caps] to convert to mime codec
595///
596/// # Returns
597///
598/// a RFC 6381 compatible codec string or [`None`]
599#[cfg(feature = "v1_20")]
600#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
601#[doc(alias = "gst_codec_utils_caps_get_mime_codec")]
602pub fn codec_utils_caps_get_mime_codec(
603    caps: &gst::CapsRef,
604) -> Result<glib::GString, glib::BoolError> {
605    assert_initialized_main_thread!();
606    unsafe {
607        Option::<_>::from_glib_full(ffi::gst_codec_utils_caps_get_mime_codec(mut_override(
608            caps.as_ptr(),
609        )))
610        .ok_or_else(|| glib::bool_error!("Unsupported caps"))
611    }
612}
613
614/// Returns flags that describe the format of the caps if known. No flags are
615/// set for unknown caps.
616/// ## `caps`
617/// the (fixed) [`gst::Caps`][crate::gst::Caps] for which flags are requested
618///
619/// # Returns
620///
621/// [`PbUtilsCapsDescriptionFlags`][crate::PbUtilsCapsDescriptionFlags] that describe `caps`, or no flags
622///  if the caps are unknown.
623#[cfg(feature = "v1_20")]
624#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
625#[doc(alias = "gst_pb_utils_get_caps_description_flags")]
626pub fn pb_utils_get_caps_description_flags(
627    caps: &gst::CapsRef,
628) -> crate::PbUtilsCapsDescriptionFlags {
629    assert_initialized_main_thread!();
630    unsafe { from_glib(ffi::gst_pb_utils_get_caps_description_flags(caps.as_ptr())) }
631}
632
633/// Returns a possible file extension for the given caps, if known.
634/// ## `caps`
635/// the (fixed) [`gst::Caps`][crate::gst::Caps] for which a file extension is needed
636///
637/// # Returns
638///
639/// a newly-allocated file extension string, or NULL on error. Free
640///  string with `g_free()` when not needed any longer.
641#[cfg(feature = "v1_20")]
642#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
643#[doc(alias = "gst_pb_utils_get_file_extension_from_caps")]
644pub fn pb_utils_get_file_extension_from_caps(caps: &gst::CapsRef) -> Option<glib::GString> {
645    assert_initialized_main_thread!();
646    unsafe {
647        from_glib_full(ffi::gst_pb_utils_get_file_extension_from_caps(
648            caps.as_ptr(),
649        ))
650    }
651}
652
653/// Parses the provided `av1c` and returns the corresponding caps
654/// ## `av1c`
655/// a [`gst::Buffer`][crate::gst::Buffer] containing a AV1CodecConfigurationRecord
656///
657/// # Returns
658///
659/// The parsed AV1 caps, or [`None`] if there
660/// is an error
661#[cfg(feature = "v1_26")]
662#[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
663#[doc(alias = "gst_codec_utils_av1_create_caps_from_av1c")]
664pub fn codec_utils_av1_create_caps_from_av1c(
665    av1c: &gst::BufferRef,
666) -> Result<gst::Caps, glib::BoolError> {
667    assert_initialized_main_thread!();
668    unsafe {
669        Option::<_>::from_glib_full(ffi::gst_codec_utils_av1_create_caps_from_av1c(
670            mut_override(av1c.as_ptr()),
671        ))
672        .ok_or_else(|| glib::bool_error!("Failed to create caps from AV1C header"))
673    }
674}
675
676/// Creates the corresponding AV1 Codec Configuration Record
677/// ## `caps`
678/// a video/x-av1 [`gst::Caps`][crate::gst::Caps]
679///
680/// # Returns
681///
682/// The AV1 Codec Configuration Record, or
683/// [`None`] if there was an error.
684#[cfg(feature = "v1_26")]
685#[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
686#[doc(alias = "gst_codec_utils_av1_create_av1c_from_caps")]
687pub fn codec_utils_av1_create_av1c_from_caps(
688    caps: &gst::CapsRef,
689) -> Result<gst::Buffer, glib::BoolError> {
690    assert_initialized_main_thread!();
691    unsafe {
692        Option::<_>::from_glib_full(ffi::gst_codec_utils_av1_create_av1c_from_caps(
693            mut_override(caps.as_ptr()),
694        ))
695        .ok_or_else(|| glib::bool_error!("Failed to create AV1C header from caps"))
696    }
697}
698
699/// Sets the level, tier and profile in `caps` if it can be determined from
700/// `decoder_configuration`. See [`codec_utils_h266_get_level()`][crate::codec_utils_h266_get_level()],
701/// [`codec_utils_h266_get_tier()`][crate::codec_utils_h266_get_tier()] and [`codec_utils_h266_get_profile()`][crate::codec_utils_h266_get_profile()]
702/// for more details on the parameters.
703/// ## `caps`
704/// the [`gst::Caps`][crate::gst::Caps] to which the level, tier and profile are to be added
705/// ## `decoder_configuration`
706/// Pointer to the VvcDecoderConfigurationRecord struct as defined in ISO/IEC 14496-15
707///
708/// # Returns
709///
710/// [`true`] if the level, tier, profile could be set, [`false`] otherwise.
711#[cfg(feature = "v1_26")]
712#[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
713#[doc(alias = "gst_codec_utils_h266_caps_set_level_tier_and_profile")]
714pub fn codec_utils_h266_caps_set_level_tier_and_profile(
715    caps: &mut gst::CapsRef,
716    decoder_configuration: &[u8],
717) -> Result<(), glib::BoolError> {
718    assert_initialized_main_thread!();
719    let len = decoder_configuration.len() as _;
720    unsafe {
721        let res: bool = from_glib(ffi::gst_codec_utils_h266_caps_set_level_tier_and_profile(
722            mut_override(caps.as_ptr()),
723            decoder_configuration.to_glib_none().0,
724            len,
725        ));
726
727        if res {
728            Ok(())
729        } else {
730            Err(glib::bool_error!(
731                "Failed to set H266 level/tier/profile to caps"
732            ))
733        }
734    }
735}
736
737/// Estimates the vp9 level as defined in
738/// https://www.webmproject.org/vp9/mp4/`vp`-codec-configuration-box, using
739/// the resolution and, if available, frame rate found in the structure passed
740/// in.
741/// ## `caps`
742/// a video/x-vp9 [`gst::Caps`][crate::gst::Caps]
743///
744/// # Returns
745///
746/// The estimated vp9 level indicator, and 0 if it could not be
747/// estimated.
748#[cfg(feature = "v1_30")]
749#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
750#[doc(alias = "gst_codec_utils_vp9_estimate_level_idc_from_caps")]
751pub fn codec_utils_vp9_estimate_level_idc_from_caps(caps: &gst::CapsRef) -> u8 {
752    assert_initialized_main_thread!();
753    unsafe { ffi::gst_codec_utils_vp9_estimate_level_idc_from_caps(mut_override(caps.as_ptr())) }
754}
755
756/// Creates a vpcC record for VP8/VP9 as per the VP Codec ISO Media File Format
757/// Binding definition found at
758/// https://www.webmproject.org/vp9/mp4/`vp`-codec-configuration-box
759/// ## `caps`
760/// a video/x-vp8 or video/x-vp9 [`gst::Caps`][crate::gst::Caps]
761///
762/// # Returns
763///
764/// Buffer containing the vpcC record, or
765/// [`None`] if the record could not be created.
766#[cfg(feature = "v1_30")]
767#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
768#[doc(alias = "gst_codec_utils_vpx_create_vpcc_from_caps")]
769pub fn codec_utils_vpx_create_vpcc_from_caps(caps: &gst::CapsRef) -> Option<gst::Buffer> {
770    assert_initialized_main_thread!();
771    unsafe {
772        from_glib_full(ffi::gst_codec_utils_vpx_create_vpcc_from_caps(
773            mut_override(caps.as_ptr()),
774        ))
775    }
776}