func (m *MPD) AddNewPeriod() *Period {
	if m.period != nil && m.period.ID == "" && m.period.AdaptationSets == nil {
		return m.GetCurrentPeriod()
	}
	period := &Period{}
	m.Periods = append(m.Periods, period)
	m.period = period
	return period
}
AddNewPeriod creates a new Period and make it the currently active one.
package mpd
import (
	"encoding/base64"
	"encoding/hex"
	"encoding/xml"
	"errors"
	"fmt"
	"strings"
	"time"
	. "github.com/zencoder/go-dash/v3/helpers/ptrs"
)
type DashProfile string
const (
	DASH_PROFILE_LIVE DashProfile = "urn:mpeg:dash:profile:isoff-live:2011"
	DASH_PROFILE_ONDEMAND DashProfile = "urn:mpeg:dash:profile:isoff-on-demand:2011"
	DASH_PROFILE_HBBTV_1_5_LIVE DashProfile = "urn:hbbtv:dash:profile:isoff-live:2012,urn:mpeg:dash:profile:isoff-live:2011"
)
type AudioChannelConfigurationScheme string
const (
	AUDIO_CHANNEL_CONFIGURATION_MPEG_DASH AudioChannelConfigurationScheme = "urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
	AUDIO_CHANNEL_CONFIGURATION_MPEG_DOLBY AudioChannelConfigurationScheme = "tag:dolby.com,2014:dash:audio_channel_configuration:2011"
)
type AccessibilityElementScheme string
const ACCESSIBILITY_ELEMENT_SCHEME_DESCRIPTIVE_AUDIO AccessibilityElementScheme = "urn:tva:metadata:cs:AudioPurposeCS:2007"
const (
	DASH_MIME_TYPE_VIDEO_MP4     string = "video/mp4"
	DASH_MIME_TYPE_AUDIO_MP4     string = "audio/mp4"
	DASH_MIME_TYPE_SUBTITLE_VTT  string = "text/vtt"
	DASH_MIME_TYPE_SUBTITLE_TTML string = "application/ttaf+xml"
	DASH_MIME_TYPE_SUBTITLE_SRT  string = "application/x-subrip"
	DASH_MIME_TYPE_SUBTITLE_DFXP string = "application/ttaf+xml"
	DASH_MIME_TYPE_IMAGE_JPEG    string = "image/jpeg"
	DASH_CONTENT_TYPE_IMAGE      string = "image"
)
var (
	ErrNoDASHProfileSet               error = errors.New("No DASH profile set")
	ErrAdaptationSetNil                     = errors.New("Adaptation Set nil")
	ErrSegmentTemplateLiveProfileOnly       = errors.New("Segment template can only be used with Live Profile")
	ErrSegmentTemplateNil                   = errors.New("Segment Template nil ")
	ErrRepresentationNil                    = errors.New("Representation nil")
	ErrAccessibilityNil                     = errors.New("Accessibility nil")
	ErrBaseURLEmpty                         = errors.New("Base URL empty")
	ErrSegmentBaseOnDemandProfileOnly       = errors.New("Segment Base can only be used with On-Demand Profile")
	ErrSegmentBaseNil                       = errors.New("Segment Base nil")
	ErrAudioChannelConfigurationNil         = errors.New("Audio Channel Configuration nil")
	ErrInvalidDefaultKID                    = errors.New("Invalid Default KID string, should be 32 characters")
	ErrPROEmpty                             = errors.New("PlayReady PRO empty")
	ErrContentProtectionNil                 = errors.New("Content Protection nil")
)
type MPD struct {
	XMLNs                      *string    `xml:"xmlns,attr"`
	Scte35NS                   *Scte35NS  `xml:"scte35,attr,omitempty"`
	XsiNS                      *XmlnsAttr `xml:"xsi,attr,omitempty"`
	XsiSchemaLocation          *XsiSL     `xml:"schemaLocation,attr,omitempty"`
	XsiCENC                    *XmlnsAttr `xml:"cenc,attr,omitempty"`
	XsiMSPR                    *XmlnsAttr `xml:"mspr,attr,omitempty"`
	Profiles                   *string    `xml:"profiles,attr"`
	Type                       *string    `xml:"type,attr"`
	MediaPresentationDuration  *string    `xml:"mediaPresentationDuration,attr"`
	MinBufferTime              *string    `xml:"minBufferTime,attr"`
	AvailabilityStartTime      *string    `xml:"availabilityStartTime,attr,omitempty"`
	MinimumUpdatePeriod        *string    `xml:"minimumUpdatePeriod,attr"`
	PublishTime                *string    `xml:"publishTime,attr"`
	TimeShiftBufferDepth       *string    `xml:"timeShiftBufferDepth,attr"`
	SuggestedPresentationDelay *Duration  `xml:"suggestedPresentationDelay,attr,omitempty"`
	BaseURL                    string     `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"`
}
type XmlnsAttr struct {
	XmlName xml.Name
	Value   string
}
func (s *XmlnsAttr) UnmarshalXMLAttr(attr xml.Attr) error {
	s.XmlName = attr.Name
	s.Value = attr.Value
	return nil
}
func (s *XmlnsAttr) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
	return xml.Attr{Name: xml.Name{Local: fmt.Sprintf("xmlns:%s", s.XmlName.Local)}, Value: s.Value}, nil
}
type XsiSL struct {
	XmlName xml.Name
	Value   string
}
func (s *XsiSL) UnmarshalXMLAttr(attr xml.Attr) error {
	s.XmlName = attr.Name
	s.Value = attr.Value
	return nil
}
func (s *XsiSL) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
	if strings.Contains(s.XmlName.Local, "schemaLocation") {
		return xml.Attr{Name: xml.Name{Local: "xsi:schemaLocation"}, Value: s.Value}, nil
	}
	return xml.Attr{}, nil
}
type Period struct {
	SupplementalProperty []DescriptorType `xml:"SupplementalProperty,omitempty"`
	ID                   string           `xml:"id,attr,omitempty"`
	Duration             Duration         `xml:"duration,attr,omitempty"`
	Start                *Duration        `xml:"start,attr,omitempty"`
	BaseURL              string           `xml:"BaseURL,omitempty"`
	SegmentBase          *SegmentBase     `xml:"SegmentBase,omitempty"`
	SegmentList          *SegmentList     `xml:"SegmentList,omitempty"`
	SegmentTemplate      *SegmentTemplate `xml:"SegmentTemplate,omitempty"`
	AdaptationSets       []*AdaptationSet `xml:"AdaptationSet,omitempty"`
	EventStreams         []EventStream    `xml:"EventStream,omitempty"`
}
type DescriptorType struct {
	SchemeIDURI *string `xml:"schemeIdUri,attr"`
	Value       *string `xml:"value,attr"`
	ID          *string `xml:"id,attr"`
}
type CommonAttributesAndElements struct {
	Profiles                  *string            `xml:"profiles,attr"`
	Width                     *string            `xml:"width,attr"`
	Height                    *string            `xml:"height,attr"`
	Sar                       *string            `xml:"sar,attr"`
	FrameRate                 *string            `xml:"frameRate,attr"`
	AudioSamplingRate         *string            `xml:"audioSamplingRate,attr"`
	MimeType                  *string            `xml:"mimeType,attr"`
	SegmentProfiles           *string            `xml:"segmentProfiles,attr"`
	Codecs                    *string            `xml:"codecs,attr"`
	MaximumSAPPeriod          *string            `xml:"maximumSAPPeriod,attr"`
	StartWithSAP              *int64             `xml:"startWithSAP,attr"`
	SubsegmentStartsWithSAP   *int64             `xml:"subsegmentStartsWithSAP,attr,omitempty"`
	MaxPlayoutRate            *string            `xml:"maxPlayoutRate,attr"`
	ScanType                  *string            `xml:"scanType,attr"`
	FramePacking              []DescriptorType   `xml:"FramePacking,omitempty"`
	AudioChannelConfiguration []DescriptorType   `xml:"AudioChannelConfiguration,omitempty"`
	ContentProtection         contentProtections `xml:"ContentProtection,omitempty"`
	EssentialProperty         []DescriptorType   `xml:"EssentialProperty,omitempty"`
	SupplementalProperty      []DescriptorType   `xml:"SupplementalProperty,omitempty"`
	InbandEventStream         *DescriptorType    `xml:"inbandEventStream,attr"`
}
type contentProtections []ContentProtectioner
func (as *contentProtections) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var scheme string
	for _, a := range start.Attr {
		if a.Name.Local == "schemeIdUri" {
			scheme = a.Value
			break
		}
	}
	var target ContentProtectioner
	switch scheme {
	case CONTENT_PROTECTION_ROOT_SCHEME_ID_URI:
		target = &CENCContentProtection{}
	case CONTENT_PROTECTION_PLAYREADY_SCHEME_ID:
		target = &PlayreadyContentProtection{}
	case CONTENT_PROTECTION_WIDEVINE_SCHEME_ID:
		target = &WidevineContentProtection{}
	default:
		target = &ContentProtection{}
	}
	if err := d.DecodeElement(target, &start); err != nil {
		return err
	}
	*as = append(*as, target)
	return nil
}
type wrappedAdaptationSet AdaptationSet
type dtoAdaptationSet struct {
	wrappedAdaptationSet
	ContentProtection contentProtections `xml:"ContentProtection,omitempty"`
}
type AdaptationSet struct {
	CommonAttributesAndElements
	XMLName             xml.Name          `xml:"AdaptationSet"`
	ID                  *string           `xml:"id,attr"`
	SegmentAlignment    *bool             `xml:"segmentAlignment,attr"`
	SubsegmentAlignment *bool             `xml:"subsegmentAlignment,attr,omitempty"`
	BitstreamSwitching  *bool             `xml:"bitstreamSwitching,attr,omitempty"`
	Lang                *string           `xml:"lang,attr"`
	Group               *string           `xml:"group,attr"`
	PAR                 *string           `xml:"par,attr"`
	MinBandwidth        *string           `xml:"minBandwidth,attr"`
	MaxBandwidth        *string           `xml:"maxBandwidth,attr"`
	MinWidth            *string           `xml:"minWidth,attr"`
	MaxWidth            *string           `xml:"maxWidth,attr"`
	MinHeight           *string           `xml:"minHeight,attr"`
	MaxHeight           *string           `xml:"maxHeight,attr"`
	ContentType         *string           `xml:"contentType,attr"`
	SelectionPriority   *uint64           `xml:"selectionPriority,attr"`
	Roles               []*Role           `xml:"Role,omitempty"`
	SegmentBase         *SegmentBase      `xml:"SegmentBase,omitempty"`
	SegmentList         *SegmentList      `xml:"SegmentList,omitempty"`
	SegmentTemplate     *SegmentTemplate  `xml:"SegmentTemplate,omitempty"`  
	Representations     []*Representation `xml:"Representation,omitempty"`
	AccessibilityElems  []*Accessibility  `xml:"Accessibility,omitempty"`
}
func (as *AdaptationSet) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var n dtoAdaptationSet
	if err := d.DecodeElement(&n, &start); err != nil {
		return err
	}
	*as = AdaptationSet(n.wrappedAdaptationSet)
	as.ContentProtection = make([]ContentProtectioner, len(n.ContentProtection))
	for i := range n.ContentProtection {
		as.ContentProtection[i] = n.ContentProtection[i]
	}
	return nil
}
const (
	CONTENT_PROTECTION_ROOT_SCHEME_ID_URI       = "urn:mpeg:dash:mp4protection:2011"
	CONTENT_PROTECTION_ROOT_VALUE               = "cenc"
	CENC_XMLNS                                  = "urn:mpeg:cenc:2013"
	CONTENT_PROTECTION_WIDEVINE_SCHEME_ID       = "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"
	CONTENT_PROTECTION_WIDEVINE_SCHEME_HEX      = "edef8ba979d64acea3c827dcd51d21ed"
	CONTENT_PROTECTION_PLAYREADY_SCHEME_ID      = "urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95"
	CONTENT_PROTECTION_PLAYREADY_SCHEME_HEX     = "9a04f07998404286ab92e65be0885f95"
	CONTENT_PROTECTION_PLAYREADY_SCHEME_V10_ID  = "urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95"
	CONTENT_PROTECTION_PLAYREADY_SCHEME_V10_HEX = "79f0049a40988642ab92e65be0885f95"
	CONTENT_PROTECTION_PLAYREADY_XMLNS          = "urn:microsoft:playready"
)
type ContentProtectioner interface {
	ContentProtected()
}
type ContentProtection struct {
	AdaptationSet *AdaptationSet `xml:"-"`
	XMLName       xml.Name       `xml:"ContentProtection"`
	SchemeIDURI   *string        `xml:"schemeIdUri,attr"`  
	XMLNS         *string        `xml:"cenc,attr"`         
	Attrs         []*xml.Attr    `xml:",any,attr"`
}
type CENCContentProtection struct {
	ContentProtection
	DefaultKID *string `xml:"default_KID,attr"`
	Value      *string `xml:"value,attr"`  
}
type PSSH struct {
	XMLNS *string `xml:"cenc,attr"`
	Value *string `xml:",chardata"`
}
type PlayreadyContentProtection struct {
	ContentProtection
	PlayreadyXMLNS *string `xml:"mspr,attr,omitempty"`
	PRO            *string `xml:"pro,omitempty"`
	PSSH           *PSSH   `xml:"pssh,omitempty"`
}
type WidevineContentProtection struct {
	ContentProtection
	PSSH *PSSH `xml:"pssh,omitempty"`
}
type ContentProtectionMarshal struct {
	AdaptationSet *AdaptationSet `xml:"-"`
	XMLName       xml.Name       `xml:"ContentProtection"`
	SchemeIDURI   *string        `xml:"schemeIdUri,attr"`  
	XMLNS         *string        `xml:"xmlns:cenc,attr"`   
	Attrs         []*xml.Attr    `xml:",any,attr"`
}
type CENCContentProtectionMarshal struct {
	ContentProtectionMarshal
	DefaultKID *string `xml:"cenc:default_KID,attr"`
	Value      *string `xml:"value,attr"`  
}
type PSSHMarshal struct {
	XMLNS *string `xml:"xmlns:cenc,attr"`
	Value *string `xml:",chardata"`
}
func psshToMarshal(pssh *PSSH) *PSSHMarshal {
	if pssh == nil {
		return nil
	}
	return &PSSHMarshal{XMLNS: pssh.XMLNS, Value: pssh.Value}
}
type PlayreadyContentProtectionMarshal struct {
	ContentProtectionMarshal
	PlayreadyXMLNS *string      `xml:"xmlns:mspr,attr,omitempty"`
	PRO            *string      `xml:"mspr:pro,omitempty"`
	PSSH           *PSSHMarshal `xml:"cenc:pssh,omitempty"`
}
type WidevineContentProtectionMarshal struct {
	ContentProtectionMarshal
	PSSH *PSSHMarshal `xml:"cenc:pssh,omitempty"`
}
func (s ContentProtection) ContentProtected() {}
func (s ContentProtection) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	err := e.Encode(&ContentProtectionMarshal{
		s.AdaptationSet,
		s.XMLName,
		s.SchemeIDURI,
		s.XMLNS,
		s.Attrs,
	})
	if err != nil {
		return err
	}
	return nil
}
func (s CENCContentProtection) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	err := e.Encode(&CENCContentProtectionMarshal{
		ContentProtectionMarshal{
			s.AdaptationSet,
			s.XMLName,
			s.SchemeIDURI,
			s.XMLNS,
			s.Attrs,
		},
		s.DefaultKID,
		s.Value,
	})
	if err != nil {
		return err
	}
	return nil
}
func (s PlayreadyContentProtection) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	err := e.Encode(&PlayreadyContentProtectionMarshal{
		ContentProtectionMarshal{
			s.AdaptationSet,
			s.XMLName,
			s.SchemeIDURI,
			s.XMLNS,
			s.Attrs,
		},
		s.PlayreadyXMLNS,
		s.PRO,
		psshToMarshal(s.PSSH),
	})
	if err != nil {
		return err
	}
	return nil
}
func (s WidevineContentProtection) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	err := e.Encode(&WidevineContentProtectionMarshal{
		ContentProtectionMarshal{
			s.AdaptationSet,
			s.XMLName,
			s.SchemeIDURI,
			s.XMLNS,
			s.Attrs,
		},
		psshToMarshal(s.PSSH),
	})
	if err != nil {
		return err
	}
	return nil
}
type Role struct {
	AdaptationSet *AdaptationSet `xml:"-"`
	SchemeIDURI   *string        `xml:"schemeIdUri,attr"`
	Value         *string        `xml:"value,attr"`
}
type SegmentTemplate struct {
	AdaptationSet          *AdaptationSet   `xml:"-"`
	SegmentTimeline        *SegmentTimeline `xml:"SegmentTimeline,omitempty"`
	PresentationTimeOffset *uint64          `xml:"presentationTimeOffset,attr,omitempty"`
	Duration               *float64         `xml:"duration,attr"`
	Initialization         *string          `xml:"initialization,attr"`
	Media                  *string          `xml:"media,attr"`
	StartNumber            *int64           `xml:"startNumber,attr"`
	Timescale              *int64           `xml:"timescale,attr"`
}
type Representation struct {
	CommonAttributesAndElements
	AdaptationSet             *AdaptationSet             `xml:"-"`
	AudioChannelConfiguration *AudioChannelConfiguration `xml:"AudioChannelConfiguration,omitempty"`
	AudioSamplingRate         *int64                     `xml:"audioSamplingRate,attr"`    
	Bandwidth                 *int64                     `xml:"bandwidth,attr"`            
	Codecs                    *string                    `xml:"codecs,attr"`               
	FrameRate                 *string                    `xml:"frameRate,attr,omitempty"`  
	Height                    *int64                     `xml:"height,attr"`               
	ID                        *string                    `xml:"id,attr"`                   
	Width                     *int64                     `xml:"width,attr"`                
	BaseURL                   *string                    `xml:"BaseURL,omitempty"`         
	SegmentBase               *SegmentBase               `xml:"SegmentBase,omitempty"`     
	SegmentList               *SegmentList               `xml:"SegmentList,omitempty"`
	SegmentTemplate           *SegmentTemplate           `xml:"SegmentTemplate,omitempty"`
}
type Accessibility struct {
	AdaptationSet *AdaptationSet `xml:"-"`
	SchemeIdUri   *string        `xml:"schemeIdUri,attr,omitempty"`
	Value         *string        `xml:"value,attr,omitempty"`
}
type AudioChannelConfiguration struct {
	SchemeIDURI *string `xml:"schemeIdUri,attr"`
	Value *string `xml:"value,attr"`
}
func NewMPD(profile DashProfile, mediaPresentationDuration, minBufferTime string, attributes ...AttrMPD) *MPD {
	period := &Period{}
	mpd := &MPD{
		XMLNs:                     Strptr("urn:mpeg:dash:schema:mpd:2011"),
		Profiles:                  Strptr((string)(profile)),
		Type:                      Strptr("static"),
		MediaPresentationDuration: Strptr(mediaPresentationDuration),
		MinBufferTime:             Strptr(minBufferTime),
		period:                    period,
		Periods:                   []*Period{period},
	}
	for i := range attributes {
		switch attr := attributes[i].(type) {
		case *attrAvailabilityStartTime:
			mpd.AvailabilityStartTime = attr.GetStrptr()
		}
	}
	return mpd
}
func NewDynamicMPD(profile DashProfile, availabilityStartTime, minBufferTime string, attributes ...AttrMPD) *MPD {
	period := &Period{}
	mpd := &MPD{
		XMLNs:                 Strptr("urn:mpeg:dash:schema:mpd:2011"),
		Profiles:              Strptr((string)(profile)),
		Type:                  Strptr("dynamic"),
		AvailabilityStartTime: Strptr(availabilityStartTime),
		MinBufferTime:         Strptr(minBufferTime),
		period:                period,
		Periods:               []*Period{period},
		UTCTiming:             &DescriptorType{},
	}
	for i := range attributes {
		switch attr := attributes[i].(type) {
		case *attrMinimumUpdatePeriod:
			mpd.MinimumUpdatePeriod = attr.GetStrptr()
		case *attrMediaPresentationDuration:
			mpd.MediaPresentationDuration = attr.GetStrptr()
		}
	}
	return mpd
}