commit - 1146e3cfa554e40c95835cd5fd7c65eb7afb40aa
commit + a30e111bb1d9e62aac3810e51749241f488e046a
blob - 1944ff91c17ec4b247f369030d6be9974a145ba2
blob + b524a68ce5470a6e0137bb827ed7145edd7d5f99
--- m3u8/m3u8.go
+++ m3u8/m3u8.go
EncryptMethodNone EncryptMethod = 0 + iota
EncryptMethodAES128
EncryptMethodSampleAES
+ encryptMethodInvalid EncryptMethod = 255
)
func (m EncryptMethod) String() string {
return "invalid"
}
+func parseEncryptMethod(s string) EncryptMethod {
+ switch s {
+ case EncryptMethodNone.String():
+ return EncryptMethodNone
+ case EncryptMethodAES128.String():
+ return EncryptMethodAES128
+ case EncryptMethodSampleAES.String():
+ return EncryptMethodSampleAES
+ }
+ return encryptMethodInvalid
+}
+
type Map struct {
URI string
ByteRange ByteRange
blob - 22fc0b281c644f6e25183ceb6de969d198189b80
blob + d019ec22dc533455dad16f1fa9b75bc93bb9732f
--- m3u8/segment.go
+++ m3u8/segment.go
import (
"bytes"
+ "encoding/hex"
"errors"
"fmt"
"io"
return nil, fmt.Errorf("parse segment duration: %w", err)
}
seg.Duration = dur
+ case tagKey:
+ key, err := parseKey(items)
+ if err != nil {
+ return nil, fmt.Errorf("parse key: %w", err)
+ }
+ seg.Key = &key
default:
return nil, fmt.Errorf("parse leading item %s: unsupported", leading)
}
seg.Range = r
case tagDiscontinuity:
seg.Discontinuity = true
+ case tagKey:
+ key, err := parseKey(items)
+ if err != nil {
+ return nil, fmt.Errorf("parse key: %w", err)
+ }
+ seg.Key = &key
default:
return nil, fmt.Errorf("parsing %s unsupported", it)
}
return time.Duration(microseconds) * time.Microsecond, nil
}
+func parseKey(items chan item) (Key, error) {
+ var key Key
+ for it := range items {
+ switch it.typ {
+ case itemError:
+ return key, errors.New(it.val)
+ case itemNewline:
+ return key, nil
+ case itemAttrName:
+ v := <-items
+ if v.typ != itemEquals {
+ return key, fmt.Errorf("expected %q after %s, got %s", "=", it.typ, v)
+ }
+ switch it.val {
+ case "METHOD":
+ v = <-items
+ key.Method = parseEncryptMethod(v.val)
+ if key.Method == encryptMethodInvalid {
+ return key, fmt.Errorf("bad encrypt method %q", v.val)
+ }
+ case "URI":
+ v = <-items
+ key.URI = strings.Trim(v.val, `"`)
+ case "IV":
+ v = <-items
+ b, err := hex.DecodeString(strings.TrimPrefix(v.val, "0x"))
+ if err != nil {
+ return key, fmt.Errorf("parse initialisation vector: %w", err)
+ }
+ if len(b) != len(key.IV) {
+ return key, fmt.Errorf("bad initialisation length %d, want %d", len(b), len(key.IV))
+ }
+ copy(key.IV[:], b)
+ case "KEYFORMAT":
+ v = <-items
+ key.Format = strings.Trim(v.val, `"`)
+ case "KEYFORMATVERSIONS":
+ v = <-items
+ ss := strings.Split(v.val, "/")
+ key.FormatVersions = make([]uint32, len(ss))
+ for i := range ss {
+ n, err := strconv.Atoi(ss[i])
+ if err != nil {
+ return key, fmt.Errorf("parse key format version: %w", err)
+ }
+ key.FormatVersions[i] = uint32(n)
+ }
+ default:
+ return key, fmt.Errorf("TODO %s", it.val)
+ }
+ }
+ }
+ return key, fmt.Errorf("TODO")
+}
+
func writeSegments(w io.Writer, segments []Segment) (n int, err error) {
for i, seg := range segments {
b, err := seg.MarshalText()
blob - 40d13ffe7d9e39b9073e50c523d8d9341d1e6072
blob + c9c777d8c62b46c04c954a12fc84294e87fd250b
--- m3u8/segment_test.go
+++ m3u8/segment_test.go
Key: &Key{
Method: EncryptMethodAES128,
URI: "key1.json?f=1041&s=0&p=1822767&m=1506045858",
- IV: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1B, 0xD0, 0x2F},
+ IV: [...]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1B, 0xD0, 0x2F},
},
URI: "1041_6_1822767.ts?m=1506045858",
}