forked from grafov/m3u8
-
Notifications
You must be signed in to change notification settings - Fork 1
/
structure.go
359 lines (330 loc) · 13.2 KB
/
structure.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
package m3u8
/*
Part of M3U8 parser & generator library.
This file defines data structures related to package.
Copyright 2013-2017 The Project Developers.
See the AUTHORS and LICENSE files at the top-level directory of this distribution
and at https://github.com/grafov/m3u8/
ॐ तारे तुत्तारे तुरे स्व
*/
import (
"bytes"
"io"
"time"
)
const (
/*
Compatibility rules described in section 7:
Clients and servers MUST implement protocol version 2 or higher to use:
o The IV attribute of the EXT-X-KEY tag.
Clients and servers MUST implement protocol version 3 or higher to use:
o Floating-point EXTINF duration values.
Clients and servers MUST implement protocol version 4 or higher to use:
o The EXT-X-BYTERANGE tag.
o The EXT-X-I-FRAME-STREAM-INF tag.
o The EXT-X-I-FRAMES-ONLY tag.
o The EXT-X-MEDIA tag.
o The AUDIO and VIDEO attributes of the EXT-X-STREAM-INF tag.
*/
minver = uint8(3)
// DATETIME represents format of the timestamps in encoded
// playlists. Format for EXT-X-PROGRAM-DATE-TIME defined in
// section 3.4.5
DATETIME = time.RFC3339Nano
)
// ListType is type of the playlist.
type ListType uint
const (
// use 0 for not defined type
MASTER ListType = iota + 1
MEDIA
)
// MediaType is the type for EXT-X-PLAYLIST-TYPE tag
type MediaType uint
const (
// use 0 for not defined type
EVENT MediaType = iota + 1
VOD
)
// SCTE35Syntax defines the format of the SCTE-35 cue points which do not use
// the draft-pantos-http-live-streaming-19 EXT-X-DATERANGE tag and instead
// have their own custom tags
type SCTE35Syntax uint
const (
// SCTE35_67_2014 will be the default due to backwards compatibility reasons.
SCTE35_67_2014 SCTE35Syntax = iota // SCTE35_67_2014 defined in http://www.scte.org/documents/pdf/standards/SCTE%2067%202014.pdf
SCTE35_OATCLS // SCTE35_OATCLS is a non-standard but common format
SCTE35_SIMPLECUES // SCTE35_SIMPLECUE non standard, commmon format for google dai https://support.google.com/admanager/answer/7245661?hl=en&ref_topic=7335768#zippy=%2Ccue-outcue-in
)
// SCTE35CueType defines the type of cue point, used by readers and writers to
// write a different syntax
type SCTE35CueType uint
const (
SCTE35Cue_Start SCTE35CueType = iota // SCTE35Cue_Start indicates an out cue point
SCTE35Cue_Mid // SCTE35Cue_Mid indicates a segment between start and end cue points
SCTE35Cue_End // SCTE35Cue_End indicates an in cue point
)
// Twitch type defines the custom tags used by twitch in manifest
type Twitch string
// MediaPlaylist structure represents a single bitrate playlist aka
// media playlist. It related to both a simple media playlists and a
// sliding window media playlists. URI lines in the Playlist point to
// media segments.
//
// Simple Media Playlist file sample:
//
// #EXTM3U
// #EXT-X-VERSION:3
// #EXT-X-TARGETDURATION:5220
// #EXTINF:5219.2,
// http://media.example.com/entire.ts
// #EXT-X-ENDLIST
//
// Sample of Sliding Window Media Playlist, using HTTPS:
//
// #EXTM3U
// #EXT-X-VERSION:3
// #EXT-X-TARGETDURATION:8
// #EXT-X-MEDIA-SEQUENCE:2680
//
// #EXTINF:7.975,
// https://priv.example.com/fileSequence2680.ts
// #EXTINF:7.941,
// https://priv.example.com/fileSequence2681.ts
// #EXTINF:7.975,
// https://priv.example.com/fileSequence2682.ts
type MediaPlaylist struct {
TargetDuration float64
SeqNo uint64 // EXT-X-MEDIA-SEQUENCE
Segments []*MediaSegment
Args string // optional arguments placed after URIs (URI?Args)
Iframe bool // EXT-X-I-FRAMES-ONLY
Closed bool // is this VOD (closed) or Live (sliding) playlist?
MediaType MediaType
DiscontinuitySeq uint64 // EXT-X-DISCONTINUITY-SEQUENCE
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
head uint // head of FIFO, we add segments to head
tail uint // tail of FIFO, we remove segments from tail
count uint // number of segments added to the playlist
buf bytes.Buffer
ver uint8
// Deprecated: Key will be removed in a future version.
// Use Keys instead. HLS spec supports FairePlay, Widevine, and PlayReady Keys on the same manifest.
Key *Key // EXT-X-KEY is optional encryption key displayed before any segments (default key for the playlist)
Keys []*Key // EXT-X-KEY is optional encryption key displayed before any segments (default set of keys for the playlist)
Map *Map // EXT-X-MAP is optional tag specifies how to obtain the Media Initialization Section (default map for the playlist)
WV *WV // Widevine related tags outside of M3U8 specs
Twitch []Twitch // non-standard tag for Twitch
Custom map[string]CustomTag
customDecoders []CustomDecoder
Images bool // EXT-X-IMAGES-ONLY
}
// MasterPlaylist structure represents a master playlist which
// combines media playlists for multiple bitrates. URI lines in the
// playlist identify media playlists. Sample of Master Playlist file:
//
// #EXTM3U
// #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000
// http://example.com/low.m3u8
// #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
// http://example.com/mid.m3u8
// #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000
// http://example.com/hi.m3u8
// #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5"
// http://example.com/audio-only.m3u8
type MasterPlaylist struct {
Variants []*Variant
Args string // optional arguments placed after URI (URI?Args)
CypherVersion string // non-standard tag for Widevine (see also WV struct)
Twitch Twitch // non-standard tag for Twitch
buf bytes.Buffer
ver uint8
independentSegments bool
Comments []string
Custom map[string]CustomTag
customDecoders []CustomDecoder
}
// Variant structure represents variants for master playlist.
// Variants included in a master playlist and point to media
// playlists.
type Variant struct {
URI string
Chunklist *MediaPlaylist
VariantParams
}
// VariantParams structure represents additional parameters for a
// variant used in EXT-X-STREAM-INF and EXT-X-I-FRAME-STREAM-INF
type VariantParams struct {
ProgramId uint32
Bandwidth uint32
AverageBandwidth uint32 // EXT-X-STREAM-INF only
Codecs string
Resolution string
Audio string // EXT-X-STREAM-INF only
Video string
Subtitles string // EXT-X-STREAM-INF only
Captions string // EXT-X-STREAM-INF only
Name string // EXT-X-STREAM-INF only (non standard Wowza/JWPlayer extension to name the variant/quality in UA)
Iframe bool // EXT-X-I-FRAME-STREAM-INF
ImageStream bool // EXT-X-IMAGE-STREAM-INF
VideoRange string
HDCPLevel string
SupplementalCodecs string
FrameRate float64 // EXT-X-STREAM-INF
Alternatives []*Alternative // EXT-X-MEDIA
}
// Alternative structure represents EXT-X-MEDIA tag in variants.
type Alternative struct {
GroupId string
URI string
Type string
Language string
Name string
Default bool
Autoselect string
Forced string
Characteristics string
Subtitles string
InstreamID string
Channels string // Keeping as a string due to the quotes used in the m3u8 file
Index int
}
// MediaSegment structure represents a media segment included in a
// media playlist. Media segment may be encrypted. Widevine supports
// own tags for encryption metadata.
type MediaSegment struct {
SeqId uint64
Title string // optional second parameter for EXTINF tag
URI string
Duration float64 // first parameter for EXTINF tag; duration must be integers if protocol version is less than 3 but we are always keep them float
Limit int64 // EXT-X-BYTERANGE <n> is length in bytes for the file under URI
Offset int64 // EXT-X-BYTERANGE [@o] is offset from the start of the file under URI
// Deprecated: Key will be removed in a future version.
// Use Keys instead. HLS spec supports FairePlay, Widevine, and PlayReady Keys on the same manifest.
Key *Key // EXT-X-KEY displayed before the segment and means changing of encryption key (in theory each segment may have own key)
Keys []*Key // EXT-X-KEY displayed before the segment and means changing of encryption key (in theory each segment may have own set of keys)
Map *Map // EXT-X-MAP displayed before the segment
Discontinuity bool // EXT-X-DISCONTINUITY indicates an encoding discontinuity between the media segment that follows it and the one that preceded it (i.e. file format, number and type of tracks, encoding parameters, encoding sequence, timestamp sequence)
SCTE *SCTE // SCTE-35 used for Ad signaling in HLS
ProgramDateTime time.Time // EXT-X-PROGRAM-DATE-TIME tag associates the first sample of a media segment with an absolute date and/or time
Custom map[string]CustomTag
CustomSubTag CustomTag // Adds custom tag under the media segment
}
// SCTE holds custom, non EXT-X-DATERANGE, SCTE-35 tags
type SCTE struct {
Syntax SCTE35Syntax // Syntax defines the format of the SCTE-35 cue tag
CueType SCTE35CueType // CueType defines whether the cue is a start, mid, end (if applicable)
Cue string
ID string
Time float64
Elapsed float64
CAID string
}
// Key structure represents information about stream encryption.
//
// Realizes EXT-X-KEY tag.
type Key struct {
Method string
URI string
IV string
Keyformat string
Keyformatversions string
KeyID string
}
// Map structure represents specifies how to obtain the Media
// Initialization Section required to parse the applicable
// Media Segments.
//
// It applied to every Media Segment that appears after it in the
// Playlist until the next EXT-X-MAP tag or until the end of the
// playlist.
//
// Realizes EXT-MAP tag.
type Map struct {
URI string
Limit int64 // <n> is length in bytes for the file under URI
Offset int64 // [@o] is offset from the start of the file under URI
}
// WV structure represents metadata for Google Widevine playlists.
// This format not described in IETF draft but provied by Widevine Live Packager as
// additional tags with #WV-prefix.
type WV struct {
AudioChannels uint
AudioFormat uint
AudioProfileIDC uint
AudioSampleSize uint
AudioSamplingFrequency uint
CypherVersion string
ECM string
VideoFormat uint
VideoFrameRate uint
VideoLevelIDC uint
VideoProfileIDC uint
VideoResolution string
VideoSAR string
}
// Playlist interface applied to various playlist types.
type Playlist interface {
Encode() *bytes.Buffer
Decode(bytes.Buffer, bool) error
DecodeFrom(reader io.Reader, strict bool) error
WithCustomDecoders([]CustomDecoder) Playlist
String() string
}
// CustomDecoder interface for decoding custom and unsupported tags
type CustomDecoder interface {
// TagName should return the full indentifier including the leading '#' as well as the
// trailing ':' if the tag also contains a value or attribute list
TagName() string
// Decode parses a line from the playlist and returns the CustomTag representation
Decode(line string) (CustomTag, error)
// SegmentTag should return true if this CustomDecoder should apply per segment.
// Should returns false if it a MediaPlaylist header tag.
// This value is ignored for MasterPlaylists.
SegmentTag() bool
}
// CustomTag interface for encoding custom and unsupported tags
type CustomTag interface {
// TagName should return the full indentifier including the leading '#' as well as the
// trailing ':' if the tag also contains a value or attribute list
TagName() string
// Encode should return the complete tag string as a *bytes.Buffer. This will
// be used by Playlist.Decode to write the tag to the m3u8.
// Return nil to not write anything to the m3u8.
Encode() *bytes.Buffer
// String should return the encoded tag as a string.
String() string
}
// Internal structure for decoding a line of input stream with a list type detection
type decodingState struct {
listType ListType
m3u bool
tagWV bool
tagStreamInf bool
tagInf bool
tagSCTE35 bool
tagRange bool
tagDiscontinuity bool
tagProgramDateTime bool
tagKeys bool
tagMap bool
tagTwitch bool
tagCustom bool
programDateTime time.Time
limit int64
offset int64
duration float64
title string
variant *Variant
alternatives map[string][]*Alternative
xkeys []*Key
xmap *Map
scte *SCTE
custom map[string]CustomTag
currentAltIdx int
}