Fixed a bug where the parser fails when the playlist does not end with a newline.

This commit is contained in:
Rutger 2016-09-10 13:22:13 +02:00
parent fe2ceb87dd
commit d7c452fe78
5 changed files with 73 additions and 34 deletions

View file

@ -0,0 +1,16 @@
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="Audio1",NAME="mp4a.40.2_96K_Spanish",LANGUAGE="spa",DEFAULT=YES,AUTOSELECT=YES,URI="A1.m3u8"
A1.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=395000,CODECS="avc1.4d001f,mp4a.40.2",AUDIO="Audio1",RESOLUTION=320x240
01.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=394000,CODECS="avc1.4d001f,mp4a.40.2",URI="01_iframe_index.m3u8"
01_iframe_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=963000,CODECS="avc1.4d001f,mp4a.40.2",AUDIO="Audio1",RESOLUTION=448x336
02.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=962000,CODECS="avc1.4d001f,mp4a.40.2",URI="02_iframe_index.m3u8"
02_iframe_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1695000,CODECS="avc1.4d001f,mp4a.40.2",AUDIO="Audio1",RESOLUTION=640x480
03.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1694000,CODECS="avc1.4d001f,mp4a.40.2",URI="03_iframe_index.m3u8"
03_iframe_index.m3u8

View file

@ -1,20 +0,0 @@
#EXTM3U
#EXT-X-TWITCH-INFO:NODE="video47.lhr02",MANIFEST-NODE="video47.lhr02",SERVER-TIME="1463829370.34",USER-IP="145.87.245.122",CLUSTER="lhr02",STREAM-TIME="39299.3432069",MANIFEST-CLUSTER="lhr02"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="chunked",NAME="Source",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3960281,RESOLUTION=1280x720,CODECS="avc1.4D4029,mp4a.40.2",VIDEO="chunked"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/chunked/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=chunked&sig=2491212c28bdc97e74c8755d6cc18f8bdd971f30
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="high",NAME="High",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1760000,RESOLUTION=1280x720,CODECS="avc1.66.31,mp4a.40.2",VIDEO="high"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/high/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=high&sig=be34da4d70ab7cabe773f12a37d863565efe2b46
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="medium",NAME="Medium",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=928000,RESOLUTION=852x480,CODECS="avc1.66.31,mp4a.40.2",VIDEO="medium"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/medium/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=medium&sig=88ee9e7c5416096599e0b46017d7de82f876b8ae
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Low",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=596000,RESOLUTION=640x360,CODECS="avc1.66.31,mp4a.40.2",VIDEO="low"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/low/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=low&sig=79398c8f2e8636720d59aa2310e19eff6ab42d46
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mobile",NAME="Mobile",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=164000,RESOLUTION=400x226,CODECS="avc1.66.31,mp4a.40.2",VIDEO="mobile"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/mobile/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=mobile&sig=cc9f889823f25969c8b8d911ea9193dc33ce41dc
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="audio_only",NAME="Audio Only",AUTOSELECT=NO,DEFAULT=NO
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=128000,CODECS="mp4a.40.2",VIDEO="audio_only"
http://video47.lhr02.hls.ttvnw.net/hls32/itmejp_21425103760_456233939/audio_only/index-live.m3u8?token=id=1079441765470438139,bid=21425103760,exp=1463915770,node=video47-1.lhr02.hls.justin.tv,nname=video47.lhr02,fmt=audio_only&sig=e3179b7cacb9530df951f8d683ff02a493100849

View file

