Skip to content
This repository has been archived by the owner on Dec 8, 2024. It is now read-only.

Fix: MediaPlaylist with discontinuities should not ignore maps #154

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e2a23f9
Fix: MediaPlaylist with discontinuities should not ignore maps
Nov 21, 2019
3cf5695
add appendSegment tests for MediaPlaylist
Nov 25, 2019
08b2d91
Merge pull request #1 from zencoder/HLS-Maps-Fix
vish91 Nov 25, 2019
2ab1b1f
Merge remote-tracking branch 'grafov/master' into upstream-merge
soldiermoth Oct 7, 2020
3d9e843
Try vanity import to work w/ travis
soldiermoth Oct 7, 2020
98975fe
remove coveralls from fork
soldiermoth Oct 7, 2020
8abd012
With support for CHANNELS
soldiermoth Oct 7, 2020
6485cdb
Upstream merge (#3)
soldiermoth Oct 7, 2020
b4814d4
Merge remote-tracking branch 'origin/master' into channels
soldiermoth Oct 7, 2020
087a7c8
Merge pull request #4 from zencoder/channels
soldiermoth Oct 8, 2020
d3f557e
add id to m3u8 key
hikeh Nov 30, 2021
adb506a
add id to m3u8 key usages
hikeh Nov 30, 2021
41f3477
add id to test
hikeh Nov 30, 2021
f39fba4
update yaml
hikeh Nov 30, 2021
dc41e13
revert update version
hikeh Nov 30, 2021
8cabadb
update Key usages of ID
hikeh Dec 1, 2021
7acba66
rename ID to KeyId
hikeh Dec 1, 2021
43ab5e1
revert yaml change
hikeh Dec 1, 2021
412c7ef
Update .travis.yml
hikeh Dec 1, 2021
420f0c3
remove space
hikeh Dec 1, 2021
203f0ae
Merge branch 'zencoder:Add_id_to_m3u8_key' into Add_id_to_m3u8_key
hikeh Dec 1, 2021
c3edfc8
Update .travis.yml
hikeh Dec 1, 2021
11b8ddf
Merge pull request #5 from hikeh/Add_id_to_m3u8_key
hikeh Dec 1, 2021
07b7cca
Add fields to support the creation of Image Playlists for HLS Roku Th…
ferpart Dec 17, 2021
90ba960
Add EXT-X-IMAGE-STREAM-INF for HLS Roku Thumbnails
ferpart Dec 28, 2021
d9e2522
Add unit tests for new tags
ferpart Dec 29, 2021
5aab70e
Merge pull request #7 from zencoder/DELIVER-2341
Dec 30, 2021
2374fe0
Add .whitesource configuration file (#6)
mend-for-github-com[bot] Feb 8, 2022
18d1454
Support for EXT-X-CUE-OUT and EXT-X-CUE-IN tags (#8)
hatondo-bcov Feb 15, 2022
5af99e3
ext-x-map byterange attribute is quoted string
mjneil Jan 8, 2024
9467fd7
Merge pull request #9 from zencoder/NT-map-byterange
mjneil Jan 8, 2024
d20ac76
add BeforeKey to map
mjneil Apr 26, 2024
ad67f0a
fix build
mjneil Apr 26, 2024
f9ca25e
add unit test
mjneil Apr 26, 2024
96e01f0
Merge pull request #10 from zencoder/DELIVER-4039-opt-a
mjneil Apr 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: go
go_import_path: github.com/grafov/m3u8

# Versions of go that are explicitly supported.
go:
Expand All @@ -9,11 +10,9 @@ go:

# Required for coverage.
before_install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
- go install golang.org/x/tools/...@latest

script:
- go build -a -v ./...
- diff <(gofmt -d .) <("")
- go test -v -covermode=count -coverprofile=coverage.out
- $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis-ci
3 changes: 3 additions & 0 deletions .whitesource
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"settingsInheritedFrom": "zencoder/whitesource-config@main"
}
30 changes: 24 additions & 6 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ var reKeyValue = regexp.MustCompile(`([a-zA-Z0-9_-]+)=("[^"]+"|[^",]+)`)

// TimeParse allows globally apply and/or override Time Parser function.
// Available variants:
// * FullTimeParse - implements full featured ISO/IEC 8601:2004
// * StrictTimeParse - implements only RFC3339 Nanoseconds format
// - FullTimeParse - implements full featured ISO/IEC 8601:2004
// - StrictTimeParse - implements only RFC3339 Nanoseconds format
var TimeParse func(value string) (time.Time, error) = FullTimeParse

// Decode parses a master playlist passed from the buffer. If `strict`
Expand Down Expand Up @@ -327,6 +327,8 @@ func decodeLineOfMasterPlaylist(p *MasterPlaylist, state *decodingState, line st
alt.Characteristics = v
case "SUBTITLES":
alt.Subtitles = v
case "CHANNELS":
alt.Channels = v
case "URI":
alt.URI = v
}
Expand Down Expand Up @@ -536,7 +538,7 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
}
// If EXT-X-KEY appeared before reference to segment (EXTINF) then it linked to this segment
if state.tagKey {
p.Segments[p.last()].Key = &Key{state.xkey.Method, state.xkey.URI, state.xkey.IV, state.xkey.Keyformat, state.xkey.Keyformatversions}
p.Segments[p.last()].Key = &Key{Method: state.xkey.Method, URI: state.xkey.URI, IV: state.xkey.IV, Keyformat: state.xkey.Keyformat, Keyformatversions: state.xkey.Keyformatversions, KeyID: state.xkey.KeyID}
// First EXT-X-KEY may appeared in the header of the playlist and linked to first segment
// but for convenient playlist generation it also linked as default playlist key
if p.Key == nil {
Expand All @@ -546,7 +548,7 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
}
// If EXT-X-MAP appeared before reference to segment (EXTINF) then it linked to this segment
if state.tagMap {
p.Segments[p.last()].Map = &Map{state.xmap.URI, state.xmap.Limit, state.xmap.Offset}
p.Segments[p.last()].Map = &Map{state.xmap.URI, state.xmap.Limit, state.xmap.Offset, false}
// First EXT-X-MAP may appeared in the header of the playlist and linked to first segment
// but for convenient playlist generation it also linked as default playlist map
if p.Map == nil {
Expand Down Expand Up @@ -632,6 +634,8 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
state.xkey.Keyformat = v
case "KEYFORMATVERSIONS":
state.xkey.Keyformatversions = v
case "KEYID":
state.xkey.KeyID = v
}
}
state.tagKey = true
Expand Down Expand Up @@ -693,10 +697,22 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
// EXT-OATCLS-SCTE35 contains the SCTE35 tag, EXT-X-CUE-OUT contains duration
state.scte.Time, _ = strconv.ParseFloat(line[15:], 64)
state.scte.CueType = SCTE35Cue_Start
case !state.tagSCTE35 && strings.HasPrefix(line, "#EXT-X-CUE-OUT:"):
state.tagSCTE35 = true
state.listType = MEDIA
state.scte = new(SCTE)
state.scte.Syntax = SCTE35_CUE
state.scte.Time, _ = strconv.ParseFloat(line[15:], 64)
state.scte.CueType = SCTE35Cue_Start
case !state.tagSCTE35 && strings.HasPrefix(line, "#EXT-X-CUE-OUT-CONT:"):
// Since different SCTE35 tags can look similar when reading them, we
// take the SCTE35Syntax of the previous segment. This will give
// the SCTESyntax of the starting cue out.
scteSyntax := p.Segments[p.tail-1].SCTE.Syntax

state.tagSCTE35 = true
state.scte = new(SCTE)
state.scte.Syntax = SCTE35_OATCLS
state.scte.Syntax = scteSyntax
state.scte.CueType = SCTE35Cue_Mid
for attribute, value := range decodeParamsLine(line[20:]) {
switch attribute {
Expand All @@ -709,9 +725,11 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
}
}
case !state.tagSCTE35 && line == "#EXT-X-CUE-IN":
// Same as EXT-X-CUE-OUT-CONT
scteSyntax := p.Segments[p.tail-1].SCTE.Syntax
state.tagSCTE35 = true
state.scte = new(SCTE)
state.scte.Syntax = SCTE35_OATCLS
state.scte.Syntax = scteSyntax
state.scte.CueType = SCTE35Cue_End
case !state.tagDiscontinuity && strings.HasPrefix(line, "#EXT-X-DISCONTINUITY"):
state.tagDiscontinuity = true
Expand Down
74 changes: 69 additions & 5 deletions reader_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*
Playlist parsing tests.
Playlist parsing tests.

Copyright 2013-2019 The Project Developers.
See the AUTHORS and LICENSE files at the top-level directory of this distribution
and at https://github.com/grafov/m3u8/
Copyright 2013-2019 The Project Developers.
See the AUTHORS and LICENSE files at the top-level directory of this distribution
and at https://github.com/grafov/m3u8/

ॐ तारे तुत्तारे तुरे स्व
ॐ तारे तुत्तारे तुरे स्व
*/
package m3u8

Expand All @@ -14,6 +14,7 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"reflect"
"testing"
Expand Down Expand Up @@ -288,6 +289,43 @@ func TestDecodeMasterWithHLSV7(t *testing.T) {
}
}

func TestDecodeMasterPlaylistWithChapters(t *testing.T) {
f, err := os.Open("sample-playlists/master-adv-example-hevc.m3u8")
if err != nil {
t.Fatal(err)
}
p := NewMasterPlaylist()
err = p.DecodeFrom(bufio.NewReader(f), false)
if err != nil {
t.Fatal(err)
}
var audio []*Alternative
for _, v := range p.Variants {
for _, a := range v.Alternatives {
if a.Type == "AUDIO" {
audio = append(audio, a)
}
}
}
if len(audio) != 3 {
t.Fatalf("expected 6 audio renditions got=%d", len(audio))
}
for _, a := range audio {
var expectedChannels string
switch a.GroupId {
case "a1":
expectedChannels = "2"
case "a2", "a3":
expectedChannels = "6"
default:
t.Fatalf("unexpected audio GROUP-ID=%q", a.GroupId)
}
if a.Channels != expectedChannels {
t.Fatalf("incorrect channels attriute expected=%q got=%q GROUP-ID=%q", expectedChannels, a.Channels, a.GroupId)
}
}
}

/****************************
* Begin Test MediaPlaylist *
****************************/
Expand Down Expand Up @@ -564,6 +602,32 @@ func TestMediaPlaylistWithOATCLSSCTE35Tag(t *testing.T) {
}
}

