Skip to content
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

Support parsing of license server URL from DASH manifest #3393

Closed
ARKMe opened this issue Oct 24, 2017 · 17 comments
Closed

Support parsing of license server URL from DASH manifest #3393

ARKMe opened this issue Oct 24, 2017 · 17 comments
Assignees

Comments

@ARKMe
Copy link

ARKMe commented Oct 24, 2017

I'm trying to play a DASH video with Widevine DRM provided by Azure.
In the manifest, inside the ContentProtection node, I receive: <ms:laurl licenseUrl="XXXXXX" />, but DashManifestParser doesn't parse that node. I'd prefer avoiding to download and parse the video manifest to get the licenseUrl, is there another way to achieve this?

@ojw28
Copy link
Contributor

ojw28 commented Nov 1, 2017

Can you please provide the full manifest, so we can see what's provided there? The url may be provided in more than once place (possibly in encoded form). What happens if you pass defaultLicenseUrl == null to HttpMediaDrmCallback constructor?

@workspace
Copy link

workspace commented Nov 17, 2017

@ARKMe my service uses Azure Media Service too.
We faced the same problem with your cases, and we solved it with custom DashManifestParser and CustomDashManifest.

AzureDashManifest

public class AzureDashManifest extends DashManifest {

  public final String drmLicenseUrl;

  public AzureDashManifest(long availabilityStartTime, long duration, long minBufferTime,
                           boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth,
                           long suggestedPresentationDelay, UtcTimingElement utcTiming,
                           Uri location, String drmLicenseUrl, List<Period> periods) {
    super(availabilityStartTime, duration, minBufferTime, dynamic, minUpdatePeriod,
        timeShiftBufferDepth, suggestedPresentationDelay, utcTiming, location, periods);
    this.drmLicenseUrl = drmLicenseUrl;
  }
}

AzureDashManifestParser

// abstract code
public class AzureDashManifestParser extends DashManifestParser {

  private String drmLicenseUrl = null;

  @Override
  protected AzureDashManifest buildMediaPresentationDescription(...) {
    return new AzureDashManifest(availabilityStartTime, durationMs, minBufferTimeMs,
        dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, utcTiming,
        location, drmLicenseUrl, periods);
  }
  @Override
  protected DrmInitData.SchemeData parseContentProtection(XmlPullParser xpp) throws XmlPullParserException,
      IOException {
...
      } else if (XmlPullParserUtil.isStartTag(xpp, "ms:laurl")) {
        drmLicenseUrl = xpp.getAttributeValue(null, "licenseUrl");
      }
...
}

Then you can use it with following steps below

  1. load manifest with custom classes for Azure (in background thread)
public static AzureDashManifest loadManifest(DataSource dataSource, Uri uri)
		throws IOException {
		DataSpec dataSpec = new DataSpec(uri,
			DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH | DataSpec.FLAG_ALLOW_GZIP);
		ParsingLoadable<DashManifest> loadable = new ParsingLoadable<>(dataSource, dataSpec,
			C.DATA_TYPE_MANIFEST, new AzureDashManifestParser());
		loadable.load();
		return (AzureDashManifest) loadable.getResult();
	}
  1. initialize drm session manager with parsed manifest.
String drmLicenseUrl = manifest.drmLicenseUrl;
Map<String, String> keyRequestProperties = new HashMap<>();
keyRequestProperties.put("Authorization", String.format("Bearer=%s", token));
drmSessionManager = buildDrmSessionManager(drmLicenseUrl, keyRequestProperties);
// then initialize player with this drm session manager.
  1. build media source with sideloaded manifest. you can reuse manifest to build media source.
videoSource = new DashMediaSource(
    manifest, new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mainHandler, null
);

@workspace
Copy link

@ojw28
As you can see from the exoplayer demo, I need to know the drm license url in the step of initializing the player. However, in the case of Azure, it is difficult to know the drm license url because it dynamically constructs the manifest. Once I've solved the problem by implementing a custom class like the above answer, is there any better way?

@ojw28
Copy link
Contributor

ojw28 commented Nov 17, 2017

@AquilesCanta - I think we probably need to add a Uri field to SchemeData, that can be populated in the manifest parser, for this kind of case. Or something like that?

It's somewhat unclear what preference should be given to that Uri vs the one from KeyRequest.getDefaultUrl though. I think we'd probably need to prefer the one provided by KeyRequest.getDefaultUrl if both are present, since that can be used as a mechanism for redirecting license requests to a heartbeat server.

@ojw28 ojw28 changed the title Opening a DASH video with Widevine DRM without knowing licenseUrl Support parsing of license server URL from DASH manifest Nov 17, 2017
@workspace
Copy link

1

@codeindream
Copy link

+1

@AquilesCanta
Copy link
Contributor

Has anyone provided a sample manifest, as requested above?

@workspace
Copy link

workspace commented Feb 13, 2018

Also, you can get Authorization header by using our service api. This dash source is the one of samples in my service. So it does not require any permission.

Manifest url

