From d5c5deaaef232ff4dbcf033d9075aac301ede80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Einarson?= Date: Thu, 4 Jan 2024 12:00:15 +0100 Subject: [PATCH 1/4] feat: add support for Marlin, and DASH-IF Clear Key elements and name spaces reset test --- CHANGELOG.md | 1 + README.md | 11 ++++++---- mpd/mpd.go | 34 ++++++++++++++++++++++++++++++ mpd/testdata/livesim/README.md | 7 ++++++ mpd/testdata/livesim/multi-drm.mpd | 30 ++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 mpd/testdata/livesim/README.md create mode 100644 mpd/testdata/livesim/multi-drm.mpd diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a86311..0574f6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - GetContentProtections, GetMimeType, GetCodecs, and GetSegmentTemplate methods for AdaptationSet and Representation +- ContentProtection elements and name spaces for Marlin DRM and DASH-IF ClearKey ## [0.10.0] - 2023-05-26 diff --git a/README.md b/README.md index 168f99b..7b35310 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ needed. The main modifications made were: value `false` or be absent * Add type comments and document enum values for certain types * Change names to plural for all subelement slices, e.g. Periods instead of Period -* Add `cenc:pssh` and `mspr:pro` DRM elements +* Add ContentProtection elements and corresponding name spaces ## XML handling @@ -74,13 +74,16 @@ and how the output looks: comes from the XML schema. The order is therefore often different from the input document. 4. Mapping to float numbers may not preserve the exact value of the input. 5. Addition of extra name spaces, such as specific DRM systems must be done explicitly. -6. Durations are mapped to nanoseconds and back. This may change the duration slightly. All trailing zeros +6. In the output, the name-spaces are added to the level where they are used and not at the top MPD level. + The output names are also fixed, and may differ from the input names. +7. Durations are mapped to nanoseconds and back. This may change the duration slightly. All trailing zeros are also removed, as are the minutes and seconds counts if they are zero and a bigger unit is present. ## Tests -The MPD marshaling/unmarshaling is tested by by using many MPDs in the `testdata/schema-mpds` and -`testdata/go-dash-fixtures` directories. See the README.md files in these directorie for their +The MPD marshaling/unmarshaling is tested by by using many MPDs in the `testdata/schema-mpds`, +`testdata/go-dash-fixtures`, and `testdata/livesim` directories. +See the README.md files in these directories for their origins and the small tweaks needed to make durations and some other values consistent after a unmarshaling/marshaling process. diff --git a/mpd/mpd.go b/mpd/mpd.go index db13ad1..5ee97a2 100644 --- a/mpd/mpd.go +++ b/mpd/mpd.go @@ -27,6 +27,13 @@ const ( MIME_TYPE_TTML = "application/ttml+xml" ) +const ( + DRM_CLEAR_KEY_DASHIF = "urn:uuid:e2719d58-a985-b3c9-781a-b030af78d30e" + DRM_PLAYREADY = "urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" + DRM_WIDEVINE = "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" + DRM_MARLIN = "urn:uuid:5e629af5-38dA-4063-8977-97ffbd9902d4" +) + // MPD is MPEG-DASH Media Presentation Description (MPD) as defined in ISO/IEC 23009-1 5'th edition. // // The tree of structs is generated from the corresponding XML Schema at https://github.com/MPEGGroup/DASHSchema @@ -510,6 +517,12 @@ type ContentProtectionType struct { Pssh *PsshType `xml:"urn:mpeg:cenc:2013 cenc:pssh,omitempty"` // MSPro is Microsoft PlayReady provisioning data with namespace "urn:microsoft:playready and "prefix "mspr". MSPro *MSProType `xml:"urn:microsoft:playready mspr:pro,omitempty"` + // ClearKey is DASH-IF clear key + ClearKey *ClearKeyType `xml:"http://dashif.org/guidelines/clearKey ck:Laurl,omitempty"` + // LaURL is DASH-IF License Acquisition URL. + LaURL *LaURL `xml:"https://dashif.org/ dashif:laurl,omitempty"` + // MarlinContentIds is Marlin Content Ids containing one or more MarlineContentId elements. + MarlinContentIds *MarlinContentIds `xml:"urn:marlin:mas:1-0:services:schemas:mpd mas:MarlinContentIds,omitempty"` DescriptorType } @@ -523,6 +536,27 @@ type MSProType struct { Value string `xml:",chardata"` } +// ClearKeyType is DASH-IF clear key type +type ClearKeyType struct { + LicType string `xml:"Lic_type,attr"` + Value string `xml:",chardata"` +} + +// LaURL is License Acquisition URL. +type LaURL struct { + Value string `xml:",chardata"` +} + +// MarlinContentIds is Marlin Content Ids containing one or more MarlineContentId elements. +type MarlinContentIds struct { + Cids []*MarlinContentId `xml:"urn:marlin:mas:1-0:services:schemas:mpd mas:MarlinContentId"` +} + +// MarlinContentId is Marlin Content Id. +type MarlinContentId struct { + Value string `xml:",chardata"` +} + // ResyncType is Resynchronization Point. type ResyncType struct { XMLName xml.Name `xml:"Resync"` diff --git a/mpd/testdata/livesim/README.md b/mpd/testdata/livesim/README.md new file mode 100644 index 0000000..c4a49ef --- /dev/null +++ b/mpd/testdata/livesim/README.md @@ -0,0 +1,7 @@ +# livesim test MPDs + +This directory contains extra MPDs for testing that all relevant elements are kept when parsing and writing the MPD. + +* ato-inf.mpd contains an infinite availabilityTimeOffset +* multi-drm.mpd contains DASH-IF clear-key, Marlin, SmoothStreaming and Widevine content protection and corresponding namespaces +* Manifest_thumbs.mpd contains one DASH-IF thumbnail adaptation set diff --git a/mpd/testdata/livesim/multi-drm.mpd b/mpd/testdata/livesim/multi-drm.mpd new file mode 100644 index 0000000..00aab85 --- /dev/null +++ b/mpd/testdata/livesim/multi-drm.mpd @@ -0,0 +1,30 @@ + + + + + + + + http://clearkey.source.org + http://clearkey.source.org + + + + + urn:marlin:kid:121a0fca0f1b475b8910297fa8e0a07e + + + + + mgIAAAEAAQCQAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AeQBnADgAYQBFAGgAcwBQAFcAMABlAEoARQBDAGwALwBxAE8AQwBnAGYAZwA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBIAHQAMwB1AGEAeABYADgAMwA5AHMAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AcABsAGEAeQByAGUAYQBkAHkALgBkAGkAcgBlAGMAdAB0AGEAcABzAC4AbgBlAHQALwBwAHIALwBzAHYAYwAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A + AAACunBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAApqaAgAAAQABAJACPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgB5AGcAOABhAEUAaABzAFAAVwAwAGUASgBFAEMAbAAvAHEATwBDAGcAZgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEgAdAAzAHUAYQB4AFgAOAAzADkAcwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcAA6AC8ALwBwAGwAYQB5AHIAZQBhAGQAeQAuAGQAaQByAGUAYwB0AHQAYQBwAHMALgBuAGUAdAAvAHAAcgAvAHMAdgBjAC8AcgBpAGcAaAB0AHMAbQBhAG4AYQBnAGUAcgAuAGEAcwBtAHgAPAAvAEwAQQBfAFUAUgBMAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= + + + + AAAATHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACwSEBIaD8oPG0dbiRApf6jgoH4aDXdpZGV2aW5lX3Rlc3QiASoIAUjj3JWbBg== + + + + + + From c3df01bc6e58f805d7b21726642bcdd43387b9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Einarson?= Date: Thu, 4 Jan 2024 12:23:39 +0100 Subject: [PATCH 2/4] test: add test file for DASH-IF thumbnails --- mpd/testdata/livesim/Manifest_thumbs.mpd | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 mpd/testdata/livesim/Manifest_thumbs.mpd diff --git a/mpd/testdata/livesim/Manifest_thumbs.mpd b/mpd/testdata/livesim/Manifest_thumbs.mpd new file mode 100644 index 0000000..93913f3 --- /dev/null +++ b/mpd/testdata/livesim/Manifest_thumbs.mpd @@ -0,0 +1,31 @@ + + + + DASH-IF thumbnails manifest. + + https://livesim.dashif.org/livesim/sts_1679656686/sid_fc1c5dae/testpic_2s/ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 8f88a4323c7f359230a230d7189a141d2223a0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Einarson?= Date: Thu, 4 Jan 2024 12:19:28 +0100 Subject: [PATCH 3/4] chore: update dependencies --- go.mod | 8 ++++---- go.sum | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index d31918a..8c99d38 100644 --- a/go.mod +++ b/go.mod @@ -5,16 +5,16 @@ go 1.19 require ( aqwari.net/xml v0.0.0-20210331023308-d9421b293817 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df - github.com/google/go-cmp v0.5.9 - github.com/stretchr/testify v1.8.2 + github.com/google/go-cmp v0.6.0 + github.com/stretchr/testify v1.8.4 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/pretty v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0fddea4..72244fa 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -21,6 +23,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -32,6 +36,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -40,6 +46,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200821192610-3366bbee4705/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 0b01f751af34fd134a35a3208ba73b529fd2f6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Einarson?= Date: Thu, 4 Jan 2024 16:40:04 +0100 Subject: [PATCH 4/4] fix: RepresentationBaseType first in AdaptationSet and Representation fix test --- CHANGELOG.md | 4 ++ mpd/mpd.go | 111 ++++++++++++++++++++++++------------------------ mpd/mpd_test.go | 14 ++++-- 3 files changed, 70 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0574f6c..e83c092 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - GetContentProtections, GetMimeType, GetCodecs, and GetSegmentTemplate methods for AdaptationSet and Representation - ContentProtection elements and name spaces for Marlin DRM and DASH-IF ClearKey +### Fixed + +- ContentProtection and other parts of RepresentationBaseType moved before other elements in AdaptationSet and Representation + ## [0.10.0] - 2023-05-26 ### Changed diff --git a/mpd/mpd.go b/mpd/mpd.go index 5ee97a2..f51df92 100644 --- a/mpd/mpd.go +++ b/mpd/mpd.go @@ -241,41 +241,41 @@ type UIntVWithIDType struct { // AdaptationSetType is AdaptationSet or EmptyAdaptationSet. // Note that XMLName is not set, since the same structure is used also for EmptyAdaptationSet. type AdaptationSetType struct { - XlinkHref string `xml:"xlink:href,attr,omitempty"` - XlinkActuate string `xml:"xlink:actuate,attr,omitempty"` // default is "onRequest" - XlinkType string `xml:"xlink:type,attr,omitempty"` // fixed "simple" - XlinkShow string `xml:"xlink:show,attr,omitempty"` // fixed "embed" - Id *uint32 `xml:"id,attr"` - Group uint32 `xml:"group,attr,omitempty"` - Lang string `xml:"lang,attr,omitempty"` - ContentType RFC6838ContentTypeType `xml:"contentType,attr,omitempty"` - Par RatioType `xml:"par,attr,omitempty"` - MinBandwidth uint32 `xml:"minBandwidth,attr,omitempty"` - MaxBandwidth uint32 `xml:"maxBandwidth,attr,omitempty"` - MinWidth uint32 `xml:"minWidth,attr,omitempty"` - MaxWidth uint32 `xml:"maxWidth,attr,omitempty"` - MinHeight uint32 `xml:"minHeight,attr,omitempty"` - MaxHeight uint32 `xml:"maxHeight,attr,omitempty"` - MinFrameRate string `xml:"minFrameRate,attr,omitempty"` - MaxFrameRate string `xml:"maxFrameRate,attr,omitempty"` - SegmentAlignment bool `xml:"segmentAlignment,attr,omitempty"` // default = false - SubsegmentAlignment bool `xml:"subsegmentAlignment,attr,omitempty"` // default = false - SubsegmentStartsWithSAP uint32 `xml:"subsegmentStartsWithSAP,attr,omitempty"` // default = 0 - BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` - InitializationSetRef *UIntVectorType `xml:"initializationSetRef,attr,omitempty"` - InitializationPrincipal AnyURI `xml:"initializationPrincipal,attr,omitempty"` - Accessibilities []*DescriptorType `xml:"Accessibility"` - Roles []*DescriptorType `xml:"Role"` - Ratings []*DescriptorType `xml:"Rating"` - Viewpoints []*DescriptorType `xml:"Viewpoint"` - ContentComponents []*ContentComponentType `xml:"ContentComponent"` - BaseURLs []*BaseURLType `xml:"BaseURL"` - SegmentBase *SegmentBaseType `xml:"SegmentBase"` - SegmentList *SegmentListType `xml:"SegmentList"` - SegmentTemplate *SegmentTemplateType `xml:"SegmentTemplate"` - Representations []*RepresentationType `xml:"Representation"` - parent *Period `xml:"-"` + XlinkHref string `xml:"xlink:href,attr,omitempty"` + XlinkActuate string `xml:"xlink:actuate,attr,omitempty"` // default is "onRequest" + XlinkType string `xml:"xlink:type,attr,omitempty"` // fixed "simple" + XlinkShow string `xml:"xlink:show,attr,omitempty"` // fixed "embed" + Id *uint32 `xml:"id,attr"` + Group uint32 `xml:"group,attr,omitempty"` + Lang string `xml:"lang,attr,omitempty"` + ContentType RFC6838ContentTypeType `xml:"contentType,attr,omitempty"` + Par RatioType `xml:"par,attr,omitempty"` + MinBandwidth uint32 `xml:"minBandwidth,attr,omitempty"` + MaxBandwidth uint32 `xml:"maxBandwidth,attr,omitempty"` + MinWidth uint32 `xml:"minWidth,attr,omitempty"` + MaxWidth uint32 `xml:"maxWidth,attr,omitempty"` + MinHeight uint32 `xml:"minHeight,attr,omitempty"` + MaxHeight uint32 `xml:"maxHeight,attr,omitempty"` + MinFrameRate string `xml:"minFrameRate,attr,omitempty"` + MaxFrameRate string `xml:"maxFrameRate,attr,omitempty"` + SegmentAlignment bool `xml:"segmentAlignment,attr,omitempty"` // default = false + SubsegmentAlignment bool `xml:"subsegmentAlignment,attr,omitempty"` // default = false + SubsegmentStartsWithSAP uint32 `xml:"subsegmentStartsWithSAP,attr,omitempty"` // default = 0 + BitstreamSwitching *bool `xml:"bitstreamSwitching,attr"` + InitializationSetRef *UIntVectorType `xml:"initializationSetRef,attr,omitempty"` + InitializationPrincipal AnyURI `xml:"initializationPrincipal,attr,omitempty"` RepresentationBaseType + Accessibilities []*DescriptorType `xml:"Accessibility"` + Roles []*DescriptorType `xml:"Role"` + Ratings []*DescriptorType `xml:"Rating"` + Viewpoints []*DescriptorType `xml:"Viewpoint"` + ContentComponents []*ContentComponentType `xml:"ContentComponent"` + BaseURLs []*BaseURLType `xml:"BaseURL"` + SegmentBase *SegmentBaseType `xml:"SegmentBase"` + SegmentList *SegmentListType `xml:"SegmentList"` + SegmentTemplate *SegmentTemplateType `xml:"SegmentTemplate"` + Representations []*RepresentationType `xml:"Representation"` + parent *Period `xml:"-"` } func (a *AdaptationSetType) SetParent(p *Period) { @@ -329,22 +329,23 @@ type ContentComponentType struct { // RepresentationType is Representation. type RepresentationType struct { - XMLName xml.Name `xml:"Representation"` - Id string `xml:"id,attr"` - Bandwidth uint32 `xml:"bandwidth,attr"` - QualityRanking *uint32 `xml:"qualityRanking,attr,omitempty"` - DependencyId *StringVectorType `xml:"dependencyId,attr,omitempty"` - AssociationId *StringVectorType `xml:"associationId,attr,omitempty"` - AssociationType *ListOf4CCType `xml:"associationType,attr,omitempty"` - MediaStreamStructureId *StringVectorType `xml:"mediaStreamStructureId,attr,omitempty"` - BaseURLs []*BaseURLType `xml:"BaseURL"` - ExtendedBandwidths []*ExtendedBandwidthType `xml:"ExtendedBandwidth"` - SubRepresentations []*SubRepresentationType `xml:"SubRepresentation"` - SegmentBase *SegmentBaseType `xml:"SegmentBase"` - SegmentList *SegmentListType `xml:"SegmentList"` - SegmentTemplate *SegmentTemplateType `xml:"SegmentTemplate"` - parent *AdaptationSetType `xml:"-"` // adaptation set + XMLName xml.Name `xml:"Representation"` + Id string `xml:"id,attr"` + Bandwidth uint32 `xml:"bandwidth,attr"` + QualityRanking *uint32 `xml:"qualityRanking,attr,omitempty"` + DependencyId *StringVectorType `xml:"dependencyId,attr,omitempty"` + AssociationId *StringVectorType `xml:"associationId,attr,omitempty"` + AssociationType *ListOf4CCType `xml:"associationType,attr,omitempty"` + MediaStreamStructureId *StringVectorType `xml:"mediaStreamStructureId,attr,omitempty"` RepresentationBaseType + BaseURLs []*BaseURLType `xml:"BaseURL"` + ExtendedBandwidths []*ExtendedBandwidthType `xml:"ExtendedBandwidth"` + SubRepresentations []*SubRepresentationType `xml:"SubRepresentation"` + SegmentBase *SegmentBaseType `xml:"SegmentBase"` + SegmentList *SegmentListType `xml:"SegmentList"` + SegmentTemplate *SegmentTemplateType `xml:"SegmentTemplate"` + parent *AdaptationSetType `xml:"-"` // adaptation set + } func (r *RepresentationType) SetParent(p *AdaptationSetType) { @@ -386,13 +387,13 @@ type ModelPairType struct { // SubRepresentationType is SubRepresentation type SubRepresentationType struct { - XMLName xml.Name `xml:"SubRepresentation"` - Level *uint32 `xml:"level,attr,omitempty"` - DependencyLevel *UIntVectorType `xml:"dependencyLevel,attr,omitempty"` - Bandwidth uint32 `xml:"bandwidth,attr,omitempty"` - ContentComponent *StringVectorType `xml:"contentComponent,attr,omitempty"` - parent *RepresentationType `xml:"-"` + XMLName xml.Name `xml:"SubRepresentation"` + Level *uint32 `xml:"level,attr,omitempty"` + DependencyLevel *UIntVectorType `xml:"dependencyLevel,attr,omitempty"` + Bandwidth uint32 `xml:"bandwidth,attr,omitempty"` + ContentComponent *StringVectorType `xml:"contentComponent,attr,omitempty"` RepresentationBaseType + parent *RepresentationType `xml:"-"` } func (s *SubRepresentationType) SetParent(p *RepresentationType) { diff --git a/mpd/mpd_test.go b/mpd/mpd_test.go index bb5dc47..3f5d628 100644 --- a/mpd/mpd_test.go +++ b/mpd/mpd_test.go @@ -15,6 +15,10 @@ import ( "github.com/stretchr/testify/require" ) +const ( + printProcessMPDFile = "" // Used to see the output of the process even if there is no essential diff +) + func TestDecodeEncodeMPDs(t *testing.T) { testDirs := []string{"testdata/go-dash-fixtures", "testdata/schema-mpds", "testdata/livesim"} for _, testDir := range testDirs { @@ -36,6 +40,10 @@ func TestDecodeEncodeMPDs(t *testing.T) { inTree, err := xmltree.Parse(td) require.NoError(t, err) outTree, err := xmltree.Parse(out) + if fName == printProcessMPDFile { + err := os.WriteFile(fName, out, 0644) + require.NoError(t, err) + } require.NoError(t, err) if !xmltree.Equal(inTree, outTree) { inBuf := bytes.Buffer{} @@ -47,11 +55,9 @@ func TestDecodeEncodeMPDs(t *testing.T) { d := cmp.Diff(inBuf.String(), outBuf.String()) // Note. There is no canonicalization and there may // be comments in the input, so the diff is not minimal. - t.Errorf("non-minimal diff for mpd %s:\n%s\n", fName, d[:400]) - ofh, err := os.Create(fName) + t.Errorf("non-minimal diff for mpd %s:\n%s. Writing file %s\n", fName, d[:400], fName) + err = os.WriteFile(fName, out, 0644) require.NoError(t, err) - _, _ = ofh.Write(out) - ofh.Close() } } }