func TestMediaPlaylistWithCueSCTE35Tag(t *testing.T) {
f, err := ioutil.ReadFile("sample-playlists/media-playlist-with-cue-scte35.m3u8")
if err != nil {
t.Fatal(err)
}
p, _, err := DecodeFrom(bytes.NewReader(f), true)
if err != nil {
t.Fatal(err)
}
pp := p.(*MediaPlaylist)

expect := map[int]*SCTE{
2: {Syntax: SCTE35_CUE, CueType: SCTE35Cue_Start, Time: 18},
3: {Syntax: SCTE35_CUE, CueType: SCTE35Cue_Mid, Time: 6.0, Elapsed: 6.0},
4: {Syntax: SCTE35_CUE, CueType: SCTE35Cue_Mid, Time: 6.0, Elapsed: 12.0},
5: {Syntax: SCTE35_CUE, CueType: SCTE35Cue_End},
}
for i := 0; i < int(pp.Count()); i++ {
if !reflect.DeepEqual(pp.Segments[i].SCTE, expect[i]) {
t.Errorf("CUE SCTE35 segment %v (uri: %v)\ngot: %#v\nexp: %#v",
i, pp.Segments[i].URI, pp.Segments[i].SCTE, expect[i],
)
}
}
}

func TestDecodeMediaPlaylistWithDiscontinuitySeq(t *testing.T) {
f, err := os.Open("sample-playlists/media-playlist-with-discontinuity-seq.m3u8")
if err != nil {
Expand Down
Loading