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