@Override public final void onStart(HostActivity host, Surface surface) { // Build the player. DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); trackSelector = buildTrackSelector(host, bandwidthMeter); String userAgent = "ExoPlayerPlaybackTests"; DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = buildDrmSessionManager(userAgent); player = buildExoPlayer(host, surface, trackSelector, drmSessionManager); player.prepare(buildSource(host, Util.getUserAgent(host, userAgent), bandwidthMeter)); player.addListener(this); player.setAudioDebugListener(this); player.setVideoDebugListener(this); player.setPlayWhenReady(true); actionHandler = new Handler(); // Schedule any pending actions. if (pendingSchedule != null) { pendingSchedule.start(player, trackSelector, actionHandler); pendingSchedule = null; } }
@Override protected final DefaultDrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager( final String userAgent) { DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager = null; if (parameters.isWidevineEncrypted) { try { MediaDrmCallback drmCallback = new HttpMediaDrmCallback(parameters.widevineLicenseUrl, new DefaultHttpDataSourceFactory(userAgent)); drmSessionManager = DefaultDrmSessionManager.newWidevineInstance(drmCallback, null, null, null); if (!parameters.useL1Widevine) { drmSessionManager.setPropertyString(SECURITY_LEVEL_PROPERTY, WIDEVINE_SECURITY_LEVEL_3); } if (offlineLicenseKeySetId != null) { drmSessionManager.setMode(DefaultDrmSessionManager.MODE_PLAYBACK, offlineLicenseKeySetId); } } catch (UnsupportedDrmException e) { throw new IllegalStateException(e); } } return drmSessionManager; }
/** * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*} * constants defined in {@link C}. * @param mediaCodecSelector A decoder selector. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. */ public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(trackType); Assertions.checkState(Util.SDK_INT >= 16); this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); formatHolder = new FormatHolder(); decodeOnlyPresentationTimestamps = new ArrayList<>(); outputBufferInfo = new MediaCodec.BufferInfo(); codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReinitializationState = REINITIALIZATION_STATE_NONE; }
/** * @param context A context. * @param mediaCodecSelector A decoder selector. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param drmSessionManager For use with encrypted content. May be null if support for encrypted * content is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @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. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); eventDispatcher = new EventDispatcher(eventHandler, eventListener); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); joiningDeadlineMs = C.TIME_UNSET; currentWidth = Format.NO_VALUE; currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; scalingMode = C.VIDEO_SCALING_MODE_DEFAULT; clearReportedVideoSize(); }
@SuppressWarnings("PMD.AvoidCatchingGenericException") // We are forced to catch Exception as ResourceBusyException is minSdk 19 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public DrmSession<FrameworkMediaCrypto> acquireSession(Looper playbackLooper, DrmInitData drmInitData) { DrmSession<FrameworkMediaCrypto> drmSession; try { SessionId sessionId = SessionId.of(mediaDrm.openSession()); FrameworkMediaCrypto mediaCrypto = mediaDrm.createMediaCrypto(sessionId.asBytes()); mediaDrm.restoreKeys(sessionId.asBytes(), keySetIdToRestore.asBytes()); drmSession = new LocalDrmSession(mediaCrypto, keySetIdToRestore, sessionId); } catch (Exception exception) { drmSession = new InvalidDrmSession(new DrmSession.DrmSessionException(exception)); notifyErrorListener(drmSession); } return drmSession; }
@NonNull public SimpleExoPlayer create(DrmSessionCreator drmSessionCreator, DefaultDrmSessionManager.EventListener drmSessionEventListener, MediaCodecSelector mediaCodecSelector) { DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = drmSessionCreator.create(drmSessionEventListener); RenderersFactory renderersFactory = new SimpleRenderersFactory( context, drmSessionManager, EXTENSION_RENDERER_MODE_OFF, DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS, mediaCodecSelector ); DefaultLoadControl loadControl = new DefaultLoadControl(); return ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl); }
/** * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*} * constants defined in {@link C}. * @param mediaCodecSelector A decoder selector. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. */ public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(trackType); Assertions.checkState(Util.SDK_INT >= 16); this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); formatHolder = new FormatHolder(); decodeOnlyPresentationTimestamps = new ArrayList<>(); outputBufferInfo = new MediaCodec.BufferInfo(); codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReinitializationState = REINITIALIZATION_STATE_NONE; }
/** * @param context A context. * @param mediaCodecSelector A decoder selector. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param drmSessionManager For use with encrypted content. May be null if support for encrypted * content is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @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. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); eventDispatcher = new EventDispatcher(eventHandler, eventListener); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); joiningDeadlineMs = C.TIME_UNSET; currentWidth = Format.NO_VALUE; currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; scalingMode = C.VIDEO_SCALING_MODE_DEFAULT; clearLastReportedVideoSize(); }
private void buildRenderers(Context context, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, ArrayList<Renderer> renderersList, long allowedVideoJoiningTimeMs) { MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer(context, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, allowedVideoJoiningTimeMs, drmSessionManager, false, mainHandler, componentListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY); renderersList.add(videoRenderer); Renderer audioRenderer = new MediaCodecAudioRenderer(MediaCodecSelector.DEFAULT, drmSessionManager, true, mainHandler, componentListener, AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC); renderersList.add(audioRenderer); Renderer textRenderer = new TextRenderer(componentListener, mainHandler.getLooper()); renderersList.add(textRenderer); MetadataRenderer<List<Id3Frame>> id3Renderer = new MetadataRenderer<>(componentListener, mainHandler.getLooper(), new Id3Decoder()); renderersList.add(id3Renderer); }
/** * @param context A context. * @param mediaCodecSelector A decoder selector. * @param videoScalingMode The scaling mode to pass to * {@link MediaCodec#setVideoScalingMode(int)}. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param drmSessionManager For use with encrypted content. May be null if support for encrypted * content is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @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. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, int videoScalingMode, long allowedJoiningTimeMs, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); this.videoScalingMode = videoScalingMode; this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); eventDispatcher = new EventDispatcher(eventHandler, eventListener); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); joiningDeadlineMs = C.TIME_UNSET; currentWidth = Format.NO_VALUE; currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; lastReportedWidth = Format.NO_VALUE; lastReportedHeight = Format.NO_VALUE; lastReportedPixelWidthHeightRatio = Format.NO_VALUE; }
/** * Generates the {@link DrmSessionManager} to use with the {@link RendererProvider}. This will * return null on API's < {@value Build.VERSION_CODES#JELLY_BEAN_MR2} * * @return The {@link DrmSessionManager} to use or <code>null</code> */ @Nullable 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; try { return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), new DelegatedMediaDrmCallback(), null, mainHandler, capabilitiesListener); } catch (Exception e) { Log.d(TAG, "Unable to create a DrmSessionManager due to an exception", e); return null; } }
@Override protected DefaultDrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager( final String userAgent) { if (widevineLicenseUrl == null) { return null; } try { MediaDrmCallback drmCallback = new HttpMediaDrmCallback(widevineLicenseUrl, new DefaultHttpDataSourceFactory(userAgent)); DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager = DefaultDrmSessionManager.newWidevineInstance(drmCallback, null, null, null); if (!useL1Widevine) { drmSessionManager.setPropertyString( SECURITY_LEVEL_PROPERTY, WIDEVINE_SECURITY_LEVEL_3); } if (offlineLicenseKeySetId != null) { drmSessionManager.setMode(DefaultDrmSessionManager.MODE_PLAYBACK, offlineLicenseKeySetId); } return drmSessionManager; } catch (UnsupportedDrmException e) { throw new IllegalStateException(e); } }
/** * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*} * constants defined in {@link C}. * @param mediaCodecSelector A decoder selector. * @param drmSessionManager For use with encrypted media. May be null if support for encrypted * media is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. */ public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys) { super(trackType); Assertions.checkState(Util.SDK_INT >= 16); this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); formatHolder = new FormatHolder(); decodeOnlyPresentationTimestamps = new ArrayList<>(); outputBufferInfo = new MediaCodec.BufferInfo(); codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReinitializationState = REINITIALIZATION_STATE_NONE; }
/** * @param context A context. * @param mediaCodecSelector A decoder selector. * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer * can attempt to seamlessly join an ongoing playback. * @param drmSessionManager For use with encrypted content. May be null if support for encrypted * content is not required. * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions. * For example a media file may start with a short clear region so as to allow playback to * begin in parallel with key acquisition. This parameter specifies whether the renderer is * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @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. * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, @Nullable Handler eventHandler, @Nullable VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.context = context.getApplicationContext(); frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); eventDispatcher = new EventDispatcher(eventHandler, eventListener); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT]; outputStreamOffsetUs = C.TIME_UNSET; joiningDeadlineMs = C.TIME_UNSET; currentWidth = Format.NO_VALUE; currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; scalingMode = C.VIDEO_SCALING_MODE_DEFAULT; clearReportedVideoSize(); }
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid, String licenseUrl, Map<String, String> keyRequestProperties) throws UnsupportedDrmException { if (Util.SDK_INT < 18) { return null; } HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl, buildHttpDataSourceFactory(false), keyRequestProperties); return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger); }
@Override protected void buildVideoRenderers(Context context, Handler mainHandler, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @ExtensionRendererMode int extensionRendererMode, VideoRendererEventListener eventListener, long allowedVideoJoiningTimeMs, ArrayList<Renderer> out) { out.add(new DebugMediaCodecVideoRenderer(context, MediaCodecSelector.DEFAULT, allowedVideoJoiningTimeMs, mainHandler, drmSessionManager, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY)); }
public DebugMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, Handler eventHandler, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, VideoRendererEventListener eventListener, int maxDroppedFrameCountToNotify) { super(context, mediaCodecSelector, allowedJoiningTimeMs, drmSessionManager, false, eventHandler, eventListener, maxDroppedFrameCountToNotify); }
@SuppressWarnings("unused") protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(host, trackSelector, new DefaultLoadControl(), drmSessionManager, SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF, 0); player.setVideoSurface(surface); return player; }
@Override protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = new DebugSimpleExoPlayer(host, trackSelector, new DefaultLoadControl(), drmSessionManager); player.setVideoSurface(surface); return player; }
LocalDrmSessionManager(KeySetId keySetIdToRestore, ExoMediaDrm<FrameworkMediaCrypto> mediaDrm, UUID drmScheme, Handler handler, DefaultDrmSessionManager.EventListener eventListener) { this.keySetIdToRestore = keySetIdToRestore; this.mediaDrm = mediaDrm; this.eventListener = eventListener; this.drmScheme = drmScheme; this.handler = handler; }
private void notifyErrorListener(DrmSession<FrameworkMediaCrypto> drmSession) { final DrmSession.DrmSessionException error = drmSession.getError(); handler.post(new Runnable() { @Override public void run() { eventListener.onDrmSessionManagerError(error); } }); }
@Override public DrmSessionManager<FrameworkMediaCrypto> create(DefaultDrmSessionManager.EventListener eventListener) { return new LocalDrmSessionManager( downloadedModularDrm.getKeySetId(), mediaDrmCreator.create(WIDEVINE_MODULAR_UUID), WIDEVINE_MODULAR_UUID, handler, eventListener ); }
@Override public DrmSessionManager<FrameworkMediaCrypto> create(DefaultDrmSessionManager.EventListener eventListener) { FrameworkMediaDrm frameworkMediaDrm = frameworkMediaDrmCreator.create(WIDEVINE_MODULAR_UUID); return new DefaultDrmSessionManager<>( WIDEVINE_MODULAR_UUID, frameworkMediaDrm, mediaDrmCallback, NO_OPTIONAL_PARAMETERS, handler, eventListener ); }
/** * @param context A {@link Context}. * @param drmSessionManager An optional {@link DrmSessionManager}. May be null if DRM protected * playbacks are not required.. * @param extensionRendererMode The extension renderer mode, which determines if and how * available extension renderers are used. Note that extensions must be included in the * application build for them to be considered available. * @param allowedVideoJoiningTimeMs The maximum duration for which video renderers can attempt * to seamlessly join an ongoing playback. * @param mediaCodecSelector Used for selecting the codec for the video renderer. */ SimpleRenderersFactory(Context context, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @ExtensionRendererMode int extensionRendererMode, long allowedVideoJoiningTimeMs, MediaCodecSelector mediaCodecSelector) { this.context = context; this.drmSessionManager = drmSessionManager; this.extensionRendererMode = extensionRendererMode; this.allowedVideoJoiningTimeMs = allowedVideoJoiningTimeMs; this.mediaCodecSelector = mediaCodecSelector; }
@Test public void givenValidMediaDrm_whenAcquiringSession_thenReturnsLocalDrmSession() throws MediaCryptoException { given(mediaDrm.createMediaCrypto(SESSION_ID.asBytes())).willReturn(frameworkMediaCrypto); DrmSession<FrameworkMediaCrypto> drmSession = localDrmSessionManager.acquireSession(IGNORED_LOOPER, IGNORED_DRM_DATA); LocalDrmSession localDrmSession = new LocalDrmSession(frameworkMediaCrypto, KEY_SET_ID_TO_RESTORE, SESSION_ID); assertThat(drmSession).isEqualTo(localDrmSession); }
@RequiresApi(api = Build.VERSION_CODES.KITKAT) @Test public void givenOpeningSessionError_whenAcquiringSession_thenReturnsInvalidDrmSession() throws MediaDrmException { ResourceBusyException resourceBusyException = new ResourceBusyException("resource is busy"); given(mediaDrm.openSession()).willThrow(resourceBusyException); DrmSession<FrameworkMediaCrypto> drmSession = localDrmSessionManager.acquireSession(IGNORED_LOOPER, IGNORED_DRM_DATA); assertThat(drmSession).isInstanceOf(InvalidDrmSession.class); assertThat(drmSession.getError().getCause()).isEqualTo(resourceBusyException); }
@Test public void givenAcquiredSession_whenReleasingSession_thenClosesCurrentSession() { DrmSession<FrameworkMediaCrypto> drmSession = new LocalDrmSession(frameworkMediaCrypto, KEY_SET_ID_TO_RESTORE, SESSION_ID); localDrmSessionManager.releaseSession(drmSession); verify(mediaDrm).closeSession(SESSION_ID.asBytes()); }
public SonicMediaCodecAudioRenderer(MediaCodecSelector mediaCodecSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, AudioRendererEventListener eventListener, AudioCapabilities audioCapabilities, AudioProcessor... audioProcessors) { super(mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, eventHandler, eventListener, audioCapabilities, audioProcessors); //Init bufferIndex = -1; speed = 1.0f; pitch = 1.0f; rate = 1.0f; }
protected SimpleExoPlayer(Context context, TrackSelector trackSelector, LoadControl loadControl, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @ExtensionRendererMode int extensionRendererMode, long allowedVideoJoiningTimeMs) { mainHandler = new Handler(); componentListener = new ComponentListener(); // Build the renderers. ArrayList<Renderer> renderersList = new ArrayList<>(); buildRenderers(context, mainHandler, drmSessionManager, extensionRendererMode, allowedVideoJoiningTimeMs, renderersList); renderers = renderersList.toArray(new Renderer[renderersList.size()]); // Obtain counts of video and audio renderers. int videoRendererCount = 0; int audioRendererCount = 0; for (Renderer renderer : renderers) { switch (renderer.getTrackType()) { case C.TRACK_TYPE_VIDEO: videoRendererCount++; break; case C.TRACK_TYPE_AUDIO: audioRendererCount++; break; } } this.videoRendererCount = videoRendererCount; this.audioRendererCount = audioRendererCount; // Set initial values. audioVolume = 1; audioSessionId = C.AUDIO_SESSION_ID_UNSET; audioStreamType = C.STREAM_TYPE_DEFAULT; videoScalingMode = C.VIDEO_SCALING_MODE_DEFAULT; // Build the player and associated objects. player = new ExoPlayerImpl(renderers, trackSelector, loadControl); }
private void buildRenderers(Context context, Handler mainHandler, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @ExtensionRendererMode int extensionRendererMode, long allowedVideoJoiningTimeMs, ArrayList<Renderer> out) { buildVideoRenderers(context, mainHandler, drmSessionManager, extensionRendererMode, componentListener, allowedVideoJoiningTimeMs, out); buildAudioRenderers(context, mainHandler, drmSessionManager, extensionRendererMode, componentListener, buildAudioProcessors(), out); buildTextRenderers(context, mainHandler, extensionRendererMode, componentListener, out); buildMetadataRenderers(context, mainHandler, extensionRendererMode, componentListener, out); buildMiscellaneousRenderers(context, mainHandler, extensionRendererMode, out); }
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid, String licenseUrl, Map<String, String> keyRequestProperties) throws UnsupportedDrmException { if (Util.SDK_INT < 18) { return null; } HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl, buildHttpDataSourceFactory(false), keyRequestProperties); return new StreamingDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger); }
private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManagerV18(UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray, boolean multiSession) throws UnsupportedDrmException { HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl, buildHttpDataSourceFactory(false)); if (keyRequestPropertiesArray != null) { for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) { drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i], keyRequestPropertiesArray[i + 1]); } } return new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger, multiSession); }
@Override protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance( new DebugRenderersFactory(host, drmSessionManager), trackSelector); player.setVideoSurface(surface); return player; }
@Override protected void buildVideoRenderers(Context context, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, long allowedVideoJoiningTimeMs, Handler eventHandler, VideoRendererEventListener eventListener, @ExtensionRendererMode int extensionRendererMode, ArrayList<Renderer> out) { out.add(new DebugMediaCodecVideoRenderer(context, MediaCodecSelector.DEFAULT, allowedVideoJoiningTimeMs, drmSessionManager, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY)); }
public DebugMediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, Handler eventHandler, VideoRendererEventListener eventListener, int maxDroppedFrameCountToNotify) { super(context, mediaCodecSelector, allowedJoiningTimeMs, drmSessionManager, false, eventHandler, eventListener, maxDroppedFrameCountToNotify); }
@Override public final void onStart(HostActivity host, Surface surface) { this.surface = surface; // Build the player. DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); trackSelector = buildTrackSelector(host, bandwidthMeter); String userAgent = "ExoPlayerPlaybackTests"; DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = buildDrmSessionManager(userAgent); player = buildExoPlayer(host, surface, trackSelector, drmSessionManager); player.prepare(buildSource(host, Util.getUserAgent(host, userAgent), bandwidthMeter)); if (playerEventListener != null) { player.addListener(playerEventListener); } if (videoDebugListener != null) { player.addVideoDebugListener(videoDebugListener); } if (audioDebugListener != null) { player.addAudioDebugListener(audioDebugListener); } player.addListener(this); player.addAudioDebugListener(this); player.addVideoDebugListener(this); player.setPlayWhenReady(true); actionHandler = new Handler(); // Schedule any pending actions. if (pendingSchedule != null) { pendingSchedule.start(player, trackSelector, surface, actionHandler); pendingSchedule = null; } }
@SuppressWarnings("unused") protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { RenderersFactory renderersFactory = new DefaultRenderersFactory(host, drmSessionManager, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF, 0); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector); player.setVideoSurface(surface); return player; }
private DrmSessionManager<FrameworkMediaCrypto> buildOfflineDrmSessionManager(UUID uuid, String licenseUrl, Map<String, String> keyRequestProperties) throws UnsupportedDrmException, IOException, DrmSession.DrmSessionException, InterruptedException { if (Util.SDK_INT < 18) { return null; } customDrmCallback = new CustomDrmCallback( DemoApplication.getAppInstance().buildHttpDataSourceFactory(new DefaultBandwidthMeter()), licenseUrl ); DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager = new DefaultDrmSessionManager<>(uuid, FrameworkMediaDrm.newInstance(uuid), customDrmCallback, null, mainHandler, eventLogger); String offlineAssetKeyIdStr = DemoApplication.getAppInstance(). getSharedPreferences().getString(DemoApplication.KEY_OFFLINE_OFFSET_ID,DemoApplication.EMPTY); byte[] offlineAssetKeyId = Base64.decode(offlineAssetKeyIdStr, Base64.DEFAULT); this.offlineLicenseHelper = OfflineLicenseHelper.newWidevineInstance(customDrmCallback, null); Pair<Long, Long> remainingSecPair = offlineLicenseHelper.getLicenseDurationRemainingSec(offlineAssetKeyId); Log.e(TAG," License remaining Play time : "+remainingSecPair.first+", Purchase time : "+remainingSecPair.second); if(DemoApplication.EMPTY.equals(offlineAssetKeyIdStr) || ( remainingSecPair.first == 0 || remainingSecPair.second == 0)) { String path = getIntent().getStringExtra(EXTRA_OFFLINE_URI); File file = getUriForManifest(path); Uri uri = Uri.fromFile(file); InputStream is = new FileInputStream(file); Log.e(TAG, "will start download now"); offlineAssetKeyId = offlineLicenseHelper.download( DemoApplication.getAppInstance().buildHttpDataSourceFactory(new DefaultBandwidthMeter()).createDataSource(), new DashManifestParser().parse(uri, is)); Pair<Long, Long> p = offlineLicenseHelper.getLicenseDurationRemainingSec(offlineAssetKeyId); Log.e(TAG, "download done : " + p.toString()); SharedPreferences sharedPreferences = DemoApplication.getAppInstance().getSharedPreferences(); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(DemoApplication.KEY_OFFLINE_OFFSET_ID, Base64.encodeToString(offlineAssetKeyId, Base64.DEFAULT)); editor.commit(); } drmSessionManager.setMode(DefaultDrmSessionManager.MODE_QUERY,offlineAssetKeyId); return drmSessionManager; }