hlssink3: convert playlist type to an enum

Change the property `playlist-type` to an enum. We also expose the
new enum externally from the crate so users of Rust can directly use it.
This commit is contained in:
Rafael Caricio 2022-06-28 22:01:59 +02:00
parent 08c6ab29e1
commit adde6fc4e3
Signed by: rafaelcaricio
GPG key ID: 3C86DBCE8E93C947
4 changed files with 64 additions and 19 deletions

View file

@ -1,4 +1,3 @@
//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com> // Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
// //
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. // This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
@ -8,6 +7,7 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use crate::playlist::{Playlist, SegmentFormatter}; use crate::playlist::{Playlist, SegmentFormatter};
use crate::HlsSink3PlaylistType;
use gio::prelude::*; use gio::prelude::*;
use glib::subclass::prelude::*; use glib::subclass::prelude::*;
use gst::prelude::*; use gst::prelude::*;
@ -24,6 +24,7 @@ const DEFAULT_PLAYLIST_LOCATION: &str = "playlist.m3u8";
const DEFAULT_MAX_NUM_SEGMENT_FILES: u32 = 10; const DEFAULT_MAX_NUM_SEGMENT_FILES: u32 = 10;
const DEFAULT_TARGET_DURATION: u32 = 15; const DEFAULT_TARGET_DURATION: u32 = 15;
const DEFAULT_PLAYLIST_LENGTH: u32 = 5; const DEFAULT_PLAYLIST_LENGTH: u32 = 5;
const DEFAULT_PLAYLIST_TYPE: HlsSink3PlaylistType = HlsSink3PlaylistType::Unspecified;
const DEFAULT_SEND_KEYFRAME_REQUESTS: bool = true; const DEFAULT_SEND_KEYFRAME_REQUESTS: bool = true;
const SIGNAL_GET_PLAYLIST_STREAM: &str = "get-playlist-stream"; const SIGNAL_GET_PLAYLIST_STREAM: &str = "get-playlist-stream";
@ -34,6 +35,28 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new("hlssink3", gst::DebugColorFlags::empty(), Some("HLS sink")) gst::DebugCategory::new("hlssink3", gst::DebugColorFlags::empty(), Some("HLS sink"))
}); });
impl From<HlsSink3PlaylistType> for Option<MediaPlaylistType> {
fn from(pl_type: HlsSink3PlaylistType) -> Self {
use HlsSink3PlaylistType::*;
match pl_type {
Unspecified => None,
Event => Some(MediaPlaylistType::Event),
Vod => Some(MediaPlaylistType::Vod),
}
}
}
impl From<Option<MediaPlaylistType>> for HlsSink3PlaylistType {
fn from(inner_pl_type: Option<MediaPlaylistType>) -> Self {
use HlsSink3PlaylistType::*;
match inner_pl_type {
None => Unspecified,
Some(MediaPlaylistType::Event) => Event,
Some(MediaPlaylistType::Vod) => Vod,
}
}
}
struct Settings { struct Settings {
location: String, location: String,
segment_formatter: SegmentFormatter, segment_formatter: SegmentFormatter,
@ -449,11 +472,12 @@ impl ObjectImpl for HlsSink3 {
DEFAULT_PLAYLIST_LENGTH, DEFAULT_PLAYLIST_LENGTH,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
), ),
glib::ParamSpecString::new( glib::ParamSpecEnum::new(
"playlist-type", "playlist-type",
"Playlist Type", "Playlist Type",
"The type of the playlist to use. When VOD type is set, the playlist will be live until the pipeline ends execution.", "The type of the playlist to use. When VOD type is set, the playlist will be live until the pipeline ends execution.",
None, HlsSink3PlaylistType::static_type(),
DEFAULT_PLAYLIST_TYPE as i32,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
), ),
glib::ParamSpecBoolean::new( glib::ParamSpecBoolean::new(
@ -517,15 +541,9 @@ impl ObjectImpl for HlsSink3 {
} }
"playlist-type" => { "playlist-type" => {
settings.playlist_type = value settings.playlist_type = value
.get::<Option<String>>() .get::<HlsSink3PlaylistType>()
.expect("type checked upstream") .expect("type checked upstream")
.map(|chosen_type| { .into();
if chosen_type.to_lowercase() == "vod" {
MediaPlaylistType::Vod
} else {
MediaPlaylistType::Event
}
})
} }
"send-keyframe-requests" => { "send-keyframe-requests" => {
settings.send_keyframe_requests = value.get().expect("type checked upstream"); settings.send_keyframe_requests = value.get().expect("type checked upstream");
@ -549,11 +567,10 @@ impl ObjectImpl for HlsSink3 {
} }
"target-duration" => settings.target_duration.to_value(), "target-duration" => settings.target_duration.to_value(),
"playlist-length" => settings.playlist_length.to_value(), "playlist-length" => settings.playlist_length.to_value(),
"playlist-type" => settings "playlist-type" => {
.playlist_type let playlist_type: HlsSink3PlaylistType = settings.playlist_type.into();
.as_ref() playlist_type.to_value()
.map(|ty| ty.to_string()) }
.to_value(),
"send-keyframe-requests" => settings.send_keyframe_requests.to_value(), "send-keyframe-requests" => settings.send_keyframe_requests.to_value(),
_ => unimplemented!(), _ => unimplemented!(),
} }

View file

@ -1,4 +1,3 @@
//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com> // Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
// //
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. // This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
@ -13,6 +12,30 @@ use glib::prelude::*;
mod imp; mod imp;
mod playlist; mod playlist;
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, glib::Enum)]
#[repr(u32)]
#[enum_type(name = "GstHlsSink3PlaylistType")]
#[non_exhaustive]
pub enum HlsSink3PlaylistType {
#[enum_value(
name = "Unspecified: The tag `#EXT-X-PLAYLIST-TYPE` won't be present in the playlist during the pipeline processing.",
nick = "Unspecified"
)]
Unspecified = 0,
#[enum_value(
name = "Event: No segments will be removed from the playlist. At the end of the processing, the tag `#EXT-X-ENDLIST` is added to the playlist. The tag `#EXT-X-PLAYLIST-TYPE:EVENT` will be present in the playlist.",
nick = "event"
)]
Event = 1,
#[enum_value(
name = "Vod: The playlist behaves like the `event` option (a live event), but at the end of the processing, the playlist will be set to `#EXT-X-PLAYLIST-TYPE:VOD`.",
nick = "vod"
)]
Vod = 2,
}
glib::wrapper! { glib::wrapper! {
pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends gst::Bin, gst::Element, gst::Object; pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends gst::Bin, gst::Element, gst::Object;
} }

