Skip to content

Commit

Permalink
chore: Partial cherry-pick and backport of #5656
Browse files Browse the repository at this point in the history
This is parts of #5656 cherry-picked and backported to support the cherry-pick of #5677, which fixes a bug in HLS.
  • Loading branch information
joeyparrish committed Oct 4, 2023
1 parent ba51991 commit 3dd413d
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 11 deletions.
5 changes: 5 additions & 0 deletions demo/common/asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ const ShakaDemoAssetInfo = class {
return this.drm.length == 1 && this.drm[0] == shakaAssets.KeySystem.CLEAR;
}

/** @return {boolean} */
isAes128() {
return this.drm.length == 1 && this.drm[0] == shakaAssets.KeySystem.AES128;
}

/**
* @param {string} mediaPlaylistFullMimeType
* @return {!ShakaDemoAssetInfo}
Expand Down
15 changes: 15 additions & 0 deletions demo/common/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ shakaAssets.KeySystem = {
FAIRPLAY: shakaDemo.MessageIds.FAIRPLAY,
PLAYREADY: shakaDemo.MessageIds.PLAYREADY,
WIDEVINE: shakaDemo.MessageIds.WIDEVINE,
AES128: shakaDemo.MessageIds.AES128,
CLEAR: shakaDemo.MessageIds.CLEAR,
};

Expand Down Expand Up @@ -88,6 +89,7 @@ shakaAssets.identifierForKeySystem = (keySystem) => {
case KeySystem.FAIRPLAY: return 'com.apple.fps';
case KeySystem.PLAYREADY: return 'com.microsoft.playready';
case KeySystem.WIDEVINE: return 'com.widevine.alpha';
case KeySystem.AES128: return 'aes128';
default: return 'no drm protection';
}
};
Expand Down Expand Up @@ -360,6 +362,7 @@ shakaAssets.testAssets = [
/* iconUri= */ 'https://storage.googleapis.com/shaka-asset-icons/sintel.png',
/* manifestUri= */ 'https://storage.googleapis.com/shaka-demo-assets/sintel-ts-aes-key-rotation/master.m3u8',
/* source= */ shakaAssets.Source.SHAKA)
.addKeySystem(shakaAssets.KeySystem.AES128)
.addFeature(shakaAssets.Feature.HLS)
.addFeature(shakaAssets.Feature.MP2TS)
.addFeature(shakaAssets.Feature.OFFLINE),
Expand All @@ -368,6 +371,7 @@ shakaAssets.testAssets = [
/* iconUri= */ 'https://storage.googleapis.com/shaka-asset-icons/sintel.png',
/* manifestUri= */ 'https://storage.googleapis.com/shaka-demo-assets/sintel-fmp4-aes/master.m3u8',
/* source= */ shakaAssets.Source.SHAKA)
.addKeySystem(shakaAssets.KeySystem.AES128)
.addFeature(shakaAssets.Feature.HLS)
.addFeature(shakaAssets.Feature.MP4)
.addFeature(shakaAssets.Feature.OFFLINE),
Expand Down Expand Up @@ -948,6 +952,7 @@ shakaAssets.testAssets = [
/* iconUri= */ 'https://storage.googleapis.com/shaka-asset-icons/art_of_motion.png',
/* manifestUri= */ 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/m3u8s/11331.m3u8',
/* source= */ shakaAssets.Source.BITCODIN)
.addKeySystem(shakaAssets.KeySystem.AES128)
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
.addFeature(shakaAssets.Feature.HLS)
.addFeature(shakaAssets.Feature.MP2TS)
Expand Down Expand Up @@ -1087,6 +1092,16 @@ shakaAssets.testAssets = [
kind: 'subtitle',
mime: 'text/vtt',
}),
new ShakaDemoAssetInfo(
/* name= */ 'Sintel (DASH, AES-128)',
/* iconUri= */ 'https://storage.googleapis.com/shaka-asset-icons/sintel.png',
/* manifestUri= */ 'https://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=mpd-time-csf)',
/* source= */ shakaAssets.Source.AZURE_MEDIA_SERVICES)
.addKeySystem(shakaAssets.KeySystem.AES128)
.addFeature(shakaAssets.Feature.DASH)
.addFeature(shakaAssets.Feature.MP4)
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
.addFeature(shakaAssets.Feature.OFFLINE),
// End Azure Media Services assets }}}

