how to implement mpeg-dash live playlist? - mpeg-dash

i'm implementing mpeg-dash video server for live streams,
chunking stream and adding chunks to mpd - works, see example
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:dash:schema:mpd:2011" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" type="Live" availabilityStartTime="2015-07-09T15:10:46.775640Z" minimumUpdatePeriod="PT10.0S" timeShiftBufferDepth="PT1.0M" maxSegmentDuration="PT20.0S" minBufferTime="PT1.0S" profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:com:dashif:dash264,urn:hbbtv:dash:profile:isoff-live:2012">
<Period id="1" start="PT0S">
<AdaptationSet group="1" mimeType="video/mp4" segmentAlignment="true" maxWidth="640" maxHeight="480" startWithSAP="1">
<SegmentTemplate timescale="1000" media="$RepresentationID$/$Time$.m4v" initialization="$RepresentationID$/init.vmoov">
<SegmentTimeline>
<S t="625" d="11000"/>
<S t="11625" d="12000"/>
<S t="23625" d="7200"/>
<S t="30825" d="9800"/>
<S t="40625" d="10760"/>
<S t="51385" d="10520"/>
<S t="61905" d="11640"/>
<S t="73545" d="9160"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="ad/a" codecs="avc1.4D401E" width="640" height="480" frameRate="25" bandwidth="1000000"></Representation>
</AdaptationSet>
<AdaptationSet group="2" mimeType="audio/mp4" segmentAlignment="true">
<SegmentTemplate timescale="1000" media="$RepresentationID$/$Time$.m4a" initialization="$RepresentationID$/init.amoov">
<SegmentTimeline>
<S t="721" d="10922"/>
<S t="11643" d="11990"/>
<S t="23633" d="7210"/>
<S t="30843" d="9792"/>
<S t="40635" d="10752"/>
<S t="51387" d="10539"/>
<S t="61926" d="11627"/>
<S t="73553" d="9173"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="ad/a" codecs="mp4a.40.02" audioSamplingRate="48000" bandwidth="66750"></Representation>
</AdaptationSet>
</Period>
</MPD>
but when i try to implement sliding playlist
(e.g. there will be 5 chunks, new chunk will replace old one.
currently i just print updated SegmentTimeline without changing any other value.)
player stops playing after .mpd refresh.
segments times - are actual timeline of stream. (i.e. same as in .m4* files)
What attributes/elements i need to implement for live video with sliding playlist?

Updating the timeline is fine, nothing else is necessary.
According the MPEG-DASH standard, the attribute "type" in the MPD element may only be set to "static" (i.e. VoD content) or "dynamic" (for live streams).
Setting it to "Live" results in an invalid manifest file and players such as the Bitmovin player or dash.js will either use "static" (as it is the default value) or they won't recognize it at all.
The audio codec should not have leading zeros, i.e. instead of "mp4a.40.02" you should use "mp4a.40.2".
There are already DASH live stream servers available, e.g. using NGINX with nginx-rtmp-module, so you can check out what they are doing, too.

Related

Cannot parse kml file to be treated as xml

