Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions mpd/content_steering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,40 @@ func TestStringsToBaseURLsAndBack(t *testing.T) {
require.EqualStringSlice(t, ss, BaseURLsToStrings(b))
}

// ISO/IEC 23009-1 Amd 1 (DASH-MPD.xsd) requires ContentSteering to be the last
// child of MPD. Strict XSD validators reject manifests that emit it earlier.
func TestContentSteeringEmittedAfterPeriodAndUTCTiming(t *testing.T) {
m := NewDynamicMPD(DASH_PROFILE_LIVE, "1970-01-01T00:00:00Z", "PT2S",
AttrMediaPresentationDuration("PT10S"))
m.BaseURL = []BaseURLValue{
{ServiceLocation: "fastly", Value: "https://f.example/x/"},
}
m.ContentSteering = &ContentSteering{
DefaultServiceLocation: Strptr("fastly"),
URI: "https://steer.example/steer",
}
out, err := m.WriteToString()
require.NoError(t, err)

baseURLIdx := strings.Index(out, "<BaseURL")
periodOpenIdx := strings.Index(out, "<Period")
periodCloseIdx := strings.LastIndex(out, "</Period>")
utcIdx := strings.Index(out, "<UTCTiming")
csIdx := strings.Index(out, "<ContentSteering")
if baseURLIdx < 0 || periodOpenIdx < 0 || periodCloseIdx < 0 || utcIdx < 0 || csIdx < 0 {
t.Fatalf("missing expected element in output: %s", out)
}
if !(baseURLIdx < periodOpenIdx) {
t.Fatalf("BaseURL must come before Period: %s", out)
}
if !(csIdx > periodCloseIdx) {
t.Fatalf("ContentSteering must come after </Period>: %s", out)
}
if !(csIdx > utcIdx) {
t.Fatalf("ContentSteering must come after UTCTiming: %s", out)
}
}

func TestReadFromStringWithOptionsAppliesSteeringOptionsForWrite(t *testing.T) {
xml := `<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="static" mediaPresentationDuration="PT10S" minBufferTime="PT2S">
Expand Down
15 changes: 9 additions & 6 deletions mpd/mpd.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ var (
ErrInbandEventStreamSchemeUriEmpty = errors.New("Inband Event Stream schemeIdUri Empty")
)

// MPD is marshaled with encoding/xml (e.g. xml.Encoder.Encode). The marshaller reflects
// on the concrete type and walks exported fields in struct source order, so reordering
// fields changes emitted XML (attributes and child element sequence).
type MPD struct {
XMLNs *string `xml:"xmlns,attr"`
XMLNsDolby *XmlnsAttr `xml:"dolby,attr"`
Expand All @@ -88,14 +91,14 @@ type MPD struct {
PublishTime *string `xml:"publishTime,attr"`
TimeShiftBufferDepth *string `xml:"timeShiftBufferDepth,attr"`
SuggestedPresentationDelay *Duration `xml:"suggestedPresentationDelay,attr,omitempty"`
BaseURL []BaseURLValue `xml:"BaseURL,omitempty"`
ContentSteering *ContentSteering `xml:"ContentSteering,omitempty"`
BaseURL []BaseURLValue `xml:"BaseURL,omitempty"`
Location string `xml:"Location,omitempty"`
period *Period
Periods []*Period `xml:"Period,omitempty"`
UTCTiming *DescriptorType `xml:"UTCTiming,omitempty"`
ID string `xml:"id,attr,omitempty"`
Comment string `xml:"-"`
Periods []*Period `xml:"Period,omitempty"`
UTCTiming *DescriptorType `xml:"UTCTiming,omitempty"`
ContentSteering *ContentSteering `xml:"ContentSteering,omitempty"`
ID string `xml:"id,attr,omitempty"`
Comment string `xml:"-"`
}

type XmlnsAttr struct {
Expand Down
Loading