// GPAC assets {{{
Expand Down
1 change: 1 addition & 0 deletions demo/common/message_ids.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ shakaDemo.MessageIds = {
WEBM: 'DEMO_WEBM',
XLINK: 'DEMO_XLINK',
/* Key systems. */
AES128: 'DEMO_AES128',
CLEAR: 'DEMO_CLEAR',
CLEAR_KEY: 'DEMO_CLEAR_KEY',
FAIRPLAY: 'DEMO_FAIRPLAY',
Expand Down
1 change: 1 addition & 0 deletions demo/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"DEMO_AD_TAG_URL": "Ad Tag URL",
"DEMO_ADS_TAB": "Ads",
"DEMO_ADS_SECTION_HEADER": "Ads",
"DEMO_AES128": "AES-128 protection",
"DEMO_ALL_CONTENT": "ALL CONTENT",
"DEMO_ALWAYS_STREAM_TEXT": "Always Stream Text",
"DEMO_ALWAYS_STREAM_TEXT_WARNING": "Text must always be streamed while native controls are enabled, for captions to work.",
Expand Down
4 changes: 4 additions & 0 deletions demo/locales/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"description": "The label on a field that allows users to provide a Ad Tag URL for a custom asset.",
"message": "Ad Tag URL"
},
"DEMO_AES128": {
"description": "Text that describes an asset that is not protected with any Digital Rights Management system but it is protected with AES-128.",
"message": "[JARGON:AES-128] protection"
},
"DEMO_ALL_CONTENT": {
"description": "A link in the header, that switches to a page for browsing or searching through the entire content library.",
"message": "ALL CONTENT"
Expand Down
2 changes: 1 addition & 1 deletion demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ shakaDemo.Main = class {
return shakaDemo.MessageIds.UNSUPPORTED_NO_DOWNLOAD;
}

if (!asset.isClear()) {
if (!asset.isClear() && !asset.isAes128()) {
const hasSupportedDRM = asset.drm.some((drm) => {
return this.support_.drm[shakaAssets.identifierForKeySystem(drm)];
});
Expand Down
7 changes: 6 additions & 1 deletion lib/media/segment_reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ shaka.media.InitSegmentReference = class {
* the quality of the media associated with this init segment.
* @param {(null|number)=} timescale
* @param {(null|BufferSource)=} segmentData
* @param {?shaka.extern.HlsAes128Key=} aes128Key
* The segment's AES-128-CBC full segment encryption key and iv.
*/
constructor(uris, startByte, endByte, mediaQuality = null, timescale = null,
segmentData = null) {
segmentData = null, aes128Key = null) {
/** @type {function():!Array.<string>} */
this.getUris = uris;

Expand All @@ -52,6 +54,9 @@ shaka.media.InitSegmentReference = class {

/** @type {BufferSource|null} */
this.segmentData = segmentData;

/** @type {?shaka.extern.HlsAes128Key} */
this.hlsAes128Key = aes128Key;
}

/**
Expand Down
20 changes: 11 additions & 9 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -1409,15 +1409,11 @@ shaka.media.StreamingEngine = class {
'ReadableStream is not supported by the browser.');
}
const fetchSegment = this.fetch_(mediaState, reference);
let result = await fetchSegment;
const result = await fetchSegment;
this.destroyer_.ensureNotDestroyed();
if (this.fatalError_) {
return;
}
if (reference.hlsAes128Key) {
goog.asserts.assert(iter, 'mediaState.segmentIterator should exist');
result = await this.aes128Decrypt_(result, reference, iter);
}
this.destroyer_.ensureNotDestroyed();

// If the text stream gets switched between fetch_() and append_(), the
Expand Down Expand Up @@ -1502,13 +1498,13 @@ shaka.media.StreamingEngine = class {

/**
* @param {!BufferSource} rawResult
* @param {!shaka.media.SegmentReference} reference
* @param {shaka.extern.HlsAes128Key} aes128Key
* @param {!shaka.media.SegmentIterator} iter
* @return {!Promise.<!BufferSource>} finalResult
* @private
*/
async aes128Decrypt_(rawResult, reference, iter) {
const key = reference.hlsAes128Key;
async aes128Decrypt_(rawResult, aes128Key, iter) {
const key = aes128Key;
if (!key.cryptoKey) {
goog.asserts.assert(key.fetchKey, 'If AES-128 cryptoKey was not ' +
'preloaded, fetchKey function should be provided');
Expand Down Expand Up @@ -2188,7 +2184,13 @@ shaka.media.StreamingEngine = class {
mediaState.operation = op;
const response = await op.promise;
mediaState.operation = null;
return response.data;
let result = response.data;
if (reference.hlsAes128Key) {
const iter = mediaState.segmentIterator;
goog.asserts.assert(iter, 'mediaState.segmentIterator should exist');
result = await this.aes128Decrypt_(result, reference.hlsAes128Key, iter);
}
return result;
}

/**
Expand Down

0 comments on commit 3dd413d

Please sign in to comment.