Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
brainfood
/
videojs-contrib-hls
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
906e1f23
authored
2014-04-07 17:11:46 -0400
by
David LaPalomento
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
WIP: playlist-loader
1 parent
58952618
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
206 additions
and
0 deletions
src/playlist-loader.js
test/playlist-loader_test.js
test/videojs-hls.html
src/playlist-loader.js
0 → 100644
View file @
906e1f2
/**
* A state machine that manages the loading, caching, and updating of
* M3U8 playlists.
*/
(
function
(
window
)
{
'use strict'
;
var
/* XXX COPIED REMOVE ME */
/**
* Constructs a new URI by interpreting a path relative to another
* URI.
* @param basePath {string} a relative or absolute URI
* @param path {string} a path part to combine with the base
* @return {string} a URI that is equivalent to composing `base`
* with `path`
* @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
*/
resolveUrl
=
function
(
basePath
,
path
)
{
// use the base element to get the browser to handle URI resolution
var
oldBase
=
document
.
querySelector
(
'base'
),
docHead
=
document
.
querySelector
(
'head'
),
a
=
document
.
createElement
(
'a'
),
base
=
oldBase
,
oldHref
,
result
;
// prep the document
if
(
oldBase
)
{
oldHref
=
oldBase
.
href
;
}
else
{
base
=
docHead
.
appendChild
(
document
.
createElement
(
'base'
));
}
base
.
href
=
basePath
;
a
.
href
=
path
;
result
=
a
.
href
;
// clean up
if
(
oldBase
)
{
oldBase
.
href
=
oldHref
;
}
else
{
docHead
.
removeChild
(
base
);
}
return
result
;
},
PlaylistLoader
=
function
(
url
)
{
var
loader
=
this
,
request
;
if
(
!
url
)
{
throw
new
Error
(
'A non-empty playlist URL is required'
);
}
loader
.
state
=
'HAVE_NOTHING'
;
request
=
new
window
.
XMLHttpRequest
();
request
.
open
(
'GET'
,
url
);
request
.
onreadystatechange
=
function
()
{
var
parser
=
new
videojs
.
m3u8
.
Parser
();
parser
.
push
(
this
.
responseText
);
if
(
parser
.
manifest
.
playlists
)
{
loader
.
master
=
parser
.
manifest
;
}
else
{
// infer a master playlist if none was previously requested
loader
.
master
=
{
playlists
:
[
parser
.
manifest
]
};
}
loader
.
state
=
'HAVE_MASTER'
;
return
;
};
request
.
send
(
null
);
};
window
.
videojs
.
hls
.
PlaylistLoader
=
PlaylistLoader
;
})(
window
);
test/playlist-loader_test.js
0 → 100644
View file @
906e1f2
(
function
(
window
)
{
'use strict'
;
var
oldXhr
,
requests
,
videojs
=
window
.
videojs
;
module
(
'Playlist Loader'
,
{
setup
:
function
()
{
oldXhr
=
window
.
XMLHttpRequest
;
requests
=
[];
window
.
XMLHttpRequest
=
function
()
{
this
.
open
=
function
(
method
,
url
)
{
this
.
method
=
method
;
this
.
url
=
url
;
};
this
.
send
=
function
()
{
requests
.
push
(
this
);
};
this
.
respond
=
function
(
response
)
{
this
.
responseText
=
response
;
this
.
readyState
=
4
;
this
.
onreadystatechange
();
};
};
this
.
send
=
function
()
{
};
},
teardown
:
function
()
{
window
.
XMLHttpRequest
=
oldXhr
;
}
});
test
(
'throws if the playlist url is empty or undefined'
,
function
()
{
throws
(
function
()
{
videojs
.
hls
.
PlaylistLoader
();
},
'requires an argument'
);
throws
(
function
()
{
videojs
.
hls
.
PlaylistLoader
(
''
);
},
'does not accept the empty string'
);
});
test
(
'starts without any metadata'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'master.m3u8'
);
strictEqual
(
loader
.
state
,
'HAVE_NOTHING'
,
'no metadata has loaded yet'
);
});
test
(
'requests the initial playlist immediately'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'master.m3u8'
);
strictEqual
(
requests
.
length
,
1
,
'made a request'
);
strictEqual
(
requests
[
0
].
url
,
'master.m3u8'
,
'requested the initial playlist'
);
});
test
(
'moves to HAVE_MASTER after loading a master playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'master.m3u8'
);
requests
.
pop
().
respond
(
'#EXTM3U\n'
+
'#EXT-X-STREAM-INF:\n'
+
'media.m3u8\n'
);
ok
(
loader
.
master
,
'the master playlist is available'
);
strictEqual
(
loader
.
state
,
'HAVE_MASTER'
,
'the state is correct'
);
});
test
(
'jumps to HAVE_METADATA when initialized with a media playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'media.m3u8'
);
requests
.
pop
().
respond
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
+
'#EXT-X-ENDLIST\n'
);
ok
(
loader
.
master
,
'infers a master playlist'
);
ok
(
loader
.
media
,
'sets the media playlist'
);
strictEqual
(
loader
.
state
,
'HAVE_METADATA'
,
'the state is correct'
);
strictEqual
(
0
,
requests
.
length
,
'no more requests are made'
);
});
test
(
'jumps to HAVE_METADATA when initialized with a live media playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'media.m3u8'
);
requests
.
pop
().
respond
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
);
ok
(
loader
.
master
,
'infers a master playlist'
);
ok
(
loader
.
media
,
'sets the media playlist'
);
strictEqual
(
loader
.
state
,
'HAVE_METADATA'
,
'the state is correct'
);
});
test
(
'moves to HAVE_METADATA after loading a media playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'master.m3u8'
);
requests
.
pop
().
respond
(
'#EXTM3U\n'
+
'#EXT-X-STREAM-INF:\n'
+
'media.m3u8\n'
+
'alt.m3u8\n'
);
strictEqual
(
requests
.
length
,
1
,
'requests the media playlist'
);
strictEqual
(
requests
[
0
].
method
,
'GET'
,
'GETs the media playlist'
);
strictEqual
(
requests
[
0
].
url
,
'media.m3u8'
,
'requests the first playlist'
);
requests
.
pop
().
response
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
);
ok
(
loader
.
master
,
'sets the master playlist'
);
ok
(
loader
.
media
,
'sets the media playlist'
);
strictEqual
(
loader
.
state
,
'HAVE_METADATA'
,
'the state is correct'
);
});
test
(
'moves to HAVE_CURRENT_METADATA when refreshing the playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'live.m3u8'
);
requests
.
pop
().
response
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
);
loader
.
refreshMedia
();
strictEqual
(
loader
.
state
,
'HAVE_CURRENT_METADATA'
,
'the state is correct'
);
strictEqual
(
requests
.
length
,
1
,
'requested playlist'
);
strictEqual
(
requests
[
0
].
url
,
'live.m3u8'
,
'refreshes the media playlist'
);
});
test
(
'returns to HAVE_METADATA after refreshing the playlist'
,
function
()
{
var
loader
=
new
videojs
.
hls
.
PlaylistLoader
(
'live.m3u8'
);
requests
.
pop
().
response
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'0.ts\n'
);
loader
.
refreshMedia
();
requests
.
pop
().
response
(
'#EXTM3U\n'
+
'#EXTINF:10,\n'
+
'1.ts\n'
);
strictEqual
(
loader
.
state
,
'HAVE_CURRENT_METADATA'
,
'the state is correct'
);
});
})(
window
);
test/videojs-hls.html
View file @
906e1f2
...
...
@@ -28,6 +28,7 @@
<!-- M3U8 -->
<script
src=
"../src/stream.js"
></script>
<script
src=
"../src/m3u8/m3u8-parser.js"
></script>
<script
src=
"../src/playlist-loader.js"
></script>
<!-- M3U8 TEST DATA -->
<script
src=
"../tmp/manifests.js"
></script>
<script
src=
"../tmp/expected.js"
></script>
...
...
@@ -51,6 +52,7 @@
<script
src=
"exp-golomb_test.js"
></script>
<script
src=
"flv-tag_test.js"
></script>
<script
src=
"m3u8_test.js"
></script>
<script
src=
"playlist-loader_test.js"
></script>
</head>
<body>
<div
id=
"qunit"
></div>
...
...
Please
register
or
sign in
to post a comment