View file

@ -1,4 +1,3 @@
//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com> // Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
// //
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. // This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.

View file

@ -1,4 +1,3 @@
//
// Copyright (C) 2021 Rafael Caricio <rafael@caricio.com> // Copyright (C) 2021 Rafael Caricio <rafael@caricio.com>
// //
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0. // This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
@ -9,6 +8,7 @@
use gio::prelude::*; use gio::prelude::*;
use gst::prelude::*; use gst::prelude::*;
use gsthlssink3::HlsSink3PlaylistType;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::io::Write; use std::io::Write;
use std::sync::{mpsc, Arc, Mutex}; use std::sync::{mpsc, Arc, Mutex};
@ -120,6 +120,12 @@ fn test_hlssink3_element_with_video_content() -> Result<(), ()> {
hlssink3.set_property("playlist-length", 2u32); hlssink3.set_property("playlist-length", 2u32);
hlssink3.set_property("max-files", 2u32); hlssink3.set_property("max-files", 2u32);
hlssink3.set_property("playlist-type", HlsSink3PlaylistType::Event);
let pl_type: HlsSink3PlaylistType = hlssink3.property("playlist-type");
assert_eq!(pl_type, HlsSink3PlaylistType::Event);
hlssink3.set_property_from_str("playlist-type", "Unspecified");
let (hls_events_sender, hls_events_receiver) = mpsc::sync_channel(20); let (hls_events_sender, hls_events_receiver) = mpsc::sync_channel(20);
let playlist_content = Arc::new(Mutex::new(String::from(""))); let playlist_content = Arc::new(Mutex::new(String::from("")));