Skip to main content

hls_playlist/
playlist.rs

1//! High level representations of extended M3U playlists.
2
3// Copyright 2024 Logan Wemyss
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17mod serialize;
18
19/// A playlist representing a list of renditions and variants of a given piece of media.
20#[derive(Debug, Clone, PartialEq, Default)]
21pub struct MultivariantPlaylist {
22    /// True if all media samples in a Media Segment can be decoded without information
23    /// from other segments.
24    pub is_independent_segments: bool,
25
26    /// A preferred point at which to start playing a Playlist.
27    pub start_offset: Option<StartOffset>,
28
29    /// A list of name value pairs where the name can be substituted for the
30    /// value (e.g. `{$<name>}`) in URI lines, quoted string attribute list
31    /// values, and hexadecimal-sequence attribute values.
32    pub variables: Vec<crate::DefinitionType>,
33
34    /// Groups of renditions that are all alternative renditions of the same content.
35    pub renditions_groups: Vec<RenditionGroup>,
36
37    /// A set of [`VariantStream`]s.
38    pub variant_streams: Vec<VariantStream>,
39
40    /// The `MediaPlaylist` files containing the I-frames of a multimedia
41    /// presentation.
42    pub i_frame_streams: Vec<IFrameStream>,
43
44    /// Arbitrary session data.
45    pub session_data: Vec<crate::SessionData>,
46
47    /// Encryption keys used in the `MediaPlaylist`s that should be preloaded.
48    pub session_key: Vec<crate::EncryptionMethod>,
49
50    /// Identifies a [`crate::steering_manifest::SteeringManifest`].
51    pub content_steering: Vec<crate::ContentSteering>,
52}
53
54/// Groups of renditions that are all alternative renditions of the same content.
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub enum RenditionGroup {
57    /// A group of video renditions.
58    Video {
59        /// The group id for this group.
60        group_id: String,
61
62        /// All the renditions a part of this group.
63        renditions: Vec<VideoRendition>,
64    },
65
66    /// A group of audio renditions.
67    Audio {
68        /// The group id for this group.
69        group_id: String,
70
71        /// All the renditions a part of this group.
72        renditions: Vec<AudioRendition>,
73    },
74
75    /// A group of subtitle renditions.
76    Subtitles {
77        /// The group id for this group.
78        group_id: String,
79
80        /// All the renditions a part of this group.
81        renditions: Vec<SubtitleRendition>,
82    },
83
84    /// A group of closed caption renditions.
85    ClosedCaptions {
86        /// The group id for this group.
87        group_id: String,
88
89        /// All the renditions a part of this group.
90        renditions: Vec<ClosedCaptionRendition>,
91    },
92}
93
94/// A video rendition.
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct VideoRendition {
97    /// Information about this rendition.
98    pub info: RenditionInfo,
99
100    /// The URI that identifies the Media Playlist file.
101    pub uri: Option<String>,
102}
103
104/// A audio rendition.
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct AudioRendition {
107    /// The audio bit depth of the rendition.
108    pub bit_depth: Option<u64>,
109
110    /// The audio sample rate of the rendition.
111    pub sample_rate: Option<u64>,
112
113    /// Information about the audio channels in the rendition.
114    pub channels: Option<crate::AudioChannelInformation>,
115
116    /// Information about this rendition.
117    pub info: RenditionInfo,
118
119    /// The URI that identifies the Media Playlist file.
120    pub uri: Option<String>,
121}
122
123/// A subtitle rendition.
124#[derive(Debug, Clone, PartialEq, Eq)]
125pub struct SubtitleRendition {
126    /// Information about this rendition.
127    pub info: RenditionInfo,
128
129    /// Indicates that the Rendition contains content that is
130    /// considered essential to play.
131    pub forced: bool,
132
133    /// The URI that identifies the Media Playlist file.
134    pub uri: String,
135}
136
137/// A closed caption rendition.
138#[derive(Debug, Clone, PartialEq, Eq)]
139pub struct ClosedCaptionRendition {
140    pub in_stream_id: crate::InStreamId,
141
142    /// Information about this rendition.
143    pub info: RenditionInfo,
144}
145
146/// Information about a given rendition.
147#[derive(Debug, Clone, PartialEq, Eq)]
148pub struct RenditionInfo {
149    /// A RFC5646 tag which identifies the primary language used in the Rendition.
150    pub language: Option<String>,
151
152    /// A RFC5646 tag which identifies a language that is associated with the Rendition.
153    pub assoc_language: Option<String>,
154
155    /// A human-readable description of the Rendition.
156    pub name: String,
157
158    /// The priority in which a given rendition should be chosen over another rendition.
159    pub priority: crate::RenditionPlaybackPriority,
160
161    /// Media Characteristic Tags that indicate individual characteristics of this Rendition.
162    pub characteristics: Vec<String>,
163
164    /// Allows the URI of a Rendition to change between two distinct downloads of
165    /// the `MultivariantPlaylist`.
166    pub stable_rendition_id: Option<String>,
167}
168
169/// A set of Renditions that can be combined to play the presentation.
170#[derive(Debug, Clone, PartialEq)]
171pub struct VariantStream {
172    /// Metadata for the stream.
173    pub stream_info: crate::StreamInf,
174
175    /// Describes the maximum frame rate for all the video in the
176    /// `VariantStream`.
177    pub frame_rate: Option<f64>,
178
179    /// The group id of the audio [`RenditionGroup`] that should be used when
180    /// playing the presentation.
181    pub audio_group_id: Option<String>,
182
183    /// The group id of the video [`RenditionGroup`] that should be used when
184    /// playing the presentation.
185    pub video_group_id: Option<String>,
186
187    /// The group id of the subtitle [`RenditionGroup`] that should be used when
188    /// playing the presentation.
189    pub subtitles_group_id: Option<String>,
190
191    /// The group id of the closed caption [`RenditionGroup`] that should be used when
192    /// playing the presentation.
193    pub closed_captions_group_id: Option<String>,
194
195    /// The `MediaPlaylist` that carries a Rendition of the Variant Stream.
196    pub uri: String,
197}
198
199/// Identifies a `MediaPlaylist` containing the I-frames of a multimedia
200/// presentation.
201#[derive(Debug, Clone, PartialEq)]
202pub struct IFrameStream {
203    /// The metadata for this stream.
204    pub stream_info: crate::StreamInf,
205
206    /// The group id of the video [`RenditionGroup`] that should be used when
207    /// playing the presentation.
208    pub video_group_id: Option<String>,
209
210    /// The URI that identifies the I-frame `MediaPlaylist` file.
211    pub uri: String,
212}
213
214/// A playlist representing a list of `MediaSegment`s and relevant information.
215#[allow(clippy::struct_excessive_bools)]
216#[derive(Debug, Clone, PartialEq, Default)]
217pub struct MediaPlaylist {
218    /// The `MediaSegments` representing segments of the media stream in order.
219    pub segments: Vec<MediaSegment>,
220
221    /// A preferred point at which to start playing a Playlist.
222    pub start_offset: Option<StartOffset>,
223
224    /// A list of name value pairs where the name can be substituted for the
225    /// value (e.g. `{$<name>}`) in URI lines, quoted string attribute list
226    /// values, and hexadecimal-sequence attribute values.
227    pub variables: Vec<crate::DefinitionType>,
228
229    /// True if all media samples in a Media Segment can be decoded without information
230    /// from other segments.
231    pub is_independent_segments: bool,
232
233    /// An upper bound on the duration of all Media
234    /// Segments in the Playlist. The duration of each Media Segment
235    /// in a Playlist file, when rounded to the nearest integer, MUST be
236    /// less than or equal to the Target Duration.
237    pub target_duration: u64,
238
239    /// The media sequence number of the first segment in [`MediaPlaylist::segments`].
240    pub first_media_sequence_number: u64,
241
242    /// Allows synchronization between different renditions of the same `VariantStream`
243    /// or different `VariantStream`s that have EXT-X-DISCONTINUITY tags in their
244    /// Media Playlists.
245    pub discontinuity_sequence_number: u64,
246
247    /// True if no more Media Segments will be added to the Media Playlist file.
248    pub finished: bool,
249
250    /// Whether or not the playlist is for a mutable append-only stream, or a
251    /// static immutable stream.
252    pub playlist_type: Option<crate::PlaylistType>,
253
254    /// If Some, indicates the server-recommended minimum distance from
255    /// the end of the Playlist at which clients should begin to play
256    /// or to which they should seek.
257    /// If None, this is set to `target_duration * 3`.
258    pub hold_back_seconds: Option<f64>,
259
260    /// True if each Media Segment in the Playlist describes a single I-frame.
261    pub iframes_only: bool,
262
263    /// `Some` if the server supports playlist delta updates.,
264    pub playlist_delta_updates_information: Option<crate::DeltaUpdateInfo>,
265
266    /// True if the server supports blocking playlist reloads.
267    pub supports_blocking_playlist_reloads: bool,
268
269    /// Information about the `PartialSegments` in this playlist.
270    pub part_information: Option<PartInformation>,
271
272    /// Information about the playlist that is not associated with
273    /// specific Media Segments.
274    pub metadata: MediaMetadata,
275}
276
277/// Information about `PartialSegments` in a given playlist.
278#[derive(Debug, Clone, PartialEq)]
279pub struct PartInformation {
280    /// Indicates the server-recommended minimum distance from
281    /// the end of the Playlist at which clients should begin to play
282    /// or to which they should seek when playing in Low-Latency Mode.
283    pub part_hold_back_seconds: f64,
284
285    /// An upper bound on the duration of all Partial Segments in the Playlist.
286    /// The duration of each Media Segment in a Playlist file, when rounded
287    /// to the nearest integer, MUST be less than or equal to the Target Duration.
288    pub part_target_duration: f64,
289}
290
291/// Information about the playlist that is not associated with
292/// specific Media Segments.
293#[derive(Debug, Clone, PartialEq, Default)]
294pub struct MediaMetadata {
295    /// A duration of time with specific attributes.
296    pub date_ranges: Vec<crate::DateRange>,
297
298    /// If Some, this indicates information about skipped `MediaSegments`.
299    /// If None, there are no skipped `MediaSegments`.
300    pub skip: Option<SkipInformation>,
301
302    /// Hints that the client should request a resource before
303    /// it is available to be delivered.
304    pub preload_hints: Vec<crate::PreloadHint>,
305
306    /// Information about an associated Renditions that is as up-to-date as
307    /// the Playlist that contains the report.
308    pub rendition_reports: Vec<crate::RenditionReport>,
309}
310
311/// Information about skipped `MediaSegments`.
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct SkipInformation {
314    /// The number of `MediaSegments` that have been skipped.
315    pub number_of_skipped_segments: u64,
316
317    /// The list of [`crate::DateRange`] IDs that have been removed
318    /// from the Playlist recently.
319    pub recently_removed_dataranges: Vec<String>,
320}
321
322/// A segment of the larger media file.
323#[derive(Debug, Clone, PartialEq)]
324pub struct MediaSegment {
325    /// The URI Identifying the media resource.
326    pub uri: String,
327
328    /// The duration of this `MediaSegment`.
329    pub duration_seconds: crate::FloatOrInteger,
330
331    /// An optional human-readable informative title of the Media Segment.
332    /// Empty string for no title.
333    pub title: String,
334
335    /// This may contain either a byte range or bitrate, but not both, because they are
336    /// mutually exclusive
337    pub byte_range_or_bitrate: Option<ByteRangeOrBitrate>,
338
339    /// True if `MediaSegment` is a discontinuity between the Media Segment
340    /// that follows it and the one that preceded it.
341    pub is_discontinuity: bool,
342
343    /// If Some, represents the encryption method used for this `MediaSegment`.
344    /// If None, no encryption is used.
345    pub encryption: Option<crate::EncryptionMethod>,
346
347    /// If Some, this `MediaSegment` requires a Media Initialization Section
348    /// and the value describes how to acquire it.
349    pub media_initialization_section: Option<MediaInitializationSection>,
350
351    /// If Some, the first sample of the `MediaSegment` is associated with this
352    /// time.
353    pub absolute_time: Option<chrono::DateTime<chrono::FixedOffset>>,
354
355    /// If true, this `MediaSegment` does not contain media data
356    /// and should not be loaded by clients.
357    pub is_gap: bool,
358
359    /// The partial segments for this `MediaSegment`.
360    pub parts: Vec<PartialSegment>,
361}
362
363/// A common sequence of bytes to initialize the parser before
364/// `MediaSegments` can be parsed.
365#[derive(Debug, Clone, PartialEq, Eq)]
366pub struct MediaInitializationSection {
367    pub uri: String,
368    pub range: Option<crate::ByteRangeWithOffset>,
369}
370
371#[derive(Debug, Clone, PartialEq, Eq)]
372pub enum ByteRangeOrBitrate {
373    /// This `MediaSegment` is a sub-range of the resource
374    /// identified by its URI.
375    ByteRange(crate::ByteRange),
376
377    /// The approximate segment bit rate of this `MediaSegment`
378    /// in kbps.
379    Bitrate(u64),
380}
381
382/// A partial slice of a `MediaSegment.`
383#[derive(Debug, Clone, PartialEq)]
384pub struct PartialSegment {
385    /// The URI for this `PartialSegment`.
386    pub uri: String,
387
388    /// The duration of this `PartialSegment`.
389    pub duration_in_seconds: f64,
390
391    /// True if this `PartialSegment` contains an independent frame.
392    pub is_independent: bool,
393
394    /// Some if this `PartialSegment` is a sub-range of the resource specified by the URI.
395    pub byte_range: Option<crate::ByteRange>,
396
397    /// True if this `PartialSegment` is not available.
398    pub is_gap: bool,
399}
400
401/// A preferred point at which to start playing a Playlist.
402#[derive(Debug, Clone, PartialEq)]
403pub struct StartOffset {
404    /// A positive offset indicates a time offset from the beginning of the Playlist.
405    /// A negative offset indicates a negative time offset from the end of the last Media
406    /// Segment in the Playlist.
407    pub offset_in_seconds: f64,
408
409    /// If `true`, clients should start playback at the Media
410    /// Segment containing the [`StartOffset::offset_in_seconds`], but should not render
411    /// media samples in that segment whose presentation times are prior to the
412    /// [`StartOffset::offset_in_seconds`].  If `false`, clients should attempt to render
413    /// every media sample in that segment.
414    pub is_precise: bool,
415}