hlssink3: Add baseclass implementation

Adding HlsBaseSink class to make code reusable

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1306>
This commit is contained in:
Seungha Yang 2023-08-31 23:58:45 +09:00
parent 0fe69cea9f
commit 5b563006f9
3 changed files with 615 additions and 538 deletions

File diff suppressed because it is too large Load diff

View file

@ -43,12 +43,19 @@ pub enum HlsSink3PlaylistType {
} }
glib::wrapper! { glib::wrapper! {
pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends gst::Bin, gst::Element, gst::Object; pub struct HlsBaseSink(ObjectSubclass<imp::HlsBaseSink>) @extends gst::Bin, gst::Element, gst::Object;
}
glib::wrapper! {
pub struct HlsSink3(ObjectSubclass<imp::HlsSink3>) @extends HlsBaseSink, gst::Bin, gst::Element, gst::Object;
} }
pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { pub fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
#[cfg(feature = "doc")] #[cfg(feature = "doc")]
HlsSink3PlaylistType::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty()); {
HlsSink3PlaylistType::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
HlsBaseSink::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
}
gst::Element::register( gst::Element::register(
Some(plugin), Some(plugin),

View file

@ -6,13 +6,9 @@
// //
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use chrono::{DateTime, Utc};
use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment}; use m3u8_rs::{MediaPlaylist, MediaPlaylistType, MediaSegment};
use std::io::Write; use std::io::Write;
const GST_M3U8_PLAYLIST_V3: usize = 3;
const GST_M3U8_PLAYLIST_V4: usize = 4;
/// An HLS playlist. /// An HLS playlist.
/// ///
/// Controls the changes that needs to happen in the playlist as new segments are added. This /// Controls the changes that needs to happen in the playlist as new segments are added. This
@ -27,37 +23,9 @@ pub struct Playlist {
} }
impl Playlist { impl Playlist {
pub fn new( pub fn new(playlist: MediaPlaylist, turn_vod: bool) -> Self {
target_duration: f32,
playlist_type: Option<MediaPlaylistType>,
i_frames_only: bool,
) -> Self {
let mut turn_vod = false;
let playlist_type = if playlist_type == Some(MediaPlaylistType::Vod) {
turn_vod = true;
Some(MediaPlaylistType::Event)
} else {
playlist_type
};
let m3u8_version = if i_frames_only {
GST_M3U8_PLAYLIST_V4
} else {
GST_M3U8_PLAYLIST_V3
};
Self { Self {
inner: MediaPlaylist { inner: playlist,
version: Some(m3u8_version),
target_duration,
media_sequence: 0,
segments: vec![],
discontinuity_sequence: 0,
end_list: false,
playlist_type,
i_frames_only,
start: None,
independent_segments: false,
unknown_tags: vec![],
},
playlist_index: 0, playlist_index: 0,
status: PlaylistRenderState::Init, status: PlaylistRenderState::Init,
turn_vod, turn_vod,
@ -65,23 +33,9 @@ impl Playlist {
} }
/// Adds a new segment to the playlist. /// Adds a new segment to the playlist.
pub fn add_segment(&mut self, uri: String, duration: f32, date_time: Option<DateTime<Utc>>) { pub fn add_segment(&mut self, segment: MediaSegment) {
self.start(); self.start();
// We are adding date-time to each segment.Putting date-time-tag only for the first segment in the playlist self.inner.segments.push(segment);
// is also valid. But it is better to put program-date-time tag for every segment to take care of any drift.
// FFMPEG also put PDT tag for each segment.
self.inner.segments.push(MediaSegment {
uri,
duration,
title: None,
byte_range: None,
discontinuity: false,
key: None,
map: None,
program_date_time: date_time.map(|d| d.into()),
daterange: None,
unknown_tags: vec![],
});
} }
/// Updates the playlist based on current state. /// Updates the playlist based on current state.