gstreamer_pbutils/
encoding_profile.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, translate::*};
4
5#[cfg(feature = "v1_20")]
6use crate::ElementProperties;
7use crate::{
8    ffi, EncodingAudioProfile, EncodingContainerProfile, EncodingProfile, EncodingVideoProfile,
9};
10
11pub trait EncodingProfileExtManual: IsA<EncodingProfile> + 'static {
12    ///
13    /// # Returns
14    ///
15    /// The properties that are going to be set on the underlying element
16    #[cfg(feature = "v1_20")]
17    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
18    #[doc(alias = "gst_encoding_profile_get_element_properties")]
19    #[doc(alias = "get_element_properties")]
20    fn element_properties(&self) -> Option<ElementProperties> {
21        unsafe {
22            from_glib_full::<_, Option<_>>(ffi::gst_encoding_profile_get_element_properties(
23                self.as_ref().to_glib_none().0,
24            ))
25            .map(ElementProperties)
26        }
27    }
28}
29
30impl<O: IsA<EncodingProfile>> EncodingProfileExtManual for O {}
31
32trait EncodingProfileBuilderCommon {
33    fn set_allow_dynamic_output(&self, allow_dynamic_output: bool);
34
35    fn set_description(&self, description: Option<&str>);
36
37    fn set_enabled(&self, enabled: bool);
38
39    fn set_format(&self, format: &gst::Caps);
40
41    fn set_name(&self, name: Option<&str>);
42
43    fn set_presence(&self, presence: u32);
44
45    fn set_preset(&self, preset: Option<&str>);
46
47    fn set_preset_name(&self, preset_name: Option<&str>);
48
49    #[cfg(feature = "v1_18")]
50    fn set_single_segment(&self, single_segment: bool);
51
52    #[cfg(feature = "v1_20")]
53    fn set_element_properties(&self, element_properties: ElementProperties);
54}
55
56impl<O: IsA<EncodingProfile>> EncodingProfileBuilderCommon for O {
57    // checker-ignore-item
58    fn set_allow_dynamic_output(&self, allow_dynamic_output: bool) {
59        unsafe {
60            ffi::gst_encoding_profile_set_allow_dynamic_output(
61                self.as_ref().to_glib_none().0,
62                allow_dynamic_output.into_glib(),
63            );
64        }
65    }
66
67    // checker-ignore-item
68    fn set_description(&self, description: Option<&str>) {
69        let description = description.to_glib_none();
70        unsafe {
71            ffi::gst_encoding_profile_set_description(
72                self.as_ref().to_glib_none().0,
73                description.0,
74            );
75        }
76    }
77
78    // checker-ignore-item
79    fn set_enabled(&self, enabled: bool) {
80        unsafe {
81            ffi::gst_encoding_profile_set_enabled(
82                self.as_ref().to_glib_none().0,
83                enabled.into_glib(),
84            );
85        }
86    }
87
88    // checker-ignore-item
89    fn set_format(&self, format: &gst::Caps) {
90        unsafe {
91            ffi::gst_encoding_profile_set_format(
92                self.as_ref().to_glib_none().0,
93                format.to_glib_none().0,
94            );
95        }
96    }
97
98    // checker-ignore-item
99    fn set_name(&self, name: Option<&str>) {
100        let name = name.to_glib_none();
101        unsafe {
102            ffi::gst_encoding_profile_set_name(self.as_ref().to_glib_none().0, name.0);
103        }
104    }
105
106    // checker-ignore-item
107    fn set_presence(&self, presence: u32) {
108        unsafe {
109            ffi::gst_encoding_profile_set_presence(self.as_ref().to_glib_none().0, presence);
110        }
111    }
112
113    // checker-ignore-item
114    fn set_preset(&self, preset: Option<&str>) {
115        let preset = preset.to_glib_none();
116        unsafe {
117            ffi::gst_encoding_profile_set_preset(self.as_ref().to_glib_none().0, preset.0);
118        }
119    }
120
121    // checker-ignore-item
122    fn set_preset_name(&self, preset_name: Option<&str>) {
123        let preset_name = preset_name.to_glib_none();
124        unsafe {
125            ffi::gst_encoding_profile_set_preset_name(
126                self.as_ref().to_glib_none().0,
127                preset_name.0,
128            );
129        }
130    }
131
132    // checker-ignore-item
133    #[cfg(feature = "v1_18")]
134    fn set_single_segment(&self, single_segment: bool) {
135        unsafe {
136            ffi::gst_encoding_profile_set_single_segment(
137                self.as_ref().to_glib_none().0,
138                single_segment.into_glib(),
139            );
140        }
141    }
142
143    // checker-ignore-item
144    #[cfg(feature = "v1_20")]
145    fn set_element_properties(&self, element_properties: ElementProperties) {
146        unsafe {
147            ffi::gst_encoding_profile_set_element_properties(
148                self.as_ref().to_glib_none().0,
149                element_properties.into_inner().into_glib_ptr(),
150            );
151        }
152    }
153}
154
155pub trait EncodingProfileHasRestrictionGetter {
156    #[doc(alias = "get_restriction")]
157    #[doc(alias = "gst_encoding_profile_get_restriction")]
158    fn restriction(&self) -> Option<gst::Caps>;
159}
160
161macro_rules! declare_encoding_profile_has_restriction(
162    ($name:ident) => {
163        impl EncodingProfileHasRestrictionGetter for $name {
164            // checker-ignore-item
165            fn restriction(&self) -> Option<gst::Caps> {
166                let profile: &EncodingProfile = glib::object::Cast::upcast_ref(self);
167
168                unsafe {
169                   from_glib_full(ffi::gst_encoding_profile_get_restriction(
170                       profile.to_glib_none().0,
171                   ))
172               }
173            }
174        }
175    }
176);
177
178impl EncodingAudioProfile {
179    // checker-ignore-item
180    fn new(
181        format: &gst::Caps,
182        preset: Option<&str>,
183        restriction: Option<&gst::Caps>,
184        presence: u32,
185    ) -> EncodingAudioProfile {
186        skip_assert_initialized!();
187        let preset = preset.to_glib_none();
188        let restriction = restriction.to_glib_none();
189        unsafe {
190            from_glib_full(ffi::gst_encoding_audio_profile_new(
191                format.to_glib_none().0,
192                preset.0,
193                restriction.0,
194                presence,
195            ))
196        }
197    }
198
199    #[doc(alias = "gst_encoding_audio_profile_new")]
200    pub fn builder(format: &gst::Caps) -> EncodingAudioProfileBuilder {
201        assert_initialized_main_thread!();
202        EncodingAudioProfileBuilder::new(format)
203    }
204}
205
206declare_encoding_profile_has_restriction!(EncodingAudioProfile);
207
208impl EncodingVideoProfile {
209    // checker-ignore-item
210    fn new(
211        format: &gst::Caps,
212        preset: Option<&str>,
213        restriction: Option<&gst::Caps>,
214        presence: u32,
215    ) -> EncodingVideoProfile {
216        skip_assert_initialized!();
217        let preset = preset.to_glib_none();
218        let restriction = restriction.to_glib_none();
219        unsafe {
220            from_glib_full(ffi::gst_encoding_video_profile_new(
221                format.to_glib_none().0,
222                preset.0,
223                restriction.0,
224                presence,
225            ))
226        }
227    }
228
229    #[doc(alias = "gst_encoding_video_profile_new")]
230    pub fn builder(format: &gst::Caps) -> EncodingVideoProfileBuilder {
231        assert_initialized_main_thread!();
232        EncodingVideoProfileBuilder::new(format)
233    }
234
235    // checker-ignore-item
236    fn set_pass(&self, pass: u32) {
237        unsafe {
238            ffi::gst_encoding_video_profile_set_pass(self.to_glib_none().0, pass);
239        }
240    }
241
242    // checker-ignore-item
243    fn set_variableframerate(&self, variableframerate: bool) {
244        unsafe {
245            ffi::gst_encoding_video_profile_set_variableframerate(
246                self.to_glib_none().0,
247                variableframerate.into_glib(),
248            );
249        }
250    }
251}
252
253declare_encoding_profile_has_restriction!(EncodingVideoProfile);
254
255impl EncodingContainerProfile {
256    // checker-ignore-item
257    fn new(
258        name: Option<&str>,
259        description: Option<&str>,
260        format: &gst::Caps,
261        preset: Option<&str>,
262    ) -> EncodingContainerProfile {
263        skip_assert_initialized!();
264        let name = name.to_glib_none();
265        let description = description.to_glib_none();
266        let preset = preset.to_glib_none();
267        unsafe {
268            from_glib_full(ffi::gst_encoding_container_profile_new(
269                name.0,
270                description.0,
271                format.to_glib_none().0,
272                preset.0,
273            ))
274        }
275    }
276
277    #[doc(alias = "gst_encoding_container_profile_new")]
278    pub fn builder(format: &gst::Caps) -> EncodingContainerProfileBuilder {
279        assert_initialized_main_thread!();
280        EncodingContainerProfileBuilder::new(format)
281    }
282
283    // checker-ignore-item
284    fn add_profile(&self, profile: impl IsA<EncodingProfile>) {
285        unsafe {
286            let res = ffi::gst_encoding_container_profile_add_profile(
287                self.to_glib_none().0,
288                profile.upcast().into_glib_ptr(),
289            );
290            // Can't possibly fail unless we pass random pointers
291            debug_assert_ne!(res, glib::ffi::GFALSE);
292        }
293    }
294}
295
296#[derive(Debug)]
297struct EncodingProfileBuilderCommonData<'a> {
298    format: &'a gst::Caps,
299    name: Option<&'a str>,
300    description: Option<&'a str>,
301    preset: Option<&'a str>,
302    preset_name: Option<&'a str>,
303    presence: u32,
304    allow_dynamic_output: bool,
305    enabled: bool,
306    #[cfg(feature = "v1_18")]
307    single_segment: bool,
308    #[cfg(feature = "v1_20")]
309    element_properties: Option<ElementProperties>,
310}
311
312impl<'a> EncodingProfileBuilderCommonData<'a> {
313    fn new(format: &'a gst::Caps) -> EncodingProfileBuilderCommonData<'a> {
314        skip_assert_initialized!();
315        EncodingProfileBuilderCommonData {
316            name: None,
317            description: None,
318            format,
319            preset: None,
320            preset_name: None,
321            presence: 0,
322            allow_dynamic_output: true,
323            enabled: true,
324            #[cfg(feature = "v1_18")]
325            single_segment: false,
326            #[cfg(feature = "v1_20")]
327            element_properties: None,
328        }
329    }
330}
331
332pub trait EncodingProfileBuilder<'a>: Sized {
333    #[doc(alias = "gst_encoding_profile_set_name")]
334    #[must_use]
335    fn name(self, name: &'a str) -> Self;
336    #[doc(alias = "gst_encoding_profile_set_description")]
337    #[must_use]
338    fn description(self, description: &'a str) -> Self;
339    #[doc(alias = "gst_encoding_profile_set_preset")]
340    #[must_use]
341    fn preset(self, preset: &'a str) -> Self;
342    #[doc(alias = "gst_encoding_profile_set_preset_name")]
343    #[must_use]
344    fn preset_name(self, preset_name: &'a str) -> Self;
345    #[doc(alias = "gst_encoding_profile_set_presence")]
346    #[must_use]
347    fn presence(self, presence: u32) -> Self;
348    #[doc(alias = "gst_encoding_profile_set_presence")]
349    #[must_use]
350    fn presence_if(self, presence: u32, predicate: bool) -> Self;
351    #[doc(alias = "gst_encoding_profile_set_presence")]
352    #[must_use]
353    fn presence_if_some(self, presence: Option<u32>) -> Self;
354    #[doc(alias = "gst_encoding_profile_set_allow_dynamic_output")]
355    #[must_use]
356    fn allow_dynamic_output(self, allow: bool) -> Self;
357    #[doc(alias = "gst_encoding_profile_set_allow_dynamic_output")]
358    #[must_use]
359    fn allow_dynamic_output_if_some(self, allow_dynamic_output: Option<bool>) -> Self;
360    #[doc(alias = "gst_encoding_profile_set_enabled")]
361    #[must_use]
362    fn enabled(self, enabled: bool) -> Self;
363    #[doc(alias = "gst_encoding_profile_set_enabled")]
364    #[must_use]
365    fn enabled_if_some(self, enabled: Option<bool>) -> Self;
366    #[cfg(feature = "v1_18")]
367    #[doc(alias = "gst_encoding_profile_set_single_segment")]
368    #[must_use]
369    fn single_segment(self, single_segment: bool) -> Self;
370    #[cfg(feature = "v1_18")]
371    #[doc(alias = "gst_encoding_profile_set_single_segment")]
372    #[must_use]
373    fn single_segment_if_some(self, single_segment: Option<bool>) -> Self;
374    #[cfg(feature = "v1_20")]
375    #[doc(alias = "gst_encoding_profile_set_element_properties")]
376    #[must_use]
377    fn element_properties(self, element_properties: ElementProperties) -> Self;
378    #[cfg(feature = "v1_20")]
379    #[doc(alias = "gst_encoding_profile_set_element_properties")]
380    #[must_use]
381    fn element_properties_if(self, element_properties: ElementProperties, predecate: bool) -> Self;
382    #[cfg(feature = "v1_20")]
383    #[doc(alias = "gst_encoding_profile_set_element_properties")]
384    #[must_use]
385    fn element_properties_if_some(self, element_properties: Option<ElementProperties>) -> Self;
386}
387
388macro_rules! declare_encoding_profile_builder_common(
389    ($name:ident) => {
390        impl<'a> EncodingProfileBuilder<'a> for $name<'a> {
391            fn name(mut self, name: &'a str) -> $name<'a> {
392                self.base.name = Some(name);
393                self
394            }
395
396            fn description(mut self, description: &'a str) -> $name<'a> {
397                self.base.description = Some(description);
398                self
399            }
400
401            fn preset(mut self, preset: &'a str) -> $name<'a> {
402                self.base.preset = Some(preset);
403                self
404            }
405
406            fn preset_name(mut self, preset_name: &'a str) -> $name<'a> {
407                self.base.preset_name = Some(preset_name);
408                self
409            }
410
411            fn presence(mut self, presence: u32) -> $name<'a> {
412                self.base.presence = presence;
413                self
414            }
415
416            fn presence_if(self, presence: u32, predicate: bool) -> $name<'a> {
417                if predicate {
418                    self.presence(presence)
419                } else {
420                    self
421                }
422            }
423
424            fn presence_if_some(self, presence: Option<u32>) -> $name<'a> {
425                if let Some(presence) = presence {
426                    self.presence(presence)
427                } else {
428                    self
429                }
430            }
431
432            fn allow_dynamic_output(mut self, allow: bool) -> $name<'a> {
433                self.base.allow_dynamic_output = allow;
434                self
435            }
436
437            fn allow_dynamic_output_if_some(self, allow_dynamic_output: Option<bool>) -> $name<'a> {
438                if let Some(allow_dynamic_output) = allow_dynamic_output {
439                    self.allow_dynamic_output(allow_dynamic_output)
440                } else {
441                    self
442                }
443            }
444
445            fn enabled(mut self, enabled: bool) -> $name<'a> {
446                self.base.enabled = enabled;
447                self
448            }
449
450            fn enabled_if_some(self, enabled: Option<bool>) -> $name<'a> {
451                if let Some(enabled) = enabled {
452                    self.enabled(enabled)
453                } else {
454                    self
455                }
456            }
457
458            #[cfg(feature = "v1_18")]
459            fn single_segment(mut self, single_segment: bool) -> $name<'a> {
460                self.base.single_segment = single_segment;
461                self
462            }
463
464            #[cfg(feature = "v1_18")]
465            fn single_segment_if_some(self, single_segment: Option<bool>) -> $name<'a> {
466                if let Some(single_segment) = single_segment {
467                    self.single_segment(single_segment)
468                } else {
469                    self
470                }
471            }
472
473            #[cfg(feature = "v1_20")]
474            fn element_properties(mut self, element_properties: ElementProperties) -> $name<'a> {
475                self.base.element_properties = Some(element_properties);
476                self
477            }
478
479            #[cfg(feature = "v1_20")]
480            fn element_properties_if(self, element_properties: ElementProperties, predicate: bool) -> $name<'a> {
481                if predicate {
482                    self.element_properties(element_properties)
483                } else {
484                    self
485                }
486            }
487
488            #[cfg(feature = "v1_20")]
489            fn element_properties_if_some(self, element_properties: Option<ElementProperties>) -> $name<'a> {
490                if let Some(element_properties) = element_properties {
491                    self.element_properties(element_properties)
492                } else {
493                    self
494                }
495            }
496        }
497    }
498);
499
500fn set_common_fields<T: EncodingProfileBuilderCommon>(
501    profile: &T,
502    base_data: EncodingProfileBuilderCommonData,
503) {
504    skip_assert_initialized!();
505    profile.set_format(base_data.format);
506    profile.set_name(base_data.name);
507    profile.set_description(base_data.description);
508    profile.set_preset(base_data.preset);
509    profile.set_preset_name(base_data.preset_name);
510    profile.set_allow_dynamic_output(base_data.allow_dynamic_output);
511    profile.set_enabled(base_data.enabled);
512    profile.set_presence(base_data.presence);
513    #[cfg(feature = "v1_18")]
514    {
515        profile.set_single_segment(base_data.single_segment);
516    }
517    #[cfg(feature = "v1_20")]
518    {
519        let mut base_data = base_data;
520        if let Some(element_properties) = base_data.element_properties.take() {
521            profile.set_element_properties(element_properties);
522        }
523    }
524}
525
526#[derive(Debug)]
527#[must_use = "The builder must be built to be used"]
528pub struct EncodingAudioProfileBuilder<'a> {
529    base: EncodingProfileBuilderCommonData<'a>,
530    restriction: Option<&'a gst::Caps>,
531}
532
533declare_encoding_profile_builder_common!(EncodingAudioProfileBuilder);
534
535impl<'a> EncodingAudioProfileBuilder<'a> {
536    fn new(format: &'a gst::Caps) -> Self {
537        skip_assert_initialized!();
538        EncodingAudioProfileBuilder {
539            base: EncodingProfileBuilderCommonData::new(format),
540            restriction: None,
541        }
542    }
543
544    #[doc(alias = "gst_encoding_profile_set_restriction")]
545    pub fn restriction(mut self, restriction: &'a gst::Caps) -> Self {
546        self.restriction = Some(restriction);
547        self
548    }
549
550    #[must_use = "Building the profile without using it has no effect"]
551    pub fn build(self) -> EncodingAudioProfile {
552        let profile = EncodingAudioProfile::new(
553            self.base.format,
554            self.base.preset,
555            self.restriction,
556            self.base.presence,
557        );
558
559        set_common_fields(&profile, self.base);
560
561        profile
562    }
563}
564
565#[derive(Debug)]
566#[must_use = "The builder must be built to be used"]
567pub struct EncodingVideoProfileBuilder<'a> {
568    base: EncodingProfileBuilderCommonData<'a>,
569    restriction: Option<&'a gst::Caps>,
570    pass: u32,
571    variable_framerate: bool,
572}
573
574declare_encoding_profile_builder_common!(EncodingVideoProfileBuilder);
575
576impl<'a> EncodingVideoProfileBuilder<'a> {
577    fn new(format: &'a gst::Caps) -> Self {
578        skip_assert_initialized!();
579        EncodingVideoProfileBuilder {
580            base: EncodingProfileBuilderCommonData::new(format),
581            restriction: None,
582            pass: 0,
583            variable_framerate: false,
584        }
585    }
586
587    #[doc(alias = "gst_encoding_video_profile_set_pass")]
588    pub fn pass(mut self, pass: u32) -> Self {
589        self.pass = pass;
590        self
591    }
592
593    #[doc(alias = "gst_encoding_video_profile_set_variableframerate")]
594    pub fn variable_framerate(mut self, variable_framerate: bool) -> Self {
595        self.variable_framerate = variable_framerate;
596        self
597    }
598
599    #[doc(alias = "gst_encoding_profile_set_restriction")]
600    pub fn restriction(mut self, restriction: &'a gst::Caps) -> Self {
601        self.restriction = Some(restriction);
602        self
603    }
604
605    #[must_use = "Building the profile without using it has no effect"]
606    pub fn build(self) -> EncodingVideoProfile {
607        let video_profile = EncodingVideoProfile::new(
608            self.base.format,
609            self.base.preset,
610            self.restriction,
611            self.base.presence,
612        );
613
614        video_profile.set_pass(self.pass);
615        video_profile.set_variableframerate(self.variable_framerate);
616
617        set_common_fields(&video_profile, self.base);
618
619        video_profile
620    }
621}
622
623#[derive(Debug)]
624#[must_use = "The builder must be built to be used"]
625pub struct EncodingContainerProfileBuilder<'a> {
626    base: EncodingProfileBuilderCommonData<'a>,
627    profiles: Vec<EncodingProfile>,
628}
629
630declare_encoding_profile_builder_common!(EncodingContainerProfileBuilder);
631
632impl<'a> EncodingContainerProfileBuilder<'a> {
633    fn new(format: &'a gst::Caps) -> Self {
634        skip_assert_initialized!();
635        EncodingContainerProfileBuilder {
636            base: EncodingProfileBuilderCommonData::new(format),
637            profiles: Vec::new(),
638        }
639    }
640
641    #[must_use = "Building the profile without using it has no effect"]
642    pub fn build(self) -> EncodingContainerProfile {
643        let container_profile = EncodingContainerProfile::new(
644            self.base.name,
645            self.base.description,
646            self.base.format,
647            self.base.preset,
648        );
649
650        for profile in self.profiles {
651            container_profile.add_profile(profile);
652        }
653
654        set_common_fields(&container_profile, self.base);
655
656        container_profile
657    }
658
659    #[doc(alias = "gst_encoding_container_profile_add_profile")]
660    pub fn add_profile(mut self, profile: impl IsA<EncodingProfile>) -> Self {
661        self.profiles.push(profile.upcast());
662        self
663    }
664}
665
666#[cfg(test)]
667mod tests {
668    use super::*;
669    use crate::{
670        auto::{EncodingContainerProfile, EncodingVideoProfile},
671        prelude::*,
672    };
673
674    const AUDIO_PROFILE_NAME: &str = "audio-profile";
675    const AUDIO_PROFILE_DESCRIPTION: &str = "audio-profile-description";
676    const PRESET: &str = "preset";
677    const PRESET_NAME: &str = "preset-name";
678    const PRESENCE: u32 = 5;
679    const ALLOW_DYNAMIC_OUTPUT: bool = false;
680    const ENABLED: bool = false;
681
682    const VIDEO_PROFILE_NAME: &str = "video-profile";
683    const VIDEO_PROFILE_DESCRIPTION: &str = "video-profile-description";
684
685    const CONTAINER_PROFILE_NAME: &str = "container-profile";
686    const CONTAINER_PROFILE_DESCRIPTION: &str = "container-profile-description";
687
688    // Video profile exclusive attributes
689    const PASS: u32 = 8;
690    const VARIABLE_FRAMERATE: bool = true;
691
692    #[test]
693    fn test_encoding_audio_profile_builder() {
694        gst::init().unwrap();
695
696        let caps = gst::Caps::builder("audio/x-raw").build();
697
698        let restriction = gst_audio::AudioCapsBuilder::new()
699            .format(gst_audio::AudioFormat::S32le)
700            .build();
701
702        let audio_profile = EncodingAudioProfile::builder(&caps)
703            .name(AUDIO_PROFILE_NAME)
704            .description(AUDIO_PROFILE_DESCRIPTION)
705            .preset(PRESET)
706            .preset_name(PRESET_NAME)
707            .restriction(&restriction)
708            .presence(PRESENCE)
709            .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT)
710            .enabled(ENABLED)
711            .build();
712
713        assert_eq!(audio_profile.name().unwrap(), AUDIO_PROFILE_NAME);
714        assert_eq!(
715            audio_profile.description().unwrap(),
716            AUDIO_PROFILE_DESCRIPTION
717        );
718        assert_eq!(audio_profile.format(), caps);
719        assert_eq!(audio_profile.preset().unwrap(), PRESET);
720        assert_eq!(audio_profile.preset_name().unwrap(), PRESET_NAME);
721        assert_eq!(audio_profile.restriction().unwrap(), restriction);
722        assert_eq!(audio_profile.presence(), PRESENCE);
723        assert_eq!(audio_profile.allows_dynamic_output(), ALLOW_DYNAMIC_OUTPUT);
724        assert_eq!(audio_profile.is_enabled(), ENABLED);
725    }
726
727    #[test]
728    fn test_encoding_video_profile_builder() {
729        gst::init().unwrap();
730
731        let caps = gst::Caps::builder("video/x-raw").build();
732
733        let restriction = gst_video::VideoCapsBuilder::new()
734            .format(gst_video::VideoFormat::Rgba)
735            .build();
736
737        let video_profile = EncodingVideoProfile::builder(&caps)
738            .name(VIDEO_PROFILE_NAME)
739            .description(VIDEO_PROFILE_DESCRIPTION)
740            .preset(PRESET)
741            .preset_name(PRESET_NAME)
742            .restriction(&restriction)
743            .presence(PRESENCE)
744            .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT)
745            .enabled(ENABLED)
746            .pass(PASS)
747            .variable_framerate(VARIABLE_FRAMERATE)
748            .build();
749
750        assert_eq!(video_profile.name().unwrap(), VIDEO_PROFILE_NAME);
751        assert_eq!(
752            video_profile.description().unwrap(),
753            VIDEO_PROFILE_DESCRIPTION
754        );
755        assert_eq!(video_profile.format(), caps);
756        assert_eq!(video_profile.preset().unwrap(), PRESET);
757        assert_eq!(video_profile.preset_name().unwrap(), PRESET_NAME);
758        assert_eq!(video_profile.restriction().unwrap(), restriction);
759        assert_eq!(video_profile.presence(), PRESENCE);
760        assert_eq!(video_profile.allows_dynamic_output(), ALLOW_DYNAMIC_OUTPUT);
761        assert_eq!(video_profile.is_enabled(), ENABLED);
762
763        let video_profile: EncodingVideoProfile =
764            glib::object::Cast::downcast(video_profile).ok().unwrap();
765        assert_eq!(video_profile.is_variableframerate(), VARIABLE_FRAMERATE);
766        assert_eq!(video_profile.pass(), PASS);
767    }
768
769    #[test]
770    fn test_encoding_container_profile_builder() {
771        gst::init().unwrap();
772
773        let container_caps = gst::Caps::builder("container/x-caps").build();
774        let video_caps = gst::Caps::builder("video/x-raw").build();
775        let audio_caps = gst::Caps::builder("audio/x-raw").build();
776
777        let video_profile = EncodingVideoProfile::builder(&video_caps)
778            .name(VIDEO_PROFILE_NAME)
779            .description(VIDEO_PROFILE_DESCRIPTION)
780            .build();
781        let audio_profile = EncodingAudioProfile::builder(&audio_caps)
782            .name(AUDIO_PROFILE_NAME)
783            .description(AUDIO_PROFILE_DESCRIPTION)
784            .build();
785
786        let profile = EncodingContainerProfile::builder(&container_caps)
787            .name(CONTAINER_PROFILE_NAME)
788            .description(CONTAINER_PROFILE_DESCRIPTION)
789            .preset(PRESET)
790            .preset_name(PRESET_NAME)
791            .presence(PRESENCE)
792            .allow_dynamic_output(ALLOW_DYNAMIC_OUTPUT)
793            .enabled(ENABLED)
794            .add_profile(audio_profile.clone())
795            .add_profile(video_profile.clone())
796            .build();
797
798        assert_eq!(profile.name().unwrap(), CONTAINER_PROFILE_NAME);
799        assert_eq!(
800            profile.description().unwrap(),
801            CONTAINER_PROFILE_DESCRIPTION
802        );
803        assert_eq!(profile.format(), container_caps);
804        assert_eq!(profile.preset().unwrap(), PRESET);
805        assert_eq!(profile.preset_name().unwrap(), PRESET_NAME);
806        assert_eq!(profile.presence(), PRESENCE);
807        assert_eq!(profile.allows_dynamic_output(), ALLOW_DYNAMIC_OUTPUT);
808        assert_eq!(profile.is_enabled(), ENABLED);
809
810        let container_profile: EncodingContainerProfile =
811            glib::object::Cast::downcast(profile).ok().unwrap();
812
813        assert!(container_profile.contains_profile(&video_profile));
814        assert!(container_profile.contains_profile(&audio_profile));
815    }
816}