Skip to content

Commit a79aec8

Browse files
Support Thumbnails (#83)
* thumbnail support * make fmt * typo * revert func main change * add func for adding thumbnails AS with id and seperate schmeuri from rep id * fix example to fix build
1 parent d939395 commit a79aec8

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

examples/ondemand.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ func exampleOndemand() {
3535
subtitleRep, _ := subtitleAS.AddNewRepresentationSubtitle(256, "captions_en")
3636
_ = subtitleRep.SetNewBaseURL("http://example.com/content/sintel/subtitles/subtitles_en.vtt")
3737

38+
thumbnailsAS, _ := m.AddNewAdaptationSetThumbnails(mpd.DASH_MIME_TYPE_IMAGE_JPEG)
39+
_, _ = thumbnailsAS.SetNewSegmentTemplateThumbnails(1801800, "$RepresentationID$/$Number$.jpg", 0, 30000)
40+
_, _ = thumbnailsAS.AddNewRepresentationThumbnails("thumbnails", "5x4","http://dashif.org/guidelines/thumbnail_tile", 50000, 1600, 720)
41+
3842
mpdStr, _ := m.WriteToString()
3943
fmt.Println(mpdStr)
4044
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static" mediaPresentationDuration="PT30S" minBufferTime="PT1.97S">
3+
<Period>
4+
<AdaptationSet mimeType="audio/mp4" startWithSAP="1" segmentAlignment="true" lang="und">
5+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
6+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"></ContentProtection>
7+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:mspr="urn:microsoft:playready">
8+
<mspr:pro>mgIAAAEAAQCQAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AQQBtAGYAagBDAFQATwBQAGIARQBPAGwAMwBXAEQALwA1AG0AYwBlAGMAQQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBCAEcAdwAxAGEAWQBaADEAWQBYAE0APQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AcABsAGEAeQByAGUAYQBkAHkALgBkAGkAcgBlAGMAdAB0AGEAcABzAC4AbgBlAHQALwBwAHIALwBzAHYAYwAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A</mspr:pro>
9+
</ContentProtection>
10+
<Representation audioSamplingRate="44100" bandwidth="128558" codecs="mp4a.40.5" id="800k/audio-und">
11+
<BaseURL>800k/output-audio-und.mp4</BaseURL>
12+
<SegmentBase indexRange="629-756">
13+
<Initialization range="0-628"></Initialization>
14+
</SegmentBase>
15+
</Representation>
16+
</AdaptationSet>
17+
<AdaptationSet mimeType="video/mp4" startWithSAP="1" scanType="progressive" segmentAlignment="true">
18+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
19+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"></ContentProtection>
20+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:mspr="urn:microsoft:playready">
21+
<mspr:pro>mgIAAAEAAQCQAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AQQBtAGYAagBDAFQATwBQAGIARQBPAGwAMwBXAEQALwA1AG0AYwBlAGMAQQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBCAEcAdwAxAGEAWQBaADEAWQBYAE0APQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AcABsAGEAeQByAGUAYQBkAHkALgBkAGkAcgBlAGMAdAB0AGEAcABzAC4AbgBlAHQALwBwAHIALwBzAHYAYwAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A</mspr:pro>
22+
</ContentProtection>
23+
<Representation bandwidth="1100690" codecs="avc1.4d401e" frameRate="30000/1001" height="360" id="800k/video-1" width="640">
24+
<BaseURL>800k/output-video-1.mp4</BaseURL>
25+
<SegmentBase indexRange="686-813">
26+
<Initialization range="0-685"></Initialization>
27+
</SegmentBase>
28+
</Representation>
29+
<Representation bandwidth="1633516" codecs="avc1.4d401f" frameRate="30000/1001" height="540" id="1200k/video-1" width="960">
30+
<BaseURL>1200k/output-video-1.mp4</BaseURL>
31+
<SegmentBase indexRange="686-813">
32+
<Initialization range="0-685"></Initialization>
33+
</SegmentBase>
34+
</Representation>
35+
</AdaptationSet>
36+
<AdaptationSet mimeType="text/vtt" lang="en">
37+
<Representation bandwidth="256" id="captions_en">
38+
<BaseURL>http://example.com/content/sintel/subtitles/subtitles_en.vtt</BaseURL>
39+
</Representation>
40+
</AdaptationSet>
41+
<AdaptationSet mimeType="image/jpeg" contentType="image">
42+
<SegmentTemplate duration="1801800" media="$RepresentationID$/$Number$.jpg" startNumber="0" timescale="30000"></SegmentTemplate>
43+
<Representation bandwidth="50000" height="720" id="5x4" width="1600">
44+
<EssentialProperty schemeIdUri="http://dashif.org/guidelines/thumbnail_tile" value="5x4"></EssentialProperty>
45+
</Representation>
46+
</AdaptationSet>
47+
</Period>
48+
</MPD>

mpd/mpd.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const (
4747
DASH_MIME_TYPE_SUBTITLE_TTML string = "application/ttaf+xml"
4848
DASH_MIME_TYPE_SUBTITLE_SRT string = "application/x-subrip"
4949
DASH_MIME_TYPE_SUBTITLE_DFXP string = "application/ttaf+xml"
50+
DASH_MIME_TYPE_IMAGE_JPEG string = "image/jpeg"
51+
DASH_CONTENT_TYPE_IMAGE string = "image"
5052
)
5153

5254
// Known error variables
@@ -462,6 +464,45 @@ func (period *Period) SetDuration(d time.Duration) {
462464
period.Duration = Duration(d)
463465
}
464466

467+
// Create a new Adaptation Set for thumbnails.
468+
// mimeType - e.g. (image/jpeg)
469+
func (m *MPD) AddNewAdaptationSetThumbnails(mimeType string) (*AdaptationSet, error) {
470+
return m.period.AddNewAdaptationSetThumbnails(mimeType)
471+
}
472+
473+
func (period *Period) AddNewAdaptationSetThumbnails(mimeType string) (*AdaptationSet, error) {
474+
as := &AdaptationSet{
475+
ContentType: Strptr(DASH_CONTENT_TYPE_IMAGE),
476+
CommonAttributesAndElements: CommonAttributesAndElements{
477+
MimeType: Strptr(mimeType),
478+
},
479+
}
480+
err := period.addAdaptationSet(as)
481+
if err != nil {
482+
return nil, err
483+
}
484+
return as, nil
485+
}
486+
487+
func (m *MPD) AddNewAdaptationSetThumbnailsWithID(id, mimeType string) (*AdaptationSet, error) {
488+
return m.period.AddNewAdaptationSetThumbnailsWithID(id, mimeType)
489+
}
490+
491+
func (period *Period) AddNewAdaptationSetThumbnailsWithID(id, mimeType string) (*AdaptationSet, error) {
492+
as := &AdaptationSet{
493+
ID: Strptr(id),
494+
ContentType: Strptr(DASH_CONTENT_TYPE_IMAGE),
495+
CommonAttributesAndElements: CommonAttributesAndElements{
496+
MimeType: Strptr(mimeType),
497+
},
498+
}
499+
err := period.addAdaptationSet(as)
500+
if err != nil {
501+
return nil, err
502+
}
503+
return as, nil
504+
}
505+
465506
// Create a new Adaptation Set for Audio Assets.
466507
// mimeType - MIME Type (i.e. audio/mp4).
467508
// segmentAlignment - Segment Alignment(i.e. true).
@@ -896,6 +937,55 @@ func (as *AdaptationSet) setSegmentTemplate(st *SegmentTemplate) error {
896937
return nil
897938
}
898939

940+
// Adds a new SegmentTemplate to a thumbnail AdaptationSet
941+
// duration - relative to timescale (i.e. 2000).
942+
// media - template string for media segments.
943+
// startNumber - the number to start segments from ($Number$) (i.e. 0).
944+
// timescale - sets the timescale for duration (i.e. 1000, represents milliseconds).
945+
func (as *AdaptationSet) SetNewSegmentTemplateThumbnails(duration int64, media string, startNumber int64, timescale int64) (*SegmentTemplate, error) {
946+
st := &SegmentTemplate{
947+
Duration: Int64ptr(duration),
948+
Media: Strptr(media),
949+
StartNumber: Int64ptr(startNumber),
950+
Timescale: Int64ptr(timescale),
951+
}
952+
953+
err := as.setSegmentTemplate(st)
954+
if err != nil {
955+
return nil, err
956+
}
957+
return st, nil
958+
}
959+
960+
// Adds a new Thumbnail representation to an AdaptationSet.
961+
// bandwidth - in Bits/s (i.e. 1518664).
962+
// id - ID for this representation, will get used as $RepresentationID$ in template strings.
963+
// width - width of the video (i.e. 1280).
964+
// height - height of the video (i.e 720).
965+
// uri -
966+
func (as *AdaptationSet) AddNewRepresentationThumbnails(id, val, uri string,bandwidth, width, height int64) (*Representation, error) {
967+
r := &Representation{
968+
Bandwidth: Int64ptr(bandwidth),
969+
ID: Strptr(id),
970+
Width: Int64ptr(width),
971+
Height: Int64ptr(height),
972+
CommonAttributesAndElements: CommonAttributesAndElements{
973+
EssentialProperty: []DescriptorType{
974+
{
975+
SchemeIDURI: Strptr(uri),
976+
Value: Strptr(val),
977+
},
978+
},
979+
},
980+
}
981+
982+
err := as.addRepresentation(r)
983+
if err != nil {
984+
return nil, err
985+
}
986+
return r, nil
987+
}
988+
899989
// Adds a new Audio representation to an AdaptationSet.
900990
// samplingRate - in Hz (i.e. 44100).
901991
// bandwidth - in Bits/s (i.e. 67095).

0 commit comments

Comments
 (0)