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