mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Make MediaDrmCallback surface more error information
Issue:#7309 PiperOrigin-RevId: 311324242
This commit is contained in:
parent
1c3c7c58ab
commit
025a2c2b62
4 changed files with 123 additions and 40 deletions
|
|
@ -24,9 +24,9 @@ import com.google.android.exoplayer2.upstream.DataSourceInputStream;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
|
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
|
||||||
|
import com.google.android.exoplayer2.upstream.StatsDataSource;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -104,14 +104,19 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
|
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request)
|
||||||
|
throws MediaDrmCallbackException {
|
||||||
String url =
|
String url =
|
||||||
request.getDefaultUrl() + "&signedRequest=" + Util.fromUtf8Bytes(request.getData());
|
request.getDefaultUrl() + "&signedRequest=" + Util.fromUtf8Bytes(request.getData());
|
||||||
return executePost(dataSourceFactory, url, /* httpBody= */ null, /* requestProperties= */ null);
|
return executePost(
|
||||||
|
dataSourceFactory,
|
||||||
|
url,
|
||||||
|
/* httpBody= */ null,
|
||||||
|
/* requestProperties= */ Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception {
|
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws MediaDrmCallbackException {
|
||||||
String url = request.getLicenseServerUrl();
|
String url = request.getLicenseServerUrl();
|
||||||
if (forceDefaultLicenseUrl || TextUtils.isEmpty(url)) {
|
if (forceDefaultLicenseUrl || TextUtils.isEmpty(url)) {
|
||||||
url = defaultLicenseUrl;
|
url = defaultLicenseUrl;
|
||||||
|
|
@ -136,41 +141,56 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
|
||||||
HttpDataSource.Factory dataSourceFactory,
|
HttpDataSource.Factory dataSourceFactory,
|
||||||
String url,
|
String url,
|
||||||
@Nullable byte[] httpBody,
|
@Nullable byte[] httpBody,
|
||||||
@Nullable Map<String, String> requestProperties)
|
Map<String, String> requestProperties)
|
||||||
throws IOException {
|
throws MediaDrmCallbackException {
|
||||||
HttpDataSource dataSource = dataSourceFactory.createDataSource();
|
StatsDataSource dataSource = new StatsDataSource(dataSourceFactory.createDataSource());
|
||||||
int manualRedirectCount = 0;
|
int manualRedirectCount = 0;
|
||||||
while (true) {
|
DataSpec dataSpec =
|
||||||
DataSpec dataSpec =
|
new DataSpec.Builder()
|
||||||
new DataSpec.Builder()
|
.setUri(url)
|
||||||
.setUri(url)
|
.setHttpRequestHeaders(requestProperties)
|
||||||
.setHttpRequestHeaders(
|
.setHttpMethod(DataSpec.HTTP_METHOD_POST)
|
||||||
requestProperties != null ? requestProperties : Collections.emptyMap())
|
.setHttpBody(httpBody)
|
||||||
.setHttpMethod(DataSpec.HTTP_METHOD_POST)
|
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
|
||||||
.setHttpBody(httpBody)
|
.build();
|
||||||
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
|
DataSpec originalDataSpec = dataSpec;
|
||||||
.build();
|
try {
|
||||||
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
while (true) {
|
||||||
try {
|
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
||||||
return Util.toByteArray(inputStream);
|
try {
|
||||||
} catch (InvalidResponseCodeException e) {
|
return Util.toByteArray(inputStream);
|
||||||
// For POST requests, the underlying network stack will not normally follow 307 or 308
|
} catch (InvalidResponseCodeException e) {
|
||||||
// redirects automatically. Do so manually here.
|
@Nullable String redirectUrl = getRedirectUrl(e, manualRedirectCount);
|
||||||
boolean manuallyRedirect =
|
if (redirectUrl == null) {
|
||||||
(e.responseCode == 307 || e.responseCode == 308)
|
throw e;
|
||||||
&& manualRedirectCount++ < MAX_MANUAL_REDIRECTS;
|
}
|
||||||
@Nullable String redirectUrl = manuallyRedirect ? getRedirectUrl(e) : null;
|
manualRedirectCount++;
|
||||||
if (redirectUrl == null) {
|
dataSpec = dataSpec.buildUpon().setUri(redirectUrl).build();
|
||||||
throw e;
|
} finally {
|
||||||
|
Util.closeQuietly(inputStream);
|
||||||
}
|
}
|
||||||
url = redirectUrl;
|
|
||||||
} finally {
|
|
||||||
Util.closeQuietly(inputStream);
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new MediaDrmCallbackException(
|
||||||
|
originalDataSpec,
|
||||||
|
Assertions.checkNotNull(dataSource.getLastOpenedUri()),
|
||||||
|
dataSource.getResponseHeaders(),
|
||||||
|
dataSource.getBytesRead(),
|
||||||
|
/* cause= */ e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable String getRedirectUrl(InvalidResponseCodeException exception) {
|
@Nullable
|
||||||
|
private static String getRedirectUrl(
|
||||||
|
InvalidResponseCodeException exception, int manualRedirectCount) {
|
||||||
|
// For POST requests, the underlying network stack will not normally follow 307 or 308
|
||||||
|
// redirects automatically. Do so manually here.
|
||||||
|
boolean manuallyRedirect =
|
||||||
|
(exception.responseCode == 307 || exception.responseCode == 308)
|
||||||
|
&& manualRedirectCount < MAX_MANUAL_REDIRECTS;
|
||||||
|
if (!manuallyRedirect) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Map<String, List<String>> headerFields = exception.headerFields;
|
Map<String, List<String>> headerFields = exception.headerFields;
|
||||||
if (headerFields != null) {
|
if (headerFields != null) {
|
||||||
@Nullable List<String> locationHeaders = headerFields.get("Location");
|
@Nullable List<String> locationHeaders = headerFields.get("Location");
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.drm;
|
||||||
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
|
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
|
||||||
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
|
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,12 +38,12 @@ public final class LocalMediaDrmCallback implements MediaDrmCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
|
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception {
|
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) {
|
||||||
return keyResponse;
|
return keyResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,10 @@ public interface MediaDrmCallback {
|
||||||
* @param uuid The UUID of the content protection scheme.
|
* @param uuid The UUID of the content protection scheme.
|
||||||
* @param request The request.
|
* @param request The request.
|
||||||
* @return The response data.
|
* @return The response data.
|
||||||
* @throws Exception If an error occurred executing the request.
|
* @throws MediaDrmCallbackException If an error occurred executing the request.
|
||||||
*/
|
*/
|
||||||
byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws Exception;
|
byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request)
|
||||||
|
throws MediaDrmCallbackException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a key request.
|
* Executes a key request.
|
||||||
|
|
@ -40,7 +41,7 @@ public interface MediaDrmCallback {
|
||||||
* @param uuid The UUID of the content protection scheme.
|
* @param uuid The UUID of the content protection scheme.
|
||||||
* @param request The request.
|
* @param request The request.
|
||||||
* @return The response data.
|
* @return The response data.
|
||||||
* @throws Exception If an error occurred executing the request.
|
* @throws MediaDrmCallbackException If an error occurred executing the request.
|
||||||
*/
|
*/
|
||||||
byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception;
|
byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws MediaDrmCallbackException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an error occurs while executing a DRM {@link MediaDrmCallback#executeKeyRequest key}
|
||||||
|
* or {@link MediaDrmCallback#executeProvisionRequest provisioning} request.
|
||||||
|
*/
|
||||||
|
public final class MediaDrmCallbackException extends IOException {
|
||||||
|
|
||||||
|
/** The {@link DataSpec} associated with the request. */
|
||||||
|
public final DataSpec dataSpec;
|
||||||
|
/**
|
||||||
|
* The {@link Uri} after redirections, or {@link #dataSpec dataSpec.uri} if no redirection
|
||||||
|
* occurred.
|
||||||
|
*/
|
||||||
|
public final Uri uriAfterRedirects;
|
||||||
|
/** The HTTP request headers included in the response. */
|
||||||
|
public final Map<String, List<String>> responseHeaders;
|
||||||
|
/** The number of bytes obtained from the server. */
|
||||||
|
public final long bytesLoaded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance with the given values.
|
||||||
|
*
|
||||||
|
* @param dataSpec See {@link #dataSpec}.
|
||||||
|
* @param uriAfterRedirects See {@link #uriAfterRedirects}.
|
||||||
|
* @param responseHeaders See {@link #responseHeaders}.
|
||||||
|
* @param bytesLoaded See {@link #bytesLoaded}.
|
||||||
|
* @param cause The cause of the exception.
|
||||||
|
*/
|
||||||
|
public MediaDrmCallbackException(
|
||||||
|
DataSpec dataSpec,
|
||||||
|
Uri uriAfterRedirects,
|
||||||
|
Map<String, List<String>> responseHeaders,
|
||||||
|
long bytesLoaded,
|
||||||
|
Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
this.dataSpec = dataSpec;
|
||||||
|
this.uriAfterRedirects = uriAfterRedirects;
|
||||||
|
this.responseHeaders = responseHeaders;
|
||||||
|
this.bytesLoaded = bytesLoaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue