From b1a7871cc6591d1a7be4c8d91d3068570255ebc8 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 28 Jan 2022 11:58:19 +0100 Subject: [PATCH 1/4] Add test content with CHANNELS attribute --- sample-playlists/master-with-channels.m3u8 | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 sample-playlists/master-with-channels.m3u8 diff --git a/sample-playlists/master-with-channels.m3u8 b/sample-playlists/master-with-channels.m3u8 new file mode 100644 index 00000000..5045a3e6 --- /dev/null +++ b/sample-playlists/master-with-channels.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-STREAM-INF:AVERAGE-BANDWIDTH=8052613,BANDWIDTH=9873268,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,AUDIO="a1" +v9/prog_index.m3u8 + From cb6092efd97225ff26709d028bdd4a3385fb4cc2 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 28 Jan 2022 16:10:54 +0100 Subject: [PATCH 2/4] Add support for CHANNELS attribute See: https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.4.1 --- reader.go | 6 ++++++ structure.go | 1 + writer.go | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/reader.go b/reader.go index b19324eb..383f600e 100644 --- a/reader.go +++ b/reader.go @@ -329,6 +329,12 @@ func decodeLineOfMasterPlaylist(p *MasterPlaylist, state *decodingState, line st alt.Subtitles = v case "URI": alt.URI = v + case "CHANNELS": + channels, err := strconv.Atoi(v) + if err != nil { + return fmt.Errorf("non-integer value \"%s\" for CHANNELS attribute", v) + } + alt.Channels = uint(channels) } } state.alternatives = append(state.alternatives, &alt) diff --git a/structure.go b/structure.go index eb5d01a2..dd1ee2ac 100644 --- a/structure.go +++ b/structure.go @@ -197,6 +197,7 @@ type Alternative struct { Forced string Characteristics string Subtitles string + Channels uint } // MediaSegment structure represents a media segment included in a diff --git a/writer.go b/writer.go index dec3690c..399f0be0 100644 --- a/writer.go +++ b/writer.go @@ -156,6 +156,11 @@ func (p *MasterPlaylist) Encode() *bytes.Buffer { p.buf.WriteRune('"') } p.buf.WriteRune('\n') + if alt.Channels != 0 { + p.buf.WriteString(",CHANNELS=\"") + p.buf.WriteString(strconv.FormatUint(uint64(alt.Channels), 10)) + p.buf.WriteRune('"') + } } } if pl.Iframe { From 9eaf34931856dd4b0d791b228b47cee98dd8a4fe Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 28 Jan 2022 16:12:16 +0100 Subject: [PATCH 3/4] Add tests --- reader_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/reader_test.go b/reader_test.go index 8d60b16c..8bfed863 100644 --- a/reader_test.go +++ b/reader_test.go @@ -972,6 +972,40 @@ func TestDecodeMediaPlaylistStartTime(t *testing.T) { } } +func TestDecodeMasterChannels(t *testing.T) { + f, err := os.Open("sample-playlists/master-with-channels.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) + + alt0 := pp.Variants[0].Alternatives[0] + if alt0.Type != "AUDIO" { + t.Error("Expected AUDIO track in test input Alternatives[0]") + } + + if alt0.Channels != 2 { + t.Error("Expected 2 channels track in test input Alternatives[0]") + } + + alt1 := pp.Variants[0].Alternatives[1] + if alt1.Type != "AUDIO" { + t.Error("Expected AUDIO track in test input Alternatives[1]") + } + + if alt1.Channels != 6 { + t.Error("Expected 6 channels track in test input Alternatives[1]") + } +} + /**************** * Benchmarks * ****************/ From 610edb600e48a0bd2e49b23731f942f2e4f7bfff Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 31 Jan 2022 11:12:11 +0100 Subject: [PATCH 4/4] Review fix --- reader.go | 2 +- writer.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reader.go b/reader.go index 383f600e..55e9bb67 100644 --- a/reader.go +++ b/reader.go @@ -332,7 +332,7 @@ func decodeLineOfMasterPlaylist(p *MasterPlaylist, state *decodingState, line st case "CHANNELS": channels, err := strconv.Atoi(v) if err != nil { - return fmt.Errorf("non-integer value \"%s\" for CHANNELS attribute", v) + return fmt.Errorf("non-integer value %q for CHANNELS attribute", v) } alt.Channels = uint(channels) } diff --git a/writer.go b/writer.go index 399f0be0..96c08636 100644 --- a/writer.go +++ b/writer.go @@ -155,12 +155,12 @@ func (p *MasterPlaylist) Encode() *bytes.Buffer { p.buf.WriteString(alt.URI) p.buf.WriteRune('"') } - p.buf.WriteRune('\n') if alt.Channels != 0 { p.buf.WriteString(",CHANNELS=\"") p.buf.WriteString(strconv.FormatUint(uint64(alt.Channels), 10)) p.buf.WriteRune('"') } + p.buf.WriteRune('\n') } } if pl.Iframe {