-
Notifications
You must be signed in to change notification settings - Fork 7.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Monkeypatch canPlayType on Android 4.0+ for HLS #1084
Changes from 7 commits
e35083b
252ad3f
5381f70
86c3f94
f86e073
817253b
0c856ce
f1d2aef
fef6282
75bd76f
94ec725
d21019a
e2a1cac
e39557e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -266,6 +266,55 @@ vjs.Html5.canControlVolume = function(){ | |
return volume !== vjs.TEST_VID.volume; | ||
}; | ||
|
||
// HTML5 Feature detection and Device Fixes --------------------------------- // | ||
(function() { | ||
var canPlayType, | ||
mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl$/i, | ||
mp4RE = /^video\/mp4$/i; | ||
|
||
vjs.Html5.patchCanPlayType = function() { | ||
// Android 4.0 and above can play HLS to some extent but it reports being unable to do so | ||
if (vjs.ANDROID_VERSION >= 4.0) { | ||
if (!canPlayType) { | ||
canPlayType = vjs.TEST_VID.constructor.prototype.canPlayType; | ||
} | ||
|
||
vjs.TEST_VID.constructor.prototype.canPlayType = function(type) { | ||
if (type && mpegurlRE.test(type)) { | ||
return "maybe"; | ||
} | ||
return canPlayType.call(this, type); | ||
}; | ||
} | ||
|
||
// Override Android 2.2 and less canPlayType method which is broken | ||
if (vjs.IS_OLD_ANDROID) { | ||
if (!canPlayType) { | ||
canPlayType = vjs.TEST_VID.constructor.prototype.canPlayType; | ||
} | ||
|
||
vjs.TEST_VID.constructor.prototype.canPlayType = function(type){ | ||
if (type && mp4RE.test(type)) { | ||
return "maybe"; | ||
} | ||
return canPlayType.call(this, type); | ||
}; | ||
} | ||
}; | ||
|
||
vjs.Html5.unpatchCanPlayType = function() { | ||
var r = canPlayType; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what returning the canPlayType was used for but it looks like it could be removed now? There's a test that stores it in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is to kind of mimic jQuery's (and others') There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That seems fine then if it's following convention. I don't totally understand the use case though. You couldn't just reference the function before unpatching? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it's mostly convention so that the user could just do |
||
if (canPlayType) { | ||
vjs.TEST_VID.constructor.prototype.canPlayType = canPlayType; | ||
canPlayType = null; | ||
return r; | ||
} | ||
}; | ||
|
||
// by default, patch the video element | ||
vjs.Html5.patchCanPlayType(); | ||
})(); | ||
|
||
// List of all HTML5 events (various uses). | ||
vjs.Html5.Events = 'loadstart,suspend,abort,error,emptied,stalled,loadedmetadata,loadeddata,canplay,canplaythrough,playing,waiting,seeking,seeked,ended,durationchange,timeupdate,progress,play,pause,ratechange,volumechange'.split(','); | ||
|
||
|
@@ -300,12 +349,3 @@ vjs.Html5.disposeMediaElement = function(el){ | |
})(); | ||
} | ||
}; | ||
|
||
// HTML5 Feature detection and Device Fixes --------------------------------- // | ||
|
||
// Override Android 2.2 and less canPlayType method which is broken | ||
if (vjs.IS_OLD_ANDROID) { | ||
document.createElement('video').constructor.prototype.canPlayType = function(type){ | ||
return (type && type.toLowerCase().indexOf('video/mp4') != -1) ? 'maybe' : ''; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
module('HTML5'); | ||
|
||
var oldAndroidVersion; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not used anymore? |
||
|
||
test('should detect whether the volume can be changed', function(){ | ||
var testVid, ConstVolumeVideo; | ||
if (!{}['__defineSetter__']) { | ||
|
@@ -38,3 +40,52 @@ test('should re-link the player if the tech is moved', function(){ | |
|
||
strictEqual(player, tech.el()['player']); | ||
}); | ||
|
||
test('patchCanPlayType patches canplaytype with our function, conditionally', function() { | ||
var oldAV = vjs.ANDROID_VERSION, | ||
video = document.createElement('video'), | ||
canPlayType = vjs.TEST_VID.constructor.prototype.canPlayType, | ||
patchCanPlayType, | ||
unpatchedCanPlayType; | ||
|
||
vjs.ANDROID_VERSION = 4.0; | ||
vjs.Html5.patchCanPlayType(); | ||
|
||
notStrictEqual(video.canPlayType, canPlayType, 'original canPlayType and patched canPlayType should not be equal'); | ||
|
||
patchCanPlayType = video.canPlayType; | ||
unpatchedCanPlayType = vjs.Html5.unpatchCanPlayType(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unpatchedCanPlayType isn't currently used |
||
|
||
strictEqual(video.canPlayType, vjs.TEST_VID.constructor.prototype.canPlayType, 'original canPlayType and unpatched canPlayType should be equal'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't these two references the same the same thing always? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep. I'll see if I can figure out what I meant to refactor this into. |
||
|
||
vjs.ANDROID_VERSION = oldAV; | ||
}); | ||
|
||
test('should return maybe for HLS urls on Android 4.0 or above', function() { | ||
var oldAV = vjs.ANDROID_VERSION, | ||
video = document.createElement('video'); | ||
|
||
vjs.ANDROID_VERSION = 4.0; | ||
vjs.Html5.patchCanPlayType(); | ||
|
||
strictEqual(video.canPlayType('application/x-mpegurl'), 'maybe', 'android version 4.0 or above should be a maybe for x-mpegurl'); | ||
strictEqual(video.canPlayType('application/x-mpegURL'), 'maybe', 'android version 4.0 or above should be a maybe for x-mpegURL'); | ||
strictEqual(video.canPlayType('application/vnd.apple.mpegurl'), 'maybe', 'android version 4.0 or above should be a maybe for vnd.apple.mpegurl'); | ||
strictEqual(video.canPlayType('application/vnd.apple.mpegURL'), 'maybe', 'android version 4.0 or above should be a maybe for vnd.apple.mpegurl'); | ||
|
||
vjs.ANDROID_VERSION = oldAV; | ||
vjs.Html5.unpatchCanPlayType(); | ||
}); | ||
|
||
test('should return a maybe for mp4 on OLD ANDROID', function() { | ||
var isOldAndroid = vjs.IS_OLD_ANDROID, | ||
video = document.createElement('video'); | ||
|
||
vjs.IS_OLD_ANDROID = true; | ||
vjs.Html5.patchCanPlayType(); | ||
|
||
strictEqual(video.canPlayType('video/mp4'), 'maybe', 'old android should return a maybe for video/mp4'); | ||
|
||
vjs.IS_OLD_ANDROID = isOldAndroid; | ||
vjs.Html5.unpatchCanPlayType(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want the end-of-line character here, in case codec info is included.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.