mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +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.HttpDataSource;
|
||||
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.Util;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -104,14 +104,19 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
|
||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request)
|
||||
throws MediaDrmCallbackException {
|
||||
String url =
|
||||
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
|
||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception {
|
||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws MediaDrmCallbackException {
|
||||
String url = request.getLicenseServerUrl();
|
||||
if (forceDefaultLicenseUrl || TextUtils.isEmpty(url)) {
|
||||
url = defaultLicenseUrl;
|
||||
|
|
@ -136,41 +141,56 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
|
|||
HttpDataSource.Factory dataSourceFactory,
|
||||
String url,
|
||||
@Nullable byte[] httpBody,
|
||||
@Nullable Map<String, String> requestProperties)
|
||||
throws IOException {
|
||||
HttpDataSource dataSource = dataSourceFactory.createDataSource();
|
||||
Map<String, String> requestProperties)
|
||||
throws MediaDrmCallbackException {
|
||||
StatsDataSource dataSource = new StatsDataSource(dataSourceFactory.createDataSource());
|
||||
int manualRedirectCount = 0;
|
||||
while (true) {
|
||||
DataSpec dataSpec =
|
||||
new DataSpec.Builder()
|
||||
.setUri(url)
|
||||
.setHttpRequestHeaders(
|
||||
requestProperties != null ? requestProperties : Collections.emptyMap())
|
||||
.setHttpMethod(DataSpec.HTTP_METHOD_POST)
|
||||
.setHttpBody(httpBody)
|
||||
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
|
||||
.build();
|
||||
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
||||
try {
|
||||
return Util.toByteArray(inputStream);
|
||||
} catch (InvalidResponseCodeException e) {
|
||||
// For POST requests, the underlying network stack will not normally follow 307 or 308
|
||||
// redirects automatically. Do so manually here.
|
||||
boolean manuallyRedirect =
|
||||
(e.responseCode == 307 || e.responseCode == 308)
|
||||
&& manualRedirectCount++ < MAX_MANUAL_REDIRECTS;
|
||||
@Nullable String redirectUrl = manuallyRedirect ? getRedirectUrl(e) : null;
|
||||
if (redirectUrl == null) {
|
||||
throw e;
|
||||
DataSpec dataSpec =
|
||||
new DataSpec.Builder()
|
||||
.setUri(url)
|
||||
.setHttpRequestHeaders(requestProperties)
|
||||
.setHttpMethod(DataSpec.HTTP_METHOD_POST)
|
||||
.setHttpBody(httpBody)
|
||||
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
|
||||
.build();
|
||||
DataSpec originalDataSpec = dataSpec;
|
||||
try {
|
||||
while (true) {
|
||||
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
||||
try {
|
||||
return Util.toByteArray(inputStream);
|
||||
} catch (InvalidResponseCodeException e) {
|
||||
@Nullable String redirectUrl = getRedirectUrl(e, manualRedirectCount);
|
||||
if (redirectUrl == null) {
|
||||
throw e;
|
||||
}
|
||||
manualRedirectCount++;
|
||||
dataSpec = dataSpec.buildUpon().setUri(redirectUrl).build();
|
||||
} 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;
|
||||
if (headerFields != null) {
|
||||
@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.ProvisionRequest;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -39,12 +38,12 @@ public final class LocalMediaDrmCallback implements MediaDrmCallback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
|
||||
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception {
|
||||
public byte[] executeKeyRequest(UUID uuid, KeyRequest request) {
|
||||
return keyResponse;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ public interface MediaDrmCallback {
|
|||
* @param uuid The UUID of the content protection scheme.
|
||||
* @param request The request.
|
||||
* @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.
|
||||
|
|
@ -40,7 +41,7 @@ public interface MediaDrmCallback {
|
|||
* @param uuid The UUID of the content protection scheme.
|
||||
* @param request The request.
|
||||
* @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