Skip to content

Commit

Permalink
+ vjs.Html5.{patchCanPlayType,unpatchCanPlayType}
Browse files Browse the repository at this point in the history
patchCanPlayType is called on load.
It patched video#canPlayType if needed.
unpatchCanPlayType will revert the patch and return the patch function.
There are also corresponding tests that test patchCanPlayType,
unpatchCanPlayType and also whether the patch functions themselves work
correctly.
  • Loading branch information
gkatsev committed Mar 18, 2014
1 parent 252ad3f commit 5381f70
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 24 deletions.
73 changes: 49 additions & 24 deletions src/js/media/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = HTMLVideoElement.prototype.canPlayType;
}

HTMLVideoElement.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 = HTMLVideoElement.prototype.canPlayType;
}

HTMLVideoElement.prototype.canPlayType = function(type){
if (type && mp4RE.test(type)) {
return "maybe";
}
return canPlayType.call(this, type);
};
}
};

vjs.Html5.unpatchCanPlayType = function() {
var r = canPlayType;
if (canPlayType) {
HTMLVideoElement.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(',');

Expand Down Expand Up @@ -300,27 +349,3 @@ vjs.Html5.disposeMediaElement = function(el){
})();
}
};

// HTML5 Feature detection and Device Fixes --------------------------------- //

// 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) {
(function() {
var canPlayType = HTMLVideoElement.prototype.canPlayType,
mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl$/i;

HTMLVideoElement.prototype.canPlayType = function(type) {
if (type && mpegurlRE.test(type)) {
return "maybe";
}
return canPlayType.call(video.constructor.prototype, type);
}
})();
}

// 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' : '';
};
}
49 changes: 49 additions & 0 deletions test/unit/media.html5.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module('HTML5');

var oldAndroidVersion;

test('should detect whether the volume can be changed', function(){
var testVid, ConstVolumeVideo;
if (!{}['__defineSetter__']) {
Expand Down Expand Up @@ -38,3 +40,50 @@ 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 = HTMLVideoElement.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();

strictEqual(video.canPlayType, HTMLVideoElement.prototype.canPlayType, 'original canPlayType and unpatched canPlayType should be equal');

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;
});

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;
});

0 comments on commit 5381f70

Please sign in to comment.