Skip to content

Commit

Permalink
Merge pull request #131 from fancybits/start-time-offset
Browse files Browse the repository at this point in the history
Add support for EXT-X-START
  • Loading branch information
leikao authored Apr 22, 2019
2 parents 6b811b7 + 3556e7a commit 1d88be5
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 1 deletion.
14 changes: 14 additions & 0 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,20 @@ func decodeLineOfMediaPlaylist(p *MediaPlaylist, wv *WV, state *decodingState, l
if _, err = fmt.Sscanf(line, "#EXT-X-DISCONTINUITY-SEQUENCE:%d", &p.DiscontinuitySeq); strict && err != nil {
return err
}
case strings.HasPrefix(line, "#EXT-X-START:"):
state.listType = MEDIA
for k, v := range decodeParamsLine(line[13:]) {
switch k {
case "TIME-OFFSET":
st, err := strconv.ParseFloat(v, 64)
if err != nil {
return fmt.Errorf("Invalid TIME-OFFSET: %s: %v", v, err)
}
p.StartTime = st
case "PRECISE":
p.StartTimePrecise = v == "YES"
}
}
case strings.HasPrefix(line, "#EXT-X-KEY:"):
state.listType = MEDIA
state.xkey = new(Key)
Expand Down
19 changes: 19 additions & 0 deletions reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,25 @@ func TestDecodeMediaPlaylistWithProgramDateTime(t *testing.T) {
}
}

func TestDecodeMediaPlaylistStartTime(t *testing.T) {
f, err := os.Open("sample-playlists/media-playlist-with-start-time.m3u8")
if err != nil {
t.Fatal(err)
}
p, listType, err := DecodeFrom(bufio.NewReader(f), true)
if err != nil {
t.Fatal(err)
}
pp := p.(*MediaPlaylist)
CheckType(t, pp)
if listType != MEDIA {
t.Error("Sample not recognized as media playlist.")
}
if pp.StartTime != float64(8.0) {
t.Errorf("Media segment StartTime != 8: %f", pp.StartTime)
}
}

/****************
* Benchmarks *
****************/
Expand Down
14 changes: 14 additions & 0 deletions sample-playlists/media-playlist-with-start-time.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-START:TIME-OFFSET=8.0
#EXTINF:10.0,
ad0.ts
#EXTINF:8.0,
ad1.ts
#EXT-X-DISCONTINUITY
#EXTINF:10.0,
movieA.ts
#EXTINF:10.0,
movieB.ts
4 changes: 3 additions & 1 deletion structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ type MediaPlaylist struct {
Closed bool // is this VOD (closed) or Live (sliding) playlist?
MediaType MediaType
DiscontinuitySeq uint64 // EXT-X-DISCONTINUITY-SEQUENCE
durationAsInt bool // output durations as integers of floats?
StartTime float64
StartTimePrecise bool
durationAsInt bool // output durations as integers of floats?
keyformat int
winsize uint // max number of segments displayed in an encoded playlist; need set to zero for VOD playlists
capacity uint // total capacity of slice used for the playlist
Expand Down
8 changes: 8 additions & 0 deletions writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,14 @@ func (p *MediaPlaylist) Encode() *bytes.Buffer {
p.buf.WriteString("#EXT-X-TARGETDURATION:")
p.buf.WriteString(strconv.FormatInt(int64(math.Ceil(p.TargetDuration)), 10)) // due section 3.4.2 of M3U8 specs EXT-X-TARGETDURATION must be integer
p.buf.WriteRune('\n')
if p.StartTime > 0.0 {
p.buf.WriteString("#EXT-X-START:TIME-OFFSET=")
p.buf.WriteString(strconv.FormatFloat(p.StartTime, 'f', -1, 64))
if p.StartTimePrecise {
p.buf.WriteString(",PRECISE=YES")
}
p.buf.WriteRune('\n')
}
if p.DiscontinuitySeq != 0 {
p.buf.WriteString("#EXT-X-DISCONTINUITY-SEQUENCE:")
p.buf.WriteString(strconv.FormatUint(uint64(p.DiscontinuitySeq), 10))
Expand Down
15 changes: 15 additions & 0 deletions writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,21 @@ func TestIndependentSegments(t *testing.T) {
}
}

// Create new media playlist
// Set default map
func TestStartTimeOffset(t *testing.T) {
p, e := NewMediaPlaylist(3, 5)
if e != nil {
t.Fatalf("Create media playlist failed: %s", e)
}
p.StartTime = 3.4

expected := `#EXT-X-START:TIME-OFFSET=3.4`
if !strings.Contains(p.String(), expected) {
t.Fatalf("Media playlist did not contain: %s\nMedia Playlist:\n%v", expected, p.String())
}
}

func TestMediaPlaylist_Slide(t *testing.T) {
m, e := NewMediaPlaylist(3, 4)
if e != nil {
Expand Down

0 comments on commit 1d88be5

Please sign in to comment.