Commit 98919fe7 by olly Committed by Oliver Woodman

Add ExoMediaDrm/ExoMediaCrypto to V2

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=131693379
parent 1fbe62c6
...@@ -43,6 +43,8 @@ import com.google.android.exoplayer2.ExoPlayerFactory; ...@@ -43,6 +43,8 @@ import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager; import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer2.drm.UnsupportedDrmException; import com.google.android.exoplayer2.drm.UnsupportedDrmException;
...@@ -367,7 +369,8 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi ...@@ -367,7 +369,8 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
return new DefaultHttpDataSource(userAgent, null); return new DefaultHttpDataSource(userAgent, null);
} }
}); });
return new StreamingDrmSessionManager(uuid, drmCallback, null, mainHandler, eventLogger); return new StreamingDrmSessionManager<FrameworkMediaCrypto>(uuid,
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger);
} }
private void releasePlayer() { private void releasePlayer() {
......
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
...@@ -104,8 +105,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -104,8 +105,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
*/ */
public MediaCodecAudioRenderer(MediaCodecSelector mediaCodecSelector, public MediaCodecAudioRenderer(MediaCodecSelector mediaCodecSelector,
DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
Handler eventHandler, AudioRendererEventListener eventListener) { boolean playClearSamplesWithoutKeys, Handler eventHandler,
AudioRendererEventListener eventListener) {
this(mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, this(mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, eventHandler,
eventListener, null, AudioManager.STREAM_MUSIC); eventListener, null, AudioManager.STREAM_MUSIC);
} }
...@@ -127,9 +129,10 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -127,9 +129,10 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
* @param streamType The type of audio stream for the {@link AudioTrack}. * @param streamType The type of audio stream for the {@link AudioTrack}.
*/ */
public MediaCodecAudioRenderer(MediaCodecSelector mediaCodecSelector, public MediaCodecAudioRenderer(MediaCodecSelector mediaCodecSelector,
DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
Handler eventHandler, AudioRendererEventListener eventListener, boolean playClearSamplesWithoutKeys, Handler eventHandler,
AudioCapabilities audioCapabilities, int streamType) { AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities,
int streamType) {
super(C.TRACK_TYPE_AUDIO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); super(C.TRACK_TYPE_AUDIO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys);
audioSessionId = AudioTrack.SESSION_ID_NOT_SET; audioSessionId = AudioTrack.SESSION_ID_NOT_SET;
audioTrack = new AudioTrack(audioCapabilities, streamType); audioTrack = new AudioTrack(audioCapabilities, streamType);
......
...@@ -16,13 +16,12 @@ ...@@ -16,13 +16,12 @@
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.drm;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.MediaCrypto;
/** /**
* A DRM session. * A DRM session.
*/ */
@TargetApi(16) @TargetApi(16)
public interface DrmSession { public interface DrmSession<T extends ExoMediaCrypto> {
/** /**
* The session has encountered an error. {@link #getError()} can be used to retrieve the cause. * The session has encountered an error. {@link #getError()} can be used to retrieve the cause.
...@@ -54,22 +53,23 @@ public interface DrmSession { ...@@ -54,22 +53,23 @@ public interface DrmSession {
int getState(); int getState();
/** /**
* Returns a {@link MediaCrypto} for the open session. * Returns a {@link ExoMediaCrypto} for the open session.
* <p> * <p>
* This method may be called when the session is in the following states: * This method may be called when the session is in the following states:
* {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS} * {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS}
* *
* @return A {@link MediaCrypto} for the open session. * @return A {@link ExoMediaCrypto} for the open session.
* @throws IllegalStateException If called when a session isn't opened. * @throws IllegalStateException If called when a session isn't opened.
*/ */
MediaCrypto getMediaCrypto(); T getMediaCrypto();
/** /**
* Whether the session requires a secure decoder for the specified mime type. * Whether the session requires a secure decoder for the specified mime type.
* <p> * <p>
* Normally this method should return {@link MediaCrypto#requiresSecureDecoderComponent(String)}, * Normally this method should return
* however in some cases implementations may wish to modify the return value (i.e. to force a * {@link ExoMediaCrypto#requiresSecureDecoderComponent(String)}, however in some cases
* secure decoder even when one is not required). * implementations may wish to modify the return value (i.e. to force a secure decoder even when
* one is not required).
* <p> * <p>
* This method may be called when the session is in the following states: * This method may be called when the session is in the following states:
* {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS} * {@link #STATE_OPENED}, {@link #STATE_OPENED_WITH_KEYS}
......
...@@ -22,7 +22,7 @@ import android.os.Looper; ...@@ -22,7 +22,7 @@ import android.os.Looper;
* Manages a DRM session. * Manages a DRM session.
*/ */
@TargetApi(16) @TargetApi(16)
public interface DrmSessionManager { public interface DrmSessionManager<T extends ExoMediaCrypto> {
/** /**
* Acquires a {@link DrmSession} for the specified {@link DrmInitData}. The {@link DrmSession} * Acquires a {@link DrmSession} for the specified {@link DrmInitData}. The {@link DrmSession}
...@@ -32,7 +32,7 @@ public interface DrmSessionManager { ...@@ -32,7 +32,7 @@ public interface DrmSessionManager {
* @param drmInitData DRM initialization data. * @param drmInitData DRM initialization data.
* @return The DRM session. * @return The DRM session.
*/ */
DrmSession acquireSession(Looper playbackLooper, DrmInitData drmInitData); DrmSession<T> acquireSession(Looper playbackLooper, DrmInitData drmInitData);
/** /**
* Releases a {@link DrmSession}. * Releases a {@link DrmSession}.
......
/*
* Copyright (C) 2016 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;
/**
* An opaque {@link android.media.MediaCrypto} equivalent.
*/
public interface ExoMediaCrypto {
/**
* @see android.media.MediaCrypto#requiresSecureDecoderComponent(String)
*/
boolean requiresSecureDecoderComponent(String mimeType);
}
/*
* Copyright (C) 2016 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.media.DeniedByServerException;
import android.media.MediaCryptoException;
import android.media.MediaDrm;
import android.media.NotProvisionedException;
import android.media.ResourceBusyException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Used to obtain keys for decrypting protected media streams. See {@link android.media.MediaDrm}.
*/
public interface ExoMediaDrm<T extends ExoMediaCrypto> {
/**
* @see android.media.MediaDrm.OnEventListener
*/
interface OnEventListener<T extends ExoMediaCrypto> {
/**
* Called when an event occurs that requires the app to be notified
*
* @param mediaDrm the {@link ExoMediaDrm} object on which the event occurred.
* @param sessionId the DRM session ID on which the event occurred
* @param event indicates the event type
* @param extra an secondary error code
* @param data optional byte array of data that may be associated with the event
*/
void onEvent(ExoMediaDrm<? extends T> mediaDrm, byte[] sessionId, int event, int extra,
byte[] data);
}
/**
* @see android.media.MediaDrm.KeyRequest
*/
interface KeyRequest {
byte[] getData();
String getDefaultUrl();
}
/**
* @see android.media.MediaDrm.ProvisionRequest
*/
interface ProvisionRequest {
byte[] getData();
String getDefaultUrl();
}
/**
* @see MediaDrm#setOnEventListener(MediaDrm.OnEventListener)
*/
void setOnEventListener(OnEventListener<? super T> listener);
/**
* @see MediaDrm#openSession()
*/
byte[] openSession() throws NotProvisionedException, ResourceBusyException;
/**
* @see MediaDrm#closeSession(byte[])
*/
void closeSession(byte[] sessionId);
/**
* @see MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)
*/
KeyRequest getKeyRequest(byte[] scope, byte[] init, String mimeType, int keyType,
HashMap<String, String> optionalParameters) throws NotProvisionedException;
/**
* @see MediaDrm#provideKeyResponse(byte[], byte[])
*/
byte[] provideKeyResponse(byte[] scope, byte[] response)
throws NotProvisionedException, DeniedByServerException;
/**
* @see MediaDrm#getProvisionRequest()
*/
ProvisionRequest getProvisionRequest();
/**
* @see MediaDrm#provideProvisionResponse(byte[])
*/
void provideProvisionResponse(byte[] response) throws DeniedByServerException;
/**
* @see MediaDrm#queryKeyStatus(byte[]).
*/
Map<String, String> queryKeyStatus(byte[] sessionId);
/**
* @see MediaDrm#release().
*/
void release();
/**
* @see MediaDrm#restoreKeys(byte[], byte[]).
*/
void restoreKeys(byte[] sessionId, byte[] keySetId);
/**
* @see MediaDrm#getPropertyString(String)
*/
String getPropertyString(String propertyName);
/**
* @see MediaDrm#getPropertyByteArray(String)
*/
byte[] getPropertyByteArray(String propertyName);
/**
* @see MediaDrm#setPropertyString(String, String)
*/
void setPropertyString(String propertyName, String value);
/**
* @see MediaDrm#setPropertyByteArray(String, byte[])
*/
void setPropertyByteArray(String propertyName, byte[] value);
/**
* @see android.media.MediaCrypto#MediaCrypto(UUID, byte[])
*
* @param uuid The UUID of the crypto scheme.
* @param initData Opaque initialization data specific to the crypto scheme.
* @return An object extends {@link ExoMediaCrypto}, using opaque crypto scheme specific data.
* @throws MediaCryptoException
*/
T createMediaCrypto(UUID uuid, byte[] initData) throws MediaCryptoException;
}
/*
* Copyright (C) 2016 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.annotation.TargetApi;
import android.media.MediaCrypto;
import com.google.android.exoplayer2.util.Assertions;
/**
* An {@link ExoMediaCrypto} implementation that wraps the framework {@link MediaCrypto}.
*/
@TargetApi(16)
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
private final MediaCrypto mediaCrypto;
/* package */ FrameworkMediaCrypto(MediaCrypto mediaCrypto) {
this.mediaCrypto = Assertions.checkNotNull(mediaCrypto);
}
public MediaCrypto getWrappedMediaCrypto() {
return mediaCrypto;
}
@Override
public boolean requiresSecureDecoderComponent(String mimeType) {
return mediaCrypto.requiresSecureDecoderComponent(mimeType);
}
}
/*
* Copyright (C) 2016 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.annotation.TargetApi;
import android.media.DeniedByServerException;
import android.media.MediaCrypto;
import android.media.MediaCryptoException;
import android.media.MediaDrm;
import android.media.NotProvisionedException;
import android.media.ResourceBusyException;
import android.media.UnsupportedSchemeException;
import com.google.android.exoplayer2.util.Assertions;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* An {@link ExoMediaDrm} implementation that wraps the framework {@link MediaDrm}.
*/
@TargetApi(18)
public final class FrameworkMediaDrm implements ExoMediaDrm<FrameworkMediaCrypto> {
private final MediaDrm mediaDrm;
/**
* Creates an instance for the specified scheme UUID.
*
* @param uuid The scheme uuid.
* @return The created instance.
* @throws UnsupportedDrmException If the DRM scheme is unsupported or cannot be instantiated.
*/
public static FrameworkMediaDrm newInstance(UUID uuid) throws UnsupportedDrmException {
try {
return new FrameworkMediaDrm(uuid);
} catch (UnsupportedSchemeException e) {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME, e);
} catch (Exception e) {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e);
}
}
private FrameworkMediaDrm(UUID uuid) throws UnsupportedSchemeException {
this.mediaDrm = new MediaDrm(Assertions.checkNotNull(uuid));
}
@Override
public void setOnEventListener(
final ExoMediaDrm.OnEventListener<? super FrameworkMediaCrypto> listener) {
mediaDrm.setOnEventListener(listener == null ? null : new MediaDrm.OnEventListener() {
@Override
public void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) {
listener.onEvent(FrameworkMediaDrm.this, sessionId, event, extra, data);
}
});
}
@Override
public byte[] openSession() throws NotProvisionedException, ResourceBusyException {
return mediaDrm.openSession();
}
@Override
public void closeSession(byte[] sessionId) {
mediaDrm.closeSession(sessionId);
}
@Override
public KeyRequest getKeyRequest(byte[] scope, byte[] init, String mimeType, int keyType,
HashMap<String, String> optionalParameters) throws NotProvisionedException {
final MediaDrm.KeyRequest request = mediaDrm.getKeyRequest(scope, init, mimeType, keyType,
optionalParameters);
return new KeyRequest() {
@Override
public byte[] getData() {
return request.getData();
}
@Override
public String getDefaultUrl() {
return request.getDefaultUrl();
}
};
}
@Override
public byte[] provideKeyResponse(byte[] scope, byte[] response)
throws NotProvisionedException, DeniedByServerException {
return mediaDrm.provideKeyResponse(scope, response);
}
@Override
public ProvisionRequest getProvisionRequest() {
final MediaDrm.ProvisionRequest provisionRequest = mediaDrm.getProvisionRequest();
return new ProvisionRequest() {
@Override
public byte[] getData() {
return provisionRequest.getData();
}
@Override
public String getDefaultUrl() {
return provisionRequest.getDefaultUrl();
}
};
}
@Override
public void provideProvisionResponse(byte[] response) throws DeniedByServerException {
mediaDrm.provideProvisionResponse(response);
}
@Override
public Map<String, String> queryKeyStatus(byte[] sessionId) {
return mediaDrm.queryKeyStatus(sessionId);
}
@Override
public void release() {
mediaDrm.release();
}
@Override
public void restoreKeys(byte[] sessionId, byte[] keySetId) {
mediaDrm.restoreKeys(sessionId, keySetId);
}
@Override
public String getPropertyString(String propertyName) {
return mediaDrm.getPropertyString(propertyName);
}
@Override
public byte[] getPropertyByteArray(String propertyName) {
return mediaDrm.getPropertyByteArray(propertyName);
}
@Override
public void setPropertyString(String propertyName, String value) {
mediaDrm.setPropertyString(propertyName, value);
}
@Override
public void setPropertyByteArray(String propertyName, byte[] value) {
mediaDrm.setPropertyByteArray(propertyName, value);
}
@Override
public FrameworkMediaCrypto createMediaCrypto(UUID uuid, byte[] initData)
throws MediaCryptoException {
return new FrameworkMediaCrypto(new MediaCrypto(uuid, initData));
}
}
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.drm;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.MediaDrm.KeyRequest;
import android.media.MediaDrm.ProvisionRequest;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
import com.google.android.exoplayer2.upstream.DataSourceInputStream; 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;
......
...@@ -15,14 +15,13 @@ ...@@ -15,14 +15,13 @@
*/ */
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.drm;
import android.annotation.TargetApi; import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
import android.media.MediaDrm; import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
import java.util.UUID; import java.util.UUID;
/** /**
* Performs {@link MediaDrm} key and provisioning requests. * Performs {@link ExoMediaDrm} key and provisioning requests.
*/ */
@TargetApi(18)
public interface MediaDrmCallback { public interface MediaDrmCallback {
/** /**
...@@ -33,7 +32,7 @@ public interface MediaDrmCallback { ...@@ -33,7 +32,7 @@ public interface MediaDrmCallback {
* @return The response data. * @return The response data.
* @throws Exception If an error occurred executing the request. * @throws Exception If an error occurred executing the request.
*/ */
byte[] executeProvisionRequest(UUID uuid, MediaDrm.ProvisionRequest request) throws Exception; byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws Exception;
/** /**
* Executes a key request. * Executes a key request.
...@@ -43,6 +42,6 @@ public interface MediaDrmCallback { ...@@ -43,6 +42,6 @@ public interface MediaDrmCallback {
* @return The response data. * @return The response data.
* @throws Exception If an error occurred executing the request. * @throws Exception If an error occurred executing the request.
*/ */
byte[] executeKeyRequest(UUID uuid, MediaDrm.KeyRequest request) throws Exception; byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception;
} }
...@@ -18,13 +18,8 @@ package com.google.android.exoplayer2.drm; ...@@ -18,13 +18,8 @@ package com.google.android.exoplayer2.drm;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.DeniedByServerException; import android.media.DeniedByServerException;
import android.media.MediaCrypto;
import android.media.MediaDrm; import android.media.MediaDrm;
import android.media.MediaDrm.KeyRequest;
import android.media.MediaDrm.OnEventListener;
import android.media.MediaDrm.ProvisionRequest;
import android.media.NotProvisionedException; import android.media.NotProvisionedException;
import android.media.UnsupportedSchemeException;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper; import android.os.Looper;
...@@ -32,6 +27,9 @@ import android.os.Message; ...@@ -32,6 +27,9 @@ import android.os.Message;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
import com.google.android.exoplayer2.drm.ExoMediaDrm.OnEventListener;
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil; import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil;
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;
...@@ -42,7 +40,8 @@ import java.util.UUID; ...@@ -42,7 +40,8 @@ import java.util.UUID;
* A {@link DrmSessionManager} that supports streaming playbacks using {@link MediaDrm}. * A {@link DrmSessionManager} that supports streaming playbacks using {@link MediaDrm}.
*/ */
@TargetApi(18) @TargetApi(18)
public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession { public class StreamingDrmSessionManager<T extends ExoMediaCrypto> implements DrmSessionManager,
DrmSession<T> {
/** /**
* Listener of {@link StreamingDrmSessionManager} events. * Listener of {@link StreamingDrmSessionManager} events.
...@@ -73,7 +72,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -73,7 +72,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
private final Handler eventHandler; private final Handler eventHandler;
private final EventListener eventListener; private final EventListener eventListener;
private final MediaDrm mediaDrm; private final ExoMediaDrm<T> mediaDrm;
private final HashMap<String, String> optionalKeyRequestParameters; private final HashMap<String, String> optionalKeyRequestParameters;
/* package */ final MediaDrmCallback callback; /* package */ final MediaDrmCallback callback;
...@@ -89,7 +88,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -89,7 +88,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
private int openCount; private int openCount;
private boolean provisioningInProgress; private boolean provisioningInProgress;
private int state; private int state;
private MediaCrypto mediaCrypto; private T mediaCrypto;
private Exception lastException; private Exception lastException;
private SchemeData schemeData; private SchemeData schemeData;
private byte[] sessionId; private byte[] sessionId;
...@@ -105,10 +104,10 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -105,10 +104,10 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public static StreamingDrmSessionManager newWidevineInstance(MediaDrmCallback callback, public static StreamingDrmSessionManager<FrameworkMediaCrypto> newWidevineInstance(
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters,
EventListener eventListener) throws UnsupportedDrmException { Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException {
return new StreamingDrmSessionManager(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters, return newFrameworkInstance(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters,
eventHandler, eventListener); eventHandler, eventListener);
} }
...@@ -125,9 +124,9 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -125,9 +124,9 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public static StreamingDrmSessionManager newPlayReadyInstance(MediaDrmCallback callback, public static StreamingDrmSessionManager<FrameworkMediaCrypto> newPlayReadyInstance(
String customData, Handler eventHandler, EventListener eventListener) MediaDrmCallback callback, String customData, Handler eventHandler,
throws UnsupportedDrmException { EventListener eventListener) throws UnsupportedDrmException {
HashMap<String, String> optionalKeyRequestParameters; HashMap<String, String> optionalKeyRequestParameters;
if (!TextUtils.isEmpty(customData)) { if (!TextUtils.isEmpty(customData)) {
optionalKeyRequestParameters = new HashMap<>(); optionalKeyRequestParameters = new HashMap<>();
...@@ -135,11 +134,13 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -135,11 +134,13 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
} else { } else {
optionalKeyRequestParameters = null; optionalKeyRequestParameters = null;
} }
return new StreamingDrmSessionManager(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters, return newFrameworkInstance(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters,
eventHandler, eventListener); eventHandler, eventListener);
} }
/** /**
* Instantiates a new instance.
*
* @param uuid The UUID of the drm scheme. * @param uuid The UUID of the drm scheme.
* @param callback Performs key and provisioning requests. * @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
...@@ -149,21 +150,32 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -149,21 +150,32 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported. * @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/ */
public StreamingDrmSessionManager(UUID uuid, MediaDrmCallback callback, public static StreamingDrmSessionManager<FrameworkMediaCrypto> newFrameworkInstance(
UUID uuid, MediaDrmCallback callback, HashMap<String, String> optionalKeyRequestParameters,
Handler eventHandler, EventListener eventListener) throws UnsupportedDrmException {
return new StreamingDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), callback,
optionalKeyRequestParameters, eventHandler, eventListener);
}
/**
* @param uuid The UUID of the drm scheme.
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
*/
public StreamingDrmSessionManager(UUID uuid, ExoMediaDrm<T> mediaDrm, MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler, HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
EventListener eventListener) throws UnsupportedDrmException { EventListener eventListener) {
this.uuid = uuid; this.uuid = uuid;
this.mediaDrm = mediaDrm;
this.callback = callback; this.callback = callback;
this.optionalKeyRequestParameters = optionalKeyRequestParameters; this.optionalKeyRequestParameters = optionalKeyRequestParameters;
this.eventHandler = eventHandler; this.eventHandler = eventHandler;
this.eventListener = eventListener; this.eventListener = eventListener;
try {
mediaDrm = new MediaDrm(uuid);
} catch (UnsupportedSchemeException e) {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME, e);
} catch (Exception e) {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e);
}
mediaDrm.setOnEventListener(new MediaDrmEventListener()); mediaDrm.setOnEventListener(new MediaDrmEventListener());
state = STATE_CLOSED; state = STATE_CLOSED;
} }
...@@ -219,7 +231,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -219,7 +231,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
// DrmSessionManager implementation. // DrmSessionManager implementation.
@Override @Override
public DrmSession acquireSession(Looper playbackLooper, DrmInitData drmInitData) { public DrmSession<T> acquireSession(Looper playbackLooper, DrmInitData drmInitData) {
Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper); Assertions.checkState(this.playbackLooper == null || this.playbackLooper == playbackLooper);
if (++openCount != 1) { if (++openCount != 1) {
return this; return this;
...@@ -284,7 +296,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -284,7 +296,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
} }
@Override @Override
public final MediaCrypto getMediaCrypto() { public final T getMediaCrypto() {
if (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS) { if (state != STATE_OPENED && state != STATE_OPENED_WITH_KEYS) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
...@@ -309,7 +321,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -309,7 +321,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
private void openInternal(boolean allowProvisioning) { private void openInternal(boolean allowProvisioning) {
try { try {
sessionId = mediaDrm.openSession(); sessionId = mediaDrm.openSession();
mediaCrypto = new MediaCrypto(uuid, sessionId); mediaCrypto = mediaDrm.createMediaCrypto(uuid, sessionId);
state = STATE_OPENED; state = STATE_OPENED;
postKeyRequest(); postKeyRequest();
} catch (NotProvisionedException e) { } catch (NotProvisionedException e) {
...@@ -447,10 +459,11 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession ...@@ -447,10 +459,11 @@ public class StreamingDrmSessionManager implements DrmSessionManager, DrmSession
} }
private class MediaDrmEventListener implements OnEventListener { private class MediaDrmEventListener implements OnEventListener<T> {
@Override @Override
public void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data) { public void onEvent(ExoMediaDrm<? extends T> md, byte[] sessionId, int event, int extra,
byte[] data) {
mediaDrmHandler.sendEmptyMessage(event); mediaDrmHandler.sendEmptyMessage(event);
} }
......
...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.decoder.DecoderCounters; ...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -165,7 +166,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -165,7 +166,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private static final int ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT = 32; private static final int ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT = 32;
private final MediaCodecSelector mediaCodecSelector; private final MediaCodecSelector mediaCodecSelector;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager<FrameworkMediaCrypto> drmSessionManager;
private final boolean playClearSamplesWithoutKeys; private final boolean playClearSamplesWithoutKeys;
private final DecoderInputBuffer buffer; private final DecoderInputBuffer buffer;
private final FormatHolder formatHolder; private final FormatHolder formatHolder;
...@@ -174,8 +175,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -174,8 +175,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private Format format; private Format format;
private MediaCodec codec; private MediaCodec codec;
private DrmSession drmSession; private DrmSession<FrameworkMediaCrypto> drmSession;
private DrmSession pendingDrmSession; private DrmSession<FrameworkMediaCrypto> pendingDrmSession;
private boolean codecIsAdaptive; private boolean codecIsAdaptive;
private boolean codecNeedsDiscardToSpsWorkaround; private boolean codecNeedsDiscardToSpsWorkaround;
private boolean codecNeedsFlushWorkaround; private boolean codecNeedsFlushWorkaround;
...@@ -216,7 +217,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -216,7 +217,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* has obtained the keys necessary to decrypt encrypted regions of the media. * has obtained the keys necessary to decrypt encrypted regions of the media.
*/ */
public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector, public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector,
DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys) { DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys) {
super(trackType); super(trackType);
Assertions.checkState(Util.SDK_INT >= 16); Assertions.checkState(Util.SDK_INT >= 16);
this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector); this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
...@@ -296,7 +298,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -296,7 +298,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex()); throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
} else if (drmSessionState == DrmSession.STATE_OPENED } else if (drmSessionState == DrmSession.STATE_OPENED
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) { || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
mediaCrypto = drmSession.getMediaCrypto(); mediaCrypto = drmSession.getMediaCrypto().getWrappedMediaCrypto();
drmSessionRequiresSecureDecoder = drmSession.requiresSecureDecoderComponent(mimeType); drmSessionRequiresSecureDecoder = drmSession.requiresSecureDecoderComponent(mimeType);
} else { } else {
// The drm session isn't open yet. // The drm session isn't open yet.
......
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
...@@ -145,7 +146,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -145,7 +146,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
*/ */
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector,
int videoScalingMode, long allowedJoiningTimeMs, DrmSessionManager drmSessionManager, int videoScalingMode, long allowedJoiningTimeMs,
DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys, Handler eventHandler, boolean playClearSamplesWithoutKeys, Handler eventHandler,
VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) {
super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment