1use 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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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}