Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7f473e0

Browse files
Merge pull request #33 from martinlindhe/multi-periods
Multi periods
2 parents d312eef + 0256ea1 commit 7f473e0

File tree

12 files changed

+355
-103
lines changed

12 files changed

+355
-103
lines changed

‎Makefile‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,29 @@ ifdef CIRCLE_ARTIFACTS
55
endif
66

77
all: test cover
8+
89
fmt:
910
find . -not -path "./vendor/*" -name '*.go' -type f | sed 's#\(.*\)/.*#1円#' | sort -u | xargs -n1 -I {} bash -c "cd {} && goimports -w *.go && gofmt -w -s -l *.go"
11+
1012
test:
1113
if [ ! -d coverage ]; then mkdir coverage; fi
1214
go test -v ./mpd -race -cover -coverprofile=$(COVERAGEDIR)/mpd.coverprofile
15+
1316
cover:
1417
go tool cover -html=$(COVERAGEDIR)/mpd.coverprofile -o $(COVERAGEDIR)/mpd.html
18+
1519
tc: test cover
20+
1621
coveralls:
1722
gover $(COVERAGEDIR) $(COVERAGEDIR)/coveralls.coverprofile
1823
goveralls -coverprofile=$(COVERAGEDIR)/coveralls.coverprofile -service=circle-ci -repotoken=$(COVERALLS_TOKEN)
24+
1925
clean:
2026
go clean
2127
rm -rf coverage/
28+
2229
examples-live:
2330
go run examples/live.go
31+
2432
examples-ondemand:
2533
go run examples/ondemand.go

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ go install ./...
2727
* Audio
2828
* Video
2929
* Subtitles
30+
* Multiple periods (multi-part playlist)
3031
* DRM (ContentProtection)
3132
* PlayReady
3233
* Widevine
3334

3435
## Known Limitations (for now) (PRs welcome)
3536

36-
* Single Period
3737
* No PSSH/PRO generation
3838
* Limited Profile Support
3939

‎mpd/duration.go‎

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// based on code from golang src/time/time.go
2+
3+
package mpd
4+
5+
import (
6+
"encoding/xml"
7+
"time"
8+
)
9+
10+
type Duration time.Duration
11+
12+
func (d Duration) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
13+
return xml.Attr{name, d.String()}, nil
14+
}
15+
16+
// String renders a Duration in XML Duration Data Type format
17+
func (d *Duration) String() string {
18+
// Largest time is 2540400h10m10.000000000s
19+
var buf [32]byte
20+
w := len(buf)
21+
22+
u := uint64(*d)
23+
neg := *d < 0
24+
if neg {
25+
u = -u
26+
}
27+
28+
if u < uint64(time.Second) {
29+
// Special case: if duration is smaller than a second,
30+
// use smaller units, like 1.2ms
31+
var prec int
32+
w--
33+
buf[w] = 'S'
34+
w--
35+
if u == 0 {
36+
return "PT0S"
37+
}
38+
/*
39+
switch {
40+
case u < uint64(Millisecond):
41+
// print microseconds
42+
prec = 3
43+
// U+00B5 'μ' micro sign == 0xC2 0xB5
44+
w-- // Need room for two bytes.
45+
copy(buf[w:], "μ")
46+
default:
47+
// print milliseconds
48+
prec = 6
49+
buf[w] = 'm'
50+
}
51+
*/
52+
w, u = fmtFrac(buf[:w], u, prec)
53+
w = fmtInt(buf[:w], u)
54+
} else {
55+
w--
56+
buf[w] = 'S'
57+
58+
w, u = fmtFrac(buf[:w], u, 9)
59+
60+
// u is now integer seconds
61+
w = fmtInt(buf[:w], u%60)
62+
u /= 60
63+
64+
// u is now integer minutes
65+
if u > 0 {
66+
w--
67+
buf[w] = 'M'
68+
w = fmtInt(buf[:w], u%60)
69+
u /= 60
70+
71+
// u is now integer hours
72+
// Stop at hours because days can be different lengths.
73+
if u > 0 {
74+
w--
75+
buf[w] = 'H'
76+
w = fmtInt(buf[:w], u)
77+
}
78+
}
79+
}
80+
81+
if neg {
82+
w--
83+
buf[w] = '-'
84+
}
85+
86+
return "PT" + string(buf[w:])
87+
}
88+
89+
// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the
90+
// tail of buf, omitting trailing zeros. it omits the decimal
91+
// point too when the fraction is 0. It returns the index where the
92+
// output bytes begin and the value v/10**prec.
93+
func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
94+
// Omit trailing zeros up to and including decimal point.
95+
w := len(buf)
96+
print := false
97+
for i := 0; i < prec; i++ {
98+
digit := v % 10
99+
print = print || digit != 0
100+
if print {
101+
w--
102+
buf[w] = byte(digit) + '0'
103+
}
104+
v /= 10
105+
}
106+
if print {
107+
w--
108+
buf[w] = '.'
109+
}
110+
return w, v
111+
}
112+
113+
// fmtInt formats v into the tail of buf.
114+
// It returns the index where the output begins.
115+
func fmtInt(buf []byte, v uint64) int {
116+
w := len(buf)
117+
if v == 0 {
118+
w--
119+
buf[w] = '0'
120+
} else {
121+
for v > 0 {
122+
w--
123+
buf[w] = byte(v%10) + '0'
124+
v /= 10
125+
}
126+
}
127+
return w
128+
}

‎mpd/duration_test.go‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package mpd
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestDuration(t *testing.T) {
11+
in := map[string]string{
12+
"0s": "PT0S",
13+
"6m16s": "PT6M16S",
14+
"1.97s": "PT1.97S",
15+
}
16+
for ins, ex := range in {
17+
timeDur, err := time.ParseDuration(ins)
18+
assert.Equal(t, nil, err)
19+
dur := Duration(timeDur)
20+
assert.Equal(t, ex, dur.String())
21+
}
22+
}

‎mpd/fixtures/hbbtv_profile.mpd‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
1212
</ContentProtection>
1313
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
14+
<SegmentTemplate duration="1968" initialization="$RepresentationID$/audio/en/init.mp4" media="$RepresentationID$/audio/en/seg-$Number$.m4f" startNumber="0" timescale="1000"></SegmentTemplate>
1415
<Representation audioSamplingRate="44100" bandwidth="67095" codecs="mp4a.40.2" id="800">
1516
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
1617
</Representation>
@@ -25,6 +26,7 @@
2526
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
2627
</ContentProtection>
2728
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
29+
<SegmentTemplate duration="1968" initialization="$RepresentationID$/video/1/init.mp4" media="$RepresentationID$/video/1/seg-$Number$.m4f" startNumber="0" timescale="1000"></SegmentTemplate>
2830
<Representation bandwidth="1518664" codecs="avc1.4d401f" frameRate="30000/1001" height="540" id="800" width="960"></Representation>
2931
<Representation bandwidth="1911775" codecs="avc1.4d401f" frameRate="30000/1001" height="576" id="1000" width="1024"></Representation>
3032
<Representation bandwidth="2295158" codecs="avc1.4d401f" frameRate="30000/1001" height="576" id="1200" width="1024"></Representation>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /