-
Notifications
You must be signed in to change notification settings - Fork 25
Feature/ios drm support #5
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
base: master
Are you sure you want to change the base?
Changes from 43 commits
bd8aa99
739a636
a55b7e5
c361b79
4080349
e0fd69e
77411f2
35250fa
e4763c9
420d88d
2898f8c
4424774
891add6
4dd1c73
d759e97
e5cd51a
d981f80
e7f1732
801dce4
d8a2a9e
b448b30
98eb7a3
075dfba
f69231f
02851bb
967dc3f
d5fe47f
80fb571
dc75d23
e1882fd
b5c2577
f38b6f8
fd16a93
59b541c
5b92ea0
a7780f9
300f283
decb56e
f710df5
0ecba93
933bbae
5dbf7e2
9016d19
f162667
c36a9cf
6c39ac7
9df4f89
3d80bfd
2072793
da8a202
c12e9d8
03b7f8d
2fb1619
c30f246
0c87b78
9b5ced2
6e3e653
24730ed
5725c62
4d12d1d
4210929
3b952dc
1b680c2
a22bf45
ce4dedf
8818b9a
bdc599d
a296fd9
2fc3b77
2d0e402
9fa4046
fccbc93
3989d73
327d862
d61a0d7
88c5541
91f200b
4efd0b5
5f42e0f
4223f5d
e28ae17
f6bc13e
fb3175f
a0bb083
0a15579
112608c
32796e9
9c04bd2
4f36eb1
a96fa33
3ddcba3
6d3936d
cc7db91
420332e
b193baa
e5b5bbe
fcef441
a3b32ac
92f7459
3762a32
976ebcc
e5bc715
cad807d
e033fc4
88d2aed
cb3e8c8
6ea6583
ed25b3f
a203aea
3a7be63
1cd9796
438df8b
4c4899b
a48fb69
c123d86
e6710f3
6de06f1
e9c978c
7525d4a
6876179
4a3ea93
3d2a58a
666c26d
f484bd8
2b067f1
22a3961
7949c55
6c7a0b4
9bc709f
1433d16
d4313e2
8a8f215
9dec6ae
be3c8b6
576273d
61a72ad
466c004
40c7371
eae487c
77c9ad3
cb3cff7
b7d1139
cde2432
f60aff7
f58ae34
47e1630
03114bc
6bdbaec
95060d7
66a85ae
62ff44a
d748d17
222adf5
a45e857
1fb07b5
917f9cb
c29244b
88d3a4a
6bd8f33
45b806d
991fd59
e6e57ec
2f8746c
a1679ef
4f9f793
e38149b
aad75d4
c38ff02
3012b81
2b9ddda
7a9081d
923bc59
e3782c4
0a361d1
7615e5d
4320b56
008f5f0
0cfc732
d858bf7
0a2f7bd
9272678
f66ca32
cfcf6ce
59be8b5
b954a4f
a86f316
9149346
c90197b
461209f
ed335f3
81cfd4e
3e38f88
3d40deb
c9a248e
78f1d29
4a8eea7
040b171
395b9b7
d266b32
03b2d4d
62166a2
725a15c
b675e59
b97663e
c7a8a25
8c40aaf
32748d5
257be24
a5bfba9
fa20965
2c5006a
0df6676
9200dce
029b893
2738892
82c191d
4d0be29
5fa4cdd
fd8ac76
f0867d7
4f07aab
a4fec8e
6d1a7be
89b6d11
68dc152
91384d8
1ecb09a
b4582c6
4157a60
052f49e
cc2e9c4
4bc2a72
08c7aaa
c579d3c
2b33b9e
b8234f8
c438509
838b99a
6bc25f1
d6a7117
e3009c6
0b914ef
c9096d1
2dd5025
7c8c613
f395bd1
9c31948
8962720
dbf1a4e
8c25828
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 |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ Version 3.x requires react-native >= 0.40.0 | |
| ### Version 4.0.0 breaking changes | ||
| Version 4.0.0 changes some behaviors and may require updates to your Gradle files. See [Updating](#updating) for details. | ||
|
|
||
| Version 4.0.0 now requires Android SDK 26+ and Gradle 3 plugin in order to support ExoPlayer 2.9.0. Google is dropping support for apps using SDKs older than 26 as of October 2018 and Gradle 2 as of January 2019. React Native 0.57 defaults to Gradle 3 & SDK 27. | ||
| Version 4.0.0 now requires Android target SDK 26+ and Gradle 3 plugin in order to support ExoPlayer 2.9.0. Google is dropping support for apps using target SDKs older than 26 as of October 2018 and Gradle 2 as of January 2019. React Native 0.57 defaults to Gradle 3 & SDK 27. | ||
|
|
||
| If you need to support an older React Native version, you should use react-native-video 3.2.1. | ||
|
|
||
|
|
@@ -420,15 +420,18 @@ Platforms: iOS | |
| Platforms: iOS | ||
|
|
||
| #### headers | ||
| Pass headers to the HTTP client. Can be used for authorization. | ||
| Pass headers to the HTTP client. Can be used for authorization. Headers must be a part of the source object. | ||
|
|
||
| To enable this on iOS, you will need to manually edit RCTVideo.m and uncomment the header code in the playerItemForSource function. This is because the code used a private API and may cause your app to be rejected by the App Store. Use at your own risk. | ||
|
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. Is this still the case now?
Author
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. This is coming from an update of RNV itself. It is related with source > headers, not source > drm > headers |
||
|
|
||
| Example: | ||
| ``` | ||
| headers={{ | ||
| Authorization: 'bearer some-token-value', | ||
| 'X-Custom-Header': 'some value' | ||
| source={{ | ||
| uri: "https://www.example.com/video.mp4", | ||
| headers: { | ||
| Authorization: 'bearer some-token-value', | ||
| 'X-Custom-Header': 'some value' | ||
| } | ||
| }} | ||
| ``` | ||
|
|
||
|
|
@@ -715,18 +718,23 @@ source={{ uri: 'http://host-serving-a-type-different-than-the-extension.ism/mani | |
| type: 'mpd' }} | ||
| ``` | ||
|
|
||
| ##### Provide DRM data | ||
| ##### Provide DRM data (only tested with http/https assets) | ||
|
|
||
| You can provide some configuration to allow DRM playback. | ||
| This feature will disable the use of `TextureView` on Android. | ||
| DRM options are `type`, `licenseServer`, `headers`. | ||
|
|
||
| ###### headers | ||
|
|
||
| You can customize headers send to the licenseServer. | ||
|
|
||
| Example: | ||
| ``` | ||
|
|
||
| ```js | ||
| source={{ | ||
| uri: 'https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd', | ||
| drm: { | ||
| type: 'widevine', | ||
| type: 'widevine', //or DRMType.WIDEVINE | ||
| licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense', | ||
| headers: { | ||
| 'X-AxDRM-Message': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImZpcnN0X3BsYXlfZXhwaXJhdGlvbiI6NjAsInBsYXlyZWFkeSI6eyJyZWFsX3RpbWVfZXhwaXJhdGlvbiI6dHJ1ZX0sImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.FAbIiPxX8BHi9RwfzD7Yn-wugU19ghrkBFKsaCPrZmU' | ||
|
|
@@ -735,7 +743,58 @@ source={{ | |
| }} | ||
| ``` | ||
|
|
||
| Platforms: Android | ||
| ###### licenseServer | ||
|
|
||
| The URL pointing to the licenseServer that will provide the authorization to play the protected stream. | ||
|
|
||
| iOS specific fields for `drm`: | ||
|
|
||
| * `certificateUrl` - Url to the .cer file. | ||
| * `contentId` (optional) - (overridable, otherwise it will take the value at `loadingRequest.request.URL.host`) | ||
| * `getLicense` - `licenseServer` and `headers` will be ignored. You will obtain as argument the `SPC` (as ASCII string, you will probably need to convert it to base 64) obtained from your `contentId` + the provided certificate via `[loadingRequest streamingContentKeyRequestDataForApp:certificateData contentIdentifier:contentIdData options:nil error:&spcError];`. | ||
| You should return on this method a `CKC` in Base64, either by just returning it or returning a `Promise` that resolves with the `CKC`. | ||
| With this prop you can override the license acquisition flow, as an example: | ||
|
|
||
| ```js | ||
| getLicense: (spcString) => { | ||
| const base64spc = btoa(spcString); | ||
| return fetch(YOUR_LICENSE_SERVER, { | ||
| method: 'POST', | ||
| // Control the headers | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| Accept: 'application/json', | ||
| }, | ||
| // Build the data as the server specs it | ||
| body: JSON.stringify({ | ||
| getFairplayLicense: { | ||
| releasePid: myPid, | ||
| spcMessage: base64spc, | ||
| } | ||
| }) | ||
| }) | ||
| .then(response => response.json()) | ||
| .then((response) => { | ||
| // Handle the response as you desire, f.e. when the server does not respond directly with the CKC | ||
| if (response && response.getFairplayLicenseResponse | ||
| && response.getFairplayLicenseResponse.ckcResponse) { | ||
| return response.getFairplayLicenseResponse.ckcResponse; | ||
| } | ||
| throw new Error('No correct response'); | ||
| }) | ||
| .catch((error) => { | ||
| console.error('CKC error', error); | ||
| }); | ||
| } | ||
| ``` | ||
|
|
||
| Platforms: Android, iOS | ||
|
|
||
| ###### type | ||
|
|
||
| You can specify the DRM type, either by string or using the exported DRMType enum. | ||
| Valid values are, for Android: DRMType.WIDEVINE / DRMType.PLAYREADY / DRMType.CLEARKEY. | ||
| for iOS: DRMType.FAIRPLAY | ||
|
|
||
| ###### Other protocols | ||
|
|
||
|
|
@@ -1202,8 +1261,8 @@ To enable audio to play in background on iOS the audio session needs to be set t | |
|
|
||
| ### Version 4.0.0 | ||
|
|
||
| #### Gradle 3 and SDK 26 requirement | ||
| In order to support ExoPlayer 2.9.0, you must use version 3 or higher of the Gradle plugin. This is included by default in React Native 0.57. ExoPlayer | ||
| #### Gradle 3 and target SDK 26 requirement | ||
| In order to support ExoPlayer 2.9.0, you must use version 3 or higher of the Gradle plugin. This is included by default in React Native 0.57. | ||
|
|
||
| #### ExoPlayer 2.9.0 Java 1.8 requirement | ||
| ExoPlayer 2.9.0 uses some Java 1.8 features, so you may need to enable support for Java 1.8 in your app/build.gradle file. If you get an error, compiling with ExoPlayer like: | ||
|
|
@@ -1238,7 +1297,7 @@ Previously, on Android MediaPlayer if you setup an AppState event when the app w | |
|
|
||
| Note, Windows does not have a concept of an app going into the background, so this doesn't apply there. | ||
|
|
||
| #### Use Android SDK 27 by default | ||
| #### Use Android target SDK 27 by default | ||
| Version 3.0 updates the Android build tools and SDK to version 27. React Native is in the process of [switchting over](https://github.com/facebook/react-native/issues/18095#issuecomment-395596130) to SDK 27 in preparation for Google's requirement that new Android apps [use SDK 26](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html) by August 2018. | ||
|
|
||
| You will either need to install the version 27 SDK and version 27.0.3 buildtools or modify your build.gradle file to configure react-native-video to use the same build settings as the rest of your app as described below. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ const styles = StyleSheet.create({ | |
| }, | ||
| }); | ||
|
|
||
| export { TextTrackType, FilterType }; | ||
| export { TextTrackType, FilterType, DRMType }; | ||
|
|
||
| export default class Video extends Component { | ||
|
|
||
|
|
@@ -211,6 +211,27 @@ export default class Video extends Component { | |
| } | ||
| }; | ||
|
|
||
| _onGetLicense = (event) => { | ||
| if (this.props.source && this.props.source.drm && this.props.source.drm.getLicense instanceof Function) { | ||
| const data = event.nativeEvent; | ||
| if (data && data.spc) { | ||
| const getLicenseOverride = this.props.source.drm.getLicense(data.spc, this.props); | ||
| const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not. | ||
| getLicensePromise.then((result => { | ||
| if (result !== undefined) { | ||
| NativeModules.VideoManager.setLicenseResult(result, findNodeHandle(this._root)); | ||
| } else { | ||
| NativeModules.VideoManager.setLicenseError('Empty license result', findNodeHandle(this._root)); | ||
| } | ||
| })).catch((error) => { | ||
| NativeModules.VideoManager.setLicenseError(error, findNodeHandle(this._root)); | ||
| }); | ||
| } | ||
|
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. What if there's no |
||
| } else { | ||
| NativeModules.VideoManager.setLicenseError("No enough data for license override", findNodeHandle(this._root)); | ||
|
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 enough…" would be a bit better 😁 |
||
| } | ||
| } | ||
|
|
||
| render() { | ||
| const resizeMode = this.props.resizeMode; | ||
| const source = resolveAssetSource(this.props.source) || {}; | ||
|
|
@@ -269,8 +290,9 @@ export default class Video extends Component { | |
| onPlaybackRateChange: this._onPlaybackRateChange, | ||
| onAudioFocusChanged: this._onAudioFocusChanged, | ||
| onAudioBecomingNoisy: this._onAudioBecomingNoisy, | ||
| onGetLicense: this._onGetLicense, | ||
| }); | ||
|
|
||
|
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 needed? |
||
| const posterStyle = { | ||
| ...StyleSheet.absoluteFillObject, | ||
| resizeMode: this.props.posterResizeMode || 'contain', | ||
|
|
@@ -398,9 +420,6 @@ Video.propTypes = { | |
| }), | ||
| stereoPan: PropTypes.number, | ||
| rate: PropTypes.number, | ||
| drmUrl: PropTypes.string, | ||
| drmName: PropTypes.string, | ||
| drmHeader: PropTypes.object, | ||
| playInBackground: PropTypes.bool, | ||
| playWhenInactive: PropTypes.bool, | ||
| ignoreSilentSwitch: PropTypes.oneOf(['ignore', 'obey']), | ||
|
|
||
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.
Isn't this a minor update the least?
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.
changed to next so they can decide