-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DRM checking capabilities for YouTube (#3)
- added the checkDrmById to the player and checkDrm to the main file - added a generic object pool to handle resource management (players here)
- Loading branch information
Jonathan Raoult
authored
Apr 28, 2017
1 parent
39dc471
commit cf83a11
Showing
15 changed files
with
596 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
'use strict'; | ||
|
||
var playersPool = require('./playersPool'), | ||
playerFactory = require('./playerFactory'), | ||
defaults = require('lodash/defaults'), | ||
pFinally = require('p-finally'); | ||
|
||
/** | ||
* @typedef {Object} drmCheckerConfig | ||
* @property {PlayersPool} playersPool | ||
*/ | ||
|
||
/** | ||
* | ||
* @param {drmCheckerConfig} config | ||
* @returns {DrmChecker} | ||
*/ | ||
function drmChecker(config) { | ||
|
||
var _config = defaults({}, config, { | ||
max: 4 | ||
}), | ||
|
||
_playersPool = playersPool({ | ||
playerFactory: playerFactory({ | ||
elementProducer: _config.elementProducer, | ||
// debug settings make non sense for DRM check | ||
debug: { | ||
mediaDuration: -1, | ||
mediaQuality: 'default' | ||
} | ||
}), | ||
max: _config.max | ||
}); | ||
|
||
/** | ||
* @param {Entry} entry | ||
* @returns {Promise.<DrmCheckReport>} | ||
*/ | ||
function checkDrm(entry) { | ||
return _playersPool.getPlayer(entry.provider) | ||
.then(function(player) { | ||
return pFinally(player.checkDrmById(entry.id), | ||
function checkDrmFinally() { | ||
_playersPool.releasePlayer(player); | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* @typedef DrmChecker | ||
* @name DrmChecker | ||
*/ | ||
var DrmChecker = { | ||
checkDrm: checkDrm | ||
}; | ||
|
||
return Object.freeze(DrmChecker); | ||
} | ||
|
||
module.exports = drmChecker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
'use strict'; | ||
|
||
var engine = require('./engine'), | ||
drmChecker = require('./drmChecker'); | ||
|
||
module.exports = { | ||
engine: engine, | ||
drmChecker: drmChecker | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
'use strict'; | ||
|
||
/** | ||
* @typedef {Object} ObjectsPoolBucket | ||
* @property {*} payload | ||
* @property {boolean} free | ||
*/ | ||
|
||
/** | ||
* @typedef {Object} objectsPoolConfig | ||
* @property {function():*|Promise.<*>} factory | ||
* @property {number} max | ||
*/ | ||
|
||
function pathBucket(bucket) { | ||
return bucket.payload; | ||
} | ||
|
||
function predicateBucketFree(bucket) { | ||
return bucket.free; | ||
} | ||
|
||
/** | ||
* @param {objectsPoolConfig} config | ||
* @returns {ObjectsPool} | ||
*/ | ||
function objectsPool(config) { | ||
var factory = config.factory, | ||
max = config.max; | ||
|
||
var buckets = []; | ||
var waiters = []; | ||
|
||
function canGrow() { | ||
return buckets.length < max; | ||
} | ||
|
||
/** | ||
* @returns {ObjectsPoolBucket} | ||
*/ | ||
function findBucketFree() { | ||
return buckets.find(predicateBucketFree); | ||
} | ||
|
||
/** | ||
* @param {*} payload | ||
* @returns {ObjectsPoolBucket} | ||
*/ | ||
function findBucketForByPayload(payload) { | ||
return buckets.find(function(bucket) { | ||
return bucket.payload === payload; | ||
}); | ||
} | ||
|
||
function removeBucket(bucket) { | ||
buckets.splice(buckets.findIndex(function(bucket_) { | ||
return bucket_ === bucket; | ||
}), 1); | ||
} | ||
|
||
/** | ||
* @returns {Promise.<ObjectsPoolBucket>} | ||
*/ | ||
function allocateBucket() { | ||
// allocate the bucket straight but make it not available | ||
var bucket = {payload: undefined, free: false}; | ||
buckets.push(bucket); | ||
|
||
return Promise | ||
.resolve(factory()) | ||
.then(function(payload) { | ||
bucket.payload = payload; | ||
bucket.free = true; | ||
return bucket; | ||
}).catch(function(error) { | ||
// in case of error we remove the bucket | ||
removeBucket(bucket); | ||
throw error; | ||
}); | ||
} | ||
|
||
/** | ||
* @returns {Promise.<function(*)>} | ||
*/ | ||
function enqueueWaiterForBucket() { | ||
return new Promise(function(resolve) { | ||
waiters.push(resolve); | ||
}); | ||
} | ||
|
||
/** | ||
* @returns {Promise.<ObjectsPoolBucket>} | ||
*/ | ||
function ensureBucket() { | ||
var bucket = findBucketFree(); | ||
|
||
if (!bucket) { | ||
// cache miss | ||
if (!canGrow()) { | ||
return enqueueWaiterForBucket() | ||
.then(markBucketOccupied); | ||
} | ||
|
||
return allocateBucket() | ||
.then(markBucketOccupied); | ||
} | ||
|
||
return Promise.resolve(markBucketOccupied(bucket)); | ||
} | ||
|
||
/** | ||
* @param {ObjectsPoolBucket} bucket | ||
* @returns {ObjectsPoolBucket} | ||
*/ | ||
function markBucketOccupied(bucket) { | ||
bucket.free = false; | ||
return bucket; | ||
} | ||
|
||
function acquire() { | ||
return ensureBucket().then(pathBucket); | ||
} | ||
|
||
function release(payload) { | ||
var bucket = findBucketForByPayload(payload); | ||
|
||
if (bucket === undefined) { | ||
throw new Error('Can not release a foreign object from a pool'); | ||
} | ||
|
||
var waiter = waiters.shift(); | ||
if (waiter !== undefined) { | ||
// recycle straight if someone is waiting | ||
waiter(bucket); | ||
} else { | ||
bucket.free = true; | ||
} | ||
} | ||
|
||
/** | ||
* @typedef ObjectsPool | ||
* @name ObjectsPool | ||
*/ | ||
var ObjectsPool = { | ||
acquire: acquire, | ||
release: release | ||
}; | ||
|
||
return Object.freeze(ObjectsPool); | ||
} | ||
|
||
module.exports = objectsPool; |
Oops, something went wrong.