I want to parse a kml file to be treated like a xml file :
var parser = require('xml2json');
router.get('/', function (req, res) {
var xml = "D:/Axes2019.kml";
var json = parser.toJson(xml);
console.log("to json -> %s", json);
res.render("index");
});
At runtime I get There are errors in your xml file: not well-formed (invalid token)
Here is the kml :
<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Schema name="Axes_2K19" id="Axes_2K19">
<SimpleField name="Name" type="string"></SimpleField>
<SimpleField name="Denomin" type="string"></SimpleField>
</Schema>
<Folder><name>Axes_2K19</name>
<Placemark>
<name>9O_6</name>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData>
<SimpleData name="Denomin">Antanimena</SimpleData>
</SchemaData></ExtendedData>
<MultiGeometry><Polygon><outerBoundaryIs><LinearRing><coordinates>47.5282959843938,-18.8881931524494 47.5273060204005,-18.8883147269749 47.525771678897,-18.8898762249651 47.525391488082,-18.8909217497064 47.5247125759123,-18.8915497434633 47.5244138545577,-18.8919299342784 47.5243188068539,-18.8924866422575 47.5259255656555,-18.8935536658841 47.5268466231657,-18.8952758397545 47.5265207453242,-18.8961312690883 47.5276816851343,-18.8957442891516 47.5279871956107,-18.8964978816599 47.529947,-18.89907 47.52965,-18.901435 47.5292802275261,-18.9017841358174 47.5286065539348,-18.9019002864366 47.5276076586099,-18.9018770563128 47.5269339850186,-18.9021906629845 47.5268062193375,-18.9027481859566 47.526667,-18.903358 47.526247,-18.903399 47.525913,-18.903094 47.525489,-18.903003 47.524572,-18.902694 47.523774,-18.902588 47.523368,-18.9026 47.522878,-18.902871 47.522666,-18.903034 47.5223273311563,-18.9027936605133 47.521073,-18.901036 47.520669,-18.900556 47.518254,-18.89732 47.5166722429164,-18.8951662207165 47.516752829692,-18.8950896025168 47.5168139317873,-18.8943258263259 47.5166917275968,-18.8930121312776 47.5173638506447,-18.8917595383246 47.5187879970001,-18.8904753419999 47.516371167,-18.887820824 47.5151030731197,-18.8858937371787 47.5153169304532,-18.8838162659395 47.5165084213109,-18.8805396660807 47.5159890535012,-18.8784851081272 47.5159886221055,-18.8784787989658 47.5193198602536,-18.8783563269751 47.521029,-18.877701 47.5222222097789,-18.8787229395467 47.5236810223034,-18.8789367968802 47.526064004019,-18.8796089199281 47.529757529473,-18.8805918742828 47.5292090646449,-18.8815425466514 47.5290563094068,-18.8836505689382 47.5292090646449,-18.8857662289869 47.5285674926446,-18.8872937813686 47.5282959843938,-18.8881931524494</coordinates></LinearRing></outerBoundaryIs></Polygon></MultiGeometry>
</Placemark>
...
</Folder>
</Document></kml>
So how to fix it ?
I checked your sample KML for XML and KML Schema validity, and it looked fine to me. Maybe your parser wants more of the namespaces defined? See below for what I usually include at the top of my KMLs:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
...
</kml>
Or maybe some of the rest of your file (which you replaced with "..." contains XML errors? Make sure all your IDs are valid too (start with a letter, no forbidden characters, etc.).

Setup a clearkey server for shaka player didn't work?

I've created a test html page for playing a MPEG-CENC protected MPEG-DASH video, and I can play if I specify kid: key pair in player.configure().
Then I want to setup a clearkey server. Refer to DRM Configuration section of Shaka Player documents, I changed the code to specify the url to get the license like below. But the page never get touched when I set a breakpoint in Page_Load event in Visual Studio. There is no error on console of browser.
The browser I use is Firefox 53.0.2 and Chrome 58.0.3029.96. Did I miss something?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/shaka-player/2.1.0/shaka-player.compiled.js"></script>
<title>MPEG-DASH Player Test</title>
<script>
//MPEG-DASH stream encrypted with MPEG-CENC:
var manifestUri = '/dashtest_encrypted/stream.mpd';
function initApp() {
// Install built-in polyfills to patch browser incompatibilities.
shaka.polyfill.installAll();
// Check to see if the browser supports the basic APIs Shaka needs.
if (shaka.Player.isBrowserSupported()) {
// Everything looks good!
initPlayer();
} else {
// This browser does not have the minimum set of APIs we need.
console.error('Browser not supported!');
}
}
function initPlayer() {
// Create a Player instance.
var video = document.getElementById('video');
var player = new shaka.Player(video);
// Configue
player.configure({
drm: {
servers: {
'org.w3.clearkey': '/clearkey/GetLic.aspx'
},
clearKeys: {
//'kid': 'key'
}
}
});
// Attach player to the window to make it easy to access in the JS console.
window.player = player;
// Listen for error events.
player.addEventListener('error', onErrorEvent);
// Try to load a manifest.
// This is an asynchronous process.
player.load(manifestUri).then(function () {
// This runs if the asynchronous load is successful.
console.log('The video has now been loaded!');
}).catch(onError); // onError is executed if the asynchronous load fails.
}
function onErrorEvent(event) {
// Extract the shaka.util.Error object from the event.
onError(event.detail);
}
function onError(error) {
// Log the error.
console.error('Error code', error.code, 'object', error);
alert(error.code);
}
document.addEventListener('DOMContentLoaded', initApp);
</script>
</head>
<body>
<video id="video" autoplay controls></video>
</body>
</html>
Here is the content of stream.MPD:
<?xml version="1.0" ?>
<MPD mediaPresentationDuration="PT12M3.022S" minBufferTime="PT15.48S" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013">
<!-- Created with Bento4 mp4-dash.py, VERSION=1.7.0-614 -->
<Period>
<!-- Video -->
<AdaptationSet maxHeight="720" maxWidth="1280" mimeType="video/mp4" minHeight="720" minWidth="1280" segmentAlignment="true" startWithSAP="1">
<!-- MPEG Common Encryption -->
<ContentProtection cenc:default_KID="7a4e12f1-8610-291f-386c-7ac1b9425abf" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<SegmentTemplate duration="15482" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/seg-$Number$.m4s" startNumber="1" timescale="1000"/>
<Representation bandwidth="1901600" codecs="avc1.64001F" frameRate="30000/1001" height="720" id="video/avc1" scanType="progressive" width="1280"/>
</AdaptationSet>
<!-- Audio -->
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<!-- MPEG Common Encryption -->
<ContentProtection cenc:default_KID="7a4e12f1-8610-291f-386c-7ac1b9425abf" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<SegmentTemplate duration="15482" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/seg-$Number$.m4s" startNumber="1" timescale="1000"/>
<Representation audioSamplingRate="44100" bandwidth="200442" codecs="mp4a.40.2" id="audio/und/mp4a">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
</Representation>
</AdaptationSet>
</Period>
</MPD>
After a very long time testing and comparison, I noticed that my .mpd file didn't have cenc:pssh tag, which resulted this problem. I recreated the .mpd and Shaka Player FINALLY asked the server.
The corrected .mpd is below:
<?xml version="1.0" ?>
<MPD mediaPresentationDuration="PT12M3.022S" minBufferTime="PT15.48S" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:cenc="urn:mpeg:cenc:2013">
<!-- Created with Bento4 mp4-dash.py, VERSION=1.7.0-614 -->
<Period>
<!-- Video -->
<AdaptationSet maxHeight="720" maxWidth="1280" mimeType="video/mp4" minHeight="720" minWidth="1280" segmentAlignment="true" startWithSAP="1">
<!-- EME Common Encryption -->
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b" value="cenc">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAF6ThLxhhApHzhsesG5Qlq/AAAAAA==</cenc:pssh>
</ContentProtection>
<!-- MPEG Common Encryption -->
<ContentProtection cenc:default_KID="7a4e12f1-8610-291f-386c-7ac1b9425abf" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<SegmentTemplate duration="15482" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/seg-$Number$.m4s" startNumber="1" timescale="1000"/>
<Representation bandwidth="1901627" codecs="avc1.64001F" frameRate="30000/1001" height="720" id="video/avc1" scanType="progressive" width="1280"/>
</AdaptationSet>
<!-- Audio -->
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<!-- EME Common Encryption -->
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b" value="cenc">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAF6ThLxhhApHzhsesG5Qlq/AAAAAA==</cenc:pssh>
</ContentProtection>
<!-- MPEG Common Encryption -->
<ContentProtection cenc:default_KID="7a4e12f1-8610-291f-386c-7ac1b9425abf" schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
<SegmentTemplate duration="15482" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/seg-$Number$.m4s" startNumber="1" timescale="1000"/>
<Representation audioSamplingRate="44100" bandwidth="200442" codecs="mp4a.40.2" id="audio/und/mp4a">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
</Representation>
</AdaptationSet>
</Period>
</MPD>

Change xml element/tag name using XmlSlurper or XmlParser

I have an xml that looks like this
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Samples>
<Sample>
<Name>
Sample1
</Name>
<Date>
01/20/2016
</Date>
</Sample>
</Samples>
I want to simply change the tag name from "Samples" to "SampleList". How will I do it?
replaceNode can be used to rename the node as below:
def xml = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Samples>
<Sample>
<Name>
Sample1
</Name>
<Date>
01/20/2016
</Date>
</Sample>
</Samples>
'''
def result = new XmlSlurper().parseText(xml)
result.replaceNode {
'SampleList' it.children()
}
groovy.xml.XmlUtil.serialize(result)
replaceNode takes a closure as method parameter which delegates to a builder. Specifically in this case the node is replaced instead of appending it to main document. 'SampleList' it.children() is similar to 'SampleList(it.children())'.
Parsed xml's root element being Samples (which needs replacement), replaceNode was directly done on the result.

How do you add a new attribute to a dataset node in OpenLaszlo platform?

How do you add a brand new attribute to a node in an OpenLaszlo XML dataset?
The way to do this is to use the lz.datapointer.setNodeAttribute() function. If you use the setNodeAttribute() function with an attribute name that does not already appear on the node, a new one will be created.
In the sample OpenLaszlo application below, if you press the button titled [displayXML] after you compile the program, you will see the XML dataset before any changes are made does not contain any "fav_saying" attribute.
After you click the [updateAttribute] button to add the favorite saying for Homer via the setNodeAttribute() method, you can then click the [displayXML] button again and you will see that an attribute called 'fav_saying' has been added to the XML dataset.
<canvas height="665" width="1000" layout="axis: x" debug="true">
<dataset name="myData">
<myXML>
<person firstname="Homer" lastname="Simpson" />
<person firstname="Marge" lastname="Simpson" />
<person firstname="Montgomery" lastname="Burns" />
</myXML>
</dataset>
<button text="displayXML">
<handler name="onclick">
Debug.write(canvas.myData.serialize());
</handler>
</button>
<button text="updateAttribute">
<handler name="onclick">
var dp = canvas.myData.getPointer(); // get datapointer to XML data
dp.setXPath('myXML/person[#firstname="Homer"]'); // set xpath to Homer Simpson
dp.setNodeAttribute('fav_saying', 'DOH!');
</handler>
</button>
</canvas>
You will also see that multiple calls to setNodeAttribute() will not add additional 'fav_saying' attributes. If the program used a different value for the saying every time then the value in the 'fav_saying' attribute would change but there would still only be one 'fav_saying' attribute.

One SVG file, many SVG gradients inside

I’m making a set of buttons which use dynamic gradients. I’ve taken care of Firefox 3.6+ and WebKit by using their proprietary CSS extensions and all I need to do is support Opera, iOS and IE9 by using background-image: url("gradient.svg").
This is relatively easy, I made an SVG file, linked it and got it working. However, I’m making a set so I need at least 6 gradients. When I normally do it in images, I create a sprite for fast HTTP access. I’m not sure how to achieve this in SVG – can I use one file and access different parts of its XML by using #identifiers, like XBL does?
My current SVG:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="select-gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="rgb(231,244,248)"/>
<stop offset="100%" stop-color="rgb(207,233,241)"/>
</linearGradient>
<style type="text/css">
rect {
fill: url(#select-gradient);
}
</style>
</defs>
<rect x="0" y="0" rx="6" ry="6" height="100%" width="100%"/>
</svg>
And then I have CSS:
.button-1 {
background-image: url("gradient-1.svg");
}
.button-2 {
background-image: url("gradient-2.svg");
}
I want to do something like this:
.button-1 {
background-image: url("gradient.svg#gradient1");
}
.button-2 {
background-image: url("gradient.svg#gradient2");
}
Is it even possible? Can you help me out? I really don’t wanna push 6 XML files when I can do it with one.
If you just want gradients for button backgrounds, most of this can be acheived in css. For the remaining browsers, ie6 + can user ms filters:
http://msdn.microsoft.com/en-us/library/ms532847.aspx
iOS uses webkit to render, so you can use -webkit vendor prefix. Unfortunately you will still need svg for opera, but this may make it easier (or just use a normal image sprite for opera's 1% of users)
in theory - according to SVG documentation #Params it is possible. You could use 2 params for setting up both colors, you could create multiple rects with different gradients, height set to 0 and then make only one 100% (like ?gradient2=100%)
What you could do is load your SVG file that contains all of the definitions first, and then load your other SVG files.
Using Firefox, jQuery SVG , and a minor shot of framework...
in your XHTML:
<div id="common_svg_defs"><!--ieb--></div>
<div id="first_thing"><!--ieb--></div>
<div id="second_thing"><!--ieb--></div>
in your JavaScript:
var do_stuff = function()
{
// load your common svg file with this goo.
$('#common_svg_defs').svg({
loadURL: 'path/filename.svg',
onLoad: function(svg, error) { run_test(svg, error);} });
}
var run_test = function(svg, error)
{
if (typeof(error) !== "undefined")
{
if (typeof(console.log) !== "undefined")
{
console.log(error);
}
}
else
{
// load your other svg files here, or just
// set a flag letting you know it's ready.
$('#first_thing').svg({
loadURL: 'path/anotherfilename.svg',
onLoad: function(svg, error) { somecallback(svg, error);} });
$('#second_thing').svg({
loadURL: 'path/anotherfilename.svg',
onLoad: function(svg, error) { somecallback(svg, error);} });
}
}
Because the id can be found in the documents scope, the SVG are capable of finding the IRI reference.
This allows you to define things once (that would not otherwise be defined in a css) and avoid id collisions.
Cheers,
Christopher Smithson

Resources