@ -0,0 +1,35 @@
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:338559
#EXT-X-KEY:METHOD=AES-128,URI="https://secure.domain.com",IV=0xb059217aa2649ce170b734
#EXTINF:2.002,338559
20140311T113819-01-338559live.ts
#EXTINF:2.002,338560
20140311T113819-01-338560live.ts
#EXTINF:2.002,338561
20140311T113819-01-338561live.ts
#EXTINF:2.002,338562
20140311T113819-01-338562live.ts
#EXTINF:2.002,338563
20140311T113819-01-338563live.ts
#EXTINF:2.002,338564
20140311T113819-01-338564live.ts
#EXTINF:2.002,338565
20140311T113819-01-338565live.ts
#EXTINF:2.002,338566
20140311T113819-01-338566live.ts
#EXTINF:2.002,338567
20140311T113819-01-338567live.ts
#EXTINF:2.002,338568
20140311T113819-01-338568live.ts
#EXTINF:2.002,338569
20140311T113819-01-338569live.ts
#EXTINF:2.002,338570
20140311T113819-01-338570live.ts
#EXTINF:2.002,338571
20140311T113819-01-338571live.ts
#EXTINF:2.002,338572
20140311T113819-01-338572live.ts
#EXTINF:2.002,338573
20140311T113819-01-338573live.ts

View file

@ -201,7 +201,7 @@ named!(pub is_master_playlist_tag_line(&[u8]) -> Option<(bool, String)>,
pub fn parse_master_playlist_tags(input: &[u8]) -> IResult<&[u8], Vec<MasterPlaylistTag>> { pub fn parse_master_playlist_tags(input: &[u8]) -> IResult<&[u8], Vec<MasterPlaylistTag>> {
chain!(input, chain!(input,
mut tags: many0!(chain!(m:master_playlist_tag ~ multispace?, || m)) ~ eof, mut tags: many0!(chain!(m:master_playlist_tag ~ multispace?, || m)) ~ eof?,
|| { tags.reverse(); tags } || { tags.reverse(); tags }
) )
} }
@ -273,7 +273,7 @@ named!(pub session_key_tag<SessionKey>,
pub fn parse_media_playlist_tags(input: &[u8]) -> IResult<&[u8], Vec<MediaPlaylistTag>> { pub fn parse_media_playlist_tags(input: &[u8]) -> IResult<&[u8], Vec<MediaPlaylistTag>> {
chain!(input, chain!(input,
mut tags: many0!(chain!(m:media_playlist_tag ~ multispace?, || m)) ~ eof, mut tags: many0!(chain!(m:media_playlist_tag ~ multispace?, || m)) ~ eof?,
|| { tags.reverse(); tags } || { tags.reverse(); tags }
) )
} }

View file

@ -48,11 +48,6 @@ fn print_parse_playlist_test(playlist_name: &str) -> bool {
} }
} }
#[test]
fn playlis_master_usher_result() {
assert!(print_parse_playlist_test("master-usher_result.m3u8"));
}
#[test] #[test]
fn playlist_master_with_alternatives() { fn playlist_master_with_alternatives() {
assert!(print_parse_playlist_test("master-with-alternatives.m3u8")); assert!(print_parse_playlist_test("master-with-alternatives.m3u8"));
@ -80,6 +75,19 @@ fn playlist_media_without_segments() {
assert!(print_parse_playlist_test("media-playlist-without-segments.m3u8")); assert!(print_parse_playlist_test("media-playlist-without-segments.m3u8"));
} }
// -----------------------------------------------------------------------------------------------
// Playlist with no newline end
#[test]
fn playlist_not_ending_in_newline_master() {
assert!(print_parse_playlist_test("master-not-ending-in-newline.m3u8"));
}
#[test]
fn playlist_not_ending_in_newline_media() {
assert!(print_parse_playlist_test("media-not-ending-in-newline.m3u8"));
}
// ----------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------
// Playlist type detection tests // Playlist type detection tests
@ -90,13 +98,13 @@ fn playlist_type_is_master() {
assert_eq!(true, result); assert_eq!(true, result);
} }
#[test] // #[test]
fn playlist_type_with_unkown_tag() { // fn playlist_type_with_unkown_tag() {
let input = get_sample_playlist("master-usher_result.m3u8"); // let input = get_sample_playlist("!!");
let result = is_master_playlist(input.as_bytes()); // let result = is_master_playlist(input.as_bytes());
println!("Playlist_type_with_unkown_tag is master playlist: {:?}", result); // println!("Playlist_type_with_unkown_tag is master playlist: {:?}", result);
assert_eq!(true, result); // assert_eq!(true, result);
} // }
#[test] #[test]
fn playlist_types() { fn playlist_types() {