Allow unknown tags at the master playlist level

This commit is contained in:
Rafael Caricio
2021-10-14 21:21:03 +02:00
parent c1ff2b3730
commit dc352301a3
3 changed files with 53 additions and 5 deletions

View File

@ -276,6 +276,7 @@ pub enum MasterPlaylistTag {
IndependentSegments, IndependentSegments,
Comment(String), Comment(String),
Uri(String), Uri(String),
Unknown(ExtTag),
} }
pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> { pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
@ -291,6 +292,8 @@ pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
| map!(start_tag, MasterPlaylistTag::Start) | map!(start_tag, MasterPlaylistTag::Start)
| map!(tag!("#EXT-X-INDEPENDENT-SEGMENTS"), |_| MasterPlaylistTag::IndependentSegments) | map!(tag!("#EXT-X-INDEPENDENT-SEGMENTS"), |_| MasterPlaylistTag::IndependentSegments)
| map!(ext_tag, MasterPlaylistTag::Unknown)
| map!(comment_tag, MasterPlaylistTag::Comment) | map!(comment_tag, MasterPlaylistTag::Comment)
| map!(consume_line, MasterPlaylistTag::Uri) | map!(consume_line, MasterPlaylistTag::Uri)
@ -328,6 +331,9 @@ pub fn master_playlist_from_tags(mut tags: Vec<MasterPlaylistTag>) -> MasterPlay
MasterPlaylistTag::IndependentSegments => { MasterPlaylistTag::IndependentSegments => {
master_playlist.independent_segments = true; master_playlist.independent_segments = true;
} }
MasterPlaylistTag::Unknown(unknown) => {
master_playlist.unknown_tags.push(unknown);
}
_ => (), _ => (),
} }
} }

View File

@ -8,6 +8,7 @@ use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
use std::fmt; use std::fmt;
use std::f32; use std::f32;
use std::fmt::Display;
macro_rules! write_some_attribute_quoted { macro_rules! write_some_attribute_quoted {
($w:expr, $tag:expr, $o:expr) => ( ($w:expr, $tag:expr, $o:expr) => (
@ -69,6 +70,7 @@ pub struct MasterPlaylist {
pub start: Option<Start>, pub start: Option<Start>,
pub independent_segments: bool, pub independent_segments: bool,
pub alternatives: Vec<AlternativeMedia>, // EXT-X-MEDIA tags pub alternatives: Vec<AlternativeMedia>, // EXT-X-MEDIA tags
pub unknown_tags: Vec<ExtTag>,
} }
impl MasterPlaylist { impl MasterPlaylist {
@ -100,6 +102,9 @@ impl MasterPlaylist {
if self.independent_segments { if self.independent_segments {
writeln!(w, "#EXT-X-INDEPENDENT-SEGMENTS")?; writeln!(w, "#EXT-X-INDEPENDENT-SEGMENTS")?;
} }
for unknown_tag in &self.unknown_tags {
writeln!(w, "{}", unknown_tag)?;
}
Ok(()) Ok(())
} }
@ -528,11 +533,7 @@ impl MediaSegment {
writeln!(w, "#EXT-X-DATERANGE:{}", v)?; writeln!(w, "#EXT-X-DATERANGE:{}", v)?;
} }
for unknown_tag in &self.unknown_tags { for unknown_tag in &self.unknown_tags {
write!(w, "#EXT-{}", unknown_tag.tag)?; writeln!(w, "{}", unknown_tag)?;
if let Some(v) = &unknown_tag.rest {
writeln!(w, ":{}", v)?;
}
write!(w, "\n")?;
} }
write!(w, "#EXTINF:{},", self.duration)?; write!(w, "#EXTINF:{},", self.duration)?;
@ -692,3 +693,43 @@ pub struct ExtTag {
pub rest: Option<String>, pub rest: Option<String>,
} }
impl Display for ExtTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "#EXT-{}", self.tag)?;
if let Some(v) = &self.rest {
write!(f, ":{}", v)?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn ext_tag_with_value_is_printable() {
let cue_out_tag = ExtTag {
tag: "X-CUE-OUT".into(),
rest: Some("DURATION=30".into()),
};
let mut output = Vec::new();
write!(output, "{}", cue_out_tag);
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-OUT:DURATION=30")
}
#[test]
fn ext_tag_without_value_is_printable() {
let cue_in_tag = ExtTag {
tag: "X-CUE-IN".into(),
rest: None,
};
let mut output = Vec::new();
write!(output, "{}", cue_in_tag);
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-IN")
}
}

View File

@ -390,6 +390,7 @@ fn create_and_parse_master_playlist_full() {
precise: Some("YES".into()), precise: Some("YES".into()),
}), }),
independent_segments: true, independent_segments: true,
unknown_tags: vec![],
}); });
let playlist_parsed = print_create_and_parse_playlist(&mut playlist_original); let playlist_parsed = print_create_and_parse_playlist(&mut playlist_original);
assert_eq!(playlist_original, playlist_parsed); assert_eq!(playlist_original, playlist_parsed);