streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

commit 9d0a9c380ce962f56c141d6db6fdacd7a41bf831
parent a30e111bb1d9e62aac3810e51749241f488e046a
Author: Oliver Lowe <o@olowe.co>
Date:   Thu, 15 May 2025 23:19:36 +1000

m3u8: support parsing EXT-X-MAP tag

Diffstat:
Mm3u8/m3u8.go | 3+++
Mm3u8/segment.go | 42++++++++++++++++++++++++++++++++++++++++--
2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/m3u8/m3u8.go b/m3u8/m3u8.go @@ -126,6 +126,9 @@ func parseEncryptMethod(s string) EncryptMethod { return encryptMethodInvalid } +// Map represents the EXT-X-MAP tag. +// A Map informs of any byte sequences to initialise readers of +// some media formats. type Map struct { URI string ByteRange ByteRange diff --git a/m3u8/segment.go b/m3u8/segment.go @@ -88,6 +88,12 @@ func parseSegment(items chan item, leading item) (*Segment, error) { return nil, fmt.Errorf("parse key: %w", err) } seg.Key = &key + case tagMap: + m, err := parseMap(items) + if err != nil { + return nil, fmt.Errorf("parse map: %w", err) + } + seg.Map = &m default: return nil, fmt.Errorf("parsing %s unsupported", it) } @@ -184,11 +190,43 @@ func parseKey(items chan item) (Key, error) { key.FormatVersions[i] = uint32(n) } default: - return key, fmt.Errorf("TODO %s", it.val) + return key, fmt.Errorf("unexpected attribute %q", it.val) + } + } + } + return key, fmt.Errorf("unexpected end of tag") +} + +func parseMap(items chan item) (Map, error) { + var mmap Map + for it := range items { + switch it.typ { + case itemError: + return mmap, errors.New(it.val) + case itemNewline: + return mmap, nil + case itemAttrName: + v := <-items + if v.typ != itemEquals { + return Map{}, fmt.Errorf("expected %q after %s, got %s", "=", it.typ, v) + } + switch it.val { + case "URI": + v = <-items + mmap.URI = strings.Trim(it.val, `"`) + case "BYTERANGE": + v = <-items + r, err := parseByteRange(v.val) + if err != nil { + return Map{}, fmt.Errorf("parse byte range: %w", err) + } + mmap.ByteRange = r + default: + return Map{}, fmt.Errorf("unexpected attribute %q", it.val) } } } - return key, fmt.Errorf("TODO") + return Map{}, fmt.Errorf("unexpected end of tag") } func writeSegments(w io.Writer, segments []Segment) (n int, err error) {