1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-05-18 16:28:20 +00:00

remove _tag suffix from MediaSegment fields

This commit is contained in:
Luro02 2020-02-16 12:50:52 +01:00
parent 8cced1ac53
commit b2c997d04d
No known key found for this signature in database
GPG key ID: B66FD4F74501A9CF
5 changed files with 92 additions and 93 deletions

View file

@ -124,7 +124,7 @@ impl MediaPlaylistBuilder {
if let Some(segments) = &self.segments {
for s in segments {
// CHECK: `#EXT-X-TARGETDURATION`
let segment_duration = s.inf_tag().duration();
let segment_duration = s.inf().duration();
let rounded_segment_duration = {
if segment_duration.subsec_nanos() < 500_000_000 {
Duration::from_secs(segment_duration.as_secs())
@ -152,7 +152,7 @@ impl MediaPlaylistBuilder {
}
// CHECK: `#EXT-X-BYTE-RANGE`
if let Some(tag) = s.byte_range_tag() {
if let Some(tag) = s.byte_range() {
if tag.to_range().start().is_none() {
let last_uri = last_range_uri.ok_or_else(Error::invalid_input)?;
if last_uri != s.uri() {
@ -286,7 +286,7 @@ fn parse_media_playlist(
let mut has_discontinuity_tag = false;
let mut unknown_tags = vec![];
let mut available_key_tags: Vec<crate::tags::ExtXKey> = vec![];
let mut available_keys: Vec<crate::tags::ExtXKey> = vec![];
for line in Lines::from(input) {
match line? {
@ -294,25 +294,25 @@ fn parse_media_playlist(
match tag {
Tag::ExtInf(t) => {
has_partial_segment = true;
segment.inf_tag(t);
segment.inf(t);
}
Tag::ExtXByteRange(t) => {
has_partial_segment = true;
segment.byte_range_tag(t);
segment.byte_range(t);
}
Tag::ExtXDiscontinuity(t) => {
has_discontinuity_tag = true;
has_partial_segment = true;
segment.discontinuity_tag(t);
segment.discontinuity(t);
}
Tag::ExtXKey(t) => {
has_partial_segment = true;
if available_key_tags.is_empty() {
if available_keys.is_empty() {
// An ExtXKey applies to every MediaSegment and to every Media
// Initialization Section declared by an EXT-X-MAP tag, that appears
// between it and the next EXT-X-KEY tag in the Playlist file with the
// same KEYFORMAT attribute (or the end of the Playlist file).
available_key_tags = available_key_tags
available_keys = available_keys
.into_iter()
.map(|k| {
if t.key_format() == k.key_format() {
@ -323,22 +323,22 @@ fn parse_media_playlist(
})
.collect();
} else {
available_key_tags.push(t);
available_keys.push(t);
}
}
Tag::ExtXMap(mut t) => {
has_partial_segment = true;
t.set_keys(available_key_tags.clone());
segment.map_tag(t);
t.set_keys(available_keys.clone());
segment.map(t);
}
Tag::ExtXProgramDateTime(t) => {
has_partial_segment = true;
segment.program_date_time_tag(t);
segment.program_date_time(t);
}
Tag::ExtXDateRange(t) => {
has_partial_segment = true;
segment.date_range_tag(t);
segment.date_range(t);
}
Tag::ExtXTargetDuration(t) => {
builder.target_duration(t);
@ -350,9 +350,11 @@ fn parse_media_playlist(
if segments.is_empty() {
return Err(Error::invalid_input());
}
if has_discontinuity_tag {
return Err(Error::invalid_input());
}
builder.discontinuity_sequence(t);
}
Tag::ExtXEndList(t) => {
@ -386,7 +388,7 @@ fn parse_media_playlist(
}
Line::Uri(uri) => {
segment.uri(uri);
segment.keys(available_key_tags.clone());
segment.keys(available_keys.clone());
segments.push(segment.build().map_err(Error::builder)?);
segment = MediaSegment::builder();
has_partial_segment = false;

View file

@ -19,22 +19,22 @@ pub struct MediaSegment {
keys: Vec<ExtXKey>,
/// The [`ExtXMap`] tag associated with the media segment.
#[builder(default)]
map_tag: Option<ExtXMap>,
map: Option<ExtXMap>,
/// The [`ExtXByteRange`] tag associated with the [`MediaSegment`].
#[builder(default)]
byte_range_tag: Option<ExtXByteRange>,
byte_range: Option<ExtXByteRange>,
/// The [`ExtXDateRange`] tag associated with the media segment.
#[builder(default)]
date_range_tag: Option<ExtXDateRange>,
date_range: Option<ExtXDateRange>,
/// The [`ExtXDiscontinuity`] tag associated with the media segment.
#[builder(default)]
discontinuity_tag: Option<ExtXDiscontinuity>,
discontinuity: Option<ExtXDiscontinuity>,
/// The [`ExtXProgramDateTime`] tag associated with the media
/// segment.
#[builder(default)]
program_date_time_tag: Option<ExtXProgramDateTime>,
program_date_time: Option<ExtXProgramDateTime>,
/// The [`ExtInf`] tag associated with the [`MediaSegment`].
inf_tag: ExtInf,
inf: ExtInf,
/// The `URI` of the [`MediaSegment`].
#[shorthand(enable(into))]
uri: String,
@ -47,12 +47,13 @@ impl MediaSegment {
impl MediaSegmentBuilder {
/// Pushes an [`ExtXKey`] tag.
pub fn push_key_tag<VALUE: Into<ExtXKey>>(&mut self, value: VALUE) -> &mut Self {
if let Some(key_tags) = &mut self.keys {
key_tags.push(value.into());
pub fn push_key<VALUE: Into<ExtXKey>>(&mut self, value: VALUE) -> &mut Self {
if let Some(keys) = &mut self.keys {
keys.push(value.into());
} else {
self.keys = Some(vec![value.into()]);
}
self
}
}
@ -63,27 +64,27 @@ impl fmt::Display for MediaSegment {
writeln!(f, "{}", value)?;
}
if let Some(value) = &self.map_tag {
if let Some(value) = &self.map {
writeln!(f, "{}", value)?;
}
if let Some(value) = &self.byte_range_tag {
if let Some(value) = &self.byte_range {
writeln!(f, "{}", value)?;
}
if let Some(value) = &self.date_range_tag {
if let Some(value) = &self.date_range {
writeln!(f, "{}", value)?;
}
if let Some(value) = &self.discontinuity_tag {
if let Some(value) = &self.discontinuity {
writeln!(f, "{}", value)?;
}
if let Some(value) = &self.program_date_time_tag {
if let Some(value) = &self.program_date_time {
writeln!(f, "{}", value)?;
}
writeln!(f, "{}", self.inf_tag)?; // TODO: there might be a `,` missing
writeln!(f, "{}", self.inf)?; // TODO: there might be a `,` missing
writeln!(f, "{}", self.uri)?;
Ok(())
}
@ -93,12 +94,12 @@ impl RequiredVersion for MediaSegment {
fn required_version(&self) -> ProtocolVersion {
required_version![
self.keys,
self.map_tag,
self.byte_range_tag,
self.date_range_tag,
self.discontinuity_tag,
self.program_date_time_tag,
self.inf_tag
self.map,
self.byte_range,
self.date_range,
self.discontinuity,
self.program_date_time,
self.inf
]
}
}
@ -120,11 +121,11 @@ mod tests {
assert_eq!(
MediaSegment::builder()
.keys(vec![ExtXKey::empty()])
.map_tag(ExtXMap::new("https://www.example.com/"))
.byte_range_tag(ExtXByteRange::new(20, Some(5)))
//.date_range_tag() // TODO!
.discontinuity_tag(ExtXDiscontinuity)
.inf_tag(ExtInf::new(Duration::from_secs(4)))
.map(ExtXMap::new("https://www.example.com/"))
.byte_range(ExtXByteRange::new(20, Some(5)))
//.date_range() // TODO!
.discontinuity(ExtXDiscontinuity)
.inf(ExtInf::new(Duration::from_secs(4)))
.uri("http://www.uri.com/")
.build()
.unwrap()

View file

@ -75,6 +75,10 @@ impl FromStr for ExtXTargetDuration {
}
}
impl From<Duration> for ExtXTargetDuration {
fn from(value: Duration) -> Self { Self::new(value) }
}
#[cfg(test)]
mod test {
use super::*;

View file

@ -6,50 +6,48 @@ use pretty_assertions::assert_eq;
#[test]
fn test_media_playlist_with_byterange() {
let media_playlist = concat!(
"#EXTM3U\n",
"#EXT-X-TARGETDURATION:10\n",
"#EXT-X-VERSION:4\n",
"#EXT-X-MEDIA-SEQUENCE:0\n",
"#EXTINF:10.0,\n",
"#EXT-X-BYTERANGE:75232@0\n",
"video.ts\n",
"#EXT-X-BYTERANGE:82112@752321\n",
"#EXTINF:10.0,\n",
"video.ts\n",
"#EXTINF:10.0,\n",
"#EXT-X-BYTERANGE:69864\n",
"video.ts\n"
)
.parse::<MediaPlaylist>()
.unwrap();
assert_eq!(
MediaPlaylist::builder()
.target_duration(ExtXTargetDuration::new(Duration::from_secs(10)))
.media_sequence(ExtXMediaSequence::new(0))
.segments(vec![
MediaSegment::builder()
.inf_tag(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range_tag(ExtXByteRange::new(75232, Some(0)))
.inf(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range(ExtXByteRange::new(75232, Some(0)))
.uri("video.ts")
.build()
.unwrap(),
MediaSegment::builder()
.inf_tag(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range_tag(ExtXByteRange::new(82112, Some(752321)))
.inf(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range(ExtXByteRange::new(82112, Some(752321)))
.uri("video.ts")
.build()
.unwrap(),
MediaSegment::builder()
.inf_tag(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range_tag(ExtXByteRange::new(69864, None))
.inf(ExtInf::new(Duration::from_secs_f64(10.0)))
.byte_range(ExtXByteRange::new(69864, None))
.uri("video.ts")
.build()
.unwrap(),
])
.build()
.unwrap(),
media_playlist
concat!(
"#EXTM3U\n",
"#EXT-X-TARGETDURATION:10\n",
"#EXT-X-VERSION:4\n",
"#EXT-X-MEDIA-SEQUENCE:0\n",
"#EXTINF:10.0,\n",
"#EXT-X-BYTERANGE:75232@0\n",
"video.ts\n",
"#EXT-X-BYTERANGE:82112@752321\n",
"#EXTINF:10.0,\n",
"video.ts\n",
"#EXTINF:10.0,\n",
"#EXT-X-BYTERANGE:69864\n",
"video.ts\n"
)
.parse::<MediaPlaylist>()
.unwrap()
)
}

View file

@ -1,10 +1,11 @@
//! Credits go to
//! - https://github.com/globocom/m3u8/blob/master/tests/playlists.py
use hls_m3u8::tags::*;
use hls_m3u8::MediaPlaylist;
use std::time::Duration;
use hls_m3u8::tags::{ExtInf, ExtXEndList};
use hls_m3u8::{MediaPlaylist, MediaSegment};
use pretty_assertions::assert_eq;
#[test]
fn test_simple_playlist() {
let playlist = concat!(
@ -17,31 +18,24 @@ fn test_simple_playlist() {
"#EXT-X-ENDLIST\n"
);
let media_playlist = playlist.parse::<MediaPlaylist>().unwrap();
assert_eq!(
media_playlist.target_duration(),
ExtXTargetDuration::new(Duration::from_secs(5220))
);
assert_eq!(media_playlist.segments().len(), 2);
assert_eq!(
media_playlist.segments()[0].inf_tag(),
&ExtInf::new(Duration::from_secs(0))
);
assert_eq!(
media_playlist.segments()[1].inf_tag(),
&ExtInf::new(Duration::from_secs(5220))
);
assert_eq!(
media_playlist.segments()[0].uri(),
&"http://media.example.com/entire1.ts".to_string()
);
assert_eq!(
media_playlist.segments()[1].uri(),
&"http://media.example.com/entire2.ts".to_string()
MediaPlaylist::builder()
.target_duration(Duration::from_secs(5220))
.segments(vec![
MediaSegment::builder()
.inf(ExtInf::new(Duration::from_secs(0)))
.uri("http://media.example.com/entire1.ts")
.build()
.unwrap(),
MediaSegment::builder()
.inf(ExtInf::new(Duration::from_secs(5220)))
.uri("http://media.example.com/entire2.ts")
.build()
.unwrap(),
])
.end_list(ExtXEndList)
.build()
.unwrap(),
playlist.parse::<MediaPlaylist>().unwrap(),
);
}