mirror of
https://github.com/rutgersc/m3u8-rs.git
synced 2025-01-03 11:48:41 +00:00
Support multiple #EXT-X-KEY tags and adjust order
This commit is contained in:
parent
381ac7732f
commit
4cb35a17ef
3 changed files with 35 additions and 27 deletions
|
@ -391,7 +391,7 @@ fn media_playlist_tag(i: &[u8]) -> IResult<&[u8], MediaPlaylistTag> {
|
||||||
fn media_playlist_from_tags(mut tags: Vec<MediaPlaylistTag>) -> MediaPlaylist {
|
fn media_playlist_from_tags(mut tags: Vec<MediaPlaylistTag>) -> MediaPlaylist {
|
||||||
let mut media_playlist = MediaPlaylist::default();
|
let mut media_playlist = MediaPlaylist::default();
|
||||||
let mut next_segment = MediaSegment::empty();
|
let mut next_segment = MediaSegment::empty();
|
||||||
let mut encryption_key = None;
|
let mut encryption_keys = vec![];
|
||||||
let mut map = None;
|
let mut map = None;
|
||||||
|
|
||||||
while let Some(tag) = tags.pop() {
|
while let Some(tag) = tags.pop() {
|
||||||
|
@ -435,7 +435,7 @@ fn media_playlist_from_tags(mut tags: Vec<MediaPlaylistTag>) -> MediaPlaylist {
|
||||||
next_segment.discontinuity = true;
|
next_segment.discontinuity = true;
|
||||||
}
|
}
|
||||||
SegmentTag::Key(k) => {
|
SegmentTag::Key(k) => {
|
||||||
encryption_key = Some(k);
|
encryption_keys.push(k);
|
||||||
}
|
}
|
||||||
SegmentTag::Map(m) => {
|
SegmentTag::Map(m) => {
|
||||||
map = Some(m);
|
map = Some(m);
|
||||||
|
@ -450,12 +450,12 @@ fn media_playlist_from_tags(mut tags: Vec<MediaPlaylistTag>) -> MediaPlaylist {
|
||||||
next_segment.unknown_tags.push(t);
|
next_segment.unknown_tags.push(t);
|
||||||
}
|
}
|
||||||
SegmentTag::Uri(u) => {
|
SegmentTag::Uri(u) => {
|
||||||
next_segment.key = encryption_key.clone();
|
next_segment.keys = encryption_keys;
|
||||||
next_segment.map = map.clone();
|
next_segment.map = map.clone();
|
||||||
next_segment.uri = u;
|
next_segment.uri = u;
|
||||||
media_playlist.segments.push(next_segment);
|
media_playlist.segments.push(next_segment);
|
||||||
next_segment = MediaSegment::empty();
|
next_segment = MediaSegment::empty();
|
||||||
encryption_key = None;
|
encryption_keys = vec![];
|
||||||
map = None;
|
map = None;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -838,7 +838,7 @@ pub struct MediaSegment {
|
||||||
/// `#EXT-X-DISCONTINUITY`
|
/// `#EXT-X-DISCONTINUITY`
|
||||||
pub discontinuity: bool,
|
pub discontinuity: bool,
|
||||||
/// `#EXT-X-KEY:<attribute-list>`
|
/// `#EXT-X-KEY:<attribute-list>`
|
||||||
pub key: Option<Key>,
|
pub keys: Vec<Key>,
|
||||||
/// `#EXT-X-MAP:<attribute-list>`
|
/// `#EXT-X-MAP:<attribute-list>`
|
||||||
pub map: Option<Map>,
|
pub map: Option<Map>,
|
||||||
/// `#EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ>`
|
/// `#EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ>`
|
||||||
|
@ -855,24 +855,19 @@ impl MediaSegment {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn write_to<T: Write>(&self, w: &mut T) -> std::io::Result<()> {
|
pub(crate) fn write_to<T: Write>(&self, w: &mut T) -> std::io::Result<()> {
|
||||||
if let Some(ref byte_range) = self.byte_range {
|
|
||||||
write!(w, "#EXT-X-BYTERANGE:")?;
|
|
||||||
byte_range.write_value_to(w)?;
|
|
||||||
writeln!(w)?;
|
|
||||||
}
|
|
||||||
if self.discontinuity {
|
if self.discontinuity {
|
||||||
writeln!(w, "#EXT-X-DISCONTINUITY")?;
|
writeln!(w, "#EXT-X-DISCONTINUITY")?;
|
||||||
}
|
}
|
||||||
if let Some(ref key) = self.key {
|
|
||||||
write!(w, "#EXT-X-KEY:")?;
|
|
||||||
key.write_attributes_to(w)?;
|
|
||||||
writeln!(w)?;
|
|
||||||
}
|
|
||||||
if let Some(ref map) = self.map {
|
if let Some(ref map) = self.map {
|
||||||
write!(w, "#EXT-X-MAP:")?;
|
write!(w, "#EXT-X-MAP:")?;
|
||||||
map.write_attributes_to(w)?;
|
map.write_attributes_to(w)?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
|
for key in &self.keys {
|
||||||
|
write!(w, "#EXT-X-KEY:")?;
|
||||||
|
key.write_attributes_to(w)?;
|
||||||
|
writeln!(w)?;
|
||||||
|
}
|
||||||
if let Some(ref v) = self.program_date_time {
|
if let Some(ref v) = self.program_date_time {
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
|
@ -885,10 +880,6 @@ impl MediaSegment {
|
||||||
v.write_attributes_to(w)?;
|
v.write_attributes_to(w)?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
for unknown_tag in &self.unknown_tags {
|
|
||||||
writeln!(w, "{}", unknown_tag)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match WRITE_OPT_FLOAT_PRECISION.load(Ordering::Relaxed) {
|
match WRITE_OPT_FLOAT_PRECISION.load(Ordering::Relaxed) {
|
||||||
MAX => {
|
MAX => {
|
||||||
write!(w, "#EXTINF:{},", self.duration)?;
|
write!(w, "#EXTINF:{},", self.duration)?;
|
||||||
|
@ -897,12 +888,20 @@ impl MediaSegment {
|
||||||
write!(w, "#EXTINF:{:.*},", n, self.duration)?;
|
write!(w, "#EXTINF:{:.*},", n, self.duration)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref v) = self.title {
|
if let Some(ref v) = self.title {
|
||||||
writeln!(w, "{}", v)?;
|
writeln!(w, "{}", v)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
|
if let Some(ref byte_range) = self.byte_range {
|
||||||
|
write!(w, "#EXT-X-BYTERANGE:")?;
|
||||||
|
byte_range.write_value_to(w)?;
|
||||||
|
writeln!(w)?;
|
||||||
|
}
|
||||||
|
for unknown_tag in &self.unknown_tags {
|
||||||
|
writeln!(w, "{}", unknown_tag)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
writeln!(w, "{}", self.uri)
|
writeln!(w, "{}", self.uri)
|
||||||
}
|
}
|
||||||
|
|
23
tests/lib.rs
23
tests/lib.rs
|
@ -373,13 +373,22 @@ fn create_and_parse_media_playlist_full() {
|
||||||
offset: Some(4559),
|
offset: Some(4559),
|
||||||
}),
|
}),
|
||||||
discontinuity: true,
|
discontinuity: true,
|
||||||
key: Some(Key {
|
keys: vec![
|
||||||
method: KeyMethod::None,
|
Key {
|
||||||
uri: Some("https://secure.domain.com".into()),
|
method: KeyMethod::None,
|
||||||
iv: Some("0xb059217aa2649ce170b734".into()),
|
uri: Some("https://secure.domain.com".into()),
|
||||||
keyformat: Some("xXkeyformatXx".into()),
|
iv: Some("0xb059217aa2649ce170b734".into()),
|
||||||
keyformatversions: Some("xXFormatVers".into()),
|
keyformat: Some("xXkeyformatXx".into()),
|
||||||
}),
|
keyformatversions: Some("xXFormatVers".into()),
|
||||||
|
},
|
||||||
|
Key {
|
||||||
|
method: KeyMethod::AES128,
|
||||||
|
uri: Some("skd://c2VjdXJlLmRvbWFpbi5jb20=".into()),
|
||||||
|
iv: Some("0xb059217aa2649ce170b734".into()),
|
||||||
|
keyformat: Some("com.apple.streamingkeydelivery".into()),
|
||||||
|
keyformatversions: Some("1".into()),
|
||||||
|
},
|
||||||
|
],
|
||||||
map: Some(Map {
|
map: Some(Map {
|
||||||
uri: "www.map-uri.com".into(),
|
uri: "www.map-uri.com".into(),
|
||||||
byte_range: Some(ByteRange {
|
byte_range: Some(ByteRange {
|
||||||
|
|
Loading…
Reference in a new issue