mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-25 00:20:59 +00:00
commit
7907f9b1f1
6 changed files with 279 additions and 2 deletions
|
@ -36,6 +36,7 @@ stable-vec = { version = "0.4" }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6"
|
pretty_assertions = "0.6"
|
||||||
version-sync = "0.9"
|
version-sync = "0.9"
|
||||||
|
automod = "0.2"
|
||||||
criterion = "0.3.1"
|
criterion = "0.3.1"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
|
|
|
@ -204,8 +204,16 @@ impl<'a> ExtXMediaBuilder<'a> {
|
||||||
.to_string());
|
.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if media_type != MediaType::Subtitles && self.is_forced.is_some() {
|
if media_type != MediaType::Subtitles && self.is_forced.unwrap_or(false) {
|
||||||
return Err(Error::invalid_input().to_string());
|
return Err(Error::custom(format!(
|
||||||
|
concat!(
|
||||||
|
"the forced attribute must not be present, ",
|
||||||
|
"unless the media_type is `MediaType::Subtitles`: ",
|
||||||
|
"media_type: {:?}, is_forced: {:?}"
|
||||||
|
),
|
||||||
|
media_type, self.is_forced
|
||||||
|
))
|
||||||
|
.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
30
tests/issues/assets/issue_00055.m3u8
Normal file
30
tests/issues/assets/issue_00055.m3u8
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
#EXT-X-INDEPENDENT-SEGMENTS
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_aac_1",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://www.example.com/file_01.m3u8",FORCED=NO
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_aac_2",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://www.example.com/file_02.m3u8",FORCED=NO
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=426x240,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=609683,AVERAGE-BANDWIDTH=337111,FRAME-RATE=24.000,AUDIO="audio_aac_1"
|
||||||
|
https://www.example.com/file_03.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=426x240,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=672828,AVERAGE-BANDWIDTH=401121,FRAME-RATE=24.000,AUDIO="audio_aac_2"
|
||||||
|
https://www.example.com/file_04.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=963123,AVERAGE-BANDWIDTH=498553,FRAME-RATE=24.000,AUDIO="audio_aac_1"
|
||||||
|
https://www.example.com/file_05.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=1026268,AVERAGE-BANDWIDTH=562563,FRAME-RATE=24.000,AUDIO="audio_aac_2"
|
||||||
|
https://www.example.com/file_06.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=1365255,AVERAGE-BANDWIDTH=652779,FRAME-RATE=24.000,AUDIO="audio_aac_1"
|
||||||
|
https://www.example.com/file_07.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",BANDWIDTH=1428400,AVERAGE-BANDWIDTH=716789,FRAME-RATE=24.000,AUDIO="audio_aac_2"
|
||||||
|
https://www.example.com/file_08.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.4D4020,mp4a.40.2",BANDWIDTH=2342667,AVERAGE-BANDWIDTH=1030774,FRAME-RATE=24.000,AUDIO="audio_aac_1"
|
||||||
|
https://www.example.com/file_09.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.4D4020,mp4a.40.2",BANDWIDTH=2405812,AVERAGE-BANDWIDTH=1094784,FRAME-RATE=24.000,AUDIO="audio_aac_2"
|
||||||
|
https://www.example.com/file_10.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=1920x1080,CODECS="avc1.64002A,mp4a.40.2",BANDWIDTH=4635327,AVERAGE-BANDWIDTH=1687626,FRAME-RATE=24.000,AUDIO="audio_aac_1"
|
||||||
|
https://www.example.com/file_11.m3u8
|
||||||
|
#EXT-X-STREAM-INF:RESOLUTION=1920x1080,CODECS="avc1.64002A,mp4a.40.2",BANDWIDTH=4698472,AVERAGE-BANDWIDTH=1751636,FRAME-RATE=24.000,AUDIO="audio_aac_2"
|
||||||
|
https://www.example.com/file_12.m3u8
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=426x240,CODECS="avc1.4D401F",BANDWIDTH=92496,AVERAGE-BANDWIDTH=31745,URI="https://www.example.com/file_13.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=640x360,CODECS="avc1.4D401F",BANDWIDTH=252672,AVERAGE-BANDWIDTH=53787,URI="https://www.example.com/file_14.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=852x480,CODECS="avc1.4D401F",BANDWIDTH=392544,AVERAGE-BANDWIDTH=72767,URI="https://www.example.com/file_15.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.4D4020",BANDWIDTH=649728,AVERAGE-BANDWIDTH=108944,URI="https://www.example.com/file_16.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=1920x1080,CODECS="avc1.64002A",BANDWIDTH=1328784,AVERAGE-BANDWIDTH=161039,URI="https://www.example.com/file_17.m3u8"
|
236
tests/issues/issue_00055.rs
Normal file
236
tests/issues/issue_00055.rs
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
// The relevant issue:
|
||||||
|
// https://github.com/sile/hls_m3u8/issues/55
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use hls_m3u8::tags::{ExtXMedia, VariantStream};
|
||||||
|
use hls_m3u8::types::{MediaType, StreamData, UFloat};
|
||||||
|
use hls_m3u8::MasterPlaylist;
|
||||||
|
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse() {
|
||||||
|
let file = include_str!("assets/issue_00055.m3u8");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
MasterPlaylist::from_str(file).unwrap(),
|
||||||
|
MasterPlaylist::builder()
|
||||||
|
.has_independent_segments(true)
|
||||||
|
.media(vec![
|
||||||
|
ExtXMedia::builder()
|
||||||
|
.media_type(MediaType::Audio)
|
||||||
|
.group_id("audio_aac_1")
|
||||||
|
.language("eng")
|
||||||
|
.name("English")
|
||||||
|
.is_autoselect(true)
|
||||||
|
.is_default(true)
|
||||||
|
.uri("https://www.example.com/file_01.m3u8")
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
ExtXMedia::builder()
|
||||||
|
.media_type(MediaType::Audio)
|
||||||
|
.group_id("audio_aac_2")
|
||||||
|
.language("eng")
|
||||||
|
.name("English")
|
||||||
|
.is_autoselect(true)
|
||||||
|
.is_default(true)
|
||||||
|
.uri("https://www.example.com/file_02.m3u8")
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
])
|
||||||
|
.variant_streams(vec![
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_03.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_1".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(609683)
|
||||||
|
.average_bandwidth(337111)
|
||||||
|
.resolution((426, 240))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_04.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_2".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(672828)
|
||||||
|
.average_bandwidth(401121)
|
||||||
|
.resolution((426, 240))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_05.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_1".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(963123)
|
||||||
|
.average_bandwidth(498553)
|
||||||
|
.resolution((640, 360))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_06.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_2".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(1026268)
|
||||||
|
.average_bandwidth(562563)
|
||||||
|
.resolution((640, 360))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_07.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_1".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(1365255)
|
||||||
|
.average_bandwidth(652779)
|
||||||
|
.resolution((852, 480))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_08.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_2".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(1428400)
|
||||||
|
.average_bandwidth(716789)
|
||||||
|
.resolution((852, 480))
|
||||||
|
.codecs(vec!["avc1.4D401F", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_09.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_1".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(2342667)
|
||||||
|
.average_bandwidth(1030774)
|
||||||
|
.resolution((1280, 720))
|
||||||
|
.codecs(vec!["avc1.4D4020", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_10.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_2".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(2405812)
|
||||||
|
.average_bandwidth(1094784)
|
||||||
|
.resolution((1280, 720))
|
||||||
|
.codecs(vec!["avc1.4D4020", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_11.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_1".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(4635327)
|
||||||
|
.average_bandwidth(1687626)
|
||||||
|
.resolution((1920, 1080))
|
||||||
|
.codecs(vec!["avc1.64002A", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXStreamInf {
|
||||||
|
uri: "https://www.example.com/file_12.m3u8".into(),
|
||||||
|
frame_rate: Some(UFloat::new(24.000)),
|
||||||
|
audio: Some("audio_aac_2".into()),
|
||||||
|
subtitles: None,
|
||||||
|
closed_captions: None,
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.bandwidth(4698472)
|
||||||
|
.average_bandwidth(1751636)
|
||||||
|
.resolution((1920, 1080))
|
||||||
|
.codecs(vec!["avc1.64002A", "mp4a.40.2"])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXIFrame {
|
||||||
|
uri: "https://www.example.com/file_13.m3u8".into(),
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.resolution((426, 240))
|
||||||
|
.codecs(vec!["avc1.4D401F"])
|
||||||
|
.bandwidth(92496)
|
||||||
|
.average_bandwidth(31745)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXIFrame {
|
||||||
|
uri: "https://www.example.com/file_14.m3u8".into(),
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.resolution((640, 360))
|
||||||
|
.codecs(vec!["avc1.4D401F"])
|
||||||
|
.bandwidth(252672)
|
||||||
|
.average_bandwidth(53787)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXIFrame {
|
||||||
|
uri: "https://www.example.com/file_15.m3u8".into(),
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.resolution((852, 480))
|
||||||
|
.codecs(vec!["avc1.4D401F"])
|
||||||
|
.bandwidth(392544)
|
||||||
|
.average_bandwidth(72767)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXIFrame {
|
||||||
|
uri: "https://www.example.com/file_16.m3u8".into(),
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.resolution((1280, 720))
|
||||||
|
.codecs(vec!["avc1.4D4020"])
|
||||||
|
.bandwidth(649728)
|
||||||
|
.average_bandwidth(108944)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
VariantStream::ExtXIFrame {
|
||||||
|
uri: "https://www.example.com/file_17.m3u8".into(),
|
||||||
|
stream_data: StreamData::builder()
|
||||||
|
.resolution((1920, 1080))
|
||||||
|
.codecs(vec!["avc1.64002A"])
|
||||||
|
.bandwidth(1328784)
|
||||||
|
.average_bandwidth(161039)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
}
|
1
tests/issues/mod.rs
Normal file
1
tests/issues/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
automod::dir!("tests/issues");
|
1
tests/mod.rs
Normal file
1
tests/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod issues;
|
Loading…
Reference in a new issue