diff --git a/CHANGELOG.md b/CHANGELOG.md index 715b4d7..542f0cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CHANNELS attribute to EXT-X-MEDIA +### Fixed + +- Renditions were not properly distributed to Variants + ## v0.1.0 - cleaned grafov/m3u8 code ### Changed diff --git a/m3u8/reader.go b/m3u8/reader.go index b7a1b41..6afd3eb 100644 --- a/m3u8/reader.go +++ b/m3u8/reader.go @@ -87,6 +87,9 @@ func (p *MasterPlaylist) decode(buf *bytes.Buffer, strict bool) error { func (p *MasterPlaylist) attachRenditionsToVariants(alternatives []*Alternative) { for _, variant := range p.Variants { + if variant.Iframe { + continue + } for _, alt := range alternatives { if alt == nil { continue @@ -231,7 +234,6 @@ func decode(buf *bytes.Buffer, strict bool, customDecoders []CustomDecoder) (Pla line = trimLineEnd(line) err = decodeLineOfMasterPlaylist(master, state, line, strict) - master.attachRenditionsToVariants(state.alternatives) if strict && err != nil { return master, state.listType, err } @@ -249,6 +251,7 @@ func decode(buf *bytes.Buffer, strict bool, customDecoders []CustomDecoder) (Pla switch state.listType { case MASTER: + master.attachRenditionsToVariants(state.alternatives) return master, MASTER, nil case MEDIA: if media.Closed || media.MediaType == EVENT { @@ -398,10 +401,6 @@ func decodeLineOfMasterPlaylist(p *MasterPlaylist, state *decodingState, line st state.listType = MASTER state.variant = new(Variant) state.variant.Iframe = true - if len(state.alternatives) > 0 { - state.variant.Alternatives = state.alternatives - state.alternatives = nil - } p.Variants = append(p.Variants, state.variant) for k, v := range decodeParamsLine(line[26:]) { switch k { diff --git a/m3u8/reader_test.go b/m3u8/reader_test.go index ded714d..435713c 100644 --- a/m3u8/reader_test.go +++ b/m3u8/reader_test.go @@ -1073,6 +1073,35 @@ func TestDecodeMasterChannels(t *testing.T) { } } +func TestDecodeRenditionsAndIframes(t *testing.T) { + f, err := os.Open("sample-playlists/master-groups-and-iframe.m3u8") + if err != nil { + t.Fatal(err) + } + p, listType, err := DecodeFrom(bufio.NewReader(f), true) + if err != nil { + t.Fatal(err) + } + + if listType != MASTER { + t.Error("Input not recognized as master playlist.") + } + pp := p.(*MasterPlaylist) + + for _, v := range pp.Variants { + switch v.Iframe { + case true: + if len(v.Alternatives) != 0 { + t.Error("Expected no alternatives in I-frame variant") + } + case false: + if len(v.Alternatives) != 1 { + t.Error("Expected 1 alternative in each video variant") + } + } + } +} + /**************** * Benchmarks * ****************/ diff --git a/m3u8/sample-playlists/master-groups-and-iframe.m3u8 b/m3u8/sample-playlists/master-groups-and-iframe.m3u8 new file mode 100644 index 0000000..6c805f1 --- /dev/null +++ b/m3u8/sample-playlists/master-groups-and-iframe.m3u8 @@ -0,0 +1,13 @@ +#EXTM3U +#EXT-X-VERSION:6 +#EXT-X-INDEPENDENT-SEGMENTS + + +#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a1",NAME="English",LANGUAGE="en-US",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="a1/prog_index.m3u8" +#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a2",NAME="English",LANGUAGE="en-US",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="6",URI="a2/prog_index.m3u8" + +#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2190673,BANDWIDTH=2523597,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=60.000,AUDIO="a1" +v5/prog_index.m3u8 +#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=248586,BANDWIDTH=593626,VIDEO-RANGE=SDR,CODECS="hvc1.2.4.L123.B0",RESOLUTION=1280x720,HDCP-LEVEL=NONE,URI="v9_i/prog_index.m3u8" +#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=8052613,BANDWIDTH=9873268,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,AUDIO="a2" +v9/prog_index.m3u8 \ No newline at end of file