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