https://educastmedia.streaming.mediaservices.windows.net/ccfa9378-938f-4368-a7e2-f4705e220c4a/video.ism/Manifest(format=mpd-time-csf)

DRM optional header token Request url

POST https://educast.com/api/v1/video/80/create_drm_token

Request body example

{
  "drm_type" : 1
}

Response example

{
  "token":"urn%3amicrosoft%3aazure%3amediaservices%3acontentkeyidentifier=2737157b-0c18-4c14-a320-3ab9f2870986&Audience=urn%3aeducast%3ausers&ExpiresOn=1518515102&Issuer=https%3a%2f%2feducast.pro&HMACSHA256=b5uMd%2fsgXlAMm3YctOL9k50xE3bHbV6hTeQygbcieD8%3d",
  "expiration_time":"2018-02-13T18:45:02.810084"
}

Usage example - Put token into HttpDrmCallback Header.

// codes from our android application
HashMap<String, String> keyRequestProperties = new HashMap<>();
keyRequestProperties.put("Authorization", String.format("Bearer=%s", drmToken.token()));
for (String key : keyRequestProperties.keySet()) {
    httpMediaDrmCallback.setKeyRequestProperty(key, keyRequestProperties.get(key));
}
return DefaultDrmSessionManager.newWidevineInstance(httpMediaDrmCallback, keyRequestProperties, handler, null);

ojw28 pushed a commit that referenced this issue Jun 18, 2018
Allows DrmInitData to carry a license server URL when the media declares one.

Issue:#3393

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=199643743
@workspace
Copy link

@ojw28 I read commit's changes, however, I can't find anything to parse license server url from manifest (e.g. ms:pro(Azure Media Services's Widevine license url label)). Is it still developing?

@AquilesCanta
Copy link
Contributor

We haven't implemented the parsing part yet. The manifest urls above seem to have expired, can we get a new one? Aside, it would be great to have some kind of specification for the license server url tags, if possible. Can you provide any of them? Thanks.

@AquilesCanta
Copy link
Contributor

Note that at this point, the only required action is to populate the SchemeData in the manifest parser. You can override parseContentProtection and the DrmSessionManager should just pick it up.

@workspace
Copy link

https://backup-educastmedia.streaming.mediaservices.windows.net/e59257e1-ef8f-4556-a654-1bf3633f1f6d/video.ism/Manifest(format=mpd-time-csf)

But this locator url can be changed soon. So, I attached the content of manifest and brief summary for microsoft's xml tag

Manifest(format=mpd-time-csf).zip

It contains license url like
<ms:laurl licenseUrl="https://educastmedia.keydelivery.mediaservices.windows.net/Widevine/?KID=8f26d4a9-e4d9-4971-aeab-782659471d4a"/>

So, ms:laurl will be target to parse. I already used custom parser which overrides parseContentProtection to pick it up.

@AquilesCanta
Copy link
Contributor

Even while using a token I am getting a 401 for the key requests using the provided token:

keyRequestProperties.put("Authorization", String.format("Bearer=%s", "urn%3amicrosoft%3aazure%3amediaservices%3acontentkeyidentifier=b73aac96-9814-4eda-bd81-35a1dd767115&Audience=urn%3aeducast%3ausers&ExpiresOn=1529677294&Issuer=https%3a%2f%2feducast.pro&HMACSHA256=cyKkfWbZCU0n6Wt84ohrE8hMxHX1QAvyJroKjm66g8s%3d"));

Can you help with this? Can you notice anything wrong with the format of the property?

The manifest url is the last one:

https://backup-educastmedia.streaming.mediaservices.windows.net/e59257e1-ef8f-4556-a654-1bf3633f1f6d/video.ism/Manifest(format=mpd-time-csf)

@workspace
Copy link

Did you get token from
https://educast.com/api/v1/video/80/create_drm_token
?
I think you tried to play with mismatching manifest and drm token because of my mistake. Can you follow below guideline to get valid manifest and drm token pair?
0. Target is our video which pk is 80

  1. GET streaming_url from https://educast.com/api/v1/video/80 response
  2. You can get manifest url by appending some format string (streaming_url) + '(format=mpd-time-csf)'
  3. Then, you can get license url by opening manifest.
  4. Get token from https://educast.com/api/v1/video/80/create_drm_token (POST with body {drm_type : 1})
  5. Follow guideline for playing our video in my previous video again.

Thank you!!

ojw28 pushed a commit that referenced this issue Jun 22, 2018
Issue:#3393

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=201694813
@ojw28
Copy link
Contributor

ojw28 commented Jun 25, 2018

I believe this is now fully implemented. @AquilesCanta - Can we close it? Thanks!

@AquilesCanta
Copy link
Contributor

Yes, apologies for not doing it before. @KiminRyu, please try it out and let us know if you run into any issues.

ojw28 pushed a commit that referenced this issue Jul 23, 2018
Allows DrmInitData to carry a license server URL when the media declares one.

Issue:#3393

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=199643743
ojw28 pushed a commit that referenced this issue Jul 23, 2018
Issue:#3393

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=201694813
@google google locked and limited conversation to collaborators Nov 23, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants