diff --git a/README.md b/README.md index 70983ca..265a414 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# mpd [![GoDoc](https://godoc.org/github.com/mc2soft/mpd?status.svg)](https://godoc.org/github.com/mc2soft/mpd) [![Build Status](https://travis-ci.org/mc2soft/mpd.svg)](https://travis-ci.org/mc2soft/mpd) +# go-dash-mpd [![GoDoc](https://godoc.org/github.com/RamanPndy/go-dash-mpd?status.svg)](https://godoc.org/github.com/RamanPndy/go-dash-mpd) Go library for parsing and generating MPEG-DASH Media Presentation Description (MPD) files. -[Documentation](http://godoc.org/github.com/mc2soft/mpd). +[Documentation](http://godoc.org/github.com/RamanPndy/go-dash-mpd). diff --git a/fixture_elemental_delta_live.mpd b/fixture_elemental_delta_live.mpd index c4c676d..c8ba15e 100644 --- a/fixture_elemental_delta_live.mpd +++ b/fixture_elemental_delta_live.mpd @@ -1,4 +1,4 @@ - + diff --git a/fixture_elemental_delta_vod.mpd b/fixture_elemental_delta_vod.mpd index 44b88fe..2ec0f74 100644 --- a/fixture_elemental_delta_vod.mpd +++ b/fixture_elemental_delta_vod.mpd @@ -1,4 +1,4 @@ - + diff --git a/fixture_elemental_delta_vod_multi_drm.mpd b/fixture_elemental_delta_vod_multi_drm.mpd index 4f33fb4..9e239b9 100644 --- a/fixture_elemental_delta_vod_multi_drm.mpd +++ b/fixture_elemental_delta_vod_multi_drm.mpd @@ -1,4 +1,4 @@ - + diff --git a/fixture_flussonic_live.mpd b/fixture_flussonic_live.mpd index e92cd74..1891c75 100644 --- a/fixture_flussonic_live.mpd +++ b/fixture_flussonic_live.mpd @@ -1,4 +1,4 @@ - + diff --git a/fixture_vod_with_base_url.mpd b/fixture_vod_with_base_url.mpd index 4313339..c6d30d0 100644 --- a/fixture_vod_with_base_url.mpd +++ b/fixture_vod_with_base_url.mpd @@ -1,4 +1,4 @@ - + https://video-1-2/ diff --git a/go.mod b/go.mod index 2da1afe..d510abf 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/mc2soft/mpd +module github.com/RamanPndy/go-dash-mpd go 1.16 diff --git a/mpd.go b/mpd.go index 8586eda..6a6fb34 100644 --- a/mpd.go +++ b/mpd.go @@ -9,7 +9,7 @@ import ( "regexp" "strconv" - copyobj "github.com/mc2soft/mpd/utils" + copyobj "github.com/RamanPndy/go-dash-mpd/utils" ) // http://mpeg.chiariglione.org/standards/mpeg-dash @@ -75,6 +75,7 @@ type MPD struct { PublishTime *string `xml:"publishTime,attr"` Profiles string `xml:"profiles,attr"` XSI *string `xml:"xsi,attr,omitempty"` + Cenc *string `xml:"cenc,attr,omitempty"` SCTE35 *string `xml:"scte35,attr,omitempty"` XSISchemaLocation *string `xml:"schemaLocation,attr"` ID *string `xml:"id,attr"` @@ -86,6 +87,7 @@ type MPD struct { type mpdMarshal struct { XMLName xml.Name `xml:"MPD"` XSI *string `xml:"xmlns:xsi,attr,omitempty"` + Cenc *string `xml:"xmlns:cenc,attr,omitempty"` XMLNS *string `xml:"xmlns,attr"` XSISchemaLocation *string `xml:"xsi:schemaLocation,attr"` ID *string `xml:"id,attr"` @@ -121,7 +123,7 @@ func (m *MPD) Encode() ([]byte, error) { // hacks for self-closing tags res := new(bytes.Buffer) - res.WriteString(``) + res.WriteString(``) res.WriteByte('\n') for { s, err := x.ReadString('\n') @@ -163,58 +165,112 @@ type periodMarshal struct { // AdaptationSet represents XSD's AdaptationSetType. type AdaptationSet struct { - MimeType string `xml:"mimeType,attr"` - SegmentAlignment ConditionalUint `xml:"segmentAlignment,attr"` - StartWithSAP *uint64 `xml:"startWithSAP,attr"` - BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` - SubsegmentAlignment ConditionalUint `xml:"subsegmentAlignment,attr"` - SubsegmentStartsWithSAP *uint64 `xml:"subsegmentStartsWithSAP,attr"` - Lang *string `xml:"lang,attr"` - ContentProtections []DRMDescriptor `xml:"ContentProtection,omitempty"` - Representations []Representation `xml:"Representation,omitempty"` - Codecs *string `xml:"codecs,attr"` + Role *Role `xml:"Role,omitempty"` + MimeType string `xml:"mimeType,attr,omitempty"` + SegmentAlignment ConditionalUint `xml:"segmentAlignment,attr"` + StartWithSAP *uint64 `xml:"startWithSAP,attr"` + BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` + SubsegmentAlignment ConditionalUint `xml:"subsegmentAlignment,attr"` + SubsegmentStartsWithSAP *uint64 `xml:"subsegmentStartsWithSAP,attr"` + Lang *string `xml:"lang,attr"` + ContentProtections []DRMDescriptor `xml:"ContentProtection,omitempty"` + Representations []Representation `xml:"Representation,omitempty"` + Codecs *string `xml:"codecs,attr"` + ContentType string `xml:"contentType,attr,omitempty"` + ID *string `xml:"id,attr"` + Width *string `xml:"width,attr,omitempty"` + Height *string `xml:"height,attr,omitempty"` + MaxWidth *string `xml:"maxWidth,attr,omitempty"` + MaxHeight *string `xml:"maxHeight,attr,omitempty"` + FrameRate *string `xml:"frameRate,attr,omitempty"` + Par *string `xml:"par,attr,omitempty"` + SupplementalProperty *SupplementalProperty `xml:"SupplementalProperty,omitempty"` } type adaptationSetMarshal struct { - MimeType string `xml:"mimeType,attr"` - SegmentAlignment ConditionalUint `xml:"segmentAlignment,attr"` - StartWithSAP *uint64 `xml:"startWithSAP,attr"` - BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` - SubsegmentAlignment ConditionalUint `xml:"subsegmentAlignment,attr"` - SubsegmentStartsWithSAP *uint64 `xml:"subsegmentStartsWithSAP,attr"` - Lang *string `xml:"lang,attr"` - ContentProtections []drmDescriptorMarshal `xml:"ContentProtection,omitempty"` - Representations []representationMarshal `xml:"Representation,omitempty"` - Codecs *string `xml:"codecs,attr"` + Role *roleMarshal `xml:"Role,omitempty"` + MimeType string `xml:"mimeType,attr,omitempty"` + SegmentAlignment ConditionalUint `xml:"segmentAlignment,attr"` + StartWithSAP *uint64 `xml:"startWithSAP,attr"` + BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` + SubsegmentAlignment ConditionalUint `xml:"subsegmentAlignment,attr"` + SubsegmentStartsWithSAP *uint64 `xml:"subsegmentStartsWithSAP,attr"` + Lang *string `xml:"lang,attr"` + ContentProtections []drmDescriptorMarshal `xml:"ContentProtection,omitempty"` + Representations []representationMarshal `xml:"Representation,omitempty"` + Codecs *string `xml:"codecs,attr"` + ContentType string `xml:"contentType,attr,omitempty"` + ID *string `xml:"id,attr"` + Width *string `xml:"width,attr,omitempty"` + Height *string `xml:"height,attr,omitempty"` + MaxWidth *string `xml:"maxWidth,attr,omitempty"` + MaxHeight *string `xml:"maxHeight,attr,omitempty"` + FrameRate *string `xml:"frameRate,attr,omitempty"` + Par *string `xml:"par,attr,omitempty"` + SupplementalProperty *supplementalPropertyMarshal `xml:"SupplementalProperty,omitempty"` +} + +type Role struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` +} + +type roleMarshal struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` +} + +type SupplementalProperty struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` +} + +type supplementalPropertyMarshal struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` } // Representation represents XSD's RepresentationType. type Representation struct { - ID *string `xml:"id,attr"` - Width *uint64 `xml:"width,attr"` - Height *uint64 `xml:"height,attr"` - SAR *string `xml:"sar,attr"` - FrameRate *string `xml:"frameRate,attr"` - Bandwidth *uint64 `xml:"bandwidth,attr"` - AudioSamplingRate *string `xml:"audioSamplingRate,attr"` - Codecs *string `xml:"codecs,attr"` - BaseURL *string `xml:"BaseURL,omitempty"` - ContentProtections []DRMDescriptor `xml:"ContentProtection,omitempty"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` + ID *string `xml:"id,attr"` + Width *uint64 `xml:"width,attr"` + Height *uint64 `xml:"height,attr"` + SAR *string `xml:"sar,attr"` + FrameRate *string `xml:"frameRate,attr"` + Bandwidth *uint64 `xml:"bandwidth,attr"` + AudioSamplingRate *string `xml:"audioSamplingRate,attr"` + Codecs *string `xml:"codecs,attr"` + BaseURL *string `xml:"BaseURL,omitempty"` + ContentProtections []DRMDescriptor `xml:"ContentProtection,omitempty"` + SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` + MimeType string `xml:"mimeType,attr,omitempty"` + AudioChannelConfiguration *AudioChannelConfiguration `xml:"AudioChannelConfiguration,omitempty"` } type representationMarshal struct { - ID *string `xml:"id,attr"` - Width *uint64 `xml:"width,attr"` - Height *uint64 `xml:"height,attr"` - SAR *string `xml:"sar,attr"` - FrameRate *string `xml:"frameRate,attr"` - Bandwidth *uint64 `xml:"bandwidth,attr"` - AudioSamplingRate *string `xml:"audioSamplingRate,attr"` - Codecs *string `xml:"codecs,attr"` - BaseURL *string `xml:"BaseURL,omitempty"` - ContentProtections []drmDescriptorMarshal `xml:"ContentProtection,omitempty"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` + ID *string `xml:"id,attr"` + Width *uint64 `xml:"width,attr"` + Height *uint64 `xml:"height,attr"` + SAR *string `xml:"sar,attr"` + FrameRate *string `xml:"frameRate,attr"` + Bandwidth *uint64 `xml:"bandwidth,attr"` + AudioSamplingRate *string `xml:"audioSamplingRate,attr"` + Codecs *string `xml:"codecs,attr"` + BaseURL *string `xml:"BaseURL,omitempty"` + ContentProtections []drmDescriptorMarshal `xml:"ContentProtection,omitempty"` + SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` + MimeType string `xml:"mimeType,attr,omitempty"` + AudioChannelConfiguration *audioChannelConfigurationMarshal `xml:"AudioChannelConfiguration,omitempty"` +} + +type AudioChannelConfiguration struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` +} + +type audioChannelConfigurationMarshal struct { + SchemeIdUri *string `xml:"schemeIdUri,attr,omitempty"` + Value *string `xml:"value,attr,omitempty"` } // Descriptor represents XSD's DescriptorType. @@ -278,6 +334,7 @@ func modifyMPD(mpd *MPD) *mpdMarshal { XSI: copyobj.String(mpd.XSI), SCTE35: copyobj.String(mpd.SCTE35), XSISchemaLocation: copyobj.String(mpd.XSISchemaLocation), + Cenc: copyobj.String(mpd.Cenc), ID: copyobj.String(mpd.ID), BaseURL: copyobj.String(mpd.BaseURL), Period: modifyPeriod(mpd.Period), @@ -312,6 +369,8 @@ func modifyAdaptationSets(as []*AdaptationSet) []*adaptationSetMarshal { BitstreamSwitching: copyobj.Bool(a.BitstreamSwitching), Codecs: copyobj.String(a.Codecs), Lang: copyobj.String(a.Lang), + ID: copyobj.String(a.ID), + ContentType: a.ContentType, MimeType: a.MimeType, SegmentAlignment: a.SegmentAlignment, StartWithSAP: copyobj.UInt64(a.StartWithSAP), @@ -319,6 +378,14 @@ func modifyAdaptationSets(as []*AdaptationSet) []*adaptationSetMarshal { SubsegmentStartsWithSAP: copyobj.UInt64(a.SubsegmentStartsWithSAP), Representations: modifyRepresentations(a.Representations), ContentProtections: modifyContentProtections(a.ContentProtections), + Role: modifyRole(a.Role), + Width: copyobj.String(a.Width), + Height: copyobj.String(a.Height), + MaxWidth: copyobj.String(a.MaxWidth), + MaxHeight: copyobj.String(a.MaxHeight), + Par: copyobj.String(a.Par), + FrameRate: copyobj.String(a.FrameRate), + SupplementalProperty: modifySupplementalProperty(a.SupplementalProperty), } asm = append(asm, adaptationSet) } @@ -329,17 +396,19 @@ func modifyRepresentations(rs []Representation) []representationMarshal { rsm := make([]representationMarshal, 0, len(rs)) for _, r := range rs { representation := representationMarshal{ - AudioSamplingRate: copyobj.String(r.AudioSamplingRate), - Bandwidth: copyobj.UInt64(r.Bandwidth), - Codecs: copyobj.String(r.Codecs), - FrameRate: copyobj.String(r.FrameRate), - Height: copyobj.UInt64(r.Height), - ID: copyobj.String(r.ID), - Width: copyobj.UInt64(r.Width), - SegmentTemplate: copySegmentTemplate(r.SegmentTemplate), - SAR: copyobj.String(r.SAR), - ContentProtections: modifyContentProtections(r.ContentProtections), - BaseURL: copyobj.String(r.BaseURL), + AudioSamplingRate: copyobj.String(r.AudioSamplingRate), + Bandwidth: copyobj.UInt64(r.Bandwidth), + Codecs: copyobj.String(r.Codecs), + FrameRate: copyobj.String(r.FrameRate), + Height: copyobj.UInt64(r.Height), + ID: copyobj.String(r.ID), + Width: copyobj.UInt64(r.Width), + SegmentTemplate: copySegmentTemplate(r.SegmentTemplate), + SAR: copyobj.String(r.SAR), + ContentProtections: modifyContentProtections(r.ContentProtections), + BaseURL: copyobj.String(r.BaseURL), + MimeType: r.MimeType, + AudioChannelConfiguration: modifyAudioChannelConfiguration(r.AudioChannelConfiguration), } rsm = append(rsm, representation) } @@ -397,3 +466,33 @@ func modifyPssh(p *Pssh) *psshMarshal { Value: copyobj.String(p.Value), } } + +func modifyRole(r *Role) *roleMarshal { + if r == nil { + return nil + } + return &roleMarshal{ + SchemeIdUri: copyobj.String(r.SchemeIdUri), + Value: copyobj.String(r.Value), + } +} + +func modifySupplementalProperty(s *SupplementalProperty) *supplementalPropertyMarshal { + if s == nil { + return nil + } + return &supplementalPropertyMarshal{ + SchemeIdUri: copyobj.String(s.SchemeIdUri), + Value: copyobj.String(s.Value), + } +} + +func modifyAudioChannelConfiguration(a *AudioChannelConfiguration) *audioChannelConfigurationMarshal { + if a == nil { + return nil + } + return &audioChannelConfigurationMarshal{ + SchemeIdUri: copyobj.String(a.SchemeIdUri), + Value: copyobj.String(a.Value), + } +}