Exoplayer2 DRM 异常 shouldWaitForKeys
Exoplayer2 DRM exception shouldWaitForKeys
您好,我正在将我的工作 DRM 实现从 Exoplayer 1.x 切换到 Exoplayer 2.x,但我有一些例外,我无法播放 DRM 许可的视频。我的 DRM 会话管理器:
protected DrmSessionManager<FrameworkMediaCrypto> generateDrmSessionManager() {
// DRM is only supported on API 18 + in the ExoPlayer
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return null;
}
// Widevine will capture the majority of use cases however playready is supported on all AndroidTV devices
UUID uuid = C.WIDEVINE_UUID;
final String licenseURL = "http://video.aaa";
HttpMediaDrmCallback drmCallback =
new HttpMediaDrmCallback(
licenseURL, buildHttpDataSourceFactory(false), KEY_REQUEST_PROPERTIES);
try {
return new DefaultDrmSessionManager<>(
uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, capabilitiesListener);
} catch (Exception e) {
Log.d(TAG, "Unable to create a DrmSessionManager due to an exception", e);
return null;
}
}
我有 drmSession,然后当 HttpMediaDrmCallback 执行时
executePost(dataSourceFactory, url, request.getData(), requestProperties);
里面有调用时导致onDrmSessionManagerError
(java.lang.IllegalArgumentException)的调用:
HttpDataSource dataSource = dataSourceFactory.createDataSource();
在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:735)
在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:676)
在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:511)
在 com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:479)
在 com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:308)
在 android.os.Handler.dispatchMessage(Handler.java:98)
在 android.os.Looper.loop(Looper.java:135)
在 android.os.HandlerThread.run(HandlerThread.java:61)
由以下原因引起:com.google.android.exoplayer2.drm.DrmSession$DrmSessionException:java.lang.IllegalArgumentException
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:604)
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:599)
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:559)
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:50)
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:679)
在 android.os.Handler.dispatchMessage(Handler.java:102)
在 android.os.Looper.loop(Looper.java:135)
在 android.os.HandlerThread.run(HandlerThread.java:61)
原因:java.lang.IllegalArgumentException
在 com.google.android.exoplayer2.util.Assertions.checkNotEmpty(Assertions.java:138)
在 com.google.android.exoplayer2.upstream.DefaultHttpDataSource.(DefaultHttpDataSource.java:148)
在 com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory.createDataSourceInternal(DefaultHttpDataSourceFactory.java:81)
在 com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory.createDataSourceInternal(DefaultHttpDataSourceFactory.java:22)
在 com.google.android.exoplayer2.upstream.HttpDataSource$BaseFactory.createDataSource(HttpDataSource.java:176)
在 com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:139)
在 com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:134)
在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:702)
在 android.os.Handler.dispatchMessage(Handler.java:102)
在 android.os.Looper.loop(Looper.java:135)
在 android.os.HandlerThread.run(HandlerThread.java:61)
我不知道它为什么会崩溃,因为在我的 Exoplayer 1.x 实现中运行良好。
异常是由于此处的userAgent字符串为空或零长度引起的:
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate,
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis,
int readTimeoutMillis, boolean allowCrossProtocolRedirects,
RequestProperties defaultRequestProperties) {
this.userAgent = Assertions.checkNotEmpty(userAgent); <---- Exception is here
this.contentTypePredicate = contentTypePredicate;
this.listener = listener;
this.requestProperties = new RequestProperties();
this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis;
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
this.defaultRequestProperties = defaultRequestProperties;
}
userAgent 是应用程序名称和 ExoPlayer 库版本的组合:
/**
* Returns a user agent string based on the given application name and the library version.
*
* @param context A valid context of the calling application.
* @param applicationName String that will be prefix'ed to the generated user agent.
* @return A user agent string generated using the applicationName and the library version.
*/
public static String getUserAgent(Context context, String applicationName) {
String versionName;
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
versionName = info.versionName;
} catch (NameNotFoundException e) {
versionName = "?";
}
return applicationName + "/" + versionName + " (Linux;Android " + Build.VERSION.RELEASE
+ ") " + ExoPlayerLibraryInfo.VERSION_SLASHY;
}
您可以在演示应用程序中看到使用和设置它的示例:https://github.com/google/ExoPlayer/tree/release-v2/demo
文档 (https://google.github.io/ExoPlayer/guide.html) 中还有关于设置 MediaPlayer 的信息,其中包括显示正在设置的 userAgent 的示例:
// Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
dataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
您好,我正在将我的工作 DRM 实现从 Exoplayer 1.x 切换到 Exoplayer 2.x,但我有一些例外,我无法播放 DRM 许可的视频。我的 DRM 会话管理器:
protected DrmSessionManager<FrameworkMediaCrypto> generateDrmSessionManager() {
// DRM is only supported on API 18 + in the ExoPlayer
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return null;
}
// Widevine will capture the majority of use cases however playready is supported on all AndroidTV devices
UUID uuid = C.WIDEVINE_UUID;
final String licenseURL = "http://video.aaa";
HttpMediaDrmCallback drmCallback =
new HttpMediaDrmCallback(
licenseURL, buildHttpDataSourceFactory(false), KEY_REQUEST_PROPERTIES);
try {
return new DefaultDrmSessionManager<>(
uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, capabilitiesListener);
} catch (Exception e) {
Log.d(TAG, "Unable to create a DrmSessionManager due to an exception", e);
return null;
}
}
我有 drmSession,然后当 HttpMediaDrmCallback 执行时
executePost(dataSourceFactory, url, request.getData(), requestProperties);
里面有调用时导致onDrmSessionManagerError
(java.lang.IllegalArgumentException)的调用:
HttpDataSource dataSource = dataSourceFactory.createDataSource();
在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.shouldWaitForKeys(MediaCodecRenderer.java:735) 在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.feedInputBuffer(MediaCodecRenderer.java:676) 在 com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:511) 在 com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:479) 在 com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:308) 在 android.os.Handler.dispatchMessage(Handler.java:98) 在 android.os.Looper.loop(Looper.java:135) 在 android.os.HandlerThread.run(HandlerThread.java:61) 由以下原因引起:com.google.android.exoplayer2.drm.DrmSession$DrmSessionException:java.lang.IllegalArgumentException 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onError(DefaultDrmSessionManager.java:604) 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeysError(DefaultDrmSessionManager.java:599) 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.onKeyResponse(DefaultDrmSessionManager.java:559) 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager.access$900(DefaultDrmSessionManager.java:50) 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostResponseHandler.handleMessage(DefaultDrmSessionManager.java:679) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:135) 在 android.os.HandlerThread.run(HandlerThread.java:61) 原因:java.lang.IllegalArgumentException 在 com.google.android.exoplayer2.util.Assertions.checkNotEmpty(Assertions.java:138) 在 com.google.android.exoplayer2.upstream.DefaultHttpDataSource.(DefaultHttpDataSource.java:148) 在 com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory.createDataSourceInternal(DefaultHttpDataSourceFactory.java:81) 在 com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory.createDataSourceInternal(DefaultHttpDataSourceFactory.java:22) 在 com.google.android.exoplayer2.upstream.HttpDataSource$BaseFactory.createDataSource(HttpDataSource.java:176) 在 com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executePost(HttpMediaDrmCallback.java:139) 在 com.google.android.exoplayer2.drm.HttpMediaDrmCallback.executeKeyRequest(HttpMediaDrmCallback.java:134) 在 com.google.android.exoplayer2.drm.DefaultDrmSessionManager$PostRequestHandler.handleMessage(DefaultDrmSessionManager.java:702) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:135) 在 android.os.HandlerThread.run(HandlerThread.java:61)
我不知道它为什么会崩溃,因为在我的 Exoplayer 1.x 实现中运行良好。
异常是由于此处的userAgent字符串为空或零长度引起的:
public DefaultHttpDataSource(String userAgent, Predicate<String> contentTypePredicate,
TransferListener<? super DefaultHttpDataSource> listener, int connectTimeoutMillis,
int readTimeoutMillis, boolean allowCrossProtocolRedirects,
RequestProperties defaultRequestProperties) {
this.userAgent = Assertions.checkNotEmpty(userAgent); <---- Exception is here
this.contentTypePredicate = contentTypePredicate;
this.listener = listener;
this.requestProperties = new RequestProperties();
this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis;
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
this.defaultRequestProperties = defaultRequestProperties;
}
userAgent 是应用程序名称和 ExoPlayer 库版本的组合:
/**
* Returns a user agent string based on the given application name and the library version.
*
* @param context A valid context of the calling application.
* @param applicationName String that will be prefix'ed to the generated user agent.
* @return A user agent string generated using the applicationName and the library version.
*/
public static String getUserAgent(Context context, String applicationName) {
String versionName;
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
versionName = info.versionName;
} catch (NameNotFoundException e) {
versionName = "?";
}
return applicationName + "/" + versionName + " (Linux;Android " + Build.VERSION.RELEASE
+ ") " + ExoPlayerLibraryInfo.VERSION_SLASHY;
}
您可以在演示应用程序中看到使用和设置它的示例:https://github.com/google/ExoPlayer/tree/release-v2/demo
文档 (https://google.github.io/ExoPlayer/guide.html) 中还有关于设置 MediaPlayer 的信息,其中包括显示正在设置的 userAgent 的示例:
// Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
dataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);